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();
3196 signal(SIGINT, IntSigHandler);
3197 signal(SIGTERM, IntSigHandler);
3198 if (*appData.cmailGameName != NULLCHAR) {
3199 signal(SIGUSR1, CmailSigHandler);
3202 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3205 XtAppMainLoop(appContext);
3206 if (appData.debugMode) fclose(debugFP); // [DM] debug
3213 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3214 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3216 unlink(gameCopyFilename);
3217 unlink(gamePasteFilename);
3220 RETSIGTYPE TermSizeSigHandler(int sig)
3233 CmailSigHandler(sig)
3239 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3241 /* Activate call-back function CmailSigHandlerCallBack() */
3242 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3244 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3248 CmailSigHandlerCallBack(isr, closure, message, count, error)
3256 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3258 /**** end signal code ****/
3268 f = fopen(appData.icsLogon, "r");
3274 strcat(buf, appData.icsLogon);
3275 f = fopen(buf, "r");
3279 ProcessICSInitScript(f);
3286 EditCommentPopDown();
3297 SetMenuEnables(enab)
3301 if (!menuBarWidget) return;
3302 while (enab->name != NULL) {
3303 w = XtNameToWidget(menuBarWidget, enab->name);
3305 DisplayError(enab->name, 0);
3307 XtSetSensitive(w, enab->value);
3313 Enables icsEnables[] = {
3314 { "menuFile.Mail Move", False },
3315 { "menuFile.Reload CMail Message", False },
3316 { "menuMode.Machine Black", False },
3317 { "menuMode.Machine White", False },
3318 { "menuMode.Analysis Mode", False },
3319 { "menuMode.Analyze File", False },
3320 { "menuMode.Two Machines", False },
3322 { "menuHelp.Hint", False },
3323 { "menuHelp.Book", False },
3324 { "menuStep.Move Now", False },
3325 { "menuOptions.Periodic Updates", False },
3326 { "menuOptions.Hide Thinking", False },
3327 { "menuOptions.Ponder Next Move", False },
3332 Enables ncpEnables[] = {
3333 { "menuFile.Mail Move", False },
3334 { "menuFile.Reload CMail Message", False },
3335 { "menuMode.Machine White", False },
3336 { "menuMode.Machine Black", False },
3337 { "menuMode.Analysis Mode", False },
3338 { "menuMode.Analyze File", False },
3339 { "menuMode.Two Machines", False },
3340 { "menuMode.ICS Client", False },
3341 { "menuMode.ICS Input Box", False },
3342 { "Action", False },
3343 { "menuStep.Revert", False },
3344 { "menuStep.Move Now", False },
3345 { "menuStep.Retract Move", False },
3346 { "menuOptions.Auto Comment", False },
3347 { "menuOptions.Auto Flag", False },
3348 { "menuOptions.Auto Flip View", False },
3349 { "menuOptions.Auto Observe", False },
3350 { "menuOptions.Auto Raise Board", False },
3351 { "menuOptions.Get Move List", False },
3352 { "menuOptions.ICS Alarm", False },
3353 { "menuOptions.Move Sound", False },
3354 { "menuOptions.Quiet Play", False },
3355 { "menuOptions.Hide Thinking", False },
3356 { "menuOptions.Periodic Updates", False },
3357 { "menuOptions.Ponder Next Move", False },
3358 { "menuHelp.Hint", False },
3359 { "menuHelp.Book", False },
3363 Enables gnuEnables[] = {
3364 { "menuMode.ICS Client", False },
3365 { "menuMode.ICS Input Box", False },
3366 { "menuAction.Accept", False },
3367 { "menuAction.Decline", False },
3368 { "menuAction.Rematch", False },
3369 { "menuAction.Adjourn", False },
3370 { "menuAction.Stop Examining", False },
3371 { "menuAction.Stop Observing", False },
3372 { "menuStep.Revert", False },
3373 { "menuOptions.Auto Comment", False },
3374 { "menuOptions.Auto Observe", False },
3375 { "menuOptions.Auto Raise Board", False },
3376 { "menuOptions.Get Move List", False },
3377 { "menuOptions.Premove", False },
3378 { "menuOptions.Quiet Play", False },
3380 /* The next two options rely on SetCmailMode being called *after* */
3381 /* SetGNUMode so that when GNU is being used to give hints these */
3382 /* menu options are still available */
3384 { "menuFile.Mail Move", False },
3385 { "menuFile.Reload CMail Message", False },
3389 Enables cmailEnables[] = {
3391 { "menuAction.Call Flag", False },
3392 { "menuAction.Draw", True },
3393 { "menuAction.Adjourn", False },
3394 { "menuAction.Abort", False },
3395 { "menuAction.Stop Observing", False },
3396 { "menuAction.Stop Examining", False },
3397 { "menuFile.Mail Move", True },
3398 { "menuFile.Reload CMail Message", True },
3402 Enables trainingOnEnables[] = {
3403 { "menuMode.Edit Comment", False },
3404 { "menuMode.Pause", False },
3405 { "menuStep.Forward", False },
3406 { "menuStep.Backward", False },
3407 { "menuStep.Forward to End", False },
3408 { "menuStep.Back to Start", False },
3409 { "menuStep.Move Now", False },
3410 { "menuStep.Truncate Game", False },
3414 Enables trainingOffEnables[] = {
3415 { "menuMode.Edit Comment", True },
3416 { "menuMode.Pause", True },
3417 { "menuStep.Forward", True },
3418 { "menuStep.Backward", True },
3419 { "menuStep.Forward to End", True },
3420 { "menuStep.Back to Start", True },
3421 { "menuStep.Move Now", True },
3422 { "menuStep.Truncate Game", True },
3426 Enables machineThinkingEnables[] = {
3427 { "menuFile.Load Game", False },
3428 { "menuFile.Load Next Game", False },
3429 { "menuFile.Load Previous Game", False },
3430 { "menuFile.Reload Same Game", False },
3431 { "menuFile.Paste Game", False },
3432 { "menuFile.Load Position", False },
3433 { "menuFile.Load Next Position", False },
3434 { "menuFile.Load Previous Position", False },
3435 { "menuFile.Reload Same Position", False },
3436 { "menuFile.Paste Position", False },
3437 { "menuMode.Machine White", False },
3438 { "menuMode.Machine Black", False },
3439 { "menuMode.Two Machines", False },
3440 { "menuStep.Retract Move", False },
3444 Enables userThinkingEnables[] = {
3445 { "menuFile.Load Game", True },
3446 { "menuFile.Load Next Game", True },
3447 { "menuFile.Load Previous Game", True },
3448 { "menuFile.Reload Same Game", True },
3449 { "menuFile.Paste Game", True },
3450 { "menuFile.Load Position", True },
3451 { "menuFile.Load Next Position", True },
3452 { "menuFile.Load Previous Position", True },
3453 { "menuFile.Reload Same Position", True },
3454 { "menuFile.Paste Position", True },
3455 { "menuMode.Machine White", True },
3456 { "menuMode.Machine Black", True },
3457 { "menuMode.Two Machines", True },
3458 { "menuStep.Retract Move", True },
3464 SetMenuEnables(icsEnables);
3467 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3468 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3475 SetMenuEnables(ncpEnables);
3481 SetMenuEnables(gnuEnables);
3487 SetMenuEnables(cmailEnables);
3493 SetMenuEnables(trainingOnEnables);
3494 if (appData.showButtonBar) {
3495 XtSetSensitive(buttonBarWidget, False);
3501 SetTrainingModeOff()
3503 SetMenuEnables(trainingOffEnables);
3504 if (appData.showButtonBar) {
3505 XtSetSensitive(buttonBarWidget, True);
3510 SetUserThinkingEnables()
3512 if (appData.noChessProgram) return;
3513 SetMenuEnables(userThinkingEnables);
3517 SetMachineThinkingEnables()
3519 if (appData.noChessProgram) return;
3520 SetMenuEnables(machineThinkingEnables);
3522 case MachinePlaysBlack:
3523 case MachinePlaysWhite:
3524 case TwoMachinesPlay:
3525 XtSetSensitive(XtNameToWidget(menuBarWidget,
3526 ModeToWidgetName(gameMode)), True);
3533 #define Abs(n) ((n)<0 ? -(n) : (n))
3536 * Find a font that matches "pattern" that is as close as
3537 * possible to the targetPxlSize. Prefer fonts that are k
3538 * pixels smaller to fonts that are k pixels larger. The
3539 * pattern must be in the X Consortium standard format,
3540 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3541 * The return value should be freed with XtFree when no
3544 char *FindFont(pattern, targetPxlSize)
3548 char **fonts, *p, *best, *scalable, *scalableTail;
3549 int i, j, nfonts, minerr, err, pxlSize;
3552 char **missing_list;
3554 char *def_string, *base_fnt_lst, strInt[3];
3556 XFontStruct **fnt_list;
3558 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3559 sprintf(strInt, "%d", targetPxlSize);
3560 p = strstr(pattern, "--");
3561 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3562 strcat(base_fnt_lst, strInt);
3563 strcat(base_fnt_lst, strchr(p + 2, '-'));
3565 if ((fntSet = XCreateFontSet(xDisplay,
3569 &def_string)) == NULL) {
3571 fprintf(stderr, _("Unable to create font set.\n"));
3575 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3577 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3579 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3580 programName, pattern);
3588 for (i=0; i<nfonts; i++) {
3591 if (*p != '-') continue;
3593 if (*p == NULLCHAR) break;
3594 if (*p++ == '-') j++;
3596 if (j < 7) continue;
3599 scalable = fonts[i];
3602 err = pxlSize - targetPxlSize;
3603 if (Abs(err) < Abs(minerr) ||
3604 (minerr > 0 && err < 0 && -err == minerr)) {
3610 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3611 /* If the error is too big and there is a scalable font,
3612 use the scalable font. */
3613 int headlen = scalableTail - scalable;
3614 p = (char *) XtMalloc(strlen(scalable) + 10);
3615 while (isdigit(*scalableTail)) scalableTail++;
3616 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3618 p = (char *) XtMalloc(strlen(best) + 1);
3621 if (appData.debugMode) {
3622 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3623 pattern, targetPxlSize, p);
3626 if (missing_count > 0)
3627 XFreeStringList(missing_list);
3628 XFreeFontSet(xDisplay, fntSet);
3630 XFreeFontNames(fonts);
3637 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3638 | GCBackground | GCFunction | GCPlaneMask;
3639 XGCValues gc_values;
3642 gc_values.plane_mask = AllPlanes;
3643 gc_values.line_width = lineGap;
3644 gc_values.line_style = LineSolid;
3645 gc_values.function = GXcopy;
3647 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3648 gc_values.background = XBlackPixel(xDisplay, xScreen);
3649 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3651 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3652 gc_values.background = XWhitePixel(xDisplay, xScreen);
3653 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3654 XSetFont(xDisplay, coordGC, coordFontID);
3656 // [HGM] make font for holdings counts (white on black0
3657 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3658 gc_values.background = XBlackPixel(xDisplay, xScreen);
3659 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3660 XSetFont(xDisplay, countGC, countFontID);
3662 if (appData.monoMode) {
3663 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3664 gc_values.background = XWhitePixel(xDisplay, xScreen);
3665 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3667 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3668 gc_values.background = XBlackPixel(xDisplay, xScreen);
3669 lightSquareGC = wbPieceGC
3670 = XtGetGC(shellWidget, value_mask, &gc_values);
3672 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3673 gc_values.background = XWhitePixel(xDisplay, xScreen);
3674 darkSquareGC = bwPieceGC
3675 = XtGetGC(shellWidget, value_mask, &gc_values);
3677 if (DefaultDepth(xDisplay, xScreen) == 1) {
3678 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3679 gc_values.function = GXcopyInverted;
3680 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3681 gc_values.function = GXcopy;
3682 if (XBlackPixel(xDisplay, xScreen) == 1) {
3683 bwPieceGC = darkSquareGC;
3684 wbPieceGC = copyInvertedGC;
3686 bwPieceGC = copyInvertedGC;
3687 wbPieceGC = lightSquareGC;
3691 gc_values.foreground = highlightSquareColor;
3692 gc_values.background = highlightSquareColor;
3693 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3695 gc_values.foreground = premoveHighlightColor;
3696 gc_values.background = premoveHighlightColor;
3697 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3699 gc_values.foreground = lightSquareColor;
3700 gc_values.background = darkSquareColor;
3701 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3703 gc_values.foreground = darkSquareColor;
3704 gc_values.background = lightSquareColor;
3705 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3707 gc_values.foreground = jailSquareColor;
3708 gc_values.background = jailSquareColor;
3709 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3711 gc_values.foreground = whitePieceColor;
3712 gc_values.background = darkSquareColor;
3713 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3715 gc_values.foreground = whitePieceColor;
3716 gc_values.background = lightSquareColor;
3717 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3719 gc_values.foreground = whitePieceColor;
3720 gc_values.background = jailSquareColor;
3721 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3723 gc_values.foreground = blackPieceColor;
3724 gc_values.background = darkSquareColor;
3725 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3727 gc_values.foreground = blackPieceColor;
3728 gc_values.background = lightSquareColor;
3729 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3731 gc_values.foreground = blackPieceColor;
3732 gc_values.background = jailSquareColor;
3733 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3737 void loadXIM(xim, xmask, filename, dest, mask)
3750 fp = fopen(filename, "rb");
3752 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3759 for (y=0; y<h; ++y) {
3760 for (x=0; x<h; ++x) {
3765 XPutPixel(xim, x, y, blackPieceColor);
3767 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3770 XPutPixel(xim, x, y, darkSquareColor);
3772 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3775 XPutPixel(xim, x, y, whitePieceColor);
3777 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3780 XPutPixel(xim, x, y, lightSquareColor);
3782 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3788 /* create Pixmap of piece */
3789 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3791 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3794 /* create Pixmap of clipmask
3795 Note: We assume the white/black pieces have the same
3796 outline, so we make only 6 masks. This is okay
3797 since the XPM clipmask routines do the same. */
3799 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3801 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3804 /* now create the 1-bit version */
3805 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3808 values.foreground = 1;
3809 values.background = 0;
3811 /* Don't use XtGetGC, not read only */
3812 maskGC = XCreateGC(xDisplay, *mask,
3813 GCForeground | GCBackground, &values);
3814 XCopyPlane(xDisplay, temp, *mask, maskGC,
3815 0, 0, squareSize, squareSize, 0, 0, 1);
3816 XFreePixmap(xDisplay, temp);
3821 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3823 void CreateXIMPieces()
3828 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3833 /* The XSynchronize calls were copied from CreatePieces.
3834 Not sure if needed, but can't hurt */
3835 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3838 /* temp needed by loadXIM() */
3839 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3840 0, 0, ss, ss, AllPlanes, XYPixmap);
3842 if (strlen(appData.pixmapDirectory) == 0) {
3846 if (appData.monoMode) {
3847 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3851 fprintf(stderr, _("\nLoading XIMs...\n"));
3853 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3854 fprintf(stderr, "%d", piece+1);
3855 for (kind=0; kind<4; kind++) {
3856 fprintf(stderr, ".");
3857 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3858 ExpandPathName(appData.pixmapDirectory),
3859 piece <= (int) WhiteKing ? "" : "w",
3860 pieceBitmapNames[piece],
3862 ximPieceBitmap[kind][piece] =
3863 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3864 0, 0, ss, ss, AllPlanes, XYPixmap);
3865 if (appData.debugMode)
3866 fprintf(stderr, _("(File:%s:) "), buf);
3867 loadXIM(ximPieceBitmap[kind][piece],
3869 &(xpmPieceBitmap2[kind][piece]),
3870 &(ximMaskPm2[piece]));
3871 if(piece <= (int)WhiteKing)
3872 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3874 fprintf(stderr," ");
3876 /* Load light and dark squares */
3877 /* If the LSQ and DSQ pieces don't exist, we will
3878 draw them with solid squares. */
3879 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3880 if (access(buf, 0) != 0) {
3884 fprintf(stderr, _("light square "));
3886 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3887 0, 0, ss, ss, AllPlanes, XYPixmap);
3888 if (appData.debugMode)
3889 fprintf(stderr, _("(File:%s:) "), buf);
3891 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3892 fprintf(stderr, _("dark square "));
3893 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3894 ExpandPathName(appData.pixmapDirectory), ss);
3895 if (appData.debugMode)
3896 fprintf(stderr, _("(File:%s:) "), buf);
3898 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3899 0, 0, ss, ss, AllPlanes, XYPixmap);
3900 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3901 xpmJailSquare = xpmLightSquare;
3903 fprintf(stderr, _("Done.\n"));
3905 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3909 void CreateXPMPieces()
3913 u_int ss = squareSize;
3915 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3916 XpmColorSymbol symbols[4];
3918 /* The XSynchronize calls were copied from CreatePieces.
3919 Not sure if needed, but can't hurt */
3920 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3922 /* Setup translations so piece colors match square colors */
3923 symbols[0].name = "light_piece";
3924 symbols[0].value = appData.whitePieceColor;
3925 symbols[1].name = "dark_piece";
3926 symbols[1].value = appData.blackPieceColor;
3927 symbols[2].name = "light_square";
3928 symbols[2].value = appData.lightSquareColor;
3929 symbols[3].name = "dark_square";
3930 symbols[3].value = appData.darkSquareColor;
3932 attr.valuemask = XpmColorSymbols;
3933 attr.colorsymbols = symbols;
3934 attr.numsymbols = 4;
3936 if (appData.monoMode) {
3937 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3941 if (strlen(appData.pixmapDirectory) == 0) {
3942 XpmPieces* pieces = builtInXpms;
3945 while (pieces->size != squareSize && pieces->size) pieces++;
3946 if (!pieces->size) {
3947 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3950 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3951 for (kind=0; kind<4; kind++) {
3953 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3954 pieces->xpm[piece][kind],
3955 &(xpmPieceBitmap2[kind][piece]),
3956 NULL, &attr)) != 0) {
3957 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3961 if(piece <= (int) WhiteKing)
3962 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3966 xpmJailSquare = xpmLightSquare;
3970 fprintf(stderr, _("\nLoading XPMs...\n"));
3973 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3974 fprintf(stderr, "%d ", piece+1);
3975 for (kind=0; kind<4; kind++) {
3976 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3977 ExpandPathName(appData.pixmapDirectory),
3978 piece > (int) WhiteKing ? "w" : "",
3979 pieceBitmapNames[piece],
3981 if (appData.debugMode) {
3982 fprintf(stderr, _("(File:%s:) "), buf);
3984 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3985 &(xpmPieceBitmap2[kind][piece]),
3986 NULL, &attr)) != 0) {
3987 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3988 // [HGM] missing: read of unorthodox piece failed; substitute King.
3989 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3990 ExpandPathName(appData.pixmapDirectory),
3992 if (appData.debugMode) {
3993 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3995 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3996 &(xpmPieceBitmap2[kind][piece]),
4000 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4005 if(piece <= (int) WhiteKing)
4006 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4009 /* Load light and dark squares */
4010 /* If the LSQ and DSQ pieces don't exist, we will
4011 draw them with solid squares. */
4012 fprintf(stderr, _("light square "));
4013 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4014 if (access(buf, 0) != 0) {
4018 if (appData.debugMode)
4019 fprintf(stderr, _("(File:%s:) "), buf);
4021 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4022 &xpmLightSquare, NULL, &attr)) != 0) {
4023 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4026 fprintf(stderr, _("dark square "));
4027 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4028 ExpandPathName(appData.pixmapDirectory), ss);
4029 if (appData.debugMode) {
4030 fprintf(stderr, _("(File:%s:) "), buf);
4032 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4033 &xpmDarkSquare, NULL, &attr)) != 0) {
4034 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4038 xpmJailSquare = xpmLightSquare;
4039 fprintf(stderr, _("Done.\n"));
4041 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4044 #endif /* HAVE_LIBXPM */
4047 /* No built-in bitmaps */
4052 u_int ss = squareSize;
4054 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4057 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4058 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4059 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4060 pieceBitmapNames[piece],
4061 ss, kind == SOLID ? 's' : 'o');
4062 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4063 if(piece <= (int)WhiteKing)
4064 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4068 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4072 /* With built-in bitmaps */
4075 BuiltInBits* bib = builtInBits;
4078 u_int ss = squareSize;
4080 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4083 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4085 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4086 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4087 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4088 pieceBitmapNames[piece],
4089 ss, kind == SOLID ? 's' : 'o');
4090 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4091 bib->bits[kind][piece], ss, ss);
4092 if(piece <= (int)WhiteKing)
4093 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4097 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4102 void ReadBitmap(pm, name, bits, wreq, hreq)
4105 unsigned char bits[];
4111 char msg[MSG_SIZ], fullname[MSG_SIZ];
4113 if (*appData.bitmapDirectory != NULLCHAR) {
4114 strcpy(fullname, appData.bitmapDirectory);
4115 strcat(fullname, "/");
4116 strcat(fullname, name);
4117 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4118 &w, &h, pm, &x_hot, &y_hot);
4119 fprintf(stderr, "load %s\n", name);
4120 if (errcode != BitmapSuccess) {
4122 case BitmapOpenFailed:
4123 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4125 case BitmapFileInvalid:
4126 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4128 case BitmapNoMemory:
4129 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4133 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4137 fprintf(stderr, _("%s: %s...using built-in\n"),
4139 } else if (w != wreq || h != hreq) {
4141 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4142 programName, fullname, w, h, wreq, hreq);
4148 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4157 if (lineGap == 0) return;
4159 /* [HR] Split this into 2 loops for non-square boards. */
4161 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4162 gridSegments[i].x1 = 0;
4163 gridSegments[i].x2 =
4164 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4165 gridSegments[i].y1 = gridSegments[i].y2
4166 = lineGap / 2 + (i * (squareSize + lineGap));
4169 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4170 gridSegments[j + i].y1 = 0;
4171 gridSegments[j + i].y2 =
4172 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4173 gridSegments[j + i].x1 = gridSegments[j + i].x2
4174 = lineGap / 2 + (j * (squareSize + lineGap));
4178 static void MenuBarSelect(w, addr, index)
4183 XtActionProc proc = (XtActionProc) addr;
4185 (proc)(NULL, NULL, NULL, NULL);
4188 void CreateMenuBarPopup(parent, name, mb)
4198 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4201 XtSetArg(args[j], XtNleftMargin, 20); j++;
4202 XtSetArg(args[j], XtNrightMargin, 20); j++;
4204 while (mi->string != NULL) {
4205 if (strcmp(mi->string, "----") == 0) {
4206 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4209 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4210 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4212 XtAddCallback(entry, XtNcallback,
4213 (XtCallbackProc) MenuBarSelect,
4214 (caddr_t) mi->proc);
4220 Widget CreateMenuBar(mb)
4224 Widget anchor, menuBar;
4226 char menuName[MSG_SIZ];
4229 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4230 XtSetArg(args[j], XtNvSpace, 0); j++;
4231 XtSetArg(args[j], XtNborderWidth, 0); j++;
4232 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4233 formWidget, args, j);
4235 while (mb->name != NULL) {
4236 strcpy(menuName, "menu");
4237 strcat(menuName, mb->name);
4239 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4242 shortName[0] = _(mb->name)[0];
4243 shortName[1] = NULLCHAR;
4244 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4247 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4250 XtSetArg(args[j], XtNborderWidth, 0); j++;
4251 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4253 CreateMenuBarPopup(menuBar, menuName, mb);
4259 Widget CreateButtonBar(mi)
4263 Widget button, buttonBar;
4267 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4269 XtSetArg(args[j], XtNhSpace, 0); j++;
4271 XtSetArg(args[j], XtNborderWidth, 0); j++;
4272 XtSetArg(args[j], XtNvSpace, 0); j++;
4273 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4274 formWidget, args, j);
4276 while (mi->string != NULL) {
4279 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4280 XtSetArg(args[j], XtNborderWidth, 0); j++;
4282 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4283 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4284 buttonBar, args, j);
4285 XtAddCallback(button, XtNcallback,
4286 (XtCallbackProc) MenuBarSelect,
4287 (caddr_t) mi->proc);
4294 CreatePieceMenu(name, color)
4301 ChessSquare selection;
4303 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4304 boardWidget, args, 0);
4306 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4307 String item = pieceMenuStrings[color][i];
4309 if (strcmp(item, "----") == 0) {
4310 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4313 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4314 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4316 selection = pieceMenuTranslation[color][i];
4317 XtAddCallback(entry, XtNcallback,
4318 (XtCallbackProc) PieceMenuSelect,
4319 (caddr_t) selection);
4320 if (selection == WhitePawn || selection == BlackPawn) {
4321 XtSetArg(args[0], XtNpopupOnEntry, entry);
4322 XtSetValues(menu, args, 1);
4335 ChessSquare selection;
4337 whitePieceMenu = CreatePieceMenu("menuW", 0);
4338 blackPieceMenu = CreatePieceMenu("menuB", 1);
4340 XtRegisterGrabAction(PieceMenuPopup, True,
4341 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4342 GrabModeAsync, GrabModeAsync);
4344 XtSetArg(args[0], XtNlabel, _("Drop"));
4345 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4346 boardWidget, args, 1);
4347 for (i = 0; i < DROP_MENU_SIZE; i++) {
4348 String item = dropMenuStrings[i];
4350 if (strcmp(item, "----") == 0) {
4351 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4354 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4355 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4357 selection = dropMenuTranslation[i];
4358 XtAddCallback(entry, XtNcallback,
4359 (XtCallbackProc) DropMenuSelect,
4360 (caddr_t) selection);
4365 void SetupDropMenu()
4373 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4374 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4375 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4376 dmEnables[i].piece);
4377 XtSetSensitive(entry, p != NULL || !appData.testLegality
4378 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4379 && !appData.icsActive));
4381 while (p && *p++ == dmEnables[i].piece) count++;
4382 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4384 XtSetArg(args[j], XtNlabel, label); j++;
4385 XtSetValues(entry, args, j);
4389 void PieceMenuPopup(w, event, params, num_params)
4393 Cardinal *num_params;
4396 if (event->type != ButtonPress) return;
4397 if (errorUp) ErrorPopDown();
4401 whichMenu = params[0];
4403 case IcsPlayingWhite:
4404 case IcsPlayingBlack:
4406 case MachinePlaysWhite:
4407 case MachinePlaysBlack:
4408 if (appData.testLegality &&
4409 gameInfo.variant != VariantBughouse &&
4410 gameInfo.variant != VariantCrazyhouse) return;
4412 whichMenu = "menuD";
4418 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4419 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4420 pmFromX = pmFromY = -1;
4424 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4426 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4428 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4431 static void PieceMenuSelect(w, piece, junk)
4436 if (pmFromX < 0 || pmFromY < 0) return;
4437 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4440 static void DropMenuSelect(w, piece, junk)
4445 if (pmFromX < 0 || pmFromY < 0) return;
4446 DropMenuEvent(piece, pmFromX, pmFromY);
4449 void WhiteClock(w, event, prms, nprms)
4455 if (gameMode == EditPosition || gameMode == IcsExamining) {
4456 SetWhiteToPlayEvent();
4457 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4462 void BlackClock(w, event, prms, nprms)
4468 if (gameMode == EditPosition || gameMode == IcsExamining) {
4469 SetBlackToPlayEvent();
4470 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4477 * If the user selects on a border boundary, return -1; if off the board,
4478 * return -2. Otherwise map the event coordinate to the square.
4480 int EventToSquare(x, limit)
4488 if ((x % (squareSize + lineGap)) >= squareSize)
4490 x /= (squareSize + lineGap);
4496 static void do_flash_delay(msec)
4502 static void drawHighlight(file, rank, gc)
4508 if (lineGap == 0 || appData.blindfold) return;
4511 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4512 (squareSize + lineGap);
4513 y = lineGap/2 + rank * (squareSize + lineGap);
4515 x = lineGap/2 + file * (squareSize + lineGap);
4516 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4517 (squareSize + lineGap);
4520 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4521 squareSize+lineGap, squareSize+lineGap);
4524 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4525 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4528 SetHighlights(fromX, fromY, toX, toY)
4529 int fromX, fromY, toX, toY;
4531 if (hi1X != fromX || hi1Y != fromY) {
4532 if (hi1X >= 0 && hi1Y >= 0) {
4533 drawHighlight(hi1X, hi1Y, lineGC);
4535 if (fromX >= 0 && fromY >= 0) {
4536 drawHighlight(fromX, fromY, highlineGC);
4539 if (hi2X != toX || hi2Y != toY) {
4540 if (hi2X >= 0 && hi2Y >= 0) {
4541 drawHighlight(hi2X, hi2Y, lineGC);
4543 if (toX >= 0 && toY >= 0) {
4544 drawHighlight(toX, toY, highlineGC);
4556 SetHighlights(-1, -1, -1, -1);
4561 SetPremoveHighlights(fromX, fromY, toX, toY)
4562 int fromX, fromY, toX, toY;
4564 if (pm1X != fromX || pm1Y != fromY) {
4565 if (pm1X >= 0 && pm1Y >= 0) {
4566 drawHighlight(pm1X, pm1Y, lineGC);
4568 if (fromX >= 0 && fromY >= 0) {
4569 drawHighlight(fromX, fromY, prelineGC);
4572 if (pm2X != toX || pm2Y != toY) {
4573 if (pm2X >= 0 && pm2Y >= 0) {
4574 drawHighlight(pm2X, pm2Y, lineGC);
4576 if (toX >= 0 && toY >= 0) {
4577 drawHighlight(toX, toY, prelineGC);
4587 ClearPremoveHighlights()
4589 SetPremoveHighlights(-1, -1, -1, -1);
4592 static void BlankSquare(x, y, color, piece, dest)
4597 if (useImages && useImageSqs) {
4601 pm = xpmLightSquare;
4606 case 2: /* neutral */
4611 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4612 squareSize, squareSize, x, y);
4622 case 2: /* neutral */
4627 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4632 I split out the routines to draw a piece so that I could
4633 make a generic flash routine.
4635 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4637 int square_color, x, y;
4640 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4641 switch (square_color) {
4643 case 2: /* neutral */
4645 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4646 ? *pieceToOutline(piece)
4647 : *pieceToSolid(piece),
4648 dest, bwPieceGC, 0, 0,
4649 squareSize, squareSize, x, y);
4652 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4653 ? *pieceToSolid(piece)
4654 : *pieceToOutline(piece),
4655 dest, wbPieceGC, 0, 0,
4656 squareSize, squareSize, x, y);
4661 static void monoDrawPiece(piece, square_color, x, y, dest)
4663 int square_color, x, y;
4666 switch (square_color) {
4668 case 2: /* neutral */
4670 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4671 ? *pieceToOutline(piece)
4672 : *pieceToSolid(piece),
4673 dest, bwPieceGC, 0, 0,
4674 squareSize, squareSize, x, y, 1);
4677 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4678 ? *pieceToSolid(piece)
4679 : *pieceToOutline(piece),
4680 dest, wbPieceGC, 0, 0,
4681 squareSize, squareSize, x, y, 1);
4686 static void colorDrawPiece(piece, square_color, x, y, dest)
4688 int square_color, x, y;
4691 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4692 switch (square_color) {
4694 XCopyPlane(xDisplay, *pieceToSolid(piece),
4695 dest, (int) piece < (int) BlackPawn
4696 ? wlPieceGC : blPieceGC, 0, 0,
4697 squareSize, squareSize, x, y, 1);
4700 XCopyPlane(xDisplay, *pieceToSolid(piece),
4701 dest, (int) piece < (int) BlackPawn
4702 ? wdPieceGC : bdPieceGC, 0, 0,
4703 squareSize, squareSize, x, y, 1);
4705 case 2: /* neutral */
4707 XCopyPlane(xDisplay, *pieceToSolid(piece),
4708 dest, (int) piece < (int) BlackPawn
4709 ? wjPieceGC : bjPieceGC, 0, 0,
4710 squareSize, squareSize, x, y, 1);
4715 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4717 int square_color, x, y;
4722 switch (square_color) {
4724 case 2: /* neutral */
4726 if ((int)piece < (int) BlackPawn) {
4734 if ((int)piece < (int) BlackPawn) {
4742 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4743 dest, wlPieceGC, 0, 0,
4744 squareSize, squareSize, x, y);
4747 typedef void (*DrawFunc)();
4749 DrawFunc ChooseDrawFunc()
4751 if (appData.monoMode) {
4752 if (DefaultDepth(xDisplay, xScreen) == 1) {
4753 return monoDrawPiece_1bit;
4755 return monoDrawPiece;
4759 return colorDrawPieceImage;
4761 return colorDrawPiece;
4765 /* [HR] determine square color depending on chess variant. */
4766 static int SquareColor(row, column)
4771 if (gameInfo.variant == VariantXiangqi) {
4772 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4774 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4776 } else if (row <= 4) {
4782 square_color = ((column + row) % 2) == 1;
4785 /* [hgm] holdings: next line makes all holdings squares light */
4786 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4788 return square_color;
4791 void DrawSquare(row, column, piece, do_flash)
4792 int row, column, do_flash;
4795 int square_color, x, y, direction, font_ascent, font_descent;
4798 XCharStruct overall;
4802 /* Calculate delay in milliseconds (2-delays per complete flash) */
4803 flash_delay = 500 / appData.flashRate;
4806 x = lineGap + ((BOARD_WIDTH-1)-column) *
4807 (squareSize + lineGap);
4808 y = lineGap + row * (squareSize + lineGap);
4810 x = lineGap + column * (squareSize + lineGap);
4811 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4812 (squareSize + lineGap);
4815 square_color = SquareColor(row, column);
4817 if ( // [HGM] holdings: blank out area between board and holdings
4818 column == BOARD_LEFT-1 || column == BOARD_RGHT
4819 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4820 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4821 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4823 // [HGM] print piece counts next to holdings
4824 string[1] = NULLCHAR;
4825 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4826 string[0] = '0' + piece;
4827 XTextExtents(countFontStruct, string, 1, &direction,
4828 &font_ascent, &font_descent, &overall);
4829 if (appData.monoMode) {
4830 XDrawImageString(xDisplay, xBoardWindow, countGC,
4831 x + squareSize - overall.width - 2,
4832 y + font_ascent + 1, string, 1);
4834 XDrawString(xDisplay, xBoardWindow, countGC,
4835 x + squareSize - overall.width - 2,
4836 y + font_ascent + 1, string, 1);
4839 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4840 string[0] = '0' + piece;
4841 XTextExtents(countFontStruct, string, 1, &direction,
4842 &font_ascent, &font_descent, &overall);
4843 if (appData.monoMode) {
4844 XDrawImageString(xDisplay, xBoardWindow, countGC,
4845 x + 2, y + font_ascent + 1, string, 1);
4847 XDrawString(xDisplay, xBoardWindow, countGC,
4848 x + 2, y + font_ascent + 1, string, 1);
4852 if (piece == EmptySquare || appData.blindfold) {
4853 BlankSquare(x, y, square_color, piece, xBoardWindow);
4855 drawfunc = ChooseDrawFunc();
4856 if (do_flash && appData.flashCount > 0) {
4857 for (i=0; i<appData.flashCount; ++i) {
4859 drawfunc(piece, square_color, x, y, xBoardWindow);
4860 XSync(xDisplay, False);
4861 do_flash_delay(flash_delay);
4863 BlankSquare(x, y, square_color, piece, xBoardWindow);
4864 XSync(xDisplay, False);
4865 do_flash_delay(flash_delay);
4868 drawfunc(piece, square_color, x, y, xBoardWindow);
4872 string[1] = NULLCHAR;
4873 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4874 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4875 string[0] = 'a' + column - BOARD_LEFT;
4876 XTextExtents(coordFontStruct, string, 1, &direction,
4877 &font_ascent, &font_descent, &overall);
4878 if (appData.monoMode) {
4879 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4880 x + squareSize - overall.width - 2,
4881 y + squareSize - font_descent - 1, string, 1);
4883 XDrawString(xDisplay, xBoardWindow, coordGC,
4884 x + squareSize - overall.width - 2,
4885 y + squareSize - font_descent - 1, string, 1);
4888 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4889 string[0] = ONE + row;
4890 XTextExtents(coordFontStruct, string, 1, &direction,
4891 &font_ascent, &font_descent, &overall);
4892 if (appData.monoMode) {
4893 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4894 x + 2, y + font_ascent + 1, string, 1);
4896 XDrawString(xDisplay, xBoardWindow, coordGC,
4897 x + 2, y + font_ascent + 1, string, 1);
4903 /* Why is this needed on some versions of X? */
4904 void EventProc(widget, unused, event)
4909 if (!XtIsRealized(widget))
4912 switch (event->type) {
4914 if (event->xexpose.count > 0) return; /* no clipping is done */
4915 XDrawPosition(widget, True, NULL);
4923 void DrawPosition(fullRedraw, board)
4924 /*Boolean*/int fullRedraw;
4927 XDrawPosition(boardWidget, fullRedraw, board);
4930 /* Returns 1 if there are "too many" differences between b1 and b2
4931 (i.e. more than 1 move was made) */
4932 static int too_many_diffs(b1, b2)
4938 for (i=0; i<BOARD_HEIGHT; ++i) {
4939 for (j=0; j<BOARD_WIDTH; ++j) {
4940 if (b1[i][j] != b2[i][j]) {
4941 if (++c > 4) /* Castling causes 4 diffs */
4950 /* Matrix describing castling maneuvers */
4951 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4952 static int castling_matrix[4][5] = {
4953 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4954 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4955 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4956 { 7, 7, 4, 5, 6 } /* 0-0, black */
4959 /* Checks whether castling occurred. If it did, *rrow and *rcol
4960 are set to the destination (row,col) of the rook that moved.
4962 Returns 1 if castling occurred, 0 if not.
4964 Note: Only handles a max of 1 castling move, so be sure
4965 to call too_many_diffs() first.
4967 static int check_castle_draw(newb, oldb, rrow, rcol)
4974 /* For each type of castling... */
4975 for (i=0; i<4; ++i) {
4976 r = castling_matrix[i];
4978 /* Check the 4 squares involved in the castling move */
4980 for (j=1; j<=4; ++j) {
4981 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4988 /* All 4 changed, so it must be a castling move */
4997 static int damage[BOARD_SIZE][BOARD_SIZE];
5000 * event handler for redrawing the board
5002 void XDrawPosition(w, repaint, board)
5004 /*Boolean*/int repaint;
5008 static int lastFlipView = 0;
5009 static int lastBoardValid = 0;
5010 static Board lastBoard;
5014 if (board == NULL) {
5015 if (!lastBoardValid) return;
5018 if (!lastBoardValid || lastFlipView != flipView) {
5019 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5020 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5025 * It would be simpler to clear the window with XClearWindow()
5026 * but this causes a very distracting flicker.
5029 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5031 /* If too much changes (begin observing new game, etc.), don't
5033 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5035 /* Special check for castling so we don't flash both the king
5036 and the rook (just flash the king). */
5038 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5039 /* Draw rook with NO flashing. King will be drawn flashing later */
5040 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5041 lastBoard[rrow][rcol] = board[rrow][rcol];
5045 /* First pass -- Draw (newly) empty squares and repair damage.
5046 This prevents you from having a piece show up twice while it
5047 is flashing on its new square */
5048 for (i = 0; i < BOARD_HEIGHT; i++)
5049 for (j = 0; j < BOARD_WIDTH; j++)
5050 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5052 DrawSquare(i, j, board[i][j], 0);
5053 damage[i][j] = False;
5056 /* Second pass -- Draw piece(s) in new position and flash them */
5057 for (i = 0; i < BOARD_HEIGHT; i++)
5058 for (j = 0; j < BOARD_WIDTH; j++)
5059 if (board[i][j] != lastBoard[i][j]) {
5060 DrawSquare(i, j, board[i][j], do_flash);
5064 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5065 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5067 for (i = 0; i < BOARD_HEIGHT; i++)
5068 for (j = 0; j < BOARD_WIDTH; j++) {
5069 DrawSquare(i, j, board[i][j], 0);
5070 damage[i][j] = False;
5074 CopyBoard(lastBoard, board);
5076 lastFlipView = flipView;
5078 /* Draw highlights */
5079 if (pm1X >= 0 && pm1Y >= 0) {
5080 drawHighlight(pm1X, pm1Y, prelineGC);
5082 if (pm2X >= 0 && pm2Y >= 0) {
5083 drawHighlight(pm2X, pm2Y, prelineGC);
5085 if (hi1X >= 0 && hi1Y >= 0) {
5086 drawHighlight(hi1X, hi1Y, highlineGC);
5088 if (hi2X >= 0 && hi2Y >= 0) {
5089 drawHighlight(hi2X, hi2Y, highlineGC);
5092 /* If piece being dragged around board, must redraw that too */
5095 XSync(xDisplay, False);
5100 * event handler for redrawing the board
5102 void DrawPositionProc(w, event, prms, nprms)
5108 XDrawPosition(w, True, NULL);
5113 * event handler for parsing user moves
5115 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5116 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5117 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5118 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5119 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5120 // and at the end FinishMove() to perform the move after optional promotion popups.
5121 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5122 void HandleUserMove(w, event, prms, nprms)
5128 if (w != boardWidget || errorExitStatus != -1) return;
5131 if (event->type == ButtonPress) {
5132 XtPopdown(promotionShell);
5133 XtDestroyWidget(promotionShell);
5134 promotionUp = False;
5142 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5143 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5144 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5147 void AnimateUserMove (Widget w, XEvent * event,
5148 String * params, Cardinal * nParams)
5150 DragPieceMove(event->xmotion.x, event->xmotion.y);
5153 Widget CommentCreate(name, text, mutable, callback, lines)
5155 int /*Boolean*/ mutable;
5156 XtCallbackProc callback;
5160 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5165 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5166 XtGetValues(boardWidget, args, j);
5169 XtSetArg(args[j], XtNresizable, True); j++;
5172 XtCreatePopupShell(name, topLevelShellWidgetClass,
5173 shellWidget, args, j);
5176 XtCreatePopupShell(name, transientShellWidgetClass,
5177 shellWidget, args, j);
5180 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5181 layoutArgs, XtNumber(layoutArgs));
5183 XtCreateManagedWidget("form", formWidgetClass, layout,
5184 formArgs, XtNumber(formArgs));
5188 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5189 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5191 XtSetArg(args[j], XtNstring, text); j++;
5192 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5193 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5194 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5195 XtSetArg(args[j], XtNright, XtChainRight); j++;
5196 XtSetArg(args[j], XtNresizable, True); j++;
5197 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5198 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5199 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5200 XtSetArg(args[j], XtNautoFill, True); j++;
5201 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5203 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5207 XtSetArg(args[j], XtNfromVert, edit); j++;
5208 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5209 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5210 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5211 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5213 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5214 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5217 XtSetArg(args[j], XtNfromVert, edit); j++;
5218 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5219 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5220 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5221 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5222 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5224 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5225 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5228 XtSetArg(args[j], XtNfromVert, edit); j++;
5229 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5230 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5231 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5232 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5233 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5235 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5236 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5239 XtSetArg(args[j], XtNfromVert, edit); j++;
5240 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5241 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5242 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5243 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5245 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5246 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5249 XtSetArg(args[j], XtNfromVert, edit); j++;
5250 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5251 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5252 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5253 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5254 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5256 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5257 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5260 XtRealizeWidget(shell);
5262 if (commentX == -1) {
5265 Dimension pw_height;
5266 Dimension ew_height;
5269 XtSetArg(args[j], XtNheight, &ew_height); j++;
5270 XtGetValues(edit, args, j);
5273 XtSetArg(args[j], XtNheight, &pw_height); j++;
5274 XtGetValues(shell, args, j);
5275 commentH = pw_height + (lines - 1) * ew_height;
5276 commentW = bw_width - 16;
5278 XSync(xDisplay, False);
5280 /* This code seems to tickle an X bug if it is executed too soon
5281 after xboard starts up. The coordinates get transformed as if
5282 the main window was positioned at (0, 0).
5284 XtTranslateCoords(shellWidget,
5285 (bw_width - commentW) / 2, 0 - commentH / 2,
5286 &commentX, &commentY);
5288 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5289 RootWindowOfScreen(XtScreen(shellWidget)),
5290 (bw_width - commentW) / 2, 0 - commentH / 2,
5295 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5298 XtSetArg(args[j], XtNheight, commentH); j++;
5299 XtSetArg(args[j], XtNwidth, commentW); j++;
5300 XtSetArg(args[j], XtNx, commentX); j++;
5301 XtSetArg(args[j], XtNy, commentY); j++;
5302 XtSetValues(shell, args, j);
5303 XtSetKeyboardFocus(shell, edit);
5308 /* Used for analysis window and ICS input window */
5309 Widget MiscCreate(name, text, mutable, callback, lines)
5311 int /*Boolean*/ mutable;
5312 XtCallbackProc callback;
5316 Widget shell, layout, form, edit;
5318 Dimension bw_width, pw_height, ew_height, w, h;
5324 XtSetArg(args[j], XtNresizable, True); j++;
5327 XtCreatePopupShell(name, topLevelShellWidgetClass,
5328 shellWidget, args, j);
5331 XtCreatePopupShell(name, transientShellWidgetClass,
5332 shellWidget, args, j);
5335 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5336 layoutArgs, XtNumber(layoutArgs));
5338 XtCreateManagedWidget("form", formWidgetClass, layout,
5339 formArgs, XtNumber(formArgs));
5343 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5344 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5346 XtSetArg(args[j], XtNstring, text); j++;
5347 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5348 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5349 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5350 XtSetArg(args[j], XtNright, XtChainRight); j++;
5351 XtSetArg(args[j], XtNresizable, True); j++;
5352 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5353 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5354 XtSetArg(args[j], XtNautoFill, True); j++;
5355 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5357 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5359 XtRealizeWidget(shell);
5362 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5363 XtGetValues(boardWidget, args, j);
5366 XtSetArg(args[j], XtNheight, &ew_height); j++;
5367 XtGetValues(edit, args, j);
5370 XtSetArg(args[j], XtNheight, &pw_height); j++;
5371 XtGetValues(shell, args, j);
5372 h = pw_height + (lines - 1) * ew_height;
5375 XSync(xDisplay, False);
5377 /* This code seems to tickle an X bug if it is executed too soon
5378 after xboard starts up. The coordinates get transformed as if
5379 the main window was positioned at (0, 0).
5381 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5383 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5384 RootWindowOfScreen(XtScreen(shellWidget)),
5385 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5389 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5392 XtSetArg(args[j], XtNheight, h); j++;
5393 XtSetArg(args[j], XtNwidth, w); j++;
5394 XtSetArg(args[j], XtNx, x); j++;
5395 XtSetArg(args[j], XtNy, y); j++;
5396 XtSetValues(shell, args, j);
5402 static int savedIndex; /* gross that this is global */
5404 void EditCommentPopUp(index, title, text)
5413 if (text == NULL) text = "";
5415 if (editShell == NULL) {
5417 CommentCreate(title, text, True, EditCommentCallback, 4);
5418 XtRealizeWidget(editShell);
5419 CatchDeleteWindow(editShell, "EditCommentPopDown");
5421 edit = XtNameToWidget(editShell, "*form.text");
5423 XtSetArg(args[j], XtNstring, text); j++;
5424 XtSetValues(edit, args, j);
5426 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5427 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5428 XtSetValues(editShell, args, j);
5431 XtPopup(editShell, XtGrabNone);
5435 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5436 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5440 void EditCommentCallback(w, client_data, call_data)
5442 XtPointer client_data, call_data;
5450 XtSetArg(args[j], XtNlabel, &name); j++;
5451 XtGetValues(w, args, j);
5453 if (strcmp(name, _("ok")) == 0) {
5454 edit = XtNameToWidget(editShell, "*form.text");
5456 XtSetArg(args[j], XtNstring, &val); j++;
5457 XtGetValues(edit, args, j);
5458 ReplaceComment(savedIndex, val);
5459 EditCommentPopDown();
5460 } else if (strcmp(name, _("cancel")) == 0) {
5461 EditCommentPopDown();
5462 } else if (strcmp(name, _("clear")) == 0) {
5463 edit = XtNameToWidget(editShell, "*form.text");
5464 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5465 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5469 void EditCommentPopDown()
5474 if (!editUp) return;
5476 XtSetArg(args[j], XtNx, &commentX); j++;
5477 XtSetArg(args[j], XtNy, &commentY); j++;
5478 XtSetArg(args[j], XtNheight, &commentH); j++;
5479 XtSetArg(args[j], XtNwidth, &commentW); j++;
5480 XtGetValues(editShell, args, j);
5481 XtPopdown(editShell);
5484 XtSetArg(args[j], XtNleftBitmap, None); j++;
5485 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5489 void ICSInputBoxPopUp()
5494 char *title = _("ICS Input");
5497 if (ICSInputShell == NULL) {
5498 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5499 tr = XtParseTranslationTable(ICSInputTranslations);
5500 edit = XtNameToWidget(ICSInputShell, "*form.text");
5501 XtOverrideTranslations(edit, tr);
5502 XtRealizeWidget(ICSInputShell);
5503 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5506 edit = XtNameToWidget(ICSInputShell, "*form.text");
5508 XtSetArg(args[j], XtNstring, ""); j++;
5509 XtSetValues(edit, args, j);
5511 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5512 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5513 XtSetValues(ICSInputShell, args, j);
5516 XtPopup(ICSInputShell, XtGrabNone);
5517 XtSetKeyboardFocus(ICSInputShell, edit);
5519 ICSInputBoxUp = True;
5521 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5522 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5526 void ICSInputSendText()
5533 edit = XtNameToWidget(ICSInputShell, "*form.text");
5535 XtSetArg(args[j], XtNstring, &val); j++;
5536 XtGetValues(edit, args, j);
5537 SendMultiLineToICS(val);
5538 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5539 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5542 void ICSInputBoxPopDown()
5547 if (!ICSInputBoxUp) return;
5549 XtPopdown(ICSInputShell);
5550 ICSInputBoxUp = False;
5552 XtSetArg(args[j], XtNleftBitmap, None); j++;
5553 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5557 void CommentPopUp(title, text)
5564 if (commentShell == NULL) {
5566 CommentCreate(title, text, False, CommentCallback, 4);
5567 XtRealizeWidget(commentShell);
5568 CatchDeleteWindow(commentShell, "CommentPopDown");
5570 edit = XtNameToWidget(commentShell, "*form.text");
5572 XtSetArg(args[j], XtNstring, text); j++;
5573 XtSetValues(edit, args, j);
5575 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5576 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5577 XtSetValues(commentShell, args, j);
5580 XtPopup(commentShell, XtGrabNone);
5581 XSync(xDisplay, False);
5586 void CommentCallback(w, client_data, call_data)
5588 XtPointer client_data, call_data;
5595 XtSetArg(args[j], XtNlabel, &name); j++;
5596 XtGetValues(w, args, j);
5598 if (strcmp(name, _("close")) == 0) {
5600 } else if (strcmp(name, _("edit")) == 0) {
5607 void CommentPopDown()
5612 if (!commentUp) return;
5614 XtSetArg(args[j], XtNx, &commentX); j++;
5615 XtSetArg(args[j], XtNy, &commentY); j++;
5616 XtSetArg(args[j], XtNwidth, &commentW); j++;
5617 XtSetArg(args[j], XtNheight, &commentH); j++;
5618 XtGetValues(commentShell, args, j);
5619 XtPopdown(commentShell);
5620 XSync(xDisplay, False);
5624 void FileNamePopUp(label, def, proc, openMode)
5631 Widget popup, layout, dialog, edit;
5637 fileProc = proc; /* I can't see a way not */
5638 fileOpenMode = openMode; /* to use globals here */
5641 XtSetArg(args[i], XtNresizable, True); i++;
5642 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5643 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5644 fileNameShell = popup =
5645 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5646 shellWidget, args, i);
5649 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5650 layoutArgs, XtNumber(layoutArgs));
5653 XtSetArg(args[i], XtNlabel, label); i++;
5654 XtSetArg(args[i], XtNvalue, def); i++;
5655 XtSetArg(args[i], XtNborderWidth, 0); i++;
5656 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5659 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5660 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5661 (XtPointer) dialog);
5663 XtRealizeWidget(popup);
5664 CatchDeleteWindow(popup, "FileNamePopDown");
5666 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5667 &x, &y, &win_x, &win_y, &mask);
5669 XtSetArg(args[0], XtNx, x - 10);
5670 XtSetArg(args[1], XtNy, y - 30);
5671 XtSetValues(popup, args, 2);
5673 XtPopup(popup, XtGrabExclusive);
5676 edit = XtNameToWidget(dialog, "*value");
5677 XtSetKeyboardFocus(popup, edit);
5680 void FileNamePopDown()
5682 if (!filenameUp) return;
5683 XtPopdown(fileNameShell);
5684 XtDestroyWidget(fileNameShell);
5689 void FileNameCallback(w, client_data, call_data)
5691 XtPointer client_data, call_data;
5696 XtSetArg(args[0], XtNlabel, &name);
5697 XtGetValues(w, args, 1);
5699 if (strcmp(name, _("cancel")) == 0) {
5704 FileNameAction(w, NULL, NULL, NULL);
5707 void FileNameAction(w, event, prms, nprms)
5719 name = XawDialogGetValueString(w = XtParent(w));
5721 if ((name != NULL) && (*name != NULLCHAR)) {
5723 XtPopdown(w = XtParent(XtParent(w)));
5727 p = strrchr(buf, ' ');
5734 fullname = ExpandPathName(buf);
5736 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5739 f = fopen(fullname, fileOpenMode);
5741 DisplayError(_("Failed to open file"), errno);
5743 (void) (*fileProc)(f, index, buf);
5750 XtPopdown(w = XtParent(XtParent(w)));
5756 void PromotionPopUp()
5759 Widget dialog, layout;
5761 Dimension bw_width, pw_width;
5765 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5766 XtGetValues(boardWidget, args, j);
5769 XtSetArg(args[j], XtNresizable, True); j++;
5770 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5772 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5773 shellWidget, args, j);
5775 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5776 layoutArgs, XtNumber(layoutArgs));
5779 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5780 XtSetArg(args[j], XtNborderWidth, 0); j++;
5781 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5784 if(gameInfo.variant != VariantShogi) {
5785 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5786 (XtPointer) dialog);
5787 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5788 (XtPointer) dialog);
5789 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5790 (XtPointer) dialog);
5791 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5792 (XtPointer) dialog);
5793 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5794 gameInfo.variant == VariantGiveaway) {
5795 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5796 (XtPointer) dialog);
5798 if(gameInfo.variant == VariantCapablanca ||
5799 gameInfo.variant == VariantGothic ||
5800 gameInfo.variant == VariantCapaRandom) {
5801 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5802 (XtPointer) dialog);
5803 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5804 (XtPointer) dialog);
5806 } else // [HGM] shogi
5808 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5809 (XtPointer) dialog);
5810 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5811 (XtPointer) dialog);
5813 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5814 (XtPointer) dialog);
5816 XtRealizeWidget(promotionShell);
5817 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5820 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5821 XtGetValues(promotionShell, args, j);
5823 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5824 lineGap + squareSize/3 +
5825 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5826 0 : 6*(squareSize + lineGap)), &x, &y);
5829 XtSetArg(args[j], XtNx, x); j++;
5830 XtSetArg(args[j], XtNy, y); j++;
5831 XtSetValues(promotionShell, args, j);
5833 XtPopup(promotionShell, XtGrabNone);
5838 void PromotionPopDown()
5840 if (!promotionUp) return;
5841 XtPopdown(promotionShell);
5842 XtDestroyWidget(promotionShell);
5843 promotionUp = False;
5846 void PromotionCallback(w, client_data, call_data)
5848 XtPointer client_data, call_data;
5854 XtSetArg(args[0], XtNlabel, &name);
5855 XtGetValues(w, args, 1);
5859 if (fromX == -1) return;
5861 if (strcmp(name, _("cancel")) == 0) {
5865 } else if (strcmp(name, _("Knight")) == 0) {
5867 } else if (strcmp(name, _("Promote")) == 0) {
5869 } else if (strcmp(name, _("Defer")) == 0) {
5872 promoChar = ToLower(name[0]);
5875 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5877 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5878 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5883 void ErrorCallback(w, client_data, call_data)
5885 XtPointer client_data, call_data;
5888 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5890 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5896 if (!errorUp) return;
5898 XtPopdown(errorShell);
5899 XtDestroyWidget(errorShell);
5900 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5903 void ErrorPopUp(title, label, modal)
5904 char *title, *label;
5908 Widget dialog, layout;
5912 Dimension bw_width, pw_width;
5913 Dimension pw_height;
5917 XtSetArg(args[i], XtNresizable, True); i++;
5918 XtSetArg(args[i], XtNtitle, title); i++;
5920 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5921 shellWidget, args, i);
5923 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5924 layoutArgs, XtNumber(layoutArgs));
5927 XtSetArg(args[i], XtNlabel, label); i++;
5928 XtSetArg(args[i], XtNborderWidth, 0); i++;
5929 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5932 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5934 XtRealizeWidget(errorShell);
5935 CatchDeleteWindow(errorShell, "ErrorPopDown");
5938 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5939 XtGetValues(boardWidget, args, i);
5941 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5942 XtSetArg(args[i], XtNheight, &pw_height); i++;
5943 XtGetValues(errorShell, args, i);
5946 /* This code seems to tickle an X bug if it is executed too soon
5947 after xboard starts up. The coordinates get transformed as if
5948 the main window was positioned at (0, 0).
5950 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5951 0 - pw_height + squareSize / 3, &x, &y);
5953 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5954 RootWindowOfScreen(XtScreen(boardWidget)),
5955 (bw_width - pw_width) / 2,
5956 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5960 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5963 XtSetArg(args[i], XtNx, x); i++;
5964 XtSetArg(args[i], XtNy, y); i++;
5965 XtSetValues(errorShell, args, i);
5968 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5971 /* Disable all user input other than deleting the window */
5972 static int frozen = 0;
5976 /* Grab by a widget that doesn't accept input */
5977 XtAddGrab(messageWidget, TRUE, FALSE);
5981 /* Undo a FreezeUI */
5984 if (!frozen) return;
5985 XtRemoveGrab(messageWidget);
5989 char *ModeToWidgetName(mode)
5993 case BeginningOfGame:
5994 if (appData.icsActive)
5995 return "menuMode.ICS Client";
5996 else if (appData.noChessProgram ||
5997 *appData.cmailGameName != NULLCHAR)
5998 return "menuMode.Edit Game";
6000 return "menuMode.Machine Black";
6001 case MachinePlaysBlack:
6002 return "menuMode.Machine Black";
6003 case MachinePlaysWhite:
6004 return "menuMode.Machine White";
6006 return "menuMode.Analysis Mode";
6008 return "menuMode.Analyze File";
6009 case TwoMachinesPlay:
6010 return "menuMode.Two Machines";
6012 return "menuMode.Edit Game";
6013 case PlayFromGameFile:
6014 return "menuFile.Load Game";
6016 return "menuMode.Edit Position";
6018 return "menuMode.Training";
6019 case IcsPlayingWhite:
6020 case IcsPlayingBlack:
6024 return "menuMode.ICS Client";
6031 void ModeHighlight()
6034 static int oldPausing = FALSE;
6035 static GameMode oldmode = (GameMode) -1;
6038 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6040 if (pausing != oldPausing) {
6041 oldPausing = pausing;
6043 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6045 XtSetArg(args[0], XtNleftBitmap, None);
6047 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6050 if (appData.showButtonBar) {
6051 /* Always toggle, don't set. Previous code messes up when
6052 invoked while the button is pressed, as releasing it
6053 toggles the state again. */
6056 XtSetArg(args[0], XtNbackground, &oldbg);
6057 XtSetArg(args[1], XtNforeground, &oldfg);
6058 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6060 XtSetArg(args[0], XtNbackground, oldfg);
6061 XtSetArg(args[1], XtNforeground, oldbg);
6063 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6067 wname = ModeToWidgetName(oldmode);
6068 if (wname != NULL) {
6069 XtSetArg(args[0], XtNleftBitmap, None);
6070 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6072 wname = ModeToWidgetName(gameMode);
6073 if (wname != NULL) {
6074 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6075 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6079 /* Maybe all the enables should be handled here, not just this one */
6080 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6081 gameMode == Training || gameMode == PlayFromGameFile);
6086 * Button/menu procedures
6088 void ResetProc(w, event, prms, nprms)
6097 int LoadGamePopUp(f, gameNumber, title)
6102 cmailMsgLoaded = FALSE;
6103 if (gameNumber == 0) {
6104 int error = GameListBuild(f);
6106 DisplayError(_("Cannot build game list"), error);
6107 } else if (!ListEmpty(&gameList) &&
6108 ((ListGame *) gameList.tailPred)->number > 1) {
6109 GameListPopUp(f, title);
6115 return LoadGame(f, gameNumber, title, FALSE);
6118 void LoadGameProc(w, event, prms, nprms)
6124 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6127 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6130 void LoadNextGameProc(w, event, prms, nprms)
6139 void LoadPrevGameProc(w, event, prms, nprms)
6148 void ReloadGameProc(w, event, prms, nprms)
6157 void LoadNextPositionProc(w, event, prms, nprms)
6166 void LoadPrevPositionProc(w, event, prms, nprms)
6175 void ReloadPositionProc(w, event, prms, nprms)
6184 void LoadPositionProc(w, event, prms, nprms)
6190 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6193 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6196 void SaveGameProc(w, event, prms, nprms)
6202 FileNamePopUp(_("Save game file name?"),
6203 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6207 void SavePositionProc(w, event, prms, nprms)
6213 FileNamePopUp(_("Save position file name?"),
6214 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6218 void ReloadCmailMsgProc(w, event, prms, nprms)
6224 ReloadCmailMsgEvent(FALSE);
6227 void MailMoveProc(w, event, prms, nprms)
6236 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6237 static char *selected_fen_position=NULL;
6240 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6241 Atom *type_return, XtPointer *value_return,
6242 unsigned long *length_return, int *format_return)
6244 char *selection_tmp;
6246 if (!selected_fen_position) return False; /* should never happen */
6247 if (*target == XA_STRING){
6248 /* note: since no XtSelectionDoneProc was registered, Xt will
6249 * automatically call XtFree on the value returned. So have to
6250 * make a copy of it allocated with XtMalloc */
6251 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6252 strcpy(selection_tmp, selected_fen_position);
6254 *value_return=selection_tmp;
6255 *length_return=strlen(selection_tmp);
6256 *type_return=XA_STRING;
6257 *format_return = 8; /* bits per byte */
6264 /* note: when called from menu all parameters are NULL, so no clue what the
6265 * Widget which was clicked on was, or what the click event was
6267 void CopyPositionProc(w, event, prms, nprms)
6275 if (selected_fen_position) free(selected_fen_position);
6276 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6277 if (!selected_fen_position) return;
6278 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6280 SendPositionSelection,
6281 NULL/* lose_ownership_proc */ ,
6282 NULL/* transfer_done_proc */);
6284 free(selected_fen_position);
6285 selected_fen_position=NULL;
6289 /* function called when the data to Paste is ready */
6291 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6292 Atom *type, XtPointer value, unsigned long *len, int *format)
6295 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6296 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6297 EditPositionPasteFEN(fenstr);
6301 /* called when Paste Position button is pressed,
6302 * all parameters will be NULL */
6303 void PastePositionProc(w, event, prms, nprms)
6309 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6310 /* (XtSelectionCallbackProc) */ PastePositionCB,
6311 NULL, /* client_data passed to PastePositionCB */
6313 /* better to use the time field from the event that triggered the
6314 * call to this function, but that isn't trivial to get
6322 SendGameSelection(Widget w, Atom *selection, Atom *target,
6323 Atom *type_return, XtPointer *value_return,
6324 unsigned long *length_return, int *format_return)
6326 char *selection_tmp;
6328 if (*target == XA_STRING){
6329 FILE* f = fopen(gameCopyFilename, "r");
6332 if (f == NULL) return False;
6336 selection_tmp = XtMalloc(len + 1);
6337 count = fread(selection_tmp, 1, len, f);
6339 XtFree(selection_tmp);
6342 selection_tmp[len] = NULLCHAR;
6343 *value_return = selection_tmp;
6344 *length_return = len;
6345 *type_return = XA_STRING;
6346 *format_return = 8; /* bits per byte */
6353 /* note: when called from menu all parameters are NULL, so no clue what the
6354 * Widget which was clicked on was, or what the click event was
6356 void CopyGameProc(w, event, prms, nprms)
6364 ret = SaveGameToFile(gameCopyFilename, FALSE);
6367 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6370 NULL/* lose_ownership_proc */ ,
6371 NULL/* transfer_done_proc */);
6374 /* function called when the data to Paste is ready */
6376 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6377 Atom *type, XtPointer value, unsigned long *len, int *format)
6380 if (value == NULL || *len == 0) {
6381 return; /* nothing had been selected to copy */
6383 f = fopen(gamePasteFilename, "w");
6385 DisplayError(_("Can't open temp file"), errno);
6388 fwrite(value, 1, *len, f);
6391 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6394 /* called when Paste Game button is pressed,
6395 * all parameters will be NULL */
6396 void PasteGameProc(w, event, prms, nprms)
6402 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6403 /* (XtSelectionCallbackProc) */ PasteGameCB,
6404 NULL, /* client_data passed to PasteGameCB */
6406 /* better to use the time field from the event that triggered the
6407 * call to this function, but that isn't trivial to get
6417 SaveGameProc(NULL, NULL, NULL, NULL);
6421 void QuitProc(w, event, prms, nprms)
6430 void PauseProc(w, event, prms, nprms)
6440 void MachineBlackProc(w, event, prms, nprms)
6446 MachineBlackEvent();
6449 void MachineWhiteProc(w, event, prms, nprms)
6455 MachineWhiteEvent();
6458 void AnalyzeModeProc(w, event, prms, nprms)
6466 if (!first.analysisSupport) {
6467 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6468 DisplayError(buf, 0);
6471 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6472 if (appData.icsActive) {
6473 if (gameMode != IcsObserving) {
6474 sprintf(buf,_("You are not observing a game"));
6475 DisplayError(buf, 0);
6477 if (appData.icsEngineAnalyze) {
6478 if (appData.debugMode)
6479 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6485 /* if enable, use want disable icsEngineAnalyze */
6486 if (appData.icsEngineAnalyze) {
6491 appData.icsEngineAnalyze = TRUE;
6492 if (appData.debugMode)
6493 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6495 if (!appData.showThinking)
6496 ShowThinkingProc(w,event,prms,nprms);
6501 void AnalyzeFileProc(w, event, prms, nprms)
6507 if (!first.analysisSupport) {
6509 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6510 DisplayError(buf, 0);
6515 if (!appData.showThinking)
6516 ShowThinkingProc(w,event,prms,nprms);
6519 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6520 AnalysisPeriodicEvent(1);
6523 void TwoMachinesProc(w, event, prms, nprms)
6532 void IcsClientProc(w, event, prms, nprms)
6541 void EditGameProc(w, event, prms, nprms)
6550 void EditPositionProc(w, event, prms, nprms)
6556 EditPositionEvent();
6559 void TrainingProc(w, event, prms, nprms)
6568 void EditCommentProc(w, event, prms, nprms)
6575 EditCommentPopDown();
6581 void IcsInputBoxProc(w, event, prms, nprms)
6587 if (ICSInputBoxUp) {
6588 ICSInputBoxPopDown();
6594 void AcceptProc(w, event, prms, nprms)
6603 void DeclineProc(w, event, prms, nprms)
6612 void RematchProc(w, event, prms, nprms)
6621 void CallFlagProc(w, event, prms, nprms)
6630 void DrawProc(w, event, prms, nprms)
6639 void AbortProc(w, event, prms, nprms)
6648 void AdjournProc(w, event, prms, nprms)
6657 void ResignProc(w, event, prms, nprms)
6666 void AdjuWhiteProc(w, event, prms, nprms)
6672 UserAdjudicationEvent(+1);
6675 void AdjuBlackProc(w, event, prms, nprms)
6681 UserAdjudicationEvent(-1);
6684 void AdjuDrawProc(w, event, prms, nprms)
6690 UserAdjudicationEvent(0);
6693 void EnterKeyProc(w, event, prms, nprms)
6699 if (ICSInputBoxUp == True)
6703 void StopObservingProc(w, event, prms, nprms)
6709 StopObservingEvent();
6712 void StopExaminingProc(w, event, prms, nprms)
6718 StopExaminingEvent();
6722 void ForwardProc(w, event, prms, nprms)
6732 void BackwardProc(w, event, prms, nprms)
6741 void ToStartProc(w, event, prms, nprms)
6750 void ToEndProc(w, event, prms, nprms)
6759 void RevertProc(w, event, prms, nprms)
6768 void TruncateGameProc(w, event, prms, nprms)
6774 TruncateGameEvent();
6776 void RetractMoveProc(w, event, prms, nprms)
6785 void MoveNowProc(w, event, prms, nprms)
6795 void AlwaysQueenProc(w, event, prms, nprms)
6803 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6805 if (appData.alwaysPromoteToQueen) {
6806 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6808 XtSetArg(args[0], XtNleftBitmap, None);
6810 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6814 void AnimateDraggingProc(w, event, prms, nprms)
6822 appData.animateDragging = !appData.animateDragging;
6824 if (appData.animateDragging) {
6825 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6828 XtSetArg(args[0], XtNleftBitmap, None);
6830 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6834 void AnimateMovingProc(w, event, prms, nprms)
6842 appData.animate = !appData.animate;
6844 if (appData.animate) {
6845 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6848 XtSetArg(args[0], XtNleftBitmap, None);
6850 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6854 void AutocommProc(w, event, prms, nprms)
6862 appData.autoComment = !appData.autoComment;
6864 if (appData.autoComment) {
6865 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6867 XtSetArg(args[0], XtNleftBitmap, None);
6869 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6874 void AutoflagProc(w, event, prms, nprms)
6882 appData.autoCallFlag = !appData.autoCallFlag;
6884 if (appData.autoCallFlag) {
6885 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6887 XtSetArg(args[0], XtNleftBitmap, None);
6889 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6893 void AutoflipProc(w, event, prms, nprms)
6901 appData.autoFlipView = !appData.autoFlipView;
6903 if (appData.autoFlipView) {
6904 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6906 XtSetArg(args[0], XtNleftBitmap, None);
6908 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6912 void AutobsProc(w, event, prms, nprms)
6920 appData.autoObserve = !appData.autoObserve;
6922 if (appData.autoObserve) {
6923 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6925 XtSetArg(args[0], XtNleftBitmap, None);
6927 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6931 void AutoraiseProc(w, event, prms, nprms)
6939 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6941 if (appData.autoRaiseBoard) {
6942 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6944 XtSetArg(args[0], XtNleftBitmap, None);
6946 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6950 void AutosaveProc(w, event, prms, nprms)
6958 appData.autoSaveGames = !appData.autoSaveGames;
6960 if (appData.autoSaveGames) {
6961 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6963 XtSetArg(args[0], XtNleftBitmap, None);
6965 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6969 void BlindfoldProc(w, event, prms, nprms)
6977 appData.blindfold = !appData.blindfold;
6979 if (appData.blindfold) {
6980 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6982 XtSetArg(args[0], XtNleftBitmap, None);
6984 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6987 DrawPosition(True, NULL);
6990 void TestLegalityProc(w, event, prms, nprms)
6998 appData.testLegality = !appData.testLegality;
7000 if (appData.testLegality) {
7001 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7003 XtSetArg(args[0], XtNleftBitmap, None);
7005 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7010 void FlashMovesProc(w, event, prms, nprms)
7018 if (appData.flashCount == 0) {
7019 appData.flashCount = 3;
7021 appData.flashCount = -appData.flashCount;
7024 if (appData.flashCount > 0) {
7025 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7027 XtSetArg(args[0], XtNleftBitmap, None);
7029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7033 void FlipViewProc(w, event, prms, nprms)
7039 flipView = !flipView;
7040 DrawPosition(True, NULL);
7043 void GetMoveListProc(w, event, prms, nprms)
7051 appData.getMoveList = !appData.getMoveList;
7053 if (appData.getMoveList) {
7054 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7057 XtSetArg(args[0], XtNleftBitmap, None);
7059 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7064 void HighlightDraggingProc(w, event, prms, nprms)
7072 appData.highlightDragging = !appData.highlightDragging;
7074 if (appData.highlightDragging) {
7075 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7077 XtSetArg(args[0], XtNleftBitmap, None);
7079 XtSetValues(XtNameToWidget(menuBarWidget,
7080 "menuOptions.Highlight Dragging"), args, 1);
7084 void HighlightLastMoveProc(w, event, prms, nprms)
7092 appData.highlightLastMove = !appData.highlightLastMove;
7094 if (appData.highlightLastMove) {
7095 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7097 XtSetArg(args[0], XtNleftBitmap, None);
7099 XtSetValues(XtNameToWidget(menuBarWidget,
7100 "menuOptions.Highlight Last Move"), args, 1);
7103 void IcsAlarmProc(w, event, prms, nprms)
7111 appData.icsAlarm = !appData.icsAlarm;
7113 if (appData.icsAlarm) {
7114 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7116 XtSetArg(args[0], XtNleftBitmap, None);
7118 XtSetValues(XtNameToWidget(menuBarWidget,
7119 "menuOptions.ICS Alarm"), args, 1);
7122 void MoveSoundProc(w, event, prms, nprms)
7130 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7132 if (appData.ringBellAfterMoves) {
7133 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7135 XtSetArg(args[0], XtNleftBitmap, None);
7137 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7142 void OldSaveStyleProc(w, event, prms, nprms)
7150 appData.oldSaveStyle = !appData.oldSaveStyle;
7152 if (appData.oldSaveStyle) {
7153 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7155 XtSetArg(args[0], XtNleftBitmap, None);
7157 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7161 void PeriodicUpdatesProc(w, event, prms, nprms)
7169 PeriodicUpdatesEvent(!appData.periodicUpdates);
7171 if (appData.periodicUpdates) {
7172 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7174 XtSetArg(args[0], XtNleftBitmap, None);
7176 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7180 void PonderNextMoveProc(w, event, prms, nprms)
7188 PonderNextMoveEvent(!appData.ponderNextMove);
7190 if (appData.ponderNextMove) {
7191 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7193 XtSetArg(args[0], XtNleftBitmap, None);
7195 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7199 void PopupExitMessageProc(w, event, prms, nprms)
7207 appData.popupExitMessage = !appData.popupExitMessage;
7209 if (appData.popupExitMessage) {
7210 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7212 XtSetArg(args[0], XtNleftBitmap, None);
7214 XtSetValues(XtNameToWidget(menuBarWidget,
7215 "menuOptions.Popup Exit Message"), args, 1);
7218 void PopupMoveErrorsProc(w, event, prms, nprms)
7226 appData.popupMoveErrors = !appData.popupMoveErrors;
7228 if (appData.popupMoveErrors) {
7229 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7231 XtSetArg(args[0], XtNleftBitmap, None);
7233 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7237 void PremoveProc(w, event, prms, nprms)
7245 appData.premove = !appData.premove;
7247 if (appData.premove) {
7248 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7250 XtSetArg(args[0], XtNleftBitmap, None);
7252 XtSetValues(XtNameToWidget(menuBarWidget,
7253 "menuOptions.Premove"), args, 1);
7256 void QuietPlayProc(w, event, prms, nprms)
7264 appData.quietPlay = !appData.quietPlay;
7266 if (appData.quietPlay) {
7267 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7269 XtSetArg(args[0], XtNleftBitmap, None);
7271 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7275 void ShowCoordsProc(w, event, prms, nprms)
7283 appData.showCoords = !appData.showCoords;
7285 if (appData.showCoords) {
7286 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7288 XtSetArg(args[0], XtNleftBitmap, None);
7290 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7293 DrawPosition(True, NULL);
7296 void ShowThinkingProc(w, event, prms, nprms)
7304 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7305 ShowThinkingEvent();
7308 void HideThinkingProc(w, event, prms, nprms)
7316 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7317 ShowThinkingEvent();
7319 if (appData.hideThinkingFromHuman) {
7320 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7322 XtSetArg(args[0], XtNleftBitmap, None);
7324 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7328 void InfoProc(w, event, prms, nprms)
7335 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7340 void ManProc(w, event, prms, nprms)
7348 if (nprms && *nprms > 0)
7352 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7356 void HintProc(w, event, prms, nprms)
7365 void BookProc(w, event, prms, nprms)
7374 void AboutProc(w, event, prms, nprms)
7382 char *zippy = " (with Zippy code)";
7386 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7387 programVersion, zippy,
7388 "Copyright 1991 Digital Equipment Corporation",
7389 "Enhancements Copyright 1992-2009 Free Software Foundation",
7390 "Enhancements Copyright 2005 Alessandro Scotti",
7391 PACKAGE, " is free software and carries NO WARRANTY;",
7392 "see the file COPYING for more information.");
7393 ErrorPopUp(_("About XBoard"), buf, FALSE);
7396 void DebugProc(w, event, prms, nprms)
7402 appData.debugMode = !appData.debugMode;
7405 void AboutGameProc(w, event, prms, nprms)
7414 void NothingProc(w, event, prms, nprms)
7423 void Iconify(w, event, prms, nprms)
7432 XtSetArg(args[0], XtNiconic, True);
7433 XtSetValues(shellWidget, args, 1);
7436 void DisplayMessage(message, extMessage)
7437 char *message, *extMessage;
7439 /* display a message in the message widget */
7448 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7453 message = extMessage;
7457 /* need to test if messageWidget already exists, since this function
7458 can also be called during the startup, if for example a Xresource
7459 is not set up correctly */
7462 XtSetArg(arg, XtNlabel, message);
7463 XtSetValues(messageWidget, &arg, 1);
7469 void DisplayTitle(text)
7474 char title[MSG_SIZ];
7477 if (text == NULL) text = "";
7479 if (appData.titleInWindow) {
7481 XtSetArg(args[i], XtNlabel, text); i++;
7482 XtSetValues(titleWidget, args, i);
7485 if (*text != NULLCHAR) {
7487 strcpy(title, text);
7488 } else if (appData.icsActive) {
7489 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7490 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7491 } else if (appData.cmailGameName[0] != NULLCHAR) {
7492 snprintf(icon, sizeof(icon), "%s", "CMail");
7493 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7495 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7496 } else if (gameInfo.variant == VariantGothic) {
7497 strcpy(icon, programName);
7498 strcpy(title, GOTHIC);
7501 } else if (gameInfo.variant == VariantFalcon) {
7502 strcpy(icon, programName);
7503 strcpy(title, FALCON);
7505 } else if (appData.noChessProgram) {
7506 strcpy(icon, programName);
7507 strcpy(title, programName);
7509 strcpy(icon, first.tidy);
7510 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7513 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7514 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7515 XtSetValues(shellWidget, args, i);
7519 void DisplayError(message, error)
7526 if (appData.debugMode || appData.matchMode) {
7527 fprintf(stderr, "%s: %s\n", programName, message);
7530 if (appData.debugMode || appData.matchMode) {
7531 fprintf(stderr, "%s: %s: %s\n",
7532 programName, message, strerror(error));
7534 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7537 ErrorPopUp(_("Error"), message, FALSE);
7541 void DisplayMoveError(message)
7546 DrawPosition(FALSE, NULL);
7547 if (appData.debugMode || appData.matchMode) {
7548 fprintf(stderr, "%s: %s\n", programName, message);
7550 if (appData.popupMoveErrors) {
7551 ErrorPopUp(_("Error"), message, FALSE);
7553 DisplayMessage(message, "");
7558 void DisplayFatalError(message, error, status)
7564 errorExitStatus = status;
7566 fprintf(stderr, "%s: %s\n", programName, message);
7568 fprintf(stderr, "%s: %s: %s\n",
7569 programName, message, strerror(error));
7570 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7573 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7574 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7580 void DisplayInformation(message)
7584 ErrorPopUp(_("Information"), message, TRUE);
7587 void DisplayNote(message)
7591 ErrorPopUp(_("Note"), message, FALSE);
7595 NullXErrorCheck(dpy, error_event)
7597 XErrorEvent *error_event;
7602 void DisplayIcsInteractionTitle(message)
7605 if (oldICSInteractionTitle == NULL) {
7606 /* Magic to find the old window title, adapted from vim */
7607 char *wina = getenv("WINDOWID");
7609 Window win = (Window) atoi(wina);
7610 Window root, parent, *children;
7611 unsigned int nchildren;
7612 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7614 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7615 if (!XQueryTree(xDisplay, win, &root, &parent,
7616 &children, &nchildren)) break;
7617 if (children) XFree((void *)children);
7618 if (parent == root || parent == 0) break;
7621 XSetErrorHandler(oldHandler);
7623 if (oldICSInteractionTitle == NULL) {
7624 oldICSInteractionTitle = "xterm";
7627 printf("\033]0;%s\007", message);
7631 char pendingReplyPrefix[MSG_SIZ];
7632 ProcRef pendingReplyPR;
7634 void AskQuestionProc(w, event, prms, nprms)
7641 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7645 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7648 void AskQuestionPopDown()
7650 if (!askQuestionUp) return;
7651 XtPopdown(askQuestionShell);
7652 XtDestroyWidget(askQuestionShell);
7653 askQuestionUp = False;
7656 void AskQuestionReplyAction(w, event, prms, nprms)
7666 reply = XawDialogGetValueString(w = XtParent(w));
7667 strcpy(buf, pendingReplyPrefix);
7668 if (*buf) strcat(buf, " ");
7671 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7672 AskQuestionPopDown();
7674 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7677 void AskQuestionCallback(w, client_data, call_data)
7679 XtPointer client_data, call_data;
7684 XtSetArg(args[0], XtNlabel, &name);
7685 XtGetValues(w, args, 1);
7687 if (strcmp(name, _("cancel")) == 0) {
7688 AskQuestionPopDown();
7690 AskQuestionReplyAction(w, NULL, NULL, NULL);
7694 void AskQuestion(title, question, replyPrefix, pr)
7695 char *title, *question, *replyPrefix;
7699 Widget popup, layout, dialog, edit;
7705 strcpy(pendingReplyPrefix, replyPrefix);
7706 pendingReplyPR = pr;
7709 XtSetArg(args[i], XtNresizable, True); i++;
7710 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7711 askQuestionShell = popup =
7712 XtCreatePopupShell(title, transientShellWidgetClass,
7713 shellWidget, args, i);
7716 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7717 layoutArgs, XtNumber(layoutArgs));
7720 XtSetArg(args[i], XtNlabel, question); i++;
7721 XtSetArg(args[i], XtNvalue, ""); i++;
7722 XtSetArg(args[i], XtNborderWidth, 0); i++;
7723 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7726 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7727 (XtPointer) dialog);
7728 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7729 (XtPointer) dialog);
7731 XtRealizeWidget(popup);
7732 CatchDeleteWindow(popup, "AskQuestionPopDown");
7734 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7735 &x, &y, &win_x, &win_y, &mask);
7737 XtSetArg(args[0], XtNx, x - 10);
7738 XtSetArg(args[1], XtNy, y - 30);
7739 XtSetValues(popup, args, 2);
7741 XtPopup(popup, XtGrabExclusive);
7742 askQuestionUp = True;
7744 edit = XtNameToWidget(dialog, "*value");
7745 XtSetKeyboardFocus(popup, edit);
7753 if (*name == NULLCHAR) {
7755 } else if (strcmp(name, "$") == 0) {
7756 putc(BELLCHAR, stderr);
7759 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7767 PlaySound(appData.soundMove);
7773 PlaySound(appData.soundIcsWin);
7779 PlaySound(appData.soundIcsLoss);
7785 PlaySound(appData.soundIcsDraw);
7789 PlayIcsUnfinishedSound()
7791 PlaySound(appData.soundIcsUnfinished);
7797 PlaySound(appData.soundIcsAlarm);
7803 system("stty echo");
7809 system("stty -echo");
7813 Colorize(cc, continuation)
7818 int count, outCount, error;
7820 if (textColors[(int)cc].bg > 0) {
7821 if (textColors[(int)cc].fg > 0) {
7822 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7823 textColors[(int)cc].fg, textColors[(int)cc].bg);
7825 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7826 textColors[(int)cc].bg);
7829 if (textColors[(int)cc].fg > 0) {
7830 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7831 textColors[(int)cc].fg);
7833 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7836 count = strlen(buf);
7837 outCount = OutputToProcess(NoProc, buf, count, &error);
7838 if (outCount < count) {
7839 DisplayFatalError(_("Error writing to display"), error, 1);
7842 if (continuation) return;
7845 PlaySound(appData.soundShout);
7848 PlaySound(appData.soundSShout);
7851 PlaySound(appData.soundChannel1);
7854 PlaySound(appData.soundChannel);
7857 PlaySound(appData.soundKibitz);
7860 PlaySound(appData.soundTell);
7862 case ColorChallenge:
7863 PlaySound(appData.soundChallenge);
7866 PlaySound(appData.soundRequest);
7869 PlaySound(appData.soundSeek);
7880 return getpwuid(getuid())->pw_name;
7883 static char *ExpandPathName(path)
7886 static char static_buf[2000];
7887 char *d, *s, buf[2000];
7893 while (*s && isspace(*s))
7902 if (*(s+1) == '/') {
7903 strcpy(d, getpwuid(getuid())->pw_dir);
7908 *strchr(buf, '/') = 0;
7909 pwd = getpwnam(buf);
7912 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7916 strcpy(d, pwd->pw_dir);
7917 strcat(d, strchr(s+1, '/'));
7928 static char host_name[MSG_SIZ];
7930 #if HAVE_GETHOSTNAME
7931 gethostname(host_name, MSG_SIZ);
7933 #else /* not HAVE_GETHOSTNAME */
7934 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7935 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7937 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7939 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7940 #endif /* not HAVE_GETHOSTNAME */
7943 XtIntervalId delayedEventTimerXID = 0;
7944 DelayedEventCallback delayedEventCallback = 0;
7949 delayedEventTimerXID = 0;
7950 delayedEventCallback();
7954 ScheduleDelayedEvent(cb, millisec)
7955 DelayedEventCallback cb; long millisec;
7957 if(delayedEventTimerXID && delayedEventCallback == cb)
7958 // [HGM] alive: replace, rather than add or flush identical event
7959 XtRemoveTimeOut(delayedEventTimerXID);
7960 delayedEventCallback = cb;
7961 delayedEventTimerXID =
7962 XtAppAddTimeOut(appContext, millisec,
7963 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7966 DelayedEventCallback
7969 if (delayedEventTimerXID) {
7970 return delayedEventCallback;
7977 CancelDelayedEvent()
7979 if (delayedEventTimerXID) {
7980 XtRemoveTimeOut(delayedEventTimerXID);
7981 delayedEventTimerXID = 0;
7985 XtIntervalId loadGameTimerXID = 0;
7987 int LoadGameTimerRunning()
7989 return loadGameTimerXID != 0;
7992 int StopLoadGameTimer()
7994 if (loadGameTimerXID != 0) {
7995 XtRemoveTimeOut(loadGameTimerXID);
7996 loadGameTimerXID = 0;
8004 LoadGameTimerCallback(arg, id)
8008 loadGameTimerXID = 0;
8013 StartLoadGameTimer(millisec)
8017 XtAppAddTimeOut(appContext, millisec,
8018 (XtTimerCallbackProc) LoadGameTimerCallback,
8022 XtIntervalId analysisClockXID = 0;
8025 AnalysisClockCallback(arg, id)
8029 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8030 || appData.icsEngineAnalyze) { // [DM]
8031 AnalysisPeriodicEvent(0);
8032 StartAnalysisClock();
8037 StartAnalysisClock()
8040 XtAppAddTimeOut(appContext, 2000,
8041 (XtTimerCallbackProc) AnalysisClockCallback,
8045 XtIntervalId clockTimerXID = 0;
8047 int ClockTimerRunning()
8049 return clockTimerXID != 0;
8052 int StopClockTimer()
8054 if (clockTimerXID != 0) {
8055 XtRemoveTimeOut(clockTimerXID);
8064 ClockTimerCallback(arg, id)
8073 StartClockTimer(millisec)
8077 XtAppAddTimeOut(appContext, millisec,
8078 (XtTimerCallbackProc) ClockTimerCallback,
8083 DisplayTimerLabel(w, color, timer, highlight)
8092 /* check for low time warning */
8093 Pixel foregroundOrWarningColor = timerForegroundPixel;
8096 appData.lowTimeWarning &&
8097 (timer / 1000) < appData.icsAlarmTime)
8098 foregroundOrWarningColor = lowTimeWarningColor;
8100 if (appData.clockMode) {
8101 sprintf(buf, "%s: %s", color, TimeString(timer));
8102 XtSetArg(args[0], XtNlabel, buf);
8104 sprintf(buf, "%s ", color);
8105 XtSetArg(args[0], XtNlabel, buf);
8110 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8111 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8113 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8114 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8117 XtSetValues(w, args, 3);
8121 DisplayWhiteClock(timeRemaining, highlight)
8127 if(appData.noGUI) return;
8128 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8129 if (highlight && iconPixmap == bIconPixmap) {
8130 iconPixmap = wIconPixmap;
8131 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8132 XtSetValues(shellWidget, args, 1);
8137 DisplayBlackClock(timeRemaining, highlight)
8143 if(appData.noGUI) return;
8144 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8145 if (highlight && iconPixmap == wIconPixmap) {
8146 iconPixmap = bIconPixmap;
8147 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8148 XtSetValues(shellWidget, args, 1);
8166 int StartChildProcess(cmdLine, dir, pr)
8173 int to_prog[2], from_prog[2];
8177 if (appData.debugMode) {
8178 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8181 /* We do NOT feed the cmdLine to the shell; we just
8182 parse it into blank-separated arguments in the
8183 most simple-minded way possible.
8186 strcpy(buf, cmdLine);
8191 if (p == NULL) break;
8196 SetUpChildIO(to_prog, from_prog);
8199 signal(SIGWINCH, TermSizeSigHandler);
8202 if ((pid = fork()) == 0) {
8204 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8205 close(to_prog[1]); // first close the unused pipe ends
8206 close(from_prog[0]);
8207 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8208 dup2(from_prog[1], 1);
8209 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8210 close(from_prog[1]); // and closing again loses one of the pipes!
8211 if(fileno(stderr) >= 2) // better safe than sorry...
8212 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8214 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8219 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8221 execvp(argv[0], argv);
8223 /* If we get here, exec failed */
8228 /* Parent process */
8230 close(from_prog[1]);
8232 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8235 cp->fdFrom = from_prog[0];
8236 cp->fdTo = to_prog[1];
8241 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8242 static RETSIGTYPE AlarmCallBack(int n)
8248 DestroyChildProcess(pr, signalType)
8252 ChildProc *cp = (ChildProc *) pr;
8254 if (cp->kind != CPReal) return;
8256 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8257 signal(SIGALRM, AlarmCallBack);
8259 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8260 kill(cp->pid, SIGKILL); // kill it forcefully
8261 wait((int *) 0); // and wait again
8265 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8267 /* Process is exiting either because of the kill or because of
8268 a quit command sent by the backend; either way, wait for it to die.
8277 InterruptChildProcess(pr)
8280 ChildProc *cp = (ChildProc *) pr;
8282 if (cp->kind != CPReal) return;
8283 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8286 int OpenTelnet(host, port, pr)
8291 char cmdLine[MSG_SIZ];
8293 if (port[0] == NULLCHAR) {
8294 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8296 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8298 return StartChildProcess(cmdLine, "", pr);
8301 int OpenTCP(host, port, pr)
8307 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8308 #else /* !OMIT_SOCKETS */
8310 struct sockaddr_in sa;
8312 unsigned short uport;
8315 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8319 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8320 sa.sin_family = AF_INET;
8321 sa.sin_addr.s_addr = INADDR_ANY;
8322 uport = (unsigned short) 0;
8323 sa.sin_port = htons(uport);
8324 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8328 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8329 if (!(hp = gethostbyname(host))) {
8331 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8332 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8333 hp->h_addrtype = AF_INET;
8335 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8336 hp->h_addr_list[0] = (char *) malloc(4);
8337 hp->h_addr_list[0][0] = b0;
8338 hp->h_addr_list[0][1] = b1;
8339 hp->h_addr_list[0][2] = b2;
8340 hp->h_addr_list[0][3] = b3;
8345 sa.sin_family = hp->h_addrtype;
8346 uport = (unsigned short) atoi(port);
8347 sa.sin_port = htons(uport);
8348 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8350 if (connect(s, (struct sockaddr *) &sa,
8351 sizeof(struct sockaddr_in)) < 0) {
8355 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8362 #endif /* !OMIT_SOCKETS */
8367 int OpenCommPort(name, pr)
8374 fd = open(name, 2, 0);
8375 if (fd < 0) return errno;
8377 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8387 int OpenLoopback(pr)
8393 SetUpChildIO(to, from);
8395 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8398 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8405 int OpenRcmd(host, user, cmd, pr)
8406 char *host, *user, *cmd;
8409 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8413 #define INPUT_SOURCE_BUF_SIZE 8192
8422 char buf[INPUT_SOURCE_BUF_SIZE];
8427 DoInputCallback(closure, source, xid)
8432 InputSource *is = (InputSource *) closure;
8437 if (is->lineByLine) {
8438 count = read(is->fd, is->unused,
8439 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8441 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8444 is->unused += count;
8446 while (p < is->unused) {
8447 q = memchr(p, '\n', is->unused - p);
8448 if (q == NULL) break;
8450 (is->func)(is, is->closure, p, q - p, 0);
8454 while (p < is->unused) {
8459 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8464 (is->func)(is, is->closure, is->buf, count, error);
8468 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8475 ChildProc *cp = (ChildProc *) pr;
8477 is = (InputSource *) calloc(1, sizeof(InputSource));
8478 is->lineByLine = lineByLine;
8482 is->fd = fileno(stdin);
8484 is->kind = cp->kind;
8485 is->fd = cp->fdFrom;
8488 is->unused = is->buf;
8491 is->xid = XtAppAddInput(appContext, is->fd,
8492 (XtPointer) (XtInputReadMask),
8493 (XtInputCallbackProc) DoInputCallback,
8495 is->closure = closure;
8496 return (InputSourceRef) is;
8500 RemoveInputSource(isr)
8503 InputSource *is = (InputSource *) isr;
8505 if (is->xid == 0) return;
8506 XtRemoveInput(is->xid);
8510 int OutputToProcess(pr, message, count, outError)
8516 static int line = 0;
8517 ChildProc *cp = (ChildProc *) pr;
8522 if (appData.noJoin || !appData.useInternalWrap)
8523 outCount = fwrite(message, 1, count, stdout);
8526 int width = get_term_width();
8527 int len = wrap(NULL, message, count, width, &line);
8528 char *msg = malloc(len);
8532 outCount = fwrite(message, 1, count, stdout);
8535 dbgchk = wrap(msg, message, count, width, &line);
8536 if (dbgchk != len && appData.debugMode)
8537 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
8538 outCount = fwrite(msg, 1, dbgchk, stdout);
8544 outCount = write(cp->fdTo, message, count);
8554 /* Output message to process, with "ms" milliseconds of delay
8555 between each character. This is needed when sending the logon
8556 script to ICC, which for some reason doesn't like the
8557 instantaneous send. */
8558 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8565 ChildProc *cp = (ChildProc *) pr;
8570 r = write(cp->fdTo, message++, 1);
8583 /**** Animation code by Hugh Fisher, DCS, ANU.
8585 Known problem: if a window overlapping the board is
8586 moved away while a piece is being animated underneath,
8587 the newly exposed area won't be updated properly.
8588 I can live with this.
8590 Known problem: if you look carefully at the animation
8591 of pieces in mono mode, they are being drawn as solid
8592 shapes without interior detail while moving. Fixing
8593 this would be a major complication for minimal return.
8596 /* Masks for XPM pieces. Black and white pieces can have
8597 different shapes, but in the interest of retaining my
8598 sanity pieces must have the same outline on both light
8599 and dark squares, and all pieces must use the same
8600 background square colors/images. */
8602 static int xpmDone = 0;
8605 CreateAnimMasks (pieceDepth)
8612 unsigned long plane;
8615 /* Need a bitmap just to get a GC with right depth */
8616 buf = XCreatePixmap(xDisplay, xBoardWindow,
8618 values.foreground = 1;
8619 values.background = 0;
8620 /* Don't use XtGetGC, not read only */
8621 maskGC = XCreateGC(xDisplay, buf,
8622 GCForeground | GCBackground, &values);
8623 XFreePixmap(xDisplay, buf);
8625 buf = XCreatePixmap(xDisplay, xBoardWindow,
8626 squareSize, squareSize, pieceDepth);
8627 values.foreground = XBlackPixel(xDisplay, xScreen);
8628 values.background = XWhitePixel(xDisplay, xScreen);
8629 bufGC = XCreateGC(xDisplay, buf,
8630 GCForeground | GCBackground, &values);
8632 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8633 /* Begin with empty mask */
8634 if(!xpmDone) // [HGM] pieces: keep using existing
8635 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8636 squareSize, squareSize, 1);
8637 XSetFunction(xDisplay, maskGC, GXclear);
8638 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8639 0, 0, squareSize, squareSize);
8641 /* Take a copy of the piece */
8646 XSetFunction(xDisplay, bufGC, GXcopy);
8647 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8649 0, 0, squareSize, squareSize, 0, 0);
8651 /* XOR the background (light) over the piece */
8652 XSetFunction(xDisplay, bufGC, GXxor);
8654 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8655 0, 0, squareSize, squareSize, 0, 0);
8657 XSetForeground(xDisplay, bufGC, lightSquareColor);
8658 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8661 /* We now have an inverted piece image with the background
8662 erased. Construct mask by just selecting all the non-zero
8663 pixels - no need to reconstruct the original image. */
8664 XSetFunction(xDisplay, maskGC, GXor);
8666 /* Might be quicker to download an XImage and create bitmap
8667 data from it rather than this N copies per piece, but it
8668 only takes a fraction of a second and there is a much
8669 longer delay for loading the pieces. */
8670 for (n = 0; n < pieceDepth; n ++) {
8671 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8672 0, 0, squareSize, squareSize,
8678 XFreePixmap(xDisplay, buf);
8679 XFreeGC(xDisplay, bufGC);
8680 XFreeGC(xDisplay, maskGC);
8684 InitAnimState (anim, info)
8686 XWindowAttributes * info;
8691 /* Each buffer is square size, same depth as window */
8692 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8693 squareSize, squareSize, info->depth);
8694 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8695 squareSize, squareSize, info->depth);
8697 /* Create a plain GC for blitting */
8698 mask = GCForeground | GCBackground | GCFunction |
8699 GCPlaneMask | GCGraphicsExposures;
8700 values.foreground = XBlackPixel(xDisplay, xScreen);
8701 values.background = XWhitePixel(xDisplay, xScreen);
8702 values.function = GXcopy;
8703 values.plane_mask = AllPlanes;
8704 values.graphics_exposures = False;
8705 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8707 /* Piece will be copied from an existing context at
8708 the start of each new animation/drag. */
8709 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8711 /* Outline will be a read-only copy of an existing */
8712 anim->outlineGC = None;
8718 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8719 XWindowAttributes info;
8721 if (xpmDone && gameInfo.variant == old) return;
8722 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8723 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8725 InitAnimState(&game, &info);
8726 InitAnimState(&player, &info);
8728 /* For XPM pieces, we need bitmaps to use as masks. */
8730 CreateAnimMasks(info.depth);
8736 static Boolean frameWaiting;
8738 static RETSIGTYPE FrameAlarm (sig)
8741 frameWaiting = False;
8742 /* In case System-V style signals. Needed?? */
8743 signal(SIGALRM, FrameAlarm);
8750 struct itimerval delay;
8752 XSync(xDisplay, False);
8755 frameWaiting = True;
8756 signal(SIGALRM, FrameAlarm);
8757 delay.it_interval.tv_sec =
8758 delay.it_value.tv_sec = time / 1000;
8759 delay.it_interval.tv_usec =
8760 delay.it_value.tv_usec = (time % 1000) * 1000;
8761 setitimer(ITIMER_REAL, &delay, NULL);
8762 while (frameWaiting) pause();
8763 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8764 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8765 setitimer(ITIMER_REAL, &delay, NULL);
8775 XSync(xDisplay, False);
8777 usleep(time * 1000);
8782 /* Convert board position to corner of screen rect and color */
8785 ScreenSquare(column, row, pt, color)
8786 int column; int row; XPoint * pt; int * color;
8789 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8790 pt->y = lineGap + row * (squareSize + lineGap);
8792 pt->x = lineGap + column * (squareSize + lineGap);
8793 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8795 *color = SquareColor(row, column);
8798 /* Convert window coords to square */
8801 BoardSquare(x, y, column, row)
8802 int x; int y; int * column; int * row;
8804 *column = EventToSquare(x, BOARD_WIDTH);
8805 if (flipView && *column >= 0)
8806 *column = BOARD_WIDTH - 1 - *column;
8807 *row = EventToSquare(y, BOARD_HEIGHT);
8808 if (!flipView && *row >= 0)
8809 *row = BOARD_HEIGHT - 1 - *row;
8814 #undef Max /* just in case */
8816 #define Max(a, b) ((a) > (b) ? (a) : (b))
8817 #define Min(a, b) ((a) < (b) ? (a) : (b))
8820 SetRect(rect, x, y, width, height)
8821 XRectangle * rect; int x; int y; int width; int height;
8825 rect->width = width;
8826 rect->height = height;
8829 /* Test if two frames overlap. If they do, return
8830 intersection rect within old and location of
8831 that rect within new. */
8834 Intersect(old, new, size, area, pt)
8835 XPoint * old; XPoint * new;
8836 int size; XRectangle * area; XPoint * pt;
8838 if (old->x > new->x + size || new->x > old->x + size ||
8839 old->y > new->y + size || new->y > old->y + size) {
8842 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8843 size - abs(old->x - new->x), size - abs(old->y - new->y));
8844 pt->x = Max(old->x - new->x, 0);
8845 pt->y = Max(old->y - new->y, 0);
8850 /* For two overlapping frames, return the rect(s)
8851 in the old that do not intersect with the new. */
8854 CalcUpdateRects(old, new, size, update, nUpdates)
8855 XPoint * old; XPoint * new; int size;
8856 XRectangle update[]; int * nUpdates;
8860 /* If old = new (shouldn't happen) then nothing to draw */
8861 if (old->x == new->x && old->y == new->y) {
8865 /* Work out what bits overlap. Since we know the rects
8866 are the same size we don't need a full intersect calc. */
8868 /* Top or bottom edge? */
8869 if (new->y > old->y) {
8870 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8872 } else if (old->y > new->y) {
8873 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8874 size, old->y - new->y);
8877 /* Left or right edge - don't overlap any update calculated above. */
8878 if (new->x > old->x) {
8879 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8880 new->x - old->x, size - abs(new->y - old->y));
8882 } else if (old->x > new->x) {
8883 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8884 old->x - new->x, size - abs(new->y - old->y));
8891 /* Generate a series of frame coords from start->mid->finish.
8892 The movement rate doubles until the half way point is
8893 reached, then halves back down to the final destination,
8894 which gives a nice slow in/out effect. The algorithmn
8895 may seem to generate too many intermediates for short
8896 moves, but remember that the purpose is to attract the
8897 viewers attention to the piece about to be moved and
8898 then to where it ends up. Too few frames would be less
8902 Tween(start, mid, finish, factor, frames, nFrames)
8903 XPoint * start; XPoint * mid;
8904 XPoint * finish; int factor;
8905 XPoint frames[]; int * nFrames;
8907 int fraction, n, count;
8911 /* Slow in, stepping 1/16th, then 1/8th, ... */
8913 for (n = 0; n < factor; n++)
8915 for (n = 0; n < factor; n++) {
8916 frames[count].x = start->x + (mid->x - start->x) / fraction;
8917 frames[count].y = start->y + (mid->y - start->y) / fraction;
8919 fraction = fraction / 2;
8923 frames[count] = *mid;
8926 /* Slow out, stepping 1/2, then 1/4, ... */
8928 for (n = 0; n < factor; n++) {
8929 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8930 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8932 fraction = fraction * 2;
8937 /* Draw a piece on the screen without disturbing what's there */
8940 SelectGCMask(piece, clip, outline, mask)
8941 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8945 /* Bitmap for piece being moved. */
8946 if (appData.monoMode) {
8947 *mask = *pieceToSolid(piece);
8948 } else if (useImages) {
8950 *mask = xpmMask[piece];
8952 *mask = ximMaskPm[piece];
8955 *mask = *pieceToSolid(piece);
8958 /* GC for piece being moved. Square color doesn't matter, but
8959 since it gets modified we make a copy of the original. */
8961 if (appData.monoMode)
8966 if (appData.monoMode)
8971 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8973 /* Outline only used in mono mode and is not modified */
8975 *outline = bwPieceGC;
8977 *outline = wbPieceGC;
8981 OverlayPiece(piece, clip, outline, dest)
8982 ChessSquare piece; GC clip; GC outline; Drawable dest;
8987 /* Draw solid rectangle which will be clipped to shape of piece */
8988 XFillRectangle(xDisplay, dest, clip,
8989 0, 0, squareSize, squareSize);
8990 if (appData.monoMode)
8991 /* Also draw outline in contrasting color for black
8992 on black / white on white cases */
8993 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8994 0, 0, squareSize, squareSize, 0, 0, 1);
8996 /* Copy the piece */
9001 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9003 0, 0, squareSize, squareSize,
9008 /* Animate the movement of a single piece */
9011 BeginAnimation(anim, piece, startColor, start)
9019 /* The old buffer is initialised with the start square (empty) */
9020 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9021 anim->prevFrame = *start;
9023 /* The piece will be drawn using its own bitmap as a matte */
9024 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9025 XSetClipMask(xDisplay, anim->pieceGC, mask);
9029 AnimationFrame(anim, frame, piece)
9034 XRectangle updates[4];
9039 /* Save what we are about to draw into the new buffer */
9040 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9041 frame->x, frame->y, squareSize, squareSize,
9044 /* Erase bits of the previous frame */
9045 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9046 /* Where the new frame overlapped the previous,
9047 the contents in newBuf are wrong. */
9048 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9049 overlap.x, overlap.y,
9050 overlap.width, overlap.height,
9052 /* Repaint the areas in the old that don't overlap new */
9053 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9054 for (i = 0; i < count; i++)
9055 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9056 updates[i].x - anim->prevFrame.x,
9057 updates[i].y - anim->prevFrame.y,
9058 updates[i].width, updates[i].height,
9059 updates[i].x, updates[i].y);
9061 /* Easy when no overlap */
9062 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9063 0, 0, squareSize, squareSize,
9064 anim->prevFrame.x, anim->prevFrame.y);
9067 /* Save this frame for next time round */
9068 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9069 0, 0, squareSize, squareSize,
9071 anim->prevFrame = *frame;
9073 /* Draw piece over original screen contents, not current,
9074 and copy entire rect. Wipes out overlapping piece images. */
9075 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9076 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9077 0, 0, squareSize, squareSize,
9078 frame->x, frame->y);
9082 EndAnimation (anim, finish)
9086 XRectangle updates[4];
9091 /* The main code will redraw the final square, so we
9092 only need to erase the bits that don't overlap. */
9093 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9094 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9095 for (i = 0; i < count; i++)
9096 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9097 updates[i].x - anim->prevFrame.x,
9098 updates[i].y - anim->prevFrame.y,
9099 updates[i].width, updates[i].height,
9100 updates[i].x, updates[i].y);
9102 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9103 0, 0, squareSize, squareSize,
9104 anim->prevFrame.x, anim->prevFrame.y);
9109 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9111 ChessSquare piece; int startColor;
9112 XPoint * start; XPoint * finish;
9113 XPoint frames[]; int nFrames;
9117 BeginAnimation(anim, piece, startColor, start);
9118 for (n = 0; n < nFrames; n++) {
9119 AnimationFrame(anim, &(frames[n]), piece);
9120 FrameDelay(appData.animSpeed);
9122 EndAnimation(anim, finish);
9125 /* Main control logic for deciding what to animate and how */
9128 AnimateMove(board, fromX, fromY, toX, toY)
9137 XPoint start, finish, mid;
9138 XPoint frames[kFactor * 2 + 1];
9139 int nFrames, startColor, endColor;
9141 /* Are we animating? */
9142 if (!appData.animate || appData.blindfold)
9145 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9146 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9147 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9149 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9150 piece = board[fromY][fromX];
9151 if (piece >= EmptySquare) return;
9156 hop = (piece == WhiteKnight || piece == BlackKnight);
9159 if (appData.debugMode) {
9160 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9161 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9162 piece, fromX, fromY, toX, toY); }
9164 ScreenSquare(fromX, fromY, &start, &startColor);
9165 ScreenSquare(toX, toY, &finish, &endColor);
9168 /* Knight: make diagonal movement then straight */
9169 if (abs(toY - fromY) < abs(toX - fromX)) {
9170 mid.x = start.x + (finish.x - start.x) / 2;
9174 mid.y = start.y + (finish.y - start.y) / 2;
9177 mid.x = start.x + (finish.x - start.x) / 2;
9178 mid.y = start.y + (finish.y - start.y) / 2;
9181 /* Don't use as many frames for very short moves */
9182 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9183 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9185 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9186 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9188 /* Be sure end square is redrawn */
9189 damage[toY][toX] = True;
9193 DragPieceBegin(x, y)
9196 int boardX, boardY, color;
9199 /* Are we animating? */
9200 if (!appData.animateDragging || appData.blindfold)
9203 /* Figure out which square we start in and the
9204 mouse position relative to top left corner. */
9205 BoardSquare(x, y, &boardX, &boardY);
9206 player.startBoardX = boardX;
9207 player.startBoardY = boardY;
9208 ScreenSquare(boardX, boardY, &corner, &color);
9209 player.startSquare = corner;
9210 player.startColor = color;
9211 /* As soon as we start dragging, the piece will jump slightly to
9212 be centered over the mouse pointer. */
9213 player.mouseDelta.x = squareSize/2;
9214 player.mouseDelta.y = squareSize/2;
9215 /* Initialise animation */
9216 player.dragPiece = PieceForSquare(boardX, boardY);
9218 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9219 player.dragActive = True;
9220 BeginAnimation(&player, player.dragPiece, color, &corner);
9221 /* Mark this square as needing to be redrawn. Note that
9222 we don't remove the piece though, since logically (ie
9223 as seen by opponent) the move hasn't been made yet. */
9224 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9225 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9226 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9227 corner.x, corner.y, squareSize, squareSize,
9228 0, 0); // [HGM] zh: unstack in stead of grab
9229 damage[boardY][boardX] = True;
9231 player.dragActive = False;
9241 /* Are we animating? */
9242 if (!appData.animateDragging || appData.blindfold)
9246 if (! player.dragActive)
9248 /* Move piece, maintaining same relative position
9249 of mouse within square */
9250 corner.x = x - player.mouseDelta.x;
9251 corner.y = y - player.mouseDelta.y;
9252 AnimationFrame(&player, &corner, player.dragPiece);
9254 if (appData.highlightDragging) {
9256 BoardSquare(x, y, &boardX, &boardY);
9257 SetHighlights(fromX, fromY, boardX, boardY);
9266 int boardX, boardY, color;
9269 /* Are we animating? */
9270 if (!appData.animateDragging || appData.blindfold)
9274 if (! player.dragActive)
9276 /* Last frame in sequence is square piece is
9277 placed on, which may not match mouse exactly. */
9278 BoardSquare(x, y, &boardX, &boardY);
9279 ScreenSquare(boardX, boardY, &corner, &color);
9280 EndAnimation(&player, &corner);
9282 /* Be sure end square is redrawn */
9283 damage[boardY][boardX] = True;
9285 /* This prevents weird things happening with fast successive
9286 clicks which on my Sun at least can cause motion events
9287 without corresponding press/release. */
9288 player.dragActive = False;
9291 /* Handle expose event while piece being dragged */
9296 if (!player.dragActive || appData.blindfold)
9299 /* What we're doing: logically, the move hasn't been made yet,
9300 so the piece is still in it's original square. But visually
9301 it's being dragged around the board. So we erase the square
9302 that the piece is on and draw it at the last known drag point. */
9303 BlankSquare(player.startSquare.x, player.startSquare.y,
9304 player.startColor, EmptySquare, xBoardWindow);
9305 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9306 damage[player.startBoardY][player.startBoardX] = TRUE;
9310 SetProgramStats( FrontEndProgramStats * stats )
9313 // [HGM] done, but perhaps backend should call this directly?
9314 EngineOutputUpdate( stats );
9317 #include <sys/ioctl.h>
9318 int get_term_width()
9320 int fd, default_width;
9323 default_width = 79; // this is FICS default anyway...
9325 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9327 if (!ioctl(fd, TIOCGSIZE, &win))
9328 default_width = win.ts_cols;
9329 #elif defined(TIOCGWINSZ)
9331 if (!ioctl(fd, TIOCGWINSZ, &win))
9332 default_width = win.ws_col;
9334 return default_width;
9337 void update_ics_width()
9339 static int old_width = 0;
9340 int new_width = get_term_width();
9342 if (old_width != new_width)
9343 ics_printf("set width %d\n", new_width);
9344 old_width = new_width;
9347 void NotifyFrontendLogin()