2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 RETSIGTYPE TermSizeSigHandler P((int sig));
236 void CreateGCs P((void));
237 void CreateXIMPieces P((void));
238 void CreateXPMPieces P((void));
239 void CreatePieces P((void));
240 void CreatePieceMenus P((void));
241 Widget CreateMenuBar P((Menu *mb));
242 Widget CreateButtonBar P ((MenuItem *mi));
243 char *FindFont P((char *pattern, int targetPxlSize));
244 void PieceMenuPopup P((Widget w, XEvent *event,
245 String *params, Cardinal *num_params));
246 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
248 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
249 u_int wreq, u_int hreq));
250 void CreateGrid P((void));
251 int EventToSquare P((int x, int limit));
252 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
253 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
254 void HandleUserMove P((Widget w, XEvent *event,
255 String *prms, Cardinal *nprms));
256 void AnimateUserMove P((Widget w, XEvent * event,
257 String * params, Cardinal * nParams));
258 void WhiteClock P((Widget w, XEvent *event,
259 String *prms, Cardinal *nprms));
260 void BlackClock P((Widget w, XEvent *event,
261 String *prms, Cardinal *nprms));
262 void DrawPositionProc P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void FileNamePopUp P((char *label, char *def,
273 FileProc proc, char *openMode));
274 void FileNamePopDown P((void));
275 void FileNameCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void FileNameAction P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void AskQuestionReplyAction P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void AskQuestionProc P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionPopDown P((void));
284 void PromotionPopUp P((void));
285 void PromotionPopDown P((void));
286 void PromotionCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void EditCommentPopDown P((void));
289 void EditCommentCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
292 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
294 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
296 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
298 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
300 void LoadPositionProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
304 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
306 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
310 void PastePositionProc P((Widget w, XEvent *event, String *prms,
312 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void SavePositionProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
318 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
320 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
322 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
324 void MachineWhiteProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void AnalyzeModeProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void AnalyzeFileProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
332 void IcsClientProc P((Widget w, XEvent *event, String *prms,
334 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void EditPositionProc P((Widget w, XEvent *event,
336 String *prms, Cardinal *nprms));
337 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void EditCommentProc P((Widget w, XEvent *event,
339 String *prms, Cardinal *nprms));
340 void IcsInputBoxProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void StopObservingProc P((Widget w, XEvent *event, String *prms,
356 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
358 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
365 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
367 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
370 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
372 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
374 void AutocommProc P((Widget w, XEvent *event, String *prms,
376 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AutobsProc P((Widget w, XEvent *event, String *prms,
380 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
385 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
388 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
390 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
392 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
396 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
398 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
400 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
402 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
404 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
408 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
410 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
412 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
414 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
423 void DisplayMove P((int moveNumber));
424 void DisplayTitle P((char *title));
425 void ICSInitScript P((void));
426 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
427 void ErrorPopUp P((char *title, char *text, int modal));
428 void ErrorPopDown P((void));
429 static char *ExpandPathName P((char *path));
430 static void CreateAnimVars P((void));
431 static void DragPieceBegin P((int x, int y));
432 static void DragPieceMove P((int x, int y));
433 static void DragPieceEnd P((int x, int y));
434 static void DrawDragPiece P((void));
435 char *ModeToWidgetName P((GameMode mode));
436 void EngineOutputUpdate( FrontEndProgramStats * stats );
437 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void ShufflePopDown P(());
445 void EnginePopDown P(());
446 void UciPopDown P(());
447 void TimeControlPopDown P(());
448 void NewVariantPopDown P(());
449 void SettingsPopDown P(());
450 void update_ics_width P(());
451 int get_term_width P(());
453 * XBoard depends on Xt R4 or higher
455 int xtVersion = XtSpecificationRelease;
460 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
461 jailSquareColor, highlightSquareColor, premoveHighlightColor;
462 Pixel lowTimeWarningColor;
463 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
464 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
465 wjPieceGC, bjPieceGC, prelineGC, countGC;
466 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
467 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
468 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
469 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
470 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
471 ICSInputShell, fileNameShell, askQuestionShell;
472 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
473 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
474 Font clockFontID, coordFontID, countFontID;
475 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
476 XtAppContext appContext;
478 char *oldICSInteractionTitle;
482 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
484 Position commentX = -1, commentY = -1;
485 Dimension commentW, commentH;
487 int squareSize, smallLayout = 0, tinyLayout = 0,
488 marginW, marginH, // [HGM] for run-time resizing
489 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
490 ICSInputBoxUp = False, askQuestionUp = False,
491 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
492 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
493 Pixel timerForegroundPixel, timerBackgroundPixel;
494 Pixel buttonForegroundPixel, buttonBackgroundPixel;
495 char *chessDir, *programName, *programVersion,
496 *gameCopyFilename, *gamePasteFilename;
500 Pixmap pieceBitmap[2][(int)BlackPawn];
501 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
502 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
503 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
504 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
505 int useImages, useImageSqs;
506 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
507 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
508 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
509 XImage *ximLightSquare, *ximDarkSquare;
512 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
513 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
515 #define White(piece) ((int)(piece) < (int)BlackPawn)
517 /* Variables for doing smooth animation. This whole thing
518 would be much easier if the board was double-buffered,
519 but that would require a fairly major rewrite. */
524 GC blitGC, pieceGC, outlineGC;
525 XPoint startSquare, prevFrame, mouseDelta;
529 int startBoardX, startBoardY;
532 /* There can be two pieces being animated at once: a player
533 can begin dragging a piece before the remote opponent has moved. */
535 static AnimState game, player;
537 /* Bitmaps for use as masks when drawing XPM pieces.
538 Need one for each black and white piece. */
539 static Pixmap xpmMask[BlackKing + 1];
541 /* This magic number is the number of intermediate frames used
542 in each half of the animation. For short moves it's reduced
543 by 1. The total number of frames will be factor * 2 + 1. */
546 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
548 MenuItem fileMenu[] = {
549 {N_("New Game"), ResetProc},
550 {N_("New Shuffle Game ..."), ShuffleMenuProc},
551 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
552 {"----", NothingProc},
553 {N_("Load Game"), LoadGameProc},
554 {N_("Load Next Game"), LoadNextGameProc},
555 {N_("Load Previous Game"), LoadPrevGameProc},
556 {N_("Reload Same Game"), ReloadGameProc},
557 {N_("Save Game"), SaveGameProc},
558 {"----", NothingProc},
559 {N_("Copy Game"), CopyGameProc},
560 {N_("Paste Game"), PasteGameProc},
561 {"----", NothingProc},
562 {N_("Load Position"), LoadPositionProc},
563 {N_("Load Next Position"), LoadNextPositionProc},
564 {N_("Load Previous Position"), LoadPrevPositionProc},
565 {N_("Reload Same Position"), ReloadPositionProc},
566 {N_("Save Position"), SavePositionProc},
567 {"----", NothingProc},
568 {N_("Copy Position"), CopyPositionProc},
569 {N_("Paste Position"), PastePositionProc},
570 {"----", NothingProc},
571 {N_("Mail Move"), MailMoveProc},
572 {N_("Reload CMail Message"), ReloadCmailMsgProc},
573 {"----", NothingProc},
574 {N_("Exit"), QuitProc},
578 MenuItem modeMenu[] = {
579 {N_("Machine White"), MachineWhiteProc},
580 {N_("Machine Black"), MachineBlackProc},
581 {N_("Two Machines"), TwoMachinesProc},
582 {N_("Analysis Mode"), AnalyzeModeProc},
583 {N_("Analyze File"), AnalyzeFileProc },
584 {N_("ICS Client"), IcsClientProc},
585 {N_("Edit Game"), EditGameProc},
586 {N_("Edit Position"), EditPositionProc},
587 {N_("Training"), TrainingProc},
588 {"----", NothingProc},
589 {N_("Show Engine Output"), EngineOutputProc},
590 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
591 {N_("Show Game List"), ShowGameListProc},
592 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
593 {"----", NothingProc},
594 {N_("Edit Tags"), EditTagsProc},
595 {N_("Edit Comment"), EditCommentProc},
596 {N_("ICS Input Box"), IcsInputBoxProc},
597 {N_("Pause"), PauseProc},
601 MenuItem actionMenu[] = {
602 {N_("Accept"), AcceptProc},
603 {N_("Decline"), DeclineProc},
604 {N_("Rematch"), RematchProc},
605 {"----", NothingProc},
606 {N_("Call Flag"), CallFlagProc},
607 {N_("Draw"), DrawProc},
608 {N_("Adjourn"), AdjournProc},
609 {N_("Abort"), AbortProc},
610 {N_("Resign"), ResignProc},
611 {"----", NothingProc},
612 {N_("Stop Observing"), StopObservingProc},
613 {N_("Stop Examining"), StopExaminingProc},
614 {"----", NothingProc},
615 {N_("Adjudicate to White"), AdjuWhiteProc},
616 {N_("Adjudicate to Black"), AdjuBlackProc},
617 {N_("Adjudicate Draw"), AdjuDrawProc},
621 MenuItem stepMenu[] = {
622 {N_("Backward"), BackwardProc},
623 {N_("Forward"), ForwardProc},
624 {N_("Back to Start"), ToStartProc},
625 {N_("Forward to End"), ToEndProc},
626 {N_("Revert"), RevertProc},
627 {N_("Truncate Game"), TruncateGameProc},
628 {"----", NothingProc},
629 {N_("Move Now"), MoveNowProc},
630 {N_("Retract Move"), RetractMoveProc},
634 MenuItem optionsMenu[] = {
635 {N_("Flip View"), FlipViewProc},
636 {"----", NothingProc},
637 {N_("Adjudications ..."), EngineMenuProc},
638 {N_("General Settings ..."), UciMenuProc},
639 {N_("Engine #1 Settings ..."), FirstSettingsProc},
640 {N_("Engine #2 Settings ..."), SecondSettingsProc},
641 {N_("Time Control ..."), TimeControlProc},
642 {"----", NothingProc},
643 {N_("Always Queen"), AlwaysQueenProc},
644 {N_("Animate Dragging"), AnimateDraggingProc},
645 {N_("Animate Moving"), AnimateMovingProc},
646 {N_("Auto Comment"), AutocommProc},
647 {N_("Auto Flag"), AutoflagProc},
648 {N_("Auto Flip View"), AutoflipProc},
649 {N_("Auto Observe"), AutobsProc},
650 {N_("Auto Raise Board"), AutoraiseProc},
651 {N_("Auto Save"), AutosaveProc},
652 {N_("Blindfold"), BlindfoldProc},
653 {N_("Flash Moves"), FlashMovesProc},
654 {N_("Get Move List"), GetMoveListProc},
656 {N_("Highlight Dragging"), HighlightDraggingProc},
658 {N_("Highlight Last Move"), HighlightLastMoveProc},
659 {N_("Move Sound"), MoveSoundProc},
660 {N_("ICS Alarm"), IcsAlarmProc},
661 {N_("Old Save Style"), OldSaveStyleProc},
662 {N_("Periodic Updates"), PeriodicUpdatesProc},
663 {N_("Ponder Next Move"), PonderNextMoveProc},
664 {N_("Popup Exit Message"), PopupExitMessageProc},
665 {N_("Popup Move Errors"), PopupMoveErrorsProc},
666 {N_("Premove"), PremoveProc},
667 {N_("Quiet Play"), QuietPlayProc},
668 {N_("Show Coords"), ShowCoordsProc},
669 {N_("Hide Thinking"), HideThinkingProc},
670 {N_("Test Legality"), TestLegalityProc},
674 MenuItem helpMenu[] = {
675 {N_("Info XBoard"), InfoProc},
676 {N_("Man XBoard"), ManProc},
677 {"----", NothingProc},
678 {N_("Hint"), HintProc},
679 {N_("Book"), BookProc},
680 {"----", NothingProc},
681 {N_("About XBoard"), AboutProc},
686 {N_("File"), fileMenu},
687 {N_("Mode"), modeMenu},
688 {N_("Action"), actionMenu},
689 {N_("Step"), stepMenu},
690 {N_("Options"), optionsMenu},
691 {N_("Help"), helpMenu},
695 #define PAUSE_BUTTON N_("P")
696 MenuItem buttonBar[] = {
699 {PAUSE_BUTTON, PauseProc},
705 #define PIECE_MENU_SIZE 18
706 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
707 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
708 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
709 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
710 N_("Empty square"), N_("Clear board") },
711 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
712 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
713 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
714 N_("Empty square"), N_("Clear board") }
716 /* must be in same order as PieceMenuStrings! */
717 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
718 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
719 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
720 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
721 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
722 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
723 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
724 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
725 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
728 #define DROP_MENU_SIZE 6
729 String dropMenuStrings[DROP_MENU_SIZE] = {
730 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
732 /* must be in same order as PieceMenuStrings! */
733 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
734 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
735 WhiteRook, WhiteQueen
743 DropMenuEnables dmEnables[] = {
761 { XtNborderWidth, 0 },
762 { XtNdefaultDistance, 0 },
766 { XtNborderWidth, 0 },
767 { XtNresizable, (XtArgVal) True },
771 { XtNborderWidth, 0 },
777 { XtNjustify, (XtArgVal) XtJustifyRight },
778 { XtNlabel, (XtArgVal) "..." },
779 { XtNresizable, (XtArgVal) True },
780 { XtNresize, (XtArgVal) False }
783 Arg messageArgs[] = {
784 { XtNjustify, (XtArgVal) XtJustifyLeft },
785 { XtNlabel, (XtArgVal) "..." },
786 { XtNresizable, (XtArgVal) True },
787 { XtNresize, (XtArgVal) False }
791 { XtNborderWidth, 0 },
792 { XtNjustify, (XtArgVal) XtJustifyLeft }
795 XtResource clientResources[] = {
796 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, whitePieceColor), XtRString,
799 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, blackPieceColor), XtRString,
802 { "lightSquareColor", "lightSquareColor", XtRString,
803 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
804 XtRString, LIGHT_SQUARE_COLOR },
805 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
806 XtOffset(AppDataPtr, darkSquareColor), XtRString,
808 { "highlightSquareColor", "highlightSquareColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
810 XtRString, HIGHLIGHT_SQUARE_COLOR },
811 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
812 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
813 XtRString, PREMOVE_HIGHLIGHT_COLOR },
814 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
816 (XtPointer) MOVES_PER_SESSION },
817 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
818 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
819 (XtPointer) TIME_INCREMENT },
820 { "initString", "initString", XtRString, sizeof(String),
821 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
822 { "secondInitString", "secondInitString", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
824 { "firstComputerString", "firstComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
827 { "secondComputerString", "secondComputerString", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
830 { "firstChessProgram", "firstChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
832 XtRString, FIRST_CHESS_PROGRAM },
833 { "secondChessProgram", "secondChessProgram", XtRString,
834 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
835 XtRString, SECOND_CHESS_PROGRAM },
836 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
838 XtRImmediate, (XtPointer) False },
839 { "noChessProgram", "noChessProgram", XtRBoolean,
840 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
841 XtRImmediate, (XtPointer) False },
842 { "firstHost", "firstHost", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
844 { "secondHost", "secondHost", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
846 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
847 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
848 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
849 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
850 { "bitmapDirectory", "bitmapDirectory", XtRString,
851 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
853 { "remoteShell", "remoteShell", XtRString, sizeof(String),
854 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
855 { "remoteUser", "remoteUser", XtRString, sizeof(String),
856 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
857 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
858 XtOffset(AppDataPtr, timeDelay), XtRString,
859 (XtPointer) TIME_DELAY_QUOTE },
860 { "timeControl", "timeControl", XtRString, sizeof(String),
861 XtOffset(AppDataPtr, timeControl), XtRString,
862 (XtPointer) TIME_CONTROL },
863 { "internetChessServerMode", "internetChessServerMode",
864 XtRBoolean, sizeof(Boolean),
865 XtOffset(AppDataPtr, icsActive), XtRImmediate,
867 { "internetChessServerHost", "internetChessServerHost",
868 XtRString, sizeof(String),
869 XtOffset(AppDataPtr, icsHost),
870 XtRString, (XtPointer) ICS_HOST },
871 { "internetChessServerPort", "internetChessServerPort",
872 XtRString, sizeof(String),
873 XtOffset(AppDataPtr, icsPort), XtRString,
874 (XtPointer) ICS_PORT },
875 { "internetChessServerCommPort", "internetChessServerCommPort",
876 XtRString, sizeof(String),
877 XtOffset(AppDataPtr, icsCommPort), XtRString,
879 { "internetChessServerLogonScript", "internetChessServerLogonScript",
880 XtRString, sizeof(String),
881 XtOffset(AppDataPtr, icsLogon), XtRString,
883 { "internetChessServerHelper", "internetChessServerHelper",
884 XtRString, sizeof(String),
885 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
886 { "internetChessServerInputBox", "internetChessServerInputBox",
887 XtRBoolean, sizeof(Boolean),
888 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
890 { "icsAlarm", "icsAlarm",
891 XtRBoolean, sizeof(Boolean),
892 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
894 { "icsAlarmTime", "icsAlarmTime",
896 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
898 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
899 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
901 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
902 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
903 { "gateway", "gateway", XtRString, sizeof(String),
904 XtOffset(AppDataPtr, gateway), XtRString, "" },
905 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
906 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
907 { "loadGameIndex", "loadGameIndex",
909 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
911 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
912 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
913 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
915 XtRImmediate, (XtPointer) True },
916 { "autoSaveGames", "autoSaveGames", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
918 XtRImmediate, (XtPointer) False },
919 { "blindfold", "blindfold", XtRBoolean,
920 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
921 XtRImmediate, (XtPointer) False },
922 { "loadPositionFile", "loadPositionFile", XtRString,
923 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
925 { "loadPositionIndex", "loadPositionIndex",
927 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
929 { "savePositionFile", "savePositionFile", XtRString,
930 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
932 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
933 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
934 { "matchGames", "matchGames", XtRInt, sizeof(int),
935 XtOffset(AppDataPtr, matchGames), XtRImmediate,
937 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, monoMode), XtRImmediate,
940 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, debugMode), XtRImmediate,
943 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
944 XtOffset(AppDataPtr, clockMode), XtRImmediate,
946 { "boardSize", "boardSize", XtRString, sizeof(String),
947 XtOffset(AppDataPtr, boardSize), XtRString, "" },
948 { "searchTime", "searchTime", XtRString, sizeof(String),
949 XtOffset(AppDataPtr, searchTime), XtRString,
951 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
952 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
954 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
955 XtOffset(AppDataPtr, showCoords), XtRImmediate,
957 { "showJail", "showJail", XtRInt, sizeof(int),
958 XtOffset(AppDataPtr, showJail), XtRImmediate,
960 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, showThinking), XtRImmediate,
963 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
966 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
967 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
969 { "clockFont", "clockFont", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
971 { "coordFont", "coordFont", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
973 { "font", "font", XtRString, sizeof(String),
974 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
975 { "ringBellAfterMoves", "ringBellAfterMoves",
976 XtRBoolean, sizeof(Boolean),
977 XtOffset(AppDataPtr, ringBellAfterMoves),
978 XtRImmediate, (XtPointer) False },
979 { "autoCallFlag", "autoCallFlag", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
981 XtRImmediate, (XtPointer) False },
982 { "autoFlipView", "autoFlipView", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
984 XtRImmediate, (XtPointer) True },
985 { "autoObserve", "autoObserve", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
987 XtRImmediate, (XtPointer) False },
988 { "autoComment", "autoComment", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
990 XtRImmediate, (XtPointer) False },
991 { "getMoveList", "getMoveList", XtRBoolean,
992 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
993 XtRImmediate, (XtPointer) True },
995 { "highlightDragging", "highlightDragging", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
997 XtRImmediate, (XtPointer) False },
999 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1001 XtRImmediate, (XtPointer) False },
1002 { "premove", "premove", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1004 XtRImmediate, (XtPointer) True },
1005 { "testLegality", "testLegality", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1007 XtRImmediate, (XtPointer) True },
1008 { "flipView", "flipView", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1010 XtRImmediate, (XtPointer) False },
1011 { "cmail", "cmailGameName", XtRString, sizeof(String),
1012 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1013 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1015 XtRImmediate, (XtPointer) False },
1016 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1018 XtRImmediate, (XtPointer) False },
1019 { "quietPlay", "quietPlay", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1021 XtRImmediate, (XtPointer) False },
1022 { "titleInWindow", "titleInWindow", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1024 XtRImmediate, (XtPointer) False },
1025 { "localLineEditing", "localLineEditing", XtRBoolean,
1026 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1027 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1029 { "zippyTalk", "zippyTalk", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1031 XtRImmediate, (XtPointer) ZIPPY_TALK },
1032 { "zippyPlay", "zippyPlay", XtRBoolean,
1033 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1034 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1035 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1037 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1039 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1041 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1042 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1043 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1045 ZIPPY_WRONG_PASSWORD },
1046 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1047 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1048 { "zippyUseI", "zippyUseI", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1050 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1051 { "zippyBughouse", "zippyBughouse", XtRInt,
1052 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1053 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1054 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1055 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1056 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1057 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1058 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1059 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1060 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1061 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1063 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1064 { "zippyAbort", "zippyAbort", XtRBoolean,
1065 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1066 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1067 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1068 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1069 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1071 (XtPointer) ZIPPY_MAX_GAMES },
1072 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1074 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1075 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1076 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1079 { "flashCount", "flashCount", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1081 (XtPointer) FLASH_COUNT },
1082 { "flashRate", "flashRate", XtRInt, sizeof(int),
1083 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1084 (XtPointer) FLASH_RATE },
1085 { "pixmapDirectory", "pixmapDirectory", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1088 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1089 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1090 (XtPointer) MS_LOGIN_DELAY },
1091 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1092 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1093 XtRImmediate, (XtPointer) False },
1094 { "colorShout", "colorShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorShout),
1096 XtRString, COLOR_SHOUT },
1097 { "colorSShout", "colorSShout", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1099 XtRString, COLOR_SSHOUT },
1100 { "colorChannel1", "colorChannel1", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1102 XtRString, COLOR_CHANNEL1 },
1103 { "colorChannel", "colorChannel", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1105 XtRString, COLOR_CHANNEL },
1106 { "colorKibitz", "colorKibitz", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1108 XtRString, COLOR_KIBITZ },
1109 { "colorTell", "colorTell", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorTell),
1111 XtRString, COLOR_TELL },
1112 { "colorChallenge", "colorChallenge", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1114 XtRString, COLOR_CHALLENGE },
1115 { "colorRequest", "colorRequest", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1117 XtRString, COLOR_REQUEST },
1118 { "colorSeek", "colorSeek", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1120 XtRString, COLOR_SEEK },
1121 { "colorNormal", "colorNormal", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1123 XtRString, COLOR_NORMAL },
1124 { "soundProgram", "soundProgram", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1126 XtRString, "play" },
1127 { "soundShout", "soundShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundShout),
1130 { "soundSShout", "soundSShout", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1133 { "soundChannel1", "soundChannel1", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1136 { "soundChannel", "soundChannel", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1139 { "soundKibitz", "soundKibitz", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1142 { "soundTell", "soundTell", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundTell),
1145 { "soundChallenge", "soundChallenge", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1148 { "soundRequest", "soundRequest", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1151 { "soundSeek", "soundSeek", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1154 { "soundMove", "soundMove", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundMove),
1157 { "soundIcsWin", "soundIcsWin", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1160 { "soundIcsLoss", "soundIcsLoss", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1163 { "soundIcsDraw", "soundIcsDraw", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1166 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1169 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1170 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1172 { "reuseFirst", "reuseFirst", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1174 XtRImmediate, (XtPointer) True },
1175 { "reuseSecond", "reuseSecond", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateDragging", "animateDragging", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateMoving", "animateMoving", XtRBoolean,
1182 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1183 XtRImmediate, (XtPointer) True },
1184 { "animateSpeed", "animateSpeed", XtRInt,
1185 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1186 XtRImmediate, (XtPointer)10 },
1187 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1189 XtRImmediate, (XtPointer) True },
1190 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1191 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1192 XtRImmediate, (XtPointer) False },
1193 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1194 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1195 XtRImmediate, (XtPointer)4 },
1196 { "initialMode", "initialMode", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, initialMode),
1198 XtRImmediate, (XtPointer) "" },
1199 { "variant", "variant", XtRString,
1200 sizeof(String), XtOffset(AppDataPtr, variant),
1201 XtRImmediate, (XtPointer) "normal" },
1202 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1206 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1207 XtRImmediate, (XtPointer)PROTOVER },
1208 { "showButtonBar", "showButtonBar", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1210 XtRImmediate, (XtPointer) True },
1211 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1212 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1213 XtRString, COLOR_LOWTIMEWARNING },
1214 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1215 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1216 XtRImmediate, (XtPointer) False },
1217 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1218 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1219 XtRImmediate, (XtPointer) False },
1220 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1225 XtRImmediate, (XtPointer) False },
1226 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1228 XtRImmediate, (XtPointer) False },
1229 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1230 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1231 XtRImmediate, (XtPointer) True },
1232 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1234 XtRImmediate, (XtPointer) 0},
1235 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1236 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1237 XtRImmediate, (XtPointer) 0},
1238 { "pgnEventHeader", "pgnEventHeader", XtRString,
1239 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1240 XtRImmediate, (XtPointer) "Computer Chess Game" },
1241 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1242 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1243 XtRImmediate, (XtPointer) -1},
1244 { "gameListTags", "gameListTags", XtRString,
1245 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1246 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1248 // [HGM] 4.3.xx options
1249 { "boardWidth", "boardWidth", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1251 XtRImmediate, (XtPointer) -1},
1252 { "boardHeight", "boardHeight", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1254 XtRImmediate, (XtPointer) -1},
1255 { "matchPause", "matchPause", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, matchPause),
1257 XtRImmediate, (XtPointer) 10000},
1258 { "holdingsSize", "holdingsSize", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1260 XtRImmediate, (XtPointer) -1},
1261 { "flipBlack", "flipBlack", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1263 XtRImmediate, (XtPointer) False},
1264 { "allWhite", "allWhite", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1266 XtRImmediate, (XtPointer) False},
1267 { "pieceToCharTable", "pieceToCharTable", XtRString,
1268 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1269 XtRImmediate, (XtPointer) 0},
1270 { "alphaRank", "alphaRank", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1272 XtRImmediate, (XtPointer) False},
1273 { "testClaims", "testClaims", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1275 XtRImmediate, (XtPointer) True},
1276 { "checkMates", "checkMates", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1278 XtRImmediate, (XtPointer) True},
1279 { "materialDraws", "materialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1281 XtRImmediate, (XtPointer) True},
1282 { "trivialDraws", "trivialDraws", XtRBoolean,
1283 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1284 XtRImmediate, (XtPointer) False},
1285 { "ruleMoves", "ruleMoves", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1287 XtRImmediate, (XtPointer) 51},
1288 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1290 XtRImmediate, (XtPointer) 6},
1291 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, engineComments),
1293 XtRImmediate, (XtPointer) 1},
1294 { "userName", "userName", XtRString,
1295 sizeof(int), XtOffset(AppDataPtr, userName),
1296 XtRImmediate, (XtPointer) 0},
1297 { "autoKibitz", "autoKibitz", XtRBoolean,
1298 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1299 XtRImmediate, (XtPointer) False},
1300 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1305 XtRImmediate, (XtPointer) 1},
1306 { "timeOddsMode", "timeOddsMode", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1308 XtRImmediate, (XtPointer) 0},
1309 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1314 XtRImmediate, (XtPointer) 1},
1315 { "firstNPS", "firstNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "secondNPS", "secondNPS", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1320 XtRImmediate, (XtPointer) -1},
1321 { "serverMoves", "serverMoves", XtRString,
1322 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1323 XtRImmediate, (XtPointer) 0},
1324 { "serverPause", "serverPause", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, serverPause),
1326 XtRImmediate, (XtPointer) 0},
1327 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1328 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1329 XtRImmediate, (XtPointer) False},
1330 { "userName", "userName", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, userName),
1332 XtRImmediate, (XtPointer) 0},
1333 { "egtFormats", "egtFormats", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1335 XtRImmediate, (XtPointer) 0},
1336 { "rewindIndex", "rewindIndex", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1338 XtRImmediate, (XtPointer) 0},
1339 { "sameColorGames", "sameColorGames", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1341 XtRImmediate, (XtPointer) 0},
1342 { "smpCores", "smpCores", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, smpCores),
1344 XtRImmediate, (XtPointer) 1},
1345 { "niceEngines", "niceEngines", XtRInt,
1346 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1347 XtRImmediate, (XtPointer) 0},
1348 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1349 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1350 XtRImmediate, (XtPointer) "xboard.debug"},
1351 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1352 sizeof(int), XtOffset(AppDataPtr, engineComments),
1353 XtRImmediate, (XtPointer) 1},
1354 { "noGUI", "noGUI", XtRBoolean,
1355 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1356 XtRImmediate, (XtPointer) 0},
1357 { "firstOptions", "firstOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "secondOptions", "secondOptions", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1362 XtRImmediate, (XtPointer) "" },
1363 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1365 XtRImmediate, (XtPointer) 0 },
1366 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1367 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1368 XtRImmediate, (XtPointer) 0 },
1370 // [HGM] Winboard_x UCI options
1371 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1376 XtRImmediate, (XtPointer) False},
1377 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1382 XtRImmediate, (XtPointer) True},
1383 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1384 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1385 XtRImmediate, (XtPointer) False},
1386 { "defaultHashSize", "defaultHashSize", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1388 XtRImmediate, (XtPointer) 64},
1389 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1390 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1391 XtRImmediate, (XtPointer) 4},
1392 { "polyglotDir", "polyglotDir", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1394 XtRImmediate, (XtPointer) "." },
1395 { "polyglotBook", "polyglotBook", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1397 XtRImmediate, (XtPointer) "" },
1398 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1399 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1400 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1401 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1403 XtRImmediate, (XtPointer) 0},
1404 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1406 XtRImmediate, (XtPointer) 0},
1407 { "keepAlive", "keepAlive", XtRInt,
1408 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1409 XtRImmediate, (XtPointer) 0},
1410 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1411 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1412 XtRImmediate, (XtPointer) False},
1413 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1414 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1415 XtRImmediate, (XtPointer) True},
1418 XrmOptionDescRec shellOptions[] = {
1419 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1420 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1421 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1422 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1423 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1424 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1425 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1426 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1427 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1428 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1429 { "-initString", "initString", XrmoptionSepArg, NULL },
1430 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1431 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1432 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1433 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1434 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1435 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1436 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1437 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1438 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1439 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1440 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1441 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1442 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1443 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1444 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1445 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1446 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1447 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1448 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1449 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1450 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1451 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1452 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1453 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1454 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1455 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1456 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1457 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1458 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1459 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1460 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1461 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1462 { "-internetChessServerMode", "internetChessServerMode",
1463 XrmoptionSepArg, NULL },
1464 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1465 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1466 { "-internetChessServerHost", "internetChessServerHost",
1467 XrmoptionSepArg, NULL },
1468 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1469 { "-internetChessServerPort", "internetChessServerPort",
1470 XrmoptionSepArg, NULL },
1471 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1472 { "-internetChessServerCommPort", "internetChessServerCommPort",
1473 XrmoptionSepArg, NULL },
1474 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1475 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1476 XrmoptionSepArg, NULL },
1477 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1478 { "-internetChessServerHelper", "internetChessServerHelper",
1479 XrmoptionSepArg, NULL },
1480 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1481 { "-internetChessServerInputBox", "internetChessServerInputBox",
1482 XrmoptionSepArg, NULL },
1483 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1484 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1485 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1486 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1487 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1488 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1489 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1490 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1491 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1492 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1493 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1494 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1495 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1496 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1497 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1498 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1499 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1500 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1501 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1502 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1503 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1504 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1505 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1506 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1507 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1508 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1509 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1510 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1511 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1512 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1513 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1514 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1515 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1516 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1517 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1518 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1519 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1520 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1521 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1522 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1523 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1524 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1525 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1526 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1527 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1528 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1529 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1530 { "-size", "boardSize", XrmoptionSepArg, NULL },
1531 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1532 { "-st", "searchTime", XrmoptionSepArg, NULL },
1533 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1534 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1535 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1536 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1537 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1539 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1540 { "-jail", "showJail", XrmoptionNoArg, "1" },
1541 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1542 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1544 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1545 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1546 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1547 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1548 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1549 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1550 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1551 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1552 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1553 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1554 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1555 { "-font", "font", XrmoptionSepArg, NULL },
1556 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1557 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1558 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1559 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1560 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1561 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1562 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1563 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1564 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1565 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1566 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1567 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1568 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1569 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1570 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1571 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1572 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1573 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1574 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1575 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1577 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1578 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1579 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1581 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1582 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1583 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1584 { "-premove", "premove", XrmoptionSepArg, NULL },
1585 { "-pre", "premove", XrmoptionNoArg, "True" },
1586 { "-xpre", "premove", XrmoptionNoArg, "False" },
1587 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1588 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1589 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1590 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1591 { "-flip", "flipView", XrmoptionNoArg, "True" },
1592 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1593 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1594 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1595 XrmoptionSepArg, NULL },
1596 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1597 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1598 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1599 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1600 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1601 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1602 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1603 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1604 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1605 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1606 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1608 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1609 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1610 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1611 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1612 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1613 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1614 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1615 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1616 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1617 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1618 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1619 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1620 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1621 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1622 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1623 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1624 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1625 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1626 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1627 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1628 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1629 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1630 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1631 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1632 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1633 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1634 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1635 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1636 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1637 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1638 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1640 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1641 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1642 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1643 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1644 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1645 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1646 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1647 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1648 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1649 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1650 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1651 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1652 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1653 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1654 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1655 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1656 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1657 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1658 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1659 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1660 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1661 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1662 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1663 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1664 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1665 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1666 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1667 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1668 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1669 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1670 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1671 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1672 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1673 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1674 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1675 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1676 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1677 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1678 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1679 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1680 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1681 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1682 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1683 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1684 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1685 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1686 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1687 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1688 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1689 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1690 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1691 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1692 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1693 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1694 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1695 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1696 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1697 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1698 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1699 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1700 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1701 { "-variant", "variant", XrmoptionSepArg, NULL },
1702 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1703 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1704 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1705 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1706 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1707 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1708 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1709 /* [AS,HR] New features */
1710 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1711 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1712 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1713 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1714 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1715 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1716 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1717 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1718 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1719 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1720 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1721 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1722 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1723 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1724 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1725 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1726 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1727 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1728 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1729 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1730 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1731 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1732 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1733 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1734 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1735 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1737 /* [HGM,HR] User-selectable board size */
1738 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1739 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1740 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1742 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1743 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1744 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1745 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1746 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1747 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1748 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1749 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1750 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1751 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1752 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1753 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1754 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1755 { "-userName", "userName", XrmoptionSepArg, NULL },
1756 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1757 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1758 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1759 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1760 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1761 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1762 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1763 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1764 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1765 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1766 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1767 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1768 { "-userName", "userName", XrmoptionSepArg, NULL },
1769 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1770 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1771 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1772 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1773 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1774 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1775 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1776 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1777 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1778 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1779 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1780 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1781 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1782 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1783 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1784 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1785 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1789 XtActionsRec boardActions[] = {
1790 { "DrawPosition", DrawPositionProc },
1791 { "HandleUserMove", HandleUserMove },
1792 { "AnimateUserMove", AnimateUserMove },
1793 { "FileNameAction", FileNameAction },
1794 { "AskQuestionProc", AskQuestionProc },
1795 { "AskQuestionReplyAction", AskQuestionReplyAction },
1796 { "PieceMenuPopup", PieceMenuPopup },
1797 { "WhiteClock", WhiteClock },
1798 { "BlackClock", BlackClock },
1799 { "Iconify", Iconify },
1800 { "ResetProc", ResetProc },
1801 { "LoadGameProc", LoadGameProc },
1802 { "LoadNextGameProc", LoadNextGameProc },
1803 { "LoadPrevGameProc", LoadPrevGameProc },
1804 { "LoadSelectedProc", LoadSelectedProc },
1805 { "ReloadGameProc", ReloadGameProc },
1806 { "LoadPositionProc", LoadPositionProc },
1807 { "LoadNextPositionProc", LoadNextPositionProc },
1808 { "LoadPrevPositionProc", LoadPrevPositionProc },
1809 { "ReloadPositionProc", ReloadPositionProc },
1810 { "CopyPositionProc", CopyPositionProc },
1811 { "PastePositionProc", PastePositionProc },
1812 { "CopyGameProc", CopyGameProc },
1813 { "PasteGameProc", PasteGameProc },
1814 { "SaveGameProc", SaveGameProc },
1815 { "SavePositionProc", SavePositionProc },
1816 { "MailMoveProc", MailMoveProc },
1817 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1818 { "QuitProc", QuitProc },
1819 { "MachineWhiteProc", MachineWhiteProc },
1820 { "MachineBlackProc", MachineBlackProc },
1821 { "AnalysisModeProc", AnalyzeModeProc },
1822 { "AnalyzeFileProc", AnalyzeFileProc },
1823 { "TwoMachinesProc", TwoMachinesProc },
1824 { "IcsClientProc", IcsClientProc },
1825 { "EditGameProc", EditGameProc },
1826 { "EditPositionProc", EditPositionProc },
1827 { "TrainingProc", EditPositionProc },
1828 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1829 { "ShowGameListProc", ShowGameListProc },
1830 { "ShowMoveListProc", HistoryShowProc},
1831 { "EditTagsProc", EditCommentProc },
1832 { "EditCommentProc", EditCommentProc },
1833 { "IcsAlarmProc", IcsAlarmProc },
1834 { "IcsInputBoxProc", IcsInputBoxProc },
1835 { "PauseProc", PauseProc },
1836 { "AcceptProc", AcceptProc },
1837 { "DeclineProc", DeclineProc },
1838 { "RematchProc", RematchProc },
1839 { "CallFlagProc", CallFlagProc },
1840 { "DrawProc", DrawProc },
1841 { "AdjournProc", AdjournProc },
1842 { "AbortProc", AbortProc },
1843 { "ResignProc", ResignProc },
1844 { "AdjuWhiteProc", AdjuWhiteProc },
1845 { "AdjuBlackProc", AdjuBlackProc },
1846 { "AdjuDrawProc", AdjuDrawProc },
1847 { "EnterKeyProc", EnterKeyProc },
1848 { "StopObservingProc", StopObservingProc },
1849 { "StopExaminingProc", StopExaminingProc },
1850 { "BackwardProc", BackwardProc },
1851 { "ForwardProc", ForwardProc },
1852 { "ToStartProc", ToStartProc },
1853 { "ToEndProc", ToEndProc },
1854 { "RevertProc", RevertProc },
1855 { "TruncateGameProc", TruncateGameProc },
1856 { "MoveNowProc", MoveNowProc },
1857 { "RetractMoveProc", RetractMoveProc },
1858 { "AlwaysQueenProc", AlwaysQueenProc },
1859 { "AnimateDraggingProc", AnimateDraggingProc },
1860 { "AnimateMovingProc", AnimateMovingProc },
1861 { "AutoflagProc", AutoflagProc },
1862 { "AutoflipProc", AutoflipProc },
1863 { "AutobsProc", AutobsProc },
1864 { "AutoraiseProc", AutoraiseProc },
1865 { "AutosaveProc", AutosaveProc },
1866 { "BlindfoldProc", BlindfoldProc },
1867 { "FlashMovesProc", FlashMovesProc },
1868 { "FlipViewProc", FlipViewProc },
1869 { "GetMoveListProc", GetMoveListProc },
1871 { "HighlightDraggingProc", HighlightDraggingProc },
1873 { "HighlightLastMoveProc", HighlightLastMoveProc },
1874 { "IcsAlarmProc", IcsAlarmProc },
1875 { "MoveSoundProc", MoveSoundProc },
1876 { "OldSaveStyleProc", OldSaveStyleProc },
1877 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1878 { "PonderNextMoveProc", PonderNextMoveProc },
1879 { "PopupExitMessageProc", PopupExitMessageProc },
1880 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1881 { "PremoveProc", PremoveProc },
1882 { "QuietPlayProc", QuietPlayProc },
1883 { "ShowCoordsProc", ShowCoordsProc },
1884 { "ShowThinkingProc", ShowThinkingProc },
1885 { "HideThinkingProc", HideThinkingProc },
1886 { "TestLegalityProc", TestLegalityProc },
1887 { "InfoProc", InfoProc },
1888 { "ManProc", ManProc },
1889 { "HintProc", HintProc },
1890 { "BookProc", BookProc },
1891 { "AboutGameProc", AboutGameProc },
1892 { "AboutProc", AboutProc },
1893 { "DebugProc", DebugProc },
1894 { "NothingProc", NothingProc },
1895 { "CommentPopDown", (XtActionProc) CommentPopDown },
1896 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1897 { "TagsPopDown", (XtActionProc) TagsPopDown },
1898 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1899 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1900 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1901 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1902 { "GameListPopDown", (XtActionProc) GameListPopDown },
1903 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1904 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1905 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1906 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1907 { "EnginePopDown", (XtActionProc) EnginePopDown },
1908 { "UciPopDown", (XtActionProc) UciPopDown },
1909 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1910 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1911 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1914 char globalTranslations[] =
1915 ":<Key>R: ResignProc() \n \
1916 :<Key>r: ResetProc() \n \
1917 :<Key>g: LoadGameProc() \n \
1918 :<Key>N: LoadNextGameProc() \n \
1919 :<Key>P: LoadPrevGameProc() \n \
1920 :<Key>Q: QuitProc() \n \
1921 :<Key>F: ToEndProc() \n \
1922 :<Key>f: ForwardProc() \n \
1923 :<Key>B: ToStartProc() \n \
1924 :<Key>b: BackwardProc() \n \
1925 :<Key>p: PauseProc() \n \
1926 :<Key>d: DrawProc() \n \
1927 :<Key>t: CallFlagProc() \n \
1928 :<Key>i: Iconify() \n \
1929 :<Key>c: Iconify() \n \
1930 :<Key>v: FlipViewProc() \n \
1931 <KeyDown>Control_L: BackwardProc() \n \
1932 <KeyUp>Control_L: ForwardProc() \n \
1933 <KeyDown>Control_R: BackwardProc() \n \
1934 <KeyUp>Control_R: ForwardProc() \n \
1935 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1936 \"Send to chess program:\",,1) \n \
1937 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1938 \"Send to second chess program:\",,2) \n";
1940 char boardTranslations[] =
1941 "<Btn1Down>: HandleUserMove() \n \
1942 <Btn1Up>: HandleUserMove() \n \
1943 <Btn1Motion>: AnimateUserMove() \n \
1944 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1945 PieceMenuPopup(menuB) \n \
1946 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1947 PieceMenuPopup(menuW) \n \
1948 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1949 PieceMenuPopup(menuW) \n \
1950 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1951 PieceMenuPopup(menuB) \n";
1953 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1954 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1956 char ICSInputTranslations[] =
1957 "<Key>Return: EnterKeyProc() \n";
1959 String xboardResources[] = {
1960 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1961 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1962 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1967 /* Max possible square size */
1968 #define MAXSQSIZE 256
1970 static int xpm_avail[MAXSQSIZE];
1972 #ifdef HAVE_DIR_STRUCT
1974 /* Extract piece size from filename */
1976 xpm_getsize(name, len, ext)
1987 if ((p=strchr(name, '.')) == NULL ||
1988 StrCaseCmp(p+1, ext) != 0)
1994 while (*p && isdigit(*p))
2001 /* Setup xpm_avail */
2003 xpm_getavail(dirname, ext)
2011 for (i=0; i<MAXSQSIZE; ++i)
2014 if (appData.debugMode)
2015 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2017 dir = opendir(dirname);
2020 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2021 programName, dirname);
2025 while ((ent=readdir(dir)) != NULL) {
2026 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2027 if (i > 0 && i < MAXSQSIZE)
2037 xpm_print_avail(fp, ext)
2043 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2044 for (i=1; i<MAXSQSIZE; ++i) {
2050 /* Return XPM piecesize closest to size */
2052 xpm_closest_to(dirname, size, ext)
2058 int sm_diff = MAXSQSIZE;
2062 xpm_getavail(dirname, ext);
2064 if (appData.debugMode)
2065 xpm_print_avail(stderr, ext);
2067 for (i=1; i<MAXSQSIZE; ++i) {
2070 diff = (diff<0) ? -diff : diff;
2071 if (diff < sm_diff) {
2079 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2085 #else /* !HAVE_DIR_STRUCT */
2086 /* If we are on a system without a DIR struct, we can't
2087 read the directory, so we can't collect a list of
2088 filenames, etc., so we can't do any size-fitting. */
2090 xpm_closest_to(dirname, size, ext)
2095 fprintf(stderr, _("\
2096 Warning: No DIR structure found on this system --\n\
2097 Unable to autosize for XPM/XIM pieces.\n\
2098 Please report this error to frankm@hiwaay.net.\n\
2099 Include system type & operating system in message.\n"));
2102 #endif /* HAVE_DIR_STRUCT */
2104 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2105 "magenta", "cyan", "white" };
2109 TextColors textColors[(int)NColorClasses];
2111 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2113 parse_color(str, which)
2117 char *p, buf[100], *d;
2120 if (strlen(str) > 99) /* watch bounds on buf */
2125 for (i=0; i<which; ++i) {
2132 /* Could be looking at something like:
2134 .. in which case we want to stop on a comma also */
2135 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2139 return -1; /* Use default for empty field */
2142 if (which == 2 || isdigit(*p))
2145 while (*p && isalpha(*p))
2150 for (i=0; i<8; ++i) {
2151 if (!StrCaseCmp(buf, cnames[i]))
2152 return which? (i+40) : (i+30);
2154 if (!StrCaseCmp(buf, "default")) return -1;
2156 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2161 parse_cpair(cc, str)
2165 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2166 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2171 /* bg and attr are optional */
2172 textColors[(int)cc].bg = parse_color(str, 1);
2173 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2174 textColors[(int)cc].attr = 0;
2180 /* Arrange to catch delete-window events */
2181 Atom wm_delete_window;
2183 CatchDeleteWindow(Widget w, String procname)
2186 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2187 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2188 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2195 XtSetArg(args[0], XtNiconic, False);
2196 XtSetValues(shellWidget, args, 1);
2198 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2202 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2204 #define BoardSize int
2205 void InitDrawingSizes(BoardSize boardSize, int flags)
2206 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2207 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2209 XtGeometryResult gres;
2212 if(!formWidget) return;
2215 * Enable shell resizing.
2217 shellArgs[0].value = (XtArgVal) &w;
2218 shellArgs[1].value = (XtArgVal) &h;
2219 XtGetValues(shellWidget, shellArgs, 2);
2221 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2222 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2223 XtSetValues(shellWidget, &shellArgs[2], 4);
2225 XtSetArg(args[0], XtNdefaultDistance, &sep);
2226 XtGetValues(formWidget, args, 1);
2228 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2229 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2232 XtSetArg(args[0], XtNwidth, boardWidth);
2233 XtSetArg(args[1], XtNheight, boardHeight);
2234 XtSetValues(boardWidget, args, 2);
2236 timerWidth = (boardWidth - sep) / 2;
2237 XtSetArg(args[0], XtNwidth, timerWidth);
2238 XtSetValues(whiteTimerWidget, args, 1);
2239 XtSetValues(blackTimerWidget, args, 1);
2241 XawFormDoLayout(formWidget, False);
2243 if (appData.titleInWindow) {
2245 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2246 XtSetArg(args[i], XtNheight, &h); i++;
2247 XtGetValues(titleWidget, args, i);
2249 w = boardWidth - 2*bor;
2251 XtSetArg(args[0], XtNwidth, &w);
2252 XtGetValues(menuBarWidget, args, 1);
2253 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2256 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2257 if (gres != XtGeometryYes && appData.debugMode) {
2259 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2260 programName, gres, w, h, wr, hr);
2264 XawFormDoLayout(formWidget, True);
2267 * Inhibit shell resizing.
2269 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2270 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2271 shellArgs[4].value = shellArgs[2].value = w;
2272 shellArgs[5].value = shellArgs[3].value = h;
2273 XtSetValues(shellWidget, &shellArgs[0], 6);
2275 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2278 for(i=0; i<4; i++) {
2280 for(p=0; p<=(int)WhiteKing; p++)
2281 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2282 if(gameInfo.variant == VariantShogi) {
2283 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2284 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2285 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2286 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2287 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2290 if(gameInfo.variant == VariantGothic) {
2291 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2295 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2296 for(p=0; p<=(int)WhiteKing; p++)
2297 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2298 if(gameInfo.variant == VariantShogi) {
2299 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2300 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2301 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2302 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2303 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2306 if(gameInfo.variant == VariantGothic) {
2307 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2313 for(i=0; i<2; i++) {
2315 for(p=0; p<=(int)WhiteKing; p++)
2316 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2317 if(gameInfo.variant == VariantShogi) {
2318 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2319 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2320 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2321 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2322 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2325 if(gameInfo.variant == VariantGothic) {
2326 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2337 void EscapeExpand(char *p, char *q)
2338 { // [HGM] initstring: routine to shape up string arguments
2339 while(*p++ = *q++) if(p[-1] == '\\')
2341 case 'n': p[-1] = '\n'; break;
2342 case 'r': p[-1] = '\r'; break;
2343 case 't': p[-1] = '\t'; break;
2344 case '\\': p[-1] = '\\'; break;
2345 case 0: *p = 0; return;
2346 default: p[-1] = q[-1]; break;
2355 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2356 XSetWindowAttributes window_attributes;
2358 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2359 XrmValue vFrom, vTo;
2360 XtGeometryResult gres;
2363 int forceMono = False;
2366 // [HGM] before anything else, expand any indirection files amongst options
2367 char *argvCopy[1000]; // 1000 seems enough
2368 char newArgs[10000]; // holds actual characters
2371 srandom(time(0)); // [HGM] book: make random truly random
2374 for(i=0; i<argc; i++) {
2375 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2376 //fprintf(stderr, "arg %s\n", argv[i]);
2377 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2379 FILE *f = fopen(argv[i]+1, "rb");
2380 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2381 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2382 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2384 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2385 newArgs[k++] = 0; // terminate current arg
2386 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2387 argvCopy[j++] = newArgs + k; // get ready for next
2389 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2403 setbuf(stdout, NULL);
2404 setbuf(stderr, NULL);
2407 programName = strrchr(argv[0], '/');
2408 if (programName == NULL)
2409 programName = argv[0];
2414 XtSetLanguageProc(NULL, NULL, NULL);
2415 bindtextdomain(PACKAGE, LOCALEDIR);
2416 textdomain(PACKAGE);
2420 XtAppInitialize(&appContext, "XBoard", shellOptions,
2421 XtNumber(shellOptions),
2422 &argc, argv, xboardResources, NULL, 0);
2424 { /* left over command line arguments, print out help and exit.
2425 * Use two columns to print help
2427 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2428 programName, argv[1]);
2430 fprintf(stderr, "Recognized options:\n");
2431 for(i = 0; i < XtNumber(shellOptions); i++)
2433 /* print first column */
2434 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2435 (shellOptions[i].argKind == XrmoptionSepArg
2437 /* print second column and end line */
2438 if (++i < XtNumber(shellOptions))
2440 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2441 shellOptions[i].option,
2442 (shellOptions[i].argKind == XrmoptionSepArg
2447 fprintf(stderr, "\n");
2454 if (p == NULL) p = "/tmp";
2455 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2456 gameCopyFilename = (char*) malloc(i);
2457 gamePasteFilename = (char*) malloc(i);
2458 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2459 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2461 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2462 clientResources, XtNumber(clientResources),
2465 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2466 static char buf[MSG_SIZ];
2467 EscapeExpand(buf, appData.initString);
2468 appData.initString = strdup(buf);
2469 EscapeExpand(buf, appData.secondInitString);
2470 appData.secondInitString = strdup(buf);
2471 EscapeExpand(buf, appData.firstComputerString);
2472 appData.firstComputerString = strdup(buf);
2473 EscapeExpand(buf, appData.secondComputerString);
2474 appData.secondComputerString = strdup(buf);
2477 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2480 if (chdir(chessDir) != 0) {
2481 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2487 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2488 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2489 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2490 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2493 setbuf(debugFP, NULL);
2496 /* [HGM,HR] make sure board size is acceptable */
2497 if(appData.NrFiles > BOARD_SIZE ||
2498 appData.NrRanks > BOARD_SIZE )
2499 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2502 /* This feature does not work; animation needs a rewrite */
2503 appData.highlightDragging = FALSE;
2507 xDisplay = XtDisplay(shellWidget);
2508 xScreen = DefaultScreen(xDisplay);
2509 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2511 gameInfo.variant = StringToVariant(appData.variant);
2512 InitPosition(FALSE);
2515 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2517 if (isdigit(appData.boardSize[0])) {
2518 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2519 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2520 &fontPxlSize, &smallLayout, &tinyLayout);
2522 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2523 programName, appData.boardSize);
2527 /* Find some defaults; use the nearest known size */
2528 SizeDefaults *szd, *nearest;
2529 int distance = 99999;
2530 nearest = szd = sizeDefaults;
2531 while (szd->name != NULL) {
2532 if (abs(szd->squareSize - squareSize) < distance) {
2534 distance = abs(szd->squareSize - squareSize);
2535 if (distance == 0) break;
2539 if (i < 2) lineGap = nearest->lineGap;
2540 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2541 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2542 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2543 if (i < 6) smallLayout = nearest->smallLayout;
2544 if (i < 7) tinyLayout = nearest->tinyLayout;
2547 SizeDefaults *szd = sizeDefaults;
2548 if (*appData.boardSize == NULLCHAR) {
2549 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2550 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2553 if (szd->name == NULL) szd--;
2555 while (szd->name != NULL &&
2556 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2557 if (szd->name == NULL) {
2558 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2559 programName, appData.boardSize);
2563 squareSize = szd->squareSize;
2564 lineGap = szd->lineGap;
2565 clockFontPxlSize = szd->clockFontPxlSize;
2566 coordFontPxlSize = szd->coordFontPxlSize;
2567 fontPxlSize = szd->fontPxlSize;
2568 smallLayout = szd->smallLayout;
2569 tinyLayout = szd->tinyLayout;
2572 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2573 if (strlen(appData.pixmapDirectory) > 0) {
2574 p = ExpandPathName(appData.pixmapDirectory);
2576 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2577 appData.pixmapDirectory);
2580 if (appData.debugMode) {
2581 fprintf(stderr, _("\
2582 XBoard square size (hint): %d\n\
2583 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2585 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2586 if (appData.debugMode) {
2587 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2591 /* [HR] height treated separately (hacked) */
2592 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2593 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2594 if (appData.showJail == 1) {
2595 /* Jail on top and bottom */
2596 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2597 XtSetArg(boardArgs[2], XtNheight,
2598 boardHeight + 2*(lineGap + squareSize));
2599 } else if (appData.showJail == 2) {
2601 XtSetArg(boardArgs[1], XtNwidth,
2602 boardWidth + 2*(lineGap + squareSize));
2603 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2606 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2607 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2611 * Determine what fonts to use.
2613 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2614 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2615 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2616 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2617 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2618 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2619 appData.font = FindFont(appData.font, fontPxlSize);
2620 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2621 countFontStruct = XQueryFont(xDisplay, countFontID);
2622 // appData.font = FindFont(appData.font, fontPxlSize);
2624 xdb = XtDatabase(xDisplay);
2625 XrmPutStringResource(&xdb, "*font", appData.font);
2628 * Detect if there are not enough colors available and adapt.
2630 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2631 appData.monoMode = True;
2634 if (!appData.monoMode) {
2635 vFrom.addr = (caddr_t) appData.lightSquareColor;
2636 vFrom.size = strlen(appData.lightSquareColor);
2637 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2638 if (vTo.addr == NULL) {
2639 appData.monoMode = True;
2642 lightSquareColor = *(Pixel *) vTo.addr;
2645 if (!appData.monoMode) {
2646 vFrom.addr = (caddr_t) appData.darkSquareColor;
2647 vFrom.size = strlen(appData.darkSquareColor);
2648 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2649 if (vTo.addr == NULL) {
2650 appData.monoMode = True;
2653 darkSquareColor = *(Pixel *) vTo.addr;
2656 if (!appData.monoMode) {
2657 vFrom.addr = (caddr_t) appData.whitePieceColor;
2658 vFrom.size = strlen(appData.whitePieceColor);
2659 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2660 if (vTo.addr == NULL) {
2661 appData.monoMode = True;
2664 whitePieceColor = *(Pixel *) vTo.addr;
2667 if (!appData.monoMode) {
2668 vFrom.addr = (caddr_t) appData.blackPieceColor;
2669 vFrom.size = strlen(appData.blackPieceColor);
2670 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2671 if (vTo.addr == NULL) {
2672 appData.monoMode = True;
2675 blackPieceColor = *(Pixel *) vTo.addr;
2679 if (!appData.monoMode) {
2680 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2681 vFrom.size = strlen(appData.highlightSquareColor);
2682 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2683 if (vTo.addr == NULL) {
2684 appData.monoMode = True;
2687 highlightSquareColor = *(Pixel *) vTo.addr;
2691 if (!appData.monoMode) {
2692 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2693 vFrom.size = strlen(appData.premoveHighlightColor);
2694 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2695 if (vTo.addr == NULL) {
2696 appData.monoMode = True;
2699 premoveHighlightColor = *(Pixel *) vTo.addr;
2704 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2707 if (appData.bitmapDirectory == NULL ||
2708 appData.bitmapDirectory[0] == NULLCHAR)
2709 appData.bitmapDirectory = DEF_BITMAP_DIR;
2712 if (appData.lowTimeWarning && !appData.monoMode) {
2713 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2714 vFrom.size = strlen(appData.lowTimeWarningColor);
2715 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2716 if (vTo.addr == NULL)
2717 appData.monoMode = True;
2719 lowTimeWarningColor = *(Pixel *) vTo.addr;
2722 if (appData.monoMode && appData.debugMode) {
2723 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2724 (unsigned long) XWhitePixel(xDisplay, xScreen),
2725 (unsigned long) XBlackPixel(xDisplay, xScreen));
2728 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2729 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2730 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2731 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2732 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2733 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2734 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2735 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2736 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2737 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2739 if (appData.colorize) {
2741 _("%s: can't parse color names; disabling colorization\n"),
2744 appData.colorize = FALSE;
2746 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2747 textColors[ColorNone].attr = 0;
2749 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2755 layoutName = "tinyLayout";
2756 } else if (smallLayout) {
2757 layoutName = "smallLayout";
2759 layoutName = "normalLayout";
2761 /* Outer layoutWidget is there only to provide a name for use in
2762 resources that depend on the layout style */
2764 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2765 layoutArgs, XtNumber(layoutArgs));
2767 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2768 formArgs, XtNumber(formArgs));
2769 XtSetArg(args[0], XtNdefaultDistance, &sep);
2770 XtGetValues(formWidget, args, 1);
2773 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2774 XtSetArg(args[0], XtNtop, XtChainTop);
2775 XtSetArg(args[1], XtNbottom, XtChainTop);
2776 XtSetValues(menuBarWidget, args, 2);
2778 widgetList[j++] = whiteTimerWidget =
2779 XtCreateWidget("whiteTime", labelWidgetClass,
2780 formWidget, timerArgs, XtNumber(timerArgs));
2781 XtSetArg(args[0], XtNfont, clockFontStruct);
2782 XtSetArg(args[1], XtNtop, XtChainTop);
2783 XtSetArg(args[2], XtNbottom, XtChainTop);
2784 XtSetValues(whiteTimerWidget, args, 3);
2786 widgetList[j++] = blackTimerWidget =
2787 XtCreateWidget("blackTime", labelWidgetClass,
2788 formWidget, timerArgs, XtNumber(timerArgs));
2789 XtSetArg(args[0], XtNfont, clockFontStruct);
2790 XtSetArg(args[1], XtNtop, XtChainTop);
2791 XtSetArg(args[2], XtNbottom, XtChainTop);
2792 XtSetValues(blackTimerWidget, args, 3);
2794 if (appData.titleInWindow) {
2795 widgetList[j++] = titleWidget =
2796 XtCreateWidget("title", labelWidgetClass, formWidget,
2797 titleArgs, XtNumber(titleArgs));
2798 XtSetArg(args[0], XtNtop, XtChainTop);
2799 XtSetArg(args[1], XtNbottom, XtChainTop);
2800 XtSetValues(titleWidget, args, 2);
2803 if (appData.showButtonBar) {
2804 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2805 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2806 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2807 XtSetArg(args[2], XtNtop, XtChainTop);
2808 XtSetArg(args[3], XtNbottom, XtChainTop);
2809 XtSetValues(buttonBarWidget, args, 4);
2812 widgetList[j++] = messageWidget =
2813 XtCreateWidget("message", labelWidgetClass, formWidget,
2814 messageArgs, XtNumber(messageArgs));
2815 XtSetArg(args[0], XtNtop, XtChainTop);
2816 XtSetArg(args[1], XtNbottom, XtChainTop);
2817 XtSetValues(messageWidget, args, 2);
2819 widgetList[j++] = boardWidget =
2820 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2821 XtNumber(boardArgs));
2823 XtManageChildren(widgetList, j);
2825 timerWidth = (boardWidth - sep) / 2;
2826 XtSetArg(args[0], XtNwidth, timerWidth);
2827 XtSetValues(whiteTimerWidget, args, 1);
2828 XtSetValues(blackTimerWidget, args, 1);
2830 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2831 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2832 XtGetValues(whiteTimerWidget, args, 2);
2834 if (appData.showButtonBar) {
2835 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2836 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2837 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2841 * formWidget uses these constraints but they are stored
2845 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2846 XtSetValues(menuBarWidget, args, i);
2847 if (appData.titleInWindow) {
2850 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2851 XtSetValues(whiteTimerWidget, args, i);
2853 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2854 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2855 XtSetValues(blackTimerWidget, args, i);
2857 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2858 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2859 XtSetValues(titleWidget, args, i);
2861 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2862 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2863 XtSetValues(messageWidget, args, i);
2864 if (appData.showButtonBar) {
2866 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2867 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2868 XtSetValues(buttonBarWidget, args, i);
2872 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2873 XtSetValues(whiteTimerWidget, args, i);
2875 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2876 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2877 XtSetValues(blackTimerWidget, args, i);
2879 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2880 XtSetValues(titleWidget, args, i);
2882 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2883 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2884 XtSetValues(messageWidget, args, i);
2885 if (appData.showButtonBar) {
2887 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2888 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2889 XtSetValues(buttonBarWidget, args, i);
2894 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2895 XtSetValues(whiteTimerWidget, args, i);
2897 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2898 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2899 XtSetValues(blackTimerWidget, args, i);
2901 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2902 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2903 XtSetValues(messageWidget, args, i);
2904 if (appData.showButtonBar) {
2906 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2907 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2908 XtSetValues(buttonBarWidget, args, i);
2912 XtSetArg(args[0], XtNfromVert, messageWidget);
2913 XtSetArg(args[1], XtNtop, XtChainTop);
2914 XtSetArg(args[2], XtNbottom, XtChainBottom);
2915 XtSetArg(args[3], XtNleft, XtChainLeft);
2916 XtSetArg(args[4], XtNright, XtChainRight);
2917 XtSetValues(boardWidget, args, 5);
2919 XtRealizeWidget(shellWidget);
2922 * Correct the width of the message and title widgets.
2923 * It is not known why some systems need the extra fudge term.
2924 * The value "2" is probably larger than needed.
2926 XawFormDoLayout(formWidget, False);
2928 #define WIDTH_FUDGE 2
2930 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2931 XtSetArg(args[i], XtNheight, &h); i++;
2932 XtGetValues(messageWidget, args, i);
2933 if (appData.showButtonBar) {
2935 XtSetArg(args[i], XtNwidth, &w); i++;
2936 XtGetValues(buttonBarWidget, args, i);
2937 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2939 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2942 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2943 if (gres != XtGeometryYes && appData.debugMode) {
2944 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2945 programName, gres, w, h, wr, hr);
2948 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2949 /* The size used for the child widget in layout lags one resize behind
2950 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2952 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2953 if (gres != XtGeometryYes && appData.debugMode) {
2954 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2955 programName, gres, w, h, wr, hr);
2958 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2959 XtSetArg(args[1], XtNright, XtChainRight);
2960 XtSetValues(messageWidget, args, 2);
2962 if (appData.titleInWindow) {
2964 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2965 XtSetArg(args[i], XtNheight, &h); i++;
2966 XtGetValues(titleWidget, args, i);
2968 w = boardWidth - 2*bor;
2970 XtSetArg(args[0], XtNwidth, &w);
2971 XtGetValues(menuBarWidget, args, 1);
2972 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2975 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2976 if (gres != XtGeometryYes && appData.debugMode) {
2978 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2979 programName, gres, w, h, wr, hr);
2982 XawFormDoLayout(formWidget, True);
2984 xBoardWindow = XtWindow(boardWidget);
2986 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2987 // not need to go into InitDrawingSizes().
2991 * Create X checkmark bitmap and initialize option menu checks.
2993 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2994 checkmark_bits, checkmark_width, checkmark_height);
2995 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2996 if (appData.alwaysPromoteToQueen) {
2997 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3000 if (appData.animateDragging) {
3001 XtSetValues(XtNameToWidget(menuBarWidget,
3002 "menuOptions.Animate Dragging"),
3005 if (appData.animate) {
3006 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3009 if (appData.autoComment) {
3010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3013 if (appData.autoCallFlag) {
3014 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3017 if (appData.autoFlipView) {
3018 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3021 if (appData.autoObserve) {
3022 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3025 if (appData.autoRaiseBoard) {
3026 XtSetValues(XtNameToWidget(menuBarWidget,
3027 "menuOptions.Auto Raise Board"), args, 1);
3029 if (appData.autoSaveGames) {
3030 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3033 if (appData.saveGameFile[0] != NULLCHAR) {
3034 /* Can't turn this off from menu */
3035 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3037 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3041 if (appData.blindfold) {
3042 XtSetValues(XtNameToWidget(menuBarWidget,
3043 "menuOptions.Blindfold"), args, 1);
3045 if (appData.flashCount > 0) {
3046 XtSetValues(XtNameToWidget(menuBarWidget,
3047 "menuOptions.Flash Moves"),
3050 if (appData.getMoveList) {
3051 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3055 if (appData.highlightDragging) {
3056 XtSetValues(XtNameToWidget(menuBarWidget,
3057 "menuOptions.Highlight Dragging"),
3061 if (appData.highlightLastMove) {
3062 XtSetValues(XtNameToWidget(menuBarWidget,
3063 "menuOptions.Highlight Last Move"),
3066 if (appData.icsAlarm) {
3067 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3070 if (appData.ringBellAfterMoves) {
3071 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3074 if (appData.oldSaveStyle) {
3075 XtSetValues(XtNameToWidget(menuBarWidget,
3076 "menuOptions.Old Save Style"), args, 1);
3078 if (appData.periodicUpdates) {
3079 XtSetValues(XtNameToWidget(menuBarWidget,
3080 "menuOptions.Periodic Updates"), args, 1);
3082 if (appData.ponderNextMove) {
3083 XtSetValues(XtNameToWidget(menuBarWidget,
3084 "menuOptions.Ponder Next Move"), args, 1);
3086 if (appData.popupExitMessage) {
3087 XtSetValues(XtNameToWidget(menuBarWidget,
3088 "menuOptions.Popup Exit Message"), args, 1);
3090 if (appData.popupMoveErrors) {
3091 XtSetValues(XtNameToWidget(menuBarWidget,
3092 "menuOptions.Popup Move Errors"), args, 1);
3094 if (appData.premove) {
3095 XtSetValues(XtNameToWidget(menuBarWidget,
3096 "menuOptions.Premove"), args, 1);
3098 if (appData.quietPlay) {
3099 XtSetValues(XtNameToWidget(menuBarWidget,
3100 "menuOptions.Quiet Play"), args, 1);
3102 if (appData.showCoords) {
3103 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3106 if (appData.hideThinkingFromHuman) {
3107 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3110 if (appData.testLegality) {
3111 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3118 ReadBitmap(&wIconPixmap, "icon_white.bm",
3119 icon_white_bits, icon_white_width, icon_white_height);
3120 ReadBitmap(&bIconPixmap, "icon_black.bm",
3121 icon_black_bits, icon_black_width, icon_black_height);
3122 iconPixmap = wIconPixmap;
3124 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3125 XtSetValues(shellWidget, args, i);
3128 * Create a cursor for the board widget.
3130 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3131 XChangeWindowAttributes(xDisplay, xBoardWindow,
3132 CWCursor, &window_attributes);
3135 * Inhibit shell resizing.
3137 shellArgs[0].value = (XtArgVal) &w;
3138 shellArgs[1].value = (XtArgVal) &h;
3139 XtGetValues(shellWidget, shellArgs, 2);
3140 shellArgs[4].value = shellArgs[2].value = w;
3141 shellArgs[5].value = shellArgs[3].value = h;
3142 XtSetValues(shellWidget, &shellArgs[2], 4);
3143 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3144 marginH = h - boardHeight;
3146 CatchDeleteWindow(shellWidget, "QuitProc");
3151 if (appData.bitmapDirectory[0] != NULLCHAR) {
3158 /* Create regular pieces */
3159 if (!useImages) CreatePieces();
3164 if (appData.animate || appData.animateDragging)
3167 XtAugmentTranslations(formWidget,
3168 XtParseTranslationTable(globalTranslations));
3169 XtAugmentTranslations(boardWidget,
3170 XtParseTranslationTable(boardTranslations));
3171 XtAugmentTranslations(whiteTimerWidget,
3172 XtParseTranslationTable(whiteTranslations));
3173 XtAugmentTranslations(blackTimerWidget,
3174 XtParseTranslationTable(blackTranslations));
3176 /* Why is the following needed on some versions of X instead
3177 * of a translation? */
3178 XtAddEventHandler(boardWidget, ExposureMask, False,
3179 (XtEventHandler) EventProc, NULL);
3184 if (errorExitStatus == -1) {
3185 if (appData.icsActive) {
3186 /* We now wait until we see "login:" from the ICS before
3187 sending the logon script (problems with timestamp otherwise) */
3188 /*ICSInitScript();*/
3189 if (appData.icsInputBox) ICSInputBoxPopUp();
3192 signal(SIGINT, IntSigHandler);
3193 signal(SIGTERM, IntSigHandler);
3194 if (*appData.cmailGameName != NULLCHAR) {
3195 signal(SIGUSR1, CmailSigHandler);
3198 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3201 XtAppMainLoop(appContext);
3202 if (appData.debugMode) fclose(debugFP); // [DM] debug
3209 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3210 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3212 unlink(gameCopyFilename);
3213 unlink(gamePasteFilename);
3216 RETSIGTYPE TermSizeSigHandler(int sig)
3229 CmailSigHandler(sig)
3235 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3237 /* Activate call-back function CmailSigHandlerCallBack() */
3238 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3240 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3244 CmailSigHandlerCallBack(isr, closure, message, count, error)
3252 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3254 /**** end signal code ****/
3264 f = fopen(appData.icsLogon, "r");
3270 strcat(buf, appData.icsLogon);
3271 f = fopen(buf, "r");
3275 ProcessICSInitScript(f);
3282 EditCommentPopDown();
3293 SetMenuEnables(enab)
3297 if (!menuBarWidget) return;
3298 while (enab->name != NULL) {
3299 w = XtNameToWidget(menuBarWidget, enab->name);
3301 DisplayError(enab->name, 0);
3303 XtSetSensitive(w, enab->value);
3309 Enables icsEnables[] = {
3310 { "menuFile.Mail Move", False },
3311 { "menuFile.Reload CMail Message", False },
3312 { "menuMode.Machine Black", False },
3313 { "menuMode.Machine White", False },
3314 { "menuMode.Analysis Mode", False },
3315 { "menuMode.Analyze File", False },
3316 { "menuMode.Two Machines", False },
3318 { "menuHelp.Hint", False },
3319 { "menuHelp.Book", False },
3320 { "menuStep.Move Now", False },
3321 { "menuOptions.Periodic Updates", False },
3322 { "menuOptions.Hide Thinking", False },
3323 { "menuOptions.Ponder Next Move", False },
3328 Enables ncpEnables[] = {
3329 { "menuFile.Mail Move", False },
3330 { "menuFile.Reload CMail Message", False },
3331 { "menuMode.Machine White", False },
3332 { "menuMode.Machine Black", False },
3333 { "menuMode.Analysis Mode", False },
3334 { "menuMode.Analyze File", False },
3335 { "menuMode.Two Machines", False },
3336 { "menuMode.ICS Client", False },
3337 { "menuMode.ICS Input Box", False },
3338 { "Action", False },
3339 { "menuStep.Revert", False },
3340 { "menuStep.Move Now", False },
3341 { "menuStep.Retract Move", False },
3342 { "menuOptions.Auto Comment", False },
3343 { "menuOptions.Auto Flag", False },
3344 { "menuOptions.Auto Flip View", False },
3345 { "menuOptions.Auto Observe", False },
3346 { "menuOptions.Auto Raise Board", False },
3347 { "menuOptions.Get Move List", False },
3348 { "menuOptions.ICS Alarm", False },
3349 { "menuOptions.Move Sound", False },
3350 { "menuOptions.Quiet Play", False },
3351 { "menuOptions.Hide Thinking", False },
3352 { "menuOptions.Periodic Updates", False },
3353 { "menuOptions.Ponder Next Move", False },
3354 { "menuHelp.Hint", False },
3355 { "menuHelp.Book", False },
3359 Enables gnuEnables[] = {
3360 { "menuMode.ICS Client", False },
3361 { "menuMode.ICS Input Box", False },
3362 { "menuAction.Accept", False },
3363 { "menuAction.Decline", False },
3364 { "menuAction.Rematch", False },
3365 { "menuAction.Adjourn", False },
3366 { "menuAction.Stop Examining", False },
3367 { "menuAction.Stop Observing", False },
3368 { "menuStep.Revert", False },
3369 { "menuOptions.Auto Comment", False },
3370 { "menuOptions.Auto Observe", False },
3371 { "menuOptions.Auto Raise Board", False },
3372 { "menuOptions.Get Move List", False },
3373 { "menuOptions.Premove", False },
3374 { "menuOptions.Quiet Play", False },
3376 /* The next two options rely on SetCmailMode being called *after* */
3377 /* SetGNUMode so that when GNU is being used to give hints these */
3378 /* menu options are still available */
3380 { "menuFile.Mail Move", False },
3381 { "menuFile.Reload CMail Message", False },
3385 Enables cmailEnables[] = {
3387 { "menuAction.Call Flag", False },
3388 { "menuAction.Draw", True },
3389 { "menuAction.Adjourn", False },
3390 { "menuAction.Abort", False },
3391 { "menuAction.Stop Observing", False },
3392 { "menuAction.Stop Examining", False },
3393 { "menuFile.Mail Move", True },
3394 { "menuFile.Reload CMail Message", True },
3398 Enables trainingOnEnables[] = {
3399 { "menuMode.Edit Comment", False },
3400 { "menuMode.Pause", False },
3401 { "menuStep.Forward", False },
3402 { "menuStep.Backward", False },
3403 { "menuStep.Forward to End", False },
3404 { "menuStep.Back to Start", False },
3405 { "menuStep.Move Now", False },
3406 { "menuStep.Truncate Game", False },
3410 Enables trainingOffEnables[] = {
3411 { "menuMode.Edit Comment", True },
3412 { "menuMode.Pause", True },
3413 { "menuStep.Forward", True },
3414 { "menuStep.Backward", True },
3415 { "menuStep.Forward to End", True },
3416 { "menuStep.Back to Start", True },
3417 { "menuStep.Move Now", True },
3418 { "menuStep.Truncate Game", True },
3422 Enables machineThinkingEnables[] = {
3423 { "menuFile.Load Game", False },
3424 { "menuFile.Load Next Game", False },
3425 { "menuFile.Load Previous Game", False },
3426 { "menuFile.Reload Same Game", False },
3427 { "menuFile.Paste Game", False },
3428 { "menuFile.Load Position", False },
3429 { "menuFile.Load Next Position", False },
3430 { "menuFile.Load Previous Position", False },
3431 { "menuFile.Reload Same Position", False },
3432 { "menuFile.Paste Position", False },
3433 { "menuMode.Machine White", False },
3434 { "menuMode.Machine Black", False },
3435 { "menuMode.Two Machines", False },
3436 { "menuStep.Retract Move", False },
3440 Enables userThinkingEnables[] = {
3441 { "menuFile.Load Game", True },
3442 { "menuFile.Load Next Game", True },
3443 { "menuFile.Load Previous Game", True },
3444 { "menuFile.Reload Same Game", True },
3445 { "menuFile.Paste Game", True },
3446 { "menuFile.Load Position", True },
3447 { "menuFile.Load Next Position", True },
3448 { "menuFile.Load Previous Position", True },
3449 { "menuFile.Reload Same Position", True },
3450 { "menuFile.Paste Position", True },
3451 { "menuMode.Machine White", True },
3452 { "menuMode.Machine Black", True },
3453 { "menuMode.Two Machines", True },
3454 { "menuStep.Retract Move", True },
3460 SetMenuEnables(icsEnables);
3463 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3464 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3471 SetMenuEnables(ncpEnables);
3477 SetMenuEnables(gnuEnables);
3483 SetMenuEnables(cmailEnables);
3489 SetMenuEnables(trainingOnEnables);
3490 if (appData.showButtonBar) {
3491 XtSetSensitive(buttonBarWidget, False);
3497 SetTrainingModeOff()
3499 SetMenuEnables(trainingOffEnables);
3500 if (appData.showButtonBar) {
3501 XtSetSensitive(buttonBarWidget, True);
3506 SetUserThinkingEnables()
3508 if (appData.noChessProgram) return;
3509 SetMenuEnables(userThinkingEnables);
3513 SetMachineThinkingEnables()
3515 if (appData.noChessProgram) return;
3516 SetMenuEnables(machineThinkingEnables);
3518 case MachinePlaysBlack:
3519 case MachinePlaysWhite:
3520 case TwoMachinesPlay:
3521 XtSetSensitive(XtNameToWidget(menuBarWidget,
3522 ModeToWidgetName(gameMode)), True);
3529 #define Abs(n) ((n)<0 ? -(n) : (n))
3532 * Find a font that matches "pattern" that is as close as
3533 * possible to the targetPxlSize. Prefer fonts that are k
3534 * pixels smaller to fonts that are k pixels larger. The
3535 * pattern must be in the X Consortium standard format,
3536 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3537 * The return value should be freed with XtFree when no
3540 char *FindFont(pattern, targetPxlSize)
3544 char **fonts, *p, *best, *scalable, *scalableTail;
3545 int i, j, nfonts, minerr, err, pxlSize;
3548 char **missing_list;
3550 char *def_string, *base_fnt_lst, strInt[3];
3552 XFontStruct **fnt_list;
3554 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3555 sprintf(strInt, "%d", targetPxlSize);
3556 p = strstr(pattern, "--");
3557 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3558 strcat(base_fnt_lst, strInt);
3559 strcat(base_fnt_lst, strchr(p + 2, '-'));
3561 if ((fntSet = XCreateFontSet(xDisplay,
3565 &def_string)) == NULL) {
3567 fprintf(stderr, _("Unable to create font set.\n"));
3571 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3573 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3575 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3576 programName, pattern);
3584 for (i=0; i<nfonts; i++) {
3587 if (*p != '-') continue;
3589 if (*p == NULLCHAR) break;
3590 if (*p++ == '-') j++;
3592 if (j < 7) continue;
3595 scalable = fonts[i];
3598 err = pxlSize - targetPxlSize;
3599 if (Abs(err) < Abs(minerr) ||
3600 (minerr > 0 && err < 0 && -err == minerr)) {
3606 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3607 /* If the error is too big and there is a scalable font,
3608 use the scalable font. */
3609 int headlen = scalableTail - scalable;
3610 p = (char *) XtMalloc(strlen(scalable) + 10);
3611 while (isdigit(*scalableTail)) scalableTail++;
3612 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3614 p = (char *) XtMalloc(strlen(best) + 1);
3617 if (appData.debugMode) {
3618 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3619 pattern, targetPxlSize, p);
3622 if (missing_count > 0)
3623 XFreeStringList(missing_list);
3624 XFreeFontSet(xDisplay, fntSet);
3626 XFreeFontNames(fonts);
3633 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3634 | GCBackground | GCFunction | GCPlaneMask;
3635 XGCValues gc_values;
3638 gc_values.plane_mask = AllPlanes;
3639 gc_values.line_width = lineGap;
3640 gc_values.line_style = LineSolid;
3641 gc_values.function = GXcopy;
3643 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3644 gc_values.background = XBlackPixel(xDisplay, xScreen);
3645 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3647 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3648 gc_values.background = XWhitePixel(xDisplay, xScreen);
3649 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3650 XSetFont(xDisplay, coordGC, coordFontID);
3652 // [HGM] make font for holdings counts (white on black0
3653 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3654 gc_values.background = XBlackPixel(xDisplay, xScreen);
3655 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3656 XSetFont(xDisplay, countGC, countFontID);
3658 if (appData.monoMode) {
3659 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3660 gc_values.background = XWhitePixel(xDisplay, xScreen);
3661 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3663 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3664 gc_values.background = XBlackPixel(xDisplay, xScreen);
3665 lightSquareGC = wbPieceGC
3666 = XtGetGC(shellWidget, value_mask, &gc_values);
3668 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3669 gc_values.background = XWhitePixel(xDisplay, xScreen);
3670 darkSquareGC = bwPieceGC
3671 = XtGetGC(shellWidget, value_mask, &gc_values);
3673 if (DefaultDepth(xDisplay, xScreen) == 1) {
3674 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3675 gc_values.function = GXcopyInverted;
3676 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3677 gc_values.function = GXcopy;
3678 if (XBlackPixel(xDisplay, xScreen) == 1) {
3679 bwPieceGC = darkSquareGC;
3680 wbPieceGC = copyInvertedGC;
3682 bwPieceGC = copyInvertedGC;
3683 wbPieceGC = lightSquareGC;
3687 gc_values.foreground = highlightSquareColor;
3688 gc_values.background = highlightSquareColor;
3689 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3691 gc_values.foreground = premoveHighlightColor;
3692 gc_values.background = premoveHighlightColor;
3693 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3695 gc_values.foreground = lightSquareColor;
3696 gc_values.background = darkSquareColor;
3697 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3699 gc_values.foreground = darkSquareColor;
3700 gc_values.background = lightSquareColor;
3701 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3703 gc_values.foreground = jailSquareColor;
3704 gc_values.background = jailSquareColor;
3705 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3707 gc_values.foreground = whitePieceColor;
3708 gc_values.background = darkSquareColor;
3709 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3711 gc_values.foreground = whitePieceColor;
3712 gc_values.background = lightSquareColor;
3713 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3715 gc_values.foreground = whitePieceColor;
3716 gc_values.background = jailSquareColor;
3717 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3719 gc_values.foreground = blackPieceColor;
3720 gc_values.background = darkSquareColor;
3721 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3723 gc_values.foreground = blackPieceColor;
3724 gc_values.background = lightSquareColor;
3725 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3727 gc_values.foreground = blackPieceColor;
3728 gc_values.background = jailSquareColor;
3729 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3733 void loadXIM(xim, xmask, filename, dest, mask)
3746 fp = fopen(filename, "rb");
3748 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3755 for (y=0; y<h; ++y) {
3756 for (x=0; x<h; ++x) {
3761 XPutPixel(xim, x, y, blackPieceColor);
3763 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3766 XPutPixel(xim, x, y, darkSquareColor);
3768 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3771 XPutPixel(xim, x, y, whitePieceColor);
3773 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3776 XPutPixel(xim, x, y, lightSquareColor);
3778 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3784 /* create Pixmap of piece */
3785 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3787 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3790 /* create Pixmap of clipmask
3791 Note: We assume the white/black pieces have the same
3792 outline, so we make only 6 masks. This is okay
3793 since the XPM clipmask routines do the same. */
3795 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3797 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3800 /* now create the 1-bit version */
3801 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3804 values.foreground = 1;
3805 values.background = 0;
3807 /* Don't use XtGetGC, not read only */
3808 maskGC = XCreateGC(xDisplay, *mask,
3809 GCForeground | GCBackground, &values);
3810 XCopyPlane(xDisplay, temp, *mask, maskGC,
3811 0, 0, squareSize, squareSize, 0, 0, 1);
3812 XFreePixmap(xDisplay, temp);
3817 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3819 void CreateXIMPieces()
3824 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3829 /* The XSynchronize calls were copied from CreatePieces.
3830 Not sure if needed, but can't hurt */
3831 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3834 /* temp needed by loadXIM() */
3835 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3836 0, 0, ss, ss, AllPlanes, XYPixmap);
3838 if (strlen(appData.pixmapDirectory) == 0) {
3842 if (appData.monoMode) {
3843 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3847 fprintf(stderr, _("\nLoading XIMs...\n"));
3849 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3850 fprintf(stderr, "%d", piece+1);
3851 for (kind=0; kind<4; kind++) {
3852 fprintf(stderr, ".");
3853 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3854 ExpandPathName(appData.pixmapDirectory),
3855 piece <= (int) WhiteKing ? "" : "w",
3856 pieceBitmapNames[piece],
3858 ximPieceBitmap[kind][piece] =
3859 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3860 0, 0, ss, ss, AllPlanes, XYPixmap);
3861 if (appData.debugMode)
3862 fprintf(stderr, _("(File:%s:) "), buf);
3863 loadXIM(ximPieceBitmap[kind][piece],
3865 &(xpmPieceBitmap2[kind][piece]),
3866 &(ximMaskPm2[piece]));
3867 if(piece <= (int)WhiteKing)
3868 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3870 fprintf(stderr," ");
3872 /* Load light and dark squares */
3873 /* If the LSQ and DSQ pieces don't exist, we will
3874 draw them with solid squares. */
3875 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3876 if (access(buf, 0) != 0) {
3880 fprintf(stderr, _("light square "));
3882 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3883 0, 0, ss, ss, AllPlanes, XYPixmap);
3884 if (appData.debugMode)
3885 fprintf(stderr, _("(File:%s:) "), buf);
3887 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3888 fprintf(stderr, _("dark square "));
3889 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3890 ExpandPathName(appData.pixmapDirectory), ss);
3891 if (appData.debugMode)
3892 fprintf(stderr, _("(File:%s:) "), buf);
3894 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3895 0, 0, ss, ss, AllPlanes, XYPixmap);
3896 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3897 xpmJailSquare = xpmLightSquare;
3899 fprintf(stderr, _("Done.\n"));
3901 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3905 void CreateXPMPieces()
3909 u_int ss = squareSize;
3911 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3912 XpmColorSymbol symbols[4];
3914 /* The XSynchronize calls were copied from CreatePieces.
3915 Not sure if needed, but can't hurt */
3916 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3918 /* Setup translations so piece colors match square colors */
3919 symbols[0].name = "light_piece";
3920 symbols[0].value = appData.whitePieceColor;
3921 symbols[1].name = "dark_piece";
3922 symbols[1].value = appData.blackPieceColor;
3923 symbols[2].name = "light_square";
3924 symbols[2].value = appData.lightSquareColor;
3925 symbols[3].name = "dark_square";
3926 symbols[3].value = appData.darkSquareColor;
3928 attr.valuemask = XpmColorSymbols;
3929 attr.colorsymbols = symbols;
3930 attr.numsymbols = 4;
3932 if (appData.monoMode) {
3933 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3937 if (strlen(appData.pixmapDirectory) == 0) {
3938 XpmPieces* pieces = builtInXpms;
3941 while (pieces->size != squareSize && pieces->size) pieces++;
3942 if (!pieces->size) {
3943 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3946 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3947 for (kind=0; kind<4; kind++) {
3949 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3950 pieces->xpm[piece][kind],
3951 &(xpmPieceBitmap2[kind][piece]),
3952 NULL, &attr)) != 0) {
3953 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3957 if(piece <= (int) WhiteKing)
3958 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3962 xpmJailSquare = xpmLightSquare;
3966 fprintf(stderr, _("\nLoading XPMs...\n"));
3969 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3970 fprintf(stderr, "%d ", piece+1);
3971 for (kind=0; kind<4; kind++) {
3972 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3973 ExpandPathName(appData.pixmapDirectory),
3974 piece > (int) WhiteKing ? "w" : "",
3975 pieceBitmapNames[piece],
3977 if (appData.debugMode) {
3978 fprintf(stderr, _("(File:%s:) "), buf);
3980 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3981 &(xpmPieceBitmap2[kind][piece]),
3982 NULL, &attr)) != 0) {
3983 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3984 // [HGM] missing: read of unorthodox piece failed; substitute King.
3985 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3986 ExpandPathName(appData.pixmapDirectory),
3988 if (appData.debugMode) {
3989 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3991 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3992 &(xpmPieceBitmap2[kind][piece]),
3996 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4001 if(piece <= (int) WhiteKing)
4002 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4005 /* Load light and dark squares */
4006 /* If the LSQ and DSQ pieces don't exist, we will
4007 draw them with solid squares. */
4008 fprintf(stderr, _("light square "));
4009 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4010 if (access(buf, 0) != 0) {
4014 if (appData.debugMode)
4015 fprintf(stderr, _("(File:%s:) "), buf);
4017 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4018 &xpmLightSquare, NULL, &attr)) != 0) {
4019 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4022 fprintf(stderr, _("dark square "));
4023 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4024 ExpandPathName(appData.pixmapDirectory), ss);
4025 if (appData.debugMode) {
4026 fprintf(stderr, _("(File:%s:) "), buf);
4028 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4029 &xpmDarkSquare, NULL, &attr)) != 0) {
4030 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4034 xpmJailSquare = xpmLightSquare;
4035 fprintf(stderr, _("Done.\n"));
4037 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4040 #endif /* HAVE_LIBXPM */
4043 /* No built-in bitmaps */
4048 u_int ss = squareSize;
4050 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4053 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4054 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4055 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4056 pieceBitmapNames[piece],
4057 ss, kind == SOLID ? 's' : 'o');
4058 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4059 if(piece <= (int)WhiteKing)
4060 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4064 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4068 /* With built-in bitmaps */
4071 BuiltInBits* bib = builtInBits;
4074 u_int ss = squareSize;
4076 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4079 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4081 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4082 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4083 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4084 pieceBitmapNames[piece],
4085 ss, kind == SOLID ? 's' : 'o');
4086 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4087 bib->bits[kind][piece], ss, ss);
4088 if(piece <= (int)WhiteKing)
4089 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4093 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4098 void ReadBitmap(pm, name, bits, wreq, hreq)
4101 unsigned char bits[];
4107 char msg[MSG_SIZ], fullname[MSG_SIZ];
4109 if (*appData.bitmapDirectory != NULLCHAR) {
4110 strcpy(fullname, appData.bitmapDirectory);
4111 strcat(fullname, "/");
4112 strcat(fullname, name);
4113 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4114 &w, &h, pm, &x_hot, &y_hot);
4115 fprintf(stderr, "load %s\n", name);
4116 if (errcode != BitmapSuccess) {
4118 case BitmapOpenFailed:
4119 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4121 case BitmapFileInvalid:
4122 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4124 case BitmapNoMemory:
4125 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4129 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4133 fprintf(stderr, _("%s: %s...using built-in\n"),
4135 } else if (w != wreq || h != hreq) {
4137 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4138 programName, fullname, w, h, wreq, hreq);
4144 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4153 if (lineGap == 0) return;
4155 /* [HR] Split this into 2 loops for non-square boards. */
4157 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4158 gridSegments[i].x1 = 0;
4159 gridSegments[i].x2 =
4160 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4161 gridSegments[i].y1 = gridSegments[i].y2
4162 = lineGap / 2 + (i * (squareSize + lineGap));
4165 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4166 gridSegments[j + i].y1 = 0;
4167 gridSegments[j + i].y2 =
4168 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4169 gridSegments[j + i].x1 = gridSegments[j + i].x2
4170 = lineGap / 2 + (j * (squareSize + lineGap));
4174 static void MenuBarSelect(w, addr, index)
4179 XtActionProc proc = (XtActionProc) addr;
4181 (proc)(NULL, NULL, NULL, NULL);
4184 void CreateMenuBarPopup(parent, name, mb)
4194 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4197 XtSetArg(args[j], XtNleftMargin, 20); j++;
4198 XtSetArg(args[j], XtNrightMargin, 20); j++;
4200 while (mi->string != NULL) {
4201 if (strcmp(mi->string, "----") == 0) {
4202 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4205 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4206 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4208 XtAddCallback(entry, XtNcallback,
4209 (XtCallbackProc) MenuBarSelect,
4210 (caddr_t) mi->proc);
4216 Widget CreateMenuBar(mb)
4220 Widget anchor, menuBar;
4222 char menuName[MSG_SIZ];
4225 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4226 XtSetArg(args[j], XtNvSpace, 0); j++;
4227 XtSetArg(args[j], XtNborderWidth, 0); j++;
4228 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4229 formWidget, args, j);
4231 while (mb->name != NULL) {
4232 strcpy(menuName, "menu");
4233 strcat(menuName, mb->name);
4235 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4238 shortName[0] = _(mb->name)[0];
4239 shortName[1] = NULLCHAR;
4240 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4243 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4246 XtSetArg(args[j], XtNborderWidth, 0); j++;
4247 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4249 CreateMenuBarPopup(menuBar, menuName, mb);
4255 Widget CreateButtonBar(mi)
4259 Widget button, buttonBar;
4263 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4265 XtSetArg(args[j], XtNhSpace, 0); j++;
4267 XtSetArg(args[j], XtNborderWidth, 0); j++;
4268 XtSetArg(args[j], XtNvSpace, 0); j++;
4269 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4270 formWidget, args, j);
4272 while (mi->string != NULL) {
4275 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4276 XtSetArg(args[j], XtNborderWidth, 0); j++;
4278 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4279 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4280 buttonBar, args, j);
4281 XtAddCallback(button, XtNcallback,
4282 (XtCallbackProc) MenuBarSelect,
4283 (caddr_t) mi->proc);
4290 CreatePieceMenu(name, color)
4297 ChessSquare selection;
4299 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4300 boardWidget, args, 0);
4302 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4303 String item = pieceMenuStrings[color][i];
4305 if (strcmp(item, "----") == 0) {
4306 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4309 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4310 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4312 selection = pieceMenuTranslation[color][i];
4313 XtAddCallback(entry, XtNcallback,
4314 (XtCallbackProc) PieceMenuSelect,
4315 (caddr_t) selection);
4316 if (selection == WhitePawn || selection == BlackPawn) {
4317 XtSetArg(args[0], XtNpopupOnEntry, entry);
4318 XtSetValues(menu, args, 1);
4331 ChessSquare selection;
4333 whitePieceMenu = CreatePieceMenu("menuW", 0);
4334 blackPieceMenu = CreatePieceMenu("menuB", 1);
4336 XtRegisterGrabAction(PieceMenuPopup, True,
4337 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4338 GrabModeAsync, GrabModeAsync);
4340 XtSetArg(args[0], XtNlabel, _("Drop"));
4341 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4342 boardWidget, args, 1);
4343 for (i = 0; i < DROP_MENU_SIZE; i++) {
4344 String item = dropMenuStrings[i];
4346 if (strcmp(item, "----") == 0) {
4347 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4350 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4351 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4353 selection = dropMenuTranslation[i];
4354 XtAddCallback(entry, XtNcallback,
4355 (XtCallbackProc) DropMenuSelect,
4356 (caddr_t) selection);
4361 void SetupDropMenu()
4369 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4370 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4371 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4372 dmEnables[i].piece);
4373 XtSetSensitive(entry, p != NULL || !appData.testLegality
4374 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4375 && !appData.icsActive));
4377 while (p && *p++ == dmEnables[i].piece) count++;
4378 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4380 XtSetArg(args[j], XtNlabel, label); j++;
4381 XtSetValues(entry, args, j);
4385 void PieceMenuPopup(w, event, params, num_params)
4389 Cardinal *num_params;
4392 if (event->type != ButtonPress) return;
4393 if (errorUp) ErrorPopDown();
4397 whichMenu = params[0];
4399 case IcsPlayingWhite:
4400 case IcsPlayingBlack:
4402 case MachinePlaysWhite:
4403 case MachinePlaysBlack:
4404 if (appData.testLegality &&
4405 gameInfo.variant != VariantBughouse &&
4406 gameInfo.variant != VariantCrazyhouse) return;
4408 whichMenu = "menuD";
4414 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4415 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4416 pmFromX = pmFromY = -1;
4420 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4422 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4424 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4427 static void PieceMenuSelect(w, piece, junk)
4432 if (pmFromX < 0 || pmFromY < 0) return;
4433 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4436 static void DropMenuSelect(w, piece, junk)
4441 if (pmFromX < 0 || pmFromY < 0) return;
4442 DropMenuEvent(piece, pmFromX, pmFromY);
4445 void WhiteClock(w, event, prms, nprms)
4451 if (gameMode == EditPosition || gameMode == IcsExamining) {
4452 SetWhiteToPlayEvent();
4453 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4458 void BlackClock(w, event, prms, nprms)
4464 if (gameMode == EditPosition || gameMode == IcsExamining) {
4465 SetBlackToPlayEvent();
4466 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4473 * If the user selects on a border boundary, return -1; if off the board,
4474 * return -2. Otherwise map the event coordinate to the square.
4476 int EventToSquare(x, limit)
4484 if ((x % (squareSize + lineGap)) >= squareSize)
4486 x /= (squareSize + lineGap);
4492 static void do_flash_delay(msec)
4498 static void drawHighlight(file, rank, gc)
4504 if (lineGap == 0 || appData.blindfold) return;
4507 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4508 (squareSize + lineGap);
4509 y = lineGap/2 + rank * (squareSize + lineGap);
4511 x = lineGap/2 + file * (squareSize + lineGap);
4512 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4513 (squareSize + lineGap);
4516 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4517 squareSize+lineGap, squareSize+lineGap);
4520 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4521 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4524 SetHighlights(fromX, fromY, toX, toY)
4525 int fromX, fromY, toX, toY;
4527 if (hi1X != fromX || hi1Y != fromY) {
4528 if (hi1X >= 0 && hi1Y >= 0) {
4529 drawHighlight(hi1X, hi1Y, lineGC);
4531 if (fromX >= 0 && fromY >= 0) {
4532 drawHighlight(fromX, fromY, highlineGC);
4535 if (hi2X != toX || hi2Y != toY) {
4536 if (hi2X >= 0 && hi2Y >= 0) {
4537 drawHighlight(hi2X, hi2Y, lineGC);
4539 if (toX >= 0 && toY >= 0) {
4540 drawHighlight(toX, toY, highlineGC);
4552 SetHighlights(-1, -1, -1, -1);
4557 SetPremoveHighlights(fromX, fromY, toX, toY)
4558 int fromX, fromY, toX, toY;
4560 if (pm1X != fromX || pm1Y != fromY) {
4561 if (pm1X >= 0 && pm1Y >= 0) {
4562 drawHighlight(pm1X, pm1Y, lineGC);
4564 if (fromX >= 0 && fromY >= 0) {
4565 drawHighlight(fromX, fromY, prelineGC);
4568 if (pm2X != toX || pm2Y != toY) {
4569 if (pm2X >= 0 && pm2Y >= 0) {
4570 drawHighlight(pm2X, pm2Y, lineGC);
4572 if (toX >= 0 && toY >= 0) {
4573 drawHighlight(toX, toY, prelineGC);
4583 ClearPremoveHighlights()
4585 SetPremoveHighlights(-1, -1, -1, -1);
4588 static void BlankSquare(x, y, color, piece, dest)
4593 if (useImages && useImageSqs) {
4597 pm = xpmLightSquare;
4602 case 2: /* neutral */
4607 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4608 squareSize, squareSize, x, y);
4618 case 2: /* neutral */
4623 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4628 I split out the routines to draw a piece so that I could
4629 make a generic flash routine.
4631 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4633 int square_color, x, y;
4636 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4637 switch (square_color) {
4639 case 2: /* neutral */
4641 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4642 ? *pieceToOutline(piece)
4643 : *pieceToSolid(piece),
4644 dest, bwPieceGC, 0, 0,
4645 squareSize, squareSize, x, y);
4648 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4649 ? *pieceToSolid(piece)
4650 : *pieceToOutline(piece),
4651 dest, wbPieceGC, 0, 0,
4652 squareSize, squareSize, x, y);
4657 static void monoDrawPiece(piece, square_color, x, y, dest)
4659 int square_color, x, y;
4662 switch (square_color) {
4664 case 2: /* neutral */
4666 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4667 ? *pieceToOutline(piece)
4668 : *pieceToSolid(piece),
4669 dest, bwPieceGC, 0, 0,
4670 squareSize, squareSize, x, y, 1);
4673 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4674 ? *pieceToSolid(piece)
4675 : *pieceToOutline(piece),
4676 dest, wbPieceGC, 0, 0,
4677 squareSize, squareSize, x, y, 1);
4682 static void colorDrawPiece(piece, square_color, x, y, dest)
4684 int square_color, x, y;
4687 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4688 switch (square_color) {
4690 XCopyPlane(xDisplay, *pieceToSolid(piece),
4691 dest, (int) piece < (int) BlackPawn
4692 ? wlPieceGC : blPieceGC, 0, 0,
4693 squareSize, squareSize, x, y, 1);
4696 XCopyPlane(xDisplay, *pieceToSolid(piece),
4697 dest, (int) piece < (int) BlackPawn
4698 ? wdPieceGC : bdPieceGC, 0, 0,
4699 squareSize, squareSize, x, y, 1);
4701 case 2: /* neutral */
4703 XCopyPlane(xDisplay, *pieceToSolid(piece),
4704 dest, (int) piece < (int) BlackPawn
4705 ? wjPieceGC : bjPieceGC, 0, 0,
4706 squareSize, squareSize, x, y, 1);
4711 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4713 int square_color, x, y;
4718 switch (square_color) {
4720 case 2: /* neutral */
4722 if ((int)piece < (int) BlackPawn) {
4730 if ((int)piece < (int) BlackPawn) {
4738 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4739 dest, wlPieceGC, 0, 0,
4740 squareSize, squareSize, x, y);
4743 typedef void (*DrawFunc)();
4745 DrawFunc ChooseDrawFunc()
4747 if (appData.monoMode) {
4748 if (DefaultDepth(xDisplay, xScreen) == 1) {
4749 return monoDrawPiece_1bit;
4751 return monoDrawPiece;
4755 return colorDrawPieceImage;
4757 return colorDrawPiece;
4761 /* [HR] determine square color depending on chess variant. */
4762 static int SquareColor(row, column)
4767 if (gameInfo.variant == VariantXiangqi) {
4768 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4770 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4772 } else if (row <= 4) {
4778 square_color = ((column + row) % 2) == 1;
4781 /* [hgm] holdings: next line makes all holdings squares light */
4782 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4784 return square_color;
4787 void DrawSquare(row, column, piece, do_flash)
4788 int row, column, do_flash;
4791 int square_color, x, y, direction, font_ascent, font_descent;
4794 XCharStruct overall;
4798 /* Calculate delay in milliseconds (2-delays per complete flash) */
4799 flash_delay = 500 / appData.flashRate;
4802 x = lineGap + ((BOARD_WIDTH-1)-column) *
4803 (squareSize + lineGap);
4804 y = lineGap + row * (squareSize + lineGap);
4806 x = lineGap + column * (squareSize + lineGap);
4807 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4808 (squareSize + lineGap);
4811 square_color = SquareColor(row, column);
4813 if ( // [HGM] holdings: blank out area between board and holdings
4814 column == BOARD_LEFT-1 || column == BOARD_RGHT
4815 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4816 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4817 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4819 // [HGM] print piece counts next to holdings
4820 string[1] = NULLCHAR;
4821 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4822 string[0] = '0' + piece;
4823 XTextExtents(countFontStruct, string, 1, &direction,
4824 &font_ascent, &font_descent, &overall);
4825 if (appData.monoMode) {
4826 XDrawImageString(xDisplay, xBoardWindow, countGC,
4827 x + squareSize - overall.width - 2,
4828 y + font_ascent + 1, string, 1);
4830 XDrawString(xDisplay, xBoardWindow, countGC,
4831 x + squareSize - overall.width - 2,
4832 y + font_ascent + 1, string, 1);
4835 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4836 string[0] = '0' + piece;
4837 XTextExtents(countFontStruct, string, 1, &direction,
4838 &font_ascent, &font_descent, &overall);
4839 if (appData.monoMode) {
4840 XDrawImageString(xDisplay, xBoardWindow, countGC,
4841 x + 2, y + font_ascent + 1, string, 1);
4843 XDrawString(xDisplay, xBoardWindow, countGC,
4844 x + 2, y + font_ascent + 1, string, 1);
4848 if (piece == EmptySquare || appData.blindfold) {
4849 BlankSquare(x, y, square_color, piece, xBoardWindow);
4851 drawfunc = ChooseDrawFunc();
4852 if (do_flash && appData.flashCount > 0) {
4853 for (i=0; i<appData.flashCount; ++i) {
4855 drawfunc(piece, square_color, x, y, xBoardWindow);
4856 XSync(xDisplay, False);
4857 do_flash_delay(flash_delay);
4859 BlankSquare(x, y, square_color, piece, xBoardWindow);
4860 XSync(xDisplay, False);
4861 do_flash_delay(flash_delay);
4864 drawfunc(piece, square_color, x, y, xBoardWindow);
4868 string[1] = NULLCHAR;
4869 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4870 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4871 string[0] = 'a' + column - BOARD_LEFT;
4872 XTextExtents(coordFontStruct, string, 1, &direction,
4873 &font_ascent, &font_descent, &overall);
4874 if (appData.monoMode) {
4875 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4876 x + squareSize - overall.width - 2,
4877 y + squareSize - font_descent - 1, string, 1);
4879 XDrawString(xDisplay, xBoardWindow, coordGC,
4880 x + squareSize - overall.width - 2,
4881 y + squareSize - font_descent - 1, string, 1);
4884 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4885 string[0] = ONE + row;
4886 XTextExtents(coordFontStruct, string, 1, &direction,
4887 &font_ascent, &font_descent, &overall);
4888 if (appData.monoMode) {
4889 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4890 x + 2, y + font_ascent + 1, string, 1);
4892 XDrawString(xDisplay, xBoardWindow, coordGC,
4893 x + 2, y + font_ascent + 1, string, 1);
4899 /* Why is this needed on some versions of X? */
4900 void EventProc(widget, unused, event)
4905 if (!XtIsRealized(widget))
4908 switch (event->type) {
4910 if (event->xexpose.count > 0) return; /* no clipping is done */
4911 XDrawPosition(widget, True, NULL);
4919 void DrawPosition(fullRedraw, board)
4920 /*Boolean*/int fullRedraw;
4923 XDrawPosition(boardWidget, fullRedraw, board);
4926 /* Returns 1 if there are "too many" differences between b1 and b2
4927 (i.e. more than 1 move was made) */
4928 static int too_many_diffs(b1, b2)
4934 for (i=0; i<BOARD_HEIGHT; ++i) {
4935 for (j=0; j<BOARD_WIDTH; ++j) {
4936 if (b1[i][j] != b2[i][j]) {
4937 if (++c > 4) /* Castling causes 4 diffs */
4946 /* Matrix describing castling maneuvers */
4947 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4948 static int castling_matrix[4][5] = {
4949 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4950 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4951 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4952 { 7, 7, 4, 5, 6 } /* 0-0, black */
4955 /* Checks whether castling occurred. If it did, *rrow and *rcol
4956 are set to the destination (row,col) of the rook that moved.
4958 Returns 1 if castling occurred, 0 if not.
4960 Note: Only handles a max of 1 castling move, so be sure
4961 to call too_many_diffs() first.
4963 static int check_castle_draw(newb, oldb, rrow, rcol)
4970 /* For each type of castling... */
4971 for (i=0; i<4; ++i) {
4972 r = castling_matrix[i];
4974 /* Check the 4 squares involved in the castling move */
4976 for (j=1; j<=4; ++j) {
4977 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4984 /* All 4 changed, so it must be a castling move */
4993 static int damage[BOARD_SIZE][BOARD_SIZE];
4996 * event handler for redrawing the board
4998 void XDrawPosition(w, repaint, board)
5000 /*Boolean*/int repaint;
5004 static int lastFlipView = 0;
5005 static int lastBoardValid = 0;
5006 static Board lastBoard;
5010 if (board == NULL) {
5011 if (!lastBoardValid) return;
5014 if (!lastBoardValid || lastFlipView != flipView) {
5015 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5016 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5021 * It would be simpler to clear the window with XClearWindow()
5022 * but this causes a very distracting flicker.
5025 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5027 /* If too much changes (begin observing new game, etc.), don't
5029 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5031 /* Special check for castling so we don't flash both the king
5032 and the rook (just flash the king). */
5034 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5035 /* Draw rook with NO flashing. King will be drawn flashing later */
5036 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5037 lastBoard[rrow][rcol] = board[rrow][rcol];
5041 /* First pass -- Draw (newly) empty squares and repair damage.
5042 This prevents you from having a piece show up twice while it
5043 is flashing on its new square */
5044 for (i = 0; i < BOARD_HEIGHT; i++)
5045 for (j = 0; j < BOARD_WIDTH; j++)
5046 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5048 DrawSquare(i, j, board[i][j], 0);
5049 damage[i][j] = False;
5052 /* Second pass -- Draw piece(s) in new position and flash them */
5053 for (i = 0; i < BOARD_HEIGHT; i++)
5054 for (j = 0; j < BOARD_WIDTH; j++)
5055 if (board[i][j] != lastBoard[i][j]) {
5056 DrawSquare(i, j, board[i][j], do_flash);
5060 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5061 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5063 for (i = 0; i < BOARD_HEIGHT; i++)
5064 for (j = 0; j < BOARD_WIDTH; j++) {
5065 DrawSquare(i, j, board[i][j], 0);
5066 damage[i][j] = False;
5070 CopyBoard(lastBoard, board);
5072 lastFlipView = flipView;
5074 /* Draw highlights */
5075 if (pm1X >= 0 && pm1Y >= 0) {
5076 drawHighlight(pm1X, pm1Y, prelineGC);
5078 if (pm2X >= 0 && pm2Y >= 0) {
5079 drawHighlight(pm2X, pm2Y, prelineGC);
5081 if (hi1X >= 0 && hi1Y >= 0) {
5082 drawHighlight(hi1X, hi1Y, highlineGC);
5084 if (hi2X >= 0 && hi2Y >= 0) {
5085 drawHighlight(hi2X, hi2Y, highlineGC);
5088 /* If piece being dragged around board, must redraw that too */
5091 XSync(xDisplay, False);
5096 * event handler for redrawing the board
5098 void DrawPositionProc(w, event, prms, nprms)
5104 XDrawPosition(w, True, NULL);
5109 * event handler for parsing user moves
5111 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5112 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5113 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5114 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5115 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5116 // and at the end FinishMove() to perform the move after optional promotion popups.
5117 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5118 void HandleUserMove(w, event, prms, nprms)
5125 Boolean saveAnimate;
5126 static int second = 0, promotionChoice = 0;
5129 if (w != boardWidget || errorExitStatus != -1) return;
5131 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5132 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5133 if (!flipView && y >= 0) {
5134 y = BOARD_HEIGHT - 1 - y;
5136 if (flipView && x >= 0) {
5137 x = BOARD_WIDTH - 1 - x;
5140 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5141 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5142 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5143 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5144 if(gameInfo.holdingsWidth &&
5145 (WhiteOnMove(currentMove)
5146 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5147 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5148 // click in right holdings, for determining promotion piece
5149 ChessSquare p = boards[currentMove][y][x];
5150 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5151 if(p != EmptySquare) {
5152 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5157 DrawPosition(FALSE, boards[currentMove]);
5160 if (event->type == ButtonPress) ErrorPopDown();
5163 if (event->type == ButtonPress) {
5164 XtPopdown(promotionShell);
5165 XtDestroyWidget(promotionShell);
5166 promotionUp = False;
5174 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5175 if(event->type == ButtonPress
5176 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5177 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5178 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5182 if (event->type == ButtonPress) {
5183 /* First square, prepare to drag */
5184 if (OKToStartUserMove(x, y)) {
5188 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5189 if (appData.highlightDragging) {
5190 SetHighlights(x, y, -1, -1);
5198 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5199 /* Click on single square in stead of drag-drop */
5200 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5201 if (appData.animateDragging) {
5202 /* Undo animation damage if any */
5203 DrawPosition(FALSE, NULL);
5206 /* Second up/down in same square; just abort move */
5211 ClearPremoveHighlights();
5213 /* First upclick in same square; start click-click mode */
5214 SetHighlights(x, y, -1, -1);
5219 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5221 if (moveType == Comment) { // kludge for indicating capture-own on Press
5222 /* Clicked again on same color piece -- changed his mind */
5223 /* note that re-clicking same square always hits same color piece */
5224 second = (x == fromX && y == fromY);
5225 if (appData.highlightDragging) {
5226 SetHighlights(x, y, -1, -1);
5230 if (OKToStartUserMove(x, y)) {
5233 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5238 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5241 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5242 DrawPosition(FALSE, boards[currentMove]);
5246 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5249 saveAnimate = appData.animate;
5250 if (event->type == ButtonPress) {
5251 /* Finish clickclick move */
5252 if (appData.animate || appData.highlightLastMove) {
5253 SetHighlights(fromX, fromY, toX, toY);
5258 /* Finish drag move */
5259 if (appData.highlightLastMove) {
5260 SetHighlights(fromX, fromY, toX, toY);
5264 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5265 /* Don't animate move and drag both */
5266 appData.animate = FALSE;
5268 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5269 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5270 appData.alwaysPromoteToQueen) { // promotion, but no choice
5271 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5273 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5274 SetHighlights(fromX, fromY, toX, toY);
5275 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5276 // [HGM] super: promotion to captured piece selected from holdings
5277 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5278 promotionChoice = TRUE;
5279 // kludge follows to temporarily execute move on display, without promoting yet
5280 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5281 boards[currentMove][toY][toX] = p;
5282 DrawPosition(FALSE, boards[currentMove]);
5283 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5284 boards[currentMove][toY][toX] = q;
5285 DisplayMessage("Click in holdings to choose piece", "");
5289 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5291 if(moveType != ImpossibleMove) { // valid move, but no promotion
5292 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5293 } else { // invalid move; could have set premove
5296 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5297 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5300 appData.animate = saveAnimate;
5301 if (appData.animate || appData.animateDragging) {
5302 /* Undo animation damage if needed */
5303 DrawPosition(FALSE, NULL);
5307 void AnimateUserMove (Widget w, XEvent * event,
5308 String * params, Cardinal * nParams)
5310 DragPieceMove(event->xmotion.x, event->xmotion.y);
5313 Widget CommentCreate(name, text, mutable, callback, lines)
5315 int /*Boolean*/ mutable;
5316 XtCallbackProc callback;
5320 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5325 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5326 XtGetValues(boardWidget, args, j);
5329 XtSetArg(args[j], XtNresizable, True); j++;
5332 XtCreatePopupShell(name, topLevelShellWidgetClass,
5333 shellWidget, args, j);
5336 XtCreatePopupShell(name, transientShellWidgetClass,
5337 shellWidget, args, j);
5340 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5341 layoutArgs, XtNumber(layoutArgs));
5343 XtCreateManagedWidget("form", formWidgetClass, layout,
5344 formArgs, XtNumber(formArgs));
5348 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5349 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5351 XtSetArg(args[j], XtNstring, text); j++;
5352 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5353 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5354 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5355 XtSetArg(args[j], XtNright, XtChainRight); j++;
5356 XtSetArg(args[j], XtNresizable, True); j++;
5357 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5358 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5359 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5360 XtSetArg(args[j], XtNautoFill, True); j++;
5361 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5363 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5367 XtSetArg(args[j], XtNfromVert, edit); j++;
5368 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5369 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5370 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5371 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5373 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5374 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5377 XtSetArg(args[j], XtNfromVert, edit); j++;
5378 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5379 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5380 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5381 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5382 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5384 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5385 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5388 XtSetArg(args[j], XtNfromVert, edit); j++;
5389 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5390 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5391 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5392 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5393 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5395 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5396 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5399 XtSetArg(args[j], XtNfromVert, edit); j++;
5400 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5401 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5402 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5403 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5405 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5406 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5409 XtSetArg(args[j], XtNfromVert, edit); j++;
5410 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5411 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5412 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5413 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5414 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5416 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5417 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5420 XtRealizeWidget(shell);
5422 if (commentX == -1) {
5425 Dimension pw_height;
5426 Dimension ew_height;
5429 XtSetArg(args[j], XtNheight, &ew_height); j++;
5430 XtGetValues(edit, args, j);
5433 XtSetArg(args[j], XtNheight, &pw_height); j++;
5434 XtGetValues(shell, args, j);
5435 commentH = pw_height + (lines - 1) * ew_height;
5436 commentW = bw_width - 16;
5438 XSync(xDisplay, False);
5440 /* This code seems to tickle an X bug if it is executed too soon
5441 after xboard starts up. The coordinates get transformed as if
5442 the main window was positioned at (0, 0).
5444 XtTranslateCoords(shellWidget,
5445 (bw_width - commentW) / 2, 0 - commentH / 2,
5446 &commentX, &commentY);
5448 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5449 RootWindowOfScreen(XtScreen(shellWidget)),
5450 (bw_width - commentW) / 2, 0 - commentH / 2,
5455 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5458 XtSetArg(args[j], XtNheight, commentH); j++;
5459 XtSetArg(args[j], XtNwidth, commentW); j++;
5460 XtSetArg(args[j], XtNx, commentX); j++;
5461 XtSetArg(args[j], XtNy, commentY); j++;
5462 XtSetValues(shell, args, j);
5463 XtSetKeyboardFocus(shell, edit);
5468 /* Used for analysis window and ICS input window */
5469 Widget MiscCreate(name, text, mutable, callback, lines)
5471 int /*Boolean*/ mutable;
5472 XtCallbackProc callback;
5476 Widget shell, layout, form, edit;
5478 Dimension bw_width, pw_height, ew_height, w, h;
5484 XtSetArg(args[j], XtNresizable, True); j++;
5487 XtCreatePopupShell(name, topLevelShellWidgetClass,
5488 shellWidget, args, j);
5491 XtCreatePopupShell(name, transientShellWidgetClass,
5492 shellWidget, args, j);
5495 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5496 layoutArgs, XtNumber(layoutArgs));
5498 XtCreateManagedWidget("form", formWidgetClass, layout,
5499 formArgs, XtNumber(formArgs));
5503 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5504 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5506 XtSetArg(args[j], XtNstring, text); j++;
5507 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5508 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5509 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5510 XtSetArg(args[j], XtNright, XtChainRight); j++;
5511 XtSetArg(args[j], XtNresizable, True); j++;
5512 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5513 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5514 XtSetArg(args[j], XtNautoFill, True); j++;
5515 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5517 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5519 XtRealizeWidget(shell);
5522 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5523 XtGetValues(boardWidget, args, j);
5526 XtSetArg(args[j], XtNheight, &ew_height); j++;
5527 XtGetValues(edit, args, j);
5530 XtSetArg(args[j], XtNheight, &pw_height); j++;
5531 XtGetValues(shell, args, j);
5532 h = pw_height + (lines - 1) * ew_height;
5535 XSync(xDisplay, False);
5537 /* This code seems to tickle an X bug if it is executed too soon
5538 after xboard starts up. The coordinates get transformed as if
5539 the main window was positioned at (0, 0).
5541 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5543 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5544 RootWindowOfScreen(XtScreen(shellWidget)),
5545 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5549 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5552 XtSetArg(args[j], XtNheight, h); j++;
5553 XtSetArg(args[j], XtNwidth, w); j++;
5554 XtSetArg(args[j], XtNx, x); j++;
5555 XtSetArg(args[j], XtNy, y); j++;
5556 XtSetValues(shell, args, j);
5562 static int savedIndex; /* gross that this is global */
5564 void EditCommentPopUp(index, title, text)
5573 if (text == NULL) text = "";
5575 if (editShell == NULL) {
5577 CommentCreate(title, text, True, EditCommentCallback, 4);
5578 XtRealizeWidget(editShell);
5579 CatchDeleteWindow(editShell, "EditCommentPopDown");
5581 edit = XtNameToWidget(editShell, "*form.text");
5583 XtSetArg(args[j], XtNstring, text); j++;
5584 XtSetValues(edit, args, j);
5586 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5587 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5588 XtSetValues(editShell, args, j);
5591 XtPopup(editShell, XtGrabNone);
5595 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5596 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5600 void EditCommentCallback(w, client_data, call_data)
5602 XtPointer client_data, call_data;
5610 XtSetArg(args[j], XtNlabel, &name); j++;
5611 XtGetValues(w, args, j);
5613 if (strcmp(name, _("ok")) == 0) {
5614 edit = XtNameToWidget(editShell, "*form.text");
5616 XtSetArg(args[j], XtNstring, &val); j++;
5617 XtGetValues(edit, args, j);
5618 ReplaceComment(savedIndex, val);
5619 EditCommentPopDown();
5620 } else if (strcmp(name, _("cancel")) == 0) {
5621 EditCommentPopDown();
5622 } else if (strcmp(name, _("clear")) == 0) {
5623 edit = XtNameToWidget(editShell, "*form.text");
5624 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5625 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5629 void EditCommentPopDown()
5634 if (!editUp) return;
5636 XtSetArg(args[j], XtNx, &commentX); j++;
5637 XtSetArg(args[j], XtNy, &commentY); j++;
5638 XtSetArg(args[j], XtNheight, &commentH); j++;
5639 XtSetArg(args[j], XtNwidth, &commentW); j++;
5640 XtGetValues(editShell, args, j);
5641 XtPopdown(editShell);
5644 XtSetArg(args[j], XtNleftBitmap, None); j++;
5645 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5649 void ICSInputBoxPopUp()
5654 char *title = _("ICS Input");
5657 if (ICSInputShell == NULL) {
5658 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5659 tr = XtParseTranslationTable(ICSInputTranslations);
5660 edit = XtNameToWidget(ICSInputShell, "*form.text");
5661 XtOverrideTranslations(edit, tr);
5662 XtRealizeWidget(ICSInputShell);
5663 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5666 edit = XtNameToWidget(ICSInputShell, "*form.text");
5668 XtSetArg(args[j], XtNstring, ""); j++;
5669 XtSetValues(edit, args, j);
5671 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5672 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5673 XtSetValues(ICSInputShell, args, j);
5676 XtPopup(ICSInputShell, XtGrabNone);
5677 XtSetKeyboardFocus(ICSInputShell, edit);
5679 ICSInputBoxUp = True;
5681 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5682 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5686 void ICSInputSendText()
5693 edit = XtNameToWidget(ICSInputShell, "*form.text");
5695 XtSetArg(args[j], XtNstring, &val); j++;
5696 XtGetValues(edit, args, j);
5697 SendMultiLineToICS(val);
5698 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5699 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5702 void ICSInputBoxPopDown()
5707 if (!ICSInputBoxUp) return;
5709 XtPopdown(ICSInputShell);
5710 ICSInputBoxUp = False;
5712 XtSetArg(args[j], XtNleftBitmap, None); j++;
5713 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5717 void CommentPopUp(title, text)
5724 if (commentShell == NULL) {
5726 CommentCreate(title, text, False, CommentCallback, 4);
5727 XtRealizeWidget(commentShell);
5728 CatchDeleteWindow(commentShell, "CommentPopDown");
5730 edit = XtNameToWidget(commentShell, "*form.text");
5732 XtSetArg(args[j], XtNstring, text); j++;
5733 XtSetValues(edit, args, j);
5735 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5736 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5737 XtSetValues(commentShell, args, j);
5740 XtPopup(commentShell, XtGrabNone);
5741 XSync(xDisplay, False);
5746 void CommentCallback(w, client_data, call_data)
5748 XtPointer client_data, call_data;
5755 XtSetArg(args[j], XtNlabel, &name); j++;
5756 XtGetValues(w, args, j);
5758 if (strcmp(name, _("close")) == 0) {
5760 } else if (strcmp(name, _("edit")) == 0) {
5767 void CommentPopDown()
5772 if (!commentUp) return;
5774 XtSetArg(args[j], XtNx, &commentX); j++;
5775 XtSetArg(args[j], XtNy, &commentY); j++;
5776 XtSetArg(args[j], XtNwidth, &commentW); j++;
5777 XtSetArg(args[j], XtNheight, &commentH); j++;
5778 XtGetValues(commentShell, args, j);
5779 XtPopdown(commentShell);
5780 XSync(xDisplay, False);
5784 void FileNamePopUp(label, def, proc, openMode)
5791 Widget popup, layout, dialog, edit;
5797 fileProc = proc; /* I can't see a way not */
5798 fileOpenMode = openMode; /* to use globals here */
5801 XtSetArg(args[i], XtNresizable, True); i++;
5802 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5803 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5804 fileNameShell = popup =
5805 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5806 shellWidget, args, i);
5809 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5810 layoutArgs, XtNumber(layoutArgs));
5813 XtSetArg(args[i], XtNlabel, label); i++;
5814 XtSetArg(args[i], XtNvalue, def); i++;
5815 XtSetArg(args[i], XtNborderWidth, 0); i++;
5816 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5819 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5820 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5821 (XtPointer) dialog);
5823 XtRealizeWidget(popup);
5824 CatchDeleteWindow(popup, "FileNamePopDown");
5826 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5827 &x, &y, &win_x, &win_y, &mask);
5829 XtSetArg(args[0], XtNx, x - 10);
5830 XtSetArg(args[1], XtNy, y - 30);
5831 XtSetValues(popup, args, 2);
5833 XtPopup(popup, XtGrabExclusive);
5836 edit = XtNameToWidget(dialog, "*value");
5837 XtSetKeyboardFocus(popup, edit);
5840 void FileNamePopDown()
5842 if (!filenameUp) return;
5843 XtPopdown(fileNameShell);
5844 XtDestroyWidget(fileNameShell);
5849 void FileNameCallback(w, client_data, call_data)
5851 XtPointer client_data, call_data;
5856 XtSetArg(args[0], XtNlabel, &name);
5857 XtGetValues(w, args, 1);
5859 if (strcmp(name, _("cancel")) == 0) {
5864 FileNameAction(w, NULL, NULL, NULL);
5867 void FileNameAction(w, event, prms, nprms)
5879 name = XawDialogGetValueString(w = XtParent(w));
5881 if ((name != NULL) && (*name != NULLCHAR)) {
5883 XtPopdown(w = XtParent(XtParent(w)));
5887 p = strrchr(buf, ' ');
5894 fullname = ExpandPathName(buf);
5896 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5899 f = fopen(fullname, fileOpenMode);
5901 DisplayError(_("Failed to open file"), errno);
5903 (void) (*fileProc)(f, index, buf);
5910 XtPopdown(w = XtParent(XtParent(w)));
5916 void PromotionPopUp()
5919 Widget dialog, layout;
5921 Dimension bw_width, pw_width;
5925 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5926 XtGetValues(boardWidget, args, j);
5929 XtSetArg(args[j], XtNresizable, True); j++;
5930 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5932 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5933 shellWidget, args, j);
5935 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5936 layoutArgs, XtNumber(layoutArgs));
5939 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5940 XtSetArg(args[j], XtNborderWidth, 0); j++;
5941 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5944 if(gameInfo.variant != VariantShogi) {
5945 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5946 (XtPointer) dialog);
5947 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5948 (XtPointer) dialog);
5949 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5950 (XtPointer) dialog);
5951 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5952 (XtPointer) dialog);
5953 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5954 gameInfo.variant == VariantGiveaway) {
5955 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5956 (XtPointer) dialog);
5958 if(gameInfo.variant == VariantCapablanca ||
5959 gameInfo.variant == VariantGothic ||
5960 gameInfo.variant == VariantCapaRandom) {
5961 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5962 (XtPointer) dialog);
5963 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5964 (XtPointer) dialog);
5966 } else // [HGM] shogi
5968 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5969 (XtPointer) dialog);
5970 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5971 (XtPointer) dialog);
5973 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5974 (XtPointer) dialog);
5976 XtRealizeWidget(promotionShell);
5977 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5980 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5981 XtGetValues(promotionShell, args, j);
5983 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5984 lineGap + squareSize/3 +
5985 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5986 0 : 6*(squareSize + lineGap)), &x, &y);
5989 XtSetArg(args[j], XtNx, x); j++;
5990 XtSetArg(args[j], XtNy, y); j++;
5991 XtSetValues(promotionShell, args, j);
5993 XtPopup(promotionShell, XtGrabNone);
5998 void PromotionPopDown()
6000 if (!promotionUp) return;
6001 XtPopdown(promotionShell);
6002 XtDestroyWidget(promotionShell);
6003 promotionUp = False;
6006 void PromotionCallback(w, client_data, call_data)
6008 XtPointer client_data, call_data;
6014 XtSetArg(args[0], XtNlabel, &name);
6015 XtGetValues(w, args, 1);
6019 if (fromX == -1) return;
6021 if (strcmp(name, _("cancel")) == 0) {
6025 } else if (strcmp(name, _("Knight")) == 0) {
6027 } else if (strcmp(name, _("Promote")) == 0) {
6029 } else if (strcmp(name, _("Defer")) == 0) {
6032 promoChar = ToLower(name[0]);
6035 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6037 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6038 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6043 void ErrorCallback(w, client_data, call_data)
6045 XtPointer client_data, call_data;
6048 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6050 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6056 if (!errorUp) return;
6058 XtPopdown(errorShell);
6059 XtDestroyWidget(errorShell);
6060 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6063 void ErrorPopUp(title, label, modal)
6064 char *title, *label;
6068 Widget dialog, layout;
6072 Dimension bw_width, pw_width;
6073 Dimension pw_height;
6077 XtSetArg(args[i], XtNresizable, True); i++;
6078 XtSetArg(args[i], XtNtitle, title); i++;
6080 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6081 shellWidget, args, i);
6083 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6084 layoutArgs, XtNumber(layoutArgs));
6087 XtSetArg(args[i], XtNlabel, label); i++;
6088 XtSetArg(args[i], XtNborderWidth, 0); i++;
6089 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6092 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6094 XtRealizeWidget(errorShell);
6095 CatchDeleteWindow(errorShell, "ErrorPopDown");
6098 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6099 XtGetValues(boardWidget, args, i);
6101 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6102 XtSetArg(args[i], XtNheight, &pw_height); i++;
6103 XtGetValues(errorShell, args, i);
6106 /* This code seems to tickle an X bug if it is executed too soon
6107 after xboard starts up. The coordinates get transformed as if
6108 the main window was positioned at (0, 0).
6110 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6111 0 - pw_height + squareSize / 3, &x, &y);
6113 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6114 RootWindowOfScreen(XtScreen(boardWidget)),
6115 (bw_width - pw_width) / 2,
6116 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6120 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6123 XtSetArg(args[i], XtNx, x); i++;
6124 XtSetArg(args[i], XtNy, y); i++;
6125 XtSetValues(errorShell, args, i);
6128 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6131 /* Disable all user input other than deleting the window */
6132 static int frozen = 0;
6136 /* Grab by a widget that doesn't accept input */
6137 XtAddGrab(messageWidget, TRUE, FALSE);
6141 /* Undo a FreezeUI */
6144 if (!frozen) return;
6145 XtRemoveGrab(messageWidget);
6149 char *ModeToWidgetName(mode)
6153 case BeginningOfGame:
6154 if (appData.icsActive)
6155 return "menuMode.ICS Client";
6156 else if (appData.noChessProgram ||
6157 *appData.cmailGameName != NULLCHAR)
6158 return "menuMode.Edit Game";
6160 return "menuMode.Machine Black";
6161 case MachinePlaysBlack:
6162 return "menuMode.Machine Black";
6163 case MachinePlaysWhite:
6164 return "menuMode.Machine White";
6166 return "menuMode.Analysis Mode";
6168 return "menuMode.Analyze File";
6169 case TwoMachinesPlay:
6170 return "menuMode.Two Machines";
6172 return "menuMode.Edit Game";
6173 case PlayFromGameFile:
6174 return "menuFile.Load Game";
6176 return "menuMode.Edit Position";
6178 return "menuMode.Training";
6179 case IcsPlayingWhite:
6180 case IcsPlayingBlack:
6184 return "menuMode.ICS Client";
6191 void ModeHighlight()
6194 static int oldPausing = FALSE;
6195 static GameMode oldmode = (GameMode) -1;
6198 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6200 if (pausing != oldPausing) {
6201 oldPausing = pausing;
6203 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6205 XtSetArg(args[0], XtNleftBitmap, None);
6207 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6210 if (appData.showButtonBar) {
6211 /* Always toggle, don't set. Previous code messes up when
6212 invoked while the button is pressed, as releasing it
6213 toggles the state again. */
6216 XtSetArg(args[0], XtNbackground, &oldbg);
6217 XtSetArg(args[1], XtNforeground, &oldfg);
6218 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6220 XtSetArg(args[0], XtNbackground, oldfg);
6221 XtSetArg(args[1], XtNforeground, oldbg);
6223 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6227 wname = ModeToWidgetName(oldmode);
6228 if (wname != NULL) {
6229 XtSetArg(args[0], XtNleftBitmap, None);
6230 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6232 wname = ModeToWidgetName(gameMode);
6233 if (wname != NULL) {
6234 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6235 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6239 /* Maybe all the enables should be handled here, not just this one */
6240 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6241 gameMode == Training || gameMode == PlayFromGameFile);
6246 * Button/menu procedures
6248 void ResetProc(w, event, prms, nprms)
6257 int LoadGamePopUp(f, gameNumber, title)
6262 cmailMsgLoaded = FALSE;
6263 if (gameNumber == 0) {
6264 int error = GameListBuild(f);
6266 DisplayError(_("Cannot build game list"), error);
6267 } else if (!ListEmpty(&gameList) &&
6268 ((ListGame *) gameList.tailPred)->number > 1) {
6269 GameListPopUp(f, title);
6275 return LoadGame(f, gameNumber, title, FALSE);
6278 void LoadGameProc(w, event, prms, nprms)
6284 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6287 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6290 void LoadNextGameProc(w, event, prms, nprms)
6299 void LoadPrevGameProc(w, event, prms, nprms)
6308 void ReloadGameProc(w, event, prms, nprms)
6317 void LoadNextPositionProc(w, event, prms, nprms)
6326 void LoadPrevPositionProc(w, event, prms, nprms)
6335 void ReloadPositionProc(w, event, prms, nprms)
6344 void LoadPositionProc(w, event, prms, nprms)
6350 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6353 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6356 void SaveGameProc(w, event, prms, nprms)
6362 FileNamePopUp(_("Save game file name?"),
6363 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6367 void SavePositionProc(w, event, prms, nprms)
6373 FileNamePopUp(_("Save position file name?"),
6374 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6378 void ReloadCmailMsgProc(w, event, prms, nprms)
6384 ReloadCmailMsgEvent(FALSE);
6387 void MailMoveProc(w, event, prms, nprms)
6396 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6397 static char *selected_fen_position=NULL;
6400 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6401 Atom *type_return, XtPointer *value_return,
6402 unsigned long *length_return, int *format_return)
6404 char *selection_tmp;
6406 if (!selected_fen_position) return False; /* should never happen */
6407 if (*target == XA_STRING){
6408 /* note: since no XtSelectionDoneProc was registered, Xt will
6409 * automatically call XtFree on the value returned. So have to
6410 * make a copy of it allocated with XtMalloc */
6411 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6412 strcpy(selection_tmp, selected_fen_position);
6414 *value_return=selection_tmp;
6415 *length_return=strlen(selection_tmp);
6416 *type_return=XA_STRING;
6417 *format_return = 8; /* bits per byte */
6424 /* note: when called from menu all parameters are NULL, so no clue what the
6425 * Widget which was clicked on was, or what the click event was
6427 void CopyPositionProc(w, event, prms, nprms)
6435 if (selected_fen_position) free(selected_fen_position);
6436 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6437 if (!selected_fen_position) return;
6438 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6440 SendPositionSelection,
6441 NULL/* lose_ownership_proc */ ,
6442 NULL/* transfer_done_proc */);
6444 free(selected_fen_position);
6445 selected_fen_position=NULL;
6449 /* function called when the data to Paste is ready */
6451 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6452 Atom *type, XtPointer value, unsigned long *len, int *format)
6455 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6456 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6457 EditPositionPasteFEN(fenstr);
6461 /* called when Paste Position button is pressed,
6462 * all parameters will be NULL */
6463 void PastePositionProc(w, event, prms, nprms)
6469 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6470 /* (XtSelectionCallbackProc) */ PastePositionCB,
6471 NULL, /* client_data passed to PastePositionCB */
6473 /* better to use the time field from the event that triggered the
6474 * call to this function, but that isn't trivial to get
6482 SendGameSelection(Widget w, Atom *selection, Atom *target,
6483 Atom *type_return, XtPointer *value_return,
6484 unsigned long *length_return, int *format_return)
6486 char *selection_tmp;
6488 if (*target == XA_STRING){
6489 FILE* f = fopen(gameCopyFilename, "r");
6492 if (f == NULL) return False;
6496 selection_tmp = XtMalloc(len + 1);
6497 count = fread(selection_tmp, 1, len, f);
6499 XtFree(selection_tmp);
6502 selection_tmp[len] = NULLCHAR;
6503 *value_return = selection_tmp;
6504 *length_return = len;
6505 *type_return = XA_STRING;
6506 *format_return = 8; /* bits per byte */
6513 /* note: when called from menu all parameters are NULL, so no clue what the
6514 * Widget which was clicked on was, or what the click event was
6516 void CopyGameProc(w, event, prms, nprms)
6524 ret = SaveGameToFile(gameCopyFilename, FALSE);
6527 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6530 NULL/* lose_ownership_proc */ ,
6531 NULL/* transfer_done_proc */);
6534 /* function called when the data to Paste is ready */
6536 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6537 Atom *type, XtPointer value, unsigned long *len, int *format)
6540 if (value == NULL || *len == 0) {
6541 return; /* nothing had been selected to copy */
6543 f = fopen(gamePasteFilename, "w");
6545 DisplayError(_("Can't open temp file"), errno);
6548 fwrite(value, 1, *len, f);
6551 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6554 /* called when Paste Game button is pressed,
6555 * all parameters will be NULL */
6556 void PasteGameProc(w, event, prms, nprms)
6562 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6563 /* (XtSelectionCallbackProc) */ PasteGameCB,
6564 NULL, /* client_data passed to PasteGameCB */
6566 /* better to use the time field from the event that triggered the
6567 * call to this function, but that isn't trivial to get
6577 SaveGameProc(NULL, NULL, NULL, NULL);
6581 void QuitProc(w, event, prms, nprms)
6590 void PauseProc(w, event, prms, nprms)
6600 void MachineBlackProc(w, event, prms, nprms)
6606 MachineBlackEvent();
6609 void MachineWhiteProc(w, event, prms, nprms)
6615 MachineWhiteEvent();
6618 void AnalyzeModeProc(w, event, prms, nprms)
6626 if (!first.analysisSupport) {
6627 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6628 DisplayError(buf, 0);
6631 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6632 if (appData.icsActive) {
6633 if (gameMode != IcsObserving) {
6634 sprintf(buf,_("You are not observing a game"));
6635 DisplayError(buf, 0);
6637 if (appData.icsEngineAnalyze) {
6638 if (appData.debugMode)
6639 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6645 /* if enable, use want disable icsEngineAnalyze */
6646 if (appData.icsEngineAnalyze) {
6651 appData.icsEngineAnalyze = TRUE;
6652 if (appData.debugMode)
6653 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6655 if (!appData.showThinking)
6656 ShowThinkingProc(w,event,prms,nprms);
6661 void AnalyzeFileProc(w, event, prms, nprms)
6667 if (!first.analysisSupport) {
6669 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6670 DisplayError(buf, 0);
6675 if (!appData.showThinking)
6676 ShowThinkingProc(w,event,prms,nprms);
6679 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6680 AnalysisPeriodicEvent(1);
6683 void TwoMachinesProc(w, event, prms, nprms)
6692 void IcsClientProc(w, event, prms, nprms)
6701 void EditGameProc(w, event, prms, nprms)
6710 void EditPositionProc(w, event, prms, nprms)
6716 EditPositionEvent();
6719 void TrainingProc(w, event, prms, nprms)
6728 void EditCommentProc(w, event, prms, nprms)
6735 EditCommentPopDown();
6741 void IcsInputBoxProc(w, event, prms, nprms)
6747 if (ICSInputBoxUp) {
6748 ICSInputBoxPopDown();
6754 void AcceptProc(w, event, prms, nprms)
6763 void DeclineProc(w, event, prms, nprms)
6772 void RematchProc(w, event, prms, nprms)
6781 void CallFlagProc(w, event, prms, nprms)
6790 void DrawProc(w, event, prms, nprms)
6799 void AbortProc(w, event, prms, nprms)
6808 void AdjournProc(w, event, prms, nprms)
6817 void ResignProc(w, event, prms, nprms)
6826 void AdjuWhiteProc(w, event, prms, nprms)
6832 UserAdjudicationEvent(+1);
6835 void AdjuBlackProc(w, event, prms, nprms)
6841 UserAdjudicationEvent(-1);
6844 void AdjuDrawProc(w, event, prms, nprms)
6850 UserAdjudicationEvent(0);
6853 void EnterKeyProc(w, event, prms, nprms)
6859 if (ICSInputBoxUp == True)
6863 void StopObservingProc(w, event, prms, nprms)
6869 StopObservingEvent();
6872 void StopExaminingProc(w, event, prms, nprms)
6878 StopExaminingEvent();
6882 void ForwardProc(w, event, prms, nprms)
6892 void BackwardProc(w, event, prms, nprms)
6901 void ToStartProc(w, event, prms, nprms)
6910 void ToEndProc(w, event, prms, nprms)
6919 void RevertProc(w, event, prms, nprms)
6928 void TruncateGameProc(w, event, prms, nprms)
6934 TruncateGameEvent();
6936 void RetractMoveProc(w, event, prms, nprms)
6945 void MoveNowProc(w, event, prms, nprms)
6955 void AlwaysQueenProc(w, event, prms, nprms)
6963 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6965 if (appData.alwaysPromoteToQueen) {
6966 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6968 XtSetArg(args[0], XtNleftBitmap, None);
6970 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6974 void AnimateDraggingProc(w, event, prms, nprms)
6982 appData.animateDragging = !appData.animateDragging;
6984 if (appData.animateDragging) {
6985 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6988 XtSetArg(args[0], XtNleftBitmap, None);
6990 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6994 void AnimateMovingProc(w, event, prms, nprms)
7002 appData.animate = !appData.animate;
7004 if (appData.animate) {
7005 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7008 XtSetArg(args[0], XtNleftBitmap, None);
7010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7014 void AutocommProc(w, event, prms, nprms)
7022 appData.autoComment = !appData.autoComment;
7024 if (appData.autoComment) {
7025 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7027 XtSetArg(args[0], XtNleftBitmap, None);
7029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7034 void AutoflagProc(w, event, prms, nprms)
7042 appData.autoCallFlag = !appData.autoCallFlag;
7044 if (appData.autoCallFlag) {
7045 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7047 XtSetArg(args[0], XtNleftBitmap, None);
7049 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7053 void AutoflipProc(w, event, prms, nprms)
7061 appData.autoFlipView = !appData.autoFlipView;
7063 if (appData.autoFlipView) {
7064 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7066 XtSetArg(args[0], XtNleftBitmap, None);
7068 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7072 void AutobsProc(w, event, prms, nprms)
7080 appData.autoObserve = !appData.autoObserve;
7082 if (appData.autoObserve) {
7083 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7085 XtSetArg(args[0], XtNleftBitmap, None);
7087 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7091 void AutoraiseProc(w, event, prms, nprms)
7099 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7101 if (appData.autoRaiseBoard) {
7102 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7104 XtSetArg(args[0], XtNleftBitmap, None);
7106 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7110 void AutosaveProc(w, event, prms, nprms)
7118 appData.autoSaveGames = !appData.autoSaveGames;
7120 if (appData.autoSaveGames) {
7121 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7123 XtSetArg(args[0], XtNleftBitmap, None);
7125 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7129 void BlindfoldProc(w, event, prms, nprms)
7137 appData.blindfold = !appData.blindfold;
7139 if (appData.blindfold) {
7140 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7142 XtSetArg(args[0], XtNleftBitmap, None);
7144 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7147 DrawPosition(True, NULL);
7150 void TestLegalityProc(w, event, prms, nprms)
7158 appData.testLegality = !appData.testLegality;
7160 if (appData.testLegality) {
7161 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7163 XtSetArg(args[0], XtNleftBitmap, None);
7165 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7170 void FlashMovesProc(w, event, prms, nprms)
7178 if (appData.flashCount == 0) {
7179 appData.flashCount = 3;
7181 appData.flashCount = -appData.flashCount;
7184 if (appData.flashCount > 0) {
7185 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7187 XtSetArg(args[0], XtNleftBitmap, None);
7189 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7193 void FlipViewProc(w, event, prms, nprms)
7199 flipView = !flipView;
7200 DrawPosition(True, NULL);
7203 void GetMoveListProc(w, event, prms, nprms)
7211 appData.getMoveList = !appData.getMoveList;
7213 if (appData.getMoveList) {
7214 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7217 XtSetArg(args[0], XtNleftBitmap, None);
7219 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7224 void HighlightDraggingProc(w, event, prms, nprms)
7232 appData.highlightDragging = !appData.highlightDragging;
7234 if (appData.highlightDragging) {
7235 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7237 XtSetArg(args[0], XtNleftBitmap, None);
7239 XtSetValues(XtNameToWidget(menuBarWidget,
7240 "menuOptions.Highlight Dragging"), args, 1);
7244 void HighlightLastMoveProc(w, event, prms, nprms)
7252 appData.highlightLastMove = !appData.highlightLastMove;
7254 if (appData.highlightLastMove) {
7255 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7257 XtSetArg(args[0], XtNleftBitmap, None);
7259 XtSetValues(XtNameToWidget(menuBarWidget,
7260 "menuOptions.Highlight Last Move"), args, 1);
7263 void IcsAlarmProc(w, event, prms, nprms)
7271 appData.icsAlarm = !appData.icsAlarm;
7273 if (appData.icsAlarm) {
7274 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7276 XtSetArg(args[0], XtNleftBitmap, None);
7278 XtSetValues(XtNameToWidget(menuBarWidget,
7279 "menuOptions.ICS Alarm"), args, 1);
7282 void MoveSoundProc(w, event, prms, nprms)
7290 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7292 if (appData.ringBellAfterMoves) {
7293 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7295 XtSetArg(args[0], XtNleftBitmap, None);
7297 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7302 void OldSaveStyleProc(w, event, prms, nprms)
7310 appData.oldSaveStyle = !appData.oldSaveStyle;
7312 if (appData.oldSaveStyle) {
7313 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7315 XtSetArg(args[0], XtNleftBitmap, None);
7317 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7321 void PeriodicUpdatesProc(w, event, prms, nprms)
7329 PeriodicUpdatesEvent(!appData.periodicUpdates);
7331 if (appData.periodicUpdates) {
7332 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7334 XtSetArg(args[0], XtNleftBitmap, None);
7336 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7340 void PonderNextMoveProc(w, event, prms, nprms)
7348 PonderNextMoveEvent(!appData.ponderNextMove);
7350 if (appData.ponderNextMove) {
7351 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7353 XtSetArg(args[0], XtNleftBitmap, None);
7355 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7359 void PopupExitMessageProc(w, event, prms, nprms)
7367 appData.popupExitMessage = !appData.popupExitMessage;
7369 if (appData.popupExitMessage) {
7370 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7372 XtSetArg(args[0], XtNleftBitmap, None);
7374 XtSetValues(XtNameToWidget(menuBarWidget,
7375 "menuOptions.Popup Exit Message"), args, 1);
7378 void PopupMoveErrorsProc(w, event, prms, nprms)
7386 appData.popupMoveErrors = !appData.popupMoveErrors;
7388 if (appData.popupMoveErrors) {
7389 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7391 XtSetArg(args[0], XtNleftBitmap, None);
7393 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7397 void PremoveProc(w, event, prms, nprms)
7405 appData.premove = !appData.premove;
7407 if (appData.premove) {
7408 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7410 XtSetArg(args[0], XtNleftBitmap, None);
7412 XtSetValues(XtNameToWidget(menuBarWidget,
7413 "menuOptions.Premove"), args, 1);
7416 void QuietPlayProc(w, event, prms, nprms)
7424 appData.quietPlay = !appData.quietPlay;
7426 if (appData.quietPlay) {
7427 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7429 XtSetArg(args[0], XtNleftBitmap, None);
7431 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7435 void ShowCoordsProc(w, event, prms, nprms)
7443 appData.showCoords = !appData.showCoords;
7445 if (appData.showCoords) {
7446 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7448 XtSetArg(args[0], XtNleftBitmap, None);
7450 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7453 DrawPosition(True, NULL);
7456 void ShowThinkingProc(w, event, prms, nprms)
7464 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7465 ShowThinkingEvent();
7468 void HideThinkingProc(w, event, prms, nprms)
7476 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7477 ShowThinkingEvent();
7479 if (appData.hideThinkingFromHuman) {
7480 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7482 XtSetArg(args[0], XtNleftBitmap, None);
7484 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7488 void InfoProc(w, event, prms, nprms)
7495 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7500 void ManProc(w, event, prms, nprms)
7508 if (nprms && *nprms > 0)
7512 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7516 void HintProc(w, event, prms, nprms)
7525 void BookProc(w, event, prms, nprms)
7534 void AboutProc(w, event, prms, nprms)
7542 char *zippy = " (with Zippy code)";
7546 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7547 programVersion, zippy,
7548 "Copyright 1991 Digital Equipment Corporation",
7549 "Enhancements Copyright 1992-2009 Free Software Foundation",
7550 "Enhancements Copyright 2005 Alessandro Scotti",
7551 PACKAGE, " is free software and carries NO WARRANTY;",
7552 "see the file COPYING for more information.");
7553 ErrorPopUp(_("About XBoard"), buf, FALSE);
7556 void DebugProc(w, event, prms, nprms)
7562 appData.debugMode = !appData.debugMode;
7565 void AboutGameProc(w, event, prms, nprms)
7574 void NothingProc(w, event, prms, nprms)
7583 void Iconify(w, event, prms, nprms)
7592 XtSetArg(args[0], XtNiconic, True);
7593 XtSetValues(shellWidget, args, 1);
7596 void DisplayMessage(message, extMessage)
7597 char *message, *extMessage;
7599 /* display a message in the message widget */
7608 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7613 message = extMessage;
7617 /* need to test if messageWidget already exists, since this function
7618 can also be called during the startup, if for example a Xresource
7619 is not set up correctly */
7622 XtSetArg(arg, XtNlabel, message);
7623 XtSetValues(messageWidget, &arg, 1);
7629 void DisplayTitle(text)
7634 char title[MSG_SIZ];
7637 if (text == NULL) text = "";
7639 if (appData.titleInWindow) {
7641 XtSetArg(args[i], XtNlabel, text); i++;
7642 XtSetValues(titleWidget, args, i);
7645 if (*text != NULLCHAR) {
7647 strcpy(title, text);
7648 } else if (appData.icsActive) {
7649 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7650 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7651 } else if (appData.cmailGameName[0] != NULLCHAR) {
7652 snprintf(icon, sizeof(icon), "%s", "CMail");
7653 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7655 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7656 } else if (gameInfo.variant == VariantGothic) {
7657 strcpy(icon, programName);
7658 strcpy(title, GOTHIC);
7661 } else if (gameInfo.variant == VariantFalcon) {
7662 strcpy(icon, programName);
7663 strcpy(title, FALCON);
7665 } else if (appData.noChessProgram) {
7666 strcpy(icon, programName);
7667 strcpy(title, programName);
7669 strcpy(icon, first.tidy);
7670 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7673 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7674 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7675 XtSetValues(shellWidget, args, i);
7679 void DisplayError(message, error)
7686 if (appData.debugMode || appData.matchMode) {
7687 fprintf(stderr, "%s: %s\n", programName, message);
7690 if (appData.debugMode || appData.matchMode) {
7691 fprintf(stderr, "%s: %s: %s\n",
7692 programName, message, strerror(error));
7694 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7697 ErrorPopUp(_("Error"), message, FALSE);
7701 void DisplayMoveError(message)
7706 DrawPosition(FALSE, NULL);
7707 if (appData.debugMode || appData.matchMode) {
7708 fprintf(stderr, "%s: %s\n", programName, message);
7710 if (appData.popupMoveErrors) {
7711 ErrorPopUp(_("Error"), message, FALSE);
7713 DisplayMessage(message, "");
7718 void DisplayFatalError(message, error, status)
7724 errorExitStatus = status;
7726 fprintf(stderr, "%s: %s\n", programName, message);
7728 fprintf(stderr, "%s: %s: %s\n",
7729 programName, message, strerror(error));
7730 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7733 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7734 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7740 void DisplayInformation(message)
7744 ErrorPopUp(_("Information"), message, TRUE);
7747 void DisplayNote(message)
7751 ErrorPopUp(_("Note"), message, FALSE);
7755 NullXErrorCheck(dpy, error_event)
7757 XErrorEvent *error_event;
7762 void DisplayIcsInteractionTitle(message)
7765 if (oldICSInteractionTitle == NULL) {
7766 /* Magic to find the old window title, adapted from vim */
7767 char *wina = getenv("WINDOWID");
7769 Window win = (Window) atoi(wina);
7770 Window root, parent, *children;
7771 unsigned int nchildren;
7772 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7774 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7775 if (!XQueryTree(xDisplay, win, &root, &parent,
7776 &children, &nchildren)) break;
7777 if (children) XFree((void *)children);
7778 if (parent == root || parent == 0) break;
7781 XSetErrorHandler(oldHandler);
7783 if (oldICSInteractionTitle == NULL) {
7784 oldICSInteractionTitle = "xterm";
7787 printf("\033]0;%s\007", message);
7791 char pendingReplyPrefix[MSG_SIZ];
7792 ProcRef pendingReplyPR;
7794 void AskQuestionProc(w, event, prms, nprms)
7801 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7805 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7808 void AskQuestionPopDown()
7810 if (!askQuestionUp) return;
7811 XtPopdown(askQuestionShell);
7812 XtDestroyWidget(askQuestionShell);
7813 askQuestionUp = False;
7816 void AskQuestionReplyAction(w, event, prms, nprms)
7826 reply = XawDialogGetValueString(w = XtParent(w));
7827 strcpy(buf, pendingReplyPrefix);
7828 if (*buf) strcat(buf, " ");
7831 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7832 AskQuestionPopDown();
7834 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7837 void AskQuestionCallback(w, client_data, call_data)
7839 XtPointer client_data, call_data;
7844 XtSetArg(args[0], XtNlabel, &name);
7845 XtGetValues(w, args, 1);
7847 if (strcmp(name, _("cancel")) == 0) {
7848 AskQuestionPopDown();
7850 AskQuestionReplyAction(w, NULL, NULL, NULL);
7854 void AskQuestion(title, question, replyPrefix, pr)
7855 char *title, *question, *replyPrefix;
7859 Widget popup, layout, dialog, edit;
7865 strcpy(pendingReplyPrefix, replyPrefix);
7866 pendingReplyPR = pr;
7869 XtSetArg(args[i], XtNresizable, True); i++;
7870 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7871 askQuestionShell = popup =
7872 XtCreatePopupShell(title, transientShellWidgetClass,
7873 shellWidget, args, i);
7876 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7877 layoutArgs, XtNumber(layoutArgs));
7880 XtSetArg(args[i], XtNlabel, question); i++;
7881 XtSetArg(args[i], XtNvalue, ""); i++;
7882 XtSetArg(args[i], XtNborderWidth, 0); i++;
7883 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7886 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7887 (XtPointer) dialog);
7888 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7889 (XtPointer) dialog);
7891 XtRealizeWidget(popup);
7892 CatchDeleteWindow(popup, "AskQuestionPopDown");
7894 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7895 &x, &y, &win_x, &win_y, &mask);
7897 XtSetArg(args[0], XtNx, x - 10);
7898 XtSetArg(args[1], XtNy, y - 30);
7899 XtSetValues(popup, args, 2);
7901 XtPopup(popup, XtGrabExclusive);
7902 askQuestionUp = True;
7904 edit = XtNameToWidget(dialog, "*value");
7905 XtSetKeyboardFocus(popup, edit);
7913 if (*name == NULLCHAR) {
7915 } else if (strcmp(name, "$") == 0) {
7916 putc(BELLCHAR, stderr);
7919 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7927 PlaySound(appData.soundMove);
7933 PlaySound(appData.soundIcsWin);
7939 PlaySound(appData.soundIcsLoss);
7945 PlaySound(appData.soundIcsDraw);
7949 PlayIcsUnfinishedSound()
7951 PlaySound(appData.soundIcsUnfinished);
7957 PlaySound(appData.soundIcsAlarm);
7963 system("stty echo");
7969 system("stty -echo");
7973 Colorize(cc, continuation)
7978 int count, outCount, error;
7980 if (textColors[(int)cc].bg > 0) {
7981 if (textColors[(int)cc].fg > 0) {
7982 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7983 textColors[(int)cc].fg, textColors[(int)cc].bg);
7985 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7986 textColors[(int)cc].bg);
7989 if (textColors[(int)cc].fg > 0) {
7990 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7991 textColors[(int)cc].fg);
7993 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7996 count = strlen(buf);
7997 outCount = OutputToProcess(NoProc, buf, count, &error);
7998 if (outCount < count) {
7999 DisplayFatalError(_("Error writing to display"), error, 1);
8002 if (continuation) return;
8005 PlaySound(appData.soundShout);
8008 PlaySound(appData.soundSShout);
8011 PlaySound(appData.soundChannel1);
8014 PlaySound(appData.soundChannel);
8017 PlaySound(appData.soundKibitz);
8020 PlaySound(appData.soundTell);
8022 case ColorChallenge:
8023 PlaySound(appData.soundChallenge);
8026 PlaySound(appData.soundRequest);
8029 PlaySound(appData.soundSeek);
8040 return getpwuid(getuid())->pw_name;
8043 static char *ExpandPathName(path)
8046 static char static_buf[2000];
8047 char *d, *s, buf[2000];
8053 while (*s && isspace(*s))
8062 if (*(s+1) == '/') {
8063 strcpy(d, getpwuid(getuid())->pw_dir);
8068 *strchr(buf, '/') = 0;
8069 pwd = getpwnam(buf);
8072 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8076 strcpy(d, pwd->pw_dir);
8077 strcat(d, strchr(s+1, '/'));
8088 static char host_name[MSG_SIZ];
8090 #if HAVE_GETHOSTNAME
8091 gethostname(host_name, MSG_SIZ);
8093 #else /* not HAVE_GETHOSTNAME */
8094 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8095 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8097 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8099 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8100 #endif /* not HAVE_GETHOSTNAME */
8103 XtIntervalId delayedEventTimerXID = 0;
8104 DelayedEventCallback delayedEventCallback = 0;
8109 delayedEventTimerXID = 0;
8110 delayedEventCallback();
8114 ScheduleDelayedEvent(cb, millisec)
8115 DelayedEventCallback cb; long millisec;
8117 if(delayedEventTimerXID && delayedEventCallback == cb)
8118 // [HGM] alive: replace, rather than add or flush identical event
8119 XtRemoveTimeOut(delayedEventTimerXID);
8120 delayedEventCallback = cb;
8121 delayedEventTimerXID =
8122 XtAppAddTimeOut(appContext, millisec,
8123 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8126 DelayedEventCallback
8129 if (delayedEventTimerXID) {
8130 return delayedEventCallback;
8137 CancelDelayedEvent()
8139 if (delayedEventTimerXID) {
8140 XtRemoveTimeOut(delayedEventTimerXID);
8141 delayedEventTimerXID = 0;
8145 XtIntervalId loadGameTimerXID = 0;
8147 int LoadGameTimerRunning()
8149 return loadGameTimerXID != 0;
8152 int StopLoadGameTimer()
8154 if (loadGameTimerXID != 0) {
8155 XtRemoveTimeOut(loadGameTimerXID);
8156 loadGameTimerXID = 0;
8164 LoadGameTimerCallback(arg, id)
8168 loadGameTimerXID = 0;
8173 StartLoadGameTimer(millisec)
8177 XtAppAddTimeOut(appContext, millisec,
8178 (XtTimerCallbackProc) LoadGameTimerCallback,
8182 XtIntervalId analysisClockXID = 0;
8185 AnalysisClockCallback(arg, id)
8189 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8190 || appData.icsEngineAnalyze) { // [DM]
8191 AnalysisPeriodicEvent(0);
8192 StartAnalysisClock();
8197 StartAnalysisClock()
8200 XtAppAddTimeOut(appContext, 2000,
8201 (XtTimerCallbackProc) AnalysisClockCallback,
8205 XtIntervalId clockTimerXID = 0;
8207 int ClockTimerRunning()
8209 return clockTimerXID != 0;
8212 int StopClockTimer()
8214 if (clockTimerXID != 0) {
8215 XtRemoveTimeOut(clockTimerXID);
8224 ClockTimerCallback(arg, id)
8233 StartClockTimer(millisec)
8237 XtAppAddTimeOut(appContext, millisec,
8238 (XtTimerCallbackProc) ClockTimerCallback,
8243 DisplayTimerLabel(w, color, timer, highlight)
8252 /* check for low time warning */
8253 Pixel foregroundOrWarningColor = timerForegroundPixel;
8256 appData.lowTimeWarning &&
8257 (timer / 1000) < appData.icsAlarmTime)
8258 foregroundOrWarningColor = lowTimeWarningColor;
8260 if (appData.clockMode) {
8261 sprintf(buf, "%s: %s", color, TimeString(timer));
8262 XtSetArg(args[0], XtNlabel, buf);
8264 sprintf(buf, "%s ", color);
8265 XtSetArg(args[0], XtNlabel, buf);
8270 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8271 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8273 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8274 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8277 XtSetValues(w, args, 3);
8281 DisplayWhiteClock(timeRemaining, highlight)
8287 if(appData.noGUI) return;
8288 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8289 if (highlight && iconPixmap == bIconPixmap) {
8290 iconPixmap = wIconPixmap;
8291 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8292 XtSetValues(shellWidget, args, 1);
8297 DisplayBlackClock(timeRemaining, highlight)
8303 if(appData.noGUI) return;
8304 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8305 if (highlight && iconPixmap == wIconPixmap) {
8306 iconPixmap = bIconPixmap;
8307 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8308 XtSetValues(shellWidget, args, 1);
8326 int StartChildProcess(cmdLine, dir, pr)
8333 int to_prog[2], from_prog[2];
8337 if (appData.debugMode) {
8338 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8341 /* We do NOT feed the cmdLine to the shell; we just
8342 parse it into blank-separated arguments in the
8343 most simple-minded way possible.
8346 strcpy(buf, cmdLine);
8351 if (p == NULL) break;
8356 SetUpChildIO(to_prog, from_prog);
8359 signal(SIGWINCH, TermSizeSigHandler);
8362 if ((pid = fork()) == 0) {
8364 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8365 close(to_prog[1]); // first close the unused pipe ends
8366 close(from_prog[0]);
8367 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8368 dup2(from_prog[1], 1);
8369 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8370 close(from_prog[1]); // and closing again loses one of the pipes!
8371 if(fileno(stderr) >= 2) // better safe than sorry...
8372 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8374 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8379 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8381 execvp(argv[0], argv);
8383 /* If we get here, exec failed */
8388 /* Parent process */
8390 close(from_prog[1]);
8392 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8395 cp->fdFrom = from_prog[0];
8396 cp->fdTo = to_prog[1];
8401 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8402 static RETSIGTYPE AlarmCallBack(int n)
8408 DestroyChildProcess(pr, signalType)
8412 ChildProc *cp = (ChildProc *) pr;
8414 if (cp->kind != CPReal) return;
8416 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8417 signal(SIGALRM, AlarmCallBack);
8419 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8420 kill(cp->pid, SIGKILL); // kill it forcefully
8421 wait((int *) 0); // and wait again
8425 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8427 /* Process is exiting either because of the kill or because of
8428 a quit command sent by the backend; either way, wait for it to die.
8437 InterruptChildProcess(pr)
8440 ChildProc *cp = (ChildProc *) pr;
8442 if (cp->kind != CPReal) return;
8443 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8446 int OpenTelnet(host, port, pr)
8451 char cmdLine[MSG_SIZ];
8453 if (port[0] == NULLCHAR) {
8454 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8456 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8458 return StartChildProcess(cmdLine, "", pr);
8461 int OpenTCP(host, port, pr)
8467 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8468 #else /* !OMIT_SOCKETS */
8470 struct sockaddr_in sa;
8472 unsigned short uport;
8475 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8479 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8480 sa.sin_family = AF_INET;
8481 sa.sin_addr.s_addr = INADDR_ANY;
8482 uport = (unsigned short) 0;
8483 sa.sin_port = htons(uport);
8484 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8488 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8489 if (!(hp = gethostbyname(host))) {
8491 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8492 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8493 hp->h_addrtype = AF_INET;
8495 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8496 hp->h_addr_list[0] = (char *) malloc(4);
8497 hp->h_addr_list[0][0] = b0;
8498 hp->h_addr_list[0][1] = b1;
8499 hp->h_addr_list[0][2] = b2;
8500 hp->h_addr_list[0][3] = b3;
8505 sa.sin_family = hp->h_addrtype;
8506 uport = (unsigned short) atoi(port);
8507 sa.sin_port = htons(uport);
8508 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8510 if (connect(s, (struct sockaddr *) &sa,
8511 sizeof(struct sockaddr_in)) < 0) {
8515 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8522 #endif /* !OMIT_SOCKETS */
8527 int OpenCommPort(name, pr)
8534 fd = open(name, 2, 0);
8535 if (fd < 0) return errno;
8537 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8547 int OpenLoopback(pr)
8553 SetUpChildIO(to, from);
8555 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8558 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8565 int OpenRcmd(host, user, cmd, pr)
8566 char *host, *user, *cmd;
8569 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8573 #define INPUT_SOURCE_BUF_SIZE 8192
8582 char buf[INPUT_SOURCE_BUF_SIZE];
8587 DoInputCallback(closure, source, xid)
8592 InputSource *is = (InputSource *) closure;
8597 if (is->lineByLine) {
8598 count = read(is->fd, is->unused,
8599 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8601 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8604 is->unused += count;
8606 while (p < is->unused) {
8607 q = memchr(p, '\n', is->unused - p);
8608 if (q == NULL) break;
8610 (is->func)(is, is->closure, p, q - p, 0);
8614 while (p < is->unused) {
8619 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8624 (is->func)(is, is->closure, is->buf, count, error);
8628 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8635 ChildProc *cp = (ChildProc *) pr;
8637 is = (InputSource *) calloc(1, sizeof(InputSource));
8638 is->lineByLine = lineByLine;
8642 is->fd = fileno(stdin);
8644 is->kind = cp->kind;
8645 is->fd = cp->fdFrom;
8648 is->unused = is->buf;
8651 is->xid = XtAppAddInput(appContext, is->fd,
8652 (XtPointer) (XtInputReadMask),
8653 (XtInputCallbackProc) DoInputCallback,
8655 is->closure = closure;
8656 return (InputSourceRef) is;
8660 RemoveInputSource(isr)
8663 InputSource *is = (InputSource *) isr;
8665 if (is->xid == 0) return;
8666 XtRemoveInput(is->xid);
8670 int OutputToProcess(pr, message, count, outError)
8676 ChildProc *cp = (ChildProc *) pr;
8680 outCount = fwrite(message, 1, count, stdout);
8682 outCount = write(cp->fdTo, message, count);
8692 /* Output message to process, with "ms" milliseconds of delay
8693 between each character. This is needed when sending the logon
8694 script to ICC, which for some reason doesn't like the
8695 instantaneous send. */
8696 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8703 ChildProc *cp = (ChildProc *) pr;
8708 r = write(cp->fdTo, message++, 1);
8721 /**** Animation code by Hugh Fisher, DCS, ANU.
8723 Known problem: if a window overlapping the board is
8724 moved away while a piece is being animated underneath,
8725 the newly exposed area won't be updated properly.
8726 I can live with this.
8728 Known problem: if you look carefully at the animation
8729 of pieces in mono mode, they are being drawn as solid
8730 shapes without interior detail while moving. Fixing
8731 this would be a major complication for minimal return.
8734 /* Masks for XPM pieces. Black and white pieces can have
8735 different shapes, but in the interest of retaining my
8736 sanity pieces must have the same outline on both light
8737 and dark squares, and all pieces must use the same
8738 background square colors/images. */
8740 static int xpmDone = 0;
8743 CreateAnimMasks (pieceDepth)
8750 unsigned long plane;
8753 /* Need a bitmap just to get a GC with right depth */
8754 buf = XCreatePixmap(xDisplay, xBoardWindow,
8756 values.foreground = 1;
8757 values.background = 0;
8758 /* Don't use XtGetGC, not read only */
8759 maskGC = XCreateGC(xDisplay, buf,
8760 GCForeground | GCBackground, &values);
8761 XFreePixmap(xDisplay, buf);
8763 buf = XCreatePixmap(xDisplay, xBoardWindow,
8764 squareSize, squareSize, pieceDepth);
8765 values.foreground = XBlackPixel(xDisplay, xScreen);
8766 values.background = XWhitePixel(xDisplay, xScreen);
8767 bufGC = XCreateGC(xDisplay, buf,
8768 GCForeground | GCBackground, &values);
8770 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8771 /* Begin with empty mask */
8772 if(!xpmDone) // [HGM] pieces: keep using existing
8773 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8774 squareSize, squareSize, 1);
8775 XSetFunction(xDisplay, maskGC, GXclear);
8776 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8777 0, 0, squareSize, squareSize);
8779 /* Take a copy of the piece */
8784 XSetFunction(xDisplay, bufGC, GXcopy);
8785 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8787 0, 0, squareSize, squareSize, 0, 0);
8789 /* XOR the background (light) over the piece */
8790 XSetFunction(xDisplay, bufGC, GXxor);
8792 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8793 0, 0, squareSize, squareSize, 0, 0);
8795 XSetForeground(xDisplay, bufGC, lightSquareColor);
8796 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8799 /* We now have an inverted piece image with the background
8800 erased. Construct mask by just selecting all the non-zero
8801 pixels - no need to reconstruct the original image. */
8802 XSetFunction(xDisplay, maskGC, GXor);
8804 /* Might be quicker to download an XImage and create bitmap
8805 data from it rather than this N copies per piece, but it
8806 only takes a fraction of a second and there is a much
8807 longer delay for loading the pieces. */
8808 for (n = 0; n < pieceDepth; n ++) {
8809 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8810 0, 0, squareSize, squareSize,
8816 XFreePixmap(xDisplay, buf);
8817 XFreeGC(xDisplay, bufGC);
8818 XFreeGC(xDisplay, maskGC);
8822 InitAnimState (anim, info)
8824 XWindowAttributes * info;
8829 /* Each buffer is square size, same depth as window */
8830 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8831 squareSize, squareSize, info->depth);
8832 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8833 squareSize, squareSize, info->depth);
8835 /* Create a plain GC for blitting */
8836 mask = GCForeground | GCBackground | GCFunction |
8837 GCPlaneMask | GCGraphicsExposures;
8838 values.foreground = XBlackPixel(xDisplay, xScreen);
8839 values.background = XWhitePixel(xDisplay, xScreen);
8840 values.function = GXcopy;
8841 values.plane_mask = AllPlanes;
8842 values.graphics_exposures = False;
8843 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8845 /* Piece will be copied from an existing context at
8846 the start of each new animation/drag. */
8847 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8849 /* Outline will be a read-only copy of an existing */
8850 anim->outlineGC = None;
8856 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8857 XWindowAttributes info;
8859 if (xpmDone && gameInfo.variant == old) return;
8860 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8861 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8863 InitAnimState(&game, &info);
8864 InitAnimState(&player, &info);
8866 /* For XPM pieces, we need bitmaps to use as masks. */
8868 CreateAnimMasks(info.depth);
8874 static Boolean frameWaiting;
8876 static RETSIGTYPE FrameAlarm (sig)
8879 frameWaiting = False;
8880 /* In case System-V style signals. Needed?? */
8881 signal(SIGALRM, FrameAlarm);
8888 struct itimerval delay;
8890 XSync(xDisplay, False);
8893 frameWaiting = True;
8894 signal(SIGALRM, FrameAlarm);
8895 delay.it_interval.tv_sec =
8896 delay.it_value.tv_sec = time / 1000;
8897 delay.it_interval.tv_usec =
8898 delay.it_value.tv_usec = (time % 1000) * 1000;
8899 setitimer(ITIMER_REAL, &delay, NULL);
8900 while (frameWaiting) pause();
8901 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8902 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8903 setitimer(ITIMER_REAL, &delay, NULL);
8913 XSync(xDisplay, False);
8915 usleep(time * 1000);
8920 /* Convert board position to corner of screen rect and color */
8923 ScreenSquare(column, row, pt, color)
8924 int column; int row; XPoint * pt; int * color;
8927 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8928 pt->y = lineGap + row * (squareSize + lineGap);
8930 pt->x = lineGap + column * (squareSize + lineGap);
8931 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8933 *color = SquareColor(row, column);
8936 /* Convert window coords to square */
8939 BoardSquare(x, y, column, row)
8940 int x; int y; int * column; int * row;
8942 *column = EventToSquare(x, BOARD_WIDTH);
8943 if (flipView && *column >= 0)
8944 *column = BOARD_WIDTH - 1 - *column;
8945 *row = EventToSquare(y, BOARD_HEIGHT);
8946 if (!flipView && *row >= 0)
8947 *row = BOARD_HEIGHT - 1 - *row;
8952 #undef Max /* just in case */
8954 #define Max(a, b) ((a) > (b) ? (a) : (b))
8955 #define Min(a, b) ((a) < (b) ? (a) : (b))
8958 SetRect(rect, x, y, width, height)
8959 XRectangle * rect; int x; int y; int width; int height;
8963 rect->width = width;
8964 rect->height = height;
8967 /* Test if two frames overlap. If they do, return
8968 intersection rect within old and location of
8969 that rect within new. */
8972 Intersect(old, new, size, area, pt)
8973 XPoint * old; XPoint * new;
8974 int size; XRectangle * area; XPoint * pt;
8976 if (old->x > new->x + size || new->x > old->x + size ||
8977 old->y > new->y + size || new->y > old->y + size) {
8980 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8981 size - abs(old->x - new->x), size - abs(old->y - new->y));
8982 pt->x = Max(old->x - new->x, 0);
8983 pt->y = Max(old->y - new->y, 0);
8988 /* For two overlapping frames, return the rect(s)
8989 in the old that do not intersect with the new. */
8992 CalcUpdateRects(old, new, size, update, nUpdates)
8993 XPoint * old; XPoint * new; int size;
8994 XRectangle update[]; int * nUpdates;
8998 /* If old = new (shouldn't happen) then nothing to draw */
8999 if (old->x == new->x && old->y == new->y) {
9003 /* Work out what bits overlap. Since we know the rects
9004 are the same size we don't need a full intersect calc. */
9006 /* Top or bottom edge? */
9007 if (new->y > old->y) {
9008 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9010 } else if (old->y > new->y) {
9011 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9012 size, old->y - new->y);
9015 /* Left or right edge - don't overlap any update calculated above. */
9016 if (new->x > old->x) {
9017 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9018 new->x - old->x, size - abs(new->y - old->y));
9020 } else if (old->x > new->x) {
9021 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9022 old->x - new->x, size - abs(new->y - old->y));
9029 /* Generate a series of frame coords from start->mid->finish.
9030 The movement rate doubles until the half way point is
9031 reached, then halves back down to the final destination,
9032 which gives a nice slow in/out effect. The algorithmn
9033 may seem to generate too many intermediates for short
9034 moves, but remember that the purpose is to attract the
9035 viewers attention to the piece about to be moved and
9036 then to where it ends up. Too few frames would be less
9040 Tween(start, mid, finish, factor, frames, nFrames)
9041 XPoint * start; XPoint * mid;
9042 XPoint * finish; int factor;
9043 XPoint frames[]; int * nFrames;
9045 int fraction, n, count;
9049 /* Slow in, stepping 1/16th, then 1/8th, ... */
9051 for (n = 0; n < factor; n++)
9053 for (n = 0; n < factor; n++) {
9054 frames[count].x = start->x + (mid->x - start->x) / fraction;
9055 frames[count].y = start->y + (mid->y - start->y) / fraction;
9057 fraction = fraction / 2;
9061 frames[count] = *mid;
9064 /* Slow out, stepping 1/2, then 1/4, ... */
9066 for (n = 0; n < factor; n++) {
9067 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9068 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9070 fraction = fraction * 2;
9075 /* Draw a piece on the screen without disturbing what's there */
9078 SelectGCMask(piece, clip, outline, mask)
9079 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9083 /* Bitmap for piece being moved. */
9084 if (appData.monoMode) {
9085 *mask = *pieceToSolid(piece);
9086 } else if (useImages) {
9088 *mask = xpmMask[piece];
9090 *mask = ximMaskPm[piece];
9093 *mask = *pieceToSolid(piece);
9096 /* GC for piece being moved. Square color doesn't matter, but
9097 since it gets modified we make a copy of the original. */
9099 if (appData.monoMode)
9104 if (appData.monoMode)
9109 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9111 /* Outline only used in mono mode and is not modified */
9113 *outline = bwPieceGC;
9115 *outline = wbPieceGC;
9119 OverlayPiece(piece, clip, outline, dest)
9120 ChessSquare piece; GC clip; GC outline; Drawable dest;
9125 /* Draw solid rectangle which will be clipped to shape of piece */
9126 XFillRectangle(xDisplay, dest, clip,
9127 0, 0, squareSize, squareSize);
9128 if (appData.monoMode)
9129 /* Also draw outline in contrasting color for black
9130 on black / white on white cases */
9131 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9132 0, 0, squareSize, squareSize, 0, 0, 1);
9134 /* Copy the piece */
9139 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9141 0, 0, squareSize, squareSize,
9146 /* Animate the movement of a single piece */
9149 BeginAnimation(anim, piece, startColor, start)
9157 /* The old buffer is initialised with the start square (empty) */
9158 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9159 anim->prevFrame = *start;
9161 /* The piece will be drawn using its own bitmap as a matte */
9162 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9163 XSetClipMask(xDisplay, anim->pieceGC, mask);
9167 AnimationFrame(anim, frame, piece)
9172 XRectangle updates[4];
9177 /* Save what we are about to draw into the new buffer */
9178 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9179 frame->x, frame->y, squareSize, squareSize,
9182 /* Erase bits of the previous frame */
9183 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9184 /* Where the new frame overlapped the previous,
9185 the contents in newBuf are wrong. */
9186 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9187 overlap.x, overlap.y,
9188 overlap.width, overlap.height,
9190 /* Repaint the areas in the old that don't overlap new */
9191 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9192 for (i = 0; i < count; i++)
9193 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9194 updates[i].x - anim->prevFrame.x,
9195 updates[i].y - anim->prevFrame.y,
9196 updates[i].width, updates[i].height,
9197 updates[i].x, updates[i].y);
9199 /* Easy when no overlap */
9200 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9201 0, 0, squareSize, squareSize,
9202 anim->prevFrame.x, anim->prevFrame.y);
9205 /* Save this frame for next time round */
9206 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9207 0, 0, squareSize, squareSize,
9209 anim->prevFrame = *frame;
9211 /* Draw piece over original screen contents, not current,
9212 and copy entire rect. Wipes out overlapping piece images. */
9213 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9214 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9215 0, 0, squareSize, squareSize,
9216 frame->x, frame->y);
9220 EndAnimation (anim, finish)
9224 XRectangle updates[4];
9229 /* The main code will redraw the final square, so we
9230 only need to erase the bits that don't overlap. */
9231 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9232 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9233 for (i = 0; i < count; i++)
9234 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9235 updates[i].x - anim->prevFrame.x,
9236 updates[i].y - anim->prevFrame.y,
9237 updates[i].width, updates[i].height,
9238 updates[i].x, updates[i].y);
9240 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9241 0, 0, squareSize, squareSize,
9242 anim->prevFrame.x, anim->prevFrame.y);
9247 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9249 ChessSquare piece; int startColor;
9250 XPoint * start; XPoint * finish;
9251 XPoint frames[]; int nFrames;
9255 BeginAnimation(anim, piece, startColor, start);
9256 for (n = 0; n < nFrames; n++) {
9257 AnimationFrame(anim, &(frames[n]), piece);
9258 FrameDelay(appData.animSpeed);
9260 EndAnimation(anim, finish);
9263 /* Main control logic for deciding what to animate and how */
9266 AnimateMove(board, fromX, fromY, toX, toY)
9275 XPoint start, finish, mid;
9276 XPoint frames[kFactor * 2 + 1];
9277 int nFrames, startColor, endColor;
9279 /* Are we animating? */
9280 if (!appData.animate || appData.blindfold)
9283 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9284 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9285 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9287 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9288 piece = board[fromY][fromX];
9289 if (piece >= EmptySquare) return;
9294 hop = (piece == WhiteKnight || piece == BlackKnight);
9297 if (appData.debugMode) {
9298 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9299 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9300 piece, fromX, fromY, toX, toY); }
9302 ScreenSquare(fromX, fromY, &start, &startColor);
9303 ScreenSquare(toX, toY, &finish, &endColor);
9306 /* Knight: make diagonal movement then straight */
9307 if (abs(toY - fromY) < abs(toX - fromX)) {
9308 mid.x = start.x + (finish.x - start.x) / 2;
9312 mid.y = start.y + (finish.y - start.y) / 2;
9315 mid.x = start.x + (finish.x - start.x) / 2;
9316 mid.y = start.y + (finish.y - start.y) / 2;
9319 /* Don't use as many frames for very short moves */
9320 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9321 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9323 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9324 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9326 /* Be sure end square is redrawn */
9327 damage[toY][toX] = True;
9331 DragPieceBegin(x, y)
9334 int boardX, boardY, color;
9337 /* Are we animating? */
9338 if (!appData.animateDragging || appData.blindfold)
9341 /* Figure out which square we start in and the
9342 mouse position relative to top left corner. */
9343 BoardSquare(x, y, &boardX, &boardY);
9344 player.startBoardX = boardX;
9345 player.startBoardY = boardY;
9346 ScreenSquare(boardX, boardY, &corner, &color);
9347 player.startSquare = corner;
9348 player.startColor = color;
9349 /* As soon as we start dragging, the piece will jump slightly to
9350 be centered over the mouse pointer. */
9351 player.mouseDelta.x = squareSize/2;
9352 player.mouseDelta.y = squareSize/2;
9353 /* Initialise animation */
9354 player.dragPiece = PieceForSquare(boardX, boardY);
9356 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9357 player.dragActive = True;
9358 BeginAnimation(&player, player.dragPiece, color, &corner);
9359 /* Mark this square as needing to be redrawn. Note that
9360 we don't remove the piece though, since logically (ie
9361 as seen by opponent) the move hasn't been made yet. */
9362 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9363 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9364 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9365 corner.x, corner.y, squareSize, squareSize,
9366 0, 0); // [HGM] zh: unstack in stead of grab
9367 damage[boardY][boardX] = True;
9369 player.dragActive = False;
9379 /* Are we animating? */
9380 if (!appData.animateDragging || appData.blindfold)
9384 if (! player.dragActive)
9386 /* Move piece, maintaining same relative position
9387 of mouse within square */
9388 corner.x = x - player.mouseDelta.x;
9389 corner.y = y - player.mouseDelta.y;
9390 AnimationFrame(&player, &corner, player.dragPiece);
9392 if (appData.highlightDragging) {
9394 BoardSquare(x, y, &boardX, &boardY);
9395 SetHighlights(fromX, fromY, boardX, boardY);
9404 int boardX, boardY, color;
9407 /* Are we animating? */
9408 if (!appData.animateDragging || appData.blindfold)
9412 if (! player.dragActive)
9414 /* Last frame in sequence is square piece is
9415 placed on, which may not match mouse exactly. */
9416 BoardSquare(x, y, &boardX, &boardY);
9417 ScreenSquare(boardX, boardY, &corner, &color);
9418 EndAnimation(&player, &corner);
9420 /* Be sure end square is redrawn */
9421 damage[boardY][boardX] = True;
9423 /* This prevents weird things happening with fast successive
9424 clicks which on my Sun at least can cause motion events
9425 without corresponding press/release. */
9426 player.dragActive = False;
9429 /* Handle expose event while piece being dragged */
9434 if (!player.dragActive || appData.blindfold)
9437 /* What we're doing: logically, the move hasn't been made yet,
9438 so the piece is still in it's original square. But visually
9439 it's being dragged around the board. So we erase the square
9440 that the piece is on and draw it at the last known drag point. */
9441 BlankSquare(player.startSquare.x, player.startSquare.y,
9442 player.startColor, EmptySquare, xBoardWindow);
9443 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9444 damage[player.startBoardY][player.startBoardX] = TRUE;
9448 SetProgramStats( FrontEndProgramStats * stats )
9451 // [HGM] done, but perhaps backend should call this directly?
9452 EngineOutputUpdate( stats );
9455 #include <sys/ioctl.h>
9456 int get_term_width()
9458 int fd, default_width;
9461 default_width = 79; // this is FICS default anyway...
9463 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9465 if (!ioctl(fd, TIOCGSIZE, &win))
9466 default_width = win.ts_cols;
9467 #elif defined(TIOCGWINSZ)
9469 if (!ioctl(fd, TIOCGWINSZ, &win))
9470 default_width = win.ws_col;
9472 return default_width;
9475 void update_ics_width()
9477 static int old_width = 0;
9478 int new_width = get_term_width();
9480 if (old_width != new_width)
9481 ics_printf("set width %d\n", new_width);
9482 old_width = new_width;
9485 void NotifyFrontendLogin()