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 XtSetValues(menuBarWidget, args, 2);
2782 widgetList[j++] = whiteTimerWidget =
2783 XtCreateWidget("whiteTime", labelWidgetClass,
2784 formWidget, timerArgs, XtNumber(timerArgs));
2785 XtSetArg(args[0], XtNfont, clockFontStruct);
2786 XtSetArg(args[1], XtNtop, XtChainTop);
2787 XtSetArg(args[2], XtNbottom, XtChainTop);
2788 XtSetValues(whiteTimerWidget, args, 3);
2790 widgetList[j++] = blackTimerWidget =
2791 XtCreateWidget("blackTime", labelWidgetClass,
2792 formWidget, timerArgs, XtNumber(timerArgs));
2793 XtSetArg(args[0], XtNfont, clockFontStruct);
2794 XtSetArg(args[1], XtNtop, XtChainTop);
2795 XtSetArg(args[2], XtNbottom, XtChainTop);
2796 XtSetValues(blackTimerWidget, args, 3);
2798 if (appData.titleInWindow) {
2799 widgetList[j++] = titleWidget =
2800 XtCreateWidget("title", labelWidgetClass, formWidget,
2801 titleArgs, XtNumber(titleArgs));
2802 XtSetArg(args[0], XtNtop, XtChainTop);
2803 XtSetArg(args[1], XtNbottom, XtChainTop);
2804 XtSetValues(titleWidget, args, 2);
2807 if (appData.showButtonBar) {
2808 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2809 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2810 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2811 XtSetArg(args[2], XtNtop, XtChainTop);
2812 XtSetArg(args[3], XtNbottom, XtChainTop);
2813 XtSetValues(buttonBarWidget, args, 4);
2816 widgetList[j++] = messageWidget =
2817 XtCreateWidget("message", labelWidgetClass, formWidget,
2818 messageArgs, XtNumber(messageArgs));
2819 XtSetArg(args[0], XtNtop, XtChainTop);
2820 XtSetArg(args[1], XtNbottom, XtChainTop);
2821 XtSetValues(messageWidget, args, 2);
2823 widgetList[j++] = boardWidget =
2824 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2825 XtNumber(boardArgs));
2827 XtManageChildren(widgetList, j);
2829 timerWidth = (boardWidth - sep) / 2;
2830 XtSetArg(args[0], XtNwidth, timerWidth);
2831 XtSetValues(whiteTimerWidget, args, 1);
2832 XtSetValues(blackTimerWidget, args, 1);
2834 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2835 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2836 XtGetValues(whiteTimerWidget, args, 2);
2838 if (appData.showButtonBar) {
2839 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2840 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2841 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2845 * formWidget uses these constraints but they are stored
2849 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2850 XtSetValues(menuBarWidget, args, i);
2851 if (appData.titleInWindow) {
2854 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2855 XtSetValues(whiteTimerWidget, args, i);
2857 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2858 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2859 XtSetValues(blackTimerWidget, args, i);
2861 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2862 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2863 XtSetValues(titleWidget, args, i);
2865 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2866 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2867 XtSetValues(messageWidget, args, i);
2868 if (appData.showButtonBar) {
2870 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2871 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2872 XtSetValues(buttonBarWidget, args, i);
2876 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2877 XtSetValues(whiteTimerWidget, args, i);
2879 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2880 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2881 XtSetValues(blackTimerWidget, args, i);
2883 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2884 XtSetValues(titleWidget, args, i);
2886 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2887 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2888 XtSetValues(messageWidget, args, i);
2889 if (appData.showButtonBar) {
2891 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2892 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2893 XtSetValues(buttonBarWidget, args, i);
2898 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2899 XtSetValues(whiteTimerWidget, args, i);
2901 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2902 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2903 XtSetValues(blackTimerWidget, args, i);
2905 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2906 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2907 XtSetValues(messageWidget, args, i);
2908 if (appData.showButtonBar) {
2910 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2911 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2912 XtSetValues(buttonBarWidget, args, i);
2916 XtSetArg(args[0], XtNfromVert, messageWidget);
2917 XtSetArg(args[1], XtNtop, XtChainTop);
2918 XtSetArg(args[2], XtNbottom, XtChainBottom);
2919 XtSetArg(args[3], XtNleft, XtChainLeft);
2920 XtSetArg(args[4], XtNright, XtChainRight);
2921 XtSetValues(boardWidget, args, 5);
2923 XtRealizeWidget(shellWidget);
2926 * Correct the width of the message and title widgets.
2927 * It is not known why some systems need the extra fudge term.
2928 * The value "2" is probably larger than needed.
2930 XawFormDoLayout(formWidget, False);
2932 #define WIDTH_FUDGE 2
2934 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2935 XtSetArg(args[i], XtNheight, &h); i++;
2936 XtGetValues(messageWidget, args, i);
2937 if (appData.showButtonBar) {
2939 XtSetArg(args[i], XtNwidth, &w); i++;
2940 XtGetValues(buttonBarWidget, args, i);
2941 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2943 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2946 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2947 if (gres != XtGeometryYes && appData.debugMode) {
2948 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2949 programName, gres, w, h, wr, hr);
2952 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2953 /* The size used for the child widget in layout lags one resize behind
2954 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2956 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2957 if (gres != XtGeometryYes && appData.debugMode) {
2958 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2959 programName, gres, w, h, wr, hr);
2962 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2963 XtSetArg(args[1], XtNright, XtChainRight);
2964 XtSetValues(messageWidget, args, 2);
2966 if (appData.titleInWindow) {
2968 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2969 XtSetArg(args[i], XtNheight, &h); i++;
2970 XtGetValues(titleWidget, args, i);
2972 w = boardWidth - 2*bor;
2974 XtSetArg(args[0], XtNwidth, &w);
2975 XtGetValues(menuBarWidget, args, 1);
2976 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2979 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2980 if (gres != XtGeometryYes && appData.debugMode) {
2982 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2983 programName, gres, w, h, wr, hr);
2986 XawFormDoLayout(formWidget, True);
2988 xBoardWindow = XtWindow(boardWidget);
2990 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2991 // not need to go into InitDrawingSizes().
2995 * Create X checkmark bitmap and initialize option menu checks.
2997 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2998 checkmark_bits, checkmark_width, checkmark_height);
2999 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
3000 if (appData.alwaysPromoteToQueen) {
3001 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3004 if (appData.animateDragging) {
3005 XtSetValues(XtNameToWidget(menuBarWidget,
3006 "menuOptions.Animate Dragging"),
3009 if (appData.animate) {
3010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3013 if (appData.autoComment) {
3014 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3017 if (appData.autoCallFlag) {
3018 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3021 if (appData.autoFlipView) {
3022 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3025 if (appData.autoObserve) {
3026 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3029 if (appData.autoRaiseBoard) {
3030 XtSetValues(XtNameToWidget(menuBarWidget,
3031 "menuOptions.Auto Raise Board"), args, 1);
3033 if (appData.autoSaveGames) {
3034 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3037 if (appData.saveGameFile[0] != NULLCHAR) {
3038 /* Can't turn this off from menu */
3039 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3041 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3045 if (appData.blindfold) {
3046 XtSetValues(XtNameToWidget(menuBarWidget,
3047 "menuOptions.Blindfold"), args, 1);
3049 if (appData.flashCount > 0) {
3050 XtSetValues(XtNameToWidget(menuBarWidget,
3051 "menuOptions.Flash Moves"),
3054 if (appData.getMoveList) {
3055 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3059 if (appData.highlightDragging) {
3060 XtSetValues(XtNameToWidget(menuBarWidget,
3061 "menuOptions.Highlight Dragging"),
3065 if (appData.highlightLastMove) {
3066 XtSetValues(XtNameToWidget(menuBarWidget,
3067 "menuOptions.Highlight Last Move"),
3070 if (appData.icsAlarm) {
3071 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3074 if (appData.ringBellAfterMoves) {
3075 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3078 if (appData.oldSaveStyle) {
3079 XtSetValues(XtNameToWidget(menuBarWidget,
3080 "menuOptions.Old Save Style"), args, 1);
3082 if (appData.periodicUpdates) {
3083 XtSetValues(XtNameToWidget(menuBarWidget,
3084 "menuOptions.Periodic Updates"), args, 1);
3086 if (appData.ponderNextMove) {
3087 XtSetValues(XtNameToWidget(menuBarWidget,
3088 "menuOptions.Ponder Next Move"), args, 1);
3090 if (appData.popupExitMessage) {
3091 XtSetValues(XtNameToWidget(menuBarWidget,
3092 "menuOptions.Popup Exit Message"), args, 1);
3094 if (appData.popupMoveErrors) {
3095 XtSetValues(XtNameToWidget(menuBarWidget,
3096 "menuOptions.Popup Move Errors"), args, 1);
3098 if (appData.premove) {
3099 XtSetValues(XtNameToWidget(menuBarWidget,
3100 "menuOptions.Premove"), args, 1);
3102 if (appData.quietPlay) {
3103 XtSetValues(XtNameToWidget(menuBarWidget,
3104 "menuOptions.Quiet Play"), args, 1);
3106 if (appData.showCoords) {
3107 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3110 if (appData.hideThinkingFromHuman) {
3111 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3114 if (appData.testLegality) {
3115 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3122 ReadBitmap(&wIconPixmap, "icon_white.bm",
3123 icon_white_bits, icon_white_width, icon_white_height);
3124 ReadBitmap(&bIconPixmap, "icon_black.bm",
3125 icon_black_bits, icon_black_width, icon_black_height);
3126 iconPixmap = wIconPixmap;
3128 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3129 XtSetValues(shellWidget, args, i);
3132 * Create a cursor for the board widget.
3134 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3135 XChangeWindowAttributes(xDisplay, xBoardWindow,
3136 CWCursor, &window_attributes);
3139 * Inhibit shell resizing.
3141 shellArgs[0].value = (XtArgVal) &w;
3142 shellArgs[1].value = (XtArgVal) &h;
3143 XtGetValues(shellWidget, shellArgs, 2);
3144 shellArgs[4].value = shellArgs[2].value = w;
3145 shellArgs[5].value = shellArgs[3].value = h;
3146 XtSetValues(shellWidget, &shellArgs[2], 4);
3147 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3148 marginH = h - boardHeight;
3150 CatchDeleteWindow(shellWidget, "QuitProc");
3155 if (appData.bitmapDirectory[0] != NULLCHAR) {
3162 /* Create regular pieces */
3163 if (!useImages) CreatePieces();
3168 if (appData.animate || appData.animateDragging)
3171 XtAugmentTranslations(formWidget,
3172 XtParseTranslationTable(globalTranslations));
3173 XtAugmentTranslations(boardWidget,
3174 XtParseTranslationTable(boardTranslations));
3175 XtAugmentTranslations(whiteTimerWidget,
3176 XtParseTranslationTable(whiteTranslations));
3177 XtAugmentTranslations(blackTimerWidget,
3178 XtParseTranslationTable(blackTranslations));
3180 /* Why is the following needed on some versions of X instead
3181 * of a translation? */
3182 XtAddEventHandler(boardWidget, ExposureMask, False,
3183 (XtEventHandler) EventProc, NULL);
3188 if (errorExitStatus == -1) {
3189 if (appData.icsActive) {
3190 /* We now wait until we see "login:" from the ICS before
3191 sending the logon script (problems with timestamp otherwise) */
3192 /*ICSInitScript();*/
3193 if (appData.icsInputBox) ICSInputBoxPopUp();
3197 signal(SIGWINCH, TermSizeSigHandler);
3199 signal(SIGINT, IntSigHandler);
3200 signal(SIGTERM, IntSigHandler);
3201 if (*appData.cmailGameName != NULLCHAR) {
3202 signal(SIGUSR1, CmailSigHandler);
3205 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3208 XtAppMainLoop(appContext);
3209 if (appData.debugMode) fclose(debugFP); // [DM] debug
3216 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3217 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3219 unlink(gameCopyFilename);
3220 unlink(gamePasteFilename);
3223 RETSIGTYPE TermSizeSigHandler(int sig)
3236 CmailSigHandler(sig)
3242 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3244 /* Activate call-back function CmailSigHandlerCallBack() */
3245 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3247 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3251 CmailSigHandlerCallBack(isr, closure, message, count, error)
3259 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3261 /**** end signal code ****/
3271 f = fopen(appData.icsLogon, "r");
3277 strcat(buf, appData.icsLogon);
3278 f = fopen(buf, "r");
3282 ProcessICSInitScript(f);
3289 EditCommentPopDown();
3300 SetMenuEnables(enab)
3304 if (!menuBarWidget) return;
3305 while (enab->name != NULL) {
3306 w = XtNameToWidget(menuBarWidget, enab->name);
3308 DisplayError(enab->name, 0);
3310 XtSetSensitive(w, enab->value);
3316 Enables icsEnables[] = {
3317 { "menuFile.Mail Move", False },
3318 { "menuFile.Reload CMail Message", False },
3319 { "menuMode.Machine Black", False },
3320 { "menuMode.Machine White", False },
3321 { "menuMode.Analysis Mode", False },
3322 { "menuMode.Analyze File", False },
3323 { "menuMode.Two Machines", False },
3325 { "menuHelp.Hint", False },
3326 { "menuHelp.Book", False },
3327 { "menuStep.Move Now", False },
3328 { "menuOptions.Periodic Updates", False },
3329 { "menuOptions.Hide Thinking", False },
3330 { "menuOptions.Ponder Next Move", False },
3335 Enables ncpEnables[] = {
3336 { "menuFile.Mail Move", False },
3337 { "menuFile.Reload CMail Message", False },
3338 { "menuMode.Machine White", False },
3339 { "menuMode.Machine Black", False },
3340 { "menuMode.Analysis Mode", False },
3341 { "menuMode.Analyze File", False },
3342 { "menuMode.Two Machines", False },
3343 { "menuMode.ICS Client", False },
3344 { "menuMode.ICS Input Box", False },
3345 { "Action", False },
3346 { "menuStep.Revert", False },
3347 { "menuStep.Move Now", False },
3348 { "menuStep.Retract Move", False },
3349 { "menuOptions.Auto Comment", False },
3350 { "menuOptions.Auto Flag", False },
3351 { "menuOptions.Auto Flip View", False },
3352 { "menuOptions.Auto Observe", False },
3353 { "menuOptions.Auto Raise Board", False },
3354 { "menuOptions.Get Move List", False },
3355 { "menuOptions.ICS Alarm", False },
3356 { "menuOptions.Move Sound", False },
3357 { "menuOptions.Quiet Play", False },
3358 { "menuOptions.Hide Thinking", False },
3359 { "menuOptions.Periodic Updates", False },
3360 { "menuOptions.Ponder Next Move", False },
3361 { "menuHelp.Hint", False },
3362 { "menuHelp.Book", False },
3366 Enables gnuEnables[] = {
3367 { "menuMode.ICS Client", False },
3368 { "menuMode.ICS Input Box", False },
3369 { "menuAction.Accept", False },
3370 { "menuAction.Decline", False },
3371 { "menuAction.Rematch", False },
3372 { "menuAction.Adjourn", False },
3373 { "menuAction.Stop Examining", False },
3374 { "menuAction.Stop Observing", False },
3375 { "menuStep.Revert", False },
3376 { "menuOptions.Auto Comment", False },
3377 { "menuOptions.Auto Observe", False },
3378 { "menuOptions.Auto Raise Board", False },
3379 { "menuOptions.Get Move List", False },
3380 { "menuOptions.Premove", False },
3381 { "menuOptions.Quiet Play", False },
3383 /* The next two options rely on SetCmailMode being called *after* */
3384 /* SetGNUMode so that when GNU is being used to give hints these */
3385 /* menu options are still available */
3387 { "menuFile.Mail Move", False },
3388 { "menuFile.Reload CMail Message", False },
3392 Enables cmailEnables[] = {
3394 { "menuAction.Call Flag", False },
3395 { "menuAction.Draw", True },
3396 { "menuAction.Adjourn", False },
3397 { "menuAction.Abort", False },
3398 { "menuAction.Stop Observing", False },
3399 { "menuAction.Stop Examining", False },
3400 { "menuFile.Mail Move", True },
3401 { "menuFile.Reload CMail Message", True },
3405 Enables trainingOnEnables[] = {
3406 { "menuMode.Edit Comment", False },
3407 { "menuMode.Pause", False },
3408 { "menuStep.Forward", False },
3409 { "menuStep.Backward", False },
3410 { "menuStep.Forward to End", False },
3411 { "menuStep.Back to Start", False },
3412 { "menuStep.Move Now", False },
3413 { "menuStep.Truncate Game", False },
3417 Enables trainingOffEnables[] = {
3418 { "menuMode.Edit Comment", True },
3419 { "menuMode.Pause", True },
3420 { "menuStep.Forward", True },
3421 { "menuStep.Backward", True },
3422 { "menuStep.Forward to End", True },
3423 { "menuStep.Back to Start", True },
3424 { "menuStep.Move Now", True },
3425 { "menuStep.Truncate Game", True },
3429 Enables machineThinkingEnables[] = {
3430 { "menuFile.Load Game", False },
3431 { "menuFile.Load Next Game", False },
3432 { "menuFile.Load Previous Game", False },
3433 { "menuFile.Reload Same Game", False },
3434 { "menuFile.Paste Game", False },
3435 { "menuFile.Load Position", False },
3436 { "menuFile.Load Next Position", False },
3437 { "menuFile.Load Previous Position", False },
3438 { "menuFile.Reload Same Position", False },
3439 { "menuFile.Paste Position", False },
3440 { "menuMode.Machine White", False },
3441 { "menuMode.Machine Black", False },
3442 { "menuMode.Two Machines", False },
3443 { "menuStep.Retract Move", False },
3447 Enables userThinkingEnables[] = {
3448 { "menuFile.Load Game", True },
3449 { "menuFile.Load Next Game", True },
3450 { "menuFile.Load Previous Game", True },
3451 { "menuFile.Reload Same Game", True },
3452 { "menuFile.Paste Game", True },
3453 { "menuFile.Load Position", True },
3454 { "menuFile.Load Next Position", True },
3455 { "menuFile.Load Previous Position", True },
3456 { "menuFile.Reload Same Position", True },
3457 { "menuFile.Paste Position", True },
3458 { "menuMode.Machine White", True },
3459 { "menuMode.Machine Black", True },
3460 { "menuMode.Two Machines", True },
3461 { "menuStep.Retract Move", True },
3467 SetMenuEnables(icsEnables);
3470 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3471 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3478 SetMenuEnables(ncpEnables);
3484 SetMenuEnables(gnuEnables);
3490 SetMenuEnables(cmailEnables);
3496 SetMenuEnables(trainingOnEnables);
3497 if (appData.showButtonBar) {
3498 XtSetSensitive(buttonBarWidget, False);
3504 SetTrainingModeOff()
3506 SetMenuEnables(trainingOffEnables);
3507 if (appData.showButtonBar) {
3508 XtSetSensitive(buttonBarWidget, True);
3513 SetUserThinkingEnables()
3515 if (appData.noChessProgram) return;
3516 SetMenuEnables(userThinkingEnables);
3520 SetMachineThinkingEnables()
3522 if (appData.noChessProgram) return;
3523 SetMenuEnables(machineThinkingEnables);
3525 case MachinePlaysBlack:
3526 case MachinePlaysWhite:
3527 case TwoMachinesPlay:
3528 XtSetSensitive(XtNameToWidget(menuBarWidget,
3529 ModeToWidgetName(gameMode)), True);
3536 #define Abs(n) ((n)<0 ? -(n) : (n))
3539 * Find a font that matches "pattern" that is as close as
3540 * possible to the targetPxlSize. Prefer fonts that are k
3541 * pixels smaller to fonts that are k pixels larger. The
3542 * pattern must be in the X Consortium standard format,
3543 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3544 * The return value should be freed with XtFree when no
3547 char *FindFont(pattern, targetPxlSize)
3551 char **fonts, *p, *best, *scalable, *scalableTail;
3552 int i, j, nfonts, minerr, err, pxlSize;
3555 char **missing_list;
3557 char *def_string, *base_fnt_lst, strInt[3];
3559 XFontStruct **fnt_list;
3561 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3562 sprintf(strInt, "%d", targetPxlSize);
3563 p = strstr(pattern, "--");
3564 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3565 strcat(base_fnt_lst, strInt);
3566 strcat(base_fnt_lst, strchr(p + 2, '-'));
3568 if ((fntSet = XCreateFontSet(xDisplay,
3572 &def_string)) == NULL) {
3574 fprintf(stderr, _("Unable to create font set.\n"));
3578 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3580 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3582 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3583 programName, pattern);
3591 for (i=0; i<nfonts; i++) {
3594 if (*p != '-') continue;
3596 if (*p == NULLCHAR) break;
3597 if (*p++ == '-') j++;
3599 if (j < 7) continue;
3602 scalable = fonts[i];
3605 err = pxlSize - targetPxlSize;
3606 if (Abs(err) < Abs(minerr) ||
3607 (minerr > 0 && err < 0 && -err == minerr)) {
3613 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3614 /* If the error is too big and there is a scalable font,
3615 use the scalable font. */
3616 int headlen = scalableTail - scalable;
3617 p = (char *) XtMalloc(strlen(scalable) + 10);
3618 while (isdigit(*scalableTail)) scalableTail++;
3619 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3621 p = (char *) XtMalloc(strlen(best) + 1);
3624 if (appData.debugMode) {
3625 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3626 pattern, targetPxlSize, p);
3629 if (missing_count > 0)
3630 XFreeStringList(missing_list);
3631 XFreeFontSet(xDisplay, fntSet);
3633 XFreeFontNames(fonts);
3640 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3641 | GCBackground | GCFunction | GCPlaneMask;
3642 XGCValues gc_values;
3645 gc_values.plane_mask = AllPlanes;
3646 gc_values.line_width = lineGap;
3647 gc_values.line_style = LineSolid;
3648 gc_values.function = GXcopy;
3650 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3651 gc_values.background = XBlackPixel(xDisplay, xScreen);
3652 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3654 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3655 gc_values.background = XWhitePixel(xDisplay, xScreen);
3656 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3657 XSetFont(xDisplay, coordGC, coordFontID);
3659 // [HGM] make font for holdings counts (white on black0
3660 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3661 gc_values.background = XBlackPixel(xDisplay, xScreen);
3662 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3663 XSetFont(xDisplay, countGC, countFontID);
3665 if (appData.monoMode) {
3666 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3667 gc_values.background = XWhitePixel(xDisplay, xScreen);
3668 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3670 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3671 gc_values.background = XBlackPixel(xDisplay, xScreen);
3672 lightSquareGC = wbPieceGC
3673 = XtGetGC(shellWidget, value_mask, &gc_values);
3675 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3676 gc_values.background = XWhitePixel(xDisplay, xScreen);
3677 darkSquareGC = bwPieceGC
3678 = XtGetGC(shellWidget, value_mask, &gc_values);
3680 if (DefaultDepth(xDisplay, xScreen) == 1) {
3681 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3682 gc_values.function = GXcopyInverted;
3683 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.function = GXcopy;
3685 if (XBlackPixel(xDisplay, xScreen) == 1) {
3686 bwPieceGC = darkSquareGC;
3687 wbPieceGC = copyInvertedGC;
3689 bwPieceGC = copyInvertedGC;
3690 wbPieceGC = lightSquareGC;
3694 gc_values.foreground = highlightSquareColor;
3695 gc_values.background = highlightSquareColor;
3696 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3698 gc_values.foreground = premoveHighlightColor;
3699 gc_values.background = premoveHighlightColor;
3700 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3702 gc_values.foreground = lightSquareColor;
3703 gc_values.background = darkSquareColor;
3704 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3706 gc_values.foreground = darkSquareColor;
3707 gc_values.background = lightSquareColor;
3708 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3710 gc_values.foreground = jailSquareColor;
3711 gc_values.background = jailSquareColor;
3712 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3714 gc_values.foreground = whitePieceColor;
3715 gc_values.background = darkSquareColor;
3716 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3718 gc_values.foreground = whitePieceColor;
3719 gc_values.background = lightSquareColor;
3720 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3722 gc_values.foreground = whitePieceColor;
3723 gc_values.background = jailSquareColor;
3724 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3726 gc_values.foreground = blackPieceColor;
3727 gc_values.background = darkSquareColor;
3728 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3730 gc_values.foreground = blackPieceColor;
3731 gc_values.background = lightSquareColor;
3732 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3734 gc_values.foreground = blackPieceColor;
3735 gc_values.background = jailSquareColor;
3736 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3740 void loadXIM(xim, xmask, filename, dest, mask)
3753 fp = fopen(filename, "rb");
3755 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3762 for (y=0; y<h; ++y) {
3763 for (x=0; x<h; ++x) {
3768 XPutPixel(xim, x, y, blackPieceColor);
3770 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3773 XPutPixel(xim, x, y, darkSquareColor);
3775 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3778 XPutPixel(xim, x, y, whitePieceColor);
3780 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3783 XPutPixel(xim, x, y, lightSquareColor);
3785 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3791 /* create Pixmap of piece */
3792 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3794 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3797 /* create Pixmap of clipmask
3798 Note: We assume the white/black pieces have the same
3799 outline, so we make only 6 masks. This is okay
3800 since the XPM clipmask routines do the same. */
3802 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3804 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3807 /* now create the 1-bit version */
3808 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3811 values.foreground = 1;
3812 values.background = 0;
3814 /* Don't use XtGetGC, not read only */
3815 maskGC = XCreateGC(xDisplay, *mask,
3816 GCForeground | GCBackground, &values);
3817 XCopyPlane(xDisplay, temp, *mask, maskGC,
3818 0, 0, squareSize, squareSize, 0, 0, 1);
3819 XFreePixmap(xDisplay, temp);
3824 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3826 void CreateXIMPieces()
3831 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3836 /* The XSynchronize calls were copied from CreatePieces.
3837 Not sure if needed, but can't hurt */
3838 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3841 /* temp needed by loadXIM() */
3842 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3843 0, 0, ss, ss, AllPlanes, XYPixmap);
3845 if (strlen(appData.pixmapDirectory) == 0) {
3849 if (appData.monoMode) {
3850 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3854 fprintf(stderr, _("\nLoading XIMs...\n"));
3856 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3857 fprintf(stderr, "%d", piece+1);
3858 for (kind=0; kind<4; kind++) {
3859 fprintf(stderr, ".");
3860 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3861 ExpandPathName(appData.pixmapDirectory),
3862 piece <= (int) WhiteKing ? "" : "w",
3863 pieceBitmapNames[piece],
3865 ximPieceBitmap[kind][piece] =
3866 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3867 0, 0, ss, ss, AllPlanes, XYPixmap);
3868 if (appData.debugMode)
3869 fprintf(stderr, _("(File:%s:) "), buf);
3870 loadXIM(ximPieceBitmap[kind][piece],
3872 &(xpmPieceBitmap2[kind][piece]),
3873 &(ximMaskPm2[piece]));
3874 if(piece <= (int)WhiteKing)
3875 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3877 fprintf(stderr," ");
3879 /* Load light and dark squares */
3880 /* If the LSQ and DSQ pieces don't exist, we will
3881 draw them with solid squares. */
3882 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3883 if (access(buf, 0) != 0) {
3887 fprintf(stderr, _("light square "));
3889 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3890 0, 0, ss, ss, AllPlanes, XYPixmap);
3891 if (appData.debugMode)
3892 fprintf(stderr, _("(File:%s:) "), buf);
3894 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3895 fprintf(stderr, _("dark square "));
3896 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3897 ExpandPathName(appData.pixmapDirectory), ss);
3898 if (appData.debugMode)
3899 fprintf(stderr, _("(File:%s:) "), buf);
3901 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3902 0, 0, ss, ss, AllPlanes, XYPixmap);
3903 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3904 xpmJailSquare = xpmLightSquare;
3906 fprintf(stderr, _("Done.\n"));
3908 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3912 void CreateXPMPieces()
3916 u_int ss = squareSize;
3918 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3919 XpmColorSymbol symbols[4];
3921 /* The XSynchronize calls were copied from CreatePieces.
3922 Not sure if needed, but can't hurt */
3923 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3925 /* Setup translations so piece colors match square colors */
3926 symbols[0].name = "light_piece";
3927 symbols[0].value = appData.whitePieceColor;
3928 symbols[1].name = "dark_piece";
3929 symbols[1].value = appData.blackPieceColor;
3930 symbols[2].name = "light_square";
3931 symbols[2].value = appData.lightSquareColor;
3932 symbols[3].name = "dark_square";
3933 symbols[3].value = appData.darkSquareColor;
3935 attr.valuemask = XpmColorSymbols;
3936 attr.colorsymbols = symbols;
3937 attr.numsymbols = 4;
3939 if (appData.monoMode) {
3940 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3944 if (strlen(appData.pixmapDirectory) == 0) {
3945 XpmPieces* pieces = builtInXpms;
3948 while (pieces->size != squareSize && pieces->size) pieces++;
3949 if (!pieces->size) {
3950 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3953 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3954 for (kind=0; kind<4; kind++) {
3956 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3957 pieces->xpm[piece][kind],
3958 &(xpmPieceBitmap2[kind][piece]),
3959 NULL, &attr)) != 0) {
3960 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3964 if(piece <= (int) WhiteKing)
3965 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3969 xpmJailSquare = xpmLightSquare;
3973 fprintf(stderr, _("\nLoading XPMs...\n"));
3976 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3977 fprintf(stderr, "%d ", piece+1);
3978 for (kind=0; kind<4; kind++) {
3979 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3980 ExpandPathName(appData.pixmapDirectory),
3981 piece > (int) WhiteKing ? "w" : "",
3982 pieceBitmapNames[piece],
3984 if (appData.debugMode) {
3985 fprintf(stderr, _("(File:%s:) "), buf);
3987 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3988 &(xpmPieceBitmap2[kind][piece]),
3989 NULL, &attr)) != 0) {
3990 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3991 // [HGM] missing: read of unorthodox piece failed; substitute King.
3992 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3993 ExpandPathName(appData.pixmapDirectory),
3995 if (appData.debugMode) {
3996 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3998 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3999 &(xpmPieceBitmap2[kind][piece]),
4003 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4008 if(piece <= (int) WhiteKing)
4009 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4012 /* Load light and dark squares */
4013 /* If the LSQ and DSQ pieces don't exist, we will
4014 draw them with solid squares. */
4015 fprintf(stderr, _("light square "));
4016 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4017 if (access(buf, 0) != 0) {
4021 if (appData.debugMode)
4022 fprintf(stderr, _("(File:%s:) "), buf);
4024 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4025 &xpmLightSquare, NULL, &attr)) != 0) {
4026 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4029 fprintf(stderr, _("dark square "));
4030 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4031 ExpandPathName(appData.pixmapDirectory), ss);
4032 if (appData.debugMode) {
4033 fprintf(stderr, _("(File:%s:) "), buf);
4035 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4036 &xpmDarkSquare, NULL, &attr)) != 0) {
4037 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4041 xpmJailSquare = xpmLightSquare;
4042 fprintf(stderr, _("Done.\n"));
4044 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4047 #endif /* HAVE_LIBXPM */
4050 /* No built-in bitmaps */
4055 u_int ss = squareSize;
4057 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4060 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4061 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4062 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4063 pieceBitmapNames[piece],
4064 ss, kind == SOLID ? 's' : 'o');
4065 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4066 if(piece <= (int)WhiteKing)
4067 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4071 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4075 /* With built-in bitmaps */
4078 BuiltInBits* bib = builtInBits;
4081 u_int ss = squareSize;
4083 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4086 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4088 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4089 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4090 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4091 pieceBitmapNames[piece],
4092 ss, kind == SOLID ? 's' : 'o');
4093 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4094 bib->bits[kind][piece], ss, ss);
4095 if(piece <= (int)WhiteKing)
4096 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4100 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4105 void ReadBitmap(pm, name, bits, wreq, hreq)
4108 unsigned char bits[];
4114 char msg[MSG_SIZ], fullname[MSG_SIZ];
4116 if (*appData.bitmapDirectory != NULLCHAR) {
4117 strcpy(fullname, appData.bitmapDirectory);
4118 strcat(fullname, "/");
4119 strcat(fullname, name);
4120 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4121 &w, &h, pm, &x_hot, &y_hot);
4122 fprintf(stderr, "load %s\n", name);
4123 if (errcode != BitmapSuccess) {
4125 case BitmapOpenFailed:
4126 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4128 case BitmapFileInvalid:
4129 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4131 case BitmapNoMemory:
4132 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4136 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4140 fprintf(stderr, _("%s: %s...using built-in\n"),
4142 } else if (w != wreq || h != hreq) {
4144 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4145 programName, fullname, w, h, wreq, hreq);
4151 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4160 if (lineGap == 0) return;
4162 /* [HR] Split this into 2 loops for non-square boards. */
4164 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4165 gridSegments[i].x1 = 0;
4166 gridSegments[i].x2 =
4167 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4168 gridSegments[i].y1 = gridSegments[i].y2
4169 = lineGap / 2 + (i * (squareSize + lineGap));
4172 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4173 gridSegments[j + i].y1 = 0;
4174 gridSegments[j + i].y2 =
4175 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4176 gridSegments[j + i].x1 = gridSegments[j + i].x2
4177 = lineGap / 2 + (j * (squareSize + lineGap));
4181 static void MenuBarSelect(w, addr, index)
4186 XtActionProc proc = (XtActionProc) addr;
4188 (proc)(NULL, NULL, NULL, NULL);
4191 void CreateMenuBarPopup(parent, name, mb)
4201 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4204 XtSetArg(args[j], XtNleftMargin, 20); j++;
4205 XtSetArg(args[j], XtNrightMargin, 20); j++;
4207 while (mi->string != NULL) {
4208 if (strcmp(mi->string, "----") == 0) {
4209 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4212 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4213 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4215 XtAddCallback(entry, XtNcallback,
4216 (XtCallbackProc) MenuBarSelect,
4217 (caddr_t) mi->proc);
4223 Widget CreateMenuBar(mb)
4227 Widget anchor, menuBar;
4229 char menuName[MSG_SIZ];
4232 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4233 XtSetArg(args[j], XtNvSpace, 0); j++;
4234 XtSetArg(args[j], XtNborderWidth, 0); j++;
4235 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4236 formWidget, args, j);
4238 while (mb->name != NULL) {
4239 strcpy(menuName, "menu");
4240 strcat(menuName, mb->name);
4242 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4245 shortName[0] = _(mb->name)[0];
4246 shortName[1] = NULLCHAR;
4247 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4250 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4253 XtSetArg(args[j], XtNborderWidth, 0); j++;
4254 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4256 CreateMenuBarPopup(menuBar, menuName, mb);
4262 Widget CreateButtonBar(mi)
4266 Widget button, buttonBar;
4270 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4272 XtSetArg(args[j], XtNhSpace, 0); j++;
4274 XtSetArg(args[j], XtNborderWidth, 0); j++;
4275 XtSetArg(args[j], XtNvSpace, 0); j++;
4276 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4277 formWidget, args, j);
4279 while (mi->string != NULL) {
4282 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4283 XtSetArg(args[j], XtNborderWidth, 0); j++;
4285 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4286 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4287 buttonBar, args, j);
4288 XtAddCallback(button, XtNcallback,
4289 (XtCallbackProc) MenuBarSelect,
4290 (caddr_t) mi->proc);
4297 CreatePieceMenu(name, color)
4304 ChessSquare selection;
4306 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4307 boardWidget, args, 0);
4309 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4310 String item = pieceMenuStrings[color][i];
4312 if (strcmp(item, "----") == 0) {
4313 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4316 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4317 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4319 selection = pieceMenuTranslation[color][i];
4320 XtAddCallback(entry, XtNcallback,
4321 (XtCallbackProc) PieceMenuSelect,
4322 (caddr_t) selection);
4323 if (selection == WhitePawn || selection == BlackPawn) {
4324 XtSetArg(args[0], XtNpopupOnEntry, entry);
4325 XtSetValues(menu, args, 1);
4338 ChessSquare selection;
4340 whitePieceMenu = CreatePieceMenu("menuW", 0);
4341 blackPieceMenu = CreatePieceMenu("menuB", 1);
4343 XtRegisterGrabAction(PieceMenuPopup, True,
4344 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4345 GrabModeAsync, GrabModeAsync);
4347 XtSetArg(args[0], XtNlabel, _("Drop"));
4348 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4349 boardWidget, args, 1);
4350 for (i = 0; i < DROP_MENU_SIZE; i++) {
4351 String item = dropMenuStrings[i];
4353 if (strcmp(item, "----") == 0) {
4354 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4357 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4358 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4360 selection = dropMenuTranslation[i];
4361 XtAddCallback(entry, XtNcallback,
4362 (XtCallbackProc) DropMenuSelect,
4363 (caddr_t) selection);
4368 void SetupDropMenu()
4376 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4377 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4378 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4379 dmEnables[i].piece);
4380 XtSetSensitive(entry, p != NULL || !appData.testLegality
4381 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4382 && !appData.icsActive));
4384 while (p && *p++ == dmEnables[i].piece) count++;
4385 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4387 XtSetArg(args[j], XtNlabel, label); j++;
4388 XtSetValues(entry, args, j);
4392 void PieceMenuPopup(w, event, params, num_params)
4396 Cardinal *num_params;
4399 if (event->type != ButtonPress) return;
4400 if (errorUp) ErrorPopDown();
4404 whichMenu = params[0];
4406 case IcsPlayingWhite:
4407 case IcsPlayingBlack:
4409 case MachinePlaysWhite:
4410 case MachinePlaysBlack:
4411 if (appData.testLegality &&
4412 gameInfo.variant != VariantBughouse &&
4413 gameInfo.variant != VariantCrazyhouse) return;
4415 whichMenu = "menuD";
4421 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4422 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4423 pmFromX = pmFromY = -1;
4427 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4429 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4431 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4434 static void PieceMenuSelect(w, piece, junk)
4439 if (pmFromX < 0 || pmFromY < 0) return;
4440 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4443 static void DropMenuSelect(w, piece, junk)
4448 if (pmFromX < 0 || pmFromY < 0) return;
4449 DropMenuEvent(piece, pmFromX, pmFromY);
4452 void WhiteClock(w, event, prms, nprms)
4458 if (gameMode == EditPosition || gameMode == IcsExamining) {
4459 SetWhiteToPlayEvent();
4460 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4465 void BlackClock(w, event, prms, nprms)
4471 if (gameMode == EditPosition || gameMode == IcsExamining) {
4472 SetBlackToPlayEvent();
4473 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4480 * If the user selects on a border boundary, return -1; if off the board,
4481 * return -2. Otherwise map the event coordinate to the square.
4483 int EventToSquare(x, limit)
4491 if ((x % (squareSize + lineGap)) >= squareSize)
4493 x /= (squareSize + lineGap);
4499 static void do_flash_delay(msec)
4505 static void drawHighlight(file, rank, gc)
4511 if (lineGap == 0 || appData.blindfold) return;
4514 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4515 (squareSize + lineGap);
4516 y = lineGap/2 + rank * (squareSize + lineGap);
4518 x = lineGap/2 + file * (squareSize + lineGap);
4519 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4520 (squareSize + lineGap);
4523 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4524 squareSize+lineGap, squareSize+lineGap);
4527 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4528 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4531 SetHighlights(fromX, fromY, toX, toY)
4532 int fromX, fromY, toX, toY;
4534 if (hi1X != fromX || hi1Y != fromY) {
4535 if (hi1X >= 0 && hi1Y >= 0) {
4536 drawHighlight(hi1X, hi1Y, lineGC);
4538 if (fromX >= 0 && fromY >= 0) {
4539 drawHighlight(fromX, fromY, highlineGC);
4542 if (hi2X != toX || hi2Y != toY) {
4543 if (hi2X >= 0 && hi2Y >= 0) {
4544 drawHighlight(hi2X, hi2Y, lineGC);
4546 if (toX >= 0 && toY >= 0) {
4547 drawHighlight(toX, toY, highlineGC);
4559 SetHighlights(-1, -1, -1, -1);
4564 SetPremoveHighlights(fromX, fromY, toX, toY)
4565 int fromX, fromY, toX, toY;
4567 if (pm1X != fromX || pm1Y != fromY) {
4568 if (pm1X >= 0 && pm1Y >= 0) {
4569 drawHighlight(pm1X, pm1Y, lineGC);
4571 if (fromX >= 0 && fromY >= 0) {
4572 drawHighlight(fromX, fromY, prelineGC);
4575 if (pm2X != toX || pm2Y != toY) {
4576 if (pm2X >= 0 && pm2Y >= 0) {
4577 drawHighlight(pm2X, pm2Y, lineGC);
4579 if (toX >= 0 && toY >= 0) {
4580 drawHighlight(toX, toY, prelineGC);
4590 ClearPremoveHighlights()
4592 SetPremoveHighlights(-1, -1, -1, -1);
4595 static void BlankSquare(x, y, color, piece, dest)
4600 if (useImages && useImageSqs) {
4604 pm = xpmLightSquare;
4609 case 2: /* neutral */
4614 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4615 squareSize, squareSize, x, y);
4625 case 2: /* neutral */
4630 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4635 I split out the routines to draw a piece so that I could
4636 make a generic flash routine.
4638 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4640 int square_color, x, y;
4643 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4644 switch (square_color) {
4646 case 2: /* neutral */
4648 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4649 ? *pieceToOutline(piece)
4650 : *pieceToSolid(piece),
4651 dest, bwPieceGC, 0, 0,
4652 squareSize, squareSize, x, y);
4655 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4656 ? *pieceToSolid(piece)
4657 : *pieceToOutline(piece),
4658 dest, wbPieceGC, 0, 0,
4659 squareSize, squareSize, x, y);
4664 static void monoDrawPiece(piece, square_color, x, y, dest)
4666 int square_color, x, y;
4669 switch (square_color) {
4671 case 2: /* neutral */
4673 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4674 ? *pieceToOutline(piece)
4675 : *pieceToSolid(piece),
4676 dest, bwPieceGC, 0, 0,
4677 squareSize, squareSize, x, y, 1);
4680 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4681 ? *pieceToSolid(piece)
4682 : *pieceToOutline(piece),
4683 dest, wbPieceGC, 0, 0,
4684 squareSize, squareSize, x, y, 1);
4689 static void colorDrawPiece(piece, square_color, x, y, dest)
4691 int square_color, x, y;
4694 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4695 switch (square_color) {
4697 XCopyPlane(xDisplay, *pieceToSolid(piece),
4698 dest, (int) piece < (int) BlackPawn
4699 ? wlPieceGC : blPieceGC, 0, 0,
4700 squareSize, squareSize, x, y, 1);
4703 XCopyPlane(xDisplay, *pieceToSolid(piece),
4704 dest, (int) piece < (int) BlackPawn
4705 ? wdPieceGC : bdPieceGC, 0, 0,
4706 squareSize, squareSize, x, y, 1);
4708 case 2: /* neutral */
4710 XCopyPlane(xDisplay, *pieceToSolid(piece),
4711 dest, (int) piece < (int) BlackPawn
4712 ? wjPieceGC : bjPieceGC, 0, 0,
4713 squareSize, squareSize, x, y, 1);
4718 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4720 int square_color, x, y;
4725 switch (square_color) {
4727 case 2: /* neutral */
4729 if ((int)piece < (int) BlackPawn) {
4737 if ((int)piece < (int) BlackPawn) {
4745 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4746 dest, wlPieceGC, 0, 0,
4747 squareSize, squareSize, x, y);
4750 typedef void (*DrawFunc)();
4752 DrawFunc ChooseDrawFunc()
4754 if (appData.monoMode) {
4755 if (DefaultDepth(xDisplay, xScreen) == 1) {
4756 return monoDrawPiece_1bit;
4758 return monoDrawPiece;
4762 return colorDrawPieceImage;
4764 return colorDrawPiece;
4768 /* [HR] determine square color depending on chess variant. */
4769 static int SquareColor(row, column)
4774 if (gameInfo.variant == VariantXiangqi) {
4775 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4777 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4779 } else if (row <= 4) {
4785 square_color = ((column + row) % 2) == 1;
4788 /* [hgm] holdings: next line makes all holdings squares light */
4789 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4791 return square_color;
4794 void DrawSquare(row, column, piece, do_flash)
4795 int row, column, do_flash;
4798 int square_color, x, y, direction, font_ascent, font_descent;
4801 XCharStruct overall;
4805 /* Calculate delay in milliseconds (2-delays per complete flash) */
4806 flash_delay = 500 / appData.flashRate;
4809 x = lineGap + ((BOARD_WIDTH-1)-column) *
4810 (squareSize + lineGap);
4811 y = lineGap + row * (squareSize + lineGap);
4813 x = lineGap + column * (squareSize + lineGap);
4814 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4815 (squareSize + lineGap);
4818 square_color = SquareColor(row, column);
4820 if ( // [HGM] holdings: blank out area between board and holdings
4821 column == BOARD_LEFT-1 || column == BOARD_RGHT
4822 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4823 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4824 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4826 // [HGM] print piece counts next to holdings
4827 string[1] = NULLCHAR;
4828 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4829 string[0] = '0' + piece;
4830 XTextExtents(countFontStruct, string, 1, &direction,
4831 &font_ascent, &font_descent, &overall);
4832 if (appData.monoMode) {
4833 XDrawImageString(xDisplay, xBoardWindow, countGC,
4834 x + squareSize - overall.width - 2,
4835 y + font_ascent + 1, string, 1);
4837 XDrawString(xDisplay, xBoardWindow, countGC,
4838 x + squareSize - overall.width - 2,
4839 y + font_ascent + 1, string, 1);
4842 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4843 string[0] = '0' + piece;
4844 XTextExtents(countFontStruct, string, 1, &direction,
4845 &font_ascent, &font_descent, &overall);
4846 if (appData.monoMode) {
4847 XDrawImageString(xDisplay, xBoardWindow, countGC,
4848 x + 2, y + font_ascent + 1, string, 1);
4850 XDrawString(xDisplay, xBoardWindow, countGC,
4851 x + 2, y + font_ascent + 1, string, 1);
4855 if (piece == EmptySquare || appData.blindfold) {
4856 BlankSquare(x, y, square_color, piece, xBoardWindow);
4858 drawfunc = ChooseDrawFunc();
4859 if (do_flash && appData.flashCount > 0) {
4860 for (i=0; i<appData.flashCount; ++i) {
4862 drawfunc(piece, square_color, x, y, xBoardWindow);
4863 XSync(xDisplay, False);
4864 do_flash_delay(flash_delay);
4866 BlankSquare(x, y, square_color, piece, xBoardWindow);
4867 XSync(xDisplay, False);
4868 do_flash_delay(flash_delay);
4871 drawfunc(piece, square_color, x, y, xBoardWindow);
4875 string[1] = NULLCHAR;
4876 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4877 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4878 string[0] = 'a' + column - BOARD_LEFT;
4879 XTextExtents(coordFontStruct, string, 1, &direction,
4880 &font_ascent, &font_descent, &overall);
4881 if (appData.monoMode) {
4882 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4883 x + squareSize - overall.width - 2,
4884 y + squareSize - font_descent - 1, string, 1);
4886 XDrawString(xDisplay, xBoardWindow, coordGC,
4887 x + squareSize - overall.width - 2,
4888 y + squareSize - font_descent - 1, string, 1);
4891 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4892 string[0] = ONE + row;
4893 XTextExtents(coordFontStruct, string, 1, &direction,
4894 &font_ascent, &font_descent, &overall);
4895 if (appData.monoMode) {
4896 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4897 x + 2, y + font_ascent + 1, string, 1);
4899 XDrawString(xDisplay, xBoardWindow, coordGC,
4900 x + 2, y + font_ascent + 1, string, 1);
4906 /* Why is this needed on some versions of X? */
4907 void EventProc(widget, unused, event)
4912 if (!XtIsRealized(widget))
4915 switch (event->type) {
4917 if (event->xexpose.count > 0) return; /* no clipping is done */
4918 XDrawPosition(widget, True, NULL);
4926 void DrawPosition(fullRedraw, board)
4927 /*Boolean*/int fullRedraw;
4930 XDrawPosition(boardWidget, fullRedraw, board);
4933 /* Returns 1 if there are "too many" differences between b1 and b2
4934 (i.e. more than 1 move was made) */
4935 static int too_many_diffs(b1, b2)
4941 for (i=0; i<BOARD_HEIGHT; ++i) {
4942 for (j=0; j<BOARD_WIDTH; ++j) {
4943 if (b1[i][j] != b2[i][j]) {
4944 if (++c > 4) /* Castling causes 4 diffs */
4953 /* Matrix describing castling maneuvers */
4954 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4955 static int castling_matrix[4][5] = {
4956 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4957 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4958 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4959 { 7, 7, 4, 5, 6 } /* 0-0, black */
4962 /* Checks whether castling occurred. If it did, *rrow and *rcol
4963 are set to the destination (row,col) of the rook that moved.
4965 Returns 1 if castling occurred, 0 if not.
4967 Note: Only handles a max of 1 castling move, so be sure
4968 to call too_many_diffs() first.
4970 static int check_castle_draw(newb, oldb, rrow, rcol)
4977 /* For each type of castling... */
4978 for (i=0; i<4; ++i) {
4979 r = castling_matrix[i];
4981 /* Check the 4 squares involved in the castling move */
4983 for (j=1; j<=4; ++j) {
4984 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4991 /* All 4 changed, so it must be a castling move */
5000 static int damage[BOARD_SIZE][BOARD_SIZE];
5003 * event handler for redrawing the board
5005 void XDrawPosition(w, repaint, board)
5007 /*Boolean*/int repaint;
5011 static int lastFlipView = 0;
5012 static int lastBoardValid = 0;
5013 static Board lastBoard;
5017 if (board == NULL) {
5018 if (!lastBoardValid) return;
5021 if (!lastBoardValid || lastFlipView != flipView) {
5022 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5023 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5028 * It would be simpler to clear the window with XClearWindow()
5029 * but this causes a very distracting flicker.
5032 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5034 /* If too much changes (begin observing new game, etc.), don't
5036 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5038 /* Special check for castling so we don't flash both the king
5039 and the rook (just flash the king). */
5041 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5042 /* Draw rook with NO flashing. King will be drawn flashing later */
5043 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5044 lastBoard[rrow][rcol] = board[rrow][rcol];
5048 /* First pass -- Draw (newly) empty squares and repair damage.
5049 This prevents you from having a piece show up twice while it
5050 is flashing on its new square */
5051 for (i = 0; i < BOARD_HEIGHT; i++)
5052 for (j = 0; j < BOARD_WIDTH; j++)
5053 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5055 DrawSquare(i, j, board[i][j], 0);
5056 damage[i][j] = False;
5059 /* Second pass -- Draw piece(s) in new position and flash them */
5060 for (i = 0; i < BOARD_HEIGHT; i++)
5061 for (j = 0; j < BOARD_WIDTH; j++)
5062 if (board[i][j] != lastBoard[i][j]) {
5063 DrawSquare(i, j, board[i][j], do_flash);
5067 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5068 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5070 for (i = 0; i < BOARD_HEIGHT; i++)
5071 for (j = 0; j < BOARD_WIDTH; j++) {
5072 DrawSquare(i, j, board[i][j], 0);
5073 damage[i][j] = False;
5077 CopyBoard(lastBoard, board);
5079 lastFlipView = flipView;
5081 /* Draw highlights */
5082 if (pm1X >= 0 && pm1Y >= 0) {
5083 drawHighlight(pm1X, pm1Y, prelineGC);
5085 if (pm2X >= 0 && pm2Y >= 0) {
5086 drawHighlight(pm2X, pm2Y, prelineGC);
5088 if (hi1X >= 0 && hi1Y >= 0) {
5089 drawHighlight(hi1X, hi1Y, highlineGC);
5091 if (hi2X >= 0 && hi2Y >= 0) {
5092 drawHighlight(hi2X, hi2Y, highlineGC);
5095 /* If piece being dragged around board, must redraw that too */
5098 XSync(xDisplay, False);
5103 * event handler for redrawing the board
5105 void DrawPositionProc(w, event, prms, nprms)
5111 XDrawPosition(w, True, NULL);
5116 * event handler for parsing user moves
5118 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5119 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5120 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5121 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5122 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5123 // and at the end FinishMove() to perform the move after optional promotion popups.
5124 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5125 void HandleUserMove(w, event, prms, nprms)
5131 if (w != boardWidget || errorExitStatus != -1) return;
5134 if (event->type == ButtonPress) {
5135 XtPopdown(promotionShell);
5136 XtDestroyWidget(promotionShell);
5137 promotionUp = False;
5145 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5146 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5147 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5150 void AnimateUserMove (Widget w, XEvent * event,
5151 String * params, Cardinal * nParams)
5153 DragPieceMove(event->xmotion.x, event->xmotion.y);
5156 Widget CommentCreate(name, text, mutable, callback, lines)
5158 int /*Boolean*/ mutable;
5159 XtCallbackProc callback;
5163 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5168 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5169 XtGetValues(boardWidget, args, j);
5172 XtSetArg(args[j], XtNresizable, True); j++;
5175 XtCreatePopupShell(name, topLevelShellWidgetClass,
5176 shellWidget, args, j);
5179 XtCreatePopupShell(name, transientShellWidgetClass,
5180 shellWidget, args, j);
5183 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5184 layoutArgs, XtNumber(layoutArgs));
5186 XtCreateManagedWidget("form", formWidgetClass, layout,
5187 formArgs, XtNumber(formArgs));
5191 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5192 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5194 XtSetArg(args[j], XtNstring, text); j++;
5195 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5196 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5197 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5198 XtSetArg(args[j], XtNright, XtChainRight); j++;
5199 XtSetArg(args[j], XtNresizable, True); j++;
5200 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5201 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5202 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5203 XtSetArg(args[j], XtNautoFill, True); j++;
5204 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5206 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5210 XtSetArg(args[j], XtNfromVert, edit); j++;
5211 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5212 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5213 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5214 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5216 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5217 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5220 XtSetArg(args[j], XtNfromVert, edit); j++;
5221 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5222 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5223 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5224 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5225 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5227 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5228 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5231 XtSetArg(args[j], XtNfromVert, edit); j++;
5232 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5233 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5234 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5235 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5236 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5238 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5239 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5242 XtSetArg(args[j], XtNfromVert, edit); j++;
5243 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5244 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5245 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5246 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5248 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5249 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5252 XtSetArg(args[j], XtNfromVert, edit); j++;
5253 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5254 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5255 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5256 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5257 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5259 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5260 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5263 XtRealizeWidget(shell);
5265 if (commentX == -1) {
5268 Dimension pw_height;
5269 Dimension ew_height;
5272 XtSetArg(args[j], XtNheight, &ew_height); j++;
5273 XtGetValues(edit, args, j);
5276 XtSetArg(args[j], XtNheight, &pw_height); j++;
5277 XtGetValues(shell, args, j);
5278 commentH = pw_height + (lines - 1) * ew_height;
5279 commentW = bw_width - 16;
5281 XSync(xDisplay, False);
5283 /* This code seems to tickle an X bug if it is executed too soon
5284 after xboard starts up. The coordinates get transformed as if
5285 the main window was positioned at (0, 0).
5287 XtTranslateCoords(shellWidget,
5288 (bw_width - commentW) / 2, 0 - commentH / 2,
5289 &commentX, &commentY);
5291 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5292 RootWindowOfScreen(XtScreen(shellWidget)),
5293 (bw_width - commentW) / 2, 0 - commentH / 2,
5298 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5301 XtSetArg(args[j], XtNheight, commentH); j++;
5302 XtSetArg(args[j], XtNwidth, commentW); j++;
5303 XtSetArg(args[j], XtNx, commentX); j++;
5304 XtSetArg(args[j], XtNy, commentY); j++;
5305 XtSetValues(shell, args, j);
5306 XtSetKeyboardFocus(shell, edit);
5311 /* Used for analysis window and ICS input window */
5312 Widget MiscCreate(name, text, mutable, callback, lines)
5314 int /*Boolean*/ mutable;
5315 XtCallbackProc callback;
5319 Widget shell, layout, form, edit;
5321 Dimension bw_width, pw_height, ew_height, w, h;
5327 XtSetArg(args[j], XtNresizable, True); j++;
5330 XtCreatePopupShell(name, topLevelShellWidgetClass,
5331 shellWidget, args, j);
5334 XtCreatePopupShell(name, transientShellWidgetClass,
5335 shellWidget, args, j);
5338 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5339 layoutArgs, XtNumber(layoutArgs));
5341 XtCreateManagedWidget("form", formWidgetClass, layout,
5342 formArgs, XtNumber(formArgs));
5346 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5347 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5349 XtSetArg(args[j], XtNstring, text); j++;
5350 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5351 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5352 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5353 XtSetArg(args[j], XtNright, XtChainRight); j++;
5354 XtSetArg(args[j], XtNresizable, True); j++;
5355 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5356 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5357 XtSetArg(args[j], XtNautoFill, True); j++;
5358 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5360 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5362 XtRealizeWidget(shell);
5365 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5366 XtGetValues(boardWidget, args, j);
5369 XtSetArg(args[j], XtNheight, &ew_height); j++;
5370 XtGetValues(edit, args, j);
5373 XtSetArg(args[j], XtNheight, &pw_height); j++;
5374 XtGetValues(shell, args, j);
5375 h = pw_height + (lines - 1) * ew_height;
5378 XSync(xDisplay, False);
5380 /* This code seems to tickle an X bug if it is executed too soon
5381 after xboard starts up. The coordinates get transformed as if
5382 the main window was positioned at (0, 0).
5384 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5386 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5387 RootWindowOfScreen(XtScreen(shellWidget)),
5388 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5392 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5395 XtSetArg(args[j], XtNheight, h); j++;
5396 XtSetArg(args[j], XtNwidth, w); j++;
5397 XtSetArg(args[j], XtNx, x); j++;
5398 XtSetArg(args[j], XtNy, y); j++;
5399 XtSetValues(shell, args, j);
5405 static int savedIndex; /* gross that this is global */
5407 void EditCommentPopUp(index, title, text)
5416 if (text == NULL) text = "";
5418 if (editShell == NULL) {
5420 CommentCreate(title, text, True, EditCommentCallback, 4);
5421 XtRealizeWidget(editShell);
5422 CatchDeleteWindow(editShell, "EditCommentPopDown");
5424 edit = XtNameToWidget(editShell, "*form.text");
5426 XtSetArg(args[j], XtNstring, text); j++;
5427 XtSetValues(edit, args, j);
5429 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5430 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5431 XtSetValues(editShell, args, j);
5434 XtPopup(editShell, XtGrabNone);
5438 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5439 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5443 void EditCommentCallback(w, client_data, call_data)
5445 XtPointer client_data, call_data;
5453 XtSetArg(args[j], XtNlabel, &name); j++;
5454 XtGetValues(w, args, j);
5456 if (strcmp(name, _("ok")) == 0) {
5457 edit = XtNameToWidget(editShell, "*form.text");
5459 XtSetArg(args[j], XtNstring, &val); j++;
5460 XtGetValues(edit, args, j);
5461 ReplaceComment(savedIndex, val);
5462 EditCommentPopDown();
5463 } else if (strcmp(name, _("cancel")) == 0) {
5464 EditCommentPopDown();
5465 } else if (strcmp(name, _("clear")) == 0) {
5466 edit = XtNameToWidget(editShell, "*form.text");
5467 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5468 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5472 void EditCommentPopDown()
5477 if (!editUp) return;
5479 XtSetArg(args[j], XtNx, &commentX); j++;
5480 XtSetArg(args[j], XtNy, &commentY); j++;
5481 XtSetArg(args[j], XtNheight, &commentH); j++;
5482 XtSetArg(args[j], XtNwidth, &commentW); j++;
5483 XtGetValues(editShell, args, j);
5484 XtPopdown(editShell);
5487 XtSetArg(args[j], XtNleftBitmap, None); j++;
5488 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5492 void ICSInputBoxPopUp()
5497 char *title = _("ICS Input");
5500 if (ICSInputShell == NULL) {
5501 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5502 tr = XtParseTranslationTable(ICSInputTranslations);
5503 edit = XtNameToWidget(ICSInputShell, "*form.text");
5504 XtOverrideTranslations(edit, tr);
5505 XtRealizeWidget(ICSInputShell);
5506 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5509 edit = XtNameToWidget(ICSInputShell, "*form.text");
5511 XtSetArg(args[j], XtNstring, ""); j++;
5512 XtSetValues(edit, args, j);
5514 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5515 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5516 XtSetValues(ICSInputShell, args, j);
5519 XtPopup(ICSInputShell, XtGrabNone);
5520 XtSetKeyboardFocus(ICSInputShell, edit);
5522 ICSInputBoxUp = True;
5524 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5525 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5529 void ICSInputSendText()
5536 edit = XtNameToWidget(ICSInputShell, "*form.text");
5538 XtSetArg(args[j], XtNstring, &val); j++;
5539 XtGetValues(edit, args, j);
5540 SendMultiLineToICS(val);
5541 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5542 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5545 void ICSInputBoxPopDown()
5550 if (!ICSInputBoxUp) return;
5552 XtPopdown(ICSInputShell);
5553 ICSInputBoxUp = False;
5555 XtSetArg(args[j], XtNleftBitmap, None); j++;
5556 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5560 void CommentPopUp(title, text)
5567 if (commentShell == NULL) {
5569 CommentCreate(title, text, False, CommentCallback, 4);
5570 XtRealizeWidget(commentShell);
5571 CatchDeleteWindow(commentShell, "CommentPopDown");
5573 edit = XtNameToWidget(commentShell, "*form.text");
5575 XtSetArg(args[j], XtNstring, text); j++;
5576 XtSetValues(edit, args, j);
5578 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5579 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5580 XtSetValues(commentShell, args, j);
5583 XtPopup(commentShell, XtGrabNone);
5584 XSync(xDisplay, False);
5589 void CommentCallback(w, client_data, call_data)
5591 XtPointer client_data, call_data;
5598 XtSetArg(args[j], XtNlabel, &name); j++;
5599 XtGetValues(w, args, j);
5601 if (strcmp(name, _("close")) == 0) {
5603 } else if (strcmp(name, _("edit")) == 0) {
5610 void CommentPopDown()
5615 if (!commentUp) return;
5617 XtSetArg(args[j], XtNx, &commentX); j++;
5618 XtSetArg(args[j], XtNy, &commentY); j++;
5619 XtSetArg(args[j], XtNwidth, &commentW); j++;
5620 XtSetArg(args[j], XtNheight, &commentH); j++;
5621 XtGetValues(commentShell, args, j);
5622 XtPopdown(commentShell);
5623 XSync(xDisplay, False);
5627 void FileNamePopUp(label, def, proc, openMode)
5634 Widget popup, layout, dialog, edit;
5640 fileProc = proc; /* I can't see a way not */
5641 fileOpenMode = openMode; /* to use globals here */
5644 XtSetArg(args[i], XtNresizable, True); i++;
5645 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5646 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5647 fileNameShell = popup =
5648 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5649 shellWidget, args, i);
5652 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5653 layoutArgs, XtNumber(layoutArgs));
5656 XtSetArg(args[i], XtNlabel, label); i++;
5657 XtSetArg(args[i], XtNvalue, def); i++;
5658 XtSetArg(args[i], XtNborderWidth, 0); i++;
5659 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5662 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5663 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5664 (XtPointer) dialog);
5666 XtRealizeWidget(popup);
5667 CatchDeleteWindow(popup, "FileNamePopDown");
5669 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5670 &x, &y, &win_x, &win_y, &mask);
5672 XtSetArg(args[0], XtNx, x - 10);
5673 XtSetArg(args[1], XtNy, y - 30);
5674 XtSetValues(popup, args, 2);
5676 XtPopup(popup, XtGrabExclusive);
5679 edit = XtNameToWidget(dialog, "*value");
5680 XtSetKeyboardFocus(popup, edit);
5683 void FileNamePopDown()
5685 if (!filenameUp) return;
5686 XtPopdown(fileNameShell);
5687 XtDestroyWidget(fileNameShell);
5692 void FileNameCallback(w, client_data, call_data)
5694 XtPointer client_data, call_data;
5699 XtSetArg(args[0], XtNlabel, &name);
5700 XtGetValues(w, args, 1);
5702 if (strcmp(name, _("cancel")) == 0) {
5707 FileNameAction(w, NULL, NULL, NULL);
5710 void FileNameAction(w, event, prms, nprms)
5722 name = XawDialogGetValueString(w = XtParent(w));
5724 if ((name != NULL) && (*name != NULLCHAR)) {
5726 XtPopdown(w = XtParent(XtParent(w)));
5730 p = strrchr(buf, ' ');
5737 fullname = ExpandPathName(buf);
5739 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5742 f = fopen(fullname, fileOpenMode);
5744 DisplayError(_("Failed to open file"), errno);
5746 (void) (*fileProc)(f, index, buf);
5753 XtPopdown(w = XtParent(XtParent(w)));
5759 void PromotionPopUp()
5762 Widget dialog, layout;
5764 Dimension bw_width, pw_width;
5768 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5769 XtGetValues(boardWidget, args, j);
5772 XtSetArg(args[j], XtNresizable, True); j++;
5773 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5775 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5776 shellWidget, args, j);
5778 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5779 layoutArgs, XtNumber(layoutArgs));
5782 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5783 XtSetArg(args[j], XtNborderWidth, 0); j++;
5784 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5787 if(gameInfo.variant != VariantShogi) {
5788 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5789 (XtPointer) dialog);
5790 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5791 (XtPointer) dialog);
5792 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5793 (XtPointer) dialog);
5794 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5795 (XtPointer) dialog);
5796 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5797 gameInfo.variant == VariantGiveaway) {
5798 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5799 (XtPointer) dialog);
5801 if(gameInfo.variant == VariantCapablanca ||
5802 gameInfo.variant == VariantGothic ||
5803 gameInfo.variant == VariantCapaRandom) {
5804 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5805 (XtPointer) dialog);
5806 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5807 (XtPointer) dialog);
5809 } else // [HGM] shogi
5811 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5812 (XtPointer) dialog);
5813 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5814 (XtPointer) dialog);
5816 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5817 (XtPointer) dialog);
5819 XtRealizeWidget(promotionShell);
5820 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5823 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5824 XtGetValues(promotionShell, args, j);
5826 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5827 lineGap + squareSize/3 +
5828 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5829 0 : 6*(squareSize + lineGap)), &x, &y);
5832 XtSetArg(args[j], XtNx, x); j++;
5833 XtSetArg(args[j], XtNy, y); j++;
5834 XtSetValues(promotionShell, args, j);
5836 XtPopup(promotionShell, XtGrabNone);
5841 void PromotionPopDown()
5843 if (!promotionUp) return;
5844 XtPopdown(promotionShell);
5845 XtDestroyWidget(promotionShell);
5846 promotionUp = False;
5849 void PromotionCallback(w, client_data, call_data)
5851 XtPointer client_data, call_data;
5857 XtSetArg(args[0], XtNlabel, &name);
5858 XtGetValues(w, args, 1);
5862 if (fromX == -1) return;
5864 if (strcmp(name, _("cancel")) == 0) {
5868 } else if (strcmp(name, _("Knight")) == 0) {
5870 } else if (strcmp(name, _("Promote")) == 0) {
5872 } else if (strcmp(name, _("Defer")) == 0) {
5875 promoChar = ToLower(name[0]);
5878 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5880 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5881 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5886 void ErrorCallback(w, client_data, call_data)
5888 XtPointer client_data, call_data;
5891 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5893 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5899 if (!errorUp) return;
5901 XtPopdown(errorShell);
5902 XtDestroyWidget(errorShell);
5903 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5906 void ErrorPopUp(title, label, modal)
5907 char *title, *label;
5911 Widget dialog, layout;
5915 Dimension bw_width, pw_width;
5916 Dimension pw_height;
5920 XtSetArg(args[i], XtNresizable, True); i++;
5921 XtSetArg(args[i], XtNtitle, title); i++;
5923 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5924 shellWidget, args, i);
5926 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5927 layoutArgs, XtNumber(layoutArgs));
5930 XtSetArg(args[i], XtNlabel, label); i++;
5931 XtSetArg(args[i], XtNborderWidth, 0); i++;
5932 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5935 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5937 XtRealizeWidget(errorShell);
5938 CatchDeleteWindow(errorShell, "ErrorPopDown");
5941 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5942 XtGetValues(boardWidget, args, i);
5944 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5945 XtSetArg(args[i], XtNheight, &pw_height); i++;
5946 XtGetValues(errorShell, args, i);
5949 /* This code seems to tickle an X bug if it is executed too soon
5950 after xboard starts up. The coordinates get transformed as if
5951 the main window was positioned at (0, 0).
5953 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5954 0 - pw_height + squareSize / 3, &x, &y);
5956 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5957 RootWindowOfScreen(XtScreen(boardWidget)),
5958 (bw_width - pw_width) / 2,
5959 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5963 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5966 XtSetArg(args[i], XtNx, x); i++;
5967 XtSetArg(args[i], XtNy, y); i++;
5968 XtSetValues(errorShell, args, i);
5971 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5974 /* Disable all user input other than deleting the window */
5975 static int frozen = 0;
5979 /* Grab by a widget that doesn't accept input */
5980 XtAddGrab(messageWidget, TRUE, FALSE);
5984 /* Undo a FreezeUI */
5987 if (!frozen) return;
5988 XtRemoveGrab(messageWidget);
5992 char *ModeToWidgetName(mode)
5996 case BeginningOfGame:
5997 if (appData.icsActive)
5998 return "menuMode.ICS Client";
5999 else if (appData.noChessProgram ||
6000 *appData.cmailGameName != NULLCHAR)
6001 return "menuMode.Edit Game";
6003 return "menuMode.Machine Black";
6004 case MachinePlaysBlack:
6005 return "menuMode.Machine Black";
6006 case MachinePlaysWhite:
6007 return "menuMode.Machine White";
6009 return "menuMode.Analysis Mode";
6011 return "menuMode.Analyze File";
6012 case TwoMachinesPlay:
6013 return "menuMode.Two Machines";
6015 return "menuMode.Edit Game";
6016 case PlayFromGameFile:
6017 return "menuFile.Load Game";
6019 return "menuMode.Edit Position";
6021 return "menuMode.Training";
6022 case IcsPlayingWhite:
6023 case IcsPlayingBlack:
6027 return "menuMode.ICS Client";
6034 void ModeHighlight()
6037 static int oldPausing = FALSE;
6038 static GameMode oldmode = (GameMode) -1;
6041 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6043 if (pausing != oldPausing) {
6044 oldPausing = pausing;
6046 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6048 XtSetArg(args[0], XtNleftBitmap, None);
6050 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6053 if (appData.showButtonBar) {
6054 /* Always toggle, don't set. Previous code messes up when
6055 invoked while the button is pressed, as releasing it
6056 toggles the state again. */
6059 XtSetArg(args[0], XtNbackground, &oldbg);
6060 XtSetArg(args[1], XtNforeground, &oldfg);
6061 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6063 XtSetArg(args[0], XtNbackground, oldfg);
6064 XtSetArg(args[1], XtNforeground, oldbg);
6066 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6070 wname = ModeToWidgetName(oldmode);
6071 if (wname != NULL) {
6072 XtSetArg(args[0], XtNleftBitmap, None);
6073 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6075 wname = ModeToWidgetName(gameMode);
6076 if (wname != NULL) {
6077 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6078 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6082 /* Maybe all the enables should be handled here, not just this one */
6083 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6084 gameMode == Training || gameMode == PlayFromGameFile);
6089 * Button/menu procedures
6091 void ResetProc(w, event, prms, nprms)
6100 int LoadGamePopUp(f, gameNumber, title)
6105 cmailMsgLoaded = FALSE;
6106 if (gameNumber == 0) {
6107 int error = GameListBuild(f);
6109 DisplayError(_("Cannot build game list"), error);
6110 } else if (!ListEmpty(&gameList) &&
6111 ((ListGame *) gameList.tailPred)->number > 1) {
6112 GameListPopUp(f, title);
6118 return LoadGame(f, gameNumber, title, FALSE);
6121 void LoadGameProc(w, event, prms, nprms)
6127 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6130 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6133 void LoadNextGameProc(w, event, prms, nprms)
6142 void LoadPrevGameProc(w, event, prms, nprms)
6151 void ReloadGameProc(w, event, prms, nprms)
6160 void LoadNextPositionProc(w, event, prms, nprms)
6169 void LoadPrevPositionProc(w, event, prms, nprms)
6178 void ReloadPositionProc(w, event, prms, nprms)
6187 void LoadPositionProc(w, event, prms, nprms)
6193 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6196 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6199 void SaveGameProc(w, event, prms, nprms)
6205 FileNamePopUp(_("Save game file name?"),
6206 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6210 void SavePositionProc(w, event, prms, nprms)
6216 FileNamePopUp(_("Save position file name?"),
6217 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6221 void ReloadCmailMsgProc(w, event, prms, nprms)
6227 ReloadCmailMsgEvent(FALSE);
6230 void MailMoveProc(w, event, prms, nprms)
6239 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6240 static char *selected_fen_position=NULL;
6243 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6244 Atom *type_return, XtPointer *value_return,
6245 unsigned long *length_return, int *format_return)
6247 char *selection_tmp;
6249 if (!selected_fen_position) return False; /* should never happen */
6250 if (*target == XA_STRING){
6251 /* note: since no XtSelectionDoneProc was registered, Xt will
6252 * automatically call XtFree on the value returned. So have to
6253 * make a copy of it allocated with XtMalloc */
6254 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6255 strcpy(selection_tmp, selected_fen_position);
6257 *value_return=selection_tmp;
6258 *length_return=strlen(selection_tmp);
6259 *type_return=XA_STRING;
6260 *format_return = 8; /* bits per byte */
6267 /* note: when called from menu all parameters are NULL, so no clue what the
6268 * Widget which was clicked on was, or what the click event was
6270 void CopyPositionProc(w, event, prms, nprms)
6278 if (selected_fen_position) free(selected_fen_position);
6279 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6280 if (!selected_fen_position) return;
6281 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6283 SendPositionSelection,
6284 NULL/* lose_ownership_proc */ ,
6285 NULL/* transfer_done_proc */);
6287 free(selected_fen_position);
6288 selected_fen_position=NULL;
6292 /* function called when the data to Paste is ready */
6294 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6295 Atom *type, XtPointer value, unsigned long *len, int *format)
6298 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6299 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6300 EditPositionPasteFEN(fenstr);
6304 /* called when Paste Position button is pressed,
6305 * all parameters will be NULL */
6306 void PastePositionProc(w, event, prms, nprms)
6312 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6313 /* (XtSelectionCallbackProc) */ PastePositionCB,
6314 NULL, /* client_data passed to PastePositionCB */
6316 /* better to use the time field from the event that triggered the
6317 * call to this function, but that isn't trivial to get
6325 SendGameSelection(Widget w, Atom *selection, Atom *target,
6326 Atom *type_return, XtPointer *value_return,
6327 unsigned long *length_return, int *format_return)
6329 char *selection_tmp;
6331 if (*target == XA_STRING){
6332 FILE* f = fopen(gameCopyFilename, "r");
6335 if (f == NULL) return False;
6339 selection_tmp = XtMalloc(len + 1);
6340 count = fread(selection_tmp, 1, len, f);
6342 XtFree(selection_tmp);
6345 selection_tmp[len] = NULLCHAR;
6346 *value_return = selection_tmp;
6347 *length_return = len;
6348 *type_return = XA_STRING;
6349 *format_return = 8; /* bits per byte */
6356 /* note: when called from menu all parameters are NULL, so no clue what the
6357 * Widget which was clicked on was, or what the click event was
6359 void CopyGameProc(w, event, prms, nprms)
6367 ret = SaveGameToFile(gameCopyFilename, FALSE);
6370 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6373 NULL/* lose_ownership_proc */ ,
6374 NULL/* transfer_done_proc */);
6377 /* function called when the data to Paste is ready */
6379 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6380 Atom *type, XtPointer value, unsigned long *len, int *format)
6383 if (value == NULL || *len == 0) {
6384 return; /* nothing had been selected to copy */
6386 f = fopen(gamePasteFilename, "w");
6388 DisplayError(_("Can't open temp file"), errno);
6391 fwrite(value, 1, *len, f);
6394 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6397 /* called when Paste Game button is pressed,
6398 * all parameters will be NULL */
6399 void PasteGameProc(w, event, prms, nprms)
6405 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6406 /* (XtSelectionCallbackProc) */ PasteGameCB,
6407 NULL, /* client_data passed to PasteGameCB */
6409 /* better to use the time field from the event that triggered the
6410 * call to this function, but that isn't trivial to get
6420 SaveGameProc(NULL, NULL, NULL, NULL);
6424 void QuitProc(w, event, prms, nprms)
6433 void PauseProc(w, event, prms, nprms)
6443 void MachineBlackProc(w, event, prms, nprms)
6449 MachineBlackEvent();
6452 void MachineWhiteProc(w, event, prms, nprms)
6458 MachineWhiteEvent();
6461 void AnalyzeModeProc(w, event, prms, nprms)
6469 if (!first.analysisSupport) {
6470 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6471 DisplayError(buf, 0);
6474 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6475 if (appData.icsActive) {
6476 if (gameMode != IcsObserving) {
6477 sprintf(buf,_("You are not observing a game"));
6478 DisplayError(buf, 0);
6480 if (appData.icsEngineAnalyze) {
6481 if (appData.debugMode)
6482 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6488 /* if enable, use want disable icsEngineAnalyze */
6489 if (appData.icsEngineAnalyze) {
6494 appData.icsEngineAnalyze = TRUE;
6495 if (appData.debugMode)
6496 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6498 if (!appData.showThinking)
6499 ShowThinkingProc(w,event,prms,nprms);
6504 void AnalyzeFileProc(w, event, prms, nprms)
6510 if (!first.analysisSupport) {
6512 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6513 DisplayError(buf, 0);
6518 if (!appData.showThinking)
6519 ShowThinkingProc(w,event,prms,nprms);
6522 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6523 AnalysisPeriodicEvent(1);
6526 void TwoMachinesProc(w, event, prms, nprms)
6535 void IcsClientProc(w, event, prms, nprms)
6544 void EditGameProc(w, event, prms, nprms)
6553 void EditPositionProc(w, event, prms, nprms)
6559 EditPositionEvent();
6562 void TrainingProc(w, event, prms, nprms)
6571 void EditCommentProc(w, event, prms, nprms)
6578 EditCommentPopDown();
6584 void IcsInputBoxProc(w, event, prms, nprms)
6590 if (ICSInputBoxUp) {
6591 ICSInputBoxPopDown();
6597 void AcceptProc(w, event, prms, nprms)
6606 void DeclineProc(w, event, prms, nprms)
6615 void RematchProc(w, event, prms, nprms)
6624 void CallFlagProc(w, event, prms, nprms)
6633 void DrawProc(w, event, prms, nprms)
6642 void AbortProc(w, event, prms, nprms)
6651 void AdjournProc(w, event, prms, nprms)
6660 void ResignProc(w, event, prms, nprms)
6669 void AdjuWhiteProc(w, event, prms, nprms)
6675 UserAdjudicationEvent(+1);
6678 void AdjuBlackProc(w, event, prms, nprms)
6684 UserAdjudicationEvent(-1);
6687 void AdjuDrawProc(w, event, prms, nprms)
6693 UserAdjudicationEvent(0);
6696 void EnterKeyProc(w, event, prms, nprms)
6702 if (ICSInputBoxUp == True)
6706 void StopObservingProc(w, event, prms, nprms)
6712 StopObservingEvent();
6715 void StopExaminingProc(w, event, prms, nprms)
6721 StopExaminingEvent();
6725 void ForwardProc(w, event, prms, nprms)
6735 void BackwardProc(w, event, prms, nprms)
6744 void ToStartProc(w, event, prms, nprms)
6753 void ToEndProc(w, event, prms, nprms)
6762 void RevertProc(w, event, prms, nprms)
6771 void TruncateGameProc(w, event, prms, nprms)
6777 TruncateGameEvent();
6779 void RetractMoveProc(w, event, prms, nprms)
6788 void MoveNowProc(w, event, prms, nprms)
6798 void AlwaysQueenProc(w, event, prms, nprms)
6806 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6808 if (appData.alwaysPromoteToQueen) {
6809 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6811 XtSetArg(args[0], XtNleftBitmap, None);
6813 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6817 void AnimateDraggingProc(w, event, prms, nprms)
6825 appData.animateDragging = !appData.animateDragging;
6827 if (appData.animateDragging) {
6828 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6831 XtSetArg(args[0], XtNleftBitmap, None);
6833 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6837 void AnimateMovingProc(w, event, prms, nprms)
6845 appData.animate = !appData.animate;
6847 if (appData.animate) {
6848 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6851 XtSetArg(args[0], XtNleftBitmap, None);
6853 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6857 void AutocommProc(w, event, prms, nprms)
6865 appData.autoComment = !appData.autoComment;
6867 if (appData.autoComment) {
6868 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6870 XtSetArg(args[0], XtNleftBitmap, None);
6872 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6877 void AutoflagProc(w, event, prms, nprms)
6885 appData.autoCallFlag = !appData.autoCallFlag;
6887 if (appData.autoCallFlag) {
6888 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6890 XtSetArg(args[0], XtNleftBitmap, None);
6892 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6896 void AutoflipProc(w, event, prms, nprms)
6904 appData.autoFlipView = !appData.autoFlipView;
6906 if (appData.autoFlipView) {
6907 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6909 XtSetArg(args[0], XtNleftBitmap, None);
6911 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6915 void AutobsProc(w, event, prms, nprms)
6923 appData.autoObserve = !appData.autoObserve;
6925 if (appData.autoObserve) {
6926 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6928 XtSetArg(args[0], XtNleftBitmap, None);
6930 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6934 void AutoraiseProc(w, event, prms, nprms)
6942 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6944 if (appData.autoRaiseBoard) {
6945 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6947 XtSetArg(args[0], XtNleftBitmap, None);
6949 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6953 void AutosaveProc(w, event, prms, nprms)
6961 appData.autoSaveGames = !appData.autoSaveGames;
6963 if (appData.autoSaveGames) {
6964 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6966 XtSetArg(args[0], XtNleftBitmap, None);
6968 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6972 void BlindfoldProc(w, event, prms, nprms)
6980 appData.blindfold = !appData.blindfold;
6982 if (appData.blindfold) {
6983 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6985 XtSetArg(args[0], XtNleftBitmap, None);
6987 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6990 DrawPosition(True, NULL);
6993 void TestLegalityProc(w, event, prms, nprms)
7001 appData.testLegality = !appData.testLegality;
7003 if (appData.testLegality) {
7004 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7006 XtSetArg(args[0], XtNleftBitmap, None);
7008 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7013 void FlashMovesProc(w, event, prms, nprms)
7021 if (appData.flashCount == 0) {
7022 appData.flashCount = 3;
7024 appData.flashCount = -appData.flashCount;
7027 if (appData.flashCount > 0) {
7028 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7030 XtSetArg(args[0], XtNleftBitmap, None);
7032 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7036 void FlipViewProc(w, event, prms, nprms)
7042 flipView = !flipView;
7043 DrawPosition(True, NULL);
7046 void GetMoveListProc(w, event, prms, nprms)
7054 appData.getMoveList = !appData.getMoveList;
7056 if (appData.getMoveList) {
7057 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7060 XtSetArg(args[0], XtNleftBitmap, None);
7062 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7067 void HighlightDraggingProc(w, event, prms, nprms)
7075 appData.highlightDragging = !appData.highlightDragging;
7077 if (appData.highlightDragging) {
7078 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7080 XtSetArg(args[0], XtNleftBitmap, None);
7082 XtSetValues(XtNameToWidget(menuBarWidget,
7083 "menuOptions.Highlight Dragging"), args, 1);
7087 void HighlightLastMoveProc(w, event, prms, nprms)
7095 appData.highlightLastMove = !appData.highlightLastMove;
7097 if (appData.highlightLastMove) {
7098 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7100 XtSetArg(args[0], XtNleftBitmap, None);
7102 XtSetValues(XtNameToWidget(menuBarWidget,
7103 "menuOptions.Highlight Last Move"), args, 1);
7106 void IcsAlarmProc(w, event, prms, nprms)
7114 appData.icsAlarm = !appData.icsAlarm;
7116 if (appData.icsAlarm) {
7117 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7119 XtSetArg(args[0], XtNleftBitmap, None);
7121 XtSetValues(XtNameToWidget(menuBarWidget,
7122 "menuOptions.ICS Alarm"), args, 1);
7125 void MoveSoundProc(w, event, prms, nprms)
7133 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7135 if (appData.ringBellAfterMoves) {
7136 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7138 XtSetArg(args[0], XtNleftBitmap, None);
7140 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7145 void OldSaveStyleProc(w, event, prms, nprms)
7153 appData.oldSaveStyle = !appData.oldSaveStyle;
7155 if (appData.oldSaveStyle) {
7156 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7158 XtSetArg(args[0], XtNleftBitmap, None);
7160 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7164 void PeriodicUpdatesProc(w, event, prms, nprms)
7172 PeriodicUpdatesEvent(!appData.periodicUpdates);
7174 if (appData.periodicUpdates) {
7175 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7177 XtSetArg(args[0], XtNleftBitmap, None);
7179 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7183 void PonderNextMoveProc(w, event, prms, nprms)
7191 PonderNextMoveEvent(!appData.ponderNextMove);
7193 if (appData.ponderNextMove) {
7194 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7196 XtSetArg(args[0], XtNleftBitmap, None);
7198 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7202 void PopupExitMessageProc(w, event, prms, nprms)
7210 appData.popupExitMessage = !appData.popupExitMessage;
7212 if (appData.popupExitMessage) {
7213 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7215 XtSetArg(args[0], XtNleftBitmap, None);
7217 XtSetValues(XtNameToWidget(menuBarWidget,
7218 "menuOptions.Popup Exit Message"), args, 1);
7221 void PopupMoveErrorsProc(w, event, prms, nprms)
7229 appData.popupMoveErrors = !appData.popupMoveErrors;
7231 if (appData.popupMoveErrors) {
7232 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7234 XtSetArg(args[0], XtNleftBitmap, None);
7236 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7240 void PremoveProc(w, event, prms, nprms)
7248 appData.premove = !appData.premove;
7250 if (appData.premove) {
7251 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7253 XtSetArg(args[0], XtNleftBitmap, None);
7255 XtSetValues(XtNameToWidget(menuBarWidget,
7256 "menuOptions.Premove"), args, 1);
7259 void QuietPlayProc(w, event, prms, nprms)
7267 appData.quietPlay = !appData.quietPlay;
7269 if (appData.quietPlay) {
7270 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7272 XtSetArg(args[0], XtNleftBitmap, None);
7274 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7278 void ShowCoordsProc(w, event, prms, nprms)
7286 appData.showCoords = !appData.showCoords;
7288 if (appData.showCoords) {
7289 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7291 XtSetArg(args[0], XtNleftBitmap, None);
7293 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7296 DrawPosition(True, NULL);
7299 void ShowThinkingProc(w, event, prms, nprms)
7307 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7308 ShowThinkingEvent();
7311 void HideThinkingProc(w, event, prms, nprms)
7319 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7320 ShowThinkingEvent();
7322 if (appData.hideThinkingFromHuman) {
7323 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7325 XtSetArg(args[0], XtNleftBitmap, None);
7327 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7331 void InfoProc(w, event, prms, nprms)
7338 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7343 void ManProc(w, event, prms, nprms)
7351 if (nprms && *nprms > 0)
7355 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7359 void HintProc(w, event, prms, nprms)
7368 void BookProc(w, event, prms, nprms)
7377 void AboutProc(w, event, prms, nprms)
7385 char *zippy = " (with Zippy code)";
7389 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7390 programVersion, zippy,
7391 "Copyright 1991 Digital Equipment Corporation",
7392 "Enhancements Copyright 1992-2009 Free Software Foundation",
7393 "Enhancements Copyright 2005 Alessandro Scotti",
7394 PACKAGE, " is free software and carries NO WARRANTY;",
7395 "see the file COPYING for more information.");
7396 ErrorPopUp(_("About XBoard"), buf, FALSE);
7399 void DebugProc(w, event, prms, nprms)
7405 appData.debugMode = !appData.debugMode;
7408 void AboutGameProc(w, event, prms, nprms)
7417 void NothingProc(w, event, prms, nprms)
7426 void Iconify(w, event, prms, nprms)
7435 XtSetArg(args[0], XtNiconic, True);
7436 XtSetValues(shellWidget, args, 1);
7439 void DisplayMessage(message, extMessage)
7440 char *message, *extMessage;
7442 /* display a message in the message widget */
7451 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7456 message = extMessage;
7460 /* need to test if messageWidget already exists, since this function
7461 can also be called during the startup, if for example a Xresource
7462 is not set up correctly */
7465 XtSetArg(arg, XtNlabel, message);
7466 XtSetValues(messageWidget, &arg, 1);
7472 void DisplayTitle(text)
7477 char title[MSG_SIZ];
7480 if (text == NULL) text = "";
7482 if (appData.titleInWindow) {
7484 XtSetArg(args[i], XtNlabel, text); i++;
7485 XtSetValues(titleWidget, args, i);
7488 if (*text != NULLCHAR) {
7490 strcpy(title, text);
7491 } else if (appData.icsActive) {
7492 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7493 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7494 } else if (appData.cmailGameName[0] != NULLCHAR) {
7495 snprintf(icon, sizeof(icon), "%s", "CMail");
7496 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7498 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7499 } else if (gameInfo.variant == VariantGothic) {
7500 strcpy(icon, programName);
7501 strcpy(title, GOTHIC);
7504 } else if (gameInfo.variant == VariantFalcon) {
7505 strcpy(icon, programName);
7506 strcpy(title, FALCON);
7508 } else if (appData.noChessProgram) {
7509 strcpy(icon, programName);
7510 strcpy(title, programName);
7512 strcpy(icon, first.tidy);
7513 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7516 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7517 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7518 XtSetValues(shellWidget, args, i);
7522 void DisplayError(message, error)
7529 if (appData.debugMode || appData.matchMode) {
7530 fprintf(stderr, "%s: %s\n", programName, message);
7533 if (appData.debugMode || appData.matchMode) {
7534 fprintf(stderr, "%s: %s: %s\n",
7535 programName, message, strerror(error));
7537 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7540 ErrorPopUp(_("Error"), message, FALSE);
7544 void DisplayMoveError(message)
7549 DrawPosition(FALSE, NULL);
7550 if (appData.debugMode || appData.matchMode) {
7551 fprintf(stderr, "%s: %s\n", programName, message);
7553 if (appData.popupMoveErrors) {
7554 ErrorPopUp(_("Error"), message, FALSE);
7556 DisplayMessage(message, "");
7561 void DisplayFatalError(message, error, status)
7567 errorExitStatus = status;
7569 fprintf(stderr, "%s: %s\n", programName, message);
7571 fprintf(stderr, "%s: %s: %s\n",
7572 programName, message, strerror(error));
7573 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7576 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7577 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7583 void DisplayInformation(message)
7587 ErrorPopUp(_("Information"), message, TRUE);
7590 void DisplayNote(message)
7594 ErrorPopUp(_("Note"), message, FALSE);
7598 NullXErrorCheck(dpy, error_event)
7600 XErrorEvent *error_event;
7605 void DisplayIcsInteractionTitle(message)
7608 if (oldICSInteractionTitle == NULL) {
7609 /* Magic to find the old window title, adapted from vim */
7610 char *wina = getenv("WINDOWID");
7612 Window win = (Window) atoi(wina);
7613 Window root, parent, *children;
7614 unsigned int nchildren;
7615 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7617 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7618 if (!XQueryTree(xDisplay, win, &root, &parent,
7619 &children, &nchildren)) break;
7620 if (children) XFree((void *)children);
7621 if (parent == root || parent == 0) break;
7624 XSetErrorHandler(oldHandler);
7626 if (oldICSInteractionTitle == NULL) {
7627 oldICSInteractionTitle = "xterm";
7630 printf("\033]0;%s\007", message);
7634 char pendingReplyPrefix[MSG_SIZ];
7635 ProcRef pendingReplyPR;
7637 void AskQuestionProc(w, event, prms, nprms)
7644 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7648 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7651 void AskQuestionPopDown()
7653 if (!askQuestionUp) return;
7654 XtPopdown(askQuestionShell);
7655 XtDestroyWidget(askQuestionShell);
7656 askQuestionUp = False;
7659 void AskQuestionReplyAction(w, event, prms, nprms)
7669 reply = XawDialogGetValueString(w = XtParent(w));
7670 strcpy(buf, pendingReplyPrefix);
7671 if (*buf) strcat(buf, " ");
7674 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7675 AskQuestionPopDown();
7677 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7680 void AskQuestionCallback(w, client_data, call_data)
7682 XtPointer client_data, call_data;
7687 XtSetArg(args[0], XtNlabel, &name);
7688 XtGetValues(w, args, 1);
7690 if (strcmp(name, _("cancel")) == 0) {
7691 AskQuestionPopDown();
7693 AskQuestionReplyAction(w, NULL, NULL, NULL);
7697 void AskQuestion(title, question, replyPrefix, pr)
7698 char *title, *question, *replyPrefix;
7702 Widget popup, layout, dialog, edit;
7708 strcpy(pendingReplyPrefix, replyPrefix);
7709 pendingReplyPR = pr;
7712 XtSetArg(args[i], XtNresizable, True); i++;
7713 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7714 askQuestionShell = popup =
7715 XtCreatePopupShell(title, transientShellWidgetClass,
7716 shellWidget, args, i);
7719 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7720 layoutArgs, XtNumber(layoutArgs));
7723 XtSetArg(args[i], XtNlabel, question); i++;
7724 XtSetArg(args[i], XtNvalue, ""); i++;
7725 XtSetArg(args[i], XtNborderWidth, 0); i++;
7726 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7729 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7730 (XtPointer) dialog);
7731 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7732 (XtPointer) dialog);
7734 XtRealizeWidget(popup);
7735 CatchDeleteWindow(popup, "AskQuestionPopDown");
7737 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7738 &x, &y, &win_x, &win_y, &mask);
7740 XtSetArg(args[0], XtNx, x - 10);
7741 XtSetArg(args[1], XtNy, y - 30);
7742 XtSetValues(popup, args, 2);
7744 XtPopup(popup, XtGrabExclusive);
7745 askQuestionUp = True;
7747 edit = XtNameToWidget(dialog, "*value");
7748 XtSetKeyboardFocus(popup, edit);
7756 if (*name == NULLCHAR) {
7758 } else if (strcmp(name, "$") == 0) {
7759 putc(BELLCHAR, stderr);
7762 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7770 PlaySound(appData.soundMove);
7776 PlaySound(appData.soundIcsWin);
7782 PlaySound(appData.soundIcsLoss);
7788 PlaySound(appData.soundIcsDraw);
7792 PlayIcsUnfinishedSound()
7794 PlaySound(appData.soundIcsUnfinished);
7800 PlaySound(appData.soundIcsAlarm);
7806 system("stty echo");
7812 system("stty -echo");
7816 Colorize(cc, continuation)
7821 int count, outCount, error;
7823 if (textColors[(int)cc].bg > 0) {
7824 if (textColors[(int)cc].fg > 0) {
7825 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7826 textColors[(int)cc].fg, textColors[(int)cc].bg);
7828 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7829 textColors[(int)cc].bg);
7832 if (textColors[(int)cc].fg > 0) {
7833 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7834 textColors[(int)cc].fg);
7836 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7839 count = strlen(buf);
7840 outCount = OutputToProcess(NoProc, buf, count, &error);
7841 if (outCount < count) {
7842 DisplayFatalError(_("Error writing to display"), error, 1);
7845 if (continuation) return;
7848 PlaySound(appData.soundShout);
7851 PlaySound(appData.soundSShout);
7854 PlaySound(appData.soundChannel1);
7857 PlaySound(appData.soundChannel);
7860 PlaySound(appData.soundKibitz);
7863 PlaySound(appData.soundTell);
7865 case ColorChallenge:
7866 PlaySound(appData.soundChallenge);
7869 PlaySound(appData.soundRequest);
7872 PlaySound(appData.soundSeek);
7883 return getpwuid(getuid())->pw_name;
7886 static char *ExpandPathName(path)
7889 static char static_buf[2000];
7890 char *d, *s, buf[2000];
7896 while (*s && isspace(*s))
7905 if (*(s+1) == '/') {
7906 strcpy(d, getpwuid(getuid())->pw_dir);
7911 *strchr(buf, '/') = 0;
7912 pwd = getpwnam(buf);
7915 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7919 strcpy(d, pwd->pw_dir);
7920 strcat(d, strchr(s+1, '/'));
7931 static char host_name[MSG_SIZ];
7933 #if HAVE_GETHOSTNAME
7934 gethostname(host_name, MSG_SIZ);
7936 #else /* not HAVE_GETHOSTNAME */
7937 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7938 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7940 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7942 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7943 #endif /* not HAVE_GETHOSTNAME */
7946 XtIntervalId delayedEventTimerXID = 0;
7947 DelayedEventCallback delayedEventCallback = 0;
7952 delayedEventTimerXID = 0;
7953 delayedEventCallback();
7957 ScheduleDelayedEvent(cb, millisec)
7958 DelayedEventCallback cb; long millisec;
7960 if(delayedEventTimerXID && delayedEventCallback == cb)
7961 // [HGM] alive: replace, rather than add or flush identical event
7962 XtRemoveTimeOut(delayedEventTimerXID);
7963 delayedEventCallback = cb;
7964 delayedEventTimerXID =
7965 XtAppAddTimeOut(appContext, millisec,
7966 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7969 DelayedEventCallback
7972 if (delayedEventTimerXID) {
7973 return delayedEventCallback;
7980 CancelDelayedEvent()
7982 if (delayedEventTimerXID) {
7983 XtRemoveTimeOut(delayedEventTimerXID);
7984 delayedEventTimerXID = 0;
7988 XtIntervalId loadGameTimerXID = 0;
7990 int LoadGameTimerRunning()
7992 return loadGameTimerXID != 0;
7995 int StopLoadGameTimer()
7997 if (loadGameTimerXID != 0) {
7998 XtRemoveTimeOut(loadGameTimerXID);
7999 loadGameTimerXID = 0;
8007 LoadGameTimerCallback(arg, id)
8011 loadGameTimerXID = 0;
8016 StartLoadGameTimer(millisec)
8020 XtAppAddTimeOut(appContext, millisec,
8021 (XtTimerCallbackProc) LoadGameTimerCallback,
8025 XtIntervalId analysisClockXID = 0;
8028 AnalysisClockCallback(arg, id)
8032 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8033 || appData.icsEngineAnalyze) { // [DM]
8034 AnalysisPeriodicEvent(0);
8035 StartAnalysisClock();
8040 StartAnalysisClock()
8043 XtAppAddTimeOut(appContext, 2000,
8044 (XtTimerCallbackProc) AnalysisClockCallback,
8048 XtIntervalId clockTimerXID = 0;
8050 int ClockTimerRunning()
8052 return clockTimerXID != 0;
8055 int StopClockTimer()
8057 if (clockTimerXID != 0) {
8058 XtRemoveTimeOut(clockTimerXID);
8067 ClockTimerCallback(arg, id)
8076 StartClockTimer(millisec)
8080 XtAppAddTimeOut(appContext, millisec,
8081 (XtTimerCallbackProc) ClockTimerCallback,
8086 DisplayTimerLabel(w, color, timer, highlight)
8095 /* check for low time warning */
8096 Pixel foregroundOrWarningColor = timerForegroundPixel;
8099 appData.lowTimeWarning &&
8100 (timer / 1000) < appData.icsAlarmTime)
8101 foregroundOrWarningColor = lowTimeWarningColor;
8103 if (appData.clockMode) {
8104 sprintf(buf, "%s: %s", color, TimeString(timer));
8105 XtSetArg(args[0], XtNlabel, buf);
8107 sprintf(buf, "%s ", color);
8108 XtSetArg(args[0], XtNlabel, buf);
8113 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8114 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8116 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8117 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8120 XtSetValues(w, args, 3);
8124 DisplayWhiteClock(timeRemaining, highlight)
8130 if(appData.noGUI) return;
8131 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8132 if (highlight && iconPixmap == bIconPixmap) {
8133 iconPixmap = wIconPixmap;
8134 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8135 XtSetValues(shellWidget, args, 1);
8140 DisplayBlackClock(timeRemaining, highlight)
8146 if(appData.noGUI) return;
8147 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8148 if (highlight && iconPixmap == wIconPixmap) {
8149 iconPixmap = bIconPixmap;
8150 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8151 XtSetValues(shellWidget, args, 1);
8169 int StartChildProcess(cmdLine, dir, pr)
8176 int to_prog[2], from_prog[2];
8180 if (appData.debugMode) {
8181 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8184 /* We do NOT feed the cmdLine to the shell; we just
8185 parse it into blank-separated arguments in the
8186 most simple-minded way possible.
8189 strcpy(buf, cmdLine);
8194 if (p == NULL) break;
8199 SetUpChildIO(to_prog, from_prog);
8201 if ((pid = fork()) == 0) {
8203 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8204 close(to_prog[1]); // first close the unused pipe ends
8205 close(from_prog[0]);
8206 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8207 dup2(from_prog[1], 1);
8208 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8209 close(from_prog[1]); // and closing again loses one of the pipes!
8210 if(fileno(stderr) >= 2) // better safe than sorry...
8211 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8213 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8218 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8220 execvp(argv[0], argv);
8222 /* If we get here, exec failed */
8227 /* Parent process */
8229 close(from_prog[1]);
8231 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8234 cp->fdFrom = from_prog[0];
8235 cp->fdTo = to_prog[1];
8240 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8241 static RETSIGTYPE AlarmCallBack(int n)
8247 DestroyChildProcess(pr, signalType)
8251 ChildProc *cp = (ChildProc *) pr;
8253 if (cp->kind != CPReal) return;
8255 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8256 signal(SIGALRM, AlarmCallBack);
8258 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8259 kill(cp->pid, SIGKILL); // kill it forcefully
8260 wait((int *) 0); // and wait again
8264 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8266 /* Process is exiting either because of the kill or because of
8267 a quit command sent by the backend; either way, wait for it to die.
8276 InterruptChildProcess(pr)
8279 ChildProc *cp = (ChildProc *) pr;
8281 if (cp->kind != CPReal) return;
8282 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8285 int OpenTelnet(host, port, pr)
8290 char cmdLine[MSG_SIZ];
8292 if (port[0] == NULLCHAR) {
8293 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8295 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8297 return StartChildProcess(cmdLine, "", pr);
8300 int OpenTCP(host, port, pr)
8306 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8307 #else /* !OMIT_SOCKETS */
8309 struct sockaddr_in sa;
8311 unsigned short uport;
8314 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8318 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8319 sa.sin_family = AF_INET;
8320 sa.sin_addr.s_addr = INADDR_ANY;
8321 uport = (unsigned short) 0;
8322 sa.sin_port = htons(uport);
8323 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8327 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8328 if (!(hp = gethostbyname(host))) {
8330 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8331 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8332 hp->h_addrtype = AF_INET;
8334 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8335 hp->h_addr_list[0] = (char *) malloc(4);
8336 hp->h_addr_list[0][0] = b0;
8337 hp->h_addr_list[0][1] = b1;
8338 hp->h_addr_list[0][2] = b2;
8339 hp->h_addr_list[0][3] = b3;
8344 sa.sin_family = hp->h_addrtype;
8345 uport = (unsigned short) atoi(port);
8346 sa.sin_port = htons(uport);
8347 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8349 if (connect(s, (struct sockaddr *) &sa,
8350 sizeof(struct sockaddr_in)) < 0) {
8354 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8361 #endif /* !OMIT_SOCKETS */
8366 int OpenCommPort(name, pr)
8373 fd = open(name, 2, 0);
8374 if (fd < 0) return errno;
8376 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8386 int OpenLoopback(pr)
8392 SetUpChildIO(to, from);
8394 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8397 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8404 int OpenRcmd(host, user, cmd, pr)
8405 char *host, *user, *cmd;
8408 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8412 #define INPUT_SOURCE_BUF_SIZE 8192
8421 char buf[INPUT_SOURCE_BUF_SIZE];
8426 DoInputCallback(closure, source, xid)
8431 InputSource *is = (InputSource *) closure;
8436 if (is->lineByLine) {
8437 count = read(is->fd, is->unused,
8438 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8440 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8443 is->unused += count;
8445 while (p < is->unused) {
8446 q = memchr(p, '\n', is->unused - p);
8447 if (q == NULL) break;
8449 (is->func)(is, is->closure, p, q - p, 0);
8453 while (p < is->unused) {
8458 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8463 (is->func)(is, is->closure, is->buf, count, error);
8467 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8474 ChildProc *cp = (ChildProc *) pr;
8476 is = (InputSource *) calloc(1, sizeof(InputSource));
8477 is->lineByLine = lineByLine;
8481 is->fd = fileno(stdin);
8483 is->kind = cp->kind;
8484 is->fd = cp->fdFrom;
8487 is->unused = is->buf;
8490 is->xid = XtAppAddInput(appContext, is->fd,
8491 (XtPointer) (XtInputReadMask),
8492 (XtInputCallbackProc) DoInputCallback,
8494 is->closure = closure;
8495 return (InputSourceRef) is;
8499 RemoveInputSource(isr)
8502 InputSource *is = (InputSource *) isr;
8504 if (is->xid == 0) return;
8505 XtRemoveInput(is->xid);
8509 int OutputToProcess(pr, message, count, outError)
8515 static int line = 0;
8516 ChildProc *cp = (ChildProc *) pr;
8521 if (appData.noJoin || !appData.useInternalWrap)
8522 outCount = fwrite(message, 1, count, stdout);
8525 int width = get_term_width();
8526 int len = wrap(NULL, message, count, width, &line);
8527 char *msg = malloc(len);
8531 outCount = fwrite(message, 1, count, stdout);
8534 dbgchk = wrap(msg, message, count, width, &line);
8535 if (dbgchk != len && appData.debugMode)
8536 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
8537 outCount = fwrite(msg, 1, dbgchk, stdout);
8543 outCount = write(cp->fdTo, message, count);
8553 /* Output message to process, with "ms" milliseconds of delay
8554 between each character. This is needed when sending the logon
8555 script to ICC, which for some reason doesn't like the
8556 instantaneous send. */
8557 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8564 ChildProc *cp = (ChildProc *) pr;
8569 r = write(cp->fdTo, message++, 1);
8582 /**** Animation code by Hugh Fisher, DCS, ANU.
8584 Known problem: if a window overlapping the board is
8585 moved away while a piece is being animated underneath,
8586 the newly exposed area won't be updated properly.
8587 I can live with this.
8589 Known problem: if you look carefully at the animation
8590 of pieces in mono mode, they are being drawn as solid
8591 shapes without interior detail while moving. Fixing
8592 this would be a major complication for minimal return.
8595 /* Masks for XPM pieces. Black and white pieces can have
8596 different shapes, but in the interest of retaining my
8597 sanity pieces must have the same outline on both light
8598 and dark squares, and all pieces must use the same
8599 background square colors/images. */
8601 static int xpmDone = 0;
8604 CreateAnimMasks (pieceDepth)
8611 unsigned long plane;
8614 /* Need a bitmap just to get a GC with right depth */
8615 buf = XCreatePixmap(xDisplay, xBoardWindow,
8617 values.foreground = 1;
8618 values.background = 0;
8619 /* Don't use XtGetGC, not read only */
8620 maskGC = XCreateGC(xDisplay, buf,
8621 GCForeground | GCBackground, &values);
8622 XFreePixmap(xDisplay, buf);
8624 buf = XCreatePixmap(xDisplay, xBoardWindow,
8625 squareSize, squareSize, pieceDepth);
8626 values.foreground = XBlackPixel(xDisplay, xScreen);
8627 values.background = XWhitePixel(xDisplay, xScreen);
8628 bufGC = XCreateGC(xDisplay, buf,
8629 GCForeground | GCBackground, &values);
8631 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8632 /* Begin with empty mask */
8633 if(!xpmDone) // [HGM] pieces: keep using existing
8634 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8635 squareSize, squareSize, 1);
8636 XSetFunction(xDisplay, maskGC, GXclear);
8637 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8638 0, 0, squareSize, squareSize);
8640 /* Take a copy of the piece */
8645 XSetFunction(xDisplay, bufGC, GXcopy);
8646 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8648 0, 0, squareSize, squareSize, 0, 0);
8650 /* XOR the background (light) over the piece */
8651 XSetFunction(xDisplay, bufGC, GXxor);
8653 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8654 0, 0, squareSize, squareSize, 0, 0);
8656 XSetForeground(xDisplay, bufGC, lightSquareColor);
8657 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8660 /* We now have an inverted piece image with the background
8661 erased. Construct mask by just selecting all the non-zero
8662 pixels - no need to reconstruct the original image. */
8663 XSetFunction(xDisplay, maskGC, GXor);
8665 /* Might be quicker to download an XImage and create bitmap
8666 data from it rather than this N copies per piece, but it
8667 only takes a fraction of a second and there is a much
8668 longer delay for loading the pieces. */
8669 for (n = 0; n < pieceDepth; n ++) {
8670 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8671 0, 0, squareSize, squareSize,
8677 XFreePixmap(xDisplay, buf);
8678 XFreeGC(xDisplay, bufGC);
8679 XFreeGC(xDisplay, maskGC);
8683 InitAnimState (anim, info)
8685 XWindowAttributes * info;
8690 /* Each buffer is square size, same depth as window */
8691 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8692 squareSize, squareSize, info->depth);
8693 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8694 squareSize, squareSize, info->depth);
8696 /* Create a plain GC for blitting */
8697 mask = GCForeground | GCBackground | GCFunction |
8698 GCPlaneMask | GCGraphicsExposures;
8699 values.foreground = XBlackPixel(xDisplay, xScreen);
8700 values.background = XWhitePixel(xDisplay, xScreen);
8701 values.function = GXcopy;
8702 values.plane_mask = AllPlanes;
8703 values.graphics_exposures = False;
8704 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8706 /* Piece will be copied from an existing context at
8707 the start of each new animation/drag. */
8708 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8710 /* Outline will be a read-only copy of an existing */
8711 anim->outlineGC = None;
8717 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8718 XWindowAttributes info;
8720 if (xpmDone && gameInfo.variant == old) return;
8721 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8722 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8724 InitAnimState(&game, &info);
8725 InitAnimState(&player, &info);
8727 /* For XPM pieces, we need bitmaps to use as masks. */
8729 CreateAnimMasks(info.depth);
8735 static Boolean frameWaiting;
8737 static RETSIGTYPE FrameAlarm (sig)
8740 frameWaiting = False;
8741 /* In case System-V style signals. Needed?? */
8742 signal(SIGALRM, FrameAlarm);
8749 struct itimerval delay;
8751 XSync(xDisplay, False);
8754 frameWaiting = True;
8755 signal(SIGALRM, FrameAlarm);
8756 delay.it_interval.tv_sec =
8757 delay.it_value.tv_sec = time / 1000;
8758 delay.it_interval.tv_usec =
8759 delay.it_value.tv_usec = (time % 1000) * 1000;
8760 setitimer(ITIMER_REAL, &delay, NULL);
8761 while (frameWaiting) pause();
8762 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8763 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8764 setitimer(ITIMER_REAL, &delay, NULL);
8774 XSync(xDisplay, False);
8776 usleep(time * 1000);
8781 /* Convert board position to corner of screen rect and color */
8784 ScreenSquare(column, row, pt, color)
8785 int column; int row; XPoint * pt; int * color;
8788 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8789 pt->y = lineGap + row * (squareSize + lineGap);
8791 pt->x = lineGap + column * (squareSize + lineGap);
8792 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8794 *color = SquareColor(row, column);
8797 /* Convert window coords to square */
8800 BoardSquare(x, y, column, row)
8801 int x; int y; int * column; int * row;
8803 *column = EventToSquare(x, BOARD_WIDTH);
8804 if (flipView && *column >= 0)
8805 *column = BOARD_WIDTH - 1 - *column;
8806 *row = EventToSquare(y, BOARD_HEIGHT);
8807 if (!flipView && *row >= 0)
8808 *row = BOARD_HEIGHT - 1 - *row;
8813 #undef Max /* just in case */
8815 #define Max(a, b) ((a) > (b) ? (a) : (b))
8816 #define Min(a, b) ((a) < (b) ? (a) : (b))
8819 SetRect(rect, x, y, width, height)
8820 XRectangle * rect; int x; int y; int width; int height;
8824 rect->width = width;
8825 rect->height = height;
8828 /* Test if two frames overlap. If they do, return
8829 intersection rect within old and location of
8830 that rect within new. */
8833 Intersect(old, new, size, area, pt)
8834 XPoint * old; XPoint * new;
8835 int size; XRectangle * area; XPoint * pt;
8837 if (old->x > new->x + size || new->x > old->x + size ||
8838 old->y > new->y + size || new->y > old->y + size) {
8841 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8842 size - abs(old->x - new->x), size - abs(old->y - new->y));
8843 pt->x = Max(old->x - new->x, 0);
8844 pt->y = Max(old->y - new->y, 0);
8849 /* For two overlapping frames, return the rect(s)
8850 in the old that do not intersect with the new. */
8853 CalcUpdateRects(old, new, size, update, nUpdates)
8854 XPoint * old; XPoint * new; int size;
8855 XRectangle update[]; int * nUpdates;
8859 /* If old = new (shouldn't happen) then nothing to draw */
8860 if (old->x == new->x && old->y == new->y) {
8864 /* Work out what bits overlap. Since we know the rects
8865 are the same size we don't need a full intersect calc. */
8867 /* Top or bottom edge? */
8868 if (new->y > old->y) {
8869 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8871 } else if (old->y > new->y) {
8872 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8873 size, old->y - new->y);
8876 /* Left or right edge - don't overlap any update calculated above. */
8877 if (new->x > old->x) {
8878 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8879 new->x - old->x, size - abs(new->y - old->y));
8881 } else if (old->x > new->x) {
8882 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8883 old->x - new->x, size - abs(new->y - old->y));
8890 /* Generate a series of frame coords from start->mid->finish.
8891 The movement rate doubles until the half way point is
8892 reached, then halves back down to the final destination,
8893 which gives a nice slow in/out effect. The algorithmn
8894 may seem to generate too many intermediates for short
8895 moves, but remember that the purpose is to attract the
8896 viewers attention to the piece about to be moved and
8897 then to where it ends up. Too few frames would be less
8901 Tween(start, mid, finish, factor, frames, nFrames)
8902 XPoint * start; XPoint * mid;
8903 XPoint * finish; int factor;
8904 XPoint frames[]; int * nFrames;
8906 int fraction, n, count;
8910 /* Slow in, stepping 1/16th, then 1/8th, ... */
8912 for (n = 0; n < factor; n++)
8914 for (n = 0; n < factor; n++) {
8915 frames[count].x = start->x + (mid->x - start->x) / fraction;
8916 frames[count].y = start->y + (mid->y - start->y) / fraction;
8918 fraction = fraction / 2;
8922 frames[count] = *mid;
8925 /* Slow out, stepping 1/2, then 1/4, ... */
8927 for (n = 0; n < factor; n++) {
8928 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8929 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8931 fraction = fraction * 2;
8936 /* Draw a piece on the screen without disturbing what's there */
8939 SelectGCMask(piece, clip, outline, mask)
8940 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8944 /* Bitmap for piece being moved. */
8945 if (appData.monoMode) {
8946 *mask = *pieceToSolid(piece);
8947 } else if (useImages) {
8949 *mask = xpmMask[piece];
8951 *mask = ximMaskPm[piece];
8954 *mask = *pieceToSolid(piece);
8957 /* GC for piece being moved. Square color doesn't matter, but
8958 since it gets modified we make a copy of the original. */
8960 if (appData.monoMode)
8965 if (appData.monoMode)
8970 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8972 /* Outline only used in mono mode and is not modified */
8974 *outline = bwPieceGC;
8976 *outline = wbPieceGC;
8980 OverlayPiece(piece, clip, outline, dest)
8981 ChessSquare piece; GC clip; GC outline; Drawable dest;
8986 /* Draw solid rectangle which will be clipped to shape of piece */
8987 XFillRectangle(xDisplay, dest, clip,
8988 0, 0, squareSize, squareSize);
8989 if (appData.monoMode)
8990 /* Also draw outline in contrasting color for black
8991 on black / white on white cases */
8992 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8993 0, 0, squareSize, squareSize, 0, 0, 1);
8995 /* Copy the piece */
9000 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9002 0, 0, squareSize, squareSize,
9007 /* Animate the movement of a single piece */
9010 BeginAnimation(anim, piece, startColor, start)
9018 /* The old buffer is initialised with the start square (empty) */
9019 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9020 anim->prevFrame = *start;
9022 /* The piece will be drawn using its own bitmap as a matte */
9023 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9024 XSetClipMask(xDisplay, anim->pieceGC, mask);
9028 AnimationFrame(anim, frame, piece)
9033 XRectangle updates[4];
9038 /* Save what we are about to draw into the new buffer */
9039 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9040 frame->x, frame->y, squareSize, squareSize,
9043 /* Erase bits of the previous frame */
9044 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9045 /* Where the new frame overlapped the previous,
9046 the contents in newBuf are wrong. */
9047 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9048 overlap.x, overlap.y,
9049 overlap.width, overlap.height,
9051 /* Repaint the areas in the old that don't overlap new */
9052 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9053 for (i = 0; i < count; i++)
9054 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9055 updates[i].x - anim->prevFrame.x,
9056 updates[i].y - anim->prevFrame.y,
9057 updates[i].width, updates[i].height,
9058 updates[i].x, updates[i].y);
9060 /* Easy when no overlap */
9061 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9062 0, 0, squareSize, squareSize,
9063 anim->prevFrame.x, anim->prevFrame.y);
9066 /* Save this frame for next time round */
9067 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9068 0, 0, squareSize, squareSize,
9070 anim->prevFrame = *frame;
9072 /* Draw piece over original screen contents, not current,
9073 and copy entire rect. Wipes out overlapping piece images. */
9074 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9075 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9076 0, 0, squareSize, squareSize,
9077 frame->x, frame->y);
9081 EndAnimation (anim, finish)
9085 XRectangle updates[4];
9090 /* The main code will redraw the final square, so we
9091 only need to erase the bits that don't overlap. */
9092 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9093 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9094 for (i = 0; i < count; i++)
9095 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9096 updates[i].x - anim->prevFrame.x,
9097 updates[i].y - anim->prevFrame.y,
9098 updates[i].width, updates[i].height,
9099 updates[i].x, updates[i].y);
9101 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9102 0, 0, squareSize, squareSize,
9103 anim->prevFrame.x, anim->prevFrame.y);
9108 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9110 ChessSquare piece; int startColor;
9111 XPoint * start; XPoint * finish;
9112 XPoint frames[]; int nFrames;
9116 BeginAnimation(anim, piece, startColor, start);
9117 for (n = 0; n < nFrames; n++) {
9118 AnimationFrame(anim, &(frames[n]), piece);
9119 FrameDelay(appData.animSpeed);
9121 EndAnimation(anim, finish);
9124 /* Main control logic for deciding what to animate and how */
9127 AnimateMove(board, fromX, fromY, toX, toY)
9136 XPoint start, finish, mid;
9137 XPoint frames[kFactor * 2 + 1];
9138 int nFrames, startColor, endColor;
9140 /* Are we animating? */
9141 if (!appData.animate || appData.blindfold)
9144 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9145 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9146 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9148 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9149 piece = board[fromY][fromX];
9150 if (piece >= EmptySquare) return;
9155 hop = (piece == WhiteKnight || piece == BlackKnight);
9158 if (appData.debugMode) {
9159 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9160 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9161 piece, fromX, fromY, toX, toY); }
9163 ScreenSquare(fromX, fromY, &start, &startColor);
9164 ScreenSquare(toX, toY, &finish, &endColor);
9167 /* Knight: make diagonal movement then straight */
9168 if (abs(toY - fromY) < abs(toX - fromX)) {
9169 mid.x = start.x + (finish.x - start.x) / 2;
9173 mid.y = start.y + (finish.y - start.y) / 2;
9176 mid.x = start.x + (finish.x - start.x) / 2;
9177 mid.y = start.y + (finish.y - start.y) / 2;
9180 /* Don't use as many frames for very short moves */
9181 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9182 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9184 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9185 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9187 /* Be sure end square is redrawn */
9188 damage[toY][toX] = True;
9192 DragPieceBegin(x, y)
9195 int boardX, boardY, color;
9198 /* Are we animating? */
9199 if (!appData.animateDragging || appData.blindfold)
9202 /* Figure out which square we start in and the
9203 mouse position relative to top left corner. */
9204 BoardSquare(x, y, &boardX, &boardY);
9205 player.startBoardX = boardX;
9206 player.startBoardY = boardY;
9207 ScreenSquare(boardX, boardY, &corner, &color);
9208 player.startSquare = corner;
9209 player.startColor = color;
9210 /* As soon as we start dragging, the piece will jump slightly to
9211 be centered over the mouse pointer. */
9212 player.mouseDelta.x = squareSize/2;
9213 player.mouseDelta.y = squareSize/2;
9214 /* Initialise animation */
9215 player.dragPiece = PieceForSquare(boardX, boardY);
9217 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9218 player.dragActive = True;
9219 BeginAnimation(&player, player.dragPiece, color, &corner);
9220 /* Mark this square as needing to be redrawn. Note that
9221 we don't remove the piece though, since logically (ie
9222 as seen by opponent) the move hasn't been made yet. */
9223 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9224 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9225 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9226 corner.x, corner.y, squareSize, squareSize,
9227 0, 0); // [HGM] zh: unstack in stead of grab
9228 damage[boardY][boardX] = True;
9230 player.dragActive = False;
9240 /* Are we animating? */
9241 if (!appData.animateDragging || appData.blindfold)
9245 if (! player.dragActive)
9247 /* Move piece, maintaining same relative position
9248 of mouse within square */
9249 corner.x = x - player.mouseDelta.x;
9250 corner.y = y - player.mouseDelta.y;
9251 AnimationFrame(&player, &corner, player.dragPiece);
9253 if (appData.highlightDragging) {
9255 BoardSquare(x, y, &boardX, &boardY);
9256 SetHighlights(fromX, fromY, boardX, boardY);
9265 int boardX, boardY, color;
9268 /* Are we animating? */
9269 if (!appData.animateDragging || appData.blindfold)
9273 if (! player.dragActive)
9275 /* Last frame in sequence is square piece is
9276 placed on, which may not match mouse exactly. */
9277 BoardSquare(x, y, &boardX, &boardY);
9278 ScreenSquare(boardX, boardY, &corner, &color);
9279 EndAnimation(&player, &corner);
9281 /* Be sure end square is redrawn */
9282 damage[boardY][boardX] = True;
9284 /* This prevents weird things happening with fast successive
9285 clicks which on my Sun at least can cause motion events
9286 without corresponding press/release. */
9287 player.dragActive = False;
9290 /* Handle expose event while piece being dragged */
9295 if (!player.dragActive || appData.blindfold)
9298 /* What we're doing: logically, the move hasn't been made yet,
9299 so the piece is still in it's original square. But visually
9300 it's being dragged around the board. So we erase the square
9301 that the piece is on and draw it at the last known drag point. */
9302 BlankSquare(player.startSquare.x, player.startSquare.y,
9303 player.startColor, EmptySquare, xBoardWindow);
9304 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9305 damage[player.startBoardY][player.startBoardX] = TRUE;
9309 SetProgramStats( FrontEndProgramStats * stats )
9312 // [HGM] done, but perhaps backend should call this directly?
9313 EngineOutputUpdate( stats );
9316 #include <sys/ioctl.h>
9317 int get_term_width()
9319 int fd, default_width;
9322 default_width = 79; // this is FICS default anyway...
9324 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9326 if (!ioctl(fd, TIOCGSIZE, &win))
9327 default_width = win.ts_cols;
9328 #elif defined(TIOCGWINSZ)
9330 if (!ioctl(fd, TIOCGWINSZ, &win))
9331 default_width = win.ws_col;
9333 return default_width;
9336 void update_ics_width()
9338 static int old_width = 0;
9339 int new_width = get_term_width();
9341 if (old_width != new_width)
9342 ics_printf("set width %d\n", new_width);
9343 old_width = new_width;
9346 void NotifyFrontendLogin()