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>
147 #include <X11/Xmu/Atoms.h>
149 #include <X11/Xaw3d/Dialog.h>
150 #include <X11/Xaw3d/Form.h>
151 #include <X11/Xaw3d/List.h>
152 #include <X11/Xaw3d/Label.h>
153 #include <X11/Xaw3d/SimpleMenu.h>
154 #include <X11/Xaw3d/SmeBSB.h>
155 #include <X11/Xaw3d/SmeLine.h>
156 #include <X11/Xaw3d/Box.h>
157 #include <X11/Xaw3d/MenuButton.h>
158 #include <X11/Xaw3d/Text.h>
159 #include <X11/Xaw3d/AsciiText.h>
161 #include <X11/Xaw/Dialog.h>
162 #include <X11/Xaw/Form.h>
163 #include <X11/Xaw/List.h>
164 #include <X11/Xaw/Label.h>
165 #include <X11/Xaw/SimpleMenu.h>
166 #include <X11/Xaw/SmeBSB.h>
167 #include <X11/Xaw/SmeLine.h>
168 #include <X11/Xaw/Box.h>
169 #include <X11/Xaw/MenuButton.h>
170 #include <X11/Xaw/Text.h>
171 #include <X11/Xaw/AsciiText.h>
174 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
179 #include "pixmaps/pixmaps.h"
180 #define IMAGE_EXT "xpm"
182 #define IMAGE_EXT "xim"
183 #include "bitmaps/bitmaps.h"
186 #include "bitmaps/icon_white.bm"
187 #include "bitmaps/icon_black.bm"
188 #include "bitmaps/checkmark.bm"
190 #include "frontend.h"
195 #include "xgamelist.h"
196 #include "xhistory.h"
197 #include "xedittags.h"
200 // must be moved to xengineoutput.h
202 void EngineOutputProc P((Widget w, XEvent *event,
203 String *prms, Cardinal *nprms));
210 #define usleep(t) _sleep2(((t)+500)/1000)
214 # define _(s) gettext (s)
215 # define N_(s) gettext_noop (s)
231 int main P((int argc, char **argv));
232 RETSIGTYPE CmailSigHandler P((int sig));
233 RETSIGTYPE IntSigHandler P((int sig));
234 RETSIGTYPE TermSizeSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244 String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248 u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254 String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256 String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258 String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272 FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopDown P((void));
284 void PromotionCallback P((Widget w, XtPointer client_data,
285 XtPointer call_data));
286 void EditCommentPopDown P((void));
287 void EditCommentCallback P((Widget w, XtPointer client_data,
288 XtPointer call_data));
289 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
290 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
291 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
294 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
296 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
298 void LoadPositionProc P((Widget w, XEvent *event,
299 String *prms, Cardinal *nprms));
300 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
302 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
304 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
306 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
308 void PastePositionProc P((Widget w, XEvent *event, String *prms,
310 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SavePositionProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
318 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
319 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
322 void MachineWhiteProc P((Widget w, XEvent *event,
323 String *prms, Cardinal *nprms));
324 void AnalyzeModeProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void AnalyzeFileProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
330 void IcsClientProc P((Widget w, XEvent *event, String *prms,
332 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void EditPositionProc P((Widget w, XEvent *event,
334 String *prms, Cardinal *nprms));
335 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void EditCommentProc P((Widget w, XEvent *event,
337 String *prms, Cardinal *nprms));
338 void IcsInputBoxProc P((Widget w, XEvent *event,
339 String *prms, Cardinal *nprms));
340 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void StopObservingProc P((Widget w, XEvent *event, String *prms,
354 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
356 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
363 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
365 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
368 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
370 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
372 void AutocommProc P((Widget w, XEvent *event, String *prms,
374 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutobsProc P((Widget w, XEvent *event, String *prms,
378 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
383 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
386 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
388 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
390 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
394 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
396 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
398 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
400 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
402 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
406 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
408 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
410 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
412 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void DisplayMove P((int moveNumber));
422 void DisplayTitle P((char *title));
423 void ICSInitScript P((void));
424 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
425 void ErrorPopUp P((char *title, char *text, int modal));
426 void ErrorPopDown P((void));
427 static char *ExpandPathName P((char *path));
428 static void CreateAnimVars P((void));
429 static void DragPieceMove P((int x, int y));
430 static void DrawDragPiece P((void));
431 char *ModeToWidgetName P((GameMode mode));
432 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void ShufflePopDown P(());
440 void EnginePopDown P(());
441 void UciPopDown P(());
442 void TimeControlPopDown P(());
443 void NewVariantPopDown P(());
444 void SettingsPopDown P(());
445 void update_ics_width P(());
446 int get_term_width P(());
448 * XBoard depends on Xt R4 or higher
450 int xtVersion = XtSpecificationRelease;
455 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
456 jailSquareColor, highlightSquareColor, premoveHighlightColor;
457 Pixel lowTimeWarningColor;
458 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
459 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
460 wjPieceGC, bjPieceGC, prelineGC, countGC;
461 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
462 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
463 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
464 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
465 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
466 ICSInputShell, fileNameShell, askQuestionShell;
467 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
468 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
469 Font clockFontID, coordFontID, countFontID;
470 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
471 XtAppContext appContext;
473 char *oldICSInteractionTitle;
477 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
479 Position commentX = -1, commentY = -1;
480 Dimension commentW, commentH;
482 int squareSize, smallLayout = 0, tinyLayout = 0,
483 marginW, marginH, // [HGM] for run-time resizing
484 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
485 ICSInputBoxUp = False, askQuestionUp = False,
486 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
487 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
488 Pixel timerForegroundPixel, timerBackgroundPixel;
489 Pixel buttonForegroundPixel, buttonBackgroundPixel;
490 char *chessDir, *programName, *programVersion,
491 *gameCopyFilename, *gamePasteFilename;
495 Pixmap pieceBitmap[2][(int)BlackPawn];
496 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
497 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
498 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
499 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
500 int useImages, useImageSqs;
501 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
502 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
503 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
504 XImage *ximLightSquare, *ximDarkSquare;
507 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
508 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
510 #define White(piece) ((int)(piece) < (int)BlackPawn)
512 /* Variables for doing smooth animation. This whole thing
513 would be much easier if the board was double-buffered,
514 but that would require a fairly major rewrite. */
519 GC blitGC, pieceGC, outlineGC;
520 XPoint startSquare, prevFrame, mouseDelta;
524 int startBoardX, startBoardY;
527 /* There can be two pieces being animated at once: a player
528 can begin dragging a piece before the remote opponent has moved. */
530 static AnimState game, player;
532 /* Bitmaps for use as masks when drawing XPM pieces.
533 Need one for each black and white piece. */
534 static Pixmap xpmMask[BlackKing + 1];
536 /* This magic number is the number of intermediate frames used
537 in each half of the animation. For short moves it's reduced
538 by 1. The total number of frames will be factor * 2 + 1. */
541 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
543 MenuItem fileMenu[] = {
544 {N_("New Game"), ResetProc},
545 {N_("New Shuffle Game ..."), ShuffleMenuProc},
546 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
547 {"----", NothingProc},
548 {N_("Load Game"), LoadGameProc},
549 {N_("Load Next Game"), LoadNextGameProc},
550 {N_("Load Previous Game"), LoadPrevGameProc},
551 {N_("Reload Same Game"), ReloadGameProc},
552 {N_("Save Game"), SaveGameProc},
553 {"----", NothingProc},
554 {N_("Copy Game"), CopyGameProc},
555 {N_("Paste Game"), PasteGameProc},
556 {"----", NothingProc},
557 {N_("Load Position"), LoadPositionProc},
558 {N_("Load Next Position"), LoadNextPositionProc},
559 {N_("Load Previous Position"), LoadPrevPositionProc},
560 {N_("Reload Same Position"), ReloadPositionProc},
561 {N_("Save Position"), SavePositionProc},
562 {"----", NothingProc},
563 {N_("Copy Position"), CopyPositionProc},
564 {N_("Paste Position"), PastePositionProc},
565 {"----", NothingProc},
566 {N_("Mail Move"), MailMoveProc},
567 {N_("Reload CMail Message"), ReloadCmailMsgProc},
568 {"----", NothingProc},
569 {N_("Exit"), QuitProc},
573 MenuItem modeMenu[] = {
574 {N_("Machine White"), MachineWhiteProc},
575 {N_("Machine Black"), MachineBlackProc},
576 {N_("Two Machines"), TwoMachinesProc},
577 {N_("Analysis Mode"), AnalyzeModeProc},
578 {N_("Analyze File"), AnalyzeFileProc },
579 {N_("ICS Client"), IcsClientProc},
580 {N_("Edit Game"), EditGameProc},
581 {N_("Edit Position"), EditPositionProc},
582 {N_("Training"), TrainingProc},
583 {"----", NothingProc},
584 {N_("Show Engine Output"), EngineOutputProc},
585 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
586 {N_("Show Game List"), ShowGameListProc},
587 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
588 {"----", NothingProc},
589 {N_("Edit Tags"), EditTagsProc},
590 {N_("Edit Comment"), EditCommentProc},
591 {N_("ICS Input Box"), IcsInputBoxProc},
592 {N_("Pause"), PauseProc},
596 MenuItem actionMenu[] = {
597 {N_("Accept"), AcceptProc},
598 {N_("Decline"), DeclineProc},
599 {N_("Rematch"), RematchProc},
600 {"----", NothingProc},
601 {N_("Call Flag"), CallFlagProc},
602 {N_("Draw"), DrawProc},
603 {N_("Adjourn"), AdjournProc},
604 {N_("Abort"), AbortProc},
605 {N_("Resign"), ResignProc},
606 {"----", NothingProc},
607 {N_("Stop Observing"), StopObservingProc},
608 {N_("Stop Examining"), StopExaminingProc},
609 {"----", NothingProc},
610 {N_("Adjudicate to White"), AdjuWhiteProc},
611 {N_("Adjudicate to Black"), AdjuBlackProc},
612 {N_("Adjudicate Draw"), AdjuDrawProc},
616 MenuItem stepMenu[] = {
617 {N_("Backward"), BackwardProc},
618 {N_("Forward"), ForwardProc},
619 {N_("Back to Start"), ToStartProc},
620 {N_("Forward to End"), ToEndProc},
621 {N_("Revert"), RevertProc},
622 {N_("Truncate Game"), TruncateGameProc},
623 {"----", NothingProc},
624 {N_("Move Now"), MoveNowProc},
625 {N_("Retract Move"), RetractMoveProc},
629 MenuItem optionsMenu[] = {
630 {N_("Flip View"), FlipViewProc},
631 {"----", NothingProc},
632 {N_("Adjudications ..."), EngineMenuProc},
633 {N_("General Settings ..."), UciMenuProc},
634 {N_("Engine #1 Settings ..."), FirstSettingsProc},
635 {N_("Engine #2 Settings ..."), SecondSettingsProc},
636 {N_("Time Control ..."), TimeControlProc},
637 {"----", NothingProc},
638 {N_("Always Queen"), AlwaysQueenProc},
639 {N_("Animate Dragging"), AnimateDraggingProc},
640 {N_("Animate Moving"), AnimateMovingProc},
641 {N_("Auto Comment"), AutocommProc},
642 {N_("Auto Flag"), AutoflagProc},
643 {N_("Auto Flip View"), AutoflipProc},
644 {N_("Auto Observe"), AutobsProc},
645 {N_("Auto Raise Board"), AutoraiseProc},
646 {N_("Auto Save"), AutosaveProc},
647 {N_("Blindfold"), BlindfoldProc},
648 {N_("Flash Moves"), FlashMovesProc},
649 {N_("Get Move List"), GetMoveListProc},
651 {N_("Highlight Dragging"), HighlightDraggingProc},
653 {N_("Highlight Last Move"), HighlightLastMoveProc},
654 {N_("Move Sound"), MoveSoundProc},
655 {N_("ICS Alarm"), IcsAlarmProc},
656 {N_("Old Save Style"), OldSaveStyleProc},
657 {N_("Periodic Updates"), PeriodicUpdatesProc},
658 {N_("Ponder Next Move"), PonderNextMoveProc},
659 {N_("Popup Exit Message"), PopupExitMessageProc},
660 {N_("Popup Move Errors"), PopupMoveErrorsProc},
661 {N_("Premove"), PremoveProc},
662 {N_("Quiet Play"), QuietPlayProc},
663 {N_("Show Coords"), ShowCoordsProc},
664 {N_("Hide Thinking"), HideThinkingProc},
665 {N_("Test Legality"), TestLegalityProc},
669 MenuItem helpMenu[] = {
670 {N_("Info XBoard"), InfoProc},
671 {N_("Man XBoard"), ManProc},
672 {"----", NothingProc},
673 {N_("Hint"), HintProc},
674 {N_("Book"), BookProc},
675 {"----", NothingProc},
676 {N_("About XBoard"), AboutProc},
681 {N_("File"), fileMenu},
682 {N_("Mode"), modeMenu},
683 {N_("Action"), actionMenu},
684 {N_("Step"), stepMenu},
685 {N_("Options"), optionsMenu},
686 {N_("Help"), helpMenu},
690 #define PAUSE_BUTTON N_("P")
691 MenuItem buttonBar[] = {
694 {PAUSE_BUTTON, PauseProc},
700 #define PIECE_MENU_SIZE 18
701 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
702 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
703 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
704 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
705 N_("Empty square"), N_("Clear board") },
706 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
707 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
708 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
709 N_("Empty square"), N_("Clear board") }
711 /* must be in same order as PieceMenuStrings! */
712 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
713 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
714 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
715 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
716 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
717 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
718 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
719 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
720 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
723 #define DROP_MENU_SIZE 6
724 String dropMenuStrings[DROP_MENU_SIZE] = {
725 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
727 /* must be in same order as PieceMenuStrings! */
728 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
729 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
730 WhiteRook, WhiteQueen
738 DropMenuEnables dmEnables[] = {
756 { XtNborderWidth, 0 },
757 { XtNdefaultDistance, 0 },
761 { XtNborderWidth, 0 },
762 { XtNresizable, (XtArgVal) True },
766 { XtNborderWidth, 0 },
772 { XtNjustify, (XtArgVal) XtJustifyRight },
773 { XtNlabel, (XtArgVal) "..." },
774 { XtNresizable, (XtArgVal) True },
775 { XtNresize, (XtArgVal) False }
778 Arg messageArgs[] = {
779 { XtNjustify, (XtArgVal) XtJustifyLeft },
780 { XtNlabel, (XtArgVal) "..." },
781 { XtNresizable, (XtArgVal) True },
782 { XtNresize, (XtArgVal) False }
786 { XtNborderWidth, 0 },
787 { XtNjustify, (XtArgVal) XtJustifyLeft }
790 XtResource clientResources[] = {
791 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
792 XtOffset(AppDataPtr, whitePieceColor), XtRString,
794 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
795 XtOffset(AppDataPtr, blackPieceColor), XtRString,
797 { "lightSquareColor", "lightSquareColor", XtRString,
798 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
799 XtRString, LIGHT_SQUARE_COLOR },
800 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
801 XtOffset(AppDataPtr, darkSquareColor), XtRString,
803 { "highlightSquareColor", "highlightSquareColor", XtRString,
804 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
805 XtRString, HIGHLIGHT_SQUARE_COLOR },
806 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
807 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
808 XtRString, PREMOVE_HIGHLIGHT_COLOR },
809 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
810 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
811 (XtPointer) MOVES_PER_SESSION },
812 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
813 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
814 (XtPointer) TIME_INCREMENT },
815 { "initString", "initString", XtRString, sizeof(String),
816 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
817 { "secondInitString", "secondInitString", XtRString, sizeof(String),
818 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
819 { "firstComputerString", "firstComputerString", XtRString,
820 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
822 { "secondComputerString", "secondComputerString", XtRString,
823 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
825 { "firstChessProgram", "firstChessProgram", XtRString,
826 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
827 XtRString, FIRST_CHESS_PROGRAM },
828 { "secondChessProgram", "secondChessProgram", XtRString,
829 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
830 XtRString, SECOND_CHESS_PROGRAM },
831 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
832 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
833 XtRImmediate, (XtPointer) False },
834 { "noChessProgram", "noChessProgram", XtRBoolean,
835 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
836 XtRImmediate, (XtPointer) False },
837 { "firstHost", "firstHost", XtRString, sizeof(String),
838 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
839 { "secondHost", "secondHost", XtRString, sizeof(String),
840 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
841 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
843 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
845 { "bitmapDirectory", "bitmapDirectory", XtRString,
846 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
848 { "remoteShell", "remoteShell", XtRString, sizeof(String),
849 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
850 { "remoteUser", "remoteUser", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
852 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
853 XtOffset(AppDataPtr, timeDelay), XtRString,
854 (XtPointer) TIME_DELAY_QUOTE },
855 { "timeControl", "timeControl", XtRString, sizeof(String),
856 XtOffset(AppDataPtr, timeControl), XtRString,
857 (XtPointer) TIME_CONTROL },
858 { "internetChessServerMode", "internetChessServerMode",
859 XtRBoolean, sizeof(Boolean),
860 XtOffset(AppDataPtr, icsActive), XtRImmediate,
862 { "internetChessServerHost", "internetChessServerHost",
863 XtRString, sizeof(String),
864 XtOffset(AppDataPtr, icsHost),
865 XtRString, (XtPointer) ICS_HOST },
866 { "internetChessServerPort", "internetChessServerPort",
867 XtRString, sizeof(String),
868 XtOffset(AppDataPtr, icsPort), XtRString,
869 (XtPointer) ICS_PORT },
870 { "internetChessServerCommPort", "internetChessServerCommPort",
871 XtRString, sizeof(String),
872 XtOffset(AppDataPtr, icsCommPort), XtRString,
874 { "internetChessServerLogonScript", "internetChessServerLogonScript",
875 XtRString, sizeof(String),
876 XtOffset(AppDataPtr, icsLogon), XtRString,
878 { "internetChessServerHelper", "internetChessServerHelper",
879 XtRString, sizeof(String),
880 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
881 { "internetChessServerInputBox", "internetChessServerInputBox",
882 XtRBoolean, sizeof(Boolean),
883 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
885 { "icsAlarm", "icsAlarm",
886 XtRBoolean, sizeof(Boolean),
887 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
889 { "icsAlarmTime", "icsAlarmTime",
891 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
893 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
894 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
896 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
897 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
898 { "gateway", "gateway", XtRString, sizeof(String),
899 XtOffset(AppDataPtr, gateway), XtRString, "" },
900 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
902 { "loadGameIndex", "loadGameIndex",
904 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
906 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
907 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
908 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
909 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
910 XtRImmediate, (XtPointer) True },
911 { "autoSaveGames", "autoSaveGames", XtRBoolean,
912 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
913 XtRImmediate, (XtPointer) False },
914 { "blindfold", "blindfold", XtRBoolean,
915 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
916 XtRImmediate, (XtPointer) False },
917 { "loadPositionFile", "loadPositionFile", XtRString,
918 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
920 { "loadPositionIndex", "loadPositionIndex",
922 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
924 { "savePositionFile", "savePositionFile", XtRString,
925 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
927 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
928 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
929 { "matchGames", "matchGames", XtRInt, sizeof(int),
930 XtOffset(AppDataPtr, matchGames), XtRImmediate,
932 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
933 XtOffset(AppDataPtr, monoMode), XtRImmediate,
935 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
936 XtOffset(AppDataPtr, debugMode), XtRImmediate,
938 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
939 XtOffset(AppDataPtr, clockMode), XtRImmediate,
941 { "boardSize", "boardSize", XtRString, sizeof(String),
942 XtOffset(AppDataPtr, boardSize), XtRString, "" },
943 { "searchTime", "searchTime", XtRString, sizeof(String),
944 XtOffset(AppDataPtr, searchTime), XtRString,
946 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
947 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
949 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
950 XtOffset(AppDataPtr, showCoords), XtRImmediate,
952 { "showJail", "showJail", XtRInt, sizeof(int),
953 XtOffset(AppDataPtr, showJail), XtRImmediate,
955 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
956 XtOffset(AppDataPtr, showThinking), XtRImmediate,
958 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
959 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
961 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
962 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
964 { "clockFont", "clockFont", XtRString, sizeof(String),
965 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
966 { "coordFont", "coordFont", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
968 { "font", "font", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
970 { "ringBellAfterMoves", "ringBellAfterMoves",
971 XtRBoolean, sizeof(Boolean),
972 XtOffset(AppDataPtr, ringBellAfterMoves),
973 XtRImmediate, (XtPointer) False },
974 { "autoCallFlag", "autoCallFlag", XtRBoolean,
975 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
976 XtRImmediate, (XtPointer) False },
977 { "autoFlipView", "autoFlipView", XtRBoolean,
978 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
979 XtRImmediate, (XtPointer) True },
980 { "autoObserve", "autoObserve", XtRBoolean,
981 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
982 XtRImmediate, (XtPointer) False },
983 { "autoComment", "autoComment", XtRBoolean,
984 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
985 XtRImmediate, (XtPointer) False },
986 { "getMoveList", "getMoveList", XtRBoolean,
987 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
988 XtRImmediate, (XtPointer) True },
990 { "highlightDragging", "highlightDragging", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
992 XtRImmediate, (XtPointer) False },
994 { "highlightLastMove", "highlightLastMove", XtRBoolean,
995 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
996 XtRImmediate, (XtPointer) False },
997 { "premove", "premove", XtRBoolean,
998 sizeof(Boolean), XtOffset(AppDataPtr, premove),
999 XtRImmediate, (XtPointer) True },
1000 { "testLegality", "testLegality", XtRBoolean,
1001 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1002 XtRImmediate, (XtPointer) True },
1003 { "flipView", "flipView", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1005 XtRImmediate, (XtPointer) False },
1006 { "cmail", "cmailGameName", XtRString, sizeof(String),
1007 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1008 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1010 XtRImmediate, (XtPointer) False },
1011 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1013 XtRImmediate, (XtPointer) False },
1014 { "quietPlay", "quietPlay", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1016 XtRImmediate, (XtPointer) False },
1017 { "titleInWindow", "titleInWindow", XtRBoolean,
1018 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1019 XtRImmediate, (XtPointer) False },
1020 { "localLineEditing", "localLineEditing", XtRBoolean,
1021 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1022 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1024 { "zippyTalk", "zippyTalk", XtRBoolean,
1025 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1026 XtRImmediate, (XtPointer) ZIPPY_TALK },
1027 { "zippyPlay", "zippyPlay", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1029 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1030 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1031 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1032 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1033 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1034 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1035 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1036 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1037 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1038 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1039 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1040 ZIPPY_WRONG_PASSWORD },
1041 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1042 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1043 { "zippyUseI", "zippyUseI", XtRBoolean,
1044 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1045 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1046 { "zippyBughouse", "zippyBughouse", XtRInt,
1047 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1048 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1049 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1050 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1051 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1052 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1053 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1054 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1055 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1056 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1057 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1058 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1059 { "zippyAbort", "zippyAbort", XtRBoolean,
1060 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1061 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1062 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1063 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1064 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1065 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1066 (XtPointer) ZIPPY_MAX_GAMES },
1067 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1068 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1069 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1070 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1071 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1074 { "flashCount", "flashCount", XtRInt, sizeof(int),
1075 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1076 (XtPointer) FLASH_COUNT },
1077 { "flashRate", "flashRate", XtRInt, sizeof(int),
1078 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1079 (XtPointer) FLASH_RATE },
1080 { "pixmapDirectory", "pixmapDirectory", XtRString,
1081 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1083 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1084 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1085 (XtPointer) MS_LOGIN_DELAY },
1086 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1087 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1088 XtRImmediate, (XtPointer) False },
1089 { "colorShout", "colorShout", XtRString,
1090 sizeof(String), XtOffset(AppDataPtr, colorShout),
1091 XtRString, COLOR_SHOUT },
1092 { "colorSShout", "colorSShout", XtRString,
1093 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1094 XtRString, COLOR_SSHOUT },
1095 { "colorChannel1", "colorChannel1", XtRString,
1096 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1097 XtRString, COLOR_CHANNEL1 },
1098 { "colorChannel", "colorChannel", XtRString,
1099 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1100 XtRString, COLOR_CHANNEL },
1101 { "colorKibitz", "colorKibitz", XtRString,
1102 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1103 XtRString, COLOR_KIBITZ },
1104 { "colorTell", "colorTell", XtRString,
1105 sizeof(String), XtOffset(AppDataPtr, colorTell),
1106 XtRString, COLOR_TELL },
1107 { "colorChallenge", "colorChallenge", XtRString,
1108 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1109 XtRString, COLOR_CHALLENGE },
1110 { "colorRequest", "colorRequest", XtRString,
1111 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1112 XtRString, COLOR_REQUEST },
1113 { "colorSeek", "colorSeek", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1115 XtRString, COLOR_SEEK },
1116 { "colorNormal", "colorNormal", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1118 XtRString, COLOR_NORMAL },
1119 { "soundProgram", "soundProgram", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1121 XtRString, "play" },
1122 { "soundShout", "soundShout", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, soundShout),
1125 { "soundSShout", "soundSShout", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1128 { "soundChannel1", "soundChannel1", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1131 { "soundChannel", "soundChannel", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1134 { "soundKibitz", "soundKibitz", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1137 { "soundTell", "soundTell", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, soundTell),
1140 { "soundChallenge", "soundChallenge", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1143 { "soundRequest", "soundRequest", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1146 { "soundSeek", "soundSeek", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1149 { "soundMove", "soundMove", XtRString,
1150 sizeof(String), XtOffset(AppDataPtr, soundMove),
1152 { "soundIcsWin", "soundIcsWin", XtRString,
1153 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1155 { "soundIcsLoss", "soundIcsLoss", XtRString,
1156 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1158 { "soundIcsDraw", "soundIcsDraw", XtRString,
1159 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1161 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1162 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1164 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1165 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1167 { "reuseFirst", "reuseFirst", XtRBoolean,
1168 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1169 XtRImmediate, (XtPointer) True },
1170 { "reuseSecond", "reuseSecond", XtRBoolean,
1171 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1172 XtRImmediate, (XtPointer) True },
1173 { "animateDragging", "animateDragging", XtRBoolean,
1174 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1175 XtRImmediate, (XtPointer) True },
1176 { "animateMoving", "animateMoving", XtRBoolean,
1177 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1178 XtRImmediate, (XtPointer) True },
1179 { "animateSpeed", "animateSpeed", XtRInt,
1180 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1181 XtRImmediate, (XtPointer)10 },
1182 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1183 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1184 XtRImmediate, (XtPointer) True },
1185 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1187 XtRImmediate, (XtPointer) False },
1188 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1189 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1190 XtRImmediate, (XtPointer)4 },
1191 { "initialMode", "initialMode", XtRString,
1192 sizeof(String), XtOffset(AppDataPtr, initialMode),
1193 XtRImmediate, (XtPointer) "" },
1194 { "variant", "variant", XtRString,
1195 sizeof(String), XtOffset(AppDataPtr, variant),
1196 XtRImmediate, (XtPointer) "normal" },
1197 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1198 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1199 XtRImmediate, (XtPointer)PROTOVER },
1200 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1201 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1202 XtRImmediate, (XtPointer)PROTOVER },
1203 { "showButtonBar", "showButtonBar", XtRBoolean,
1204 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1205 XtRImmediate, (XtPointer) True },
1206 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1207 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1208 XtRString, COLOR_LOWTIMEWARNING },
1209 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1210 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1211 XtRImmediate, (XtPointer) False },
1212 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1213 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1214 XtRImmediate, (XtPointer) False },
1215 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1216 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1217 XtRImmediate, (XtPointer) False },
1218 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1219 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1220 XtRImmediate, (XtPointer) False },
1221 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1222 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1223 XtRImmediate, (XtPointer) False },
1224 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1225 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1226 XtRImmediate, (XtPointer) True },
1227 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1228 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1229 XtRImmediate, (XtPointer) 0},
1230 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1232 XtRImmediate, (XtPointer) 0},
1233 { "pgnEventHeader", "pgnEventHeader", XtRString,
1234 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1235 XtRImmediate, (XtPointer) "Computer Chess Game" },
1236 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1237 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1238 XtRImmediate, (XtPointer) -1},
1239 { "gameListTags", "gameListTags", XtRString,
1240 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1241 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1243 // [HGM] 4.3.xx options
1244 { "boardWidth", "boardWidth", XtRInt,
1245 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1246 XtRImmediate, (XtPointer) -1},
1247 { "boardHeight", "boardHeight", XtRInt,
1248 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1249 XtRImmediate, (XtPointer) -1},
1250 { "matchPause", "matchPause", XtRInt,
1251 sizeof(int), XtOffset(AppDataPtr, matchPause),
1252 XtRImmediate, (XtPointer) 10000},
1253 { "holdingsSize", "holdingsSize", XtRInt,
1254 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1255 XtRImmediate, (XtPointer) -1},
1256 { "flipBlack", "flipBlack", XtRBoolean,
1257 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1258 XtRImmediate, (XtPointer) False},
1259 { "allWhite", "allWhite", XtRBoolean,
1260 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1261 XtRImmediate, (XtPointer) False},
1262 { "pieceToCharTable", "pieceToCharTable", XtRString,
1263 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1264 XtRImmediate, (XtPointer) 0},
1265 { "alphaRank", "alphaRank", XtRBoolean,
1266 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1267 XtRImmediate, (XtPointer) False},
1268 { "testClaims", "testClaims", XtRBoolean,
1269 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1270 XtRImmediate, (XtPointer) True},
1271 { "checkMates", "checkMates", XtRBoolean,
1272 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1273 XtRImmediate, (XtPointer) True},
1274 { "materialDraws", "materialDraws", XtRBoolean,
1275 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1276 XtRImmediate, (XtPointer) True},
1277 { "trivialDraws", "trivialDraws", XtRBoolean,
1278 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1279 XtRImmediate, (XtPointer) False},
1280 { "ruleMoves", "ruleMoves", XtRInt,
1281 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1282 XtRImmediate, (XtPointer) 51},
1283 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1284 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1285 XtRImmediate, (XtPointer) 6},
1286 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1287 sizeof(int), XtOffset(AppDataPtr, engineComments),
1288 XtRImmediate, (XtPointer) 1},
1289 { "userName", "userName", XtRString,
1290 sizeof(int), XtOffset(AppDataPtr, userName),
1291 XtRImmediate, (XtPointer) 0},
1292 { "autoKibitz", "autoKibitz", XtRBoolean,
1293 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1294 XtRImmediate, (XtPointer) False},
1295 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1296 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1297 XtRImmediate, (XtPointer) 1},
1298 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1299 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1300 XtRImmediate, (XtPointer) 1},
1301 { "timeOddsMode", "timeOddsMode", XtRInt,
1302 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1303 XtRImmediate, (XtPointer) 0},
1304 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1306 XtRImmediate, (XtPointer) 1},
1307 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1308 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1309 XtRImmediate, (XtPointer) 1},
1310 { "firstNPS", "firstNPS", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1312 XtRImmediate, (XtPointer) -1},
1313 { "secondNPS", "secondNPS", XtRInt,
1314 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1315 XtRImmediate, (XtPointer) -1},
1316 { "serverMoves", "serverMoves", XtRString,
1317 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1318 XtRImmediate, (XtPointer) 0},
1319 { "serverPause", "serverPause", XtRInt,
1320 sizeof(int), XtOffset(AppDataPtr, serverPause),
1321 XtRImmediate, (XtPointer) 0},
1322 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1323 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1324 XtRImmediate, (XtPointer) False},
1325 { "userName", "userName", XtRString,
1326 sizeof(String), XtOffset(AppDataPtr, userName),
1327 XtRImmediate, (XtPointer) 0},
1328 { "egtFormats", "egtFormats", XtRString,
1329 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1330 XtRImmediate, (XtPointer) 0},
1331 { "rewindIndex", "rewindIndex", XtRInt,
1332 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1333 XtRImmediate, (XtPointer) 0},
1334 { "sameColorGames", "sameColorGames", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1336 XtRImmediate, (XtPointer) 0},
1337 { "smpCores", "smpCores", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, smpCores),
1339 XtRImmediate, (XtPointer) 1},
1340 { "niceEngines", "niceEngines", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1342 XtRImmediate, (XtPointer) 0},
1343 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1344 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1345 XtRImmediate, (XtPointer) "xboard.debug"},
1346 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1347 sizeof(int), XtOffset(AppDataPtr, engineComments),
1348 XtRImmediate, (XtPointer) 1},
1349 { "noGUI", "noGUI", XtRBoolean,
1350 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1351 XtRImmediate, (XtPointer) 0},
1352 { "firstOptions", "firstOptions", XtRString,
1353 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1354 XtRImmediate, (XtPointer) "" },
1355 { "secondOptions", "secondOptions", XtRString,
1356 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1357 XtRImmediate, (XtPointer) "" },
1358 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1359 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1360 XtRImmediate, (XtPointer) 0 },
1361 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1362 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1363 XtRImmediate, (XtPointer) 0 },
1365 // [HGM] Winboard_x UCI options
1366 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1367 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1368 XtRImmediate, (XtPointer) False},
1369 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1370 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1371 XtRImmediate, (XtPointer) False},
1372 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1373 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1374 XtRImmediate, (XtPointer) True},
1375 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1376 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1377 XtRImmediate, (XtPointer) True},
1378 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1379 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1380 XtRImmediate, (XtPointer) False},
1381 { "defaultHashSize", "defaultHashSize", XtRInt,
1382 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1383 XtRImmediate, (XtPointer) 64},
1384 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1385 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1386 XtRImmediate, (XtPointer) 4},
1387 { "polyglotDir", "polyglotDir", XtRString,
1388 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1389 XtRImmediate, (XtPointer) "." },
1390 { "polyglotBook", "polyglotBook", XtRString,
1391 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1392 XtRImmediate, (XtPointer) "" },
1393 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1394 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1395 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1396 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1397 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1398 XtRImmediate, (XtPointer) 0},
1399 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1400 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1401 XtRImmediate, (XtPointer) 0},
1402 { "keepAlive", "keepAlive", XtRInt,
1403 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1404 XtRImmediate, (XtPointer) 0},
1405 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1406 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1407 XtRImmediate, (XtPointer) False},
1408 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1409 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1410 XtRImmediate, (XtPointer) False},
1411 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1412 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1414 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1415 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1416 XtRImmediate, (XtPointer) True},
1417 { "autoDisplayTags", "autoDisplayTags", XtRBoolean,
1418 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayTags),
1419 XtRImmediate, (XtPointer) True},
1420 { "autoDisplayComment", "autoDisplayComment", XtRBoolean,
1421 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayComment),
1422 XtRImmediate, (XtPointer) True},
1423 { "pasteSelection", "pasteSelection", XtRBoolean,
1424 sizeof(Boolean), XtOffset(AppDataPtr, pasteSelection),
1425 XtRImmediate, (XtPointer) False},
1428 XrmOptionDescRec shellOptions[] = {
1429 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1430 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1431 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1432 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1433 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1434 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1435 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1436 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1437 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1438 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1439 { "-initString", "initString", XrmoptionSepArg, NULL },
1440 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1441 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1442 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1443 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1444 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1445 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1446 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1447 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1448 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1449 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1450 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1451 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1452 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1453 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1454 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1455 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1456 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1457 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1458 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1459 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1460 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1461 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1462 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1463 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1464 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1465 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1466 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1467 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1468 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1469 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1470 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1471 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1472 { "-internetChessServerMode", "internetChessServerMode",
1473 XrmoptionSepArg, NULL },
1474 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1475 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1476 { "-internetChessServerHost", "internetChessServerHost",
1477 XrmoptionSepArg, NULL },
1478 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1479 { "-internetChessServerPort", "internetChessServerPort",
1480 XrmoptionSepArg, NULL },
1481 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1482 { "-internetChessServerCommPort", "internetChessServerCommPort",
1483 XrmoptionSepArg, NULL },
1484 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1485 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1486 XrmoptionSepArg, NULL },
1487 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1488 { "-internetChessServerHelper", "internetChessServerHelper",
1489 XrmoptionSepArg, NULL },
1490 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1491 { "-internetChessServerInputBox", "internetChessServerInputBox",
1492 XrmoptionSepArg, NULL },
1493 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1494 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1495 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1496 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1497 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1498 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1499 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1500 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1501 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1502 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1503 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1504 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1505 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1506 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1507 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1508 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1509 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1510 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1511 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1512 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1513 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1514 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1515 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1516 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1517 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1518 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1519 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1520 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1521 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1522 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1523 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1524 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1525 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1526 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1527 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1528 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1529 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1530 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1531 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1532 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1533 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1534 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1535 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1536 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1537 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1538 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1539 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1540 { "-size", "boardSize", XrmoptionSepArg, NULL },
1541 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1542 { "-st", "searchTime", XrmoptionSepArg, NULL },
1543 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1544 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1545 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1546 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1547 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1549 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1550 { "-jail", "showJail", XrmoptionNoArg, "1" },
1551 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1552 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1554 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1555 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1556 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1557 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1558 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1559 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1560 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1561 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1562 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1563 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1564 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1565 { "-font", "font", XrmoptionSepArg, NULL },
1566 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1567 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1568 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1569 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1570 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1571 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1572 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1573 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1574 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1575 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1576 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1577 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1578 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1579 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1580 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1581 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1582 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1583 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1584 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1585 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1587 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1588 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1589 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1591 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1592 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1593 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1594 { "-premove", "premove", XrmoptionSepArg, NULL },
1595 { "-pre", "premove", XrmoptionNoArg, "True" },
1596 { "-xpre", "premove", XrmoptionNoArg, "False" },
1597 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1598 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1599 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1600 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1601 { "-flip", "flipView", XrmoptionNoArg, "True" },
1602 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1603 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1604 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1605 XrmoptionSepArg, NULL },
1606 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1607 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1608 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1609 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1610 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1611 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1612 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1613 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1614 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1615 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1616 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1618 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1619 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1620 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1621 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1622 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1623 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1624 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1625 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1626 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1627 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1628 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1629 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1630 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1631 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1632 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1633 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1634 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1635 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1636 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1637 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1638 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1639 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1640 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1641 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1642 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1643 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1644 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1645 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1646 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1647 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1648 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1650 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1651 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1652 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1653 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1654 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1655 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1656 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1657 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1658 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1659 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1660 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1661 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1662 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1663 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1664 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1665 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1666 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1667 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1668 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1669 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1670 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1671 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1672 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1673 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1674 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1675 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1676 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1677 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1678 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1679 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1680 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1681 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1682 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1683 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1684 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1685 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1686 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1687 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1688 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1689 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1690 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1691 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1692 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1693 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1694 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1695 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1696 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1697 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1698 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1699 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1700 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1701 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1702 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1703 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1704 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1705 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1706 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1707 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1708 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1709 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1710 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1711 { "-variant", "variant", XrmoptionSepArg, NULL },
1712 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1713 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1714 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1715 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1716 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1717 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1718 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1719 /* [AS,HR] New features */
1720 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1721 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1722 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1723 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1724 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1725 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1726 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1727 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1728 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1729 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1730 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1731 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1732 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1733 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1734 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1735 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1736 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1737 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1738 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1739 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1740 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1741 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1742 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1743 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1744 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1745 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1747 /* [HGM,HR] User-selectable board size */
1748 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1749 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1750 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1752 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1753 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1754 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1755 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1756 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1757 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1758 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1759 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1760 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1761 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1762 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1763 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1764 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1765 { "-userName", "userName", XrmoptionSepArg, NULL },
1766 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1767 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1768 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1769 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1770 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1771 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1772 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1773 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1774 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1775 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1776 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1777 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1778 { "-userName", "userName", XrmoptionSepArg, NULL },
1779 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1780 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1781 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1782 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1783 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1784 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1785 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1786 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1787 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1788 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1789 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1790 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1791 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1792 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1793 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1794 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1795 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1796 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1797 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1798 { "-autoDisplayTags", "autoDisplayTags", XrmoptionSepArg, NULL },
1799 { "-autoDisplayComment", "autoDisplayComment", XrmoptionSepArg, NULL },
1800 { "-pasteSelection", "pasteSelection", XrmoptionSepArg, NULL },
1803 XtActionsRec boardActions[] = {
1804 { "DrawPosition", DrawPositionProc },
1805 { "HandleUserMove", HandleUserMove },
1806 { "AnimateUserMove", AnimateUserMove },
1807 { "FileNameAction", FileNameAction },
1808 { "AskQuestionProc", AskQuestionProc },
1809 { "AskQuestionReplyAction", AskQuestionReplyAction },
1810 { "PieceMenuPopup", PieceMenuPopup },
1811 { "WhiteClock", WhiteClock },
1812 { "BlackClock", BlackClock },
1813 { "Iconify", Iconify },
1814 { "ResetProc", ResetProc },
1815 { "LoadGameProc", LoadGameProc },
1816 { "LoadNextGameProc", LoadNextGameProc },
1817 { "LoadPrevGameProc", LoadPrevGameProc },
1818 { "LoadSelectedProc", LoadSelectedProc },
1819 { "ReloadGameProc", ReloadGameProc },
1820 { "LoadPositionProc", LoadPositionProc },
1821 { "LoadNextPositionProc", LoadNextPositionProc },
1822 { "LoadPrevPositionProc", LoadPrevPositionProc },
1823 { "ReloadPositionProc", ReloadPositionProc },
1824 { "CopyPositionProc", CopyPositionProc },
1825 { "PastePositionProc", PastePositionProc },
1826 { "CopyGameProc", CopyGameProc },
1827 { "PasteGameProc", PasteGameProc },
1828 { "SaveGameProc", SaveGameProc },
1829 { "SavePositionProc", SavePositionProc },
1830 { "MailMoveProc", MailMoveProc },
1831 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1832 { "QuitProc", QuitProc },
1833 { "MachineWhiteProc", MachineWhiteProc },
1834 { "MachineBlackProc", MachineBlackProc },
1835 { "AnalysisModeProc", AnalyzeModeProc },
1836 { "AnalyzeFileProc", AnalyzeFileProc },
1837 { "TwoMachinesProc", TwoMachinesProc },
1838 { "IcsClientProc", IcsClientProc },
1839 { "EditGameProc", EditGameProc },
1840 { "EditPositionProc", EditPositionProc },
1841 { "TrainingProc", EditPositionProc },
1842 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1843 { "ShowGameListProc", ShowGameListProc },
1844 { "ShowMoveListProc", HistoryShowProc},
1845 { "EditTagsProc", EditCommentProc },
1846 { "EditCommentProc", EditCommentProc },
1847 { "IcsAlarmProc", IcsAlarmProc },
1848 { "IcsInputBoxProc", IcsInputBoxProc },
1849 { "PauseProc", PauseProc },
1850 { "AcceptProc", AcceptProc },
1851 { "DeclineProc", DeclineProc },
1852 { "RematchProc", RematchProc },
1853 { "CallFlagProc", CallFlagProc },
1854 { "DrawProc", DrawProc },
1855 { "AdjournProc", AdjournProc },
1856 { "AbortProc", AbortProc },
1857 { "ResignProc", ResignProc },
1858 { "AdjuWhiteProc", AdjuWhiteProc },
1859 { "AdjuBlackProc", AdjuBlackProc },
1860 { "AdjuDrawProc", AdjuDrawProc },
1861 { "EnterKeyProc", EnterKeyProc },
1862 { "StopObservingProc", StopObservingProc },
1863 { "StopExaminingProc", StopExaminingProc },
1864 { "BackwardProc", BackwardProc },
1865 { "ForwardProc", ForwardProc },
1866 { "ToStartProc", ToStartProc },
1867 { "ToEndProc", ToEndProc },
1868 { "RevertProc", RevertProc },
1869 { "TruncateGameProc", TruncateGameProc },
1870 { "MoveNowProc", MoveNowProc },
1871 { "RetractMoveProc", RetractMoveProc },
1872 { "AlwaysQueenProc", AlwaysQueenProc },
1873 { "AnimateDraggingProc", AnimateDraggingProc },
1874 { "AnimateMovingProc", AnimateMovingProc },
1875 { "AutoflagProc", AutoflagProc },
1876 { "AutoflipProc", AutoflipProc },
1877 { "AutobsProc", AutobsProc },
1878 { "AutoraiseProc", AutoraiseProc },
1879 { "AutosaveProc", AutosaveProc },
1880 { "BlindfoldProc", BlindfoldProc },
1881 { "FlashMovesProc", FlashMovesProc },
1882 { "FlipViewProc", FlipViewProc },
1883 { "GetMoveListProc", GetMoveListProc },
1885 { "HighlightDraggingProc", HighlightDraggingProc },
1887 { "HighlightLastMoveProc", HighlightLastMoveProc },
1888 { "IcsAlarmProc", IcsAlarmProc },
1889 { "MoveSoundProc", MoveSoundProc },
1890 { "OldSaveStyleProc", OldSaveStyleProc },
1891 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1892 { "PonderNextMoveProc", PonderNextMoveProc },
1893 { "PopupExitMessageProc", PopupExitMessageProc },
1894 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1895 { "PremoveProc", PremoveProc },
1896 { "QuietPlayProc", QuietPlayProc },
1897 { "ShowCoordsProc", ShowCoordsProc },
1898 { "ShowThinkingProc", ShowThinkingProc },
1899 { "HideThinkingProc", HideThinkingProc },
1900 { "TestLegalityProc", TestLegalityProc },
1901 { "InfoProc", InfoProc },
1902 { "ManProc", ManProc },
1903 { "HintProc", HintProc },
1904 { "BookProc", BookProc },
1905 { "AboutGameProc", AboutGameProc },
1906 { "AboutProc", AboutProc },
1907 { "DebugProc", DebugProc },
1908 { "NothingProc", NothingProc },
1909 { "CommentPopDown", (XtActionProc) CommentPopDown },
1910 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1911 { "TagsPopDown", (XtActionProc) TagsPopDown },
1912 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1913 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1914 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1915 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1916 { "GameListPopDown", (XtActionProc) GameListPopDown },
1917 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1918 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1919 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1920 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1921 { "EnginePopDown", (XtActionProc) EnginePopDown },
1922 { "UciPopDown", (XtActionProc) UciPopDown },
1923 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1924 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1925 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1928 char globalTranslations[] =
1929 ":<Key>R: ResignProc() \n \
1930 :<Key>r: ResetProc() \n \
1931 :<Key>g: LoadGameProc() \n \
1932 :<Key>N: LoadNextGameProc() \n \
1933 :<Key>P: LoadPrevGameProc() \n \
1934 :<Key>Q: QuitProc() \n \
1935 :<Key>F: ToEndProc() \n \
1936 :<Key>f: ForwardProc() \n \
1937 :<Key>B: ToStartProc() \n \
1938 :<Key>b: BackwardProc() \n \
1939 :<Key>p: PauseProc() \n \
1940 :<Key>d: DrawProc() \n \
1941 :<Key>t: CallFlagProc() \n \
1942 :<Key>i: Iconify() \n \
1943 :<Key>c: Iconify() \n \
1944 :<Key>v: FlipViewProc() \n \
1945 <KeyDown>Control_L: BackwardProc() \n \
1946 <KeyUp>Control_L: ForwardProc() \n \
1947 <KeyDown>Control_R: BackwardProc() \n \
1948 <KeyUp>Control_R: ForwardProc() \n \
1949 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1950 \"Send to chess program:\",,1) \n \
1951 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1952 \"Send to second chess program:\",,2) \n";
1954 char boardTranslations[] =
1955 "<Btn1Down>: HandleUserMove() \n \
1956 <Btn1Up>: HandleUserMove() \n \
1957 <Btn1Motion>: AnimateUserMove() \n \
1958 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1959 PieceMenuPopup(menuB) \n \
1960 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1961 PieceMenuPopup(menuW) \n \
1962 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1963 PieceMenuPopup(menuW) \n \
1964 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1965 PieceMenuPopup(menuB) \n";
1967 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1968 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1970 char ICSInputTranslations[] =
1971 "<Key>Return: EnterKeyProc() \n";
1973 String xboardResources[] = {
1974 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1975 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1976 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1981 /* Max possible square size */
1982 #define MAXSQSIZE 256
1984 static int xpm_avail[MAXSQSIZE];
1986 #ifdef HAVE_DIR_STRUCT
1988 /* Extract piece size from filename */
1990 xpm_getsize(name, len, ext)
2001 if ((p=strchr(name, '.')) == NULL ||
2002 StrCaseCmp(p+1, ext) != 0)
2008 while (*p && isdigit(*p))
2015 /* Setup xpm_avail */
2017 xpm_getavail(dirname, ext)
2025 for (i=0; i<MAXSQSIZE; ++i)
2028 if (appData.debugMode)
2029 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2031 dir = opendir(dirname);
2034 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2035 programName, dirname);
2039 while ((ent=readdir(dir)) != NULL) {
2040 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2041 if (i > 0 && i < MAXSQSIZE)
2051 xpm_print_avail(fp, ext)
2057 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2058 for (i=1; i<MAXSQSIZE; ++i) {
2064 /* Return XPM piecesize closest to size */
2066 xpm_closest_to(dirname, size, ext)
2072 int sm_diff = MAXSQSIZE;
2076 xpm_getavail(dirname, ext);
2078 if (appData.debugMode)
2079 xpm_print_avail(stderr, ext);
2081 for (i=1; i<MAXSQSIZE; ++i) {
2084 diff = (diff<0) ? -diff : diff;
2085 if (diff < sm_diff) {
2093 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2099 #else /* !HAVE_DIR_STRUCT */
2100 /* If we are on a system without a DIR struct, we can't
2101 read the directory, so we can't collect a list of
2102 filenames, etc., so we can't do any size-fitting. */
2104 xpm_closest_to(dirname, size, ext)
2109 fprintf(stderr, _("\
2110 Warning: No DIR structure found on this system --\n\
2111 Unable to autosize for XPM/XIM pieces.\n\
2112 Please report this error to frankm@hiwaay.net.\n\
2113 Include system type & operating system in message.\n"));
2116 #endif /* HAVE_DIR_STRUCT */
2118 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2119 "magenta", "cyan", "white" };
2123 TextColors textColors[(int)NColorClasses];
2125 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2127 parse_color(str, which)
2131 char *p, buf[100], *d;
2134 if (strlen(str) > 99) /* watch bounds on buf */
2139 for (i=0; i<which; ++i) {
2146 /* Could be looking at something like:
2148 .. in which case we want to stop on a comma also */
2149 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2153 return -1; /* Use default for empty field */
2156 if (which == 2 || isdigit(*p))
2159 while (*p && isalpha(*p))
2164 for (i=0; i<8; ++i) {
2165 if (!StrCaseCmp(buf, cnames[i]))
2166 return which? (i+40) : (i+30);
2168 if (!StrCaseCmp(buf, "default")) return -1;
2170 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2175 parse_cpair(cc, str)
2179 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2180 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2185 /* bg and attr are optional */
2186 textColors[(int)cc].bg = parse_color(str, 1);
2187 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2188 textColors[(int)cc].attr = 0;
2194 /* Arrange to catch delete-window events */
2195 Atom wm_delete_window;
2197 CatchDeleteWindow(Widget w, String procname)
2200 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2201 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2202 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2209 XtSetArg(args[0], XtNiconic, False);
2210 XtSetValues(shellWidget, args, 1);
2212 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2216 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2218 #define BoardSize int
2219 void InitDrawingSizes(BoardSize boardSize, int flags)
2220 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2221 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2223 XtGeometryResult gres;
2226 if(!formWidget) return;
2229 * Enable shell resizing.
2231 shellArgs[0].value = (XtArgVal) &w;
2232 shellArgs[1].value = (XtArgVal) &h;
2233 XtGetValues(shellWidget, shellArgs, 2);
2235 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2236 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2237 XtSetValues(shellWidget, &shellArgs[2], 4);
2239 XtSetArg(args[0], XtNdefaultDistance, &sep);
2240 XtGetValues(formWidget, args, 1);
2242 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2243 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2246 XtSetArg(args[0], XtNwidth, boardWidth);
2247 XtSetArg(args[1], XtNheight, boardHeight);
2248 XtSetValues(boardWidget, args, 2);
2250 timerWidth = (boardWidth - sep) / 2;
2251 XtSetArg(args[0], XtNwidth, timerWidth);
2252 XtSetValues(whiteTimerWidget, args, 1);
2253 XtSetValues(blackTimerWidget, args, 1);
2255 XawFormDoLayout(formWidget, False);
2257 if (appData.titleInWindow) {
2259 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2260 XtSetArg(args[i], XtNheight, &h); i++;
2261 XtGetValues(titleWidget, args, i);
2263 w = boardWidth - 2*bor;
2265 XtSetArg(args[0], XtNwidth, &w);
2266 XtGetValues(menuBarWidget, args, 1);
2267 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2270 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2271 if (gres != XtGeometryYes && appData.debugMode) {
2273 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2274 programName, gres, w, h, wr, hr);
2278 XawFormDoLayout(formWidget, True);
2281 * Inhibit shell resizing.
2283 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2284 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2285 shellArgs[4].value = shellArgs[2].value = w;
2286 shellArgs[5].value = shellArgs[3].value = h;
2287 XtSetValues(shellWidget, &shellArgs[0], 6);
2289 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2292 for(i=0; i<4; i++) {
2294 for(p=0; p<=(int)WhiteKing; p++)
2295 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2296 if(gameInfo.variant == VariantShogi) {
2297 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2298 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2299 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2300 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2301 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2304 if(gameInfo.variant == VariantGothic) {
2305 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2309 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2310 for(p=0; p<=(int)WhiteKing; p++)
2311 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2312 if(gameInfo.variant == VariantShogi) {
2313 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2314 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2315 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2316 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2317 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2320 if(gameInfo.variant == VariantGothic) {
2321 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2327 for(i=0; i<2; i++) {
2329 for(p=0; p<=(int)WhiteKing; p++)
2330 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2331 if(gameInfo.variant == VariantShogi) {
2332 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2333 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2334 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2335 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2336 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2339 if(gameInfo.variant == VariantGothic) {
2340 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2351 void EscapeExpand(char *p, char *q)
2352 { // [HGM] initstring: routine to shape up string arguments
2353 while(*p++ = *q++) if(p[-1] == '\\')
2355 case 'n': p[-1] = '\n'; break;
2356 case 'r': p[-1] = '\r'; break;
2357 case 't': p[-1] = '\t'; break;
2358 case '\\': p[-1] = '\\'; break;
2359 case 0: *p = 0; return;
2360 default: p[-1] = q[-1]; break;
2369 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2370 XSetWindowAttributes window_attributes;
2372 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2373 XrmValue vFrom, vTo;
2374 XtGeometryResult gres;
2377 int forceMono = False;
2380 // [HGM] before anything else, expand any indirection files amongst options
2381 char *argvCopy[1000]; // 1000 seems enough
2382 char newArgs[10000]; // holds actual characters
2385 srandom(time(0)); // [HGM] book: make random truly random
2388 for(i=0; i<argc; i++) {
2389 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2390 //fprintf(stderr, "arg %s\n", argv[i]);
2391 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2393 FILE *f = fopen(argv[i]+1, "rb");
2394 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2395 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2396 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2398 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2399 newArgs[k++] = 0; // terminate current arg
2400 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2401 argvCopy[j++] = newArgs + k; // get ready for next
2403 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2417 setbuf(stdout, NULL);
2418 setbuf(stderr, NULL);
2421 programName = strrchr(argv[0], '/');
2422 if (programName == NULL)
2423 programName = argv[0];
2428 XtSetLanguageProc(NULL, NULL, NULL);
2429 bindtextdomain(PACKAGE, LOCALEDIR);
2430 textdomain(PACKAGE);
2434 XtAppInitialize(&appContext, "XBoard", shellOptions,
2435 XtNumber(shellOptions),
2436 &argc, argv, xboardResources, NULL, 0);
2438 { /* left over command line arguments, print out help and exit.
2439 * Use two columns to print help
2441 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2442 programName, argv[1]);
2444 fprintf(stderr, "Recognized options:\n");
2445 for(i = 0; i < XtNumber(shellOptions); i++)
2447 /* print first column */
2448 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2449 (shellOptions[i].argKind == XrmoptionSepArg
2451 /* print second column and end line */
2452 if (++i < XtNumber(shellOptions))
2454 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2455 shellOptions[i].option,
2456 (shellOptions[i].argKind == XrmoptionSepArg
2461 fprintf(stderr, "\n");
2468 if (p == NULL) p = "/tmp";
2469 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2470 gameCopyFilename = (char*) malloc(i);
2471 gamePasteFilename = (char*) malloc(i);
2472 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2473 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2475 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2476 clientResources, XtNumber(clientResources),
2479 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2480 static char buf[MSG_SIZ];
2481 EscapeExpand(buf, appData.initString);
2482 appData.initString = strdup(buf);
2483 EscapeExpand(buf, appData.secondInitString);
2484 appData.secondInitString = strdup(buf);
2485 EscapeExpand(buf, appData.firstComputerString);
2486 appData.firstComputerString = strdup(buf);
2487 EscapeExpand(buf, appData.secondComputerString);
2488 appData.secondComputerString = strdup(buf);
2491 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2494 if (chdir(chessDir) != 0) {
2495 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2501 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2502 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2503 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2504 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2507 setbuf(debugFP, NULL);
2510 /* [HGM,HR] make sure board size is acceptable */
2511 if(appData.NrFiles > BOARD_FILES ||
2512 appData.NrRanks > BOARD_RANKS )
2513 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2516 /* This feature does not work; animation needs a rewrite */
2517 appData.highlightDragging = FALSE;
2521 xDisplay = XtDisplay(shellWidget);
2522 xScreen = DefaultScreen(xDisplay);
2523 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2525 gameInfo.variant = StringToVariant(appData.variant);
2526 InitPosition(FALSE);
2529 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2531 if (isdigit(appData.boardSize[0])) {
2532 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2533 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2534 &fontPxlSize, &smallLayout, &tinyLayout);
2536 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2537 programName, appData.boardSize);
2541 /* Find some defaults; use the nearest known size */
2542 SizeDefaults *szd, *nearest;
2543 int distance = 99999;
2544 nearest = szd = sizeDefaults;
2545 while (szd->name != NULL) {
2546 if (abs(szd->squareSize - squareSize) < distance) {
2548 distance = abs(szd->squareSize - squareSize);
2549 if (distance == 0) break;
2553 if (i < 2) lineGap = nearest->lineGap;
2554 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2555 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2556 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2557 if (i < 6) smallLayout = nearest->smallLayout;
2558 if (i < 7) tinyLayout = nearest->tinyLayout;
2561 SizeDefaults *szd = sizeDefaults;
2562 if (*appData.boardSize == NULLCHAR) {
2563 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2564 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2567 if (szd->name == NULL) szd--;
2569 while (szd->name != NULL &&
2570 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2571 if (szd->name == NULL) {
2572 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2573 programName, appData.boardSize);
2577 squareSize = szd->squareSize;
2578 lineGap = szd->lineGap;
2579 clockFontPxlSize = szd->clockFontPxlSize;
2580 coordFontPxlSize = szd->coordFontPxlSize;
2581 fontPxlSize = szd->fontPxlSize;
2582 smallLayout = szd->smallLayout;
2583 tinyLayout = szd->tinyLayout;
2586 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2587 if (strlen(appData.pixmapDirectory) > 0) {
2588 p = ExpandPathName(appData.pixmapDirectory);
2590 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2591 appData.pixmapDirectory);
2594 if (appData.debugMode) {
2595 fprintf(stderr, _("\
2596 XBoard square size (hint): %d\n\
2597 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2599 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2600 if (appData.debugMode) {
2601 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2605 /* [HR] height treated separately (hacked) */
2606 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2607 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2608 if (appData.showJail == 1) {
2609 /* Jail on top and bottom */
2610 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2611 XtSetArg(boardArgs[2], XtNheight,
2612 boardHeight + 2*(lineGap + squareSize));
2613 } else if (appData.showJail == 2) {
2615 XtSetArg(boardArgs[1], XtNwidth,
2616 boardWidth + 2*(lineGap + squareSize));
2617 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2620 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2621 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2625 * Determine what fonts to use.
2627 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2628 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2629 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2630 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2631 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2632 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2633 appData.font = FindFont(appData.font, fontPxlSize);
2634 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2635 countFontStruct = XQueryFont(xDisplay, countFontID);
2636 // appData.font = FindFont(appData.font, fontPxlSize);
2638 xdb = XtDatabase(xDisplay);
2639 XrmPutStringResource(&xdb, "*font", appData.font);
2642 * Detect if there are not enough colors available and adapt.
2644 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2645 appData.monoMode = True;
2648 if (!appData.monoMode) {
2649 vFrom.addr = (caddr_t) appData.lightSquareColor;
2650 vFrom.size = strlen(appData.lightSquareColor);
2651 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2652 if (vTo.addr == NULL) {
2653 appData.monoMode = True;
2656 lightSquareColor = *(Pixel *) vTo.addr;
2659 if (!appData.monoMode) {
2660 vFrom.addr = (caddr_t) appData.darkSquareColor;
2661 vFrom.size = strlen(appData.darkSquareColor);
2662 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2663 if (vTo.addr == NULL) {
2664 appData.monoMode = True;
2667 darkSquareColor = *(Pixel *) vTo.addr;
2670 if (!appData.monoMode) {
2671 vFrom.addr = (caddr_t) appData.whitePieceColor;
2672 vFrom.size = strlen(appData.whitePieceColor);
2673 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2674 if (vTo.addr == NULL) {
2675 appData.monoMode = True;
2678 whitePieceColor = *(Pixel *) vTo.addr;
2681 if (!appData.monoMode) {
2682 vFrom.addr = (caddr_t) appData.blackPieceColor;
2683 vFrom.size = strlen(appData.blackPieceColor);
2684 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2685 if (vTo.addr == NULL) {
2686 appData.monoMode = True;
2689 blackPieceColor = *(Pixel *) vTo.addr;
2693 if (!appData.monoMode) {
2694 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2695 vFrom.size = strlen(appData.highlightSquareColor);
2696 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2697 if (vTo.addr == NULL) {
2698 appData.monoMode = True;
2701 highlightSquareColor = *(Pixel *) vTo.addr;
2705 if (!appData.monoMode) {
2706 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2707 vFrom.size = strlen(appData.premoveHighlightColor);
2708 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2709 if (vTo.addr == NULL) {
2710 appData.monoMode = True;
2713 premoveHighlightColor = *(Pixel *) vTo.addr;
2718 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2721 if (appData.bitmapDirectory == NULL ||
2722 appData.bitmapDirectory[0] == NULLCHAR)
2723 appData.bitmapDirectory = DEF_BITMAP_DIR;
2726 if (appData.lowTimeWarning && !appData.monoMode) {
2727 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2728 vFrom.size = strlen(appData.lowTimeWarningColor);
2729 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2730 if (vTo.addr == NULL)
2731 appData.monoMode = True;
2733 lowTimeWarningColor = *(Pixel *) vTo.addr;
2736 if (appData.monoMode && appData.debugMode) {
2737 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2738 (unsigned long) XWhitePixel(xDisplay, xScreen),
2739 (unsigned long) XBlackPixel(xDisplay, xScreen));
2742 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2743 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2744 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2745 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2746 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2747 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2748 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2749 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2750 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2751 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2753 if (appData.colorize) {
2755 _("%s: can't parse color names; disabling colorization\n"),
2758 appData.colorize = FALSE;
2760 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2761 textColors[ColorNone].attr = 0;
2763 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2769 layoutName = "tinyLayout";
2770 } else if (smallLayout) {
2771 layoutName = "smallLayout";
2773 layoutName = "normalLayout";
2775 /* Outer layoutWidget is there only to provide a name for use in
2776 resources that depend on the layout style */
2778 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2779 layoutArgs, XtNumber(layoutArgs));
2781 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2782 formArgs, XtNumber(formArgs));
2783 XtSetArg(args[0], XtNdefaultDistance, &sep);
2784 XtGetValues(formWidget, args, 1);
2787 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2788 XtSetArg(args[0], XtNtop, XtChainTop);
2789 XtSetArg(args[1], XtNbottom, XtChainTop);
2790 XtSetArg(args[2], XtNright, XtChainLeft);
2791 XtSetValues(menuBarWidget, args, 3);
2793 widgetList[j++] = whiteTimerWidget =
2794 XtCreateWidget("whiteTime", labelWidgetClass,
2795 formWidget, timerArgs, XtNumber(timerArgs));
2796 XtSetArg(args[0], XtNfont, clockFontStruct);
2797 XtSetArg(args[1], XtNtop, XtChainTop);
2798 XtSetArg(args[2], XtNbottom, XtChainTop);
2799 XtSetValues(whiteTimerWidget, args, 3);
2801 widgetList[j++] = blackTimerWidget =
2802 XtCreateWidget("blackTime", labelWidgetClass,
2803 formWidget, timerArgs, XtNumber(timerArgs));
2804 XtSetArg(args[0], XtNfont, clockFontStruct);
2805 XtSetArg(args[1], XtNtop, XtChainTop);
2806 XtSetArg(args[2], XtNbottom, XtChainTop);
2807 XtSetValues(blackTimerWidget, args, 3);
2809 if (appData.titleInWindow) {
2810 widgetList[j++] = titleWidget =
2811 XtCreateWidget("title", labelWidgetClass, formWidget,
2812 titleArgs, XtNumber(titleArgs));
2813 XtSetArg(args[0], XtNtop, XtChainTop);
2814 XtSetArg(args[1], XtNbottom, XtChainTop);
2815 XtSetValues(titleWidget, args, 2);
2818 if (appData.showButtonBar) {
2819 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2820 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2821 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2822 XtSetArg(args[2], XtNtop, XtChainTop);
2823 XtSetArg(args[3], XtNbottom, XtChainTop);
2824 XtSetValues(buttonBarWidget, args, 4);
2827 widgetList[j++] = messageWidget =
2828 XtCreateWidget("message", labelWidgetClass, formWidget,
2829 messageArgs, XtNumber(messageArgs));
2830 XtSetArg(args[0], XtNtop, XtChainTop);
2831 XtSetArg(args[1], XtNbottom, XtChainTop);
2832 XtSetValues(messageWidget, args, 2);
2834 widgetList[j++] = boardWidget =
2835 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2836 XtNumber(boardArgs));
2838 XtManageChildren(widgetList, j);
2840 timerWidth = (boardWidth - sep) / 2;
2841 XtSetArg(args[0], XtNwidth, timerWidth);
2842 XtSetValues(whiteTimerWidget, args, 1);
2843 XtSetValues(blackTimerWidget, args, 1);
2845 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2846 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2847 XtGetValues(whiteTimerWidget, args, 2);
2849 if (appData.showButtonBar) {
2850 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2851 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2852 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2856 * formWidget uses these constraints but they are stored
2860 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2861 XtSetValues(menuBarWidget, args, i);
2862 if (appData.titleInWindow) {
2865 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2866 XtSetValues(whiteTimerWidget, args, i);
2868 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2869 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2870 XtSetValues(blackTimerWidget, args, i);
2872 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2873 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2874 XtSetValues(titleWidget, args, i);
2876 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2877 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2878 XtSetValues(messageWidget, args, i);
2879 if (appData.showButtonBar) {
2881 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2882 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2883 XtSetValues(buttonBarWidget, args, i);
2887 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2888 XtSetValues(whiteTimerWidget, args, i);
2890 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2891 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2892 XtSetValues(blackTimerWidget, args, i);
2894 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2895 XtSetValues(titleWidget, args, i);
2897 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2898 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2899 XtSetValues(messageWidget, args, i);
2900 if (appData.showButtonBar) {
2902 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2903 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2904 XtSetValues(buttonBarWidget, args, i);
2909 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2910 XtSetValues(whiteTimerWidget, args, i);
2912 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2913 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2914 XtSetValues(blackTimerWidget, args, i);
2916 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2917 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2918 XtSetValues(messageWidget, args, i);
2919 if (appData.showButtonBar) {
2921 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2922 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2923 XtSetValues(buttonBarWidget, args, i);
2927 XtSetArg(args[0], XtNfromVert, messageWidget);
2928 XtSetArg(args[1], XtNtop, XtChainTop);
2929 XtSetArg(args[2], XtNbottom, XtChainBottom);
2930 XtSetArg(args[3], XtNleft, XtChainLeft);
2931 XtSetArg(args[4], XtNright, XtChainRight);
2932 XtSetValues(boardWidget, args, 5);
2934 XtRealizeWidget(shellWidget);
2937 * Correct the width of the message and title widgets.
2938 * It is not known why some systems need the extra fudge term.
2939 * The value "2" is probably larger than needed.
2941 XawFormDoLayout(formWidget, False);
2943 #define WIDTH_FUDGE 2
2945 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2946 XtSetArg(args[i], XtNheight, &h); i++;
2947 XtGetValues(messageWidget, args, i);
2948 if (appData.showButtonBar) {
2950 XtSetArg(args[i], XtNwidth, &w); i++;
2951 XtGetValues(buttonBarWidget, args, i);
2952 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2954 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2957 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2958 if (gres != XtGeometryYes && appData.debugMode) {
2959 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2960 programName, gres, w, h, wr, hr);
2963 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2964 /* The size used for the child widget in layout lags one resize behind
2965 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2967 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2968 if (gres != XtGeometryYes && appData.debugMode) {
2969 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2970 programName, gres, w, h, wr, hr);
2973 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2974 XtSetArg(args[1], XtNright, XtChainRight);
2975 XtSetValues(messageWidget, args, 2);
2977 if (appData.titleInWindow) {
2979 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2980 XtSetArg(args[i], XtNheight, &h); i++;
2981 XtGetValues(titleWidget, args, i);
2983 w = boardWidth - 2*bor;
2985 XtSetArg(args[0], XtNwidth, &w);
2986 XtGetValues(menuBarWidget, args, 1);
2987 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2990 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2991 if (gres != XtGeometryYes && appData.debugMode) {
2993 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2994 programName, gres, w, h, wr, hr);
2997 XawFormDoLayout(formWidget, True);
2999 xBoardWindow = XtWindow(boardWidget);
3001 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
3002 // not need to go into InitDrawingSizes().
3006 * Create X checkmark bitmap and initialize option menu checks.
3008 ReadBitmap(&xMarkPixmap, "checkmark.bm",
3009 checkmark_bits, checkmark_width, checkmark_height);
3010 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
3011 if (appData.alwaysPromoteToQueen) {
3012 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3015 if (appData.animateDragging) {
3016 XtSetValues(XtNameToWidget(menuBarWidget,
3017 "menuOptions.Animate Dragging"),
3020 if (appData.animate) {
3021 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3024 if (appData.autoComment) {
3025 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3028 if (appData.autoCallFlag) {
3029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3032 if (appData.autoFlipView) {
3033 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3036 if (appData.autoObserve) {
3037 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3040 if (appData.autoRaiseBoard) {
3041 XtSetValues(XtNameToWidget(menuBarWidget,
3042 "menuOptions.Auto Raise Board"), args, 1);
3044 if (appData.autoSaveGames) {
3045 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3048 if (appData.saveGameFile[0] != NULLCHAR) {
3049 /* Can't turn this off from menu */
3050 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3052 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3056 if (appData.blindfold) {
3057 XtSetValues(XtNameToWidget(menuBarWidget,
3058 "menuOptions.Blindfold"), args, 1);
3060 if (appData.flashCount > 0) {
3061 XtSetValues(XtNameToWidget(menuBarWidget,
3062 "menuOptions.Flash Moves"),
3065 if (appData.getMoveList) {
3066 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3070 if (appData.highlightDragging) {
3071 XtSetValues(XtNameToWidget(menuBarWidget,
3072 "menuOptions.Highlight Dragging"),
3076 if (appData.highlightLastMove) {
3077 XtSetValues(XtNameToWidget(menuBarWidget,
3078 "menuOptions.Highlight Last Move"),
3081 if (appData.icsAlarm) {
3082 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3085 if (appData.ringBellAfterMoves) {
3086 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3089 if (appData.oldSaveStyle) {
3090 XtSetValues(XtNameToWidget(menuBarWidget,
3091 "menuOptions.Old Save Style"), args, 1);
3093 if (appData.periodicUpdates) {
3094 XtSetValues(XtNameToWidget(menuBarWidget,
3095 "menuOptions.Periodic Updates"), args, 1);
3097 if (appData.ponderNextMove) {
3098 XtSetValues(XtNameToWidget(menuBarWidget,
3099 "menuOptions.Ponder Next Move"), args, 1);
3101 if (appData.popupExitMessage) {
3102 XtSetValues(XtNameToWidget(menuBarWidget,
3103 "menuOptions.Popup Exit Message"), args, 1);
3105 if (appData.popupMoveErrors) {
3106 XtSetValues(XtNameToWidget(menuBarWidget,
3107 "menuOptions.Popup Move Errors"), args, 1);
3109 if (appData.premove) {
3110 XtSetValues(XtNameToWidget(menuBarWidget,
3111 "menuOptions.Premove"), args, 1);
3113 if (appData.quietPlay) {
3114 XtSetValues(XtNameToWidget(menuBarWidget,
3115 "menuOptions.Quiet Play"), args, 1);
3117 if (appData.showCoords) {
3118 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3121 if (appData.hideThinkingFromHuman) {
3122 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3125 if (appData.testLegality) {
3126 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3133 ReadBitmap(&wIconPixmap, "icon_white.bm",
3134 icon_white_bits, icon_white_width, icon_white_height);
3135 ReadBitmap(&bIconPixmap, "icon_black.bm",
3136 icon_black_bits, icon_black_width, icon_black_height);
3137 iconPixmap = wIconPixmap;
3139 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3140 XtSetValues(shellWidget, args, i);
3143 * Create a cursor for the board widget.
3145 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3146 XChangeWindowAttributes(xDisplay, xBoardWindow,
3147 CWCursor, &window_attributes);
3150 * Inhibit shell resizing.
3152 shellArgs[0].value = (XtArgVal) &w;
3153 shellArgs[1].value = (XtArgVal) &h;
3154 XtGetValues(shellWidget, shellArgs, 2);
3155 shellArgs[4].value = shellArgs[2].value = w;
3156 shellArgs[5].value = shellArgs[3].value = h;
3157 XtSetValues(shellWidget, &shellArgs[2], 4);
3158 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3159 marginH = h - boardHeight;
3161 CatchDeleteWindow(shellWidget, "QuitProc");
3166 if (appData.bitmapDirectory[0] != NULLCHAR) {
3173 /* Create regular pieces */
3174 if (!useImages) CreatePieces();
3179 if (appData.animate || appData.animateDragging)
3182 XtAugmentTranslations(formWidget,
3183 XtParseTranslationTable(globalTranslations));
3184 XtAugmentTranslations(boardWidget,
3185 XtParseTranslationTable(boardTranslations));
3186 XtAugmentTranslations(whiteTimerWidget,
3187 XtParseTranslationTable(whiteTranslations));
3188 XtAugmentTranslations(blackTimerWidget,
3189 XtParseTranslationTable(blackTranslations));
3191 /* Why is the following needed on some versions of X instead
3192 * of a translation? */
3193 XtAddEventHandler(boardWidget, ExposureMask, False,
3194 (XtEventHandler) EventProc, NULL);
3199 if (errorExitStatus == -1) {
3200 if (appData.icsActive) {
3201 /* We now wait until we see "login:" from the ICS before
3202 sending the logon script (problems with timestamp otherwise) */
3203 /*ICSInitScript();*/
3204 if (appData.icsInputBox) ICSInputBoxPopUp();
3208 signal(SIGWINCH, TermSizeSigHandler);
3210 signal(SIGINT, IntSigHandler);
3211 signal(SIGTERM, IntSigHandler);
3212 if (*appData.cmailGameName != NULLCHAR) {
3213 signal(SIGUSR1, CmailSigHandler);
3216 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3219 XtAppMainLoop(appContext);
3220 if (appData.debugMode) fclose(debugFP); // [DM] debug
3227 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3228 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3230 unlink(gameCopyFilename);
3231 unlink(gamePasteFilename);
3234 RETSIGTYPE TermSizeSigHandler(int sig)
3247 CmailSigHandler(sig)
3253 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3255 /* Activate call-back function CmailSigHandlerCallBack() */
3256 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3258 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3262 CmailSigHandlerCallBack(isr, closure, message, count, error)
3270 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3272 /**** end signal code ****/
3282 f = fopen(appData.icsLogon, "r");
3288 strcat(buf, appData.icsLogon);
3289 f = fopen(buf, "r");
3293 ProcessICSInitScript(f);
3300 EditCommentPopDown();
3315 if (!menuBarWidget) return;
3316 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
3318 DisplayError("menuStep.Revert", 0);
3320 XtSetSensitive(w, !grey);
3325 SetMenuEnables(enab)
3329 if (!menuBarWidget) return;
3330 while (enab->name != NULL) {
3331 w = XtNameToWidget(menuBarWidget, enab->name);
3333 DisplayError(enab->name, 0);
3335 XtSetSensitive(w, enab->value);
3341 Enables icsEnables[] = {
3342 { "menuFile.Mail Move", False },
3343 { "menuFile.Reload CMail Message", False },
3344 { "menuMode.Machine Black", False },
3345 { "menuMode.Machine White", False },
3346 { "menuMode.Analysis Mode", False },
3347 { "menuMode.Analyze File", False },
3348 { "menuMode.Two Machines", False },
3350 { "menuHelp.Hint", False },
3351 { "menuHelp.Book", False },
3352 { "menuStep.Move Now", False },
3353 { "menuOptions.Periodic Updates", False },
3354 { "menuOptions.Hide Thinking", False },
3355 { "menuOptions.Ponder Next Move", False },
3360 Enables ncpEnables[] = {
3361 { "menuFile.Mail Move", False },
3362 { "menuFile.Reload CMail Message", False },
3363 { "menuMode.Machine White", False },
3364 { "menuMode.Machine Black", False },
3365 { "menuMode.Analysis Mode", False },
3366 { "menuMode.Analyze File", False },
3367 { "menuMode.Two Machines", False },
3368 { "menuMode.ICS Client", False },
3369 { "menuMode.ICS Input Box", False },
3370 { "Action", False },
3371 { "menuStep.Revert", False },
3372 { "menuStep.Move Now", False },
3373 { "menuStep.Retract Move", False },
3374 { "menuOptions.Auto Comment", False },
3375 { "menuOptions.Auto Flag", False },
3376 { "menuOptions.Auto Flip View", False },
3377 { "menuOptions.Auto Observe", False },
3378 { "menuOptions.Auto Raise Board", False },
3379 { "menuOptions.Get Move List", False },
3380 { "menuOptions.ICS Alarm", False },
3381 { "menuOptions.Move Sound", False },
3382 { "menuOptions.Quiet Play", False },
3383 { "menuOptions.Hide Thinking", False },
3384 { "menuOptions.Periodic Updates", False },
3385 { "menuOptions.Ponder Next Move", False },
3386 { "menuHelp.Hint", False },
3387 { "menuHelp.Book", False },
3391 Enables gnuEnables[] = {
3392 { "menuMode.ICS Client", False },
3393 { "menuMode.ICS Input Box", False },
3394 { "menuAction.Accept", False },
3395 { "menuAction.Decline", False },
3396 { "menuAction.Rematch", False },
3397 { "menuAction.Adjourn", False },
3398 { "menuAction.Stop Examining", False },
3399 { "menuAction.Stop Observing", False },
3400 { "menuStep.Revert", False },
3401 { "menuOptions.Auto Comment", False },
3402 { "menuOptions.Auto Observe", False },
3403 { "menuOptions.Auto Raise Board", False },
3404 { "menuOptions.Get Move List", False },
3405 { "menuOptions.Premove", False },
3406 { "menuOptions.Quiet Play", False },
3408 /* The next two options rely on SetCmailMode being called *after* */
3409 /* SetGNUMode so that when GNU is being used to give hints these */
3410 /* menu options are still available */
3412 { "menuFile.Mail Move", False },
3413 { "menuFile.Reload CMail Message", False },
3417 Enables cmailEnables[] = {
3419 { "menuAction.Call Flag", False },
3420 { "menuAction.Draw", True },
3421 { "menuAction.Adjourn", False },
3422 { "menuAction.Abort", False },
3423 { "menuAction.Stop Observing", False },
3424 { "menuAction.Stop Examining", False },
3425 { "menuFile.Mail Move", True },
3426 { "menuFile.Reload CMail Message", True },
3430 Enables trainingOnEnables[] = {
3431 { "menuMode.Edit Comment", False },
3432 { "menuMode.Pause", False },
3433 { "menuStep.Forward", False },
3434 { "menuStep.Backward", False },
3435 { "menuStep.Forward to End", False },
3436 { "menuStep.Back to Start", False },
3437 { "menuStep.Move Now", False },
3438 { "menuStep.Truncate Game", False },
3442 Enables trainingOffEnables[] = {
3443 { "menuMode.Edit Comment", True },
3444 { "menuMode.Pause", True },
3445 { "menuStep.Forward", True },
3446 { "menuStep.Backward", True },
3447 { "menuStep.Forward to End", True },
3448 { "menuStep.Back to Start", True },
3449 { "menuStep.Move Now", True },
3450 { "menuStep.Truncate Game", True },
3454 Enables machineThinkingEnables[] = {
3455 { "menuFile.Load Game", False },
3456 { "menuFile.Load Next Game", False },
3457 { "menuFile.Load Previous Game", False },
3458 { "menuFile.Reload Same Game", False },
3459 { "menuFile.Paste Game", False },
3460 { "menuFile.Load Position", False },
3461 { "menuFile.Load Next Position", False },
3462 { "menuFile.Load Previous Position", False },
3463 { "menuFile.Reload Same Position", False },
3464 { "menuFile.Paste Position", False },
3465 { "menuMode.Machine White", False },
3466 { "menuMode.Machine Black", False },
3467 { "menuMode.Two Machines", False },
3468 { "menuStep.Retract Move", False },
3472 Enables userThinkingEnables[] = {
3473 { "menuFile.Load Game", True },
3474 { "menuFile.Load Next Game", True },
3475 { "menuFile.Load Previous Game", True },
3476 { "menuFile.Reload Same Game", True },
3477 { "menuFile.Paste Game", True },
3478 { "menuFile.Load Position", True },
3479 { "menuFile.Load Next Position", True },
3480 { "menuFile.Load Previous Position", True },
3481 { "menuFile.Reload Same Position", True },
3482 { "menuFile.Paste Position", True },
3483 { "menuMode.Machine White", True },
3484 { "menuMode.Machine Black", True },
3485 { "menuMode.Two Machines", True },
3486 { "menuStep.Retract Move", True },
3492 SetMenuEnables(icsEnables);
3495 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3496 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3503 SetMenuEnables(ncpEnables);
3509 SetMenuEnables(gnuEnables);
3515 SetMenuEnables(cmailEnables);
3521 SetMenuEnables(trainingOnEnables);
3522 if (appData.showButtonBar) {
3523 XtSetSensitive(buttonBarWidget, False);
3529 SetTrainingModeOff()
3531 SetMenuEnables(trainingOffEnables);
3532 if (appData.showButtonBar) {
3533 XtSetSensitive(buttonBarWidget, True);
3538 SetUserThinkingEnables()
3540 if (appData.noChessProgram) return;
3541 SetMenuEnables(userThinkingEnables);
3545 SetMachineThinkingEnables()
3547 if (appData.noChessProgram) return;
3548 SetMenuEnables(machineThinkingEnables);
3550 case MachinePlaysBlack:
3551 case MachinePlaysWhite:
3552 case TwoMachinesPlay:
3553 XtSetSensitive(XtNameToWidget(menuBarWidget,
3554 ModeToWidgetName(gameMode)), True);
3561 #define Abs(n) ((n)<0 ? -(n) : (n))
3564 * Find a font that matches "pattern" that is as close as
3565 * possible to the targetPxlSize. Prefer fonts that are k
3566 * pixels smaller to fonts that are k pixels larger. The
3567 * pattern must be in the X Consortium standard format,
3568 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3569 * The return value should be freed with XtFree when no
3572 char *FindFont(pattern, targetPxlSize)
3576 char **fonts, *p, *best, *scalable, *scalableTail;
3577 int i, j, nfonts, minerr, err, pxlSize;
3580 char **missing_list;
3582 char *def_string, *base_fnt_lst, strInt[3];
3584 XFontStruct **fnt_list;
3586 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3587 sprintf(strInt, "%d", targetPxlSize);
3588 p = strstr(pattern, "--");
3589 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3590 strcat(base_fnt_lst, strInt);
3591 strcat(base_fnt_lst, strchr(p + 2, '-'));
3593 if ((fntSet = XCreateFontSet(xDisplay,
3597 &def_string)) == NULL) {
3599 fprintf(stderr, _("Unable to create font set.\n"));
3603 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3605 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3607 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3608 programName, pattern);
3616 for (i=0; i<nfonts; i++) {
3619 if (*p != '-') continue;
3621 if (*p == NULLCHAR) break;
3622 if (*p++ == '-') j++;
3624 if (j < 7) continue;
3627 scalable = fonts[i];
3630 err = pxlSize - targetPxlSize;
3631 if (Abs(err) < Abs(minerr) ||
3632 (minerr > 0 && err < 0 && -err == minerr)) {
3638 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3639 /* If the error is too big and there is a scalable font,
3640 use the scalable font. */
3641 int headlen = scalableTail - scalable;
3642 p = (char *) XtMalloc(strlen(scalable) + 10);
3643 while (isdigit(*scalableTail)) scalableTail++;
3644 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3646 p = (char *) XtMalloc(strlen(best) + 1);
3649 if (appData.debugMode) {
3650 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3651 pattern, targetPxlSize, p);
3654 if (missing_count > 0)
3655 XFreeStringList(missing_list);
3656 XFreeFontSet(xDisplay, fntSet);
3658 XFreeFontNames(fonts);
3665 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3666 | GCBackground | GCFunction | GCPlaneMask;
3667 XGCValues gc_values;
3670 gc_values.plane_mask = AllPlanes;
3671 gc_values.line_width = lineGap;
3672 gc_values.line_style = LineSolid;
3673 gc_values.function = GXcopy;
3675 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3676 gc_values.background = XBlackPixel(xDisplay, xScreen);
3677 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3679 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3680 gc_values.background = XWhitePixel(xDisplay, xScreen);
3681 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3682 XSetFont(xDisplay, coordGC, coordFontID);
3684 // [HGM] make font for holdings counts (white on black0
3685 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3686 gc_values.background = XBlackPixel(xDisplay, xScreen);
3687 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3688 XSetFont(xDisplay, countGC, countFontID);
3690 if (appData.monoMode) {
3691 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3692 gc_values.background = XWhitePixel(xDisplay, xScreen);
3693 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3695 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3696 gc_values.background = XBlackPixel(xDisplay, xScreen);
3697 lightSquareGC = wbPieceGC
3698 = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3701 gc_values.background = XWhitePixel(xDisplay, xScreen);
3702 darkSquareGC = bwPieceGC
3703 = XtGetGC(shellWidget, value_mask, &gc_values);
3705 if (DefaultDepth(xDisplay, xScreen) == 1) {
3706 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3707 gc_values.function = GXcopyInverted;
3708 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3709 gc_values.function = GXcopy;
3710 if (XBlackPixel(xDisplay, xScreen) == 1) {
3711 bwPieceGC = darkSquareGC;
3712 wbPieceGC = copyInvertedGC;
3714 bwPieceGC = copyInvertedGC;
3715 wbPieceGC = lightSquareGC;
3719 gc_values.foreground = highlightSquareColor;
3720 gc_values.background = highlightSquareColor;
3721 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3723 gc_values.foreground = premoveHighlightColor;
3724 gc_values.background = premoveHighlightColor;
3725 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3727 gc_values.foreground = lightSquareColor;
3728 gc_values.background = darkSquareColor;
3729 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3731 gc_values.foreground = darkSquareColor;
3732 gc_values.background = lightSquareColor;
3733 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3735 gc_values.foreground = jailSquareColor;
3736 gc_values.background = jailSquareColor;
3737 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3739 gc_values.foreground = whitePieceColor;
3740 gc_values.background = darkSquareColor;
3741 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3743 gc_values.foreground = whitePieceColor;
3744 gc_values.background = lightSquareColor;
3745 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3747 gc_values.foreground = whitePieceColor;
3748 gc_values.background = jailSquareColor;
3749 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3751 gc_values.foreground = blackPieceColor;
3752 gc_values.background = darkSquareColor;
3753 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3755 gc_values.foreground = blackPieceColor;
3756 gc_values.background = lightSquareColor;
3757 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3759 gc_values.foreground = blackPieceColor;
3760 gc_values.background = jailSquareColor;
3761 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3765 void loadXIM(xim, xmask, filename, dest, mask)
3778 fp = fopen(filename, "rb");
3780 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3787 for (y=0; y<h; ++y) {
3788 for (x=0; x<h; ++x) {
3793 XPutPixel(xim, x, y, blackPieceColor);
3795 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3798 XPutPixel(xim, x, y, darkSquareColor);
3800 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3803 XPutPixel(xim, x, y, whitePieceColor);
3805 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3808 XPutPixel(xim, x, y, lightSquareColor);
3810 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3816 /* create Pixmap of piece */
3817 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3819 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3822 /* create Pixmap of clipmask
3823 Note: We assume the white/black pieces have the same
3824 outline, so we make only 6 masks. This is okay
3825 since the XPM clipmask routines do the same. */
3827 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3829 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3832 /* now create the 1-bit version */
3833 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3836 values.foreground = 1;
3837 values.background = 0;
3839 /* Don't use XtGetGC, not read only */
3840 maskGC = XCreateGC(xDisplay, *mask,
3841 GCForeground | GCBackground, &values);
3842 XCopyPlane(xDisplay, temp, *mask, maskGC,
3843 0, 0, squareSize, squareSize, 0, 0, 1);
3844 XFreePixmap(xDisplay, temp);
3849 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3851 void CreateXIMPieces()
3856 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3861 /* The XSynchronize calls were copied from CreatePieces.
3862 Not sure if needed, but can't hurt */
3863 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3866 /* temp needed by loadXIM() */
3867 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3868 0, 0, ss, ss, AllPlanes, XYPixmap);
3870 if (strlen(appData.pixmapDirectory) == 0) {
3874 if (appData.monoMode) {
3875 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3879 fprintf(stderr, _("\nLoading XIMs...\n"));
3881 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3882 fprintf(stderr, "%d", piece+1);
3883 for (kind=0; kind<4; kind++) {
3884 fprintf(stderr, ".");
3885 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3886 ExpandPathName(appData.pixmapDirectory),
3887 piece <= (int) WhiteKing ? "" : "w",
3888 pieceBitmapNames[piece],
3890 ximPieceBitmap[kind][piece] =
3891 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3892 0, 0, ss, ss, AllPlanes, XYPixmap);
3893 if (appData.debugMode)
3894 fprintf(stderr, _("(File:%s:) "), buf);
3895 loadXIM(ximPieceBitmap[kind][piece],
3897 &(xpmPieceBitmap2[kind][piece]),
3898 &(ximMaskPm2[piece]));
3899 if(piece <= (int)WhiteKing)
3900 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3902 fprintf(stderr," ");
3904 /* Load light and dark squares */
3905 /* If the LSQ and DSQ pieces don't exist, we will
3906 draw them with solid squares. */
3907 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3908 if (access(buf, 0) != 0) {
3912 fprintf(stderr, _("light square "));
3914 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3915 0, 0, ss, ss, AllPlanes, XYPixmap);
3916 if (appData.debugMode)
3917 fprintf(stderr, _("(File:%s:) "), buf);
3919 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3920 fprintf(stderr, _("dark square "));
3921 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3922 ExpandPathName(appData.pixmapDirectory), ss);
3923 if (appData.debugMode)
3924 fprintf(stderr, _("(File:%s:) "), buf);
3926 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3927 0, 0, ss, ss, AllPlanes, XYPixmap);
3928 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3929 xpmJailSquare = xpmLightSquare;
3931 fprintf(stderr, _("Done.\n"));
3933 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3937 void CreateXPMPieces()
3941 u_int ss = squareSize;
3943 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3944 XpmColorSymbol symbols[4];
3946 /* The XSynchronize calls were copied from CreatePieces.
3947 Not sure if needed, but can't hurt */
3948 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3950 /* Setup translations so piece colors match square colors */
3951 symbols[0].name = "light_piece";
3952 symbols[0].value = appData.whitePieceColor;
3953 symbols[1].name = "dark_piece";
3954 symbols[1].value = appData.blackPieceColor;
3955 symbols[2].name = "light_square";
3956 symbols[2].value = appData.lightSquareColor;
3957 symbols[3].name = "dark_square";
3958 symbols[3].value = appData.darkSquareColor;
3960 attr.valuemask = XpmColorSymbols;
3961 attr.colorsymbols = symbols;
3962 attr.numsymbols = 4;
3964 if (appData.monoMode) {
3965 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3969 if (strlen(appData.pixmapDirectory) == 0) {
3970 XpmPieces* pieces = builtInXpms;
3973 while (pieces->size != squareSize && pieces->size) pieces++;
3974 if (!pieces->size) {
3975 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3978 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3979 for (kind=0; kind<4; kind++) {
3981 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3982 pieces->xpm[piece][kind],
3983 &(xpmPieceBitmap2[kind][piece]),
3984 NULL, &attr)) != 0) {
3985 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3989 if(piece <= (int) WhiteKing)
3990 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3994 xpmJailSquare = xpmLightSquare;
3998 fprintf(stderr, _("\nLoading XPMs...\n"));
4001 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4002 fprintf(stderr, "%d ", piece+1);
4003 for (kind=0; kind<4; kind++) {
4004 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
4005 ExpandPathName(appData.pixmapDirectory),
4006 piece > (int) WhiteKing ? "w" : "",
4007 pieceBitmapNames[piece],
4009 if (appData.debugMode) {
4010 fprintf(stderr, _("(File:%s:) "), buf);
4012 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4013 &(xpmPieceBitmap2[kind][piece]),
4014 NULL, &attr)) != 0) {
4015 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
4016 // [HGM] missing: read of unorthodox piece failed; substitute King.
4017 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
4018 ExpandPathName(appData.pixmapDirectory),
4020 if (appData.debugMode) {
4021 fprintf(stderr, _("(Replace by File:%s:) "), buf);
4023 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4024 &(xpmPieceBitmap2[kind][piece]),
4028 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4033 if(piece <= (int) WhiteKing)
4034 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4037 /* Load light and dark squares */
4038 /* If the LSQ and DSQ pieces don't exist, we will
4039 draw them with solid squares. */
4040 fprintf(stderr, _("light square "));
4041 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4042 if (access(buf, 0) != 0) {
4046 if (appData.debugMode)
4047 fprintf(stderr, _("(File:%s:) "), buf);
4049 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4050 &xpmLightSquare, NULL, &attr)) != 0) {
4051 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4054 fprintf(stderr, _("dark square "));
4055 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4056 ExpandPathName(appData.pixmapDirectory), ss);
4057 if (appData.debugMode) {
4058 fprintf(stderr, _("(File:%s:) "), buf);
4060 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4061 &xpmDarkSquare, NULL, &attr)) != 0) {
4062 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4066 xpmJailSquare = xpmLightSquare;
4067 fprintf(stderr, _("Done.\n"));
4069 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4072 #endif /* HAVE_LIBXPM */
4075 /* No built-in bitmaps */
4080 u_int ss = squareSize;
4082 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4085 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4086 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4087 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4088 pieceBitmapNames[piece],
4089 ss, kind == SOLID ? 's' : 'o');
4090 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4091 if(piece <= (int)WhiteKing)
4092 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4096 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4100 /* With built-in bitmaps */
4103 BuiltInBits* bib = builtInBits;
4106 u_int ss = squareSize;
4108 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4111 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4113 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4114 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4115 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4116 pieceBitmapNames[piece],
4117 ss, kind == SOLID ? 's' : 'o');
4118 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4119 bib->bits[kind][piece], ss, ss);
4120 if(piece <= (int)WhiteKing)
4121 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4125 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4130 void ReadBitmap(pm, name, bits, wreq, hreq)
4133 unsigned char bits[];
4139 char msg[MSG_SIZ], fullname[MSG_SIZ];
4141 if (*appData.bitmapDirectory != NULLCHAR) {
4142 strcpy(fullname, appData.bitmapDirectory);
4143 strcat(fullname, "/");
4144 strcat(fullname, name);
4145 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4146 &w, &h, pm, &x_hot, &y_hot);
4147 fprintf(stderr, "load %s\n", name);
4148 if (errcode != BitmapSuccess) {
4150 case BitmapOpenFailed:
4151 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4153 case BitmapFileInvalid:
4154 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4156 case BitmapNoMemory:
4157 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4161 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4165 fprintf(stderr, _("%s: %s...using built-in\n"),
4167 } else if (w != wreq || h != hreq) {
4169 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4170 programName, fullname, w, h, wreq, hreq);
4176 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4185 if (lineGap == 0) return;
4187 /* [HR] Split this into 2 loops for non-square boards. */
4189 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4190 gridSegments[i].x1 = 0;
4191 gridSegments[i].x2 =
4192 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4193 gridSegments[i].y1 = gridSegments[i].y2
4194 = lineGap / 2 + (i * (squareSize + lineGap));
4197 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4198 gridSegments[j + i].y1 = 0;
4199 gridSegments[j + i].y2 =
4200 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4201 gridSegments[j + i].x1 = gridSegments[j + i].x2
4202 = lineGap / 2 + (j * (squareSize + lineGap));
4206 static void MenuBarSelect(w, addr, index)
4211 XtActionProc proc = (XtActionProc) addr;
4213 (proc)(NULL, NULL, NULL, NULL);
4216 void CreateMenuBarPopup(parent, name, mb)
4226 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4229 XtSetArg(args[j], XtNleftMargin, 20); j++;
4230 XtSetArg(args[j], XtNrightMargin, 20); j++;
4232 while (mi->string != NULL) {
4233 if (strcmp(mi->string, "----") == 0) {
4234 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4237 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4238 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4240 XtAddCallback(entry, XtNcallback,
4241 (XtCallbackProc) MenuBarSelect,
4242 (caddr_t) mi->proc);
4248 Widget CreateMenuBar(mb)
4252 Widget anchor, menuBar;
4254 char menuName[MSG_SIZ];
4257 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4258 XtSetArg(args[j], XtNvSpace, 0); j++;
4259 XtSetArg(args[j], XtNborderWidth, 0); j++;
4260 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4261 formWidget, args, j);
4263 while (mb->name != NULL) {
4264 strcpy(menuName, "menu");
4265 strcat(menuName, mb->name);
4267 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4270 shortName[0] = _(mb->name)[0];
4271 shortName[1] = NULLCHAR;
4272 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4275 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4278 XtSetArg(args[j], XtNborderWidth, 0); j++;
4279 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4281 CreateMenuBarPopup(menuBar, menuName, mb);
4287 Widget CreateButtonBar(mi)
4291 Widget button, buttonBar;
4295 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4297 XtSetArg(args[j], XtNhSpace, 0); j++;
4299 XtSetArg(args[j], XtNborderWidth, 0); j++;
4300 XtSetArg(args[j], XtNvSpace, 0); j++;
4301 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4302 formWidget, args, j);
4304 while (mi->string != NULL) {
4307 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4308 XtSetArg(args[j], XtNborderWidth, 0); j++;
4310 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4311 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4312 buttonBar, args, j);
4313 XtAddCallback(button, XtNcallback,
4314 (XtCallbackProc) MenuBarSelect,
4315 (caddr_t) mi->proc);
4322 CreatePieceMenu(name, color)
4329 ChessSquare selection;
4331 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4332 boardWidget, args, 0);
4334 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4335 String item = pieceMenuStrings[color][i];
4337 if (strcmp(item, "----") == 0) {
4338 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4341 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4342 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4344 selection = pieceMenuTranslation[color][i];
4345 XtAddCallback(entry, XtNcallback,
4346 (XtCallbackProc) PieceMenuSelect,
4347 (caddr_t) selection);
4348 if (selection == WhitePawn || selection == BlackPawn) {
4349 XtSetArg(args[0], XtNpopupOnEntry, entry);
4350 XtSetValues(menu, args, 1);
4363 ChessSquare selection;
4365 whitePieceMenu = CreatePieceMenu("menuW", 0);
4366 blackPieceMenu = CreatePieceMenu("menuB", 1);
4368 XtRegisterGrabAction(PieceMenuPopup, True,
4369 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4370 GrabModeAsync, GrabModeAsync);
4372 XtSetArg(args[0], XtNlabel, _("Drop"));
4373 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4374 boardWidget, args, 1);
4375 for (i = 0; i < DROP_MENU_SIZE; i++) {
4376 String item = dropMenuStrings[i];
4378 if (strcmp(item, "----") == 0) {
4379 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4382 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4383 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4385 selection = dropMenuTranslation[i];
4386 XtAddCallback(entry, XtNcallback,
4387 (XtCallbackProc) DropMenuSelect,
4388 (caddr_t) selection);
4393 void SetupDropMenu()
4401 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4402 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4403 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4404 dmEnables[i].piece);
4405 XtSetSensitive(entry, p != NULL || !appData.testLegality
4406 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4407 && !appData.icsActive));
4409 while (p && *p++ == dmEnables[i].piece) count++;
4410 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4412 XtSetArg(args[j], XtNlabel, label); j++;
4413 XtSetValues(entry, args, j);
4417 void PieceMenuPopup(w, event, params, num_params)
4421 Cardinal *num_params;
4424 if (event->type != ButtonPress) return;
4425 if (errorUp) ErrorPopDown();
4429 whichMenu = params[0];
4431 case IcsPlayingWhite:
4432 case IcsPlayingBlack:
4434 case MachinePlaysWhite:
4435 case MachinePlaysBlack:
4436 if (appData.testLegality &&
4437 gameInfo.variant != VariantBughouse &&
4438 gameInfo.variant != VariantCrazyhouse) return;
4440 whichMenu = "menuD";
4446 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4447 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4448 pmFromX = pmFromY = -1;
4452 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4454 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4456 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4459 static void PieceMenuSelect(w, piece, junk)
4464 if (pmFromX < 0 || pmFromY < 0) return;
4465 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4468 static void DropMenuSelect(w, piece, junk)
4473 if (pmFromX < 0 || pmFromY < 0) return;
4474 DropMenuEvent(piece, pmFromX, pmFromY);
4477 void WhiteClock(w, event, prms, nprms)
4483 if (gameMode == EditPosition || gameMode == IcsExamining) {
4484 SetWhiteToPlayEvent();
4485 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4490 void BlackClock(w, event, prms, nprms)
4496 if (gameMode == EditPosition || gameMode == IcsExamining) {
4497 SetBlackToPlayEvent();
4498 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4505 * If the user selects on a border boundary, return -1; if off the board,
4506 * return -2. Otherwise map the event coordinate to the square.
4508 int EventToSquare(x, limit)
4516 if ((x % (squareSize + lineGap)) >= squareSize)
4518 x /= (squareSize + lineGap);
4524 static void do_flash_delay(msec)
4530 static void drawHighlight(file, rank, gc)
4536 if (lineGap == 0 || appData.blindfold) return;
4539 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4540 (squareSize + lineGap);
4541 y = lineGap/2 + rank * (squareSize + lineGap);
4543 x = lineGap/2 + file * (squareSize + lineGap);
4544 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4545 (squareSize + lineGap);
4548 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4549 squareSize+lineGap, squareSize+lineGap);
4552 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4553 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4556 SetHighlights(fromX, fromY, toX, toY)
4557 int fromX, fromY, toX, toY;
4559 if (hi1X != fromX || hi1Y != fromY) {
4560 if (hi1X >= 0 && hi1Y >= 0) {
4561 drawHighlight(hi1X, hi1Y, lineGC);
4563 if (fromX >= 0 && fromY >= 0) {
4564 drawHighlight(fromX, fromY, highlineGC);
4567 if (hi2X != toX || hi2Y != toY) {
4568 if (hi2X >= 0 && hi2Y >= 0) {
4569 drawHighlight(hi2X, hi2Y, lineGC);
4571 if (toX >= 0 && toY >= 0) {
4572 drawHighlight(toX, toY, highlineGC);
4584 SetHighlights(-1, -1, -1, -1);
4589 SetPremoveHighlights(fromX, fromY, toX, toY)
4590 int fromX, fromY, toX, toY;
4592 if (pm1X != fromX || pm1Y != fromY) {
4593 if (pm1X >= 0 && pm1Y >= 0) {
4594 drawHighlight(pm1X, pm1Y, lineGC);
4596 if (fromX >= 0 && fromY >= 0) {
4597 drawHighlight(fromX, fromY, prelineGC);
4600 if (pm2X != toX || pm2Y != toY) {
4601 if (pm2X >= 0 && pm2Y >= 0) {
4602 drawHighlight(pm2X, pm2Y, lineGC);
4604 if (toX >= 0 && toY >= 0) {
4605 drawHighlight(toX, toY, prelineGC);
4615 ClearPremoveHighlights()
4617 SetPremoveHighlights(-1, -1, -1, -1);
4620 static void BlankSquare(x, y, color, piece, dest)
4625 if (useImages && useImageSqs) {
4629 pm = xpmLightSquare;
4634 case 2: /* neutral */
4639 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4640 squareSize, squareSize, x, y);
4650 case 2: /* neutral */
4655 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4660 I split out the routines to draw a piece so that I could
4661 make a generic flash routine.
4663 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4665 int square_color, x, y;
4668 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4669 switch (square_color) {
4671 case 2: /* neutral */
4673 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4674 ? *pieceToOutline(piece)
4675 : *pieceToSolid(piece),
4676 dest, bwPieceGC, 0, 0,
4677 squareSize, squareSize, x, y);
4680 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4681 ? *pieceToSolid(piece)
4682 : *pieceToOutline(piece),
4683 dest, wbPieceGC, 0, 0,
4684 squareSize, squareSize, x, y);
4689 static void monoDrawPiece(piece, square_color, x, y, dest)
4691 int square_color, x, y;
4694 switch (square_color) {
4696 case 2: /* neutral */
4698 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4699 ? *pieceToOutline(piece)
4700 : *pieceToSolid(piece),
4701 dest, bwPieceGC, 0, 0,
4702 squareSize, squareSize, x, y, 1);
4705 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4706 ? *pieceToSolid(piece)
4707 : *pieceToOutline(piece),
4708 dest, wbPieceGC, 0, 0,
4709 squareSize, squareSize, x, y, 1);
4714 static void colorDrawPiece(piece, square_color, x, y, dest)
4716 int square_color, x, y;
4719 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4720 switch (square_color) {
4722 XCopyPlane(xDisplay, *pieceToSolid(piece),
4723 dest, (int) piece < (int) BlackPawn
4724 ? wlPieceGC : blPieceGC, 0, 0,
4725 squareSize, squareSize, x, y, 1);
4728 XCopyPlane(xDisplay, *pieceToSolid(piece),
4729 dest, (int) piece < (int) BlackPawn
4730 ? wdPieceGC : bdPieceGC, 0, 0,
4731 squareSize, squareSize, x, y, 1);
4733 case 2: /* neutral */
4735 XCopyPlane(xDisplay, *pieceToSolid(piece),
4736 dest, (int) piece < (int) BlackPawn
4737 ? wjPieceGC : bjPieceGC, 0, 0,
4738 squareSize, squareSize, x, y, 1);
4743 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4745 int square_color, x, y;
4750 switch (square_color) {
4752 case 2: /* neutral */
4754 if ((int)piece < (int) BlackPawn) {
4762 if ((int)piece < (int) BlackPawn) {
4770 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4771 dest, wlPieceGC, 0, 0,
4772 squareSize, squareSize, x, y);
4775 typedef void (*DrawFunc)();
4777 DrawFunc ChooseDrawFunc()
4779 if (appData.monoMode) {
4780 if (DefaultDepth(xDisplay, xScreen) == 1) {
4781 return monoDrawPiece_1bit;
4783 return monoDrawPiece;
4787 return colorDrawPieceImage;
4789 return colorDrawPiece;
4793 /* [HR] determine square color depending on chess variant. */
4794 static int SquareColor(row, column)
4799 if (gameInfo.variant == VariantXiangqi) {
4800 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4802 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4804 } else if (row <= 4) {
4810 square_color = ((column + row) % 2) == 1;
4813 /* [hgm] holdings: next line makes all holdings squares light */
4814 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4816 return square_color;
4819 void DrawSquare(row, column, piece, do_flash)
4820 int row, column, do_flash;
4823 int square_color, x, y, direction, font_ascent, font_descent;
4826 XCharStruct overall;
4830 /* Calculate delay in milliseconds (2-delays per complete flash) */
4831 flash_delay = 500 / appData.flashRate;
4834 x = lineGap + ((BOARD_WIDTH-1)-column) *
4835 (squareSize + lineGap);
4836 y = lineGap + row * (squareSize + lineGap);
4838 x = lineGap + column * (squareSize + lineGap);
4839 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4840 (squareSize + lineGap);
4843 square_color = SquareColor(row, column);
4845 if ( // [HGM] holdings: blank out area between board and holdings
4846 column == BOARD_LEFT-1 || column == BOARD_RGHT
4847 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4848 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4849 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4851 // [HGM] print piece counts next to holdings
4852 string[1] = NULLCHAR;
4853 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4854 string[0] = '0' + piece;
4855 XTextExtents(countFontStruct, string, 1, &direction,
4856 &font_ascent, &font_descent, &overall);
4857 if (appData.monoMode) {
4858 XDrawImageString(xDisplay, xBoardWindow, countGC,
4859 x + squareSize - overall.width - 2,
4860 y + font_ascent + 1, string, 1);
4862 XDrawString(xDisplay, xBoardWindow, countGC,
4863 x + squareSize - overall.width - 2,
4864 y + font_ascent + 1, string, 1);
4867 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4868 string[0] = '0' + piece;
4869 XTextExtents(countFontStruct, string, 1, &direction,
4870 &font_ascent, &font_descent, &overall);
4871 if (appData.monoMode) {
4872 XDrawImageString(xDisplay, xBoardWindow, countGC,
4873 x + 2, y + font_ascent + 1, string, 1);
4875 XDrawString(xDisplay, xBoardWindow, countGC,
4876 x + 2, y + font_ascent + 1, string, 1);
4880 if (piece == EmptySquare || appData.blindfold) {
4881 BlankSquare(x, y, square_color, piece, xBoardWindow);
4883 drawfunc = ChooseDrawFunc();
4884 if (do_flash && appData.flashCount > 0) {
4885 for (i=0; i<appData.flashCount; ++i) {
4887 drawfunc(piece, square_color, x, y, xBoardWindow);
4888 XSync(xDisplay, False);
4889 do_flash_delay(flash_delay);
4891 BlankSquare(x, y, square_color, piece, xBoardWindow);
4892 XSync(xDisplay, False);
4893 do_flash_delay(flash_delay);
4896 drawfunc(piece, square_color, x, y, xBoardWindow);
4900 string[1] = NULLCHAR;
4901 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4902 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4903 string[0] = 'a' + column - BOARD_LEFT;
4904 XTextExtents(coordFontStruct, string, 1, &direction,
4905 &font_ascent, &font_descent, &overall);
4906 if (appData.monoMode) {
4907 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4908 x + squareSize - overall.width - 2,
4909 y + squareSize - font_descent - 1, string, 1);
4911 XDrawString(xDisplay, xBoardWindow, coordGC,
4912 x + squareSize - overall.width - 2,
4913 y + squareSize - font_descent - 1, string, 1);
4916 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4917 string[0] = ONE + row;
4918 XTextExtents(coordFontStruct, string, 1, &direction,
4919 &font_ascent, &font_descent, &overall);
4920 if (appData.monoMode) {
4921 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4922 x + 2, y + font_ascent + 1, string, 1);
4924 XDrawString(xDisplay, xBoardWindow, coordGC,
4925 x + 2, y + font_ascent + 1, string, 1);
4931 /* Why is this needed on some versions of X? */
4932 void EventProc(widget, unused, event)
4937 if (!XtIsRealized(widget))
4940 switch (event->type) {
4942 if (event->xexpose.count > 0) return; /* no clipping is done */
4943 XDrawPosition(widget, True, NULL);
4951 void DrawPosition(fullRedraw, board)
4952 /*Boolean*/int fullRedraw;
4955 XDrawPosition(boardWidget, fullRedraw, board);
4958 /* Returns 1 if there are "too many" differences between b1 and b2
4959 (i.e. more than 1 move was made) */
4960 static int too_many_diffs(b1, b2)
4966 for (i=0; i<BOARD_HEIGHT; ++i) {
4967 for (j=0; j<BOARD_WIDTH; ++j) {
4968 if (b1[i][j] != b2[i][j]) {
4969 if (++c > 4) /* Castling causes 4 diffs */
4978 /* Matrix describing castling maneuvers */
4979 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4980 static int castling_matrix[4][5] = {
4981 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4982 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4983 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4984 { 7, 7, 4, 5, 6 } /* 0-0, black */
4987 /* Checks whether castling occurred. If it did, *rrow and *rcol
4988 are set to the destination (row,col) of the rook that moved.
4990 Returns 1 if castling occurred, 0 if not.
4992 Note: Only handles a max of 1 castling move, so be sure
4993 to call too_many_diffs() first.
4995 static int check_castle_draw(newb, oldb, rrow, rcol)
5002 /* For each type of castling... */
5003 for (i=0; i<4; ++i) {
5004 r = castling_matrix[i];
5006 /* Check the 4 squares involved in the castling move */
5008 for (j=1; j<=4; ++j) {
5009 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
5016 /* All 4 changed, so it must be a castling move */
5025 static int damage[BOARD_RANKS][BOARD_FILES];
5028 * event handler for redrawing the board
5030 void XDrawPosition(w, repaint, board)
5032 /*Boolean*/int repaint;
5036 static int lastFlipView = 0;
5037 static int lastBoardValid = 0;
5038 static Board lastBoard;
5042 if (board == NULL) {
5043 if (!lastBoardValid) return;
5046 if (!lastBoardValid || lastFlipView != flipView) {
5047 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5048 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5053 * It would be simpler to clear the window with XClearWindow()
5054 * but this causes a very distracting flicker.
5057 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5059 /* If too much changes (begin observing new game, etc.), don't
5061 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5063 /* Special check for castling so we don't flash both the king
5064 and the rook (just flash the king). */
5066 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5067 /* Draw rook with NO flashing. King will be drawn flashing later */
5068 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5069 lastBoard[rrow][rcol] = board[rrow][rcol];
5073 /* First pass -- Draw (newly) empty squares and repair damage.
5074 This prevents you from having a piece show up twice while it
5075 is flashing on its new square */
5076 for (i = 0; i < BOARD_HEIGHT; i++)
5077 for (j = 0; j < BOARD_WIDTH; j++)
5078 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5080 DrawSquare(i, j, board[i][j], 0);
5081 damage[i][j] = False;
5084 /* Second pass -- Draw piece(s) in new position and flash them */
5085 for (i = 0; i < BOARD_HEIGHT; i++)
5086 for (j = 0; j < BOARD_WIDTH; j++)
5087 if (board[i][j] != lastBoard[i][j]) {
5088 DrawSquare(i, j, board[i][j], do_flash);
5092 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5093 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5095 for (i = 0; i < BOARD_HEIGHT; i++)
5096 for (j = 0; j < BOARD_WIDTH; j++) {
5097 DrawSquare(i, j, board[i][j], 0);
5098 damage[i][j] = False;
5102 CopyBoard(lastBoard, board);
5104 lastFlipView = flipView;
5106 /* Draw highlights */
5107 if (pm1X >= 0 && pm1Y >= 0) {
5108 drawHighlight(pm1X, pm1Y, prelineGC);
5110 if (pm2X >= 0 && pm2Y >= 0) {
5111 drawHighlight(pm2X, pm2Y, prelineGC);
5113 if (hi1X >= 0 && hi1Y >= 0) {
5114 drawHighlight(hi1X, hi1Y, highlineGC);
5116 if (hi2X >= 0 && hi2Y >= 0) {
5117 drawHighlight(hi2X, hi2Y, highlineGC);
5120 /* If piece being dragged around board, must redraw that too */
5123 XSync(xDisplay, False);
5128 * event handler for redrawing the board
5130 void DrawPositionProc(w, event, prms, nprms)
5136 XDrawPosition(w, True, NULL);
5141 * event handler for parsing user moves
5143 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5144 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5145 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5146 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5147 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5148 // and at the end FinishMove() to perform the move after optional promotion popups.
5149 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5150 void HandleUserMove(w, event, prms, nprms)
5156 if (w != boardWidget || errorExitStatus != -1) return;
5159 if (event->type == ButtonPress) {
5160 XtPopdown(promotionShell);
5161 XtDestroyWidget(promotionShell);
5162 promotionUp = False;
5170 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5171 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5172 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5175 void AnimateUserMove (Widget w, XEvent * event,
5176 String * params, Cardinal * nParams)
5178 DragPieceMove(event->xmotion.x, event->xmotion.y);
5181 Widget CommentCreate(name, text, mutable, callback, lines)
5183 int /*Boolean*/ mutable;
5184 XtCallbackProc callback;
5188 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5193 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5194 XtGetValues(boardWidget, args, j);
5197 XtSetArg(args[j], XtNresizable, True); j++;
5200 XtCreatePopupShell(name, topLevelShellWidgetClass,
5201 shellWidget, args, j);
5204 XtCreatePopupShell(name, transientShellWidgetClass,
5205 shellWidget, args, j);
5208 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5209 layoutArgs, XtNumber(layoutArgs));
5211 XtCreateManagedWidget("form", formWidgetClass, layout,
5212 formArgs, XtNumber(formArgs));
5216 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5217 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5219 XtSetArg(args[j], XtNstring, text); j++;
5220 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5221 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5222 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5223 XtSetArg(args[j], XtNright, XtChainRight); j++;
5224 XtSetArg(args[j], XtNresizable, True); j++;
5225 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5226 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5227 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5228 XtSetArg(args[j], XtNautoFill, True); j++;
5229 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5231 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5235 XtSetArg(args[j], XtNfromVert, edit); j++;
5236 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5237 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5238 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5239 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5241 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5242 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5245 XtSetArg(args[j], XtNfromVert, edit); j++;
5246 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5247 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5248 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5249 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5250 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5252 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5253 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5256 XtSetArg(args[j], XtNfromVert, edit); j++;
5257 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5258 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5259 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5260 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5261 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5263 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5264 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5267 XtSetArg(args[j], XtNfromVert, edit); j++;
5268 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5269 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5270 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5271 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5273 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5274 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5277 XtSetArg(args[j], XtNfromVert, edit); j++;
5278 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5279 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5280 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5281 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5282 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5284 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5285 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5288 XtRealizeWidget(shell);
5290 if (commentX == -1) {
5293 Dimension pw_height;
5294 Dimension ew_height;
5297 XtSetArg(args[j], XtNheight, &ew_height); j++;
5298 XtGetValues(edit, args, j);
5301 XtSetArg(args[j], XtNheight, &pw_height); j++;
5302 XtGetValues(shell, args, j);
5303 commentH = pw_height + (lines - 1) * ew_height;
5304 commentW = bw_width - 16;
5306 XSync(xDisplay, False);
5308 /* This code seems to tickle an X bug if it is executed too soon
5309 after xboard starts up. The coordinates get transformed as if
5310 the main window was positioned at (0, 0).
5312 XtTranslateCoords(shellWidget,
5313 (bw_width - commentW) / 2, 0 - commentH / 2,
5314 &commentX, &commentY);
5316 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5317 RootWindowOfScreen(XtScreen(shellWidget)),
5318 (bw_width - commentW) / 2, 0 - commentH / 2,
5323 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5326 XtSetArg(args[j], XtNheight, commentH); j++;
5327 XtSetArg(args[j], XtNwidth, commentW); j++;
5328 XtSetArg(args[j], XtNx, commentX); j++;
5329 XtSetArg(args[j], XtNy, commentY); j++;
5330 XtSetValues(shell, args, j);
5331 XtSetKeyboardFocus(shell, edit);
5336 /* Used for analysis window and ICS input window */
5337 Widget MiscCreate(name, text, mutable, callback, lines)
5339 int /*Boolean*/ mutable;
5340 XtCallbackProc callback;
5344 Widget shell, layout, form, edit;
5346 Dimension bw_width, pw_height, ew_height, w, h;
5352 XtSetArg(args[j], XtNresizable, True); j++;
5355 XtCreatePopupShell(name, topLevelShellWidgetClass,
5356 shellWidget, args, j);
5359 XtCreatePopupShell(name, transientShellWidgetClass,
5360 shellWidget, args, j);
5363 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5364 layoutArgs, XtNumber(layoutArgs));
5366 XtCreateManagedWidget("form", formWidgetClass, layout,
5367 formArgs, XtNumber(formArgs));
5371 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5372 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5374 XtSetArg(args[j], XtNstring, text); j++;
5375 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5376 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5377 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5378 XtSetArg(args[j], XtNright, XtChainRight); j++;
5379 XtSetArg(args[j], XtNresizable, True); j++;
5380 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5381 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5382 XtSetArg(args[j], XtNautoFill, True); j++;
5383 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5385 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5387 XtRealizeWidget(shell);
5390 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5391 XtGetValues(boardWidget, args, j);
5394 XtSetArg(args[j], XtNheight, &ew_height); j++;
5395 XtGetValues(edit, args, j);
5398 XtSetArg(args[j], XtNheight, &pw_height); j++;
5399 XtGetValues(shell, args, j);
5400 h = pw_height + (lines - 1) * ew_height;
5403 XSync(xDisplay, False);
5405 /* This code seems to tickle an X bug if it is executed too soon
5406 after xboard starts up. The coordinates get transformed as if
5407 the main window was positioned at (0, 0).
5409 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5411 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5412 RootWindowOfScreen(XtScreen(shellWidget)),
5413 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5417 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5420 XtSetArg(args[j], XtNheight, h); j++;
5421 XtSetArg(args[j], XtNwidth, w); j++;
5422 XtSetArg(args[j], XtNx, x); j++;
5423 XtSetArg(args[j], XtNy, y); j++;
5424 XtSetValues(shell, args, j);
5430 static int savedIndex; /* gross that this is global */
5432 void EditCommentPopUp(index, title, text)
5441 if (text == NULL) text = "";
5443 if (editShell == NULL) {
5445 CommentCreate(title, text, True, EditCommentCallback, 4);
5446 XtRealizeWidget(editShell);
5447 CatchDeleteWindow(editShell, "EditCommentPopDown");
5449 edit = XtNameToWidget(editShell, "*form.text");
5451 XtSetArg(args[j], XtNstring, text); j++;
5452 XtSetValues(edit, args, j);
5454 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5455 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5456 XtSetValues(editShell, args, j);
5459 XtPopup(editShell, XtGrabNone);
5463 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5464 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5468 void EditCommentCallback(w, client_data, call_data)
5470 XtPointer client_data, call_data;
5478 XtSetArg(args[j], XtNlabel, &name); j++;
5479 XtGetValues(w, args, j);
5481 if (strcmp(name, _("ok")) == 0) {
5482 edit = XtNameToWidget(editShell, "*form.text");
5484 XtSetArg(args[j], XtNstring, &val); j++;
5485 XtGetValues(edit, args, j);
5486 ReplaceComment(savedIndex, val);
5487 EditCommentPopDown();
5488 } else if (strcmp(name, _("cancel")) == 0) {
5489 EditCommentPopDown();
5490 } else if (strcmp(name, _("clear")) == 0) {
5491 edit = XtNameToWidget(editShell, "*form.text");
5492 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5493 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5497 void EditCommentPopDown()
5502 if (!editUp) return;
5504 XtSetArg(args[j], XtNx, &commentX); j++;
5505 XtSetArg(args[j], XtNy, &commentY); j++;
5506 XtSetArg(args[j], XtNheight, &commentH); j++;
5507 XtSetArg(args[j], XtNwidth, &commentW); j++;
5508 XtGetValues(editShell, args, j);
5509 XtPopdown(editShell);
5512 XtSetArg(args[j], XtNleftBitmap, None); j++;
5513 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5517 void ICSInputBoxPopUp()
5522 char *title = _("ICS Input");
5525 if (ICSInputShell == NULL) {
5526 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5527 tr = XtParseTranslationTable(ICSInputTranslations);
5528 edit = XtNameToWidget(ICSInputShell, "*form.text");
5529 XtOverrideTranslations(edit, tr);
5530 XtRealizeWidget(ICSInputShell);
5531 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5534 edit = XtNameToWidget(ICSInputShell, "*form.text");
5536 XtSetArg(args[j], XtNstring, ""); j++;
5537 XtSetValues(edit, args, j);
5539 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5540 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5541 XtSetValues(ICSInputShell, args, j);
5544 XtPopup(ICSInputShell, XtGrabNone);
5545 XtSetKeyboardFocus(ICSInputShell, edit);
5547 ICSInputBoxUp = True;
5549 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5550 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5554 void ICSInputSendText()
5561 edit = XtNameToWidget(ICSInputShell, "*form.text");
5563 XtSetArg(args[j], XtNstring, &val); j++;
5564 XtGetValues(edit, args, j);
5565 SendMultiLineToICS(val);
5566 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5567 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5570 void ICSInputBoxPopDown()
5575 if (!ICSInputBoxUp) return;
5577 XtPopdown(ICSInputShell);
5578 ICSInputBoxUp = False;
5580 XtSetArg(args[j], XtNleftBitmap, None); j++;
5581 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5585 void CommentPopUp(title, text)
5592 if (commentShell == NULL) {
5594 CommentCreate(title, text, False, CommentCallback, 4);
5595 XtRealizeWidget(commentShell);
5596 CatchDeleteWindow(commentShell, "CommentPopDown");
5598 edit = XtNameToWidget(commentShell, "*form.text");
5600 XtSetArg(args[j], XtNstring, text); j++;
5601 XtSetValues(edit, args, j);
5603 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5604 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5605 XtSetValues(commentShell, args, j);
5608 XtPopup(commentShell, XtGrabNone);
5609 XSync(xDisplay, False);
5614 void CommentCallback(w, client_data, call_data)
5616 XtPointer client_data, call_data;
5623 XtSetArg(args[j], XtNlabel, &name); j++;
5624 XtGetValues(w, args, j);
5626 if (strcmp(name, _("close")) == 0) {
5628 } else if (strcmp(name, _("edit")) == 0) {
5635 void CommentPopDown()
5640 if (!commentUp) return;
5642 XtSetArg(args[j], XtNx, &commentX); j++;
5643 XtSetArg(args[j], XtNy, &commentY); j++;
5644 XtSetArg(args[j], XtNwidth, &commentW); j++;
5645 XtSetArg(args[j], XtNheight, &commentH); j++;
5646 XtGetValues(commentShell, args, j);
5647 XtPopdown(commentShell);
5648 XSync(xDisplay, False);
5652 void FileNamePopUp(label, def, proc, openMode)
5659 Widget popup, layout, dialog, edit;
5665 fileProc = proc; /* I can't see a way not */
5666 fileOpenMode = openMode; /* to use globals here */
5669 XtSetArg(args[i], XtNresizable, True); i++;
5670 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5671 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5672 fileNameShell = popup =
5673 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5674 shellWidget, args, i);
5677 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5678 layoutArgs, XtNumber(layoutArgs));
5681 XtSetArg(args[i], XtNlabel, label); i++;
5682 XtSetArg(args[i], XtNvalue, def); i++;
5683 XtSetArg(args[i], XtNborderWidth, 0); i++;
5684 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5687 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5688 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5689 (XtPointer) dialog);
5691 XtRealizeWidget(popup);
5692 CatchDeleteWindow(popup, "FileNamePopDown");
5694 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5695 &x, &y, &win_x, &win_y, &mask);
5697 XtSetArg(args[0], XtNx, x - 10);
5698 XtSetArg(args[1], XtNy, y - 30);
5699 XtSetValues(popup, args, 2);
5701 XtPopup(popup, XtGrabExclusive);
5704 edit = XtNameToWidget(dialog, "*value");
5705 XtSetKeyboardFocus(popup, edit);
5708 void FileNamePopDown()
5710 if (!filenameUp) return;
5711 XtPopdown(fileNameShell);
5712 XtDestroyWidget(fileNameShell);
5717 void FileNameCallback(w, client_data, call_data)
5719 XtPointer client_data, call_data;
5724 XtSetArg(args[0], XtNlabel, &name);
5725 XtGetValues(w, args, 1);
5727 if (strcmp(name, _("cancel")) == 0) {
5732 FileNameAction(w, NULL, NULL, NULL);
5735 void FileNameAction(w, event, prms, nprms)
5747 name = XawDialogGetValueString(w = XtParent(w));
5749 if ((name != NULL) && (*name != NULLCHAR)) {
5751 XtPopdown(w = XtParent(XtParent(w)));
5755 p = strrchr(buf, ' ');
5762 fullname = ExpandPathName(buf);
5764 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5767 f = fopen(fullname, fileOpenMode);
5769 DisplayError(_("Failed to open file"), errno);
5771 (void) (*fileProc)(f, index, buf);
5778 XtPopdown(w = XtParent(XtParent(w)));
5784 void PromotionPopUp()
5787 Widget dialog, layout;
5789 Dimension bw_width, pw_width;
5793 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5794 XtGetValues(boardWidget, args, j);
5797 XtSetArg(args[j], XtNresizable, True); j++;
5798 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5800 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5801 shellWidget, args, j);
5803 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5804 layoutArgs, XtNumber(layoutArgs));
5807 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5808 XtSetArg(args[j], XtNborderWidth, 0); j++;
5809 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5812 if(gameInfo.variant != VariantShogi) {
5813 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5814 (XtPointer) dialog);
5815 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5816 (XtPointer) dialog);
5817 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5818 (XtPointer) dialog);
5819 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5820 (XtPointer) dialog);
5821 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5822 gameInfo.variant == VariantGiveaway) {
5823 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5824 (XtPointer) dialog);
5826 if(gameInfo.variant == VariantCapablanca ||
5827 gameInfo.variant == VariantGothic ||
5828 gameInfo.variant == VariantCapaRandom) {
5829 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5830 (XtPointer) dialog);
5831 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5832 (XtPointer) dialog);
5834 } else // [HGM] shogi
5836 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5837 (XtPointer) dialog);
5838 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5839 (XtPointer) dialog);
5841 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5842 (XtPointer) dialog);
5844 XtRealizeWidget(promotionShell);
5845 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5848 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5849 XtGetValues(promotionShell, args, j);
5851 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5852 lineGap + squareSize/3 +
5853 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5854 0 : 6*(squareSize + lineGap)), &x, &y);
5857 XtSetArg(args[j], XtNx, x); j++;
5858 XtSetArg(args[j], XtNy, y); j++;
5859 XtSetValues(promotionShell, args, j);
5861 XtPopup(promotionShell, XtGrabNone);
5866 void PromotionPopDown()
5868 if (!promotionUp) return;
5869 XtPopdown(promotionShell);
5870 XtDestroyWidget(promotionShell);
5871 promotionUp = False;
5874 void PromotionCallback(w, client_data, call_data)
5876 XtPointer client_data, call_data;
5882 XtSetArg(args[0], XtNlabel, &name);
5883 XtGetValues(w, args, 1);
5887 if (fromX == -1) return;
5889 if (strcmp(name, _("cancel")) == 0) {
5893 } else if (strcmp(name, _("Knight")) == 0) {
5895 } else if (strcmp(name, _("Promote")) == 0) {
5897 } else if (strcmp(name, _("Defer")) == 0) {
5900 promoChar = ToLower(name[0]);
5903 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5905 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5906 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5911 void ErrorCallback(w, client_data, call_data)
5913 XtPointer client_data, call_data;
5916 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5918 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5924 if (!errorUp) return;
5926 XtPopdown(errorShell);
5927 XtDestroyWidget(errorShell);
5928 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5931 void ErrorPopUp(title, label, modal)
5932 char *title, *label;
5936 Widget dialog, layout;
5940 Dimension bw_width, pw_width;
5941 Dimension pw_height;
5945 XtSetArg(args[i], XtNresizable, True); i++;
5946 XtSetArg(args[i], XtNtitle, title); i++;
5948 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5949 shellWidget, args, i);
5951 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5952 layoutArgs, XtNumber(layoutArgs));
5955 XtSetArg(args[i], XtNlabel, label); i++;
5956 XtSetArg(args[i], XtNborderWidth, 0); i++;
5957 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5960 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5962 XtRealizeWidget(errorShell);
5963 CatchDeleteWindow(errorShell, "ErrorPopDown");
5966 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5967 XtGetValues(boardWidget, args, i);
5969 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5970 XtSetArg(args[i], XtNheight, &pw_height); i++;
5971 XtGetValues(errorShell, args, i);
5974 /* This code seems to tickle an X bug if it is executed too soon
5975 after xboard starts up. The coordinates get transformed as if
5976 the main window was positioned at (0, 0).
5978 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5979 0 - pw_height + squareSize / 3, &x, &y);
5981 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5982 RootWindowOfScreen(XtScreen(boardWidget)),
5983 (bw_width - pw_width) / 2,
5984 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5988 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5991 XtSetArg(args[i], XtNx, x); i++;
5992 XtSetArg(args[i], XtNy, y); i++;
5993 XtSetValues(errorShell, args, i);
5996 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5999 /* Disable all user input other than deleting the window */
6000 static int frozen = 0;
6004 /* Grab by a widget that doesn't accept input */
6005 XtAddGrab(messageWidget, TRUE, FALSE);
6009 /* Undo a FreezeUI */
6012 if (!frozen) return;
6013 XtRemoveGrab(messageWidget);
6017 char *ModeToWidgetName(mode)
6021 case BeginningOfGame:
6022 if (appData.icsActive)
6023 return "menuMode.ICS Client";
6024 else if (appData.noChessProgram ||
6025 *appData.cmailGameName != NULLCHAR)
6026 return "menuMode.Edit Game";
6028 return "menuMode.Machine Black";
6029 case MachinePlaysBlack:
6030 return "menuMode.Machine Black";
6031 case MachinePlaysWhite:
6032 return "menuMode.Machine White";
6034 return "menuMode.Analysis Mode";
6036 return "menuMode.Analyze File";
6037 case TwoMachinesPlay:
6038 return "menuMode.Two Machines";
6040 return "menuMode.Edit Game";
6041 case PlayFromGameFile:
6042 return "menuFile.Load Game";
6044 return "menuMode.Edit Position";
6046 return "menuMode.Training";
6047 case IcsPlayingWhite:
6048 case IcsPlayingBlack:
6052 return "menuMode.ICS Client";
6059 void ModeHighlight()
6062 static int oldPausing = FALSE;
6063 static GameMode oldmode = (GameMode) -1;
6066 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6068 if (pausing != oldPausing) {
6069 oldPausing = pausing;
6071 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6073 XtSetArg(args[0], XtNleftBitmap, None);
6075 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6078 if (appData.showButtonBar) {
6079 /* Always toggle, don't set. Previous code messes up when
6080 invoked while the button is pressed, as releasing it
6081 toggles the state again. */
6084 XtSetArg(args[0], XtNbackground, &oldbg);
6085 XtSetArg(args[1], XtNforeground, &oldfg);
6086 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6088 XtSetArg(args[0], XtNbackground, oldfg);
6089 XtSetArg(args[1], XtNforeground, oldbg);
6091 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6095 wname = ModeToWidgetName(oldmode);
6096 if (wname != NULL) {
6097 XtSetArg(args[0], XtNleftBitmap, None);
6098 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6100 wname = ModeToWidgetName(gameMode);
6101 if (wname != NULL) {
6102 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6103 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6107 /* Maybe all the enables should be handled here, not just this one */
6108 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6109 gameMode == Training || gameMode == PlayFromGameFile);
6114 * Button/menu procedures
6116 void ResetProc(w, event, prms, nprms)
6125 int LoadGamePopUp(f, gameNumber, title)
6130 cmailMsgLoaded = FALSE;
6131 if (gameNumber == 0) {
6132 int error = GameListBuild(f);
6134 DisplayError(_("Cannot build game list"), error);
6135 } else if (!ListEmpty(&gameList) &&
6136 ((ListGame *) gameList.tailPred)->number > 1) {
6137 GameListPopUp(f, title);
6143 return LoadGame(f, gameNumber, title, FALSE);
6146 void LoadGameProc(w, event, prms, nprms)
6152 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6155 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6158 void LoadNextGameProc(w, event, prms, nprms)
6167 void LoadPrevGameProc(w, event, prms, nprms)
6176 void ReloadGameProc(w, event, prms, nprms)
6185 void LoadNextPositionProc(w, event, prms, nprms)
6194 void LoadPrevPositionProc(w, event, prms, nprms)
6203 void ReloadPositionProc(w, event, prms, nprms)
6212 void LoadPositionProc(w, event, prms, nprms)
6218 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6221 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6224 void SaveGameProc(w, event, prms, nprms)
6230 FileNamePopUp(_("Save game file name?"),
6231 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6235 void SavePositionProc(w, event, prms, nprms)
6241 FileNamePopUp(_("Save position file name?"),
6242 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6246 void ReloadCmailMsgProc(w, event, prms, nprms)
6252 ReloadCmailMsgEvent(FALSE);
6255 void MailMoveProc(w, event, prms, nprms)
6264 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6265 static char *selected_fen_position=NULL;
6268 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6269 Atom *type_return, XtPointer *value_return,
6270 unsigned long *length_return, int *format_return)
6272 char *selection_tmp;
6274 if (!selected_fen_position) return False; /* should never happen */
6275 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
6276 /* note: since no XtSelectionDoneProc was registered, Xt will
6277 * automatically call XtFree on the value returned. So have to
6278 * make a copy of it allocated with XtMalloc */
6279 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6280 strcpy(selection_tmp, selected_fen_position);
6282 *value_return=selection_tmp;
6283 *length_return=strlen(selection_tmp);
6284 *type_return=*target;
6285 *format_return = 8; /* bits per byte */
6287 } else if (*target == XA_TARGETS(xDisplay)) {
6288 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
6289 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
6290 targets_tmp[1] = XA_STRING;
6291 *value_return = targets_tmp;
6292 *type_return = XA_ATOM;
6294 *format_return = 8 * sizeof(Atom);
6295 if (*format_return > 32) {
6296 *length_return *= *format_return / 32;
6297 *format_return = 32;
6305 /* note: when called from menu all parameters are NULL, so no clue what the
6306 * Widget which was clicked on was, or what the click event was
6308 void CopyPositionProc(w, event, prms, nprms)
6315 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
6316 * have a notion of a position that is selected but not copied.
6317 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
6319 if (selected_fen_position) free(selected_fen_position);
6320 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6321 if (!selected_fen_position) return;
6322 XtOwnSelection(menuBarWidget, XA_PRIMARY,
6324 SendPositionSelection,
6325 NULL/* lose_ownership_proc */ ,
6326 NULL/* transfer_done_proc */);
6327 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
6329 SendPositionSelection,
6330 NULL/* lose_ownership_proc */ ,
6331 NULL/* transfer_done_proc */);
6334 /* function called when the data to Paste is ready */
6336 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6337 Atom *type, XtPointer value, unsigned long *len, int *format)
6340 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6341 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6342 EditPositionPasteFEN(fenstr);
6346 /* called when Paste Position button is pressed,
6347 * all parameters will be NULL */
6348 void PastePositionProc(w, event, prms, nprms)
6354 XtGetSelectionValue(menuBarWidget,
6355 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
6356 /* (XtSelectionCallbackProc) */ PastePositionCB,
6357 NULL, /* client_data passed to PastePositionCB */
6359 /* better to use the time field from the event that triggered the
6360 * call to this function, but that isn't trivial to get
6368 SendGameSelection(Widget w, Atom *selection, Atom *target,
6369 Atom *type_return, XtPointer *value_return,
6370 unsigned long *length_return, int *format_return)
6372 char *selection_tmp;
6374 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
6375 FILE* f = fopen(gameCopyFilename, "r");
6378 if (f == NULL) return False;
6382 selection_tmp = XtMalloc(len + 1);
6383 count = fread(selection_tmp, 1, len, f);
6385 XtFree(selection_tmp);
6388 selection_tmp[len] = NULLCHAR;
6389 *value_return = selection_tmp;
6390 *length_return = len;
6391 *type_return = *target;
6392 *format_return = 8; /* bits per byte */
6394 } else if (*target == XA_TARGETS(xDisplay)) {
6395 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
6396 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
6397 targets_tmp[1] = XA_STRING;
6398 *value_return = targets_tmp;
6399 *type_return = XA_ATOM;
6401 *format_return = 8 * sizeof(Atom);
6402 if (*format_return > 32) {
6403 *length_return *= *format_return / 32;
6404 *format_return = 32;
6412 /* note: when called from menu all parameters are NULL, so no clue what the
6413 * Widget which was clicked on was, or what the click event was
6415 void CopyGameProc(w, event, prms, nprms)
6423 ret = SaveGameToFile(gameCopyFilename, FALSE);
6427 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
6428 * have a notion of a game that is selected but not copied.
6429 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
6431 XtOwnSelection(menuBarWidget, XA_PRIMARY,
6434 NULL/* lose_ownership_proc */ ,
6435 NULL/* transfer_done_proc */);
6436 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
6439 NULL/* lose_ownership_proc */ ,
6440 NULL/* transfer_done_proc */);
6443 /* function called when the data to Paste is ready */
6445 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6446 Atom *type, XtPointer value, unsigned long *len, int *format)
6449 if (value == NULL || *len == 0) {
6450 return; /* nothing had been selected to copy */
6452 f = fopen(gamePasteFilename, "w");
6454 DisplayError(_("Can't open temp file"), errno);
6457 fwrite(value, 1, *len, f);
6460 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6463 /* called when Paste Game button is pressed,
6464 * all parameters will be NULL */
6465 void PasteGameProc(w, event, prms, nprms)
6471 XtGetSelectionValue(menuBarWidget,
6472 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
6473 /* (XtSelectionCallbackProc) */ PasteGameCB,
6474 NULL, /* client_data passed to PasteGameCB */
6476 /* better to use the time field from the event that triggered the
6477 * call to this function, but that isn't trivial to get
6487 SaveGameProc(NULL, NULL, NULL, NULL);
6491 void QuitProc(w, event, prms, nprms)
6500 void PauseProc(w, event, prms, nprms)
6510 void MachineBlackProc(w, event, prms, nprms)
6516 MachineBlackEvent();
6519 void MachineWhiteProc(w, event, prms, nprms)
6525 MachineWhiteEvent();
6528 void AnalyzeModeProc(w, event, prms, nprms)
6536 if (!first.analysisSupport) {
6537 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6538 DisplayError(buf, 0);
6541 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6542 if (appData.icsActive) {
6543 if (gameMode != IcsObserving) {
6544 sprintf(buf,_("You are not observing a game"));
6545 DisplayError(buf, 0);
6547 if (appData.icsEngineAnalyze) {
6548 if (appData.debugMode)
6549 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6555 /* if enable, use want disable icsEngineAnalyze */
6556 if (appData.icsEngineAnalyze) {
6561 appData.icsEngineAnalyze = TRUE;
6562 if (appData.debugMode)
6563 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6565 if (!appData.showThinking)
6566 ShowThinkingProc(w,event,prms,nprms);
6571 void AnalyzeFileProc(w, event, prms, nprms)
6577 if (!first.analysisSupport) {
6579 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6580 DisplayError(buf, 0);
6585 if (!appData.showThinking)
6586 ShowThinkingProc(w,event,prms,nprms);
6589 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6590 AnalysisPeriodicEvent(1);
6593 void TwoMachinesProc(w, event, prms, nprms)
6602 void IcsClientProc(w, event, prms, nprms)
6611 void EditGameProc(w, event, prms, nprms)
6620 void EditPositionProc(w, event, prms, nprms)
6626 EditPositionEvent();
6629 void TrainingProc(w, event, prms, nprms)
6638 void EditCommentProc(w, event, prms, nprms)
6645 EditCommentPopDown();
6651 void IcsInputBoxProc(w, event, prms, nprms)
6657 if (ICSInputBoxUp) {
6658 ICSInputBoxPopDown();
6664 void AcceptProc(w, event, prms, nprms)
6673 void DeclineProc(w, event, prms, nprms)
6682 void RematchProc(w, event, prms, nprms)
6691 void CallFlagProc(w, event, prms, nprms)
6700 void DrawProc(w, event, prms, nprms)
6709 void AbortProc(w, event, prms, nprms)
6718 void AdjournProc(w, event, prms, nprms)
6727 void ResignProc(w, event, prms, nprms)
6736 void AdjuWhiteProc(w, event, prms, nprms)
6742 UserAdjudicationEvent(+1);
6745 void AdjuBlackProc(w, event, prms, nprms)
6751 UserAdjudicationEvent(-1);
6754 void AdjuDrawProc(w, event, prms, nprms)
6760 UserAdjudicationEvent(0);
6763 void EnterKeyProc(w, event, prms, nprms)
6769 if (ICSInputBoxUp == True)
6773 void StopObservingProc(w, event, prms, nprms)
6779 StopObservingEvent();
6782 void StopExaminingProc(w, event, prms, nprms)
6788 StopExaminingEvent();
6792 void ForwardProc(w, event, prms, nprms)
6802 void BackwardProc(w, event, prms, nprms)
6811 void ToStartProc(w, event, prms, nprms)
6820 void ToEndProc(w, event, prms, nprms)
6829 void RevertProc(w, event, prms, nprms)
6838 void TruncateGameProc(w, event, prms, nprms)
6844 TruncateGameEvent();
6846 void RetractMoveProc(w, event, prms, nprms)
6855 void MoveNowProc(w, event, prms, nprms)
6865 void AlwaysQueenProc(w, event, prms, nprms)
6873 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6875 if (appData.alwaysPromoteToQueen) {
6876 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6878 XtSetArg(args[0], XtNleftBitmap, None);
6880 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6884 void AnimateDraggingProc(w, event, prms, nprms)
6892 appData.animateDragging = !appData.animateDragging;
6894 if (appData.animateDragging) {
6895 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6898 XtSetArg(args[0], XtNleftBitmap, None);
6900 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6904 void AnimateMovingProc(w, event, prms, nprms)
6912 appData.animate = !appData.animate;
6914 if (appData.animate) {
6915 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6918 XtSetArg(args[0], XtNleftBitmap, None);
6920 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6924 void AutocommProc(w, event, prms, nprms)
6932 appData.autoComment = !appData.autoComment;
6934 if (appData.autoComment) {
6935 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6937 XtSetArg(args[0], XtNleftBitmap, None);
6939 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6944 void AutoflagProc(w, event, prms, nprms)
6952 appData.autoCallFlag = !appData.autoCallFlag;
6954 if (appData.autoCallFlag) {
6955 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6957 XtSetArg(args[0], XtNleftBitmap, None);
6959 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6963 void AutoflipProc(w, event, prms, nprms)
6971 appData.autoFlipView = !appData.autoFlipView;
6973 if (appData.autoFlipView) {
6974 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6976 XtSetArg(args[0], XtNleftBitmap, None);
6978 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6982 void AutobsProc(w, event, prms, nprms)
6990 appData.autoObserve = !appData.autoObserve;
6992 if (appData.autoObserve) {
6993 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6995 XtSetArg(args[0], XtNleftBitmap, None);
6997 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7001 void AutoraiseProc(w, event, prms, nprms)
7009 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7011 if (appData.autoRaiseBoard) {
7012 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7014 XtSetArg(args[0], XtNleftBitmap, None);
7016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7020 void AutosaveProc(w, event, prms, nprms)
7028 appData.autoSaveGames = !appData.autoSaveGames;
7030 if (appData.autoSaveGames) {
7031 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7033 XtSetArg(args[0], XtNleftBitmap, None);
7035 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7039 void BlindfoldProc(w, event, prms, nprms)
7047 appData.blindfold = !appData.blindfold;
7049 if (appData.blindfold) {
7050 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7052 XtSetArg(args[0], XtNleftBitmap, None);
7054 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7057 DrawPosition(True, NULL);
7060 void TestLegalityProc(w, event, prms, nprms)
7068 appData.testLegality = !appData.testLegality;
7070 if (appData.testLegality) {
7071 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7073 XtSetArg(args[0], XtNleftBitmap, None);
7075 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7080 void FlashMovesProc(w, event, prms, nprms)
7088 if (appData.flashCount == 0) {
7089 appData.flashCount = 3;
7091 appData.flashCount = -appData.flashCount;
7094 if (appData.flashCount > 0) {
7095 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7097 XtSetArg(args[0], XtNleftBitmap, None);
7099 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7103 void FlipViewProc(w, event, prms, nprms)
7109 flipView = !flipView;
7110 DrawPosition(True, NULL);
7113 void GetMoveListProc(w, event, prms, nprms)
7121 appData.getMoveList = !appData.getMoveList;
7123 if (appData.getMoveList) {
7124 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7127 XtSetArg(args[0], XtNleftBitmap, None);
7129 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7134 void HighlightDraggingProc(w, event, prms, nprms)
7142 appData.highlightDragging = !appData.highlightDragging;
7144 if (appData.highlightDragging) {
7145 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7147 XtSetArg(args[0], XtNleftBitmap, None);
7149 XtSetValues(XtNameToWidget(menuBarWidget,
7150 "menuOptions.Highlight Dragging"), args, 1);
7154 void HighlightLastMoveProc(w, event, prms, nprms)
7162 appData.highlightLastMove = !appData.highlightLastMove;
7164 if (appData.highlightLastMove) {
7165 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7167 XtSetArg(args[0], XtNleftBitmap, None);
7169 XtSetValues(XtNameToWidget(menuBarWidget,
7170 "menuOptions.Highlight Last Move"), args, 1);
7173 void IcsAlarmProc(w, event, prms, nprms)
7181 appData.icsAlarm = !appData.icsAlarm;
7183 if (appData.icsAlarm) {
7184 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7186 XtSetArg(args[0], XtNleftBitmap, None);
7188 XtSetValues(XtNameToWidget(menuBarWidget,
7189 "menuOptions.ICS Alarm"), args, 1);
7192 void MoveSoundProc(w, event, prms, nprms)
7200 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7202 if (appData.ringBellAfterMoves) {
7203 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7205 XtSetArg(args[0], XtNleftBitmap, None);
7207 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7212 void OldSaveStyleProc(w, event, prms, nprms)
7220 appData.oldSaveStyle = !appData.oldSaveStyle;
7222 if (appData.oldSaveStyle) {
7223 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7225 XtSetArg(args[0], XtNleftBitmap, None);
7227 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7231 void PeriodicUpdatesProc(w, event, prms, nprms)
7239 PeriodicUpdatesEvent(!appData.periodicUpdates);
7241 if (appData.periodicUpdates) {
7242 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7244 XtSetArg(args[0], XtNleftBitmap, None);
7246 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7250 void PonderNextMoveProc(w, event, prms, nprms)
7258 PonderNextMoveEvent(!appData.ponderNextMove);
7260 if (appData.ponderNextMove) {
7261 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7263 XtSetArg(args[0], XtNleftBitmap, None);
7265 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7269 void PopupExitMessageProc(w, event, prms, nprms)
7277 appData.popupExitMessage = !appData.popupExitMessage;
7279 if (appData.popupExitMessage) {
7280 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7282 XtSetArg(args[0], XtNleftBitmap, None);
7284 XtSetValues(XtNameToWidget(menuBarWidget,
7285 "menuOptions.Popup Exit Message"), args, 1);
7288 void PopupMoveErrorsProc(w, event, prms, nprms)
7296 appData.popupMoveErrors = !appData.popupMoveErrors;
7298 if (appData.popupMoveErrors) {
7299 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7301 XtSetArg(args[0], XtNleftBitmap, None);
7303 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7307 void PremoveProc(w, event, prms, nprms)
7315 appData.premove = !appData.premove;
7317 if (appData.premove) {
7318 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7320 XtSetArg(args[0], XtNleftBitmap, None);
7322 XtSetValues(XtNameToWidget(menuBarWidget,
7323 "menuOptions.Premove"), args, 1);
7326 void QuietPlayProc(w, event, prms, nprms)
7334 appData.quietPlay = !appData.quietPlay;
7336 if (appData.quietPlay) {
7337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7339 XtSetArg(args[0], XtNleftBitmap, None);
7341 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7345 void ShowCoordsProc(w, event, prms, nprms)
7353 appData.showCoords = !appData.showCoords;
7355 if (appData.showCoords) {
7356 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7358 XtSetArg(args[0], XtNleftBitmap, None);
7360 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7363 DrawPosition(True, NULL);
7366 void ShowThinkingProc(w, event, prms, nprms)
7372 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7373 ShowThinkingEvent();
7376 void HideThinkingProc(w, event, prms, nprms)
7384 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7385 ShowThinkingEvent();
7387 if (appData.hideThinkingFromHuman) {
7388 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7390 XtSetArg(args[0], XtNleftBitmap, None);
7392 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7396 void InfoProc(w, event, prms, nprms)
7403 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7408 void ManProc(w, event, prms, nprms)
7416 if (nprms && *nprms > 0)
7420 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7424 void HintProc(w, event, prms, nprms)
7433 void BookProc(w, event, prms, nprms)
7442 void AboutProc(w, event, prms, nprms)
7450 char *zippy = " (with Zippy code)";
7454 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7455 programVersion, zippy,
7456 "Copyright 1991 Digital Equipment Corporation",
7457 "Enhancements Copyright 1992-2009 Free Software Foundation",
7458 "Enhancements Copyright 2005 Alessandro Scotti",
7459 PACKAGE, " is free software and carries NO WARRANTY;",
7460 "see the file COPYING for more information.");
7461 ErrorPopUp(_("About XBoard"), buf, FALSE);
7464 void DebugProc(w, event, prms, nprms)
7470 appData.debugMode = !appData.debugMode;
7473 void AboutGameProc(w, event, prms, nprms)
7482 void NothingProc(w, event, prms, nprms)
7491 void Iconify(w, event, prms, nprms)
7500 XtSetArg(args[0], XtNiconic, True);
7501 XtSetValues(shellWidget, args, 1);
7504 void DisplayMessage(message, extMessage)
7505 char *message, *extMessage;
7507 /* display a message in the message widget */
7516 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7521 message = extMessage;
7525 /* need to test if messageWidget already exists, since this function
7526 can also be called during the startup, if for example a Xresource
7527 is not set up correctly */
7530 XtSetArg(arg, XtNlabel, message);
7531 XtSetValues(messageWidget, &arg, 1);
7537 void DisplayTitle(text)
7542 char title[MSG_SIZ];
7545 if (text == NULL) text = "";
7547 if (appData.titleInWindow) {
7549 XtSetArg(args[i], XtNlabel, text); i++;
7550 XtSetValues(titleWidget, args, i);
7553 if (*text != NULLCHAR) {
7555 strcpy(title, text);
7556 } else if (appData.icsActive) {
7557 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7558 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7559 } else if (appData.cmailGameName[0] != NULLCHAR) {
7560 snprintf(icon, sizeof(icon), "%s", "CMail");
7561 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7563 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7564 } else if (gameInfo.variant == VariantGothic) {
7565 strcpy(icon, programName);
7566 strcpy(title, GOTHIC);
7569 } else if (gameInfo.variant == VariantFalcon) {
7570 strcpy(icon, programName);
7571 strcpy(title, FALCON);
7573 } else if (appData.noChessProgram) {
7574 strcpy(icon, programName);
7575 strcpy(title, programName);
7577 strcpy(icon, first.tidy);
7578 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7581 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7582 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7583 XtSetValues(shellWidget, args, i);
7587 void DisplayError(message, error)
7594 if (appData.debugMode || appData.matchMode) {
7595 fprintf(stderr, "%s: %s\n", programName, message);
7598 if (appData.debugMode || appData.matchMode) {
7599 fprintf(stderr, "%s: %s: %s\n",
7600 programName, message, strerror(error));
7602 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7605 ErrorPopUp(_("Error"), message, FALSE);
7609 void DisplayMoveError(message)
7614 DrawPosition(FALSE, NULL);
7615 if (appData.debugMode || appData.matchMode) {
7616 fprintf(stderr, "%s: %s\n", programName, message);
7618 if (appData.popupMoveErrors) {
7619 ErrorPopUp(_("Error"), message, FALSE);
7621 DisplayMessage(message, "");
7626 void DisplayFatalError(message, error, status)
7632 errorExitStatus = status;
7634 fprintf(stderr, "%s: %s\n", programName, message);
7636 fprintf(stderr, "%s: %s: %s\n",
7637 programName, message, strerror(error));
7638 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7641 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7642 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7648 void DisplayInformation(message)
7652 ErrorPopUp(_("Information"), message, TRUE);
7655 void DisplayNote(message)
7659 ErrorPopUp(_("Note"), message, FALSE);
7663 NullXErrorCheck(dpy, error_event)
7665 XErrorEvent *error_event;
7670 void DisplayIcsInteractionTitle(message)
7673 if (oldICSInteractionTitle == NULL) {
7674 /* Magic to find the old window title, adapted from vim */
7675 char *wina = getenv("WINDOWID");
7677 Window win = (Window) atoi(wina);
7678 Window root, parent, *children;
7679 unsigned int nchildren;
7680 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7682 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7683 if (!XQueryTree(xDisplay, win, &root, &parent,
7684 &children, &nchildren)) break;
7685 if (children) XFree((void *)children);
7686 if (parent == root || parent == 0) break;
7689 XSetErrorHandler(oldHandler);
7691 if (oldICSInteractionTitle == NULL) {
7692 oldICSInteractionTitle = "xterm";
7695 printf("\033]0;%s\007", message);
7699 char pendingReplyPrefix[MSG_SIZ];
7700 ProcRef pendingReplyPR;
7702 void AskQuestionProc(w, event, prms, nprms)
7709 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7713 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7716 void AskQuestionPopDown()
7718 if (!askQuestionUp) return;
7719 XtPopdown(askQuestionShell);
7720 XtDestroyWidget(askQuestionShell);
7721 askQuestionUp = False;
7724 void AskQuestionReplyAction(w, event, prms, nprms)
7734 reply = XawDialogGetValueString(w = XtParent(w));
7735 strcpy(buf, pendingReplyPrefix);
7736 if (*buf) strcat(buf, " ");
7739 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7740 AskQuestionPopDown();
7742 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7745 void AskQuestionCallback(w, client_data, call_data)
7747 XtPointer client_data, call_data;
7752 XtSetArg(args[0], XtNlabel, &name);
7753 XtGetValues(w, args, 1);
7755 if (strcmp(name, _("cancel")) == 0) {
7756 AskQuestionPopDown();
7758 AskQuestionReplyAction(w, NULL, NULL, NULL);
7762 void AskQuestion(title, question, replyPrefix, pr)
7763 char *title, *question, *replyPrefix;
7767 Widget popup, layout, dialog, edit;
7773 strcpy(pendingReplyPrefix, replyPrefix);
7774 pendingReplyPR = pr;
7777 XtSetArg(args[i], XtNresizable, True); i++;
7778 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7779 askQuestionShell = popup =
7780 XtCreatePopupShell(title, transientShellWidgetClass,
7781 shellWidget, args, i);
7784 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7785 layoutArgs, XtNumber(layoutArgs));
7788 XtSetArg(args[i], XtNlabel, question); i++;
7789 XtSetArg(args[i], XtNvalue, ""); i++;
7790 XtSetArg(args[i], XtNborderWidth, 0); i++;
7791 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7794 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7795 (XtPointer) dialog);
7796 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7797 (XtPointer) dialog);
7799 XtRealizeWidget(popup);
7800 CatchDeleteWindow(popup, "AskQuestionPopDown");
7802 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7803 &x, &y, &win_x, &win_y, &mask);
7805 XtSetArg(args[0], XtNx, x - 10);
7806 XtSetArg(args[1], XtNy, y - 30);
7807 XtSetValues(popup, args, 2);
7809 XtPopup(popup, XtGrabExclusive);
7810 askQuestionUp = True;
7812 edit = XtNameToWidget(dialog, "*value");
7813 XtSetKeyboardFocus(popup, edit);
7821 if (*name == NULLCHAR) {
7823 } else if (strcmp(name, "$") == 0) {
7824 putc(BELLCHAR, stderr);
7827 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7835 PlaySound(appData.soundMove);
7841 PlaySound(appData.soundIcsWin);
7847 PlaySound(appData.soundIcsLoss);
7853 PlaySound(appData.soundIcsDraw);
7857 PlayIcsUnfinishedSound()
7859 PlaySound(appData.soundIcsUnfinished);
7865 PlaySound(appData.soundIcsAlarm);
7871 system("stty echo");
7877 system("stty -echo");
7881 Colorize(cc, continuation)
7886 int count, outCount, error;
7888 if (textColors[(int)cc].bg > 0) {
7889 if (textColors[(int)cc].fg > 0) {
7890 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7891 textColors[(int)cc].fg, textColors[(int)cc].bg);
7893 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7894 textColors[(int)cc].bg);
7897 if (textColors[(int)cc].fg > 0) {
7898 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7899 textColors[(int)cc].fg);
7901 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7904 count = strlen(buf);
7905 outCount = OutputToProcess(NoProc, buf, count, &error);
7906 if (outCount < count) {
7907 DisplayFatalError(_("Error writing to display"), error, 1);
7910 if (continuation) return;
7913 PlaySound(appData.soundShout);
7916 PlaySound(appData.soundSShout);
7919 PlaySound(appData.soundChannel1);
7922 PlaySound(appData.soundChannel);
7925 PlaySound(appData.soundKibitz);
7928 PlaySound(appData.soundTell);
7930 case ColorChallenge:
7931 PlaySound(appData.soundChallenge);
7934 PlaySound(appData.soundRequest);
7937 PlaySound(appData.soundSeek);
7948 return getpwuid(getuid())->pw_name;
7951 static char *ExpandPathName(path)
7954 static char static_buf[2000];
7955 char *d, *s, buf[2000];
7961 while (*s && isspace(*s))
7970 if (*(s+1) == '/') {
7971 strcpy(d, getpwuid(getuid())->pw_dir);
7976 *strchr(buf, '/') = 0;
7977 pwd = getpwnam(buf);
7980 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7984 strcpy(d, pwd->pw_dir);
7985 strcat(d, strchr(s+1, '/'));
7996 static char host_name[MSG_SIZ];
7998 #if HAVE_GETHOSTNAME
7999 gethostname(host_name, MSG_SIZ);
8001 #else /* not HAVE_GETHOSTNAME */
8002 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8003 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8005 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8007 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8008 #endif /* not HAVE_GETHOSTNAME */
8011 XtIntervalId delayedEventTimerXID = 0;
8012 DelayedEventCallback delayedEventCallback = 0;
8017 delayedEventTimerXID = 0;
8018 delayedEventCallback();
8022 ScheduleDelayedEvent(cb, millisec)
8023 DelayedEventCallback cb; long millisec;
8025 if(delayedEventTimerXID && delayedEventCallback == cb)
8026 // [HGM] alive: replace, rather than add or flush identical event
8027 XtRemoveTimeOut(delayedEventTimerXID);
8028 delayedEventCallback = cb;
8029 delayedEventTimerXID =
8030 XtAppAddTimeOut(appContext, millisec,
8031 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8034 DelayedEventCallback
8037 if (delayedEventTimerXID) {
8038 return delayedEventCallback;
8045 CancelDelayedEvent()
8047 if (delayedEventTimerXID) {
8048 XtRemoveTimeOut(delayedEventTimerXID);
8049 delayedEventTimerXID = 0;
8053 XtIntervalId loadGameTimerXID = 0;
8055 int LoadGameTimerRunning()
8057 return loadGameTimerXID != 0;
8060 int StopLoadGameTimer()
8062 if (loadGameTimerXID != 0) {
8063 XtRemoveTimeOut(loadGameTimerXID);
8064 loadGameTimerXID = 0;
8072 LoadGameTimerCallback(arg, id)
8076 loadGameTimerXID = 0;
8081 StartLoadGameTimer(millisec)
8085 XtAppAddTimeOut(appContext, millisec,
8086 (XtTimerCallbackProc) LoadGameTimerCallback,
8090 XtIntervalId analysisClockXID = 0;
8093 AnalysisClockCallback(arg, id)
8097 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8098 || appData.icsEngineAnalyze) { // [DM]
8099 AnalysisPeriodicEvent(0);
8100 StartAnalysisClock();
8105 StartAnalysisClock()
8108 XtAppAddTimeOut(appContext, 2000,
8109 (XtTimerCallbackProc) AnalysisClockCallback,
8113 XtIntervalId clockTimerXID = 0;
8115 int ClockTimerRunning()
8117 return clockTimerXID != 0;
8120 int StopClockTimer()
8122 if (clockTimerXID != 0) {
8123 XtRemoveTimeOut(clockTimerXID);
8132 ClockTimerCallback(arg, id)
8141 StartClockTimer(millisec)
8145 XtAppAddTimeOut(appContext, millisec,
8146 (XtTimerCallbackProc) ClockTimerCallback,
8151 DisplayTimerLabel(w, color, timer, highlight)
8160 /* check for low time warning */
8161 Pixel foregroundOrWarningColor = timerForegroundPixel;
8164 appData.lowTimeWarning &&
8165 (timer / 1000) < appData.icsAlarmTime)
8166 foregroundOrWarningColor = lowTimeWarningColor;
8168 if (appData.clockMode) {
8169 sprintf(buf, "%s: %s", color, TimeString(timer));
8170 XtSetArg(args[0], XtNlabel, buf);
8172 sprintf(buf, "%s ", color);
8173 XtSetArg(args[0], XtNlabel, buf);
8178 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8179 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8181 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8182 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8185 XtSetValues(w, args, 3);
8189 DisplayWhiteClock(timeRemaining, highlight)
8195 if(appData.noGUI) return;
8196 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8197 if (highlight && iconPixmap == bIconPixmap) {
8198 iconPixmap = wIconPixmap;
8199 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8200 XtSetValues(shellWidget, args, 1);
8205 DisplayBlackClock(timeRemaining, highlight)
8211 if(appData.noGUI) return;
8212 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8213 if (highlight && iconPixmap == wIconPixmap) {
8214 iconPixmap = bIconPixmap;
8215 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8216 XtSetValues(shellWidget, args, 1);
8234 int StartChildProcess(cmdLine, dir, pr)
8241 int to_prog[2], from_prog[2];
8245 if (appData.debugMode) {
8246 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8249 /* We do NOT feed the cmdLine to the shell; we just
8250 parse it into blank-separated arguments in the
8251 most simple-minded way possible.
8254 strcpy(buf, cmdLine);
8259 if (p == NULL) break;
8264 SetUpChildIO(to_prog, from_prog);
8266 if ((pid = fork()) == 0) {
8268 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8269 close(to_prog[1]); // first close the unused pipe ends
8270 close(from_prog[0]);
8271 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8272 dup2(from_prog[1], 1);
8273 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8274 close(from_prog[1]); // and closing again loses one of the pipes!
8275 if(fileno(stderr) >= 2) // better safe than sorry...
8276 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8278 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8283 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8285 execvp(argv[0], argv);
8287 /* If we get here, exec failed */
8292 /* Parent process */
8294 close(from_prog[1]);
8296 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8299 cp->fdFrom = from_prog[0];
8300 cp->fdTo = to_prog[1];
8305 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8306 static RETSIGTYPE AlarmCallBack(int n)
8312 DestroyChildProcess(pr, signalType)
8316 ChildProc *cp = (ChildProc *) pr;
8318 if (cp->kind != CPReal) return;
8320 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8321 signal(SIGALRM, AlarmCallBack);
8323 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8324 kill(cp->pid, SIGKILL); // kill it forcefully
8325 wait((int *) 0); // and wait again
8329 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8331 /* Process is exiting either because of the kill or because of
8332 a quit command sent by the backend; either way, wait for it to die.
8341 InterruptChildProcess(pr)
8344 ChildProc *cp = (ChildProc *) pr;
8346 if (cp->kind != CPReal) return;
8347 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8350 int OpenTelnet(host, port, pr)
8355 char cmdLine[MSG_SIZ];
8357 if (port[0] == NULLCHAR) {
8358 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8360 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8362 return StartChildProcess(cmdLine, "", pr);
8365 int OpenTCP(host, port, pr)
8371 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8372 #else /* !OMIT_SOCKETS */
8374 struct sockaddr_in sa;
8376 unsigned short uport;
8379 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8383 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8384 sa.sin_family = AF_INET;
8385 sa.sin_addr.s_addr = INADDR_ANY;
8386 uport = (unsigned short) 0;
8387 sa.sin_port = htons(uport);
8388 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8392 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8393 if (!(hp = gethostbyname(host))) {
8395 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8396 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8397 hp->h_addrtype = AF_INET;
8399 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8400 hp->h_addr_list[0] = (char *) malloc(4);
8401 hp->h_addr_list[0][0] = b0;
8402 hp->h_addr_list[0][1] = b1;
8403 hp->h_addr_list[0][2] = b2;
8404 hp->h_addr_list[0][3] = b3;
8409 sa.sin_family = hp->h_addrtype;
8410 uport = (unsigned short) atoi(port);
8411 sa.sin_port = htons(uport);
8412 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8414 if (connect(s, (struct sockaddr *) &sa,
8415 sizeof(struct sockaddr_in)) < 0) {
8419 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8426 #endif /* !OMIT_SOCKETS */
8431 int OpenCommPort(name, pr)
8438 fd = open(name, 2, 0);
8439 if (fd < 0) return errno;
8441 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8451 int OpenLoopback(pr)
8457 SetUpChildIO(to, from);
8459 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8462 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8469 int OpenRcmd(host, user, cmd, pr)
8470 char *host, *user, *cmd;
8473 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8477 #define INPUT_SOURCE_BUF_SIZE 8192
8486 char buf[INPUT_SOURCE_BUF_SIZE];
8491 DoInputCallback(closure, source, xid)
8496 InputSource *is = (InputSource *) closure;
8501 if (is->lineByLine) {
8502 count = read(is->fd, is->unused,
8503 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8505 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8508 is->unused += count;
8510 while (p < is->unused) {
8511 q = memchr(p, '\n', is->unused - p);
8512 if (q == NULL) break;
8514 (is->func)(is, is->closure, p, q - p, 0);
8518 while (p < is->unused) {
8523 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8528 (is->func)(is, is->closure, is->buf, count, error);
8532 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8539 ChildProc *cp = (ChildProc *) pr;
8541 is = (InputSource *) calloc(1, sizeof(InputSource));
8542 is->lineByLine = lineByLine;
8546 is->fd = fileno(stdin);
8548 is->kind = cp->kind;
8549 is->fd = cp->fdFrom;
8552 is->unused = is->buf;
8555 is->xid = XtAppAddInput(appContext, is->fd,
8556 (XtPointer) (XtInputReadMask),
8557 (XtInputCallbackProc) DoInputCallback,
8559 is->closure = closure;
8560 return (InputSourceRef) is;
8564 RemoveInputSource(isr)
8567 InputSource *is = (InputSource *) isr;
8569 if (is->xid == 0) return;
8570 XtRemoveInput(is->xid);
8574 int OutputToProcess(pr, message, count, outError)
8580 static int line = 0;
8581 ChildProc *cp = (ChildProc *) pr;
8586 if (appData.noJoin || !appData.useInternalWrap)
8587 outCount = fwrite(message, 1, count, stdout);
8590 int width = get_term_width();
8591 int len = wrap(NULL, message, count, width, &line);
8592 char *msg = malloc(len);
8596 outCount = fwrite(message, 1, count, stdout);
8599 dbgchk = wrap(msg, message, count, width, &line);
8600 if (dbgchk != len && appData.debugMode)
8601 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
8602 outCount = fwrite(msg, 1, dbgchk, stdout);
8608 outCount = write(cp->fdTo, message, count);
8618 /* Output message to process, with "ms" milliseconds of delay
8619 between each character. This is needed when sending the logon
8620 script to ICC, which for some reason doesn't like the
8621 instantaneous send. */
8622 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8629 ChildProc *cp = (ChildProc *) pr;
8634 r = write(cp->fdTo, message++, 1);
8647 /**** Animation code by Hugh Fisher, DCS, ANU.
8649 Known problem: if a window overlapping the board is
8650 moved away while a piece is being animated underneath,
8651 the newly exposed area won't be updated properly.
8652 I can live with this.
8654 Known problem: if you look carefully at the animation
8655 of pieces in mono mode, they are being drawn as solid
8656 shapes without interior detail while moving. Fixing
8657 this would be a major complication for minimal return.
8660 /* Masks for XPM pieces. Black and white pieces can have
8661 different shapes, but in the interest of retaining my
8662 sanity pieces must have the same outline on both light
8663 and dark squares, and all pieces must use the same
8664 background square colors/images. */
8666 static int xpmDone = 0;
8669 CreateAnimMasks (pieceDepth)
8676 unsigned long plane;
8679 /* Need a bitmap just to get a GC with right depth */
8680 buf = XCreatePixmap(xDisplay, xBoardWindow,
8682 values.foreground = 1;
8683 values.background = 0;
8684 /* Don't use XtGetGC, not read only */
8685 maskGC = XCreateGC(xDisplay, buf,
8686 GCForeground | GCBackground, &values);
8687 XFreePixmap(xDisplay, buf);
8689 buf = XCreatePixmap(xDisplay, xBoardWindow,
8690 squareSize, squareSize, pieceDepth);
8691 values.foreground = XBlackPixel(xDisplay, xScreen);
8692 values.background = XWhitePixel(xDisplay, xScreen);
8693 bufGC = XCreateGC(xDisplay, buf,
8694 GCForeground | GCBackground, &values);
8696 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8697 /* Begin with empty mask */
8698 if(!xpmDone) // [HGM] pieces: keep using existing
8699 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8700 squareSize, squareSize, 1);
8701 XSetFunction(xDisplay, maskGC, GXclear);
8702 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8703 0, 0, squareSize, squareSize);
8705 /* Take a copy of the piece */
8710 XSetFunction(xDisplay, bufGC, GXcopy);
8711 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8713 0, 0, squareSize, squareSize, 0, 0);
8715 /* XOR the background (light) over the piece */
8716 XSetFunction(xDisplay, bufGC, GXxor);
8718 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8719 0, 0, squareSize, squareSize, 0, 0);
8721 XSetForeground(xDisplay, bufGC, lightSquareColor);
8722 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8725 /* We now have an inverted piece image with the background
8726 erased. Construct mask by just selecting all the non-zero
8727 pixels - no need to reconstruct the original image. */
8728 XSetFunction(xDisplay, maskGC, GXor);
8730 /* Might be quicker to download an XImage and create bitmap
8731 data from it rather than this N copies per piece, but it
8732 only takes a fraction of a second and there is a much
8733 longer delay for loading the pieces. */
8734 for (n = 0; n < pieceDepth; n ++) {
8735 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8736 0, 0, squareSize, squareSize,
8742 XFreePixmap(xDisplay, buf);
8743 XFreeGC(xDisplay, bufGC);
8744 XFreeGC(xDisplay, maskGC);
8748 InitAnimState (anim, info)
8750 XWindowAttributes * info;
8755 /* Each buffer is square size, same depth as window */
8756 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8757 squareSize, squareSize, info->depth);
8758 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8759 squareSize, squareSize, info->depth);
8761 /* Create a plain GC for blitting */
8762 mask = GCForeground | GCBackground | GCFunction |
8763 GCPlaneMask | GCGraphicsExposures;
8764 values.foreground = XBlackPixel(xDisplay, xScreen);
8765 values.background = XWhitePixel(xDisplay, xScreen);
8766 values.function = GXcopy;
8767 values.plane_mask = AllPlanes;
8768 values.graphics_exposures = False;
8769 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8771 /* Piece will be copied from an existing context at
8772 the start of each new animation/drag. */
8773 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8775 /* Outline will be a read-only copy of an existing */
8776 anim->outlineGC = None;
8782 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8783 XWindowAttributes info;
8785 if (xpmDone && gameInfo.variant == old) return;
8786 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8787 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8789 InitAnimState(&game, &info);
8790 InitAnimState(&player, &info);
8792 /* For XPM pieces, we need bitmaps to use as masks. */
8794 CreateAnimMasks(info.depth);
8800 static Boolean frameWaiting;
8802 static RETSIGTYPE FrameAlarm (sig)
8805 frameWaiting = False;
8806 /* In case System-V style signals. Needed?? */
8807 signal(SIGALRM, FrameAlarm);
8814 struct itimerval delay;
8816 XSync(xDisplay, False);
8819 frameWaiting = True;
8820 signal(SIGALRM, FrameAlarm);
8821 delay.it_interval.tv_sec =
8822 delay.it_value.tv_sec = time / 1000;
8823 delay.it_interval.tv_usec =
8824 delay.it_value.tv_usec = (time % 1000) * 1000;
8825 setitimer(ITIMER_REAL, &delay, NULL);
8826 while (frameWaiting) pause();
8827 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8828 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8829 setitimer(ITIMER_REAL, &delay, NULL);
8839 XSync(xDisplay, False);
8841 usleep(time * 1000);
8846 /* Convert board position to corner of screen rect and color */
8849 ScreenSquare(column, row, pt, color)
8850 int column; int row; XPoint * pt; int * color;
8853 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8854 pt->y = lineGap + row * (squareSize + lineGap);
8856 pt->x = lineGap + column * (squareSize + lineGap);
8857 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8859 *color = SquareColor(row, column);
8862 /* Convert window coords to square */
8865 BoardSquare(x, y, column, row)
8866 int x; int y; int * column; int * row;
8868 *column = EventToSquare(x, BOARD_WIDTH);
8869 if (flipView && *column >= 0)
8870 *column = BOARD_WIDTH - 1 - *column;
8871 *row = EventToSquare(y, BOARD_HEIGHT);
8872 if (!flipView && *row >= 0)
8873 *row = BOARD_HEIGHT - 1 - *row;
8878 #undef Max /* just in case */
8880 #define Max(a, b) ((a) > (b) ? (a) : (b))
8881 #define Min(a, b) ((a) < (b) ? (a) : (b))
8884 SetRect(rect, x, y, width, height)
8885 XRectangle * rect; int x; int y; int width; int height;
8889 rect->width = width;
8890 rect->height = height;
8893 /* Test if two frames overlap. If they do, return
8894 intersection rect within old and location of
8895 that rect within new. */
8898 Intersect(old, new, size, area, pt)
8899 XPoint * old; XPoint * new;
8900 int size; XRectangle * area; XPoint * pt;
8902 if (old->x > new->x + size || new->x > old->x + size ||
8903 old->y > new->y + size || new->y > old->y + size) {
8906 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8907 size - abs(old->x - new->x), size - abs(old->y - new->y));
8908 pt->x = Max(old->x - new->x, 0);
8909 pt->y = Max(old->y - new->y, 0);
8914 /* For two overlapping frames, return the rect(s)
8915 in the old that do not intersect with the new. */
8918 CalcUpdateRects(old, new, size, update, nUpdates)
8919 XPoint * old; XPoint * new; int size;
8920 XRectangle update[]; int * nUpdates;
8924 /* If old = new (shouldn't happen) then nothing to draw */
8925 if (old->x == new->x && old->y == new->y) {
8929 /* Work out what bits overlap. Since we know the rects
8930 are the same size we don't need a full intersect calc. */
8932 /* Top or bottom edge? */
8933 if (new->y > old->y) {
8934 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8936 } else if (old->y > new->y) {
8937 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8938 size, old->y - new->y);
8941 /* Left or right edge - don't overlap any update calculated above. */
8942 if (new->x > old->x) {
8943 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8944 new->x - old->x, size - abs(new->y - old->y));
8946 } else if (old->x > new->x) {
8947 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8948 old->x - new->x, size - abs(new->y - old->y));
8955 /* Generate a series of frame coords from start->mid->finish.
8956 The movement rate doubles until the half way point is
8957 reached, then halves back down to the final destination,
8958 which gives a nice slow in/out effect. The algorithmn
8959 may seem to generate too many intermediates for short
8960 moves, but remember that the purpose is to attract the
8961 viewers attention to the piece about to be moved and
8962 then to where it ends up. Too few frames would be less
8966 Tween(start, mid, finish, factor, frames, nFrames)
8967 XPoint * start; XPoint * mid;
8968 XPoint * finish; int factor;
8969 XPoint frames[]; int * nFrames;
8971 int fraction, n, count;
8975 /* Slow in, stepping 1/16th, then 1/8th, ... */
8977 for (n = 0; n < factor; n++)
8979 for (n = 0; n < factor; n++) {
8980 frames[count].x = start->x + (mid->x - start->x) / fraction;
8981 frames[count].y = start->y + (mid->y - start->y) / fraction;
8983 fraction = fraction / 2;
8987 frames[count] = *mid;
8990 /* Slow out, stepping 1/2, then 1/4, ... */
8992 for (n = 0; n < factor; n++) {
8993 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8994 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8996 fraction = fraction * 2;
9001 /* Draw a piece on the screen without disturbing what's there */
9004 SelectGCMask(piece, clip, outline, mask)
9005 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9009 /* Bitmap for piece being moved. */
9010 if (appData.monoMode) {
9011 *mask = *pieceToSolid(piece);
9012 } else if (useImages) {
9014 *mask = xpmMask[piece];
9016 *mask = ximMaskPm[piece];
9019 *mask = *pieceToSolid(piece);
9022 /* GC for piece being moved. Square color doesn't matter, but
9023 since it gets modified we make a copy of the original. */
9025 if (appData.monoMode)
9030 if (appData.monoMode)
9035 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9037 /* Outline only used in mono mode and is not modified */
9039 *outline = bwPieceGC;
9041 *outline = wbPieceGC;
9045 OverlayPiece(piece, clip, outline, dest)
9046 ChessSquare piece; GC clip; GC outline; Drawable dest;
9051 /* Draw solid rectangle which will be clipped to shape of piece */
9052 XFillRectangle(xDisplay, dest, clip,
9053 0, 0, squareSize, squareSize);
9054 if (appData.monoMode)
9055 /* Also draw outline in contrasting color for black
9056 on black / white on white cases */
9057 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9058 0, 0, squareSize, squareSize, 0, 0, 1);
9060 /* Copy the piece */
9065 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9067 0, 0, squareSize, squareSize,
9072 /* Animate the movement of a single piece */
9075 BeginAnimation(anim, piece, startColor, start)
9083 /* The old buffer is initialised with the start square (empty) */
9084 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9085 anim->prevFrame = *start;
9087 /* The piece will be drawn using its own bitmap as a matte */
9088 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9089 XSetClipMask(xDisplay, anim->pieceGC, mask);
9093 AnimationFrame(anim, frame, piece)
9098 XRectangle updates[4];
9103 /* Save what we are about to draw into the new buffer */
9104 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9105 frame->x, frame->y, squareSize, squareSize,
9108 /* Erase bits of the previous frame */
9109 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9110 /* Where the new frame overlapped the previous,
9111 the contents in newBuf are wrong. */
9112 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9113 overlap.x, overlap.y,
9114 overlap.width, overlap.height,
9116 /* Repaint the areas in the old that don't overlap new */
9117 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9118 for (i = 0; i < count; i++)
9119 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9120 updates[i].x - anim->prevFrame.x,
9121 updates[i].y - anim->prevFrame.y,
9122 updates[i].width, updates[i].height,
9123 updates[i].x, updates[i].y);
9125 /* Easy when no overlap */
9126 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9127 0, 0, squareSize, squareSize,
9128 anim->prevFrame.x, anim->prevFrame.y);
9131 /* Save this frame for next time round */
9132 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9133 0, 0, squareSize, squareSize,
9135 anim->prevFrame = *frame;
9137 /* Draw piece over original screen contents, not current,
9138 and copy entire rect. Wipes out overlapping piece images. */
9139 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9140 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9141 0, 0, squareSize, squareSize,
9142 frame->x, frame->y);
9146 EndAnimation (anim, finish)
9150 XRectangle updates[4];
9155 /* The main code will redraw the final square, so we
9156 only need to erase the bits that don't overlap. */
9157 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9158 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9159 for (i = 0; i < count; i++)
9160 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9161 updates[i].x - anim->prevFrame.x,
9162 updates[i].y - anim->prevFrame.y,
9163 updates[i].width, updates[i].height,
9164 updates[i].x, updates[i].y);
9166 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9167 0, 0, squareSize, squareSize,
9168 anim->prevFrame.x, anim->prevFrame.y);
9173 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9175 ChessSquare piece; int startColor;
9176 XPoint * start; XPoint * finish;
9177 XPoint frames[]; int nFrames;
9181 BeginAnimation(anim, piece, startColor, start);
9182 for (n = 0; n < nFrames; n++) {
9183 AnimationFrame(anim, &(frames[n]), piece);
9184 FrameDelay(appData.animSpeed);
9186 EndAnimation(anim, finish);
9189 /* Main control logic for deciding what to animate and how */
9192 AnimateMove(board, fromX, fromY, toX, toY)
9201 XPoint start, finish, mid;
9202 XPoint frames[kFactor * 2 + 1];
9203 int nFrames, startColor, endColor;
9205 /* Are we animating? */
9206 if (!appData.animate || appData.blindfold)
9209 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9210 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9211 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9213 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9214 piece = board[fromY][fromX];
9215 if (piece >= EmptySquare) return;
9220 hop = (piece == WhiteKnight || piece == BlackKnight);
9223 if (appData.debugMode) {
9224 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9225 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9226 piece, fromX, fromY, toX, toY); }
9228 ScreenSquare(fromX, fromY, &start, &startColor);
9229 ScreenSquare(toX, toY, &finish, &endColor);
9232 /* Knight: make diagonal movement then straight */
9233 if (abs(toY - fromY) < abs(toX - fromX)) {
9234 mid.x = start.x + (finish.x - start.x) / 2;
9238 mid.y = start.y + (finish.y - start.y) / 2;
9241 mid.x = start.x + (finish.x - start.x) / 2;
9242 mid.y = start.y + (finish.y - start.y) / 2;
9245 /* Don't use as many frames for very short moves */
9246 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9247 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9249 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9250 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9252 /* Be sure end square is redrawn */
9253 damage[toY][toX] = True;
9257 DragPieceBegin(x, y)
9260 int boardX, boardY, color;
9263 /* Are we animating? */
9264 if (!appData.animateDragging || appData.blindfold)
9267 /* Figure out which square we start in and the
9268 mouse position relative to top left corner. */
9269 BoardSquare(x, y, &boardX, &boardY);
9270 player.startBoardX = boardX;
9271 player.startBoardY = boardY;
9272 ScreenSquare(boardX, boardY, &corner, &color);
9273 player.startSquare = corner;
9274 player.startColor = color;
9275 /* As soon as we start dragging, the piece will jump slightly to
9276 be centered over the mouse pointer. */
9277 player.mouseDelta.x = squareSize/2;
9278 player.mouseDelta.y = squareSize/2;
9279 /* Initialise animation */
9280 player.dragPiece = PieceForSquare(boardX, boardY);
9282 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9283 player.dragActive = True;
9284 BeginAnimation(&player, player.dragPiece, color, &corner);
9285 /* Mark this square as needing to be redrawn. Note that
9286 we don't remove the piece though, since logically (ie
9287 as seen by opponent) the move hasn't been made yet. */
9288 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9289 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9290 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9291 corner.x, corner.y, squareSize, squareSize,
9292 0, 0); // [HGM] zh: unstack in stead of grab
9293 damage[boardY][boardX] = True;
9295 player.dragActive = False;
9305 /* Are we animating? */
9306 if (!appData.animateDragging || appData.blindfold)
9310 if (! player.dragActive)
9312 /* Move piece, maintaining same relative position
9313 of mouse within square */
9314 corner.x = x - player.mouseDelta.x;
9315 corner.y = y - player.mouseDelta.y;
9316 AnimationFrame(&player, &corner, player.dragPiece);
9318 if (appData.highlightDragging) {
9320 BoardSquare(x, y, &boardX, &boardY);
9321 SetHighlights(fromX, fromY, boardX, boardY);
9330 int boardX, boardY, color;
9333 /* Are we animating? */
9334 if (!appData.animateDragging || appData.blindfold)
9338 if (! player.dragActive)
9340 /* Last frame in sequence is square piece is
9341 placed on, which may not match mouse exactly. */
9342 BoardSquare(x, y, &boardX, &boardY);
9343 ScreenSquare(boardX, boardY, &corner, &color);
9344 EndAnimation(&player, &corner);
9346 /* Be sure end square is redrawn */
9347 damage[boardY][boardX] = True;
9349 /* This prevents weird things happening with fast successive
9350 clicks which on my Sun at least can cause motion events
9351 without corresponding press/release. */
9352 player.dragActive = False;
9355 /* Handle expose event while piece being dragged */
9360 if (!player.dragActive || appData.blindfold)
9363 /* What we're doing: logically, the move hasn't been made yet,
9364 so the piece is still in it's original square. But visually
9365 it's being dragged around the board. So we erase the square
9366 that the piece is on and draw it at the last known drag point. */
9367 BlankSquare(player.startSquare.x, player.startSquare.y,
9368 player.startColor, EmptySquare, xBoardWindow);
9369 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9370 damage[player.startBoardY][player.startBoardX] = TRUE;
9373 #include <sys/ioctl.h>
9374 int get_term_width()
9376 int fd, default_width;
9379 default_width = 79; // this is FICS default anyway...
9381 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9383 if (!ioctl(fd, TIOCGSIZE, &win))
9384 default_width = win.ts_cols;
9385 #elif defined(TIOCGWINSZ)
9387 if (!ioctl(fd, TIOCGWINSZ, &win))
9388 default_width = win.ws_col;
9390 return default_width;
9393 void update_ics_width()
9395 static int old_width = 0;
9396 int new_width = get_term_width();
9398 if (old_width != new_width)
9399 ics_printf("set width %d\n", new_width);
9400 old_width = new_width;
9403 void NotifyFrontendLogin()