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},
1419 { "autoDisplayTags", "autoDisplayTags", XtRBoolean,
1420 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayTags),
1421 XtRImmediate, (XtPointer) True},
1422 { "autoDisplayComment", "autoDisplayComment", XtRBoolean,
1423 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayComment),
1424 XtRImmediate, (XtPointer) True},
1427 XrmOptionDescRec shellOptions[] = {
1428 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1429 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1430 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1431 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1432 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1433 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1434 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1435 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1436 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1437 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1438 { "-initString", "initString", XrmoptionSepArg, NULL },
1439 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1440 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1441 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1442 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1443 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1444 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1445 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1446 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1447 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1448 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1449 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1450 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1451 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1452 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1453 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1454 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1455 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1456 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1457 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1458 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1459 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1460 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1461 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1462 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1463 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1464 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1465 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1466 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1467 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1468 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1469 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1470 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1471 { "-internetChessServerMode", "internetChessServerMode",
1472 XrmoptionSepArg, NULL },
1473 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1474 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1475 { "-internetChessServerHost", "internetChessServerHost",
1476 XrmoptionSepArg, NULL },
1477 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1478 { "-internetChessServerPort", "internetChessServerPort",
1479 XrmoptionSepArg, NULL },
1480 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1481 { "-internetChessServerCommPort", "internetChessServerCommPort",
1482 XrmoptionSepArg, NULL },
1483 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1484 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1485 XrmoptionSepArg, NULL },
1486 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1487 { "-internetChessServerHelper", "internetChessServerHelper",
1488 XrmoptionSepArg, NULL },
1489 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1490 { "-internetChessServerInputBox", "internetChessServerInputBox",
1491 XrmoptionSepArg, NULL },
1492 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1493 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1494 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1495 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1496 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1497 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1498 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1499 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1500 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1501 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1502 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1503 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1504 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1505 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1506 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1507 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1508 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1509 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1510 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1511 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1512 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1513 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1514 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1515 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1516 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1517 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1518 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1519 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1520 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1521 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1522 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1523 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1524 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1525 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1526 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1527 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1528 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1529 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1530 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1531 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1532 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1533 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1534 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1535 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1536 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1537 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1538 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1539 { "-size", "boardSize", XrmoptionSepArg, NULL },
1540 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1541 { "-st", "searchTime", XrmoptionSepArg, NULL },
1542 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1543 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1544 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1545 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1546 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1548 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1549 { "-jail", "showJail", XrmoptionNoArg, "1" },
1550 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1551 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1553 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1554 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1555 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1556 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1557 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1558 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1559 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1560 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1561 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1562 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1563 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1564 { "-font", "font", XrmoptionSepArg, NULL },
1565 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1566 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1567 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1568 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1569 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1570 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1571 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1572 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1573 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1574 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1575 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1576 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1577 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1578 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1579 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1580 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1581 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1582 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1583 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1584 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1586 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1587 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1588 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1590 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1591 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1592 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1593 { "-premove", "premove", XrmoptionSepArg, NULL },
1594 { "-pre", "premove", XrmoptionNoArg, "True" },
1595 { "-xpre", "premove", XrmoptionNoArg, "False" },
1596 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1597 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1598 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1599 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1600 { "-flip", "flipView", XrmoptionNoArg, "True" },
1601 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1602 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1603 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1604 XrmoptionSepArg, NULL },
1605 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1606 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1607 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1608 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1609 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1610 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1611 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1612 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1613 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1614 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1615 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1617 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1618 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1619 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1620 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1621 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1622 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1623 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1624 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1625 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1626 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1627 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1628 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1629 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1630 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1631 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1632 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1633 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1634 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1635 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1636 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1637 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1638 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1639 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1640 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1641 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1642 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1643 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1644 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1645 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1646 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1647 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1649 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1650 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1651 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1652 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1653 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1654 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1655 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1656 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1657 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1658 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1659 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1660 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1661 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1662 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1663 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1664 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1665 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1666 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1667 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1668 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1669 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1670 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1671 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1672 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1673 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1674 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1675 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1676 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1677 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1678 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1679 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1680 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1681 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1682 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1683 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1684 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1685 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1686 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1687 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1688 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1689 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1690 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1691 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1692 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1693 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1694 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1695 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1696 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1697 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1698 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1699 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1700 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1701 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1702 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1703 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1704 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1705 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1706 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1707 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1708 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1709 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1710 { "-variant", "variant", XrmoptionSepArg, NULL },
1711 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1712 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1713 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1714 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1715 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1716 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1717 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1718 /* [AS,HR] New features */
1719 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1720 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1721 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1722 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1723 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1724 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1725 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1726 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1727 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1728 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1729 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1730 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1731 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1732 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1733 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1734 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1735 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1736 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1737 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1738 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1739 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1740 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1741 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1742 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1743 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1744 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1746 /* [HGM,HR] User-selectable board size */
1747 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1748 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1749 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1751 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1752 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1753 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1754 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1755 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1756 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1757 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1758 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1759 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1760 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1761 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1762 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1763 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1764 { "-userName", "userName", XrmoptionSepArg, NULL },
1765 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1766 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1767 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1768 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1769 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1770 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1771 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1772 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1773 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1774 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1775 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1776 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1777 { "-userName", "userName", XrmoptionSepArg, NULL },
1778 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1779 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1780 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1781 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1782 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1783 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1784 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1785 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1786 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1787 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1788 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1789 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1790 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1791 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1792 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1793 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1794 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1795 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1796 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1797 { "-autoDisplayTags", "autoDisplayTags", XrmoptionSepArg, NULL },
1798 { "-autoDisplayComment", "autoDisplayComment", XrmoptionSepArg, NULL },
1801 XtActionsRec boardActions[] = {
1802 { "DrawPosition", DrawPositionProc },
1803 { "HandleUserMove", HandleUserMove },
1804 { "AnimateUserMove", AnimateUserMove },
1805 { "FileNameAction", FileNameAction },
1806 { "AskQuestionProc", AskQuestionProc },
1807 { "AskQuestionReplyAction", AskQuestionReplyAction },
1808 { "PieceMenuPopup", PieceMenuPopup },
1809 { "WhiteClock", WhiteClock },
1810 { "BlackClock", BlackClock },
1811 { "Iconify", Iconify },
1812 { "ResetProc", ResetProc },
1813 { "LoadGameProc", LoadGameProc },
1814 { "LoadNextGameProc", LoadNextGameProc },
1815 { "LoadPrevGameProc", LoadPrevGameProc },
1816 { "LoadSelectedProc", LoadSelectedProc },
1817 { "ReloadGameProc", ReloadGameProc },
1818 { "LoadPositionProc", LoadPositionProc },
1819 { "LoadNextPositionProc", LoadNextPositionProc },
1820 { "LoadPrevPositionProc", LoadPrevPositionProc },
1821 { "ReloadPositionProc", ReloadPositionProc },
1822 { "CopyPositionProc", CopyPositionProc },
1823 { "PastePositionProc", PastePositionProc },
1824 { "CopyGameProc", CopyGameProc },
1825 { "PasteGameProc", PasteGameProc },
1826 { "SaveGameProc", SaveGameProc },
1827 { "SavePositionProc", SavePositionProc },
1828 { "MailMoveProc", MailMoveProc },
1829 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1830 { "QuitProc", QuitProc },
1831 { "MachineWhiteProc", MachineWhiteProc },
1832 { "MachineBlackProc", MachineBlackProc },
1833 { "AnalysisModeProc", AnalyzeModeProc },
1834 { "AnalyzeFileProc", AnalyzeFileProc },
1835 { "TwoMachinesProc", TwoMachinesProc },
1836 { "IcsClientProc", IcsClientProc },
1837 { "EditGameProc", EditGameProc },
1838 { "EditPositionProc", EditPositionProc },
1839 { "TrainingProc", EditPositionProc },
1840 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1841 { "ShowGameListProc", ShowGameListProc },
1842 { "ShowMoveListProc", HistoryShowProc},
1843 { "EditTagsProc", EditCommentProc },
1844 { "EditCommentProc", EditCommentProc },
1845 { "IcsAlarmProc", IcsAlarmProc },
1846 { "IcsInputBoxProc", IcsInputBoxProc },
1847 { "PauseProc", PauseProc },
1848 { "AcceptProc", AcceptProc },
1849 { "DeclineProc", DeclineProc },
1850 { "RematchProc", RematchProc },
1851 { "CallFlagProc", CallFlagProc },
1852 { "DrawProc", DrawProc },
1853 { "AdjournProc", AdjournProc },
1854 { "AbortProc", AbortProc },
1855 { "ResignProc", ResignProc },
1856 { "AdjuWhiteProc", AdjuWhiteProc },
1857 { "AdjuBlackProc", AdjuBlackProc },
1858 { "AdjuDrawProc", AdjuDrawProc },
1859 { "EnterKeyProc", EnterKeyProc },
1860 { "StopObservingProc", StopObservingProc },
1861 { "StopExaminingProc", StopExaminingProc },
1862 { "BackwardProc", BackwardProc },
1863 { "ForwardProc", ForwardProc },
1864 { "ToStartProc", ToStartProc },
1865 { "ToEndProc", ToEndProc },
1866 { "RevertProc", RevertProc },
1867 { "TruncateGameProc", TruncateGameProc },
1868 { "MoveNowProc", MoveNowProc },
1869 { "RetractMoveProc", RetractMoveProc },
1870 { "AlwaysQueenProc", AlwaysQueenProc },
1871 { "AnimateDraggingProc", AnimateDraggingProc },
1872 { "AnimateMovingProc", AnimateMovingProc },
1873 { "AutoflagProc", AutoflagProc },
1874 { "AutoflipProc", AutoflipProc },
1875 { "AutobsProc", AutobsProc },
1876 { "AutoraiseProc", AutoraiseProc },
1877 { "AutosaveProc", AutosaveProc },
1878 { "BlindfoldProc", BlindfoldProc },
1879 { "FlashMovesProc", FlashMovesProc },
1880 { "FlipViewProc", FlipViewProc },
1881 { "GetMoveListProc", GetMoveListProc },
1883 { "HighlightDraggingProc", HighlightDraggingProc },
1885 { "HighlightLastMoveProc", HighlightLastMoveProc },
1886 { "IcsAlarmProc", IcsAlarmProc },
1887 { "MoveSoundProc", MoveSoundProc },
1888 { "OldSaveStyleProc", OldSaveStyleProc },
1889 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1890 { "PonderNextMoveProc", PonderNextMoveProc },
1891 { "PopupExitMessageProc", PopupExitMessageProc },
1892 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1893 { "PremoveProc", PremoveProc },
1894 { "QuietPlayProc", QuietPlayProc },
1895 { "ShowCoordsProc", ShowCoordsProc },
1896 { "ShowThinkingProc", ShowThinkingProc },
1897 { "HideThinkingProc", HideThinkingProc },
1898 { "TestLegalityProc", TestLegalityProc },
1899 { "InfoProc", InfoProc },
1900 { "ManProc", ManProc },
1901 { "HintProc", HintProc },
1902 { "BookProc", BookProc },
1903 { "AboutGameProc", AboutGameProc },
1904 { "AboutProc", AboutProc },
1905 { "DebugProc", DebugProc },
1906 { "NothingProc", NothingProc },
1907 { "CommentPopDown", (XtActionProc) CommentPopDown },
1908 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1909 { "TagsPopDown", (XtActionProc) TagsPopDown },
1910 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1911 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1912 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1913 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1914 { "GameListPopDown", (XtActionProc) GameListPopDown },
1915 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1916 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1917 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1918 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1919 { "EnginePopDown", (XtActionProc) EnginePopDown },
1920 { "UciPopDown", (XtActionProc) UciPopDown },
1921 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1922 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1923 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1926 char globalTranslations[] =
1927 ":<Key>R: ResignProc() \n \
1928 :<Key>r: ResetProc() \n \
1929 :<Key>g: LoadGameProc() \n \
1930 :<Key>N: LoadNextGameProc() \n \
1931 :<Key>P: LoadPrevGameProc() \n \
1932 :<Key>Q: QuitProc() \n \
1933 :<Key>F: ToEndProc() \n \
1934 :<Key>f: ForwardProc() \n \
1935 :<Key>B: ToStartProc() \n \
1936 :<Key>b: BackwardProc() \n \
1937 :<Key>p: PauseProc() \n \
1938 :<Key>d: DrawProc() \n \
1939 :<Key>t: CallFlagProc() \n \
1940 :<Key>i: Iconify() \n \
1941 :<Key>c: Iconify() \n \
1942 :<Key>v: FlipViewProc() \n \
1943 <KeyDown>Control_L: BackwardProc() \n \
1944 <KeyUp>Control_L: ForwardProc() \n \
1945 <KeyDown>Control_R: BackwardProc() \n \
1946 <KeyUp>Control_R: ForwardProc() \n \
1947 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1948 \"Send to chess program:\",,1) \n \
1949 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1950 \"Send to second chess program:\",,2) \n";
1952 char boardTranslations[] =
1953 "<Btn1Down>: HandleUserMove() \n \
1954 <Btn1Up>: HandleUserMove() \n \
1955 <Btn1Motion>: AnimateUserMove() \n \
1956 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1957 PieceMenuPopup(menuB) \n \
1958 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1959 PieceMenuPopup(menuW) \n \
1960 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1961 PieceMenuPopup(menuW) \n \
1962 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1963 PieceMenuPopup(menuB) \n";
1965 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1966 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1968 char ICSInputTranslations[] =
1969 "<Key>Return: EnterKeyProc() \n";
1971 String xboardResources[] = {
1972 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1973 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1974 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1979 /* Max possible square size */
1980 #define MAXSQSIZE 256
1982 static int xpm_avail[MAXSQSIZE];
1984 #ifdef HAVE_DIR_STRUCT
1986 /* Extract piece size from filename */
1988 xpm_getsize(name, len, ext)
1999 if ((p=strchr(name, '.')) == NULL ||
2000 StrCaseCmp(p+1, ext) != 0)
2006 while (*p && isdigit(*p))
2013 /* Setup xpm_avail */
2015 xpm_getavail(dirname, ext)
2023 for (i=0; i<MAXSQSIZE; ++i)
2026 if (appData.debugMode)
2027 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2029 dir = opendir(dirname);
2032 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2033 programName, dirname);
2037 while ((ent=readdir(dir)) != NULL) {
2038 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2039 if (i > 0 && i < MAXSQSIZE)
2049 xpm_print_avail(fp, ext)
2055 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2056 for (i=1; i<MAXSQSIZE; ++i) {
2062 /* Return XPM piecesize closest to size */
2064 xpm_closest_to(dirname, size, ext)
2070 int sm_diff = MAXSQSIZE;
2074 xpm_getavail(dirname, ext);
2076 if (appData.debugMode)
2077 xpm_print_avail(stderr, ext);
2079 for (i=1; i<MAXSQSIZE; ++i) {
2082 diff = (diff<0) ? -diff : diff;
2083 if (diff < sm_diff) {
2091 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2097 #else /* !HAVE_DIR_STRUCT */
2098 /* If we are on a system without a DIR struct, we can't
2099 read the directory, so we can't collect a list of
2100 filenames, etc., so we can't do any size-fitting. */
2102 xpm_closest_to(dirname, size, ext)
2107 fprintf(stderr, _("\
2108 Warning: No DIR structure found on this system --\n\
2109 Unable to autosize for XPM/XIM pieces.\n\
2110 Please report this error to frankm@hiwaay.net.\n\
2111 Include system type & operating system in message.\n"));
2114 #endif /* HAVE_DIR_STRUCT */
2116 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2117 "magenta", "cyan", "white" };
2121 TextColors textColors[(int)NColorClasses];
2123 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2125 parse_color(str, which)
2129 char *p, buf[100], *d;
2132 if (strlen(str) > 99) /* watch bounds on buf */
2137 for (i=0; i<which; ++i) {
2144 /* Could be looking at something like:
2146 .. in which case we want to stop on a comma also */
2147 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2151 return -1; /* Use default for empty field */
2154 if (which == 2 || isdigit(*p))
2157 while (*p && isalpha(*p))
2162 for (i=0; i<8; ++i) {
2163 if (!StrCaseCmp(buf, cnames[i]))
2164 return which? (i+40) : (i+30);
2166 if (!StrCaseCmp(buf, "default")) return -1;
2168 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2173 parse_cpair(cc, str)
2177 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2178 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2183 /* bg and attr are optional */
2184 textColors[(int)cc].bg = parse_color(str, 1);
2185 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2186 textColors[(int)cc].attr = 0;
2192 /* Arrange to catch delete-window events */
2193 Atom wm_delete_window;
2195 CatchDeleteWindow(Widget w, String procname)
2198 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2199 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2200 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2207 XtSetArg(args[0], XtNiconic, False);
2208 XtSetValues(shellWidget, args, 1);
2210 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2214 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2216 #define BoardSize int
2217 void InitDrawingSizes(BoardSize boardSize, int flags)
2218 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2219 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2221 XtGeometryResult gres;
2224 if(!formWidget) return;
2227 * Enable shell resizing.
2229 shellArgs[0].value = (XtArgVal) &w;
2230 shellArgs[1].value = (XtArgVal) &h;
2231 XtGetValues(shellWidget, shellArgs, 2);
2233 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2234 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2235 XtSetValues(shellWidget, &shellArgs[2], 4);
2237 XtSetArg(args[0], XtNdefaultDistance, &sep);
2238 XtGetValues(formWidget, args, 1);
2240 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2241 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2244 XtSetArg(args[0], XtNwidth, boardWidth);
2245 XtSetArg(args[1], XtNheight, boardHeight);
2246 XtSetValues(boardWidget, args, 2);
2248 timerWidth = (boardWidth - sep) / 2;
2249 XtSetArg(args[0], XtNwidth, timerWidth);
2250 XtSetValues(whiteTimerWidget, args, 1);
2251 XtSetValues(blackTimerWidget, args, 1);
2253 XawFormDoLayout(formWidget, False);
2255 if (appData.titleInWindow) {
2257 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2258 XtSetArg(args[i], XtNheight, &h); i++;
2259 XtGetValues(titleWidget, args, i);
2261 w = boardWidth - 2*bor;
2263 XtSetArg(args[0], XtNwidth, &w);
2264 XtGetValues(menuBarWidget, args, 1);
2265 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2268 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2269 if (gres != XtGeometryYes && appData.debugMode) {
2271 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2272 programName, gres, w, h, wr, hr);
2276 XawFormDoLayout(formWidget, True);
2279 * Inhibit shell resizing.
2281 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2282 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2283 shellArgs[4].value = shellArgs[2].value = w;
2284 shellArgs[5].value = shellArgs[3].value = h;
2285 XtSetValues(shellWidget, &shellArgs[0], 6);
2287 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2290 for(i=0; i<4; i++) {
2292 for(p=0; p<=(int)WhiteKing; p++)
2293 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2294 if(gameInfo.variant == VariantShogi) {
2295 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2296 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2297 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2298 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2299 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2302 if(gameInfo.variant == VariantGothic) {
2303 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2307 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2308 for(p=0; p<=(int)WhiteKing; p++)
2309 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2310 if(gameInfo.variant == VariantShogi) {
2311 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2312 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2313 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2314 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2315 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2318 if(gameInfo.variant == VariantGothic) {
2319 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2325 for(i=0; i<2; i++) {
2327 for(p=0; p<=(int)WhiteKing; p++)
2328 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2329 if(gameInfo.variant == VariantShogi) {
2330 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2331 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2332 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2333 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2334 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2337 if(gameInfo.variant == VariantGothic) {
2338 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2349 void EscapeExpand(char *p, char *q)
2350 { // [HGM] initstring: routine to shape up string arguments
2351 while(*p++ = *q++) if(p[-1] == '\\')
2353 case 'n': p[-1] = '\n'; break;
2354 case 'r': p[-1] = '\r'; break;
2355 case 't': p[-1] = '\t'; break;
2356 case '\\': p[-1] = '\\'; break;
2357 case 0: *p = 0; return;
2358 default: p[-1] = q[-1]; break;
2367 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2368 XSetWindowAttributes window_attributes;
2370 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2371 XrmValue vFrom, vTo;
2372 XtGeometryResult gres;
2375 int forceMono = False;
2378 // [HGM] before anything else, expand any indirection files amongst options
2379 char *argvCopy[1000]; // 1000 seems enough
2380 char newArgs[10000]; // holds actual characters
2383 srandom(time(0)); // [HGM] book: make random truly random
2386 for(i=0; i<argc; i++) {
2387 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2388 //fprintf(stderr, "arg %s\n", argv[i]);
2389 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2391 FILE *f = fopen(argv[i]+1, "rb");
2392 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2393 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2394 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2396 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2397 newArgs[k++] = 0; // terminate current arg
2398 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2399 argvCopy[j++] = newArgs + k; // get ready for next
2401 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2415 setbuf(stdout, NULL);
2416 setbuf(stderr, NULL);
2419 programName = strrchr(argv[0], '/');
2420 if (programName == NULL)
2421 programName = argv[0];
2426 XtSetLanguageProc(NULL, NULL, NULL);
2427 bindtextdomain(PACKAGE, LOCALEDIR);
2428 textdomain(PACKAGE);
2432 XtAppInitialize(&appContext, "XBoard", shellOptions,
2433 XtNumber(shellOptions),
2434 &argc, argv, xboardResources, NULL, 0);
2436 { /* left over command line arguments, print out help and exit.
2437 * Use two columns to print help
2439 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2440 programName, argv[1]);
2442 fprintf(stderr, "Recognized options:\n");
2443 for(i = 0; i < XtNumber(shellOptions); i++)
2445 /* print first column */
2446 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2447 (shellOptions[i].argKind == XrmoptionSepArg
2449 /* print second column and end line */
2450 if (++i < XtNumber(shellOptions))
2452 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2453 shellOptions[i].option,
2454 (shellOptions[i].argKind == XrmoptionSepArg
2459 fprintf(stderr, "\n");
2466 if (p == NULL) p = "/tmp";
2467 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2468 gameCopyFilename = (char*) malloc(i);
2469 gamePasteFilename = (char*) malloc(i);
2470 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2471 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2473 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2474 clientResources, XtNumber(clientResources),
2477 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2478 static char buf[MSG_SIZ];
2479 EscapeExpand(buf, appData.initString);
2480 appData.initString = strdup(buf);
2481 EscapeExpand(buf, appData.secondInitString);
2482 appData.secondInitString = strdup(buf);
2483 EscapeExpand(buf, appData.firstComputerString);
2484 appData.firstComputerString = strdup(buf);
2485 EscapeExpand(buf, appData.secondComputerString);
2486 appData.secondComputerString = strdup(buf);
2489 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2492 if (chdir(chessDir) != 0) {
2493 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2499 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2500 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2501 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2502 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2505 setbuf(debugFP, NULL);
2508 /* [HGM,HR] make sure board size is acceptable */
2509 if(appData.NrFiles > BOARD_SIZE ||
2510 appData.NrRanks > BOARD_SIZE )
2511 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2514 /* This feature does not work; animation needs a rewrite */
2515 appData.highlightDragging = FALSE;
2519 xDisplay = XtDisplay(shellWidget);
2520 xScreen = DefaultScreen(xDisplay);
2521 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2523 gameInfo.variant = StringToVariant(appData.variant);
2524 InitPosition(FALSE);
2527 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2529 if (isdigit(appData.boardSize[0])) {
2530 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2531 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2532 &fontPxlSize, &smallLayout, &tinyLayout);
2534 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2535 programName, appData.boardSize);
2539 /* Find some defaults; use the nearest known size */
2540 SizeDefaults *szd, *nearest;
2541 int distance = 99999;
2542 nearest = szd = sizeDefaults;
2543 while (szd->name != NULL) {
2544 if (abs(szd->squareSize - squareSize) < distance) {
2546 distance = abs(szd->squareSize - squareSize);
2547 if (distance == 0) break;
2551 if (i < 2) lineGap = nearest->lineGap;
2552 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2553 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2554 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2555 if (i < 6) smallLayout = nearest->smallLayout;
2556 if (i < 7) tinyLayout = nearest->tinyLayout;
2559 SizeDefaults *szd = sizeDefaults;
2560 if (*appData.boardSize == NULLCHAR) {
2561 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2562 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2565 if (szd->name == NULL) szd--;
2567 while (szd->name != NULL &&
2568 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2569 if (szd->name == NULL) {
2570 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2571 programName, appData.boardSize);
2575 squareSize = szd->squareSize;
2576 lineGap = szd->lineGap;
2577 clockFontPxlSize = szd->clockFontPxlSize;
2578 coordFontPxlSize = szd->coordFontPxlSize;
2579 fontPxlSize = szd->fontPxlSize;
2580 smallLayout = szd->smallLayout;
2581 tinyLayout = szd->tinyLayout;
2584 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2585 if (strlen(appData.pixmapDirectory) > 0) {
2586 p = ExpandPathName(appData.pixmapDirectory);
2588 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2589 appData.pixmapDirectory);
2592 if (appData.debugMode) {
2593 fprintf(stderr, _("\
2594 XBoard square size (hint): %d\n\
2595 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2597 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2598 if (appData.debugMode) {
2599 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2603 /* [HR] height treated separately (hacked) */
2604 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2605 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2606 if (appData.showJail == 1) {
2607 /* Jail on top and bottom */
2608 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2609 XtSetArg(boardArgs[2], XtNheight,
2610 boardHeight + 2*(lineGap + squareSize));
2611 } else if (appData.showJail == 2) {
2613 XtSetArg(boardArgs[1], XtNwidth,
2614 boardWidth + 2*(lineGap + squareSize));
2615 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2618 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2619 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2623 * Determine what fonts to use.
2625 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2626 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2627 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2628 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2629 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2630 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2631 appData.font = FindFont(appData.font, fontPxlSize);
2632 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2633 countFontStruct = XQueryFont(xDisplay, countFontID);
2634 // appData.font = FindFont(appData.font, fontPxlSize);
2636 xdb = XtDatabase(xDisplay);
2637 XrmPutStringResource(&xdb, "*font", appData.font);
2640 * Detect if there are not enough colors available and adapt.
2642 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2643 appData.monoMode = True;
2646 if (!appData.monoMode) {
2647 vFrom.addr = (caddr_t) appData.lightSquareColor;
2648 vFrom.size = strlen(appData.lightSquareColor);
2649 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2650 if (vTo.addr == NULL) {
2651 appData.monoMode = True;
2654 lightSquareColor = *(Pixel *) vTo.addr;
2657 if (!appData.monoMode) {
2658 vFrom.addr = (caddr_t) appData.darkSquareColor;
2659 vFrom.size = strlen(appData.darkSquareColor);
2660 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2661 if (vTo.addr == NULL) {
2662 appData.monoMode = True;
2665 darkSquareColor = *(Pixel *) vTo.addr;
2668 if (!appData.monoMode) {
2669 vFrom.addr = (caddr_t) appData.whitePieceColor;
2670 vFrom.size = strlen(appData.whitePieceColor);
2671 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2672 if (vTo.addr == NULL) {
2673 appData.monoMode = True;
2676 whitePieceColor = *(Pixel *) vTo.addr;
2679 if (!appData.monoMode) {
2680 vFrom.addr = (caddr_t) appData.blackPieceColor;
2681 vFrom.size = strlen(appData.blackPieceColor);
2682 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2683 if (vTo.addr == NULL) {
2684 appData.monoMode = True;
2687 blackPieceColor = *(Pixel *) vTo.addr;
2691 if (!appData.monoMode) {
2692 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2693 vFrom.size = strlen(appData.highlightSquareColor);
2694 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2695 if (vTo.addr == NULL) {
2696 appData.monoMode = True;
2699 highlightSquareColor = *(Pixel *) vTo.addr;
2703 if (!appData.monoMode) {
2704 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2705 vFrom.size = strlen(appData.premoveHighlightColor);
2706 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2707 if (vTo.addr == NULL) {
2708 appData.monoMode = True;
2711 premoveHighlightColor = *(Pixel *) vTo.addr;
2716 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2719 if (appData.bitmapDirectory == NULL ||
2720 appData.bitmapDirectory[0] == NULLCHAR)
2721 appData.bitmapDirectory = DEF_BITMAP_DIR;
2724 if (appData.lowTimeWarning && !appData.monoMode) {
2725 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2726 vFrom.size = strlen(appData.lowTimeWarningColor);
2727 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2728 if (vTo.addr == NULL)
2729 appData.monoMode = True;
2731 lowTimeWarningColor = *(Pixel *) vTo.addr;
2734 if (appData.monoMode && appData.debugMode) {
2735 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2736 (unsigned long) XWhitePixel(xDisplay, xScreen),
2737 (unsigned long) XBlackPixel(xDisplay, xScreen));
2740 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2741 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2742 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2743 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2744 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2745 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2746 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2747 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2748 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2749 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2751 if (appData.colorize) {
2753 _("%s: can't parse color names; disabling colorization\n"),
2756 appData.colorize = FALSE;
2758 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2759 textColors[ColorNone].attr = 0;
2761 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2767 layoutName = "tinyLayout";
2768 } else if (smallLayout) {
2769 layoutName = "smallLayout";
2771 layoutName = "normalLayout";
2773 /* Outer layoutWidget is there only to provide a name for use in
2774 resources that depend on the layout style */
2776 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2777 layoutArgs, XtNumber(layoutArgs));
2779 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2780 formArgs, XtNumber(formArgs));
2781 XtSetArg(args[0], XtNdefaultDistance, &sep);
2782 XtGetValues(formWidget, args, 1);
2785 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2786 XtSetArg(args[0], XtNtop, XtChainTop);
2787 XtSetArg(args[1], XtNbottom, XtChainTop);
2788 XtSetArg(args[2], XtNright, XtChainLeft);
2789 XtSetValues(menuBarWidget, args, 3);
2791 widgetList[j++] = whiteTimerWidget =
2792 XtCreateWidget("whiteTime", labelWidgetClass,
2793 formWidget, timerArgs, XtNumber(timerArgs));
2794 XtSetArg(args[0], XtNfont, clockFontStruct);
2795 XtSetArg(args[1], XtNtop, XtChainTop);
2796 XtSetArg(args[2], XtNbottom, XtChainTop);
2797 XtSetValues(whiteTimerWidget, args, 3);
2799 widgetList[j++] = blackTimerWidget =
2800 XtCreateWidget("blackTime", labelWidgetClass,
2801 formWidget, timerArgs, XtNumber(timerArgs));
2802 XtSetArg(args[0], XtNfont, clockFontStruct);
2803 XtSetArg(args[1], XtNtop, XtChainTop);
2804 XtSetArg(args[2], XtNbottom, XtChainTop);
2805 XtSetValues(blackTimerWidget, args, 3);
2807 if (appData.titleInWindow) {
2808 widgetList[j++] = titleWidget =
2809 XtCreateWidget("title", labelWidgetClass, formWidget,
2810 titleArgs, XtNumber(titleArgs));
2811 XtSetArg(args[0], XtNtop, XtChainTop);
2812 XtSetArg(args[1], XtNbottom, XtChainTop);
2813 XtSetValues(titleWidget, args, 2);
2816 if (appData.showButtonBar) {
2817 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2818 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2819 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2820 XtSetArg(args[2], XtNtop, XtChainTop);
2821 XtSetArg(args[3], XtNbottom, XtChainTop);
2822 XtSetValues(buttonBarWidget, args, 4);
2825 widgetList[j++] = messageWidget =
2826 XtCreateWidget("message", labelWidgetClass, formWidget,
2827 messageArgs, XtNumber(messageArgs));
2828 XtSetArg(args[0], XtNtop, XtChainTop);
2829 XtSetArg(args[1], XtNbottom, XtChainTop);
2830 XtSetValues(messageWidget, args, 2);
2832 widgetList[j++] = boardWidget =
2833 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2834 XtNumber(boardArgs));
2836 XtManageChildren(widgetList, j);
2838 timerWidth = (boardWidth - sep) / 2;
2839 XtSetArg(args[0], XtNwidth, timerWidth);
2840 XtSetValues(whiteTimerWidget, args, 1);
2841 XtSetValues(blackTimerWidget, args, 1);
2843 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2844 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2845 XtGetValues(whiteTimerWidget, args, 2);
2847 if (appData.showButtonBar) {
2848 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2849 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2850 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2854 * formWidget uses these constraints but they are stored
2858 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2859 XtSetValues(menuBarWidget, args, i);
2860 if (appData.titleInWindow) {
2863 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2864 XtSetValues(whiteTimerWidget, args, i);
2866 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2867 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2868 XtSetValues(blackTimerWidget, args, i);
2870 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2871 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2872 XtSetValues(titleWidget, args, i);
2874 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2875 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2876 XtSetValues(messageWidget, args, i);
2877 if (appData.showButtonBar) {
2879 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2880 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2881 XtSetValues(buttonBarWidget, args, i);
2885 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2886 XtSetValues(whiteTimerWidget, args, i);
2888 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2889 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2890 XtSetValues(blackTimerWidget, args, i);
2892 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2893 XtSetValues(titleWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2896 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2897 XtSetValues(messageWidget, args, i);
2898 if (appData.showButtonBar) {
2900 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2901 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2902 XtSetValues(buttonBarWidget, args, i);
2907 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2908 XtSetValues(whiteTimerWidget, args, i);
2910 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2911 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2912 XtSetValues(blackTimerWidget, args, i);
2914 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2915 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2916 XtSetValues(messageWidget, args, i);
2917 if (appData.showButtonBar) {
2919 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2920 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2921 XtSetValues(buttonBarWidget, args, i);
2925 XtSetArg(args[0], XtNfromVert, messageWidget);
2926 XtSetArg(args[1], XtNtop, XtChainTop);
2927 XtSetArg(args[2], XtNbottom, XtChainBottom);
2928 XtSetArg(args[3], XtNleft, XtChainLeft);
2929 XtSetArg(args[4], XtNright, XtChainRight);
2930 XtSetValues(boardWidget, args, 5);
2932 XtRealizeWidget(shellWidget);
2935 * Correct the width of the message and title widgets.
2936 * It is not known why some systems need the extra fudge term.
2937 * The value "2" is probably larger than needed.
2939 XawFormDoLayout(formWidget, False);
2941 #define WIDTH_FUDGE 2
2943 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2944 XtSetArg(args[i], XtNheight, &h); i++;
2945 XtGetValues(messageWidget, args, i);
2946 if (appData.showButtonBar) {
2948 XtSetArg(args[i], XtNwidth, &w); i++;
2949 XtGetValues(buttonBarWidget, args, i);
2950 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2952 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2955 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2956 if (gres != XtGeometryYes && appData.debugMode) {
2957 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2958 programName, gres, w, h, wr, hr);
2961 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2962 /* The size used for the child widget in layout lags one resize behind
2963 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2965 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2966 if (gres != XtGeometryYes && appData.debugMode) {
2967 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2968 programName, gres, w, h, wr, hr);
2971 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2972 XtSetArg(args[1], XtNright, XtChainRight);
2973 XtSetValues(messageWidget, args, 2);
2975 if (appData.titleInWindow) {
2977 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2978 XtSetArg(args[i], XtNheight, &h); i++;
2979 XtGetValues(titleWidget, args, i);
2981 w = boardWidth - 2*bor;
2983 XtSetArg(args[0], XtNwidth, &w);
2984 XtGetValues(menuBarWidget, args, 1);
2985 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2988 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2989 if (gres != XtGeometryYes && appData.debugMode) {
2991 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2992 programName, gres, w, h, wr, hr);
2995 XawFormDoLayout(formWidget, True);
2997 xBoardWindow = XtWindow(boardWidget);
2999 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
3000 // not need to go into InitDrawingSizes().
3004 * Create X checkmark bitmap and initialize option menu checks.
3006 ReadBitmap(&xMarkPixmap, "checkmark.bm",
3007 checkmark_bits, checkmark_width, checkmark_height);
3008 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
3009 if (appData.alwaysPromoteToQueen) {
3010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3013 if (appData.animateDragging) {
3014 XtSetValues(XtNameToWidget(menuBarWidget,
3015 "menuOptions.Animate Dragging"),
3018 if (appData.animate) {
3019 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3022 if (appData.autoComment) {
3023 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3026 if (appData.autoCallFlag) {
3027 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3030 if (appData.autoFlipView) {
3031 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3034 if (appData.autoObserve) {
3035 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3038 if (appData.autoRaiseBoard) {
3039 XtSetValues(XtNameToWidget(menuBarWidget,
3040 "menuOptions.Auto Raise Board"), args, 1);
3042 if (appData.autoSaveGames) {
3043 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3046 if (appData.saveGameFile[0] != NULLCHAR) {
3047 /* Can't turn this off from menu */
3048 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3050 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3054 if (appData.blindfold) {
3055 XtSetValues(XtNameToWidget(menuBarWidget,
3056 "menuOptions.Blindfold"), args, 1);
3058 if (appData.flashCount > 0) {
3059 XtSetValues(XtNameToWidget(menuBarWidget,
3060 "menuOptions.Flash Moves"),
3063 if (appData.getMoveList) {
3064 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3068 if (appData.highlightDragging) {
3069 XtSetValues(XtNameToWidget(menuBarWidget,
3070 "menuOptions.Highlight Dragging"),
3074 if (appData.highlightLastMove) {
3075 XtSetValues(XtNameToWidget(menuBarWidget,
3076 "menuOptions.Highlight Last Move"),
3079 if (appData.icsAlarm) {
3080 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3083 if (appData.ringBellAfterMoves) {
3084 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3087 if (appData.oldSaveStyle) {
3088 XtSetValues(XtNameToWidget(menuBarWidget,
3089 "menuOptions.Old Save Style"), args, 1);
3091 if (appData.periodicUpdates) {
3092 XtSetValues(XtNameToWidget(menuBarWidget,
3093 "menuOptions.Periodic Updates"), args, 1);
3095 if (appData.ponderNextMove) {
3096 XtSetValues(XtNameToWidget(menuBarWidget,
3097 "menuOptions.Ponder Next Move"), args, 1);
3099 if (appData.popupExitMessage) {
3100 XtSetValues(XtNameToWidget(menuBarWidget,
3101 "menuOptions.Popup Exit Message"), args, 1);
3103 if (appData.popupMoveErrors) {
3104 XtSetValues(XtNameToWidget(menuBarWidget,
3105 "menuOptions.Popup Move Errors"), args, 1);
3107 if (appData.premove) {
3108 XtSetValues(XtNameToWidget(menuBarWidget,
3109 "menuOptions.Premove"), args, 1);
3111 if (appData.quietPlay) {
3112 XtSetValues(XtNameToWidget(menuBarWidget,
3113 "menuOptions.Quiet Play"), args, 1);
3115 if (appData.showCoords) {
3116 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3119 if (appData.hideThinkingFromHuman) {
3120 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3123 if (appData.testLegality) {
3124 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3131 ReadBitmap(&wIconPixmap, "icon_white.bm",
3132 icon_white_bits, icon_white_width, icon_white_height);
3133 ReadBitmap(&bIconPixmap, "icon_black.bm",
3134 icon_black_bits, icon_black_width, icon_black_height);
3135 iconPixmap = wIconPixmap;
3137 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3138 XtSetValues(shellWidget, args, i);
3141 * Create a cursor for the board widget.
3143 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3144 XChangeWindowAttributes(xDisplay, xBoardWindow,
3145 CWCursor, &window_attributes);
3148 * Inhibit shell resizing.
3150 shellArgs[0].value = (XtArgVal) &w;
3151 shellArgs[1].value = (XtArgVal) &h;
3152 XtGetValues(shellWidget, shellArgs, 2);
3153 shellArgs[4].value = shellArgs[2].value = w;
3154 shellArgs[5].value = shellArgs[3].value = h;
3155 XtSetValues(shellWidget, &shellArgs[2], 4);
3156 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3157 marginH = h - boardHeight;
3159 CatchDeleteWindow(shellWidget, "QuitProc");
3164 if (appData.bitmapDirectory[0] != NULLCHAR) {
3171 /* Create regular pieces */
3172 if (!useImages) CreatePieces();
3177 if (appData.animate || appData.animateDragging)
3180 XtAugmentTranslations(formWidget,
3181 XtParseTranslationTable(globalTranslations));
3182 XtAugmentTranslations(boardWidget,
3183 XtParseTranslationTable(boardTranslations));
3184 XtAugmentTranslations(whiteTimerWidget,
3185 XtParseTranslationTable(whiteTranslations));
3186 XtAugmentTranslations(blackTimerWidget,
3187 XtParseTranslationTable(blackTranslations));
3189 /* Why is the following needed on some versions of X instead
3190 * of a translation? */
3191 XtAddEventHandler(boardWidget, ExposureMask, False,
3192 (XtEventHandler) EventProc, NULL);
3197 if (errorExitStatus == -1) {
3198 if (appData.icsActive) {
3199 /* We now wait until we see "login:" from the ICS before
3200 sending the logon script (problems with timestamp otherwise) */
3201 /*ICSInitScript();*/
3202 if (appData.icsInputBox) ICSInputBoxPopUp();
3206 signal(SIGWINCH, TermSizeSigHandler);
3208 signal(SIGINT, IntSigHandler);
3209 signal(SIGTERM, IntSigHandler);
3210 if (*appData.cmailGameName != NULLCHAR) {
3211 signal(SIGUSR1, CmailSigHandler);
3214 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3217 XtAppMainLoop(appContext);
3218 if (appData.debugMode) fclose(debugFP); // [DM] debug
3225 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3226 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3228 unlink(gameCopyFilename);
3229 unlink(gamePasteFilename);
3232 RETSIGTYPE TermSizeSigHandler(int sig)
3245 CmailSigHandler(sig)
3251 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3253 /* Activate call-back function CmailSigHandlerCallBack() */
3254 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3256 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3260 CmailSigHandlerCallBack(isr, closure, message, count, error)
3268 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3270 /**** end signal code ****/
3280 f = fopen(appData.icsLogon, "r");
3286 strcat(buf, appData.icsLogon);
3287 f = fopen(buf, "r");
3291 ProcessICSInitScript(f);
3298 EditCommentPopDown();
3309 SetMenuEnables(enab)
3313 if (!menuBarWidget) return;
3314 while (enab->name != NULL) {
3315 w = XtNameToWidget(menuBarWidget, enab->name);
3317 DisplayError(enab->name, 0);
3319 XtSetSensitive(w, enab->value);
3325 Enables icsEnables[] = {
3326 { "menuFile.Mail Move", False },
3327 { "menuFile.Reload CMail Message", False },
3328 { "menuMode.Machine Black", False },
3329 { "menuMode.Machine White", False },
3330 { "menuMode.Analysis Mode", False },
3331 { "menuMode.Analyze File", False },
3332 { "menuMode.Two Machines", False },
3334 { "menuHelp.Hint", False },
3335 { "menuHelp.Book", False },
3336 { "menuStep.Move Now", False },
3337 { "menuOptions.Periodic Updates", False },
3338 { "menuOptions.Hide Thinking", False },
3339 { "menuOptions.Ponder Next Move", False },
3344 Enables ncpEnables[] = {
3345 { "menuFile.Mail Move", False },
3346 { "menuFile.Reload CMail Message", False },
3347 { "menuMode.Machine White", False },
3348 { "menuMode.Machine Black", False },
3349 { "menuMode.Analysis Mode", False },
3350 { "menuMode.Analyze File", False },
3351 { "menuMode.Two Machines", False },
3352 { "menuMode.ICS Client", False },
3353 { "menuMode.ICS Input Box", False },
3354 { "Action", False },
3355 { "menuStep.Revert", False },
3356 { "menuStep.Move Now", False },
3357 { "menuStep.Retract Move", False },
3358 { "menuOptions.Auto Comment", False },
3359 { "menuOptions.Auto Flag", False },
3360 { "menuOptions.Auto Flip View", False },
3361 { "menuOptions.Auto Observe", False },
3362 { "menuOptions.Auto Raise Board", False },
3363 { "menuOptions.Get Move List", False },
3364 { "menuOptions.ICS Alarm", False },
3365 { "menuOptions.Move Sound", False },
3366 { "menuOptions.Quiet Play", False },
3367 { "menuOptions.Hide Thinking", False },
3368 { "menuOptions.Periodic Updates", False },
3369 { "menuOptions.Ponder Next Move", False },
3370 { "menuHelp.Hint", False },
3371 { "menuHelp.Book", False },
3375 Enables gnuEnables[] = {
3376 { "menuMode.ICS Client", False },
3377 { "menuMode.ICS Input Box", False },
3378 { "menuAction.Accept", False },
3379 { "menuAction.Decline", False },
3380 { "menuAction.Rematch", False },
3381 { "menuAction.Adjourn", False },
3382 { "menuAction.Stop Examining", False },
3383 { "menuAction.Stop Observing", False },
3384 { "menuStep.Revert", False },
3385 { "menuOptions.Auto Comment", False },
3386 { "menuOptions.Auto Observe", False },
3387 { "menuOptions.Auto Raise Board", False },
3388 { "menuOptions.Get Move List", False },
3389 { "menuOptions.Premove", False },
3390 { "menuOptions.Quiet Play", False },
3392 /* The next two options rely on SetCmailMode being called *after* */
3393 /* SetGNUMode so that when GNU is being used to give hints these */
3394 /* menu options are still available */
3396 { "menuFile.Mail Move", False },
3397 { "menuFile.Reload CMail Message", False },
3401 Enables cmailEnables[] = {
3403 { "menuAction.Call Flag", False },
3404 { "menuAction.Draw", True },
3405 { "menuAction.Adjourn", False },
3406 { "menuAction.Abort", False },
3407 { "menuAction.Stop Observing", False },
3408 { "menuAction.Stop Examining", False },
3409 { "menuFile.Mail Move", True },
3410 { "menuFile.Reload CMail Message", True },
3414 Enables trainingOnEnables[] = {
3415 { "menuMode.Edit Comment", False },
3416 { "menuMode.Pause", False },
3417 { "menuStep.Forward", False },
3418 { "menuStep.Backward", False },
3419 { "menuStep.Forward to End", False },
3420 { "menuStep.Back to Start", False },
3421 { "menuStep.Move Now", False },
3422 { "menuStep.Truncate Game", False },
3426 Enables trainingOffEnables[] = {
3427 { "menuMode.Edit Comment", True },
3428 { "menuMode.Pause", True },
3429 { "menuStep.Forward", True },
3430 { "menuStep.Backward", True },
3431 { "menuStep.Forward to End", True },
3432 { "menuStep.Back to Start", True },
3433 { "menuStep.Move Now", True },
3434 { "menuStep.Truncate Game", True },
3438 Enables machineThinkingEnables[] = {
3439 { "menuFile.Load Game", False },
3440 { "menuFile.Load Next Game", False },
3441 { "menuFile.Load Previous Game", False },
3442 { "menuFile.Reload Same Game", False },
3443 { "menuFile.Paste Game", False },
3444 { "menuFile.Load Position", False },
3445 { "menuFile.Load Next Position", False },
3446 { "menuFile.Load Previous Position", False },
3447 { "menuFile.Reload Same Position", False },
3448 { "menuFile.Paste Position", False },
3449 { "menuMode.Machine White", False },
3450 { "menuMode.Machine Black", False },
3451 { "menuMode.Two Machines", False },
3452 { "menuStep.Retract Move", False },
3456 Enables userThinkingEnables[] = {
3457 { "menuFile.Load Game", True },
3458 { "menuFile.Load Next Game", True },
3459 { "menuFile.Load Previous Game", True },
3460 { "menuFile.Reload Same Game", True },
3461 { "menuFile.Paste Game", True },
3462 { "menuFile.Load Position", True },
3463 { "menuFile.Load Next Position", True },
3464 { "menuFile.Load Previous Position", True },
3465 { "menuFile.Reload Same Position", True },
3466 { "menuFile.Paste Position", True },
3467 { "menuMode.Machine White", True },
3468 { "menuMode.Machine Black", True },
3469 { "menuMode.Two Machines", True },
3470 { "menuStep.Retract Move", True },
3476 SetMenuEnables(icsEnables);
3479 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3480 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3487 SetMenuEnables(ncpEnables);
3493 SetMenuEnables(gnuEnables);
3499 SetMenuEnables(cmailEnables);
3505 SetMenuEnables(trainingOnEnables);
3506 if (appData.showButtonBar) {
3507 XtSetSensitive(buttonBarWidget, False);
3513 SetTrainingModeOff()
3515 SetMenuEnables(trainingOffEnables);
3516 if (appData.showButtonBar) {
3517 XtSetSensitive(buttonBarWidget, True);
3522 SetUserThinkingEnables()
3524 if (appData.noChessProgram) return;
3525 SetMenuEnables(userThinkingEnables);
3529 SetMachineThinkingEnables()
3531 if (appData.noChessProgram) return;
3532 SetMenuEnables(machineThinkingEnables);
3534 case MachinePlaysBlack:
3535 case MachinePlaysWhite:
3536 case TwoMachinesPlay:
3537 XtSetSensitive(XtNameToWidget(menuBarWidget,
3538 ModeToWidgetName(gameMode)), True);
3545 #define Abs(n) ((n)<0 ? -(n) : (n))
3548 * Find a font that matches "pattern" that is as close as
3549 * possible to the targetPxlSize. Prefer fonts that are k
3550 * pixels smaller to fonts that are k pixels larger. The
3551 * pattern must be in the X Consortium standard format,
3552 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3553 * The return value should be freed with XtFree when no
3556 char *FindFont(pattern, targetPxlSize)
3560 char **fonts, *p, *best, *scalable, *scalableTail;
3561 int i, j, nfonts, minerr, err, pxlSize;
3564 char **missing_list;
3566 char *def_string, *base_fnt_lst, strInt[3];
3568 XFontStruct **fnt_list;
3570 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3571 sprintf(strInt, "%d", targetPxlSize);
3572 p = strstr(pattern, "--");
3573 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3574 strcat(base_fnt_lst, strInt);
3575 strcat(base_fnt_lst, strchr(p + 2, '-'));
3577 if ((fntSet = XCreateFontSet(xDisplay,
3581 &def_string)) == NULL) {
3583 fprintf(stderr, _("Unable to create font set.\n"));
3587 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3589 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3591 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3592 programName, pattern);
3600 for (i=0; i<nfonts; i++) {
3603 if (*p != '-') continue;
3605 if (*p == NULLCHAR) break;
3606 if (*p++ == '-') j++;
3608 if (j < 7) continue;
3611 scalable = fonts[i];
3614 err = pxlSize - targetPxlSize;
3615 if (Abs(err) < Abs(minerr) ||
3616 (minerr > 0 && err < 0 && -err == minerr)) {
3622 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3623 /* If the error is too big and there is a scalable font,
3624 use the scalable font. */
3625 int headlen = scalableTail - scalable;
3626 p = (char *) XtMalloc(strlen(scalable) + 10);
3627 while (isdigit(*scalableTail)) scalableTail++;
3628 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3630 p = (char *) XtMalloc(strlen(best) + 1);
3633 if (appData.debugMode) {
3634 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3635 pattern, targetPxlSize, p);
3638 if (missing_count > 0)
3639 XFreeStringList(missing_list);
3640 XFreeFontSet(xDisplay, fntSet);
3642 XFreeFontNames(fonts);
3649 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3650 | GCBackground | GCFunction | GCPlaneMask;
3651 XGCValues gc_values;
3654 gc_values.plane_mask = AllPlanes;
3655 gc_values.line_width = lineGap;
3656 gc_values.line_style = LineSolid;
3657 gc_values.function = GXcopy;
3659 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3660 gc_values.background = XBlackPixel(xDisplay, xScreen);
3661 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3663 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3664 gc_values.background = XWhitePixel(xDisplay, xScreen);
3665 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3666 XSetFont(xDisplay, coordGC, coordFontID);
3668 // [HGM] make font for holdings counts (white on black0
3669 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3670 gc_values.background = XBlackPixel(xDisplay, xScreen);
3671 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3672 XSetFont(xDisplay, countGC, countFontID);
3674 if (appData.monoMode) {
3675 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3676 gc_values.background = XWhitePixel(xDisplay, xScreen);
3677 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3679 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3680 gc_values.background = XBlackPixel(xDisplay, xScreen);
3681 lightSquareGC = wbPieceGC
3682 = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3685 gc_values.background = XWhitePixel(xDisplay, xScreen);
3686 darkSquareGC = bwPieceGC
3687 = XtGetGC(shellWidget, value_mask, &gc_values);
3689 if (DefaultDepth(xDisplay, xScreen) == 1) {
3690 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3691 gc_values.function = GXcopyInverted;
3692 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3693 gc_values.function = GXcopy;
3694 if (XBlackPixel(xDisplay, xScreen) == 1) {
3695 bwPieceGC = darkSquareGC;
3696 wbPieceGC = copyInvertedGC;
3698 bwPieceGC = copyInvertedGC;
3699 wbPieceGC = lightSquareGC;
3703 gc_values.foreground = highlightSquareColor;
3704 gc_values.background = highlightSquareColor;
3705 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3707 gc_values.foreground = premoveHighlightColor;
3708 gc_values.background = premoveHighlightColor;
3709 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3711 gc_values.foreground = lightSquareColor;
3712 gc_values.background = darkSquareColor;
3713 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3715 gc_values.foreground = darkSquareColor;
3716 gc_values.background = lightSquareColor;
3717 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3719 gc_values.foreground = jailSquareColor;
3720 gc_values.background = jailSquareColor;
3721 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3723 gc_values.foreground = whitePieceColor;
3724 gc_values.background = darkSquareColor;
3725 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3727 gc_values.foreground = whitePieceColor;
3728 gc_values.background = lightSquareColor;
3729 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3731 gc_values.foreground = whitePieceColor;
3732 gc_values.background = jailSquareColor;
3733 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3735 gc_values.foreground = blackPieceColor;
3736 gc_values.background = darkSquareColor;
3737 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3739 gc_values.foreground = blackPieceColor;
3740 gc_values.background = lightSquareColor;
3741 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3743 gc_values.foreground = blackPieceColor;
3744 gc_values.background = jailSquareColor;
3745 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3749 void loadXIM(xim, xmask, filename, dest, mask)
3762 fp = fopen(filename, "rb");
3764 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3771 for (y=0; y<h; ++y) {
3772 for (x=0; x<h; ++x) {
3777 XPutPixel(xim, x, y, blackPieceColor);
3779 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3782 XPutPixel(xim, x, y, darkSquareColor);
3784 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3787 XPutPixel(xim, x, y, whitePieceColor);
3789 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3792 XPutPixel(xim, x, y, lightSquareColor);
3794 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3800 /* create Pixmap of piece */
3801 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3803 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3806 /* create Pixmap of clipmask
3807 Note: We assume the white/black pieces have the same
3808 outline, so we make only 6 masks. This is okay
3809 since the XPM clipmask routines do the same. */
3811 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3813 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3816 /* now create the 1-bit version */
3817 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3820 values.foreground = 1;
3821 values.background = 0;
3823 /* Don't use XtGetGC, not read only */
3824 maskGC = XCreateGC(xDisplay, *mask,
3825 GCForeground | GCBackground, &values);
3826 XCopyPlane(xDisplay, temp, *mask, maskGC,
3827 0, 0, squareSize, squareSize, 0, 0, 1);
3828 XFreePixmap(xDisplay, temp);
3833 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3835 void CreateXIMPieces()
3840 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3845 /* The XSynchronize calls were copied from CreatePieces.
3846 Not sure if needed, but can't hurt */
3847 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3850 /* temp needed by loadXIM() */
3851 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3852 0, 0, ss, ss, AllPlanes, XYPixmap);
3854 if (strlen(appData.pixmapDirectory) == 0) {
3858 if (appData.monoMode) {
3859 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3863 fprintf(stderr, _("\nLoading XIMs...\n"));
3865 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3866 fprintf(stderr, "%d", piece+1);
3867 for (kind=0; kind<4; kind++) {
3868 fprintf(stderr, ".");
3869 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3870 ExpandPathName(appData.pixmapDirectory),
3871 piece <= (int) WhiteKing ? "" : "w",
3872 pieceBitmapNames[piece],
3874 ximPieceBitmap[kind][piece] =
3875 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3876 0, 0, ss, ss, AllPlanes, XYPixmap);
3877 if (appData.debugMode)
3878 fprintf(stderr, _("(File:%s:) "), buf);
3879 loadXIM(ximPieceBitmap[kind][piece],
3881 &(xpmPieceBitmap2[kind][piece]),
3882 &(ximMaskPm2[piece]));
3883 if(piece <= (int)WhiteKing)
3884 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3886 fprintf(stderr," ");
3888 /* Load light and dark squares */
3889 /* If the LSQ and DSQ pieces don't exist, we will
3890 draw them with solid squares. */
3891 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3892 if (access(buf, 0) != 0) {
3896 fprintf(stderr, _("light square "));
3898 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3899 0, 0, ss, ss, AllPlanes, XYPixmap);
3900 if (appData.debugMode)
3901 fprintf(stderr, _("(File:%s:) "), buf);
3903 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3904 fprintf(stderr, _("dark square "));
3905 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3906 ExpandPathName(appData.pixmapDirectory), ss);
3907 if (appData.debugMode)
3908 fprintf(stderr, _("(File:%s:) "), buf);
3910 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3911 0, 0, ss, ss, AllPlanes, XYPixmap);
3912 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3913 xpmJailSquare = xpmLightSquare;
3915 fprintf(stderr, _("Done.\n"));
3917 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3921 void CreateXPMPieces()
3925 u_int ss = squareSize;
3927 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3928 XpmColorSymbol symbols[4];
3930 /* The XSynchronize calls were copied from CreatePieces.
3931 Not sure if needed, but can't hurt */
3932 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3934 /* Setup translations so piece colors match square colors */
3935 symbols[0].name = "light_piece";
3936 symbols[0].value = appData.whitePieceColor;
3937 symbols[1].name = "dark_piece";
3938 symbols[1].value = appData.blackPieceColor;
3939 symbols[2].name = "light_square";
3940 symbols[2].value = appData.lightSquareColor;
3941 symbols[3].name = "dark_square";
3942 symbols[3].value = appData.darkSquareColor;
3944 attr.valuemask = XpmColorSymbols;
3945 attr.colorsymbols = symbols;
3946 attr.numsymbols = 4;
3948 if (appData.monoMode) {
3949 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3953 if (strlen(appData.pixmapDirectory) == 0) {
3954 XpmPieces* pieces = builtInXpms;
3957 while (pieces->size != squareSize && pieces->size) pieces++;
3958 if (!pieces->size) {
3959 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3962 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3963 for (kind=0; kind<4; kind++) {
3965 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3966 pieces->xpm[piece][kind],
3967 &(xpmPieceBitmap2[kind][piece]),
3968 NULL, &attr)) != 0) {
3969 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3973 if(piece <= (int) WhiteKing)
3974 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3978 xpmJailSquare = xpmLightSquare;
3982 fprintf(stderr, _("\nLoading XPMs...\n"));
3985 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3986 fprintf(stderr, "%d ", piece+1);
3987 for (kind=0; kind<4; kind++) {
3988 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3989 ExpandPathName(appData.pixmapDirectory),
3990 piece > (int) WhiteKing ? "w" : "",
3991 pieceBitmapNames[piece],
3993 if (appData.debugMode) {
3994 fprintf(stderr, _("(File:%s:) "), buf);
3996 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3997 &(xpmPieceBitmap2[kind][piece]),
3998 NULL, &attr)) != 0) {
3999 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
4000 // [HGM] missing: read of unorthodox piece failed; substitute King.
4001 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
4002 ExpandPathName(appData.pixmapDirectory),
4004 if (appData.debugMode) {
4005 fprintf(stderr, _("(Replace by File:%s:) "), buf);
4007 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4008 &(xpmPieceBitmap2[kind][piece]),
4012 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4017 if(piece <= (int) WhiteKing)
4018 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4021 /* Load light and dark squares */
4022 /* If the LSQ and DSQ pieces don't exist, we will
4023 draw them with solid squares. */
4024 fprintf(stderr, _("light square "));
4025 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4026 if (access(buf, 0) != 0) {
4030 if (appData.debugMode)
4031 fprintf(stderr, _("(File:%s:) "), buf);
4033 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4034 &xpmLightSquare, NULL, &attr)) != 0) {
4035 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4038 fprintf(stderr, _("dark square "));
4039 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4040 ExpandPathName(appData.pixmapDirectory), ss);
4041 if (appData.debugMode) {
4042 fprintf(stderr, _("(File:%s:) "), buf);
4044 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4045 &xpmDarkSquare, NULL, &attr)) != 0) {
4046 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4050 xpmJailSquare = xpmLightSquare;
4051 fprintf(stderr, _("Done.\n"));
4053 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4056 #endif /* HAVE_LIBXPM */
4059 /* No built-in bitmaps */
4064 u_int ss = squareSize;
4066 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4069 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4070 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4071 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4072 pieceBitmapNames[piece],
4073 ss, kind == SOLID ? 's' : 'o');
4074 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4075 if(piece <= (int)WhiteKing)
4076 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4080 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4084 /* With built-in bitmaps */
4087 BuiltInBits* bib = builtInBits;
4090 u_int ss = squareSize;
4092 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4095 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4097 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4098 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4099 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4100 pieceBitmapNames[piece],
4101 ss, kind == SOLID ? 's' : 'o');
4102 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4103 bib->bits[kind][piece], ss, ss);
4104 if(piece <= (int)WhiteKing)
4105 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4109 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4114 void ReadBitmap(pm, name, bits, wreq, hreq)
4117 unsigned char bits[];
4123 char msg[MSG_SIZ], fullname[MSG_SIZ];
4125 if (*appData.bitmapDirectory != NULLCHAR) {
4126 strcpy(fullname, appData.bitmapDirectory);
4127 strcat(fullname, "/");
4128 strcat(fullname, name);
4129 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4130 &w, &h, pm, &x_hot, &y_hot);
4131 fprintf(stderr, "load %s\n", name);
4132 if (errcode != BitmapSuccess) {
4134 case BitmapOpenFailed:
4135 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4137 case BitmapFileInvalid:
4138 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4140 case BitmapNoMemory:
4141 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4145 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4149 fprintf(stderr, _("%s: %s...using built-in\n"),
4151 } else if (w != wreq || h != hreq) {
4153 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4154 programName, fullname, w, h, wreq, hreq);
4160 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4169 if (lineGap == 0) return;
4171 /* [HR] Split this into 2 loops for non-square boards. */
4173 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4174 gridSegments[i].x1 = 0;
4175 gridSegments[i].x2 =
4176 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4177 gridSegments[i].y1 = gridSegments[i].y2
4178 = lineGap / 2 + (i * (squareSize + lineGap));
4181 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4182 gridSegments[j + i].y1 = 0;
4183 gridSegments[j + i].y2 =
4184 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4185 gridSegments[j + i].x1 = gridSegments[j + i].x2
4186 = lineGap / 2 + (j * (squareSize + lineGap));
4190 static void MenuBarSelect(w, addr, index)
4195 XtActionProc proc = (XtActionProc) addr;
4197 (proc)(NULL, NULL, NULL, NULL);
4200 void CreateMenuBarPopup(parent, name, mb)
4210 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4213 XtSetArg(args[j], XtNleftMargin, 20); j++;
4214 XtSetArg(args[j], XtNrightMargin, 20); j++;
4216 while (mi->string != NULL) {
4217 if (strcmp(mi->string, "----") == 0) {
4218 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4221 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4222 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4224 XtAddCallback(entry, XtNcallback,
4225 (XtCallbackProc) MenuBarSelect,
4226 (caddr_t) mi->proc);
4232 Widget CreateMenuBar(mb)
4236 Widget anchor, menuBar;
4238 char menuName[MSG_SIZ];
4241 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4242 XtSetArg(args[j], XtNvSpace, 0); j++;
4243 XtSetArg(args[j], XtNborderWidth, 0); j++;
4244 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4245 formWidget, args, j);
4247 while (mb->name != NULL) {
4248 strcpy(menuName, "menu");
4249 strcat(menuName, mb->name);
4251 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4254 shortName[0] = _(mb->name)[0];
4255 shortName[1] = NULLCHAR;
4256 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4259 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4262 XtSetArg(args[j], XtNborderWidth, 0); j++;
4263 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4265 CreateMenuBarPopup(menuBar, menuName, mb);
4271 Widget CreateButtonBar(mi)
4275 Widget button, buttonBar;
4279 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4281 XtSetArg(args[j], XtNhSpace, 0); j++;
4283 XtSetArg(args[j], XtNborderWidth, 0); j++;
4284 XtSetArg(args[j], XtNvSpace, 0); j++;
4285 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4286 formWidget, args, j);
4288 while (mi->string != NULL) {
4291 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4292 XtSetArg(args[j], XtNborderWidth, 0); j++;
4294 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4295 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4296 buttonBar, args, j);
4297 XtAddCallback(button, XtNcallback,
4298 (XtCallbackProc) MenuBarSelect,
4299 (caddr_t) mi->proc);
4306 CreatePieceMenu(name, color)
4313 ChessSquare selection;
4315 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4316 boardWidget, args, 0);
4318 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4319 String item = pieceMenuStrings[color][i];
4321 if (strcmp(item, "----") == 0) {
4322 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4325 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4326 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4328 selection = pieceMenuTranslation[color][i];
4329 XtAddCallback(entry, XtNcallback,
4330 (XtCallbackProc) PieceMenuSelect,
4331 (caddr_t) selection);
4332 if (selection == WhitePawn || selection == BlackPawn) {
4333 XtSetArg(args[0], XtNpopupOnEntry, entry);
4334 XtSetValues(menu, args, 1);
4347 ChessSquare selection;
4349 whitePieceMenu = CreatePieceMenu("menuW", 0);
4350 blackPieceMenu = CreatePieceMenu("menuB", 1);
4352 XtRegisterGrabAction(PieceMenuPopup, True,
4353 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4354 GrabModeAsync, GrabModeAsync);
4356 XtSetArg(args[0], XtNlabel, _("Drop"));
4357 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4358 boardWidget, args, 1);
4359 for (i = 0; i < DROP_MENU_SIZE; i++) {
4360 String item = dropMenuStrings[i];
4362 if (strcmp(item, "----") == 0) {
4363 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4366 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4367 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4369 selection = dropMenuTranslation[i];
4370 XtAddCallback(entry, XtNcallback,
4371 (XtCallbackProc) DropMenuSelect,
4372 (caddr_t) selection);
4377 void SetupDropMenu()
4385 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4386 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4387 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4388 dmEnables[i].piece);
4389 XtSetSensitive(entry, p != NULL || !appData.testLegality
4390 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4391 && !appData.icsActive));
4393 while (p && *p++ == dmEnables[i].piece) count++;
4394 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4396 XtSetArg(args[j], XtNlabel, label); j++;
4397 XtSetValues(entry, args, j);
4401 void PieceMenuPopup(w, event, params, num_params)
4405 Cardinal *num_params;
4408 if (event->type != ButtonPress) return;
4409 if (errorUp) ErrorPopDown();
4413 whichMenu = params[0];
4415 case IcsPlayingWhite:
4416 case IcsPlayingBlack:
4418 case MachinePlaysWhite:
4419 case MachinePlaysBlack:
4420 if (appData.testLegality &&
4421 gameInfo.variant != VariantBughouse &&
4422 gameInfo.variant != VariantCrazyhouse) return;
4424 whichMenu = "menuD";
4430 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4431 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4432 pmFromX = pmFromY = -1;
4436 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4438 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4440 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4443 static void PieceMenuSelect(w, piece, junk)
4448 if (pmFromX < 0 || pmFromY < 0) return;
4449 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4452 static void DropMenuSelect(w, piece, junk)
4457 if (pmFromX < 0 || pmFromY < 0) return;
4458 DropMenuEvent(piece, pmFromX, pmFromY);
4461 void WhiteClock(w, event, prms, nprms)
4467 if (gameMode == EditPosition || gameMode == IcsExamining) {
4468 SetWhiteToPlayEvent();
4469 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4474 void BlackClock(w, event, prms, nprms)
4480 if (gameMode == EditPosition || gameMode == IcsExamining) {
4481 SetBlackToPlayEvent();
4482 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4489 * If the user selects on a border boundary, return -1; if off the board,
4490 * return -2. Otherwise map the event coordinate to the square.
4492 int EventToSquare(x, limit)
4500 if ((x % (squareSize + lineGap)) >= squareSize)
4502 x /= (squareSize + lineGap);
4508 static void do_flash_delay(msec)
4514 static void drawHighlight(file, rank, gc)
4520 if (lineGap == 0 || appData.blindfold) return;
4523 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4524 (squareSize + lineGap);
4525 y = lineGap/2 + rank * (squareSize + lineGap);
4527 x = lineGap/2 + file * (squareSize + lineGap);
4528 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4529 (squareSize + lineGap);
4532 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4533 squareSize+lineGap, squareSize+lineGap);
4536 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4537 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4540 SetHighlights(fromX, fromY, toX, toY)
4541 int fromX, fromY, toX, toY;
4543 if (hi1X != fromX || hi1Y != fromY) {
4544 if (hi1X >= 0 && hi1Y >= 0) {
4545 drawHighlight(hi1X, hi1Y, lineGC);
4547 if (fromX >= 0 && fromY >= 0) {
4548 drawHighlight(fromX, fromY, highlineGC);
4551 if (hi2X != toX || hi2Y != toY) {
4552 if (hi2X >= 0 && hi2Y >= 0) {
4553 drawHighlight(hi2X, hi2Y, lineGC);
4555 if (toX >= 0 && toY >= 0) {
4556 drawHighlight(toX, toY, highlineGC);
4568 SetHighlights(-1, -1, -1, -1);
4573 SetPremoveHighlights(fromX, fromY, toX, toY)
4574 int fromX, fromY, toX, toY;
4576 if (pm1X != fromX || pm1Y != fromY) {
4577 if (pm1X >= 0 && pm1Y >= 0) {
4578 drawHighlight(pm1X, pm1Y, lineGC);
4580 if (fromX >= 0 && fromY >= 0) {
4581 drawHighlight(fromX, fromY, prelineGC);
4584 if (pm2X != toX || pm2Y != toY) {
4585 if (pm2X >= 0 && pm2Y >= 0) {
4586 drawHighlight(pm2X, pm2Y, lineGC);
4588 if (toX >= 0 && toY >= 0) {
4589 drawHighlight(toX, toY, prelineGC);
4599 ClearPremoveHighlights()
4601 SetPremoveHighlights(-1, -1, -1, -1);
4604 static void BlankSquare(x, y, color, piece, dest)
4609 if (useImages && useImageSqs) {
4613 pm = xpmLightSquare;
4618 case 2: /* neutral */
4623 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4624 squareSize, squareSize, x, y);
4634 case 2: /* neutral */
4639 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4644 I split out the routines to draw a piece so that I could
4645 make a generic flash routine.
4647 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4649 int square_color, x, y;
4652 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4653 switch (square_color) {
4655 case 2: /* neutral */
4657 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4658 ? *pieceToOutline(piece)
4659 : *pieceToSolid(piece),
4660 dest, bwPieceGC, 0, 0,
4661 squareSize, squareSize, x, y);
4664 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4665 ? *pieceToSolid(piece)
4666 : *pieceToOutline(piece),
4667 dest, wbPieceGC, 0, 0,
4668 squareSize, squareSize, x, y);
4673 static void monoDrawPiece(piece, square_color, x, y, dest)
4675 int square_color, x, y;
4678 switch (square_color) {
4680 case 2: /* neutral */
4682 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4683 ? *pieceToOutline(piece)
4684 : *pieceToSolid(piece),
4685 dest, bwPieceGC, 0, 0,
4686 squareSize, squareSize, x, y, 1);
4689 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4690 ? *pieceToSolid(piece)
4691 : *pieceToOutline(piece),
4692 dest, wbPieceGC, 0, 0,
4693 squareSize, squareSize, x, y, 1);
4698 static void colorDrawPiece(piece, square_color, x, y, dest)
4700 int square_color, x, y;
4703 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4704 switch (square_color) {
4706 XCopyPlane(xDisplay, *pieceToSolid(piece),
4707 dest, (int) piece < (int) BlackPawn
4708 ? wlPieceGC : blPieceGC, 0, 0,
4709 squareSize, squareSize, x, y, 1);
4712 XCopyPlane(xDisplay, *pieceToSolid(piece),
4713 dest, (int) piece < (int) BlackPawn
4714 ? wdPieceGC : bdPieceGC, 0, 0,
4715 squareSize, squareSize, x, y, 1);
4717 case 2: /* neutral */
4719 XCopyPlane(xDisplay, *pieceToSolid(piece),
4720 dest, (int) piece < (int) BlackPawn
4721 ? wjPieceGC : bjPieceGC, 0, 0,
4722 squareSize, squareSize, x, y, 1);
4727 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4729 int square_color, x, y;
4734 switch (square_color) {
4736 case 2: /* neutral */
4738 if ((int)piece < (int) BlackPawn) {
4746 if ((int)piece < (int) BlackPawn) {
4754 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4755 dest, wlPieceGC, 0, 0,
4756 squareSize, squareSize, x, y);
4759 typedef void (*DrawFunc)();
4761 DrawFunc ChooseDrawFunc()
4763 if (appData.monoMode) {
4764 if (DefaultDepth(xDisplay, xScreen) == 1) {
4765 return monoDrawPiece_1bit;
4767 return monoDrawPiece;
4771 return colorDrawPieceImage;
4773 return colorDrawPiece;
4777 /* [HR] determine square color depending on chess variant. */
4778 static int SquareColor(row, column)
4783 if (gameInfo.variant == VariantXiangqi) {
4784 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4786 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4788 } else if (row <= 4) {
4794 square_color = ((column + row) % 2) == 1;
4797 /* [hgm] holdings: next line makes all holdings squares light */
4798 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4800 return square_color;
4803 void DrawSquare(row, column, piece, do_flash)
4804 int row, column, do_flash;
4807 int square_color, x, y, direction, font_ascent, font_descent;
4810 XCharStruct overall;
4814 /* Calculate delay in milliseconds (2-delays per complete flash) */
4815 flash_delay = 500 / appData.flashRate;
4818 x = lineGap + ((BOARD_WIDTH-1)-column) *
4819 (squareSize + lineGap);
4820 y = lineGap + row * (squareSize + lineGap);
4822 x = lineGap + column * (squareSize + lineGap);
4823 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4824 (squareSize + lineGap);
4827 square_color = SquareColor(row, column);
4829 if ( // [HGM] holdings: blank out area between board and holdings
4830 column == BOARD_LEFT-1 || column == BOARD_RGHT
4831 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4832 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4833 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4835 // [HGM] print piece counts next to holdings
4836 string[1] = NULLCHAR;
4837 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4838 string[0] = '0' + piece;
4839 XTextExtents(countFontStruct, string, 1, &direction,
4840 &font_ascent, &font_descent, &overall);
4841 if (appData.monoMode) {
4842 XDrawImageString(xDisplay, xBoardWindow, countGC,
4843 x + squareSize - overall.width - 2,
4844 y + font_ascent + 1, string, 1);
4846 XDrawString(xDisplay, xBoardWindow, countGC,
4847 x + squareSize - overall.width - 2,
4848 y + font_ascent + 1, string, 1);
4851 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4852 string[0] = '0' + piece;
4853 XTextExtents(countFontStruct, string, 1, &direction,
4854 &font_ascent, &font_descent, &overall);
4855 if (appData.monoMode) {
4856 XDrawImageString(xDisplay, xBoardWindow, countGC,
4857 x + 2, y + font_ascent + 1, string, 1);
4859 XDrawString(xDisplay, xBoardWindow, countGC,
4860 x + 2, y + font_ascent + 1, string, 1);
4864 if (piece == EmptySquare || appData.blindfold) {
4865 BlankSquare(x, y, square_color, piece, xBoardWindow);
4867 drawfunc = ChooseDrawFunc();
4868 if (do_flash && appData.flashCount > 0) {
4869 for (i=0; i<appData.flashCount; ++i) {
4871 drawfunc(piece, square_color, x, y, xBoardWindow);
4872 XSync(xDisplay, False);
4873 do_flash_delay(flash_delay);
4875 BlankSquare(x, y, square_color, piece, xBoardWindow);
4876 XSync(xDisplay, False);
4877 do_flash_delay(flash_delay);
4880 drawfunc(piece, square_color, x, y, xBoardWindow);
4884 string[1] = NULLCHAR;
4885 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4886 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4887 string[0] = 'a' + column - BOARD_LEFT;
4888 XTextExtents(coordFontStruct, string, 1, &direction,
4889 &font_ascent, &font_descent, &overall);
4890 if (appData.monoMode) {
4891 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4892 x + squareSize - overall.width - 2,
4893 y + squareSize - font_descent - 1, string, 1);
4895 XDrawString(xDisplay, xBoardWindow, coordGC,
4896 x + squareSize - overall.width - 2,
4897 y + squareSize - font_descent - 1, string, 1);
4900 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4901 string[0] = ONE + row;
4902 XTextExtents(coordFontStruct, string, 1, &direction,
4903 &font_ascent, &font_descent, &overall);
4904 if (appData.monoMode) {
4905 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4906 x + 2, y + font_ascent + 1, string, 1);
4908 XDrawString(xDisplay, xBoardWindow, coordGC,
4909 x + 2, y + font_ascent + 1, string, 1);
4915 /* Why is this needed on some versions of X? */
4916 void EventProc(widget, unused, event)
4921 if (!XtIsRealized(widget))
4924 switch (event->type) {
4926 if (event->xexpose.count > 0) return; /* no clipping is done */
4927 XDrawPosition(widget, True, NULL);
4935 void DrawPosition(fullRedraw, board)
4936 /*Boolean*/int fullRedraw;
4939 XDrawPosition(boardWidget, fullRedraw, board);
4942 /* Returns 1 if there are "too many" differences between b1 and b2
4943 (i.e. more than 1 move was made) */
4944 static int too_many_diffs(b1, b2)
4950 for (i=0; i<BOARD_HEIGHT; ++i) {
4951 for (j=0; j<BOARD_WIDTH; ++j) {
4952 if (b1[i][j] != b2[i][j]) {
4953 if (++c > 4) /* Castling causes 4 diffs */
4962 /* Matrix describing castling maneuvers */
4963 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4964 static int castling_matrix[4][5] = {
4965 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4966 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4967 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4968 { 7, 7, 4, 5, 6 } /* 0-0, black */
4971 /* Checks whether castling occurred. If it did, *rrow and *rcol
4972 are set to the destination (row,col) of the rook that moved.
4974 Returns 1 if castling occurred, 0 if not.
4976 Note: Only handles a max of 1 castling move, so be sure
4977 to call too_many_diffs() first.
4979 static int check_castle_draw(newb, oldb, rrow, rcol)
4986 /* For each type of castling... */
4987 for (i=0; i<4; ++i) {
4988 r = castling_matrix[i];
4990 /* Check the 4 squares involved in the castling move */
4992 for (j=1; j<=4; ++j) {
4993 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
5000 /* All 4 changed, so it must be a castling move */
5009 static int damage[BOARD_SIZE][BOARD_SIZE];
5012 * event handler for redrawing the board
5014 void XDrawPosition(w, repaint, board)
5016 /*Boolean*/int repaint;
5020 static int lastFlipView = 0;
5021 static int lastBoardValid = 0;
5022 static Board lastBoard;
5026 if (board == NULL) {
5027 if (!lastBoardValid) return;
5030 if (!lastBoardValid || lastFlipView != flipView) {
5031 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5032 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5037 * It would be simpler to clear the window with XClearWindow()
5038 * but this causes a very distracting flicker.
5041 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5043 /* If too much changes (begin observing new game, etc.), don't
5045 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5047 /* Special check for castling so we don't flash both the king
5048 and the rook (just flash the king). */
5050 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5051 /* Draw rook with NO flashing. King will be drawn flashing later */
5052 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5053 lastBoard[rrow][rcol] = board[rrow][rcol];
5057 /* First pass -- Draw (newly) empty squares and repair damage.
5058 This prevents you from having a piece show up twice while it
5059 is flashing on its new square */
5060 for (i = 0; i < BOARD_HEIGHT; i++)
5061 for (j = 0; j < BOARD_WIDTH; j++)
5062 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5064 DrawSquare(i, j, board[i][j], 0);
5065 damage[i][j] = False;
5068 /* Second pass -- Draw piece(s) in new position and flash them */
5069 for (i = 0; i < BOARD_HEIGHT; i++)
5070 for (j = 0; j < BOARD_WIDTH; j++)
5071 if (board[i][j] != lastBoard[i][j]) {
5072 DrawSquare(i, j, board[i][j], do_flash);
5076 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5077 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5079 for (i = 0; i < BOARD_HEIGHT; i++)
5080 for (j = 0; j < BOARD_WIDTH; j++) {
5081 DrawSquare(i, j, board[i][j], 0);
5082 damage[i][j] = False;
5086 CopyBoard(lastBoard, board);
5088 lastFlipView = flipView;
5090 /* Draw highlights */
5091 if (pm1X >= 0 && pm1Y >= 0) {
5092 drawHighlight(pm1X, pm1Y, prelineGC);
5094 if (pm2X >= 0 && pm2Y >= 0) {
5095 drawHighlight(pm2X, pm2Y, prelineGC);
5097 if (hi1X >= 0 && hi1Y >= 0) {
5098 drawHighlight(hi1X, hi1Y, highlineGC);
5100 if (hi2X >= 0 && hi2Y >= 0) {
5101 drawHighlight(hi2X, hi2Y, highlineGC);
5104 /* If piece being dragged around board, must redraw that too */
5107 XSync(xDisplay, False);
5112 * event handler for redrawing the board
5114 void DrawPositionProc(w, event, prms, nprms)
5120 XDrawPosition(w, True, NULL);
5125 * event handler for parsing user moves
5127 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5128 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5129 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5130 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5131 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5132 // and at the end FinishMove() to perform the move after optional promotion popups.
5133 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5134 void HandleUserMove(w, event, prms, nprms)
5140 if (w != boardWidget || errorExitStatus != -1) return;
5143 if (event->type == ButtonPress) {
5144 XtPopdown(promotionShell);
5145 XtDestroyWidget(promotionShell);
5146 promotionUp = False;
5154 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5155 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5156 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5159 void AnimateUserMove (Widget w, XEvent * event,
5160 String * params, Cardinal * nParams)
5162 DragPieceMove(event->xmotion.x, event->xmotion.y);
5165 Widget CommentCreate(name, text, mutable, callback, lines)
5167 int /*Boolean*/ mutable;
5168 XtCallbackProc callback;
5172 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5177 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5178 XtGetValues(boardWidget, args, j);
5181 XtSetArg(args[j], XtNresizable, True); j++;
5184 XtCreatePopupShell(name, topLevelShellWidgetClass,
5185 shellWidget, args, j);
5188 XtCreatePopupShell(name, transientShellWidgetClass,
5189 shellWidget, args, j);
5192 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5193 layoutArgs, XtNumber(layoutArgs));
5195 XtCreateManagedWidget("form", formWidgetClass, layout,
5196 formArgs, XtNumber(formArgs));
5200 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5201 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5203 XtSetArg(args[j], XtNstring, text); j++;
5204 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5205 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5206 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5207 XtSetArg(args[j], XtNright, XtChainRight); j++;
5208 XtSetArg(args[j], XtNresizable, True); j++;
5209 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5210 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5211 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5212 XtSetArg(args[j], XtNautoFill, True); j++;
5213 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5215 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5219 XtSetArg(args[j], XtNfromVert, edit); j++;
5220 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5221 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5222 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5223 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5225 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5226 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5229 XtSetArg(args[j], XtNfromVert, edit); j++;
5230 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5231 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5232 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5233 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5234 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5236 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5237 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5240 XtSetArg(args[j], XtNfromVert, edit); j++;
5241 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5242 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5243 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5244 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5245 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5247 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5248 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5251 XtSetArg(args[j], XtNfromVert, edit); j++;
5252 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5253 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5254 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5255 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5257 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5258 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5261 XtSetArg(args[j], XtNfromVert, edit); j++;
5262 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5263 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5264 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5265 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5266 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5268 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5269 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5272 XtRealizeWidget(shell);
5274 if (commentX == -1) {
5277 Dimension pw_height;
5278 Dimension ew_height;
5281 XtSetArg(args[j], XtNheight, &ew_height); j++;
5282 XtGetValues(edit, args, j);
5285 XtSetArg(args[j], XtNheight, &pw_height); j++;
5286 XtGetValues(shell, args, j);
5287 commentH = pw_height + (lines - 1) * ew_height;
5288 commentW = bw_width - 16;
5290 XSync(xDisplay, False);
5292 /* This code seems to tickle an X bug if it is executed too soon
5293 after xboard starts up. The coordinates get transformed as if
5294 the main window was positioned at (0, 0).
5296 XtTranslateCoords(shellWidget,
5297 (bw_width - commentW) / 2, 0 - commentH / 2,
5298 &commentX, &commentY);
5300 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5301 RootWindowOfScreen(XtScreen(shellWidget)),
5302 (bw_width - commentW) / 2, 0 - commentH / 2,
5307 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5310 XtSetArg(args[j], XtNheight, commentH); j++;
5311 XtSetArg(args[j], XtNwidth, commentW); j++;
5312 XtSetArg(args[j], XtNx, commentX); j++;
5313 XtSetArg(args[j], XtNy, commentY); j++;
5314 XtSetValues(shell, args, j);
5315 XtSetKeyboardFocus(shell, edit);
5320 /* Used for analysis window and ICS input window */
5321 Widget MiscCreate(name, text, mutable, callback, lines)
5323 int /*Boolean*/ mutable;
5324 XtCallbackProc callback;
5328 Widget shell, layout, form, edit;
5330 Dimension bw_width, pw_height, ew_height, w, h;
5336 XtSetArg(args[j], XtNresizable, True); j++;
5339 XtCreatePopupShell(name, topLevelShellWidgetClass,
5340 shellWidget, args, j);
5343 XtCreatePopupShell(name, transientShellWidgetClass,
5344 shellWidget, args, j);
5347 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5348 layoutArgs, XtNumber(layoutArgs));
5350 XtCreateManagedWidget("form", formWidgetClass, layout,
5351 formArgs, XtNumber(formArgs));
5355 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5356 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5358 XtSetArg(args[j], XtNstring, text); j++;
5359 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5360 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5361 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5362 XtSetArg(args[j], XtNright, XtChainRight); j++;
5363 XtSetArg(args[j], XtNresizable, True); j++;
5364 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5365 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5366 XtSetArg(args[j], XtNautoFill, True); j++;
5367 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5369 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5371 XtRealizeWidget(shell);
5374 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5375 XtGetValues(boardWidget, args, j);
5378 XtSetArg(args[j], XtNheight, &ew_height); j++;
5379 XtGetValues(edit, args, j);
5382 XtSetArg(args[j], XtNheight, &pw_height); j++;
5383 XtGetValues(shell, args, j);
5384 h = pw_height + (lines - 1) * ew_height;
5387 XSync(xDisplay, False);
5389 /* This code seems to tickle an X bug if it is executed too soon
5390 after xboard starts up. The coordinates get transformed as if
5391 the main window was positioned at (0, 0).
5393 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5395 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5396 RootWindowOfScreen(XtScreen(shellWidget)),
5397 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5401 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5404 XtSetArg(args[j], XtNheight, h); j++;
5405 XtSetArg(args[j], XtNwidth, w); j++;
5406 XtSetArg(args[j], XtNx, x); j++;
5407 XtSetArg(args[j], XtNy, y); j++;
5408 XtSetValues(shell, args, j);
5414 static int savedIndex; /* gross that this is global */
5416 void EditCommentPopUp(index, title, text)
5425 if (text == NULL) text = "";
5427 if (editShell == NULL) {
5429 CommentCreate(title, text, True, EditCommentCallback, 4);
5430 XtRealizeWidget(editShell);
5431 CatchDeleteWindow(editShell, "EditCommentPopDown");
5433 edit = XtNameToWidget(editShell, "*form.text");
5435 XtSetArg(args[j], XtNstring, text); j++;
5436 XtSetValues(edit, args, j);
5438 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5439 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5440 XtSetValues(editShell, args, j);
5443 XtPopup(editShell, XtGrabNone);
5447 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5448 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5452 void EditCommentCallback(w, client_data, call_data)
5454 XtPointer client_data, call_data;
5462 XtSetArg(args[j], XtNlabel, &name); j++;
5463 XtGetValues(w, args, j);
5465 if (strcmp(name, _("ok")) == 0) {
5466 edit = XtNameToWidget(editShell, "*form.text");
5468 XtSetArg(args[j], XtNstring, &val); j++;
5469 XtGetValues(edit, args, j);
5470 ReplaceComment(savedIndex, val);
5471 EditCommentPopDown();
5472 } else if (strcmp(name, _("cancel")) == 0) {
5473 EditCommentPopDown();
5474 } else if (strcmp(name, _("clear")) == 0) {
5475 edit = XtNameToWidget(editShell, "*form.text");
5476 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5477 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5481 void EditCommentPopDown()
5486 if (!editUp) return;
5488 XtSetArg(args[j], XtNx, &commentX); j++;
5489 XtSetArg(args[j], XtNy, &commentY); j++;
5490 XtSetArg(args[j], XtNheight, &commentH); j++;
5491 XtSetArg(args[j], XtNwidth, &commentW); j++;
5492 XtGetValues(editShell, args, j);
5493 XtPopdown(editShell);
5496 XtSetArg(args[j], XtNleftBitmap, None); j++;
5497 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5501 void ICSInputBoxPopUp()
5506 char *title = _("ICS Input");
5509 if (ICSInputShell == NULL) {
5510 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5511 tr = XtParseTranslationTable(ICSInputTranslations);
5512 edit = XtNameToWidget(ICSInputShell, "*form.text");
5513 XtOverrideTranslations(edit, tr);
5514 XtRealizeWidget(ICSInputShell);
5515 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5518 edit = XtNameToWidget(ICSInputShell, "*form.text");
5520 XtSetArg(args[j], XtNstring, ""); j++;
5521 XtSetValues(edit, args, j);
5523 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5524 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5525 XtSetValues(ICSInputShell, args, j);
5528 XtPopup(ICSInputShell, XtGrabNone);
5529 XtSetKeyboardFocus(ICSInputShell, edit);
5531 ICSInputBoxUp = True;
5533 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5534 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5538 void ICSInputSendText()
5545 edit = XtNameToWidget(ICSInputShell, "*form.text");
5547 XtSetArg(args[j], XtNstring, &val); j++;
5548 XtGetValues(edit, args, j);
5549 SendMultiLineToICS(val);
5550 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5551 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5554 void ICSInputBoxPopDown()
5559 if (!ICSInputBoxUp) return;
5561 XtPopdown(ICSInputShell);
5562 ICSInputBoxUp = False;
5564 XtSetArg(args[j], XtNleftBitmap, None); j++;
5565 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5569 void CommentPopUp(title, text)
5576 if (commentShell == NULL) {
5578 CommentCreate(title, text, False, CommentCallback, 4);
5579 XtRealizeWidget(commentShell);
5580 CatchDeleteWindow(commentShell, "CommentPopDown");
5582 edit = XtNameToWidget(commentShell, "*form.text");
5584 XtSetArg(args[j], XtNstring, text); j++;
5585 XtSetValues(edit, args, j);
5587 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5588 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5589 XtSetValues(commentShell, args, j);
5592 XtPopup(commentShell, XtGrabNone);
5593 XSync(xDisplay, False);
5598 void CommentCallback(w, client_data, call_data)
5600 XtPointer client_data, call_data;
5607 XtSetArg(args[j], XtNlabel, &name); j++;
5608 XtGetValues(w, args, j);
5610 if (strcmp(name, _("close")) == 0) {
5612 } else if (strcmp(name, _("edit")) == 0) {
5619 void CommentPopDown()
5624 if (!commentUp) return;
5626 XtSetArg(args[j], XtNx, &commentX); j++;
5627 XtSetArg(args[j], XtNy, &commentY); j++;
5628 XtSetArg(args[j], XtNwidth, &commentW); j++;
5629 XtSetArg(args[j], XtNheight, &commentH); j++;
5630 XtGetValues(commentShell, args, j);
5631 XtPopdown(commentShell);
5632 XSync(xDisplay, False);
5636 void FileNamePopUp(label, def, proc, openMode)
5643 Widget popup, layout, dialog, edit;
5649 fileProc = proc; /* I can't see a way not */
5650 fileOpenMode = openMode; /* to use globals here */
5653 XtSetArg(args[i], XtNresizable, True); i++;
5654 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5655 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5656 fileNameShell = popup =
5657 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5658 shellWidget, args, i);
5661 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5662 layoutArgs, XtNumber(layoutArgs));
5665 XtSetArg(args[i], XtNlabel, label); i++;
5666 XtSetArg(args[i], XtNvalue, def); i++;
5667 XtSetArg(args[i], XtNborderWidth, 0); i++;
5668 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5671 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5672 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5673 (XtPointer) dialog);
5675 XtRealizeWidget(popup);
5676 CatchDeleteWindow(popup, "FileNamePopDown");
5678 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5679 &x, &y, &win_x, &win_y, &mask);
5681 XtSetArg(args[0], XtNx, x - 10);
5682 XtSetArg(args[1], XtNy, y - 30);
5683 XtSetValues(popup, args, 2);
5685 XtPopup(popup, XtGrabExclusive);
5688 edit = XtNameToWidget(dialog, "*value");
5689 XtSetKeyboardFocus(popup, edit);
5692 void FileNamePopDown()
5694 if (!filenameUp) return;
5695 XtPopdown(fileNameShell);
5696 XtDestroyWidget(fileNameShell);
5701 void FileNameCallback(w, client_data, call_data)
5703 XtPointer client_data, call_data;
5708 XtSetArg(args[0], XtNlabel, &name);
5709 XtGetValues(w, args, 1);
5711 if (strcmp(name, _("cancel")) == 0) {
5716 FileNameAction(w, NULL, NULL, NULL);
5719 void FileNameAction(w, event, prms, nprms)
5731 name = XawDialogGetValueString(w = XtParent(w));
5733 if ((name != NULL) && (*name != NULLCHAR)) {
5735 XtPopdown(w = XtParent(XtParent(w)));
5739 p = strrchr(buf, ' ');
5746 fullname = ExpandPathName(buf);
5748 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5751 f = fopen(fullname, fileOpenMode);
5753 DisplayError(_("Failed to open file"), errno);
5755 (void) (*fileProc)(f, index, buf);
5762 XtPopdown(w = XtParent(XtParent(w)));
5768 void PromotionPopUp()
5771 Widget dialog, layout;
5773 Dimension bw_width, pw_width;
5777 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5778 XtGetValues(boardWidget, args, j);
5781 XtSetArg(args[j], XtNresizable, True); j++;
5782 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5784 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5785 shellWidget, args, j);
5787 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5788 layoutArgs, XtNumber(layoutArgs));
5791 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5792 XtSetArg(args[j], XtNborderWidth, 0); j++;
5793 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5796 if(gameInfo.variant != VariantShogi) {
5797 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5798 (XtPointer) dialog);
5799 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5800 (XtPointer) dialog);
5801 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5802 (XtPointer) dialog);
5803 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5804 (XtPointer) dialog);
5805 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5806 gameInfo.variant == VariantGiveaway) {
5807 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5808 (XtPointer) dialog);
5810 if(gameInfo.variant == VariantCapablanca ||
5811 gameInfo.variant == VariantGothic ||
5812 gameInfo.variant == VariantCapaRandom) {
5813 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5814 (XtPointer) dialog);
5815 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5816 (XtPointer) dialog);
5818 } else // [HGM] shogi
5820 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5821 (XtPointer) dialog);
5822 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5823 (XtPointer) dialog);
5825 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5826 (XtPointer) dialog);
5828 XtRealizeWidget(promotionShell);
5829 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5832 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5833 XtGetValues(promotionShell, args, j);
5835 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5836 lineGap + squareSize/3 +
5837 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5838 0 : 6*(squareSize + lineGap)), &x, &y);
5841 XtSetArg(args[j], XtNx, x); j++;
5842 XtSetArg(args[j], XtNy, y); j++;
5843 XtSetValues(promotionShell, args, j);
5845 XtPopup(promotionShell, XtGrabNone);
5850 void PromotionPopDown()
5852 if (!promotionUp) return;
5853 XtPopdown(promotionShell);
5854 XtDestroyWidget(promotionShell);
5855 promotionUp = False;
5858 void PromotionCallback(w, client_data, call_data)
5860 XtPointer client_data, call_data;
5866 XtSetArg(args[0], XtNlabel, &name);
5867 XtGetValues(w, args, 1);
5871 if (fromX == -1) return;
5873 if (strcmp(name, _("cancel")) == 0) {
5877 } else if (strcmp(name, _("Knight")) == 0) {
5879 } else if (strcmp(name, _("Promote")) == 0) {
5881 } else if (strcmp(name, _("Defer")) == 0) {
5884 promoChar = ToLower(name[0]);
5887 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5889 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5890 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5895 void ErrorCallback(w, client_data, call_data)
5897 XtPointer client_data, call_data;
5900 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5902 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5908 if (!errorUp) return;
5910 XtPopdown(errorShell);
5911 XtDestroyWidget(errorShell);
5912 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5915 void ErrorPopUp(title, label, modal)
5916 char *title, *label;
5920 Widget dialog, layout;
5924 Dimension bw_width, pw_width;
5925 Dimension pw_height;
5929 XtSetArg(args[i], XtNresizable, True); i++;
5930 XtSetArg(args[i], XtNtitle, title); i++;
5932 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5933 shellWidget, args, i);
5935 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5936 layoutArgs, XtNumber(layoutArgs));
5939 XtSetArg(args[i], XtNlabel, label); i++;
5940 XtSetArg(args[i], XtNborderWidth, 0); i++;
5941 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5944 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5946 XtRealizeWidget(errorShell);
5947 CatchDeleteWindow(errorShell, "ErrorPopDown");
5950 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5951 XtGetValues(boardWidget, args, i);
5953 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5954 XtSetArg(args[i], XtNheight, &pw_height); i++;
5955 XtGetValues(errorShell, args, i);
5958 /* This code seems to tickle an X bug if it is executed too soon
5959 after xboard starts up. The coordinates get transformed as if
5960 the main window was positioned at (0, 0).
5962 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5963 0 - pw_height + squareSize / 3, &x, &y);
5965 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5966 RootWindowOfScreen(XtScreen(boardWidget)),
5967 (bw_width - pw_width) / 2,
5968 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5972 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5975 XtSetArg(args[i], XtNx, x); i++;
5976 XtSetArg(args[i], XtNy, y); i++;
5977 XtSetValues(errorShell, args, i);
5980 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5983 /* Disable all user input other than deleting the window */
5984 static int frozen = 0;
5988 /* Grab by a widget that doesn't accept input */
5989 XtAddGrab(messageWidget, TRUE, FALSE);
5993 /* Undo a FreezeUI */
5996 if (!frozen) return;
5997 XtRemoveGrab(messageWidget);
6001 char *ModeToWidgetName(mode)
6005 case BeginningOfGame:
6006 if (appData.icsActive)
6007 return "menuMode.ICS Client";
6008 else if (appData.noChessProgram ||
6009 *appData.cmailGameName != NULLCHAR)
6010 return "menuMode.Edit Game";
6012 return "menuMode.Machine Black";
6013 case MachinePlaysBlack:
6014 return "menuMode.Machine Black";
6015 case MachinePlaysWhite:
6016 return "menuMode.Machine White";
6018 return "menuMode.Analysis Mode";
6020 return "menuMode.Analyze File";
6021 case TwoMachinesPlay:
6022 return "menuMode.Two Machines";
6024 return "menuMode.Edit Game";
6025 case PlayFromGameFile:
6026 return "menuFile.Load Game";
6028 return "menuMode.Edit Position";
6030 return "menuMode.Training";
6031 case IcsPlayingWhite:
6032 case IcsPlayingBlack:
6036 return "menuMode.ICS Client";
6043 void ModeHighlight()
6046 static int oldPausing = FALSE;
6047 static GameMode oldmode = (GameMode) -1;
6050 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6052 if (pausing != oldPausing) {
6053 oldPausing = pausing;
6055 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6057 XtSetArg(args[0], XtNleftBitmap, None);
6059 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6062 if (appData.showButtonBar) {
6063 /* Always toggle, don't set. Previous code messes up when
6064 invoked while the button is pressed, as releasing it
6065 toggles the state again. */
6068 XtSetArg(args[0], XtNbackground, &oldbg);
6069 XtSetArg(args[1], XtNforeground, &oldfg);
6070 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6072 XtSetArg(args[0], XtNbackground, oldfg);
6073 XtSetArg(args[1], XtNforeground, oldbg);
6075 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6079 wname = ModeToWidgetName(oldmode);
6080 if (wname != NULL) {
6081 XtSetArg(args[0], XtNleftBitmap, None);
6082 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6084 wname = ModeToWidgetName(gameMode);
6085 if (wname != NULL) {
6086 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6087 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6091 /* Maybe all the enables should be handled here, not just this one */
6092 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6093 gameMode == Training || gameMode == PlayFromGameFile);
6098 * Button/menu procedures
6100 void ResetProc(w, event, prms, nprms)
6109 int LoadGamePopUp(f, gameNumber, title)
6114 cmailMsgLoaded = FALSE;
6115 if (gameNumber == 0) {
6116 int error = GameListBuild(f);
6118 DisplayError(_("Cannot build game list"), error);
6119 } else if (!ListEmpty(&gameList) &&
6120 ((ListGame *) gameList.tailPred)->number > 1) {
6121 GameListPopUp(f, title);
6127 return LoadGame(f, gameNumber, title, FALSE);
6130 void LoadGameProc(w, event, prms, nprms)
6136 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6139 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6142 void LoadNextGameProc(w, event, prms, nprms)
6151 void LoadPrevGameProc(w, event, prms, nprms)
6160 void ReloadGameProc(w, event, prms, nprms)
6169 void LoadNextPositionProc(w, event, prms, nprms)
6178 void LoadPrevPositionProc(w, event, prms, nprms)
6187 void ReloadPositionProc(w, event, prms, nprms)
6196 void LoadPositionProc(w, event, prms, nprms)
6202 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6205 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6208 void SaveGameProc(w, event, prms, nprms)
6214 FileNamePopUp(_("Save game file name?"),
6215 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6219 void SavePositionProc(w, event, prms, nprms)
6225 FileNamePopUp(_("Save position file name?"),
6226 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6230 void ReloadCmailMsgProc(w, event, prms, nprms)
6236 ReloadCmailMsgEvent(FALSE);
6239 void MailMoveProc(w, event, prms, nprms)
6248 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6249 static char *selected_fen_position=NULL;
6252 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6253 Atom *type_return, XtPointer *value_return,
6254 unsigned long *length_return, int *format_return)
6256 char *selection_tmp;
6258 if (!selected_fen_position) return False; /* should never happen */
6259 if (*target == XA_STRING){
6260 /* note: since no XtSelectionDoneProc was registered, Xt will
6261 * automatically call XtFree on the value returned. So have to
6262 * make a copy of it allocated with XtMalloc */
6263 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6264 strcpy(selection_tmp, selected_fen_position);
6266 *value_return=selection_tmp;
6267 *length_return=strlen(selection_tmp);
6268 *type_return=XA_STRING;
6269 *format_return = 8; /* bits per byte */
6276 /* note: when called from menu all parameters are NULL, so no clue what the
6277 * Widget which was clicked on was, or what the click event was
6279 void CopyPositionProc(w, event, prms, nprms)
6287 if (selected_fen_position) free(selected_fen_position);
6288 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6289 if (!selected_fen_position) return;
6290 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6292 SendPositionSelection,
6293 NULL/* lose_ownership_proc */ ,
6294 NULL/* transfer_done_proc */);
6296 free(selected_fen_position);
6297 selected_fen_position=NULL;
6301 /* function called when the data to Paste is ready */
6303 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6304 Atom *type, XtPointer value, unsigned long *len, int *format)
6307 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6308 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6309 EditPositionPasteFEN(fenstr);
6313 /* called when Paste Position button is pressed,
6314 * all parameters will be NULL */
6315 void PastePositionProc(w, event, prms, nprms)
6321 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6322 /* (XtSelectionCallbackProc) */ PastePositionCB,
6323 NULL, /* client_data passed to PastePositionCB */
6325 /* better to use the time field from the event that triggered the
6326 * call to this function, but that isn't trivial to get
6334 SendGameSelection(Widget w, Atom *selection, Atom *target,
6335 Atom *type_return, XtPointer *value_return,
6336 unsigned long *length_return, int *format_return)
6338 char *selection_tmp;
6340 if (*target == XA_STRING){
6341 FILE* f = fopen(gameCopyFilename, "r");
6344 if (f == NULL) return False;
6348 selection_tmp = XtMalloc(len + 1);
6349 count = fread(selection_tmp, 1, len, f);
6351 XtFree(selection_tmp);
6354 selection_tmp[len] = NULLCHAR;
6355 *value_return = selection_tmp;
6356 *length_return = len;
6357 *type_return = XA_STRING;
6358 *format_return = 8; /* bits per byte */
6365 /* note: when called from menu all parameters are NULL, so no clue what the
6366 * Widget which was clicked on was, or what the click event was
6368 void CopyGameProc(w, event, prms, nprms)
6376 ret = SaveGameToFile(gameCopyFilename, FALSE);
6379 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6382 NULL/* lose_ownership_proc */ ,
6383 NULL/* transfer_done_proc */);
6386 /* function called when the data to Paste is ready */
6388 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6389 Atom *type, XtPointer value, unsigned long *len, int *format)
6392 if (value == NULL || *len == 0) {
6393 return; /* nothing had been selected to copy */
6395 f = fopen(gamePasteFilename, "w");
6397 DisplayError(_("Can't open temp file"), errno);
6400 fwrite(value, 1, *len, f);
6403 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6406 /* called when Paste Game button is pressed,
6407 * all parameters will be NULL */
6408 void PasteGameProc(w, event, prms, nprms)
6414 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6415 /* (XtSelectionCallbackProc) */ PasteGameCB,
6416 NULL, /* client_data passed to PasteGameCB */
6418 /* better to use the time field from the event that triggered the
6419 * call to this function, but that isn't trivial to get
6429 SaveGameProc(NULL, NULL, NULL, NULL);
6433 void QuitProc(w, event, prms, nprms)
6442 void PauseProc(w, event, prms, nprms)
6452 void MachineBlackProc(w, event, prms, nprms)
6458 MachineBlackEvent();
6461 void MachineWhiteProc(w, event, prms, nprms)
6467 MachineWhiteEvent();
6470 void AnalyzeModeProc(w, event, prms, nprms)
6478 if (!first.analysisSupport) {
6479 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6480 DisplayError(buf, 0);
6483 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6484 if (appData.icsActive) {
6485 if (gameMode != IcsObserving) {
6486 sprintf(buf,_("You are not observing a game"));
6487 DisplayError(buf, 0);
6489 if (appData.icsEngineAnalyze) {
6490 if (appData.debugMode)
6491 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6497 /* if enable, use want disable icsEngineAnalyze */
6498 if (appData.icsEngineAnalyze) {
6503 appData.icsEngineAnalyze = TRUE;
6504 if (appData.debugMode)
6505 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6507 if (!appData.showThinking)
6508 ShowThinkingProc(w,event,prms,nprms);
6513 void AnalyzeFileProc(w, event, prms, nprms)
6519 if (!first.analysisSupport) {
6521 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6522 DisplayError(buf, 0);
6527 if (!appData.showThinking)
6528 ShowThinkingProc(w,event,prms,nprms);
6531 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6532 AnalysisPeriodicEvent(1);
6535 void TwoMachinesProc(w, event, prms, nprms)
6544 void IcsClientProc(w, event, prms, nprms)
6553 void EditGameProc(w, event, prms, nprms)
6562 void EditPositionProc(w, event, prms, nprms)
6568 EditPositionEvent();
6571 void TrainingProc(w, event, prms, nprms)
6580 void EditCommentProc(w, event, prms, nprms)
6587 EditCommentPopDown();
6593 void IcsInputBoxProc(w, event, prms, nprms)
6599 if (ICSInputBoxUp) {
6600 ICSInputBoxPopDown();
6606 void AcceptProc(w, event, prms, nprms)
6615 void DeclineProc(w, event, prms, nprms)
6624 void RematchProc(w, event, prms, nprms)
6633 void CallFlagProc(w, event, prms, nprms)
6642 void DrawProc(w, event, prms, nprms)
6651 void AbortProc(w, event, prms, nprms)
6660 void AdjournProc(w, event, prms, nprms)
6669 void ResignProc(w, event, prms, nprms)
6678 void AdjuWhiteProc(w, event, prms, nprms)
6684 UserAdjudicationEvent(+1);
6687 void AdjuBlackProc(w, event, prms, nprms)
6693 UserAdjudicationEvent(-1);
6696 void AdjuDrawProc(w, event, prms, nprms)
6702 UserAdjudicationEvent(0);
6705 void EnterKeyProc(w, event, prms, nprms)
6711 if (ICSInputBoxUp == True)
6715 void StopObservingProc(w, event, prms, nprms)
6721 StopObservingEvent();
6724 void StopExaminingProc(w, event, prms, nprms)
6730 StopExaminingEvent();
6734 void ForwardProc(w, event, prms, nprms)
6744 void BackwardProc(w, event, prms, nprms)
6753 void ToStartProc(w, event, prms, nprms)
6762 void ToEndProc(w, event, prms, nprms)
6771 void RevertProc(w, event, prms, nprms)
6780 void TruncateGameProc(w, event, prms, nprms)
6786 TruncateGameEvent();
6788 void RetractMoveProc(w, event, prms, nprms)
6797 void MoveNowProc(w, event, prms, nprms)
6807 void AlwaysQueenProc(w, event, prms, nprms)
6815 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6817 if (appData.alwaysPromoteToQueen) {
6818 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6820 XtSetArg(args[0], XtNleftBitmap, None);
6822 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6826 void AnimateDraggingProc(w, event, prms, nprms)
6834 appData.animateDragging = !appData.animateDragging;
6836 if (appData.animateDragging) {
6837 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6840 XtSetArg(args[0], XtNleftBitmap, None);
6842 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6846 void AnimateMovingProc(w, event, prms, nprms)
6854 appData.animate = !appData.animate;
6856 if (appData.animate) {
6857 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6860 XtSetArg(args[0], XtNleftBitmap, None);
6862 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6866 void AutocommProc(w, event, prms, nprms)
6874 appData.autoComment = !appData.autoComment;
6876 if (appData.autoComment) {
6877 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6879 XtSetArg(args[0], XtNleftBitmap, None);
6881 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6886 void AutoflagProc(w, event, prms, nprms)
6894 appData.autoCallFlag = !appData.autoCallFlag;
6896 if (appData.autoCallFlag) {
6897 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6899 XtSetArg(args[0], XtNleftBitmap, None);
6901 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6905 void AutoflipProc(w, event, prms, nprms)
6913 appData.autoFlipView = !appData.autoFlipView;
6915 if (appData.autoFlipView) {
6916 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6918 XtSetArg(args[0], XtNleftBitmap, None);
6920 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6924 void AutobsProc(w, event, prms, nprms)
6932 appData.autoObserve = !appData.autoObserve;
6934 if (appData.autoObserve) {
6935 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6937 XtSetArg(args[0], XtNleftBitmap, None);
6939 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6943 void AutoraiseProc(w, event, prms, nprms)
6951 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6953 if (appData.autoRaiseBoard) {
6954 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6956 XtSetArg(args[0], XtNleftBitmap, None);
6958 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6962 void AutosaveProc(w, event, prms, nprms)
6970 appData.autoSaveGames = !appData.autoSaveGames;
6972 if (appData.autoSaveGames) {
6973 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6975 XtSetArg(args[0], XtNleftBitmap, None);
6977 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6981 void BlindfoldProc(w, event, prms, nprms)
6989 appData.blindfold = !appData.blindfold;
6991 if (appData.blindfold) {
6992 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6994 XtSetArg(args[0], XtNleftBitmap, None);
6996 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6999 DrawPosition(True, NULL);
7002 void TestLegalityProc(w, event, prms, nprms)
7010 appData.testLegality = !appData.testLegality;
7012 if (appData.testLegality) {
7013 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7015 XtSetArg(args[0], XtNleftBitmap, None);
7017 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7022 void FlashMovesProc(w, event, prms, nprms)
7030 if (appData.flashCount == 0) {
7031 appData.flashCount = 3;
7033 appData.flashCount = -appData.flashCount;
7036 if (appData.flashCount > 0) {
7037 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7039 XtSetArg(args[0], XtNleftBitmap, None);
7041 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7045 void FlipViewProc(w, event, prms, nprms)
7051 flipView = !flipView;
7052 DrawPosition(True, NULL);
7055 void GetMoveListProc(w, event, prms, nprms)
7063 appData.getMoveList = !appData.getMoveList;
7065 if (appData.getMoveList) {
7066 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7069 XtSetArg(args[0], XtNleftBitmap, None);
7071 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7076 void HighlightDraggingProc(w, event, prms, nprms)
7084 appData.highlightDragging = !appData.highlightDragging;
7086 if (appData.highlightDragging) {
7087 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7089 XtSetArg(args[0], XtNleftBitmap, None);
7091 XtSetValues(XtNameToWidget(menuBarWidget,
7092 "menuOptions.Highlight Dragging"), args, 1);
7096 void HighlightLastMoveProc(w, event, prms, nprms)
7104 appData.highlightLastMove = !appData.highlightLastMove;
7106 if (appData.highlightLastMove) {
7107 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7109 XtSetArg(args[0], XtNleftBitmap, None);
7111 XtSetValues(XtNameToWidget(menuBarWidget,
7112 "menuOptions.Highlight Last Move"), args, 1);
7115 void IcsAlarmProc(w, event, prms, nprms)
7123 appData.icsAlarm = !appData.icsAlarm;
7125 if (appData.icsAlarm) {
7126 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7128 XtSetArg(args[0], XtNleftBitmap, None);
7130 XtSetValues(XtNameToWidget(menuBarWidget,
7131 "menuOptions.ICS Alarm"), args, 1);
7134 void MoveSoundProc(w, event, prms, nprms)
7142 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7144 if (appData.ringBellAfterMoves) {
7145 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7147 XtSetArg(args[0], XtNleftBitmap, None);
7149 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7154 void OldSaveStyleProc(w, event, prms, nprms)
7162 appData.oldSaveStyle = !appData.oldSaveStyle;
7164 if (appData.oldSaveStyle) {
7165 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7167 XtSetArg(args[0], XtNleftBitmap, None);
7169 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7173 void PeriodicUpdatesProc(w, event, prms, nprms)
7181 PeriodicUpdatesEvent(!appData.periodicUpdates);
7183 if (appData.periodicUpdates) {
7184 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7186 XtSetArg(args[0], XtNleftBitmap, None);
7188 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7192 void PonderNextMoveProc(w, event, prms, nprms)
7200 PonderNextMoveEvent(!appData.ponderNextMove);
7202 if (appData.ponderNextMove) {
7203 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7205 XtSetArg(args[0], XtNleftBitmap, None);
7207 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7211 void PopupExitMessageProc(w, event, prms, nprms)
7219 appData.popupExitMessage = !appData.popupExitMessage;
7221 if (appData.popupExitMessage) {
7222 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7224 XtSetArg(args[0], XtNleftBitmap, None);
7226 XtSetValues(XtNameToWidget(menuBarWidget,
7227 "menuOptions.Popup Exit Message"), args, 1);
7230 void PopupMoveErrorsProc(w, event, prms, nprms)
7238 appData.popupMoveErrors = !appData.popupMoveErrors;
7240 if (appData.popupMoveErrors) {
7241 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7243 XtSetArg(args[0], XtNleftBitmap, None);
7245 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7249 void PremoveProc(w, event, prms, nprms)
7257 appData.premove = !appData.premove;
7259 if (appData.premove) {
7260 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7262 XtSetArg(args[0], XtNleftBitmap, None);
7264 XtSetValues(XtNameToWidget(menuBarWidget,
7265 "menuOptions.Premove"), args, 1);
7268 void QuietPlayProc(w, event, prms, nprms)
7276 appData.quietPlay = !appData.quietPlay;
7278 if (appData.quietPlay) {
7279 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7281 XtSetArg(args[0], XtNleftBitmap, None);
7283 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7287 void ShowCoordsProc(w, event, prms, nprms)
7295 appData.showCoords = !appData.showCoords;
7297 if (appData.showCoords) {
7298 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7300 XtSetArg(args[0], XtNleftBitmap, None);
7302 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7305 DrawPosition(True, NULL);
7308 void ShowThinkingProc(w, event, prms, nprms)
7316 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7317 ShowThinkingEvent();
7320 void HideThinkingProc(w, event, prms, nprms)
7328 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7329 ShowThinkingEvent();
7331 if (appData.hideThinkingFromHuman) {
7332 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7334 XtSetArg(args[0], XtNleftBitmap, None);
7336 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7340 void InfoProc(w, event, prms, nprms)
7347 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7352 void ManProc(w, event, prms, nprms)
7360 if (nprms && *nprms > 0)
7364 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7368 void HintProc(w, event, prms, nprms)
7377 void BookProc(w, event, prms, nprms)
7386 void AboutProc(w, event, prms, nprms)
7394 char *zippy = " (with Zippy code)";
7398 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7399 programVersion, zippy,
7400 "Copyright 1991 Digital Equipment Corporation",
7401 "Enhancements Copyright 1992-2009 Free Software Foundation",
7402 "Enhancements Copyright 2005 Alessandro Scotti",
7403 PACKAGE, " is free software and carries NO WARRANTY;",
7404 "see the file COPYING for more information.");
7405 ErrorPopUp(_("About XBoard"), buf, FALSE);
7408 void DebugProc(w, event, prms, nprms)
7414 appData.debugMode = !appData.debugMode;
7417 void AboutGameProc(w, event, prms, nprms)
7426 void NothingProc(w, event, prms, nprms)
7435 void Iconify(w, event, prms, nprms)
7444 XtSetArg(args[0], XtNiconic, True);
7445 XtSetValues(shellWidget, args, 1);
7448 void DisplayMessage(message, extMessage)
7449 char *message, *extMessage;
7451 /* display a message in the message widget */
7460 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7465 message = extMessage;
7469 /* need to test if messageWidget already exists, since this function
7470 can also be called during the startup, if for example a Xresource
7471 is not set up correctly */
7474 XtSetArg(arg, XtNlabel, message);
7475 XtSetValues(messageWidget, &arg, 1);
7481 void DisplayTitle(text)
7486 char title[MSG_SIZ];
7489 if (text == NULL) text = "";
7491 if (appData.titleInWindow) {
7493 XtSetArg(args[i], XtNlabel, text); i++;
7494 XtSetValues(titleWidget, args, i);
7497 if (*text != NULLCHAR) {
7499 strcpy(title, text);
7500 } else if (appData.icsActive) {
7501 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7502 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7503 } else if (appData.cmailGameName[0] != NULLCHAR) {
7504 snprintf(icon, sizeof(icon), "%s", "CMail");
7505 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7507 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7508 } else if (gameInfo.variant == VariantGothic) {
7509 strcpy(icon, programName);
7510 strcpy(title, GOTHIC);
7513 } else if (gameInfo.variant == VariantFalcon) {
7514 strcpy(icon, programName);
7515 strcpy(title, FALCON);
7517 } else if (appData.noChessProgram) {
7518 strcpy(icon, programName);
7519 strcpy(title, programName);
7521 strcpy(icon, first.tidy);
7522 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7525 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7526 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7527 XtSetValues(shellWidget, args, i);
7531 void DisplayError(message, error)
7538 if (appData.debugMode || appData.matchMode) {
7539 fprintf(stderr, "%s: %s\n", programName, message);
7542 if (appData.debugMode || appData.matchMode) {
7543 fprintf(stderr, "%s: %s: %s\n",
7544 programName, message, strerror(error));
7546 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7549 ErrorPopUp(_("Error"), message, FALSE);
7553 void DisplayMoveError(message)
7558 DrawPosition(FALSE, NULL);
7559 if (appData.debugMode || appData.matchMode) {
7560 fprintf(stderr, "%s: %s\n", programName, message);
7562 if (appData.popupMoveErrors) {
7563 ErrorPopUp(_("Error"), message, FALSE);
7565 DisplayMessage(message, "");
7570 void DisplayFatalError(message, error, status)
7576 errorExitStatus = status;
7578 fprintf(stderr, "%s: %s\n", programName, message);
7580 fprintf(stderr, "%s: %s: %s\n",
7581 programName, message, strerror(error));
7582 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7585 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7586 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7592 void DisplayInformation(message)
7596 ErrorPopUp(_("Information"), message, TRUE);
7599 void DisplayNote(message)
7603 ErrorPopUp(_("Note"), message, FALSE);
7607 NullXErrorCheck(dpy, error_event)
7609 XErrorEvent *error_event;
7614 void DisplayIcsInteractionTitle(message)
7617 if (oldICSInteractionTitle == NULL) {
7618 /* Magic to find the old window title, adapted from vim */
7619 char *wina = getenv("WINDOWID");
7621 Window win = (Window) atoi(wina);
7622 Window root, parent, *children;
7623 unsigned int nchildren;
7624 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7626 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7627 if (!XQueryTree(xDisplay, win, &root, &parent,
7628 &children, &nchildren)) break;
7629 if (children) XFree((void *)children);
7630 if (parent == root || parent == 0) break;
7633 XSetErrorHandler(oldHandler);
7635 if (oldICSInteractionTitle == NULL) {
7636 oldICSInteractionTitle = "xterm";
7639 printf("\033]0;%s\007", message);
7643 char pendingReplyPrefix[MSG_SIZ];
7644 ProcRef pendingReplyPR;
7646 void AskQuestionProc(w, event, prms, nprms)
7653 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7657 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7660 void AskQuestionPopDown()
7662 if (!askQuestionUp) return;
7663 XtPopdown(askQuestionShell);
7664 XtDestroyWidget(askQuestionShell);
7665 askQuestionUp = False;
7668 void AskQuestionReplyAction(w, event, prms, nprms)
7678 reply = XawDialogGetValueString(w = XtParent(w));
7679 strcpy(buf, pendingReplyPrefix);
7680 if (*buf) strcat(buf, " ");
7683 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7684 AskQuestionPopDown();
7686 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7689 void AskQuestionCallback(w, client_data, call_data)
7691 XtPointer client_data, call_data;
7696 XtSetArg(args[0], XtNlabel, &name);
7697 XtGetValues(w, args, 1);
7699 if (strcmp(name, _("cancel")) == 0) {
7700 AskQuestionPopDown();
7702 AskQuestionReplyAction(w, NULL, NULL, NULL);
7706 void AskQuestion(title, question, replyPrefix, pr)
7707 char *title, *question, *replyPrefix;
7711 Widget popup, layout, dialog, edit;
7717 strcpy(pendingReplyPrefix, replyPrefix);
7718 pendingReplyPR = pr;
7721 XtSetArg(args[i], XtNresizable, True); i++;
7722 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7723 askQuestionShell = popup =
7724 XtCreatePopupShell(title, transientShellWidgetClass,
7725 shellWidget, args, i);
7728 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7729 layoutArgs, XtNumber(layoutArgs));
7732 XtSetArg(args[i], XtNlabel, question); i++;
7733 XtSetArg(args[i], XtNvalue, ""); i++;
7734 XtSetArg(args[i], XtNborderWidth, 0); i++;
7735 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7738 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7739 (XtPointer) dialog);
7740 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7741 (XtPointer) dialog);
7743 XtRealizeWidget(popup);
7744 CatchDeleteWindow(popup, "AskQuestionPopDown");
7746 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7747 &x, &y, &win_x, &win_y, &mask);
7749 XtSetArg(args[0], XtNx, x - 10);
7750 XtSetArg(args[1], XtNy, y - 30);
7751 XtSetValues(popup, args, 2);
7753 XtPopup(popup, XtGrabExclusive);
7754 askQuestionUp = True;
7756 edit = XtNameToWidget(dialog, "*value");
7757 XtSetKeyboardFocus(popup, edit);
7765 if (*name == NULLCHAR) {
7767 } else if (strcmp(name, "$") == 0) {
7768 putc(BELLCHAR, stderr);
7771 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7779 PlaySound(appData.soundMove);
7785 PlaySound(appData.soundIcsWin);
7791 PlaySound(appData.soundIcsLoss);
7797 PlaySound(appData.soundIcsDraw);
7801 PlayIcsUnfinishedSound()
7803 PlaySound(appData.soundIcsUnfinished);
7809 PlaySound(appData.soundIcsAlarm);
7815 system("stty echo");
7821 system("stty -echo");
7825 Colorize(cc, continuation)
7830 int count, outCount, error;
7832 if (textColors[(int)cc].bg > 0) {
7833 if (textColors[(int)cc].fg > 0) {
7834 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7835 textColors[(int)cc].fg, textColors[(int)cc].bg);
7837 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7838 textColors[(int)cc].bg);
7841 if (textColors[(int)cc].fg > 0) {
7842 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7843 textColors[(int)cc].fg);
7845 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7848 count = strlen(buf);
7849 outCount = OutputToProcess(NoProc, buf, count, &error);
7850 if (outCount < count) {
7851 DisplayFatalError(_("Error writing to display"), error, 1);
7854 if (continuation) return;
7857 PlaySound(appData.soundShout);
7860 PlaySound(appData.soundSShout);
7863 PlaySound(appData.soundChannel1);
7866 PlaySound(appData.soundChannel);
7869 PlaySound(appData.soundKibitz);
7872 PlaySound(appData.soundTell);
7874 case ColorChallenge:
7875 PlaySound(appData.soundChallenge);
7878 PlaySound(appData.soundRequest);
7881 PlaySound(appData.soundSeek);
7892 return getpwuid(getuid())->pw_name;
7895 static char *ExpandPathName(path)
7898 static char static_buf[2000];
7899 char *d, *s, buf[2000];
7905 while (*s && isspace(*s))
7914 if (*(s+1) == '/') {
7915 strcpy(d, getpwuid(getuid())->pw_dir);
7920 *strchr(buf, '/') = 0;
7921 pwd = getpwnam(buf);
7924 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7928 strcpy(d, pwd->pw_dir);
7929 strcat(d, strchr(s+1, '/'));
7940 static char host_name[MSG_SIZ];
7942 #if HAVE_GETHOSTNAME
7943 gethostname(host_name, MSG_SIZ);
7945 #else /* not HAVE_GETHOSTNAME */
7946 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7947 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7949 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7951 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7952 #endif /* not HAVE_GETHOSTNAME */
7955 XtIntervalId delayedEventTimerXID = 0;
7956 DelayedEventCallback delayedEventCallback = 0;
7961 delayedEventTimerXID = 0;
7962 delayedEventCallback();
7966 ScheduleDelayedEvent(cb, millisec)
7967 DelayedEventCallback cb; long millisec;
7969 if(delayedEventTimerXID && delayedEventCallback == cb)
7970 // [HGM] alive: replace, rather than add or flush identical event
7971 XtRemoveTimeOut(delayedEventTimerXID);
7972 delayedEventCallback = cb;
7973 delayedEventTimerXID =
7974 XtAppAddTimeOut(appContext, millisec,
7975 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7978 DelayedEventCallback
7981 if (delayedEventTimerXID) {
7982 return delayedEventCallback;
7989 CancelDelayedEvent()
7991 if (delayedEventTimerXID) {
7992 XtRemoveTimeOut(delayedEventTimerXID);
7993 delayedEventTimerXID = 0;
7997 XtIntervalId loadGameTimerXID = 0;
7999 int LoadGameTimerRunning()
8001 return loadGameTimerXID != 0;
8004 int StopLoadGameTimer()
8006 if (loadGameTimerXID != 0) {
8007 XtRemoveTimeOut(loadGameTimerXID);
8008 loadGameTimerXID = 0;
8016 LoadGameTimerCallback(arg, id)
8020 loadGameTimerXID = 0;
8025 StartLoadGameTimer(millisec)
8029 XtAppAddTimeOut(appContext, millisec,
8030 (XtTimerCallbackProc) LoadGameTimerCallback,
8034 XtIntervalId analysisClockXID = 0;
8037 AnalysisClockCallback(arg, id)
8041 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8042 || appData.icsEngineAnalyze) { // [DM]
8043 AnalysisPeriodicEvent(0);
8044 StartAnalysisClock();
8049 StartAnalysisClock()
8052 XtAppAddTimeOut(appContext, 2000,
8053 (XtTimerCallbackProc) AnalysisClockCallback,
8057 XtIntervalId clockTimerXID = 0;
8059 int ClockTimerRunning()
8061 return clockTimerXID != 0;
8064 int StopClockTimer()
8066 if (clockTimerXID != 0) {
8067 XtRemoveTimeOut(clockTimerXID);
8076 ClockTimerCallback(arg, id)
8085 StartClockTimer(millisec)
8089 XtAppAddTimeOut(appContext, millisec,
8090 (XtTimerCallbackProc) ClockTimerCallback,
8095 DisplayTimerLabel(w, color, timer, highlight)
8104 /* check for low time warning */
8105 Pixel foregroundOrWarningColor = timerForegroundPixel;
8108 appData.lowTimeWarning &&
8109 (timer / 1000) < appData.icsAlarmTime)
8110 foregroundOrWarningColor = lowTimeWarningColor;
8112 if (appData.clockMode) {
8113 sprintf(buf, "%s: %s", color, TimeString(timer));
8114 XtSetArg(args[0], XtNlabel, buf);
8116 sprintf(buf, "%s ", color);
8117 XtSetArg(args[0], XtNlabel, buf);
8122 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8123 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8125 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8126 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8129 XtSetValues(w, args, 3);
8133 DisplayWhiteClock(timeRemaining, highlight)
8139 if(appData.noGUI) return;
8140 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8141 if (highlight && iconPixmap == bIconPixmap) {
8142 iconPixmap = wIconPixmap;
8143 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8144 XtSetValues(shellWidget, args, 1);
8149 DisplayBlackClock(timeRemaining, highlight)
8155 if(appData.noGUI) return;
8156 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8157 if (highlight && iconPixmap == wIconPixmap) {
8158 iconPixmap = bIconPixmap;
8159 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8160 XtSetValues(shellWidget, args, 1);
8178 int StartChildProcess(cmdLine, dir, pr)
8185 int to_prog[2], from_prog[2];
8189 if (appData.debugMode) {
8190 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8193 /* We do NOT feed the cmdLine to the shell; we just
8194 parse it into blank-separated arguments in the
8195 most simple-minded way possible.
8198 strcpy(buf, cmdLine);
8203 if (p == NULL) break;
8208 SetUpChildIO(to_prog, from_prog);
8210 if ((pid = fork()) == 0) {
8212 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8213 close(to_prog[1]); // first close the unused pipe ends
8214 close(from_prog[0]);
8215 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8216 dup2(from_prog[1], 1);
8217 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8218 close(from_prog[1]); // and closing again loses one of the pipes!
8219 if(fileno(stderr) >= 2) // better safe than sorry...
8220 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8222 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8227 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8229 execvp(argv[0], argv);
8231 /* If we get here, exec failed */
8236 /* Parent process */
8238 close(from_prog[1]);
8240 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8243 cp->fdFrom = from_prog[0];
8244 cp->fdTo = to_prog[1];
8249 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8250 static RETSIGTYPE AlarmCallBack(int n)
8256 DestroyChildProcess(pr, signalType)
8260 ChildProc *cp = (ChildProc *) pr;
8262 if (cp->kind != CPReal) return;
8264 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8265 signal(SIGALRM, AlarmCallBack);
8267 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8268 kill(cp->pid, SIGKILL); // kill it forcefully
8269 wait((int *) 0); // and wait again
8273 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8275 /* Process is exiting either because of the kill or because of
8276 a quit command sent by the backend; either way, wait for it to die.
8285 InterruptChildProcess(pr)
8288 ChildProc *cp = (ChildProc *) pr;
8290 if (cp->kind != CPReal) return;
8291 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8294 int OpenTelnet(host, port, pr)
8299 char cmdLine[MSG_SIZ];
8301 if (port[0] == NULLCHAR) {
8302 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8304 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8306 return StartChildProcess(cmdLine, "", pr);
8309 int OpenTCP(host, port, pr)
8315 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8316 #else /* !OMIT_SOCKETS */
8318 struct sockaddr_in sa;
8320 unsigned short uport;
8323 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8327 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8328 sa.sin_family = AF_INET;
8329 sa.sin_addr.s_addr = INADDR_ANY;
8330 uport = (unsigned short) 0;
8331 sa.sin_port = htons(uport);
8332 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8336 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8337 if (!(hp = gethostbyname(host))) {
8339 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8340 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8341 hp->h_addrtype = AF_INET;
8343 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8344 hp->h_addr_list[0] = (char *) malloc(4);
8345 hp->h_addr_list[0][0] = b0;
8346 hp->h_addr_list[0][1] = b1;
8347 hp->h_addr_list[0][2] = b2;
8348 hp->h_addr_list[0][3] = b3;
8353 sa.sin_family = hp->h_addrtype;
8354 uport = (unsigned short) atoi(port);
8355 sa.sin_port = htons(uport);
8356 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8358 if (connect(s, (struct sockaddr *) &sa,
8359 sizeof(struct sockaddr_in)) < 0) {
8363 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8370 #endif /* !OMIT_SOCKETS */
8375 int OpenCommPort(name, pr)
8382 fd = open(name, 2, 0);
8383 if (fd < 0) return errno;
8385 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8395 int OpenLoopback(pr)
8401 SetUpChildIO(to, from);
8403 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8406 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8413 int OpenRcmd(host, user, cmd, pr)
8414 char *host, *user, *cmd;
8417 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8421 #define INPUT_SOURCE_BUF_SIZE 8192
8430 char buf[INPUT_SOURCE_BUF_SIZE];
8435 DoInputCallback(closure, source, xid)
8440 InputSource *is = (InputSource *) closure;
8445 if (is->lineByLine) {
8446 count = read(is->fd, is->unused,
8447 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8449 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8452 is->unused += count;
8454 while (p < is->unused) {
8455 q = memchr(p, '\n', is->unused - p);
8456 if (q == NULL) break;
8458 (is->func)(is, is->closure, p, q - p, 0);
8462 while (p < is->unused) {
8467 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8472 (is->func)(is, is->closure, is->buf, count, error);
8476 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8483 ChildProc *cp = (ChildProc *) pr;
8485 is = (InputSource *) calloc(1, sizeof(InputSource));
8486 is->lineByLine = lineByLine;
8490 is->fd = fileno(stdin);
8492 is->kind = cp->kind;
8493 is->fd = cp->fdFrom;
8496 is->unused = is->buf;
8499 is->xid = XtAppAddInput(appContext, is->fd,
8500 (XtPointer) (XtInputReadMask),
8501 (XtInputCallbackProc) DoInputCallback,
8503 is->closure = closure;
8504 return (InputSourceRef) is;
8508 RemoveInputSource(isr)
8511 InputSource *is = (InputSource *) isr;
8513 if (is->xid == 0) return;
8514 XtRemoveInput(is->xid);
8518 int OutputToProcess(pr, message, count, outError)
8524 static int line = 0;
8525 ChildProc *cp = (ChildProc *) pr;
8530 if (appData.noJoin || !appData.useInternalWrap)
8531 outCount = fwrite(message, 1, count, stdout);
8534 int width = get_term_width();
8535 int len = wrap(NULL, message, count, width, &line);
8536 char *msg = malloc(len);
8540 outCount = fwrite(message, 1, count, stdout);
8543 dbgchk = wrap(msg, message, count, width, &line);
8544 if (dbgchk != len && appData.debugMode)
8545 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
8546 outCount = fwrite(msg, 1, dbgchk, stdout);
8552 outCount = write(cp->fdTo, message, count);
8562 /* Output message to process, with "ms" milliseconds of delay
8563 between each character. This is needed when sending the logon
8564 script to ICC, which for some reason doesn't like the
8565 instantaneous send. */
8566 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8573 ChildProc *cp = (ChildProc *) pr;
8578 r = write(cp->fdTo, message++, 1);
8591 /**** Animation code by Hugh Fisher, DCS, ANU.
8593 Known problem: if a window overlapping the board is
8594 moved away while a piece is being animated underneath,
8595 the newly exposed area won't be updated properly.
8596 I can live with this.
8598 Known problem: if you look carefully at the animation
8599 of pieces in mono mode, they are being drawn as solid
8600 shapes without interior detail while moving. Fixing
8601 this would be a major complication for minimal return.
8604 /* Masks for XPM pieces. Black and white pieces can have
8605 different shapes, but in the interest of retaining my
8606 sanity pieces must have the same outline on both light
8607 and dark squares, and all pieces must use the same
8608 background square colors/images. */
8610 static int xpmDone = 0;
8613 CreateAnimMasks (pieceDepth)
8620 unsigned long plane;
8623 /* Need a bitmap just to get a GC with right depth */
8624 buf = XCreatePixmap(xDisplay, xBoardWindow,
8626 values.foreground = 1;
8627 values.background = 0;
8628 /* Don't use XtGetGC, not read only */
8629 maskGC = XCreateGC(xDisplay, buf,
8630 GCForeground | GCBackground, &values);
8631 XFreePixmap(xDisplay, buf);
8633 buf = XCreatePixmap(xDisplay, xBoardWindow,
8634 squareSize, squareSize, pieceDepth);
8635 values.foreground = XBlackPixel(xDisplay, xScreen);
8636 values.background = XWhitePixel(xDisplay, xScreen);
8637 bufGC = XCreateGC(xDisplay, buf,
8638 GCForeground | GCBackground, &values);
8640 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8641 /* Begin with empty mask */
8642 if(!xpmDone) // [HGM] pieces: keep using existing
8643 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8644 squareSize, squareSize, 1);
8645 XSetFunction(xDisplay, maskGC, GXclear);
8646 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8647 0, 0, squareSize, squareSize);
8649 /* Take a copy of the piece */
8654 XSetFunction(xDisplay, bufGC, GXcopy);
8655 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8657 0, 0, squareSize, squareSize, 0, 0);
8659 /* XOR the background (light) over the piece */
8660 XSetFunction(xDisplay, bufGC, GXxor);
8662 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8663 0, 0, squareSize, squareSize, 0, 0);
8665 XSetForeground(xDisplay, bufGC, lightSquareColor);
8666 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8669 /* We now have an inverted piece image with the background
8670 erased. Construct mask by just selecting all the non-zero
8671 pixels - no need to reconstruct the original image. */
8672 XSetFunction(xDisplay, maskGC, GXor);
8674 /* Might be quicker to download an XImage and create bitmap
8675 data from it rather than this N copies per piece, but it
8676 only takes a fraction of a second and there is a much
8677 longer delay for loading the pieces. */
8678 for (n = 0; n < pieceDepth; n ++) {
8679 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8680 0, 0, squareSize, squareSize,
8686 XFreePixmap(xDisplay, buf);
8687 XFreeGC(xDisplay, bufGC);
8688 XFreeGC(xDisplay, maskGC);
8692 InitAnimState (anim, info)
8694 XWindowAttributes * info;
8699 /* Each buffer is square size, same depth as window */
8700 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8701 squareSize, squareSize, info->depth);
8702 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8703 squareSize, squareSize, info->depth);
8705 /* Create a plain GC for blitting */
8706 mask = GCForeground | GCBackground | GCFunction |
8707 GCPlaneMask | GCGraphicsExposures;
8708 values.foreground = XBlackPixel(xDisplay, xScreen);
8709 values.background = XWhitePixel(xDisplay, xScreen);
8710 values.function = GXcopy;
8711 values.plane_mask = AllPlanes;
8712 values.graphics_exposures = False;
8713 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8715 /* Piece will be copied from an existing context at
8716 the start of each new animation/drag. */
8717 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8719 /* Outline will be a read-only copy of an existing */
8720 anim->outlineGC = None;
8726 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8727 XWindowAttributes info;
8729 if (xpmDone && gameInfo.variant == old) return;
8730 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8731 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8733 InitAnimState(&game, &info);
8734 InitAnimState(&player, &info);
8736 /* For XPM pieces, we need bitmaps to use as masks. */
8738 CreateAnimMasks(info.depth);
8744 static Boolean frameWaiting;
8746 static RETSIGTYPE FrameAlarm (sig)
8749 frameWaiting = False;
8750 /* In case System-V style signals. Needed?? */
8751 signal(SIGALRM, FrameAlarm);
8758 struct itimerval delay;
8760 XSync(xDisplay, False);
8763 frameWaiting = True;
8764 signal(SIGALRM, FrameAlarm);
8765 delay.it_interval.tv_sec =
8766 delay.it_value.tv_sec = time / 1000;
8767 delay.it_interval.tv_usec =
8768 delay.it_value.tv_usec = (time % 1000) * 1000;
8769 setitimer(ITIMER_REAL, &delay, NULL);
8770 while (frameWaiting) pause();
8771 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8772 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8773 setitimer(ITIMER_REAL, &delay, NULL);
8783 XSync(xDisplay, False);
8785 usleep(time * 1000);
8790 /* Convert board position to corner of screen rect and color */
8793 ScreenSquare(column, row, pt, color)
8794 int column; int row; XPoint * pt; int * color;
8797 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8798 pt->y = lineGap + row * (squareSize + lineGap);
8800 pt->x = lineGap + column * (squareSize + lineGap);
8801 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8803 *color = SquareColor(row, column);
8806 /* Convert window coords to square */
8809 BoardSquare(x, y, column, row)
8810 int x; int y; int * column; int * row;
8812 *column = EventToSquare(x, BOARD_WIDTH);
8813 if (flipView && *column >= 0)
8814 *column = BOARD_WIDTH - 1 - *column;
8815 *row = EventToSquare(y, BOARD_HEIGHT);
8816 if (!flipView && *row >= 0)
8817 *row = BOARD_HEIGHT - 1 - *row;
8822 #undef Max /* just in case */
8824 #define Max(a, b) ((a) > (b) ? (a) : (b))
8825 #define Min(a, b) ((a) < (b) ? (a) : (b))
8828 SetRect(rect, x, y, width, height)
8829 XRectangle * rect; int x; int y; int width; int height;
8833 rect->width = width;
8834 rect->height = height;
8837 /* Test if two frames overlap. If they do, return
8838 intersection rect within old and location of
8839 that rect within new. */
8842 Intersect(old, new, size, area, pt)
8843 XPoint * old; XPoint * new;
8844 int size; XRectangle * area; XPoint * pt;
8846 if (old->x > new->x + size || new->x > old->x + size ||
8847 old->y > new->y + size || new->y > old->y + size) {
8850 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8851 size - abs(old->x - new->x), size - abs(old->y - new->y));
8852 pt->x = Max(old->x - new->x, 0);
8853 pt->y = Max(old->y - new->y, 0);
8858 /* For two overlapping frames, return the rect(s)
8859 in the old that do not intersect with the new. */
8862 CalcUpdateRects(old, new, size, update, nUpdates)
8863 XPoint * old; XPoint * new; int size;
8864 XRectangle update[]; int * nUpdates;
8868 /* If old = new (shouldn't happen) then nothing to draw */
8869 if (old->x == new->x && old->y == new->y) {
8873 /* Work out what bits overlap. Since we know the rects
8874 are the same size we don't need a full intersect calc. */
8876 /* Top or bottom edge? */
8877 if (new->y > old->y) {
8878 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8880 } else if (old->y > new->y) {
8881 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8882 size, old->y - new->y);
8885 /* Left or right edge - don't overlap any update calculated above. */
8886 if (new->x > old->x) {
8887 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8888 new->x - old->x, size - abs(new->y - old->y));
8890 } else if (old->x > new->x) {
8891 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8892 old->x - new->x, size - abs(new->y - old->y));
8899 /* Generate a series of frame coords from start->mid->finish.
8900 The movement rate doubles until the half way point is
8901 reached, then halves back down to the final destination,
8902 which gives a nice slow in/out effect. The algorithmn
8903 may seem to generate too many intermediates for short
8904 moves, but remember that the purpose is to attract the
8905 viewers attention to the piece about to be moved and
8906 then to where it ends up. Too few frames would be less
8910 Tween(start, mid, finish, factor, frames, nFrames)
8911 XPoint * start; XPoint * mid;
8912 XPoint * finish; int factor;
8913 XPoint frames[]; int * nFrames;
8915 int fraction, n, count;
8919 /* Slow in, stepping 1/16th, then 1/8th, ... */
8921 for (n = 0; n < factor; n++)
8923 for (n = 0; n < factor; n++) {
8924 frames[count].x = start->x + (mid->x - start->x) / fraction;
8925 frames[count].y = start->y + (mid->y - start->y) / fraction;
8927 fraction = fraction / 2;
8931 frames[count] = *mid;
8934 /* Slow out, stepping 1/2, then 1/4, ... */
8936 for (n = 0; n < factor; n++) {
8937 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8938 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8940 fraction = fraction * 2;
8945 /* Draw a piece on the screen without disturbing what's there */
8948 SelectGCMask(piece, clip, outline, mask)
8949 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8953 /* Bitmap for piece being moved. */
8954 if (appData.monoMode) {
8955 *mask = *pieceToSolid(piece);
8956 } else if (useImages) {
8958 *mask = xpmMask[piece];
8960 *mask = ximMaskPm[piece];
8963 *mask = *pieceToSolid(piece);
8966 /* GC for piece being moved. Square color doesn't matter, but
8967 since it gets modified we make a copy of the original. */
8969 if (appData.monoMode)
8974 if (appData.monoMode)
8979 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8981 /* Outline only used in mono mode and is not modified */
8983 *outline = bwPieceGC;
8985 *outline = wbPieceGC;
8989 OverlayPiece(piece, clip, outline, dest)
8990 ChessSquare piece; GC clip; GC outline; Drawable dest;
8995 /* Draw solid rectangle which will be clipped to shape of piece */
8996 XFillRectangle(xDisplay, dest, clip,
8997 0, 0, squareSize, squareSize);
8998 if (appData.monoMode)
8999 /* Also draw outline in contrasting color for black
9000 on black / white on white cases */
9001 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9002 0, 0, squareSize, squareSize, 0, 0, 1);
9004 /* Copy the piece */
9009 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9011 0, 0, squareSize, squareSize,
9016 /* Animate the movement of a single piece */
9019 BeginAnimation(anim, piece, startColor, start)
9027 /* The old buffer is initialised with the start square (empty) */
9028 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9029 anim->prevFrame = *start;
9031 /* The piece will be drawn using its own bitmap as a matte */
9032 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9033 XSetClipMask(xDisplay, anim->pieceGC, mask);
9037 AnimationFrame(anim, frame, piece)
9042 XRectangle updates[4];
9047 /* Save what we are about to draw into the new buffer */
9048 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9049 frame->x, frame->y, squareSize, squareSize,
9052 /* Erase bits of the previous frame */
9053 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9054 /* Where the new frame overlapped the previous,
9055 the contents in newBuf are wrong. */
9056 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9057 overlap.x, overlap.y,
9058 overlap.width, overlap.height,
9060 /* Repaint the areas in the old that don't overlap new */
9061 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9062 for (i = 0; i < count; i++)
9063 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9064 updates[i].x - anim->prevFrame.x,
9065 updates[i].y - anim->prevFrame.y,
9066 updates[i].width, updates[i].height,
9067 updates[i].x, updates[i].y);
9069 /* Easy when no overlap */
9070 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9071 0, 0, squareSize, squareSize,
9072 anim->prevFrame.x, anim->prevFrame.y);
9075 /* Save this frame for next time round */
9076 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9077 0, 0, squareSize, squareSize,
9079 anim->prevFrame = *frame;
9081 /* Draw piece over original screen contents, not current,
9082 and copy entire rect. Wipes out overlapping piece images. */
9083 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9084 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9085 0, 0, squareSize, squareSize,
9086 frame->x, frame->y);
9090 EndAnimation (anim, finish)
9094 XRectangle updates[4];
9099 /* The main code will redraw the final square, so we
9100 only need to erase the bits that don't overlap. */
9101 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9102 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9103 for (i = 0; i < count; i++)
9104 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9105 updates[i].x - anim->prevFrame.x,
9106 updates[i].y - anim->prevFrame.y,
9107 updates[i].width, updates[i].height,
9108 updates[i].x, updates[i].y);
9110 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9111 0, 0, squareSize, squareSize,
9112 anim->prevFrame.x, anim->prevFrame.y);
9117 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9119 ChessSquare piece; int startColor;
9120 XPoint * start; XPoint * finish;
9121 XPoint frames[]; int nFrames;
9125 BeginAnimation(anim, piece, startColor, start);
9126 for (n = 0; n < nFrames; n++) {
9127 AnimationFrame(anim, &(frames[n]), piece);
9128 FrameDelay(appData.animSpeed);
9130 EndAnimation(anim, finish);
9133 /* Main control logic for deciding what to animate and how */
9136 AnimateMove(board, fromX, fromY, toX, toY)
9145 XPoint start, finish, mid;
9146 XPoint frames[kFactor * 2 + 1];
9147 int nFrames, startColor, endColor;
9149 /* Are we animating? */
9150 if (!appData.animate || appData.blindfold)
9153 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9154 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9155 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9157 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9158 piece = board[fromY][fromX];
9159 if (piece >= EmptySquare) return;
9164 hop = (piece == WhiteKnight || piece == BlackKnight);
9167 if (appData.debugMode) {
9168 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9169 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9170 piece, fromX, fromY, toX, toY); }
9172 ScreenSquare(fromX, fromY, &start, &startColor);
9173 ScreenSquare(toX, toY, &finish, &endColor);
9176 /* Knight: make diagonal movement then straight */
9177 if (abs(toY - fromY) < abs(toX - fromX)) {
9178 mid.x = start.x + (finish.x - start.x) / 2;
9182 mid.y = start.y + (finish.y - start.y) / 2;
9185 mid.x = start.x + (finish.x - start.x) / 2;
9186 mid.y = start.y + (finish.y - start.y) / 2;
9189 /* Don't use as many frames for very short moves */
9190 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9191 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9193 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9194 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9196 /* Be sure end square is redrawn */
9197 damage[toY][toX] = True;
9201 DragPieceBegin(x, y)
9204 int boardX, boardY, color;
9207 /* Are we animating? */
9208 if (!appData.animateDragging || appData.blindfold)
9211 /* Figure out which square we start in and the
9212 mouse position relative to top left corner. */
9213 BoardSquare(x, y, &boardX, &boardY);
9214 player.startBoardX = boardX;
9215 player.startBoardY = boardY;
9216 ScreenSquare(boardX, boardY, &corner, &color);
9217 player.startSquare = corner;
9218 player.startColor = color;
9219 /* As soon as we start dragging, the piece will jump slightly to
9220 be centered over the mouse pointer. */
9221 player.mouseDelta.x = squareSize/2;
9222 player.mouseDelta.y = squareSize/2;
9223 /* Initialise animation */
9224 player.dragPiece = PieceForSquare(boardX, boardY);
9226 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9227 player.dragActive = True;
9228 BeginAnimation(&player, player.dragPiece, color, &corner);
9229 /* Mark this square as needing to be redrawn. Note that
9230 we don't remove the piece though, since logically (ie
9231 as seen by opponent) the move hasn't been made yet. */
9232 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9233 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9234 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9235 corner.x, corner.y, squareSize, squareSize,
9236 0, 0); // [HGM] zh: unstack in stead of grab
9237 damage[boardY][boardX] = True;
9239 player.dragActive = False;
9249 /* Are we animating? */
9250 if (!appData.animateDragging || appData.blindfold)
9254 if (! player.dragActive)
9256 /* Move piece, maintaining same relative position
9257 of mouse within square */
9258 corner.x = x - player.mouseDelta.x;
9259 corner.y = y - player.mouseDelta.y;
9260 AnimationFrame(&player, &corner, player.dragPiece);
9262 if (appData.highlightDragging) {
9264 BoardSquare(x, y, &boardX, &boardY);
9265 SetHighlights(fromX, fromY, boardX, boardY);
9274 int boardX, boardY, color;
9277 /* Are we animating? */
9278 if (!appData.animateDragging || appData.blindfold)
9282 if (! player.dragActive)
9284 /* Last frame in sequence is square piece is
9285 placed on, which may not match mouse exactly. */
9286 BoardSquare(x, y, &boardX, &boardY);
9287 ScreenSquare(boardX, boardY, &corner, &color);
9288 EndAnimation(&player, &corner);
9290 /* Be sure end square is redrawn */
9291 damage[boardY][boardX] = True;
9293 /* This prevents weird things happening with fast successive
9294 clicks which on my Sun at least can cause motion events
9295 without corresponding press/release. */
9296 player.dragActive = False;
9299 /* Handle expose event while piece being dragged */
9304 if (!player.dragActive || appData.blindfold)
9307 /* What we're doing: logically, the move hasn't been made yet,
9308 so the piece is still in it's original square. But visually
9309 it's being dragged around the board. So we erase the square
9310 that the piece is on and draw it at the last known drag point. */
9311 BlankSquare(player.startSquare.x, player.startSquare.y,
9312 player.startColor, EmptySquare, xBoardWindow);
9313 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9314 damage[player.startBoardY][player.startBoardX] = TRUE;
9318 SetProgramStats( FrontEndProgramStats * stats )
9321 // [HGM] done, but perhaps backend should call this directly?
9322 EngineOutputUpdate( stats );
9325 #include <sys/ioctl.h>
9326 int get_term_width()
9328 int fd, default_width;
9331 default_width = 79; // this is FICS default anyway...
9333 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9335 if (!ioctl(fd, TIOCGSIZE, &win))
9336 default_width = win.ts_cols;
9337 #elif defined(TIOCGWINSZ)
9339 if (!ioctl(fd, TIOCGWINSZ, &win))
9340 default_width = win.ws_col;
9342 return default_width;
9345 void update_ics_width()
9347 static int old_width = 0;
9348 int new_width = get_term_width();
9350 if (old_width != new_width)
9351 ics_printf("set width %d\n", new_width);
9352 old_width = new_width;
9355 void NotifyFrontendLogin()