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 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1901 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1902 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1903 { "GameListPopDown", (XtActionProc) GameListPopDown },
1904 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1905 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1906 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1907 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1908 { "EnginePopDown", (XtActionProc) EnginePopDown },
1909 { "UciPopDown", (XtActionProc) UciPopDown },
1910 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1911 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1912 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1915 char globalTranslations[] =
1916 ":<Key>R: ResignProc() \n \
1917 :<Key>r: ResetProc() \n \
1918 :<Key>g: LoadGameProc() \n \
1919 :<Key>N: LoadNextGameProc() \n \
1920 :<Key>P: LoadPrevGameProc() \n \
1921 :<Key>Q: QuitProc() \n \
1922 :<Key>F: ToEndProc() \n \
1923 :<Key>f: ForwardProc() \n \
1924 :<Key>B: ToStartProc() \n \
1925 :<Key>b: BackwardProc() \n \
1926 :<Key>p: PauseProc() \n \
1927 :<Key>d: DrawProc() \n \
1928 :<Key>t: CallFlagProc() \n \
1929 :<Key>i: Iconify() \n \
1930 :<Key>c: Iconify() \n \
1931 :<Key>v: FlipViewProc() \n \
1932 <KeyDown>Control_L: BackwardProc() \n \
1933 <KeyUp>Control_L: ForwardProc() \n \
1934 <KeyDown>Control_R: BackwardProc() \n \
1935 <KeyUp>Control_R: ForwardProc() \n \
1936 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1937 \"Send to chess program:\",,1) \n \
1938 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1939 \"Send to second chess program:\",,2) \n";
1941 char boardTranslations[] =
1942 "<Btn1Down>: HandleUserMove() \n \
1943 <Btn1Up>: HandleUserMove() \n \
1944 <Btn1Motion>: AnimateUserMove() \n \
1945 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1946 PieceMenuPopup(menuB) \n \
1947 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1948 PieceMenuPopup(menuW) \n \
1949 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1950 PieceMenuPopup(menuW) \n \
1951 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1952 PieceMenuPopup(menuB) \n";
1954 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1955 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1957 char ICSInputTranslations[] =
1958 "<Key>Return: EnterKeyProc() \n";
1960 String xboardResources[] = {
1961 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1962 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1963 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1968 /* Max possible square size */
1969 #define MAXSQSIZE 256
1971 static int xpm_avail[MAXSQSIZE];
1973 #ifdef HAVE_DIR_STRUCT
1975 /* Extract piece size from filename */
1977 xpm_getsize(name, len, ext)
1988 if ((p=strchr(name, '.')) == NULL ||
1989 StrCaseCmp(p+1, ext) != 0)
1995 while (*p && isdigit(*p))
2002 /* Setup xpm_avail */
2004 xpm_getavail(dirname, ext)
2012 for (i=0; i<MAXSQSIZE; ++i)
2015 if (appData.debugMode)
2016 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2018 dir = opendir(dirname);
2021 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2022 programName, dirname);
2026 while ((ent=readdir(dir)) != NULL) {
2027 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2028 if (i > 0 && i < MAXSQSIZE)
2038 xpm_print_avail(fp, ext)
2044 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2045 for (i=1; i<MAXSQSIZE; ++i) {
2051 /* Return XPM piecesize closest to size */
2053 xpm_closest_to(dirname, size, ext)
2059 int sm_diff = MAXSQSIZE;
2063 xpm_getavail(dirname, ext);
2065 if (appData.debugMode)
2066 xpm_print_avail(stderr, ext);
2068 for (i=1; i<MAXSQSIZE; ++i) {
2071 diff = (diff<0) ? -diff : diff;
2072 if (diff < sm_diff) {
2080 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2086 #else /* !HAVE_DIR_STRUCT */
2087 /* If we are on a system without a DIR struct, we can't
2088 read the directory, so we can't collect a list of
2089 filenames, etc., so we can't do any size-fitting. */
2091 xpm_closest_to(dirname, size, ext)
2096 fprintf(stderr, _("\
2097 Warning: No DIR structure found on this system --\n\
2098 Unable to autosize for XPM/XIM pieces.\n\
2099 Please report this error to frankm@hiwaay.net.\n\
2100 Include system type & operating system in message.\n"));
2103 #endif /* HAVE_DIR_STRUCT */
2105 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2106 "magenta", "cyan", "white" };
2110 TextColors textColors[(int)NColorClasses];
2112 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2114 parse_color(str, which)
2118 char *p, buf[100], *d;
2121 if (strlen(str) > 99) /* watch bounds on buf */
2126 for (i=0; i<which; ++i) {
2133 /* Could be looking at something like:
2135 .. in which case we want to stop on a comma also */
2136 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2140 return -1; /* Use default for empty field */
2143 if (which == 2 || isdigit(*p))
2146 while (*p && isalpha(*p))
2151 for (i=0; i<8; ++i) {
2152 if (!StrCaseCmp(buf, cnames[i]))
2153 return which? (i+40) : (i+30);
2155 if (!StrCaseCmp(buf, "default")) return -1;
2157 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2162 parse_cpair(cc, str)
2166 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2167 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2172 /* bg and attr are optional */
2173 textColors[(int)cc].bg = parse_color(str, 1);
2174 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2175 textColors[(int)cc].attr = 0;
2181 /* Arrange to catch delete-window events */
2182 Atom wm_delete_window;
2184 CatchDeleteWindow(Widget w, String procname)
2187 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2188 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2189 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2196 XtSetArg(args[0], XtNiconic, False);
2197 XtSetValues(shellWidget, args, 1);
2199 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2203 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2205 #define BoardSize int
2206 void InitDrawingSizes(BoardSize boardSize, int flags)
2207 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2208 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2210 XtGeometryResult gres;
2213 if(!formWidget) return;
2216 * Enable shell resizing.
2218 shellArgs[0].value = (XtArgVal) &w;
2219 shellArgs[1].value = (XtArgVal) &h;
2220 XtGetValues(shellWidget, shellArgs, 2);
2222 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2223 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2224 XtSetValues(shellWidget, &shellArgs[2], 4);
2226 XtSetArg(args[0], XtNdefaultDistance, &sep);
2227 XtGetValues(formWidget, args, 1);
2229 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2230 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2233 XtSetArg(args[0], XtNwidth, boardWidth);
2234 XtSetArg(args[1], XtNheight, boardHeight);
2235 XtSetValues(boardWidget, args, 2);
2237 timerWidth = (boardWidth - sep) / 2;
2238 XtSetArg(args[0], XtNwidth, timerWidth);
2239 XtSetValues(whiteTimerWidget, args, 1);
2240 XtSetValues(blackTimerWidget, args, 1);
2242 XawFormDoLayout(formWidget, False);
2244 if (appData.titleInWindow) {
2246 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2247 XtSetArg(args[i], XtNheight, &h); i++;
2248 XtGetValues(titleWidget, args, i);
2250 w = boardWidth - 2*bor;
2252 XtSetArg(args[0], XtNwidth, &w);
2253 XtGetValues(menuBarWidget, args, 1);
2254 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2257 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2258 if (gres != XtGeometryYes && appData.debugMode) {
2260 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2261 programName, gres, w, h, wr, hr);
2265 XawFormDoLayout(formWidget, True);
2268 * Inhibit shell resizing.
2270 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2271 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2272 shellArgs[4].value = shellArgs[2].value = w;
2273 shellArgs[5].value = shellArgs[3].value = h;
2274 XtSetValues(shellWidget, &shellArgs[0], 6);
2276 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2279 for(i=0; i<4; i++) {
2281 for(p=0; p<=(int)WhiteKing; p++)
2282 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2283 if(gameInfo.variant == VariantShogi) {
2284 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2285 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2286 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2287 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2288 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2291 if(gameInfo.variant == VariantGothic) {
2292 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2296 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2297 for(p=0; p<=(int)WhiteKing; p++)
2298 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2299 if(gameInfo.variant == VariantShogi) {
2300 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2301 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2302 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2303 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2304 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2307 if(gameInfo.variant == VariantGothic) {
2308 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2314 for(i=0; i<2; i++) {
2316 for(p=0; p<=(int)WhiteKing; p++)
2317 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2318 if(gameInfo.variant == VariantShogi) {
2319 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2320 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2321 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2322 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2323 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2326 if(gameInfo.variant == VariantGothic) {
2327 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2338 void EscapeExpand(char *p, char *q)
2339 { // [HGM] initstring: routine to shape up string arguments
2340 while(*p++ = *q++) if(p[-1] == '\\')
2342 case 'n': p[-1] = '\n'; break;
2343 case 'r': p[-1] = '\r'; break;
2344 case 't': p[-1] = '\t'; break;
2345 case '\\': p[-1] = '\\'; break;
2346 case 0: *p = 0; return;
2347 default: p[-1] = q[-1]; break;
2356 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2357 XSetWindowAttributes window_attributes;
2359 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2360 XrmValue vFrom, vTo;
2361 XtGeometryResult gres;
2364 int forceMono = False;
2367 // [HGM] before anything else, expand any indirection files amongst options
2368 char *argvCopy[1000]; // 1000 seems enough
2369 char newArgs[10000]; // holds actual characters
2372 srandom(time(0)); // [HGM] book: make random truly random
2375 for(i=0; i<argc; i++) {
2376 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2377 //fprintf(stderr, "arg %s\n", argv[i]);
2378 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2380 FILE *f = fopen(argv[i]+1, "rb");
2381 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2382 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2383 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2385 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2386 newArgs[k++] = 0; // terminate current arg
2387 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2388 argvCopy[j++] = newArgs + k; // get ready for next
2390 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2404 setbuf(stdout, NULL);
2405 setbuf(stderr, NULL);
2408 programName = strrchr(argv[0], '/');
2409 if (programName == NULL)
2410 programName = argv[0];
2415 XtSetLanguageProc(NULL, NULL, NULL);
2416 bindtextdomain(PACKAGE, LOCALEDIR);
2417 textdomain(PACKAGE);
2421 XtAppInitialize(&appContext, "XBoard", shellOptions,
2422 XtNumber(shellOptions),
2423 &argc, argv, xboardResources, NULL, 0);
2425 { /* left over command line arguments, print out help and exit.
2426 * Use two columns to print help
2428 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2429 programName, argv[1]);
2431 fprintf(stderr, "Recognized options:\n");
2432 for(i = 0; i < XtNumber(shellOptions); i++)
2434 /* print first column */
2435 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2436 (shellOptions[i].argKind == XrmoptionSepArg
2438 /* print second column and end line */
2439 if (++i < XtNumber(shellOptions))
2441 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2442 shellOptions[i].option,
2443 (shellOptions[i].argKind == XrmoptionSepArg
2448 fprintf(stderr, "\n");
2455 if (p == NULL) p = "/tmp";
2456 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2457 gameCopyFilename = (char*) malloc(i);
2458 gamePasteFilename = (char*) malloc(i);
2459 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2460 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2462 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2463 clientResources, XtNumber(clientResources),
2466 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2467 static char buf[MSG_SIZ];
2468 EscapeExpand(buf, appData.initString);
2469 appData.initString = strdup(buf);
2470 EscapeExpand(buf, appData.secondInitString);
2471 appData.secondInitString = strdup(buf);
2472 EscapeExpand(buf, appData.firstComputerString);
2473 appData.firstComputerString = strdup(buf);
2474 EscapeExpand(buf, appData.secondComputerString);
2475 appData.secondComputerString = strdup(buf);
2478 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2481 if (chdir(chessDir) != 0) {
2482 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2488 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2489 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2490 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2491 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2494 setbuf(debugFP, NULL);
2497 /* [HGM,HR] make sure board size is acceptable */
2498 if(appData.NrFiles > BOARD_SIZE ||
2499 appData.NrRanks > BOARD_SIZE )
2500 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2503 /* This feature does not work; animation needs a rewrite */
2504 appData.highlightDragging = FALSE;
2508 xDisplay = XtDisplay(shellWidget);
2509 xScreen = DefaultScreen(xDisplay);
2510 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2512 gameInfo.variant = StringToVariant(appData.variant);
2513 InitPosition(FALSE);
2516 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2518 if (isdigit(appData.boardSize[0])) {
2519 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2520 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2521 &fontPxlSize, &smallLayout, &tinyLayout);
2523 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2524 programName, appData.boardSize);
2528 /* Find some defaults; use the nearest known size */
2529 SizeDefaults *szd, *nearest;
2530 int distance = 99999;
2531 nearest = szd = sizeDefaults;
2532 while (szd->name != NULL) {
2533 if (abs(szd->squareSize - squareSize) < distance) {
2535 distance = abs(szd->squareSize - squareSize);
2536 if (distance == 0) break;
2540 if (i < 2) lineGap = nearest->lineGap;
2541 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2542 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2543 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2544 if (i < 6) smallLayout = nearest->smallLayout;
2545 if (i < 7) tinyLayout = nearest->tinyLayout;
2548 SizeDefaults *szd = sizeDefaults;
2549 if (*appData.boardSize == NULLCHAR) {
2550 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2551 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2554 if (szd->name == NULL) szd--;
2556 while (szd->name != NULL &&
2557 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2558 if (szd->name == NULL) {
2559 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2560 programName, appData.boardSize);
2564 squareSize = szd->squareSize;
2565 lineGap = szd->lineGap;
2566 clockFontPxlSize = szd->clockFontPxlSize;
2567 coordFontPxlSize = szd->coordFontPxlSize;
2568 fontPxlSize = szd->fontPxlSize;
2569 smallLayout = szd->smallLayout;
2570 tinyLayout = szd->tinyLayout;
2573 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2574 if (strlen(appData.pixmapDirectory) > 0) {
2575 p = ExpandPathName(appData.pixmapDirectory);
2577 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2578 appData.pixmapDirectory);
2581 if (appData.debugMode) {
2582 fprintf(stderr, _("\
2583 XBoard square size (hint): %d\n\
2584 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2586 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2587 if (appData.debugMode) {
2588 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2592 /* [HR] height treated separately (hacked) */
2593 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2594 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2595 if (appData.showJail == 1) {
2596 /* Jail on top and bottom */
2597 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2598 XtSetArg(boardArgs[2], XtNheight,
2599 boardHeight + 2*(lineGap + squareSize));
2600 } else if (appData.showJail == 2) {
2602 XtSetArg(boardArgs[1], XtNwidth,
2603 boardWidth + 2*(lineGap + squareSize));
2604 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2607 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2608 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2612 * Determine what fonts to use.
2614 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2615 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2616 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2617 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2618 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2619 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2620 appData.font = FindFont(appData.font, fontPxlSize);
2621 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2622 countFontStruct = XQueryFont(xDisplay, countFontID);
2623 // appData.font = FindFont(appData.font, fontPxlSize);
2625 xdb = XtDatabase(xDisplay);
2626 XrmPutStringResource(&xdb, "*font", appData.font);
2629 * Detect if there are not enough colors available and adapt.
2631 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2632 appData.monoMode = True;
2635 if (!appData.monoMode) {
2636 vFrom.addr = (caddr_t) appData.lightSquareColor;
2637 vFrom.size = strlen(appData.lightSquareColor);
2638 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2639 if (vTo.addr == NULL) {
2640 appData.monoMode = True;
2643 lightSquareColor = *(Pixel *) vTo.addr;
2646 if (!appData.monoMode) {
2647 vFrom.addr = (caddr_t) appData.darkSquareColor;
2648 vFrom.size = strlen(appData.darkSquareColor);
2649 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2650 if (vTo.addr == NULL) {
2651 appData.monoMode = True;
2654 darkSquareColor = *(Pixel *) vTo.addr;
2657 if (!appData.monoMode) {
2658 vFrom.addr = (caddr_t) appData.whitePieceColor;
2659 vFrom.size = strlen(appData.whitePieceColor);
2660 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2661 if (vTo.addr == NULL) {
2662 appData.monoMode = True;
2665 whitePieceColor = *(Pixel *) vTo.addr;
2668 if (!appData.monoMode) {
2669 vFrom.addr = (caddr_t) appData.blackPieceColor;
2670 vFrom.size = strlen(appData.blackPieceColor);
2671 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2672 if (vTo.addr == NULL) {
2673 appData.monoMode = True;
2676 blackPieceColor = *(Pixel *) vTo.addr;
2680 if (!appData.monoMode) {
2681 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2682 vFrom.size = strlen(appData.highlightSquareColor);
2683 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2684 if (vTo.addr == NULL) {
2685 appData.monoMode = True;
2688 highlightSquareColor = *(Pixel *) vTo.addr;
2692 if (!appData.monoMode) {
2693 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2694 vFrom.size = strlen(appData.premoveHighlightColor);
2695 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2696 if (vTo.addr == NULL) {
2697 appData.monoMode = True;
2700 premoveHighlightColor = *(Pixel *) vTo.addr;
2705 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2708 if (appData.bitmapDirectory == NULL ||
2709 appData.bitmapDirectory[0] == NULLCHAR)
2710 appData.bitmapDirectory = DEF_BITMAP_DIR;
2713 if (appData.lowTimeWarning && !appData.monoMode) {
2714 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2715 vFrom.size = strlen(appData.lowTimeWarningColor);
2716 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2717 if (vTo.addr == NULL)
2718 appData.monoMode = True;
2720 lowTimeWarningColor = *(Pixel *) vTo.addr;
2723 if (appData.monoMode && appData.debugMode) {
2724 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2725 (unsigned long) XWhitePixel(xDisplay, xScreen),
2726 (unsigned long) XBlackPixel(xDisplay, xScreen));
2729 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2730 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2731 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2732 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2733 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2734 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2735 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2736 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2737 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2738 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2740 if (appData.colorize) {
2742 _("%s: can't parse color names; disabling colorization\n"),
2745 appData.colorize = FALSE;
2747 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2748 textColors[ColorNone].attr = 0;
2750 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2756 layoutName = "tinyLayout";
2757 } else if (smallLayout) {
2758 layoutName = "smallLayout";
2760 layoutName = "normalLayout";
2762 /* Outer layoutWidget is there only to provide a name for use in
2763 resources that depend on the layout style */
2765 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2766 layoutArgs, XtNumber(layoutArgs));
2768 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2769 formArgs, XtNumber(formArgs));
2770 XtSetArg(args[0], XtNdefaultDistance, &sep);
2771 XtGetValues(formWidget, args, 1);
2774 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2775 XtSetArg(args[0], XtNtop, XtChainTop);
2776 XtSetArg(args[1], XtNbottom, XtChainTop);
2777 XtSetValues(menuBarWidget, args, 2);
2779 widgetList[j++] = whiteTimerWidget =
2780 XtCreateWidget("whiteTime", labelWidgetClass,
2781 formWidget, timerArgs, XtNumber(timerArgs));
2782 XtSetArg(args[0], XtNfont, clockFontStruct);
2783 XtSetArg(args[1], XtNtop, XtChainTop);
2784 XtSetArg(args[2], XtNbottom, XtChainTop);
2785 XtSetValues(whiteTimerWidget, args, 3);
2787 widgetList[j++] = blackTimerWidget =
2788 XtCreateWidget("blackTime", labelWidgetClass,
2789 formWidget, timerArgs, XtNumber(timerArgs));
2790 XtSetArg(args[0], XtNfont, clockFontStruct);
2791 XtSetArg(args[1], XtNtop, XtChainTop);
2792 XtSetArg(args[2], XtNbottom, XtChainTop);
2793 XtSetValues(blackTimerWidget, args, 3);
2795 if (appData.titleInWindow) {
2796 widgetList[j++] = titleWidget =
2797 XtCreateWidget("title", labelWidgetClass, formWidget,
2798 titleArgs, XtNumber(titleArgs));
2799 XtSetArg(args[0], XtNtop, XtChainTop);
2800 XtSetArg(args[1], XtNbottom, XtChainTop);
2801 XtSetValues(titleWidget, args, 2);
2804 if (appData.showButtonBar) {
2805 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2806 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2807 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2808 XtSetArg(args[2], XtNtop, XtChainTop);
2809 XtSetArg(args[3], XtNbottom, XtChainTop);
2810 XtSetValues(buttonBarWidget, args, 4);
2813 widgetList[j++] = messageWidget =
2814 XtCreateWidget("message", labelWidgetClass, formWidget,
2815 messageArgs, XtNumber(messageArgs));
2816 XtSetArg(args[0], XtNtop, XtChainTop);
2817 XtSetArg(args[1], XtNbottom, XtChainTop);
2818 XtSetValues(messageWidget, args, 2);
2820 widgetList[j++] = boardWidget =
2821 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2822 XtNumber(boardArgs));
2824 XtManageChildren(widgetList, j);
2826 timerWidth = (boardWidth - sep) / 2;
2827 XtSetArg(args[0], XtNwidth, timerWidth);
2828 XtSetValues(whiteTimerWidget, args, 1);
2829 XtSetValues(blackTimerWidget, args, 1);
2831 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2832 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2833 XtGetValues(whiteTimerWidget, args, 2);
2835 if (appData.showButtonBar) {
2836 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2837 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2838 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2842 * formWidget uses these constraints but they are stored
2846 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2847 XtSetValues(menuBarWidget, args, i);
2848 if (appData.titleInWindow) {
2851 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2852 XtSetValues(whiteTimerWidget, args, i);
2854 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2855 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2856 XtSetValues(blackTimerWidget, args, i);
2858 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2859 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2860 XtSetValues(titleWidget, args, i);
2862 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2863 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2864 XtSetValues(messageWidget, args, i);
2865 if (appData.showButtonBar) {
2867 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2868 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2869 XtSetValues(buttonBarWidget, args, i);
2873 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2874 XtSetValues(whiteTimerWidget, args, i);
2876 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2877 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2878 XtSetValues(blackTimerWidget, args, i);
2880 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2881 XtSetValues(titleWidget, args, i);
2883 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2884 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2885 XtSetValues(messageWidget, args, i);
2886 if (appData.showButtonBar) {
2888 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2889 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2890 XtSetValues(buttonBarWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2896 XtSetValues(whiteTimerWidget, args, i);
2898 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2899 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2900 XtSetValues(blackTimerWidget, args, i);
2902 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2903 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2904 XtSetValues(messageWidget, args, i);
2905 if (appData.showButtonBar) {
2907 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2908 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2909 XtSetValues(buttonBarWidget, args, i);
2913 XtSetArg(args[0], XtNfromVert, messageWidget);
2914 XtSetArg(args[1], XtNtop, XtChainTop);
2915 XtSetArg(args[2], XtNbottom, XtChainBottom);
2916 XtSetArg(args[3], XtNleft, XtChainLeft);
2917 XtSetArg(args[4], XtNright, XtChainRight);
2918 XtSetValues(boardWidget, args, 5);
2920 XtRealizeWidget(shellWidget);
2923 * Correct the width of the message and title widgets.
2924 * It is not known why some systems need the extra fudge term.
2925 * The value "2" is probably larger than needed.
2927 XawFormDoLayout(formWidget, False);
2929 #define WIDTH_FUDGE 2
2931 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2932 XtSetArg(args[i], XtNheight, &h); i++;
2933 XtGetValues(messageWidget, args, i);
2934 if (appData.showButtonBar) {
2936 XtSetArg(args[i], XtNwidth, &w); i++;
2937 XtGetValues(buttonBarWidget, args, i);
2938 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2940 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2943 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2944 if (gres != XtGeometryYes && appData.debugMode) {
2945 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2946 programName, gres, w, h, wr, hr);
2949 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2950 /* The size used for the child widget in layout lags one resize behind
2951 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2953 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2954 if (gres != XtGeometryYes && appData.debugMode) {
2955 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2956 programName, gres, w, h, wr, hr);
2959 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2960 XtSetArg(args[1], XtNright, XtChainRight);
2961 XtSetValues(messageWidget, args, 2);
2963 if (appData.titleInWindow) {
2965 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2966 XtSetArg(args[i], XtNheight, &h); i++;
2967 XtGetValues(titleWidget, args, i);
2969 w = boardWidth - 2*bor;
2971 XtSetArg(args[0], XtNwidth, &w);
2972 XtGetValues(menuBarWidget, args, 1);
2973 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2976 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2977 if (gres != XtGeometryYes && appData.debugMode) {
2979 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2980 programName, gres, w, h, wr, hr);
2983 XawFormDoLayout(formWidget, True);
2985 xBoardWindow = XtWindow(boardWidget);
2987 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2988 // not need to go into InitDrawingSizes().
2992 * Create X checkmark bitmap and initialize option menu checks.
2994 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2995 checkmark_bits, checkmark_width, checkmark_height);
2996 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2997 if (appData.alwaysPromoteToQueen) {
2998 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3001 if (appData.animateDragging) {
3002 XtSetValues(XtNameToWidget(menuBarWidget,
3003 "menuOptions.Animate Dragging"),
3006 if (appData.animate) {
3007 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3010 if (appData.autoComment) {
3011 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3014 if (appData.autoCallFlag) {
3015 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3018 if (appData.autoFlipView) {
3019 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3022 if (appData.autoObserve) {
3023 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3026 if (appData.autoRaiseBoard) {
3027 XtSetValues(XtNameToWidget(menuBarWidget,
3028 "menuOptions.Auto Raise Board"), args, 1);
3030 if (appData.autoSaveGames) {
3031 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3034 if (appData.saveGameFile[0] != NULLCHAR) {
3035 /* Can't turn this off from menu */
3036 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3038 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3042 if (appData.blindfold) {
3043 XtSetValues(XtNameToWidget(menuBarWidget,
3044 "menuOptions.Blindfold"), args, 1);
3046 if (appData.flashCount > 0) {
3047 XtSetValues(XtNameToWidget(menuBarWidget,
3048 "menuOptions.Flash Moves"),
3051 if (appData.getMoveList) {
3052 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3056 if (appData.highlightDragging) {
3057 XtSetValues(XtNameToWidget(menuBarWidget,
3058 "menuOptions.Highlight Dragging"),
3062 if (appData.highlightLastMove) {
3063 XtSetValues(XtNameToWidget(menuBarWidget,
3064 "menuOptions.Highlight Last Move"),
3067 if (appData.icsAlarm) {
3068 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3071 if (appData.ringBellAfterMoves) {
3072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3075 if (appData.oldSaveStyle) {
3076 XtSetValues(XtNameToWidget(menuBarWidget,
3077 "menuOptions.Old Save Style"), args, 1);
3079 if (appData.periodicUpdates) {
3080 XtSetValues(XtNameToWidget(menuBarWidget,
3081 "menuOptions.Periodic Updates"), args, 1);
3083 if (appData.ponderNextMove) {
3084 XtSetValues(XtNameToWidget(menuBarWidget,
3085 "menuOptions.Ponder Next Move"), args, 1);
3087 if (appData.popupExitMessage) {
3088 XtSetValues(XtNameToWidget(menuBarWidget,
3089 "menuOptions.Popup Exit Message"), args, 1);
3091 if (appData.popupMoveErrors) {
3092 XtSetValues(XtNameToWidget(menuBarWidget,
3093 "menuOptions.Popup Move Errors"), args, 1);
3095 if (appData.premove) {
3096 XtSetValues(XtNameToWidget(menuBarWidget,
3097 "menuOptions.Premove"), args, 1);
3099 if (appData.quietPlay) {
3100 XtSetValues(XtNameToWidget(menuBarWidget,
3101 "menuOptions.Quiet Play"), args, 1);
3103 if (appData.showCoords) {
3104 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3107 if (appData.hideThinkingFromHuman) {
3108 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3111 if (appData.testLegality) {
3112 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3119 ReadBitmap(&wIconPixmap, "icon_white.bm",
3120 icon_white_bits, icon_white_width, icon_white_height);
3121 ReadBitmap(&bIconPixmap, "icon_black.bm",
3122 icon_black_bits, icon_black_width, icon_black_height);
3123 iconPixmap = wIconPixmap;
3125 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3126 XtSetValues(shellWidget, args, i);
3129 * Create a cursor for the board widget.
3131 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3132 XChangeWindowAttributes(xDisplay, xBoardWindow,
3133 CWCursor, &window_attributes);
3136 * Inhibit shell resizing.
3138 shellArgs[0].value = (XtArgVal) &w;
3139 shellArgs[1].value = (XtArgVal) &h;
3140 XtGetValues(shellWidget, shellArgs, 2);
3141 shellArgs[4].value = shellArgs[2].value = w;
3142 shellArgs[5].value = shellArgs[3].value = h;
3143 XtSetValues(shellWidget, &shellArgs[2], 4);
3144 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3145 marginH = h - boardHeight;
3147 CatchDeleteWindow(shellWidget, "QuitProc");
3152 if (appData.bitmapDirectory[0] != NULLCHAR) {
3159 /* Create regular pieces */
3160 if (!useImages) CreatePieces();
3165 if (appData.animate || appData.animateDragging)
3168 XtAugmentTranslations(formWidget,
3169 XtParseTranslationTable(globalTranslations));
3170 XtAugmentTranslations(boardWidget,
3171 XtParseTranslationTable(boardTranslations));
3172 XtAugmentTranslations(whiteTimerWidget,
3173 XtParseTranslationTable(whiteTranslations));
3174 XtAugmentTranslations(blackTimerWidget,
3175 XtParseTranslationTable(blackTranslations));
3177 /* Why is the following needed on some versions of X instead
3178 * of a translation? */
3179 XtAddEventHandler(boardWidget, ExposureMask, False,
3180 (XtEventHandler) EventProc, NULL);
3185 if (errorExitStatus == -1) {
3186 if (appData.icsActive) {
3187 /* We now wait until we see "login:" from the ICS before
3188 sending the logon script (problems with timestamp otherwise) */
3189 /*ICSInitScript();*/
3190 if (appData.icsInputBox) ICSInputBoxPopUp();
3193 signal(SIGINT, IntSigHandler);
3194 signal(SIGTERM, IntSigHandler);
3195 if (*appData.cmailGameName != NULLCHAR) {
3196 signal(SIGUSR1, CmailSigHandler);
3199 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3202 XtAppMainLoop(appContext);
3203 if (appData.debugMode) fclose(debugFP); // [DM] debug
3210 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3211 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3213 unlink(gameCopyFilename);
3214 unlink(gamePasteFilename);
3217 RETSIGTYPE TermSizeSigHandler(int sig)
3230 CmailSigHandler(sig)
3236 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3238 /* Activate call-back function CmailSigHandlerCallBack() */
3239 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3241 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3245 CmailSigHandlerCallBack(isr, closure, message, count, error)
3253 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3255 /**** end signal code ****/
3265 f = fopen(appData.icsLogon, "r");
3271 strcat(buf, appData.icsLogon);
3272 f = fopen(buf, "r");
3276 ProcessICSInitScript(f);
3283 EditCommentPopDown();
3294 SetMenuEnables(enab)
3298 if (!menuBarWidget) return;
3299 while (enab->name != NULL) {
3300 w = XtNameToWidget(menuBarWidget, enab->name);
3302 DisplayError(enab->name, 0);
3304 XtSetSensitive(w, enab->value);
3310 Enables icsEnables[] = {
3311 { "menuFile.Mail Move", False },
3312 { "menuFile.Reload CMail Message", False },
3313 { "menuMode.Machine Black", False },
3314 { "menuMode.Machine White", False },
3315 { "menuMode.Analysis Mode", False },
3316 { "menuMode.Analyze File", False },
3317 { "menuMode.Two Machines", False },
3319 { "menuHelp.Hint", False },
3320 { "menuHelp.Book", False },
3321 { "menuStep.Move Now", False },
3322 { "menuOptions.Periodic Updates", False },
3323 { "menuOptions.Hide Thinking", False },
3324 { "menuOptions.Ponder Next Move", False },
3329 Enables ncpEnables[] = {
3330 { "menuFile.Mail Move", False },
3331 { "menuFile.Reload CMail Message", False },
3332 { "menuMode.Machine White", False },
3333 { "menuMode.Machine Black", False },
3334 { "menuMode.Analysis Mode", False },
3335 { "menuMode.Analyze File", False },
3336 { "menuMode.Two Machines", False },
3337 { "menuMode.ICS Client", False },
3338 { "menuMode.ICS Input Box", False },
3339 { "Action", False },
3340 { "menuStep.Revert", False },
3341 { "menuStep.Move Now", False },
3342 { "menuStep.Retract Move", False },
3343 { "menuOptions.Auto Comment", False },
3344 { "menuOptions.Auto Flag", False },
3345 { "menuOptions.Auto Flip View", False },
3346 { "menuOptions.Auto Observe", False },
3347 { "menuOptions.Auto Raise Board", False },
3348 { "menuOptions.Get Move List", False },
3349 { "menuOptions.ICS Alarm", False },
3350 { "menuOptions.Move Sound", False },
3351 { "menuOptions.Quiet Play", False },
3352 { "menuOptions.Hide Thinking", False },
3353 { "menuOptions.Periodic Updates", False },
3354 { "menuOptions.Ponder Next Move", False },
3355 { "menuHelp.Hint", False },
3356 { "menuHelp.Book", False },
3360 Enables gnuEnables[] = {
3361 { "menuMode.ICS Client", False },
3362 { "menuMode.ICS Input Box", False },
3363 { "menuAction.Accept", False },
3364 { "menuAction.Decline", False },
3365 { "menuAction.Rematch", False },
3366 { "menuAction.Adjourn", False },
3367 { "menuAction.Stop Examining", False },
3368 { "menuAction.Stop Observing", False },
3369 { "menuStep.Revert", False },
3370 { "menuOptions.Auto Comment", False },
3371 { "menuOptions.Auto Observe", False },
3372 { "menuOptions.Auto Raise Board", False },
3373 { "menuOptions.Get Move List", False },
3374 { "menuOptions.Premove", False },
3375 { "menuOptions.Quiet Play", False },
3377 /* The next two options rely on SetCmailMode being called *after* */
3378 /* SetGNUMode so that when GNU is being used to give hints these */
3379 /* menu options are still available */
3381 { "menuFile.Mail Move", False },
3382 { "menuFile.Reload CMail Message", False },
3386 Enables cmailEnables[] = {
3388 { "menuAction.Call Flag", False },
3389 { "menuAction.Draw", True },
3390 { "menuAction.Adjourn", False },
3391 { "menuAction.Abort", False },
3392 { "menuAction.Stop Observing", False },
3393 { "menuAction.Stop Examining", False },
3394 { "menuFile.Mail Move", True },
3395 { "menuFile.Reload CMail Message", True },
3399 Enables trainingOnEnables[] = {
3400 { "menuMode.Edit Comment", False },
3401 { "menuMode.Pause", False },
3402 { "menuStep.Forward", False },
3403 { "menuStep.Backward", False },
3404 { "menuStep.Forward to End", False },
3405 { "menuStep.Back to Start", False },
3406 { "menuStep.Move Now", False },
3407 { "menuStep.Truncate Game", False },
3411 Enables trainingOffEnables[] = {
3412 { "menuMode.Edit Comment", True },
3413 { "menuMode.Pause", True },
3414 { "menuStep.Forward", True },
3415 { "menuStep.Backward", True },
3416 { "menuStep.Forward to End", True },
3417 { "menuStep.Back to Start", True },
3418 { "menuStep.Move Now", True },
3419 { "menuStep.Truncate Game", True },
3423 Enables machineThinkingEnables[] = {
3424 { "menuFile.Load Game", False },
3425 { "menuFile.Load Next Game", False },
3426 { "menuFile.Load Previous Game", False },
3427 { "menuFile.Reload Same Game", False },
3428 { "menuFile.Paste Game", False },
3429 { "menuFile.Load Position", False },
3430 { "menuFile.Load Next Position", False },
3431 { "menuFile.Load Previous Position", False },
3432 { "menuFile.Reload Same Position", False },
3433 { "menuFile.Paste Position", False },
3434 { "menuMode.Machine White", False },
3435 { "menuMode.Machine Black", False },
3436 { "menuMode.Two Machines", False },
3437 { "menuStep.Retract Move", False },
3441 Enables userThinkingEnables[] = {
3442 { "menuFile.Load Game", True },
3443 { "menuFile.Load Next Game", True },
3444 { "menuFile.Load Previous Game", True },
3445 { "menuFile.Reload Same Game", True },
3446 { "menuFile.Paste Game", True },
3447 { "menuFile.Load Position", True },
3448 { "menuFile.Load Next Position", True },
3449 { "menuFile.Load Previous Position", True },
3450 { "menuFile.Reload Same Position", True },
3451 { "menuFile.Paste Position", True },
3452 { "menuMode.Machine White", True },
3453 { "menuMode.Machine Black", True },
3454 { "menuMode.Two Machines", True },
3455 { "menuStep.Retract Move", True },
3461 SetMenuEnables(icsEnables);
3464 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3465 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3472 SetMenuEnables(ncpEnables);
3478 SetMenuEnables(gnuEnables);
3484 SetMenuEnables(cmailEnables);
3490 SetMenuEnables(trainingOnEnables);
3491 if (appData.showButtonBar) {
3492 XtSetSensitive(buttonBarWidget, False);
3498 SetTrainingModeOff()
3500 SetMenuEnables(trainingOffEnables);
3501 if (appData.showButtonBar) {
3502 XtSetSensitive(buttonBarWidget, True);
3507 SetUserThinkingEnables()
3509 if (appData.noChessProgram) return;
3510 SetMenuEnables(userThinkingEnables);
3514 SetMachineThinkingEnables()
3516 if (appData.noChessProgram) return;
3517 SetMenuEnables(machineThinkingEnables);
3519 case MachinePlaysBlack:
3520 case MachinePlaysWhite:
3521 case TwoMachinesPlay:
3522 XtSetSensitive(XtNameToWidget(menuBarWidget,
3523 ModeToWidgetName(gameMode)), True);
3530 #define Abs(n) ((n)<0 ? -(n) : (n))
3533 * Find a font that matches "pattern" that is as close as
3534 * possible to the targetPxlSize. Prefer fonts that are k
3535 * pixels smaller to fonts that are k pixels larger. The
3536 * pattern must be in the X Consortium standard format,
3537 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3538 * The return value should be freed with XtFree when no
3541 char *FindFont(pattern, targetPxlSize)
3545 char **fonts, *p, *best, *scalable, *scalableTail;
3546 int i, j, nfonts, minerr, err, pxlSize;
3549 char **missing_list;
3551 char *def_string, *base_fnt_lst, strInt[3];
3553 XFontStruct **fnt_list;
3555 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3556 sprintf(strInt, "%d", targetPxlSize);
3557 p = strstr(pattern, "--");
3558 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3559 strcat(base_fnt_lst, strInt);
3560 strcat(base_fnt_lst, strchr(p + 2, '-'));
3562 if ((fntSet = XCreateFontSet(xDisplay,
3566 &def_string)) == NULL) {
3568 fprintf(stderr, _("Unable to create font set.\n"));
3572 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3574 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3576 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3577 programName, pattern);
3585 for (i=0; i<nfonts; i++) {
3588 if (*p != '-') continue;
3590 if (*p == NULLCHAR) break;
3591 if (*p++ == '-') j++;
3593 if (j < 7) continue;
3596 scalable = fonts[i];
3599 err = pxlSize - targetPxlSize;
3600 if (Abs(err) < Abs(minerr) ||
3601 (minerr > 0 && err < 0 && -err == minerr)) {
3607 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3608 /* If the error is too big and there is a scalable font,
3609 use the scalable font. */
3610 int headlen = scalableTail - scalable;
3611 p = (char *) XtMalloc(strlen(scalable) + 10);
3612 while (isdigit(*scalableTail)) scalableTail++;
3613 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3615 p = (char *) XtMalloc(strlen(best) + 1);
3618 if (appData.debugMode) {
3619 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3620 pattern, targetPxlSize, p);
3623 if (missing_count > 0)
3624 XFreeStringList(missing_list);
3625 XFreeFontSet(xDisplay, fntSet);
3627 XFreeFontNames(fonts);
3634 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3635 | GCBackground | GCFunction | GCPlaneMask;
3636 XGCValues gc_values;
3639 gc_values.plane_mask = AllPlanes;
3640 gc_values.line_width = lineGap;
3641 gc_values.line_style = LineSolid;
3642 gc_values.function = GXcopy;
3644 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3645 gc_values.background = XBlackPixel(xDisplay, xScreen);
3646 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3648 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3649 gc_values.background = XWhitePixel(xDisplay, xScreen);
3650 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3651 XSetFont(xDisplay, coordGC, coordFontID);
3653 // [HGM] make font for holdings counts (white on black0
3654 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3655 gc_values.background = XBlackPixel(xDisplay, xScreen);
3656 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3657 XSetFont(xDisplay, countGC, countFontID);
3659 if (appData.monoMode) {
3660 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3661 gc_values.background = XWhitePixel(xDisplay, xScreen);
3662 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3664 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3665 gc_values.background = XBlackPixel(xDisplay, xScreen);
3666 lightSquareGC = wbPieceGC
3667 = XtGetGC(shellWidget, value_mask, &gc_values);
3669 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3670 gc_values.background = XWhitePixel(xDisplay, xScreen);
3671 darkSquareGC = bwPieceGC
3672 = XtGetGC(shellWidget, value_mask, &gc_values);
3674 if (DefaultDepth(xDisplay, xScreen) == 1) {
3675 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3676 gc_values.function = GXcopyInverted;
3677 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3678 gc_values.function = GXcopy;
3679 if (XBlackPixel(xDisplay, xScreen) == 1) {
3680 bwPieceGC = darkSquareGC;
3681 wbPieceGC = copyInvertedGC;
3683 bwPieceGC = copyInvertedGC;
3684 wbPieceGC = lightSquareGC;
3688 gc_values.foreground = highlightSquareColor;
3689 gc_values.background = highlightSquareColor;
3690 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = premoveHighlightColor;
3693 gc_values.background = premoveHighlightColor;
3694 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3696 gc_values.foreground = lightSquareColor;
3697 gc_values.background = darkSquareColor;
3698 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = darkSquareColor;
3701 gc_values.background = lightSquareColor;
3702 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3704 gc_values.foreground = jailSquareColor;
3705 gc_values.background = jailSquareColor;
3706 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3708 gc_values.foreground = whitePieceColor;
3709 gc_values.background = darkSquareColor;
3710 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = whitePieceColor;
3713 gc_values.background = lightSquareColor;
3714 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = whitePieceColor;
3717 gc_values.background = jailSquareColor;
3718 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3720 gc_values.foreground = blackPieceColor;
3721 gc_values.background = darkSquareColor;
3722 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3724 gc_values.foreground = blackPieceColor;
3725 gc_values.background = lightSquareColor;
3726 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3728 gc_values.foreground = blackPieceColor;
3729 gc_values.background = jailSquareColor;
3730 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3734 void loadXIM(xim, xmask, filename, dest, mask)
3747 fp = fopen(filename, "rb");
3749 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3756 for (y=0; y<h; ++y) {
3757 for (x=0; x<h; ++x) {
3762 XPutPixel(xim, x, y, blackPieceColor);
3764 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3767 XPutPixel(xim, x, y, darkSquareColor);
3769 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3772 XPutPixel(xim, x, y, whitePieceColor);
3774 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3777 XPutPixel(xim, x, y, lightSquareColor);
3779 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3785 /* create Pixmap of piece */
3786 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3788 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3791 /* create Pixmap of clipmask
3792 Note: We assume the white/black pieces have the same
3793 outline, so we make only 6 masks. This is okay
3794 since the XPM clipmask routines do the same. */
3796 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3798 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3801 /* now create the 1-bit version */
3802 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3805 values.foreground = 1;
3806 values.background = 0;
3808 /* Don't use XtGetGC, not read only */
3809 maskGC = XCreateGC(xDisplay, *mask,
3810 GCForeground | GCBackground, &values);
3811 XCopyPlane(xDisplay, temp, *mask, maskGC,
3812 0, 0, squareSize, squareSize, 0, 0, 1);
3813 XFreePixmap(xDisplay, temp);
3818 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3820 void CreateXIMPieces()
3825 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3830 /* The XSynchronize calls were copied from CreatePieces.
3831 Not sure if needed, but can't hurt */
3832 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3835 /* temp needed by loadXIM() */
3836 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3837 0, 0, ss, ss, AllPlanes, XYPixmap);
3839 if (strlen(appData.pixmapDirectory) == 0) {
3843 if (appData.monoMode) {
3844 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3848 fprintf(stderr, _("\nLoading XIMs...\n"));
3850 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3851 fprintf(stderr, "%d", piece+1);
3852 for (kind=0; kind<4; kind++) {
3853 fprintf(stderr, ".");
3854 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3855 ExpandPathName(appData.pixmapDirectory),
3856 piece <= (int) WhiteKing ? "" : "w",
3857 pieceBitmapNames[piece],
3859 ximPieceBitmap[kind][piece] =
3860 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3861 0, 0, ss, ss, AllPlanes, XYPixmap);
3862 if (appData.debugMode)
3863 fprintf(stderr, _("(File:%s:) "), buf);
3864 loadXIM(ximPieceBitmap[kind][piece],
3866 &(xpmPieceBitmap2[kind][piece]),
3867 &(ximMaskPm2[piece]));
3868 if(piece <= (int)WhiteKing)
3869 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3871 fprintf(stderr," ");
3873 /* Load light and dark squares */
3874 /* If the LSQ and DSQ pieces don't exist, we will
3875 draw them with solid squares. */
3876 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3877 if (access(buf, 0) != 0) {
3881 fprintf(stderr, _("light square "));
3883 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3884 0, 0, ss, ss, AllPlanes, XYPixmap);
3885 if (appData.debugMode)
3886 fprintf(stderr, _("(File:%s:) "), buf);
3888 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3889 fprintf(stderr, _("dark square "));
3890 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3891 ExpandPathName(appData.pixmapDirectory), ss);
3892 if (appData.debugMode)
3893 fprintf(stderr, _("(File:%s:) "), buf);
3895 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3896 0, 0, ss, ss, AllPlanes, XYPixmap);
3897 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3898 xpmJailSquare = xpmLightSquare;
3900 fprintf(stderr, _("Done.\n"));
3902 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3906 void CreateXPMPieces()
3910 u_int ss = squareSize;
3912 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3913 XpmColorSymbol symbols[4];
3915 /* The XSynchronize calls were copied from CreatePieces.
3916 Not sure if needed, but can't hurt */
3917 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3919 /* Setup translations so piece colors match square colors */
3920 symbols[0].name = "light_piece";
3921 symbols[0].value = appData.whitePieceColor;
3922 symbols[1].name = "dark_piece";
3923 symbols[1].value = appData.blackPieceColor;
3924 symbols[2].name = "light_square";
3925 symbols[2].value = appData.lightSquareColor;
3926 symbols[3].name = "dark_square";
3927 symbols[3].value = appData.darkSquareColor;
3929 attr.valuemask = XpmColorSymbols;
3930 attr.colorsymbols = symbols;
3931 attr.numsymbols = 4;
3933 if (appData.monoMode) {
3934 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3938 if (strlen(appData.pixmapDirectory) == 0) {
3939 XpmPieces* pieces = builtInXpms;
3942 while (pieces->size != squareSize && pieces->size) pieces++;
3943 if (!pieces->size) {
3944 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3947 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3948 for (kind=0; kind<4; kind++) {
3950 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3951 pieces->xpm[piece][kind],
3952 &(xpmPieceBitmap2[kind][piece]),
3953 NULL, &attr)) != 0) {
3954 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3958 if(piece <= (int) WhiteKing)
3959 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3963 xpmJailSquare = xpmLightSquare;
3967 fprintf(stderr, _("\nLoading XPMs...\n"));
3970 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3971 fprintf(stderr, "%d ", piece+1);
3972 for (kind=0; kind<4; kind++) {
3973 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3974 ExpandPathName(appData.pixmapDirectory),
3975 piece > (int) WhiteKing ? "w" : "",
3976 pieceBitmapNames[piece],
3978 if (appData.debugMode) {
3979 fprintf(stderr, _("(File:%s:) "), buf);
3981 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3982 &(xpmPieceBitmap2[kind][piece]),
3983 NULL, &attr)) != 0) {
3984 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3985 // [HGM] missing: read of unorthodox piece failed; substitute King.
3986 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3987 ExpandPathName(appData.pixmapDirectory),
3989 if (appData.debugMode) {
3990 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3992 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3993 &(xpmPieceBitmap2[kind][piece]),
3997 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4002 if(piece <= (int) WhiteKing)
4003 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4006 /* Load light and dark squares */
4007 /* If the LSQ and DSQ pieces don't exist, we will
4008 draw them with solid squares. */
4009 fprintf(stderr, _("light square "));
4010 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4011 if (access(buf, 0) != 0) {
4015 if (appData.debugMode)
4016 fprintf(stderr, _("(File:%s:) "), buf);
4018 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4019 &xpmLightSquare, NULL, &attr)) != 0) {
4020 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4023 fprintf(stderr, _("dark square "));
4024 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4025 ExpandPathName(appData.pixmapDirectory), ss);
4026 if (appData.debugMode) {
4027 fprintf(stderr, _("(File:%s:) "), buf);
4029 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4030 &xpmDarkSquare, NULL, &attr)) != 0) {
4031 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4035 xpmJailSquare = xpmLightSquare;
4036 fprintf(stderr, _("Done.\n"));
4038 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4041 #endif /* HAVE_LIBXPM */
4044 /* No built-in bitmaps */
4049 u_int ss = squareSize;
4051 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4054 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4055 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4056 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4057 pieceBitmapNames[piece],
4058 ss, kind == SOLID ? 's' : 'o');
4059 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4060 if(piece <= (int)WhiteKing)
4061 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4065 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4069 /* With built-in bitmaps */
4072 BuiltInBits* bib = builtInBits;
4075 u_int ss = squareSize;
4077 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4080 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4082 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4083 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4084 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4085 pieceBitmapNames[piece],
4086 ss, kind == SOLID ? 's' : 'o');
4087 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4088 bib->bits[kind][piece], ss, ss);
4089 if(piece <= (int)WhiteKing)
4090 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4094 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4099 void ReadBitmap(pm, name, bits, wreq, hreq)
4102 unsigned char bits[];
4108 char msg[MSG_SIZ], fullname[MSG_SIZ];
4110 if (*appData.bitmapDirectory != NULLCHAR) {
4111 strcpy(fullname, appData.bitmapDirectory);
4112 strcat(fullname, "/");
4113 strcat(fullname, name);
4114 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4115 &w, &h, pm, &x_hot, &y_hot);
4116 fprintf(stderr, "load %s\n", name);
4117 if (errcode != BitmapSuccess) {
4119 case BitmapOpenFailed:
4120 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4122 case BitmapFileInvalid:
4123 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4125 case BitmapNoMemory:
4126 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4130 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4134 fprintf(stderr, _("%s: %s...using built-in\n"),
4136 } else if (w != wreq || h != hreq) {
4138 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4139 programName, fullname, w, h, wreq, hreq);
4145 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4154 if (lineGap == 0) return;
4156 /* [HR] Split this into 2 loops for non-square boards. */
4158 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4159 gridSegments[i].x1 = 0;
4160 gridSegments[i].x2 =
4161 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4162 gridSegments[i].y1 = gridSegments[i].y2
4163 = lineGap / 2 + (i * (squareSize + lineGap));
4166 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4167 gridSegments[j + i].y1 = 0;
4168 gridSegments[j + i].y2 =
4169 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4170 gridSegments[j + i].x1 = gridSegments[j + i].x2
4171 = lineGap / 2 + (j * (squareSize + lineGap));
4175 static void MenuBarSelect(w, addr, index)
4180 XtActionProc proc = (XtActionProc) addr;
4182 (proc)(NULL, NULL, NULL, NULL);
4185 void CreateMenuBarPopup(parent, name, mb)
4195 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4198 XtSetArg(args[j], XtNleftMargin, 20); j++;
4199 XtSetArg(args[j], XtNrightMargin, 20); j++;
4201 while (mi->string != NULL) {
4202 if (strcmp(mi->string, "----") == 0) {
4203 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4206 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4207 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4209 XtAddCallback(entry, XtNcallback,
4210 (XtCallbackProc) MenuBarSelect,
4211 (caddr_t) mi->proc);
4217 Widget CreateMenuBar(mb)
4221 Widget anchor, menuBar;
4223 char menuName[MSG_SIZ];
4226 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4227 XtSetArg(args[j], XtNvSpace, 0); j++;
4228 XtSetArg(args[j], XtNborderWidth, 0); j++;
4229 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4230 formWidget, args, j);
4232 while (mb->name != NULL) {
4233 strcpy(menuName, "menu");
4234 strcat(menuName, mb->name);
4236 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4239 shortName[0] = _(mb->name)[0];
4240 shortName[1] = NULLCHAR;
4241 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4244 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4247 XtSetArg(args[j], XtNborderWidth, 0); j++;
4248 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4250 CreateMenuBarPopup(menuBar, menuName, mb);
4256 Widget CreateButtonBar(mi)
4260 Widget button, buttonBar;
4264 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4266 XtSetArg(args[j], XtNhSpace, 0); j++;
4268 XtSetArg(args[j], XtNborderWidth, 0); j++;
4269 XtSetArg(args[j], XtNvSpace, 0); j++;
4270 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4271 formWidget, args, j);
4273 while (mi->string != NULL) {
4276 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4277 XtSetArg(args[j], XtNborderWidth, 0); j++;
4279 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4280 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4281 buttonBar, args, j);
4282 XtAddCallback(button, XtNcallback,
4283 (XtCallbackProc) MenuBarSelect,
4284 (caddr_t) mi->proc);
4291 CreatePieceMenu(name, color)
4298 ChessSquare selection;
4300 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4301 boardWidget, args, 0);
4303 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4304 String item = pieceMenuStrings[color][i];
4306 if (strcmp(item, "----") == 0) {
4307 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4310 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4311 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4313 selection = pieceMenuTranslation[color][i];
4314 XtAddCallback(entry, XtNcallback,
4315 (XtCallbackProc) PieceMenuSelect,
4316 (caddr_t) selection);
4317 if (selection == WhitePawn || selection == BlackPawn) {
4318 XtSetArg(args[0], XtNpopupOnEntry, entry);
4319 XtSetValues(menu, args, 1);
4332 ChessSquare selection;
4334 whitePieceMenu = CreatePieceMenu("menuW", 0);
4335 blackPieceMenu = CreatePieceMenu("menuB", 1);
4337 XtRegisterGrabAction(PieceMenuPopup, True,
4338 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4339 GrabModeAsync, GrabModeAsync);
4341 XtSetArg(args[0], XtNlabel, _("Drop"));
4342 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4343 boardWidget, args, 1);
4344 for (i = 0; i < DROP_MENU_SIZE; i++) {
4345 String item = dropMenuStrings[i];
4347 if (strcmp(item, "----") == 0) {
4348 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4351 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4352 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4354 selection = dropMenuTranslation[i];
4355 XtAddCallback(entry, XtNcallback,
4356 (XtCallbackProc) DropMenuSelect,
4357 (caddr_t) selection);
4362 void SetupDropMenu()
4370 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4371 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4372 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4373 dmEnables[i].piece);
4374 XtSetSensitive(entry, p != NULL || !appData.testLegality
4375 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4376 && !appData.icsActive));
4378 while (p && *p++ == dmEnables[i].piece) count++;
4379 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4381 XtSetArg(args[j], XtNlabel, label); j++;
4382 XtSetValues(entry, args, j);
4386 void PieceMenuPopup(w, event, params, num_params)
4390 Cardinal *num_params;
4393 if (event->type != ButtonPress) return;
4394 if (errorUp) ErrorPopDown();
4398 whichMenu = params[0];
4400 case IcsPlayingWhite:
4401 case IcsPlayingBlack:
4403 case MachinePlaysWhite:
4404 case MachinePlaysBlack:
4405 if (appData.testLegality &&
4406 gameInfo.variant != VariantBughouse &&
4407 gameInfo.variant != VariantCrazyhouse) return;
4409 whichMenu = "menuD";
4415 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4416 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4417 pmFromX = pmFromY = -1;
4421 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4423 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4425 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4428 static void PieceMenuSelect(w, piece, junk)
4433 if (pmFromX < 0 || pmFromY < 0) return;
4434 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4437 static void DropMenuSelect(w, piece, junk)
4442 if (pmFromX < 0 || pmFromY < 0) return;
4443 DropMenuEvent(piece, pmFromX, pmFromY);
4446 void WhiteClock(w, event, prms, nprms)
4452 if (gameMode == EditPosition || gameMode == IcsExamining) {
4453 SetWhiteToPlayEvent();
4454 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4459 void BlackClock(w, event, prms, nprms)
4465 if (gameMode == EditPosition || gameMode == IcsExamining) {
4466 SetBlackToPlayEvent();
4467 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4474 * If the user selects on a border boundary, return -1; if off the board,
4475 * return -2. Otherwise map the event coordinate to the square.
4477 int EventToSquare(x, limit)
4485 if ((x % (squareSize + lineGap)) >= squareSize)
4487 x /= (squareSize + lineGap);
4493 static void do_flash_delay(msec)
4499 static void drawHighlight(file, rank, gc)
4505 if (lineGap == 0 || appData.blindfold) return;
4508 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4509 (squareSize + lineGap);
4510 y = lineGap/2 + rank * (squareSize + lineGap);
4512 x = lineGap/2 + file * (squareSize + lineGap);
4513 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4514 (squareSize + lineGap);
4517 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4518 squareSize+lineGap, squareSize+lineGap);
4521 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4522 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4525 SetHighlights(fromX, fromY, toX, toY)
4526 int fromX, fromY, toX, toY;
4528 if (hi1X != fromX || hi1Y != fromY) {
4529 if (hi1X >= 0 && hi1Y >= 0) {
4530 drawHighlight(hi1X, hi1Y, lineGC);
4532 if (fromX >= 0 && fromY >= 0) {
4533 drawHighlight(fromX, fromY, highlineGC);
4536 if (hi2X != toX || hi2Y != toY) {
4537 if (hi2X >= 0 && hi2Y >= 0) {
4538 drawHighlight(hi2X, hi2Y, lineGC);
4540 if (toX >= 0 && toY >= 0) {
4541 drawHighlight(toX, toY, highlineGC);
4553 SetHighlights(-1, -1, -1, -1);
4558 SetPremoveHighlights(fromX, fromY, toX, toY)
4559 int fromX, fromY, toX, toY;
4561 if (pm1X != fromX || pm1Y != fromY) {
4562 if (pm1X >= 0 && pm1Y >= 0) {
4563 drawHighlight(pm1X, pm1Y, lineGC);
4565 if (fromX >= 0 && fromY >= 0) {
4566 drawHighlight(fromX, fromY, prelineGC);
4569 if (pm2X != toX || pm2Y != toY) {
4570 if (pm2X >= 0 && pm2Y >= 0) {
4571 drawHighlight(pm2X, pm2Y, lineGC);
4573 if (toX >= 0 && toY >= 0) {
4574 drawHighlight(toX, toY, prelineGC);
4584 ClearPremoveHighlights()
4586 SetPremoveHighlights(-1, -1, -1, -1);
4589 static void BlankSquare(x, y, color, piece, dest)
4594 if (useImages && useImageSqs) {
4598 pm = xpmLightSquare;
4603 case 2: /* neutral */
4608 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4609 squareSize, squareSize, x, y);
4619 case 2: /* neutral */
4624 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4629 I split out the routines to draw a piece so that I could
4630 make a generic flash routine.
4632 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4634 int square_color, x, y;
4637 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4638 switch (square_color) {
4640 case 2: /* neutral */
4642 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4643 ? *pieceToOutline(piece)
4644 : *pieceToSolid(piece),
4645 dest, bwPieceGC, 0, 0,
4646 squareSize, squareSize, x, y);
4649 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4650 ? *pieceToSolid(piece)
4651 : *pieceToOutline(piece),
4652 dest, wbPieceGC, 0, 0,
4653 squareSize, squareSize, x, y);
4658 static void monoDrawPiece(piece, square_color, x, y, dest)
4660 int square_color, x, y;
4663 switch (square_color) {
4665 case 2: /* neutral */
4667 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4668 ? *pieceToOutline(piece)
4669 : *pieceToSolid(piece),
4670 dest, bwPieceGC, 0, 0,
4671 squareSize, squareSize, x, y, 1);
4674 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4675 ? *pieceToSolid(piece)
4676 : *pieceToOutline(piece),
4677 dest, wbPieceGC, 0, 0,
4678 squareSize, squareSize, x, y, 1);
4683 static void colorDrawPiece(piece, square_color, x, y, dest)
4685 int square_color, x, y;
4688 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4689 switch (square_color) {
4691 XCopyPlane(xDisplay, *pieceToSolid(piece),
4692 dest, (int) piece < (int) BlackPawn
4693 ? wlPieceGC : blPieceGC, 0, 0,
4694 squareSize, squareSize, x, y, 1);
4697 XCopyPlane(xDisplay, *pieceToSolid(piece),
4698 dest, (int) piece < (int) BlackPawn
4699 ? wdPieceGC : bdPieceGC, 0, 0,
4700 squareSize, squareSize, x, y, 1);
4702 case 2: /* neutral */
4704 XCopyPlane(xDisplay, *pieceToSolid(piece),
4705 dest, (int) piece < (int) BlackPawn
4706 ? wjPieceGC : bjPieceGC, 0, 0,
4707 squareSize, squareSize, x, y, 1);
4712 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4714 int square_color, x, y;
4719 switch (square_color) {
4721 case 2: /* neutral */
4723 if ((int)piece < (int) BlackPawn) {
4731 if ((int)piece < (int) BlackPawn) {
4739 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4740 dest, wlPieceGC, 0, 0,
4741 squareSize, squareSize, x, y);
4744 typedef void (*DrawFunc)();
4746 DrawFunc ChooseDrawFunc()
4748 if (appData.monoMode) {
4749 if (DefaultDepth(xDisplay, xScreen) == 1) {
4750 return monoDrawPiece_1bit;
4752 return monoDrawPiece;
4756 return colorDrawPieceImage;
4758 return colorDrawPiece;
4762 /* [HR] determine square color depending on chess variant. */
4763 static int SquareColor(row, column)
4768 if (gameInfo.variant == VariantXiangqi) {
4769 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4771 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4773 } else if (row <= 4) {
4779 square_color = ((column + row) % 2) == 1;
4782 /* [hgm] holdings: next line makes all holdings squares light */
4783 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4785 return square_color;
4788 void DrawSquare(row, column, piece, do_flash)
4789 int row, column, do_flash;
4792 int square_color, x, y, direction, font_ascent, font_descent;
4795 XCharStruct overall;
4799 /* Calculate delay in milliseconds (2-delays per complete flash) */
4800 flash_delay = 500 / appData.flashRate;
4803 x = lineGap + ((BOARD_WIDTH-1)-column) *
4804 (squareSize + lineGap);
4805 y = lineGap + row * (squareSize + lineGap);
4807 x = lineGap + column * (squareSize + lineGap);
4808 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4809 (squareSize + lineGap);
4812 square_color = SquareColor(row, column);
4814 if ( // [HGM] holdings: blank out area between board and holdings
4815 column == BOARD_LEFT-1 || column == BOARD_RGHT
4816 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4817 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4818 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4820 // [HGM] print piece counts next to holdings
4821 string[1] = NULLCHAR;
4822 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4823 string[0] = '0' + piece;
4824 XTextExtents(countFontStruct, string, 1, &direction,
4825 &font_ascent, &font_descent, &overall);
4826 if (appData.monoMode) {
4827 XDrawImageString(xDisplay, xBoardWindow, countGC,
4828 x + squareSize - overall.width - 2,
4829 y + font_ascent + 1, string, 1);
4831 XDrawString(xDisplay, xBoardWindow, countGC,
4832 x + squareSize - overall.width - 2,
4833 y + font_ascent + 1, string, 1);
4836 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4837 string[0] = '0' + piece;
4838 XTextExtents(countFontStruct, string, 1, &direction,
4839 &font_ascent, &font_descent, &overall);
4840 if (appData.monoMode) {
4841 XDrawImageString(xDisplay, xBoardWindow, countGC,
4842 x + 2, y + font_ascent + 1, string, 1);
4844 XDrawString(xDisplay, xBoardWindow, countGC,
4845 x + 2, y + font_ascent + 1, string, 1);
4849 if (piece == EmptySquare || appData.blindfold) {
4850 BlankSquare(x, y, square_color, piece, xBoardWindow);
4852 drawfunc = ChooseDrawFunc();
4853 if (do_flash && appData.flashCount > 0) {
4854 for (i=0; i<appData.flashCount; ++i) {
4856 drawfunc(piece, square_color, x, y, xBoardWindow);
4857 XSync(xDisplay, False);
4858 do_flash_delay(flash_delay);
4860 BlankSquare(x, y, square_color, piece, xBoardWindow);
4861 XSync(xDisplay, False);
4862 do_flash_delay(flash_delay);
4865 drawfunc(piece, square_color, x, y, xBoardWindow);
4869 string[1] = NULLCHAR;
4870 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4871 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4872 string[0] = 'a' + column - BOARD_LEFT;
4873 XTextExtents(coordFontStruct, string, 1, &direction,
4874 &font_ascent, &font_descent, &overall);
4875 if (appData.monoMode) {
4876 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4877 x + squareSize - overall.width - 2,
4878 y + squareSize - font_descent - 1, string, 1);
4880 XDrawString(xDisplay, xBoardWindow, coordGC,
4881 x + squareSize - overall.width - 2,
4882 y + squareSize - font_descent - 1, string, 1);
4885 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4886 string[0] = ONE + row;
4887 XTextExtents(coordFontStruct, string, 1, &direction,
4888 &font_ascent, &font_descent, &overall);
4889 if (appData.monoMode) {
4890 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4891 x + 2, y + font_ascent + 1, string, 1);
4893 XDrawString(xDisplay, xBoardWindow, coordGC,
4894 x + 2, y + font_ascent + 1, string, 1);
4900 /* Why is this needed on some versions of X? */
4901 void EventProc(widget, unused, event)
4906 if (!XtIsRealized(widget))
4909 switch (event->type) {
4911 if (event->xexpose.count > 0) return; /* no clipping is done */
4912 XDrawPosition(widget, True, NULL);
4920 void DrawPosition(fullRedraw, board)
4921 /*Boolean*/int fullRedraw;
4924 XDrawPosition(boardWidget, fullRedraw, board);
4927 /* Returns 1 if there are "too many" differences between b1 and b2
4928 (i.e. more than 1 move was made) */
4929 static int too_many_diffs(b1, b2)
4935 for (i=0; i<BOARD_HEIGHT; ++i) {
4936 for (j=0; j<BOARD_WIDTH; ++j) {
4937 if (b1[i][j] != b2[i][j]) {
4938 if (++c > 4) /* Castling causes 4 diffs */
4947 /* Matrix describing castling maneuvers */
4948 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4949 static int castling_matrix[4][5] = {
4950 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4951 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4952 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4953 { 7, 7, 4, 5, 6 } /* 0-0, black */
4956 /* Checks whether castling occurred. If it did, *rrow and *rcol
4957 are set to the destination (row,col) of the rook that moved.
4959 Returns 1 if castling occurred, 0 if not.
4961 Note: Only handles a max of 1 castling move, so be sure
4962 to call too_many_diffs() first.
4964 static int check_castle_draw(newb, oldb, rrow, rcol)
4971 /* For each type of castling... */
4972 for (i=0; i<4; ++i) {
4973 r = castling_matrix[i];
4975 /* Check the 4 squares involved in the castling move */
4977 for (j=1; j<=4; ++j) {
4978 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4985 /* All 4 changed, so it must be a castling move */
4994 static int damage[BOARD_SIZE][BOARD_SIZE];
4997 * event handler for redrawing the board
4999 void XDrawPosition(w, repaint, board)
5001 /*Boolean*/int repaint;
5005 static int lastFlipView = 0;
5006 static int lastBoardValid = 0;
5007 static Board lastBoard;
5011 if (board == NULL) {
5012 if (!lastBoardValid) return;
5015 if (!lastBoardValid || lastFlipView != flipView) {
5016 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5017 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5022 * It would be simpler to clear the window with XClearWindow()
5023 * but this causes a very distracting flicker.
5026 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5028 /* If too much changes (begin observing new game, etc.), don't
5030 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5032 /* Special check for castling so we don't flash both the king
5033 and the rook (just flash the king). */
5035 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5036 /* Draw rook with NO flashing. King will be drawn flashing later */
5037 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5038 lastBoard[rrow][rcol] = board[rrow][rcol];
5042 /* First pass -- Draw (newly) empty squares and repair damage.
5043 This prevents you from having a piece show up twice while it
5044 is flashing on its new square */
5045 for (i = 0; i < BOARD_HEIGHT; i++)
5046 for (j = 0; j < BOARD_WIDTH; j++)
5047 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5049 DrawSquare(i, j, board[i][j], 0);
5050 damage[i][j] = False;
5053 /* Second pass -- Draw piece(s) in new position and flash them */
5054 for (i = 0; i < BOARD_HEIGHT; i++)
5055 for (j = 0; j < BOARD_WIDTH; j++)
5056 if (board[i][j] != lastBoard[i][j]) {
5057 DrawSquare(i, j, board[i][j], do_flash);
5061 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5062 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5064 for (i = 0; i < BOARD_HEIGHT; i++)
5065 for (j = 0; j < BOARD_WIDTH; j++) {
5066 DrawSquare(i, j, board[i][j], 0);
5067 damage[i][j] = False;
5071 CopyBoard(lastBoard, board);
5073 lastFlipView = flipView;
5075 /* Draw highlights */
5076 if (pm1X >= 0 && pm1Y >= 0) {
5077 drawHighlight(pm1X, pm1Y, prelineGC);
5079 if (pm2X >= 0 && pm2Y >= 0) {
5080 drawHighlight(pm2X, pm2Y, prelineGC);
5082 if (hi1X >= 0 && hi1Y >= 0) {
5083 drawHighlight(hi1X, hi1Y, highlineGC);
5085 if (hi2X >= 0 && hi2Y >= 0) {
5086 drawHighlight(hi2X, hi2Y, highlineGC);
5089 /* If piece being dragged around board, must redraw that too */
5092 XSync(xDisplay, False);
5097 * event handler for redrawing the board
5099 void DrawPositionProc(w, event, prms, nprms)
5105 XDrawPosition(w, True, NULL);
5110 * event handler for parsing user moves
5112 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5113 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5114 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5115 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5116 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5117 // and at the end FinishMove() to perform the move after optional promotion popups.
5118 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5119 void HandleUserMove(w, event, prms, nprms)
5126 Boolean saveAnimate;
5127 static int second = 0, promotionChoice = 0;
5130 if (w != boardWidget || errorExitStatus != -1) return;
5132 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5133 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5134 if (!flipView && y >= 0) {
5135 y = BOARD_HEIGHT - 1 - y;
5137 if (flipView && x >= 0) {
5138 x = BOARD_WIDTH - 1 - x;
5141 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5142 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5143 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5144 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5145 if(gameInfo.holdingsWidth &&
5146 (WhiteOnMove(currentMove)
5147 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5148 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5149 // click in right holdings, for determining promotion piece
5150 ChessSquare p = boards[currentMove][y][x];
5151 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5152 if(p != EmptySquare) {
5153 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5158 DrawPosition(FALSE, boards[currentMove]);
5161 if (event->type == ButtonPress) ErrorPopDown();
5164 if (event->type == ButtonPress) {
5165 XtPopdown(promotionShell);
5166 XtDestroyWidget(promotionShell);
5167 promotionUp = False;
5175 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5176 if(event->type == ButtonPress
5177 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5178 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5179 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5183 if (event->type == ButtonPress) {
5184 /* First square, prepare to drag */
5185 if (OKToStartUserMove(x, y)) {
5189 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5190 if (appData.highlightDragging) {
5191 SetHighlights(x, y, -1, -1);
5199 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5200 /* Click on single square in stead of drag-drop */
5201 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5202 if (appData.animateDragging) {
5203 /* Undo animation damage if any */
5204 DrawPosition(FALSE, NULL);
5207 /* Second up/down in same square; just abort move */
5212 ClearPremoveHighlights();
5214 /* First upclick in same square; start click-click mode */
5215 SetHighlights(x, y, -1, -1);
5220 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5222 if (moveType == Comment) { // kludge for indicating capture-own on Press
5223 /* Clicked again on same color piece -- changed his mind */
5224 /* note that re-clicking same square always hits same color piece */
5225 second = (x == fromX && y == fromY);
5226 if (appData.highlightDragging) {
5227 SetHighlights(x, y, -1, -1);
5231 if (OKToStartUserMove(x, y)) {
5234 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5239 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5242 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5243 DrawPosition(FALSE, boards[currentMove]);
5247 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5250 saveAnimate = appData.animate;
5251 if (event->type == ButtonPress) {
5252 /* Finish clickclick move */
5253 if (appData.animate || appData.highlightLastMove) {
5254 SetHighlights(fromX, fromY, toX, toY);
5259 /* Finish drag move */
5260 if (appData.highlightLastMove) {
5261 SetHighlights(fromX, fromY, toX, toY);
5265 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5266 /* Don't animate move and drag both */
5267 appData.animate = FALSE;
5269 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5270 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5271 appData.alwaysPromoteToQueen) { // promotion, but no choice
5272 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5274 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5275 SetHighlights(fromX, fromY, toX, toY);
5276 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5277 // [HGM] super: promotion to captured piece selected from holdings
5278 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5279 promotionChoice = TRUE;
5280 // kludge follows to temporarily execute move on display, without promoting yet
5281 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5282 boards[currentMove][toY][toX] = p;
5283 DrawPosition(FALSE, boards[currentMove]);
5284 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5285 boards[currentMove][toY][toX] = q;
5286 DisplayMessage("Click in holdings to choose piece", "");
5290 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5292 if(moveType != ImpossibleMove) { // valid move, but no promotion
5293 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5294 } else { // invalid move; could have set premove
5297 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5298 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5301 appData.animate = saveAnimate;
5302 if (appData.animate || appData.animateDragging) {
5303 /* Undo animation damage if needed */
5304 DrawPosition(FALSE, NULL);
5308 void AnimateUserMove (Widget w, XEvent * event,
5309 String * params, Cardinal * nParams)
5311 DragPieceMove(event->xmotion.x, event->xmotion.y);
5314 Widget CommentCreate(name, text, mutable, callback, lines)
5316 int /*Boolean*/ mutable;
5317 XtCallbackProc callback;
5321 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5326 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5327 XtGetValues(boardWidget, args, j);
5330 XtSetArg(args[j], XtNresizable, True); j++;
5333 XtCreatePopupShell(name, topLevelShellWidgetClass,
5334 shellWidget, args, j);
5337 XtCreatePopupShell(name, transientShellWidgetClass,
5338 shellWidget, args, j);
5341 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5342 layoutArgs, XtNumber(layoutArgs));
5344 XtCreateManagedWidget("form", formWidgetClass, layout,
5345 formArgs, XtNumber(formArgs));
5349 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5350 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5352 XtSetArg(args[j], XtNstring, text); j++;
5353 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5354 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5355 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5356 XtSetArg(args[j], XtNright, XtChainRight); j++;
5357 XtSetArg(args[j], XtNresizable, True); j++;
5358 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5359 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5360 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5361 XtSetArg(args[j], XtNautoFill, True); j++;
5362 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5364 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5368 XtSetArg(args[j], XtNfromVert, edit); j++;
5369 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5370 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5371 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5372 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5374 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5375 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5378 XtSetArg(args[j], XtNfromVert, edit); j++;
5379 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5380 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5381 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5382 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5383 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5385 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5386 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5389 XtSetArg(args[j], XtNfromVert, edit); j++;
5390 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5391 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5392 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5393 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5394 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5396 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5397 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5400 XtSetArg(args[j], XtNfromVert, edit); j++;
5401 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5402 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5403 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5404 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5406 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5407 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5410 XtSetArg(args[j], XtNfromVert, edit); j++;
5411 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5412 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5413 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5414 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5415 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5417 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5418 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5421 XtRealizeWidget(shell);
5423 if (commentX == -1) {
5426 Dimension pw_height;
5427 Dimension ew_height;
5430 XtSetArg(args[j], XtNheight, &ew_height); j++;
5431 XtGetValues(edit, args, j);
5434 XtSetArg(args[j], XtNheight, &pw_height); j++;
5435 XtGetValues(shell, args, j);
5436 commentH = pw_height + (lines - 1) * ew_height;
5437 commentW = bw_width - 16;
5439 XSync(xDisplay, False);
5441 /* This code seems to tickle an X bug if it is executed too soon
5442 after xboard starts up. The coordinates get transformed as if
5443 the main window was positioned at (0, 0).
5445 XtTranslateCoords(shellWidget,
5446 (bw_width - commentW) / 2, 0 - commentH / 2,
5447 &commentX, &commentY);
5449 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5450 RootWindowOfScreen(XtScreen(shellWidget)),
5451 (bw_width - commentW) / 2, 0 - commentH / 2,
5456 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5459 XtSetArg(args[j], XtNheight, commentH); j++;
5460 XtSetArg(args[j], XtNwidth, commentW); j++;
5461 XtSetArg(args[j], XtNx, commentX); j++;
5462 XtSetArg(args[j], XtNy, commentY); j++;
5463 XtSetValues(shell, args, j);
5464 XtSetKeyboardFocus(shell, edit);
5469 /* Used for analysis window and ICS input window */
5470 Widget MiscCreate(name, text, mutable, callback, lines)
5472 int /*Boolean*/ mutable;
5473 XtCallbackProc callback;
5477 Widget shell, layout, form, edit;
5479 Dimension bw_width, pw_height, ew_height, w, h;
5485 XtSetArg(args[j], XtNresizable, True); j++;
5488 XtCreatePopupShell(name, topLevelShellWidgetClass,
5489 shellWidget, args, j);
5492 XtCreatePopupShell(name, transientShellWidgetClass,
5493 shellWidget, args, j);
5496 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5497 layoutArgs, XtNumber(layoutArgs));
5499 XtCreateManagedWidget("form", formWidgetClass, layout,
5500 formArgs, XtNumber(formArgs));
5504 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5505 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5507 XtSetArg(args[j], XtNstring, text); j++;
5508 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5509 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5510 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5511 XtSetArg(args[j], XtNright, XtChainRight); j++;
5512 XtSetArg(args[j], XtNresizable, True); j++;
5513 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5514 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5515 XtSetArg(args[j], XtNautoFill, True); j++;
5516 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5518 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5520 XtRealizeWidget(shell);
5523 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5524 XtGetValues(boardWidget, args, j);
5527 XtSetArg(args[j], XtNheight, &ew_height); j++;
5528 XtGetValues(edit, args, j);
5531 XtSetArg(args[j], XtNheight, &pw_height); j++;
5532 XtGetValues(shell, args, j);
5533 h = pw_height + (lines - 1) * ew_height;
5536 XSync(xDisplay, False);
5538 /* This code seems to tickle an X bug if it is executed too soon
5539 after xboard starts up. The coordinates get transformed as if
5540 the main window was positioned at (0, 0).
5542 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5544 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5545 RootWindowOfScreen(XtScreen(shellWidget)),
5546 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5550 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5553 XtSetArg(args[j], XtNheight, h); j++;
5554 XtSetArg(args[j], XtNwidth, w); j++;
5555 XtSetArg(args[j], XtNx, x); j++;
5556 XtSetArg(args[j], XtNy, y); j++;
5557 XtSetValues(shell, args, j);
5563 static int savedIndex; /* gross that this is global */
5565 void EditCommentPopUp(index, title, text)
5574 if (text == NULL) text = "";
5576 if (editShell == NULL) {
5578 CommentCreate(title, text, True, EditCommentCallback, 4);
5579 XtRealizeWidget(editShell);
5580 CatchDeleteWindow(editShell, "EditCommentPopDown");
5582 edit = XtNameToWidget(editShell, "*form.text");
5584 XtSetArg(args[j], XtNstring, text); j++;
5585 XtSetValues(edit, args, j);
5587 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5588 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5589 XtSetValues(editShell, args, j);
5592 XtPopup(editShell, XtGrabNone);
5596 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5597 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5601 void EditCommentCallback(w, client_data, call_data)
5603 XtPointer client_data, call_data;
5611 XtSetArg(args[j], XtNlabel, &name); j++;
5612 XtGetValues(w, args, j);
5614 if (strcmp(name, _("ok")) == 0) {
5615 edit = XtNameToWidget(editShell, "*form.text");
5617 XtSetArg(args[j], XtNstring, &val); j++;
5618 XtGetValues(edit, args, j);
5619 ReplaceComment(savedIndex, val);
5620 EditCommentPopDown();
5621 } else if (strcmp(name, _("cancel")) == 0) {
5622 EditCommentPopDown();
5623 } else if (strcmp(name, _("clear")) == 0) {
5624 edit = XtNameToWidget(editShell, "*form.text");
5625 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5626 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5630 void EditCommentPopDown()
5635 if (!editUp) return;
5637 XtSetArg(args[j], XtNx, &commentX); j++;
5638 XtSetArg(args[j], XtNy, &commentY); j++;
5639 XtSetArg(args[j], XtNheight, &commentH); j++;
5640 XtSetArg(args[j], XtNwidth, &commentW); j++;
5641 XtGetValues(editShell, args, j);
5642 XtPopdown(editShell);
5645 XtSetArg(args[j], XtNleftBitmap, None); j++;
5646 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5650 void ICSInputBoxPopUp()
5655 char *title = _("ICS Input");
5658 if (ICSInputShell == NULL) {
5659 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5660 tr = XtParseTranslationTable(ICSInputTranslations);
5661 edit = XtNameToWidget(ICSInputShell, "*form.text");
5662 XtOverrideTranslations(edit, tr);
5663 XtRealizeWidget(ICSInputShell);
5664 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5667 edit = XtNameToWidget(ICSInputShell, "*form.text");
5669 XtSetArg(args[j], XtNstring, ""); j++;
5670 XtSetValues(edit, args, j);
5672 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5673 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5674 XtSetValues(ICSInputShell, args, j);
5677 XtPopup(ICSInputShell, XtGrabNone);
5678 XtSetKeyboardFocus(ICSInputShell, edit);
5680 ICSInputBoxUp = True;
5682 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5683 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5687 void ICSInputSendText()
5694 edit = XtNameToWidget(ICSInputShell, "*form.text");
5696 XtSetArg(args[j], XtNstring, &val); j++;
5697 XtGetValues(edit, args, j);
5698 SendMultiLineToICS(val);
5699 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5700 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5703 void ICSInputBoxPopDown()
5708 if (!ICSInputBoxUp) return;
5710 XtPopdown(ICSInputShell);
5711 ICSInputBoxUp = False;
5713 XtSetArg(args[j], XtNleftBitmap, None); j++;
5714 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5718 void CommentPopUp(title, text)
5725 if (commentShell == NULL) {
5727 CommentCreate(title, text, False, CommentCallback, 4);
5728 XtRealizeWidget(commentShell);
5729 CatchDeleteWindow(commentShell, "CommentPopDown");
5731 edit = XtNameToWidget(commentShell, "*form.text");
5733 XtSetArg(args[j], XtNstring, text); j++;
5734 XtSetValues(edit, args, j);
5736 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5737 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5738 XtSetValues(commentShell, args, j);
5741 XtPopup(commentShell, XtGrabNone);
5742 XSync(xDisplay, False);
5747 void CommentCallback(w, client_data, call_data)
5749 XtPointer client_data, call_data;
5756 XtSetArg(args[j], XtNlabel, &name); j++;
5757 XtGetValues(w, args, j);
5759 if (strcmp(name, _("close")) == 0) {
5761 } else if (strcmp(name, _("edit")) == 0) {
5768 void CommentPopDown()
5773 if (!commentUp) return;
5775 XtSetArg(args[j], XtNx, &commentX); j++;
5776 XtSetArg(args[j], XtNy, &commentY); j++;
5777 XtSetArg(args[j], XtNwidth, &commentW); j++;
5778 XtSetArg(args[j], XtNheight, &commentH); j++;
5779 XtGetValues(commentShell, args, j);
5780 XtPopdown(commentShell);
5781 XSync(xDisplay, False);
5785 void FileNamePopUp(label, def, proc, openMode)
5792 Widget popup, layout, dialog, edit;
5798 fileProc = proc; /* I can't see a way not */
5799 fileOpenMode = openMode; /* to use globals here */
5802 XtSetArg(args[i], XtNresizable, True); i++;
5803 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5804 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5805 fileNameShell = popup =
5806 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5807 shellWidget, args, i);
5810 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5811 layoutArgs, XtNumber(layoutArgs));
5814 XtSetArg(args[i], XtNlabel, label); i++;
5815 XtSetArg(args[i], XtNvalue, def); i++;
5816 XtSetArg(args[i], XtNborderWidth, 0); i++;
5817 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5820 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5821 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5822 (XtPointer) dialog);
5824 XtRealizeWidget(popup);
5825 CatchDeleteWindow(popup, "FileNamePopDown");
5827 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5828 &x, &y, &win_x, &win_y, &mask);
5830 XtSetArg(args[0], XtNx, x - 10);
5831 XtSetArg(args[1], XtNy, y - 30);
5832 XtSetValues(popup, args, 2);
5834 XtPopup(popup, XtGrabExclusive);
5837 edit = XtNameToWidget(dialog, "*value");
5838 XtSetKeyboardFocus(popup, edit);
5841 void FileNamePopDown()
5843 if (!filenameUp) return;
5844 XtPopdown(fileNameShell);
5845 XtDestroyWidget(fileNameShell);
5850 void FileNameCallback(w, client_data, call_data)
5852 XtPointer client_data, call_data;
5857 XtSetArg(args[0], XtNlabel, &name);
5858 XtGetValues(w, args, 1);
5860 if (strcmp(name, _("cancel")) == 0) {
5865 FileNameAction(w, NULL, NULL, NULL);
5868 void FileNameAction(w, event, prms, nprms)
5880 name = XawDialogGetValueString(w = XtParent(w));
5882 if ((name != NULL) && (*name != NULLCHAR)) {
5884 XtPopdown(w = XtParent(XtParent(w)));
5888 p = strrchr(buf, ' ');
5895 fullname = ExpandPathName(buf);
5897 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5900 f = fopen(fullname, fileOpenMode);
5902 DisplayError(_("Failed to open file"), errno);
5904 (void) (*fileProc)(f, index, buf);
5911 XtPopdown(w = XtParent(XtParent(w)));
5917 void PromotionPopUp()
5920 Widget dialog, layout;
5922 Dimension bw_width, pw_width;
5926 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5927 XtGetValues(boardWidget, args, j);
5930 XtSetArg(args[j], XtNresizable, True); j++;
5931 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5933 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5934 shellWidget, args, j);
5936 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5937 layoutArgs, XtNumber(layoutArgs));
5940 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5941 XtSetArg(args[j], XtNborderWidth, 0); j++;
5942 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5945 if(gameInfo.variant != VariantShogi) {
5946 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5947 (XtPointer) dialog);
5948 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5949 (XtPointer) dialog);
5950 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5951 (XtPointer) dialog);
5952 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5953 (XtPointer) dialog);
5954 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5955 gameInfo.variant == VariantGiveaway) {
5956 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5957 (XtPointer) dialog);
5959 if(gameInfo.variant == VariantCapablanca ||
5960 gameInfo.variant == VariantGothic ||
5961 gameInfo.variant == VariantCapaRandom) {
5962 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5963 (XtPointer) dialog);
5964 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5965 (XtPointer) dialog);
5967 } else // [HGM] shogi
5969 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5970 (XtPointer) dialog);
5971 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5972 (XtPointer) dialog);
5974 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5975 (XtPointer) dialog);
5977 XtRealizeWidget(promotionShell);
5978 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5981 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5982 XtGetValues(promotionShell, args, j);
5984 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5985 lineGap + squareSize/3 +
5986 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5987 0 : 6*(squareSize + lineGap)), &x, &y);
5990 XtSetArg(args[j], XtNx, x); j++;
5991 XtSetArg(args[j], XtNy, y); j++;
5992 XtSetValues(promotionShell, args, j);
5994 XtPopup(promotionShell, XtGrabNone);
5999 void PromotionPopDown()
6001 if (!promotionUp) return;
6002 XtPopdown(promotionShell);
6003 XtDestroyWidget(promotionShell);
6004 promotionUp = False;
6007 void PromotionCallback(w, client_data, call_data)
6009 XtPointer client_data, call_data;
6015 XtSetArg(args[0], XtNlabel, &name);
6016 XtGetValues(w, args, 1);
6020 if (fromX == -1) return;
6022 if (strcmp(name, _("cancel")) == 0) {
6026 } else if (strcmp(name, _("Knight")) == 0) {
6028 } else if (strcmp(name, _("Promote")) == 0) {
6030 } else if (strcmp(name, _("Defer")) == 0) {
6033 promoChar = ToLower(name[0]);
6036 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6038 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6039 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6044 void ErrorCallback(w, client_data, call_data)
6046 XtPointer client_data, call_data;
6049 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6051 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6057 if (!errorUp) return;
6059 XtPopdown(errorShell);
6060 XtDestroyWidget(errorShell);
6061 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6064 void ErrorPopUp(title, label, modal)
6065 char *title, *label;
6069 Widget dialog, layout;
6073 Dimension bw_width, pw_width;
6074 Dimension pw_height;
6078 XtSetArg(args[i], XtNresizable, True); i++;
6079 XtSetArg(args[i], XtNtitle, title); i++;
6081 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6082 shellWidget, args, i);
6084 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6085 layoutArgs, XtNumber(layoutArgs));
6088 XtSetArg(args[i], XtNlabel, label); i++;
6089 XtSetArg(args[i], XtNborderWidth, 0); i++;
6090 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6093 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6095 XtRealizeWidget(errorShell);
6096 CatchDeleteWindow(errorShell, "ErrorPopDown");
6099 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6100 XtGetValues(boardWidget, args, i);
6102 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6103 XtSetArg(args[i], XtNheight, &pw_height); i++;
6104 XtGetValues(errorShell, args, i);
6107 /* This code seems to tickle an X bug if it is executed too soon
6108 after xboard starts up. The coordinates get transformed as if
6109 the main window was positioned at (0, 0).
6111 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6112 0 - pw_height + squareSize / 3, &x, &y);
6114 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6115 RootWindowOfScreen(XtScreen(boardWidget)),
6116 (bw_width - pw_width) / 2,
6117 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6121 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6124 XtSetArg(args[i], XtNx, x); i++;
6125 XtSetArg(args[i], XtNy, y); i++;
6126 XtSetValues(errorShell, args, i);
6129 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6132 /* Disable all user input other than deleting the window */
6133 static int frozen = 0;
6137 /* Grab by a widget that doesn't accept input */
6138 XtAddGrab(messageWidget, TRUE, FALSE);
6142 /* Undo a FreezeUI */
6145 if (!frozen) return;
6146 XtRemoveGrab(messageWidget);
6150 char *ModeToWidgetName(mode)
6154 case BeginningOfGame:
6155 if (appData.icsActive)
6156 return "menuMode.ICS Client";
6157 else if (appData.noChessProgram ||
6158 *appData.cmailGameName != NULLCHAR)
6159 return "menuMode.Edit Game";
6161 return "menuMode.Machine Black";
6162 case MachinePlaysBlack:
6163 return "menuMode.Machine Black";
6164 case MachinePlaysWhite:
6165 return "menuMode.Machine White";
6167 return "menuMode.Analysis Mode";
6169 return "menuMode.Analyze File";
6170 case TwoMachinesPlay:
6171 return "menuMode.Two Machines";
6173 return "menuMode.Edit Game";
6174 case PlayFromGameFile:
6175 return "menuFile.Load Game";
6177 return "menuMode.Edit Position";
6179 return "menuMode.Training";
6180 case IcsPlayingWhite:
6181 case IcsPlayingBlack:
6185 return "menuMode.ICS Client";
6192 void ModeHighlight()
6195 static int oldPausing = FALSE;
6196 static GameMode oldmode = (GameMode) -1;
6199 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6201 if (pausing != oldPausing) {
6202 oldPausing = pausing;
6204 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6206 XtSetArg(args[0], XtNleftBitmap, None);
6208 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6211 if (appData.showButtonBar) {
6212 /* Always toggle, don't set. Previous code messes up when
6213 invoked while the button is pressed, as releasing it
6214 toggles the state again. */
6217 XtSetArg(args[0], XtNbackground, &oldbg);
6218 XtSetArg(args[1], XtNforeground, &oldfg);
6219 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6221 XtSetArg(args[0], XtNbackground, oldfg);
6222 XtSetArg(args[1], XtNforeground, oldbg);
6224 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6228 wname = ModeToWidgetName(oldmode);
6229 if (wname != NULL) {
6230 XtSetArg(args[0], XtNleftBitmap, None);
6231 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6233 wname = ModeToWidgetName(gameMode);
6234 if (wname != NULL) {
6235 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6236 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6240 /* Maybe all the enables should be handled here, not just this one */
6241 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6242 gameMode == Training || gameMode == PlayFromGameFile);
6247 * Button/menu procedures
6249 void ResetProc(w, event, prms, nprms)
6256 EngineOutputPopDown();
6259 int LoadGamePopUp(f, gameNumber, title)
6264 cmailMsgLoaded = FALSE;
6265 if (gameNumber == 0) {
6266 int error = GameListBuild(f);
6268 DisplayError(_("Cannot build game list"), error);
6269 } else if (!ListEmpty(&gameList) &&
6270 ((ListGame *) gameList.tailPred)->number > 1) {
6271 GameListPopUp(f, title);
6277 return LoadGame(f, gameNumber, title, FALSE);
6280 void LoadGameProc(w, event, prms, nprms)
6286 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6289 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6292 void LoadNextGameProc(w, event, prms, nprms)
6301 void LoadPrevGameProc(w, event, prms, nprms)
6310 void ReloadGameProc(w, event, prms, nprms)
6319 void LoadNextPositionProc(w, event, prms, nprms)
6328 void LoadPrevPositionProc(w, event, prms, nprms)
6337 void ReloadPositionProc(w, event, prms, nprms)
6346 void LoadPositionProc(w, event, prms, nprms)
6352 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6355 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6358 void SaveGameProc(w, event, prms, nprms)
6364 FileNamePopUp(_("Save game file name?"),
6365 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6369 void SavePositionProc(w, event, prms, nprms)
6375 FileNamePopUp(_("Save position file name?"),
6376 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6380 void ReloadCmailMsgProc(w, event, prms, nprms)
6386 ReloadCmailMsgEvent(FALSE);
6389 void MailMoveProc(w, event, prms, nprms)
6398 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6399 static char *selected_fen_position=NULL;
6402 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6403 Atom *type_return, XtPointer *value_return,
6404 unsigned long *length_return, int *format_return)
6406 char *selection_tmp;
6408 if (!selected_fen_position) return False; /* should never happen */
6409 if (*target == XA_STRING){
6410 /* note: since no XtSelectionDoneProc was registered, Xt will
6411 * automatically call XtFree on the value returned. So have to
6412 * make a copy of it allocated with XtMalloc */
6413 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6414 strcpy(selection_tmp, selected_fen_position);
6416 *value_return=selection_tmp;
6417 *length_return=strlen(selection_tmp);
6418 *type_return=XA_STRING;
6419 *format_return = 8; /* bits per byte */
6426 /* note: when called from menu all parameters are NULL, so no clue what the
6427 * Widget which was clicked on was, or what the click event was
6429 void CopyPositionProc(w, event, prms, nprms)
6437 if (selected_fen_position) free(selected_fen_position);
6438 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6439 if (!selected_fen_position) return;
6440 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6442 SendPositionSelection,
6443 NULL/* lose_ownership_proc */ ,
6444 NULL/* transfer_done_proc */);
6446 free(selected_fen_position);
6447 selected_fen_position=NULL;
6451 /* function called when the data to Paste is ready */
6453 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6454 Atom *type, XtPointer value, unsigned long *len, int *format)
6457 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6458 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6459 EditPositionPasteFEN(fenstr);
6463 /* called when Paste Position button is pressed,
6464 * all parameters will be NULL */
6465 void PastePositionProc(w, event, prms, nprms)
6471 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6472 /* (XtSelectionCallbackProc) */ PastePositionCB,
6473 NULL, /* client_data passed to PastePositionCB */
6475 /* better to use the time field from the event that triggered the
6476 * call to this function, but that isn't trivial to get
6484 SendGameSelection(Widget w, Atom *selection, Atom *target,
6485 Atom *type_return, XtPointer *value_return,
6486 unsigned long *length_return, int *format_return)
6488 char *selection_tmp;
6490 if (*target == XA_STRING){
6491 FILE* f = fopen(gameCopyFilename, "r");
6494 if (f == NULL) return False;
6498 selection_tmp = XtMalloc(len + 1);
6499 count = fread(selection_tmp, 1, len, f);
6501 XtFree(selection_tmp);
6504 selection_tmp[len] = NULLCHAR;
6505 *value_return = selection_tmp;
6506 *length_return = len;
6507 *type_return = XA_STRING;
6508 *format_return = 8; /* bits per byte */
6515 /* note: when called from menu all parameters are NULL, so no clue what the
6516 * Widget which was clicked on was, or what the click event was
6518 void CopyGameProc(w, event, prms, nprms)
6526 ret = SaveGameToFile(gameCopyFilename, FALSE);
6529 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6532 NULL/* lose_ownership_proc */ ,
6533 NULL/* transfer_done_proc */);
6536 /* function called when the data to Paste is ready */
6538 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6539 Atom *type, XtPointer value, unsigned long *len, int *format)
6542 if (value == NULL || *len == 0) {
6543 return; /* nothing had been selected to copy */
6545 f = fopen(gamePasteFilename, "w");
6547 DisplayError(_("Can't open temp file"), errno);
6550 fwrite(value, 1, *len, f);
6553 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6556 /* called when Paste Game button is pressed,
6557 * all parameters will be NULL */
6558 void PasteGameProc(w, event, prms, nprms)
6564 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6565 /* (XtSelectionCallbackProc) */ PasteGameCB,
6566 NULL, /* client_data passed to PasteGameCB */
6568 /* better to use the time field from the event that triggered the
6569 * call to this function, but that isn't trivial to get
6579 SaveGameProc(NULL, NULL, NULL, NULL);
6583 void QuitProc(w, event, prms, nprms)
6592 void PauseProc(w, event, prms, nprms)
6602 void MachineBlackProc(w, event, prms, nprms)
6608 MachineBlackEvent();
6611 void MachineWhiteProc(w, event, prms, nprms)
6617 MachineWhiteEvent();
6620 void AnalyzeModeProc(w, event, prms, nprms)
6628 if (!first.analysisSupport) {
6629 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6630 DisplayError(buf, 0);
6633 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6634 if (appData.icsActive) {
6635 if (gameMode != IcsObserving) {
6636 sprintf(buf,_("You are not observing a game"));
6637 DisplayError(buf, 0);
6639 if (appData.icsEngineAnalyze) {
6640 if (appData.debugMode)
6641 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6647 /* if enable, use want disable icsEngineAnalyze */
6648 if (appData.icsEngineAnalyze) {
6653 appData.icsEngineAnalyze = TRUE;
6654 if (appData.debugMode)
6655 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6657 if (!appData.showThinking)
6658 ShowThinkingProc(w,event,prms,nprms);
6663 void AnalyzeFileProc(w, event, prms, nprms)
6669 if (!first.analysisSupport) {
6671 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6672 DisplayError(buf, 0);
6677 if (!appData.showThinking)
6678 ShowThinkingProc(w,event,prms,nprms);
6681 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6682 AnalysisPeriodicEvent(1);
6685 void TwoMachinesProc(w, event, prms, nprms)
6694 void IcsClientProc(w, event, prms, nprms)
6703 void EditGameProc(w, event, prms, nprms)
6712 void EditPositionProc(w, event, prms, nprms)
6718 EditPositionEvent();
6721 void TrainingProc(w, event, prms, nprms)
6730 void EditCommentProc(w, event, prms, nprms)
6737 EditCommentPopDown();
6743 void IcsInputBoxProc(w, event, prms, nprms)
6749 if (ICSInputBoxUp) {
6750 ICSInputBoxPopDown();
6756 void AcceptProc(w, event, prms, nprms)
6765 void DeclineProc(w, event, prms, nprms)
6774 void RematchProc(w, event, prms, nprms)
6783 void CallFlagProc(w, event, prms, nprms)
6792 void DrawProc(w, event, prms, nprms)
6801 void AbortProc(w, event, prms, nprms)
6810 void AdjournProc(w, event, prms, nprms)
6819 void ResignProc(w, event, prms, nprms)
6828 void AdjuWhiteProc(w, event, prms, nprms)
6834 UserAdjudicationEvent(+1);
6837 void AdjuBlackProc(w, event, prms, nprms)
6843 UserAdjudicationEvent(-1);
6846 void AdjuDrawProc(w, event, prms, nprms)
6852 UserAdjudicationEvent(0);
6855 void EnterKeyProc(w, event, prms, nprms)
6861 if (ICSInputBoxUp == True)
6865 void StopObservingProc(w, event, prms, nprms)
6871 StopObservingEvent();
6874 void StopExaminingProc(w, event, prms, nprms)
6880 StopExaminingEvent();
6884 void ForwardProc(w, event, prms, nprms)
6894 void BackwardProc(w, event, prms, nprms)
6903 void ToStartProc(w, event, prms, nprms)
6912 void ToEndProc(w, event, prms, nprms)
6921 void RevertProc(w, event, prms, nprms)
6930 void TruncateGameProc(w, event, prms, nprms)
6936 TruncateGameEvent();
6938 void RetractMoveProc(w, event, prms, nprms)
6947 void MoveNowProc(w, event, prms, nprms)
6957 void AlwaysQueenProc(w, event, prms, nprms)
6965 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6967 if (appData.alwaysPromoteToQueen) {
6968 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6970 XtSetArg(args[0], XtNleftBitmap, None);
6972 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6976 void AnimateDraggingProc(w, event, prms, nprms)
6984 appData.animateDragging = !appData.animateDragging;
6986 if (appData.animateDragging) {
6987 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6990 XtSetArg(args[0], XtNleftBitmap, None);
6992 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6996 void AnimateMovingProc(w, event, prms, nprms)
7004 appData.animate = !appData.animate;
7006 if (appData.animate) {
7007 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7010 XtSetArg(args[0], XtNleftBitmap, None);
7012 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7016 void AutocommProc(w, event, prms, nprms)
7024 appData.autoComment = !appData.autoComment;
7026 if (appData.autoComment) {
7027 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7029 XtSetArg(args[0], XtNleftBitmap, None);
7031 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7036 void AutoflagProc(w, event, prms, nprms)
7044 appData.autoCallFlag = !appData.autoCallFlag;
7046 if (appData.autoCallFlag) {
7047 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7049 XtSetArg(args[0], XtNleftBitmap, None);
7051 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7055 void AutoflipProc(w, event, prms, nprms)
7063 appData.autoFlipView = !appData.autoFlipView;
7065 if (appData.autoFlipView) {
7066 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7068 XtSetArg(args[0], XtNleftBitmap, None);
7070 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7074 void AutobsProc(w, event, prms, nprms)
7082 appData.autoObserve = !appData.autoObserve;
7084 if (appData.autoObserve) {
7085 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7087 XtSetArg(args[0], XtNleftBitmap, None);
7089 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7093 void AutoraiseProc(w, event, prms, nprms)
7101 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7103 if (appData.autoRaiseBoard) {
7104 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7106 XtSetArg(args[0], XtNleftBitmap, None);
7108 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7112 void AutosaveProc(w, event, prms, nprms)
7120 appData.autoSaveGames = !appData.autoSaveGames;
7122 if (appData.autoSaveGames) {
7123 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7125 XtSetArg(args[0], XtNleftBitmap, None);
7127 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7131 void BlindfoldProc(w, event, prms, nprms)
7139 appData.blindfold = !appData.blindfold;
7141 if (appData.blindfold) {
7142 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7144 XtSetArg(args[0], XtNleftBitmap, None);
7146 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7149 DrawPosition(True, NULL);
7152 void TestLegalityProc(w, event, prms, nprms)
7160 appData.testLegality = !appData.testLegality;
7162 if (appData.testLegality) {
7163 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7165 XtSetArg(args[0], XtNleftBitmap, None);
7167 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7172 void FlashMovesProc(w, event, prms, nprms)
7180 if (appData.flashCount == 0) {
7181 appData.flashCount = 3;
7183 appData.flashCount = -appData.flashCount;
7186 if (appData.flashCount > 0) {
7187 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7189 XtSetArg(args[0], XtNleftBitmap, None);
7191 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7195 void FlipViewProc(w, event, prms, nprms)
7201 flipView = !flipView;
7202 DrawPosition(True, NULL);
7205 void GetMoveListProc(w, event, prms, nprms)
7213 appData.getMoveList = !appData.getMoveList;
7215 if (appData.getMoveList) {
7216 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7219 XtSetArg(args[0], XtNleftBitmap, None);
7221 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7226 void HighlightDraggingProc(w, event, prms, nprms)
7234 appData.highlightDragging = !appData.highlightDragging;
7236 if (appData.highlightDragging) {
7237 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7239 XtSetArg(args[0], XtNleftBitmap, None);
7241 XtSetValues(XtNameToWidget(menuBarWidget,
7242 "menuOptions.Highlight Dragging"), args, 1);
7246 void HighlightLastMoveProc(w, event, prms, nprms)
7254 appData.highlightLastMove = !appData.highlightLastMove;
7256 if (appData.highlightLastMove) {
7257 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7259 XtSetArg(args[0], XtNleftBitmap, None);
7261 XtSetValues(XtNameToWidget(menuBarWidget,
7262 "menuOptions.Highlight Last Move"), args, 1);
7265 void IcsAlarmProc(w, event, prms, nprms)
7273 appData.icsAlarm = !appData.icsAlarm;
7275 if (appData.icsAlarm) {
7276 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7278 XtSetArg(args[0], XtNleftBitmap, None);
7280 XtSetValues(XtNameToWidget(menuBarWidget,
7281 "menuOptions.ICS Alarm"), args, 1);
7284 void MoveSoundProc(w, event, prms, nprms)
7292 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7294 if (appData.ringBellAfterMoves) {
7295 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7297 XtSetArg(args[0], XtNleftBitmap, None);
7299 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7304 void OldSaveStyleProc(w, event, prms, nprms)
7312 appData.oldSaveStyle = !appData.oldSaveStyle;
7314 if (appData.oldSaveStyle) {
7315 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7317 XtSetArg(args[0], XtNleftBitmap, None);
7319 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7323 void PeriodicUpdatesProc(w, event, prms, nprms)
7331 PeriodicUpdatesEvent(!appData.periodicUpdates);
7333 if (appData.periodicUpdates) {
7334 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7336 XtSetArg(args[0], XtNleftBitmap, None);
7338 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7342 void PonderNextMoveProc(w, event, prms, nprms)
7350 PonderNextMoveEvent(!appData.ponderNextMove);
7352 if (appData.ponderNextMove) {
7353 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7355 XtSetArg(args[0], XtNleftBitmap, None);
7357 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7361 void PopupExitMessageProc(w, event, prms, nprms)
7369 appData.popupExitMessage = !appData.popupExitMessage;
7371 if (appData.popupExitMessage) {
7372 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7374 XtSetArg(args[0], XtNleftBitmap, None);
7376 XtSetValues(XtNameToWidget(menuBarWidget,
7377 "menuOptions.Popup Exit Message"), args, 1);
7380 void PopupMoveErrorsProc(w, event, prms, nprms)
7388 appData.popupMoveErrors = !appData.popupMoveErrors;
7390 if (appData.popupMoveErrors) {
7391 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7393 XtSetArg(args[0], XtNleftBitmap, None);
7395 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7399 void PremoveProc(w, event, prms, nprms)
7407 appData.premove = !appData.premove;
7409 if (appData.premove) {
7410 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7412 XtSetArg(args[0], XtNleftBitmap, None);
7414 XtSetValues(XtNameToWidget(menuBarWidget,
7415 "menuOptions.Premove"), args, 1);
7418 void QuietPlayProc(w, event, prms, nprms)
7426 appData.quietPlay = !appData.quietPlay;
7428 if (appData.quietPlay) {
7429 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7431 XtSetArg(args[0], XtNleftBitmap, None);
7433 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7437 void ShowCoordsProc(w, event, prms, nprms)
7445 appData.showCoords = !appData.showCoords;
7447 if (appData.showCoords) {
7448 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7450 XtSetArg(args[0], XtNleftBitmap, None);
7452 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7455 DrawPosition(True, NULL);
7458 void ShowThinkingProc(w, event, prms, nprms)
7466 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7467 ShowThinkingEvent();
7470 void HideThinkingProc(w, event, prms, nprms)
7478 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7479 ShowThinkingEvent();
7481 if (appData.hideThinkingFromHuman) {
7482 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7484 XtSetArg(args[0], XtNleftBitmap, None);
7486 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7490 void InfoProc(w, event, prms, nprms)
7497 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7502 void ManProc(w, event, prms, nprms)
7510 if (nprms && *nprms > 0)
7514 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7518 void HintProc(w, event, prms, nprms)
7527 void BookProc(w, event, prms, nprms)
7536 void AboutProc(w, event, prms, nprms)
7544 char *zippy = " (with Zippy code)";
7548 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7549 programVersion, zippy,
7550 "Copyright 1991 Digital Equipment Corporation",
7551 "Enhancements Copyright 1992-2009 Free Software Foundation",
7552 "Enhancements Copyright 2005 Alessandro Scotti",
7553 PACKAGE, " is free software and carries NO WARRANTY;",
7554 "see the file COPYING for more information.");
7555 ErrorPopUp(_("About XBoard"), buf, FALSE);
7558 void DebugProc(w, event, prms, nprms)
7564 appData.debugMode = !appData.debugMode;
7567 void AboutGameProc(w, event, prms, nprms)
7576 void NothingProc(w, event, prms, nprms)
7585 void Iconify(w, event, prms, nprms)
7594 XtSetArg(args[0], XtNiconic, True);
7595 XtSetValues(shellWidget, args, 1);
7598 void DisplayMessage(message, extMessage)
7599 char *message, *extMessage;
7601 /* display a message in the message widget */
7610 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7615 message = extMessage;
7619 /* need to test if messageWidget already exists, since this function
7620 can also be called during the startup, if for example a Xresource
7621 is not set up correctly */
7624 XtSetArg(arg, XtNlabel, message);
7625 XtSetValues(messageWidget, &arg, 1);
7631 void DisplayTitle(text)
7636 char title[MSG_SIZ];
7639 if (text == NULL) text = "";
7641 if (appData.titleInWindow) {
7643 XtSetArg(args[i], XtNlabel, text); i++;
7644 XtSetValues(titleWidget, args, i);
7647 if (*text != NULLCHAR) {
7649 strcpy(title, text);
7650 } else if (appData.icsActive) {
7651 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7652 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7653 } else if (appData.cmailGameName[0] != NULLCHAR) {
7654 snprintf(icon, sizeof(icon), "%s", "CMail");
7655 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7657 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7658 } else if (gameInfo.variant == VariantGothic) {
7659 strcpy(icon, programName);
7660 strcpy(title, GOTHIC);
7663 } else if (gameInfo.variant == VariantFalcon) {
7664 strcpy(icon, programName);
7665 strcpy(title, FALCON);
7667 } else if (appData.noChessProgram) {
7668 strcpy(icon, programName);
7669 strcpy(title, programName);
7671 strcpy(icon, first.tidy);
7672 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7675 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7676 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7677 XtSetValues(shellWidget, args, i);
7681 void DisplayError(message, error)
7688 if (appData.debugMode || appData.matchMode) {
7689 fprintf(stderr, "%s: %s\n", programName, message);
7692 if (appData.debugMode || appData.matchMode) {
7693 fprintf(stderr, "%s: %s: %s\n",
7694 programName, message, strerror(error));
7696 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7699 ErrorPopUp(_("Error"), message, FALSE);
7703 void DisplayMoveError(message)
7708 DrawPosition(FALSE, NULL);
7709 if (appData.debugMode || appData.matchMode) {
7710 fprintf(stderr, "%s: %s\n", programName, message);
7712 if (appData.popupMoveErrors) {
7713 ErrorPopUp(_("Error"), message, FALSE);
7715 DisplayMessage(message, "");
7720 void DisplayFatalError(message, error, status)
7726 errorExitStatus = status;
7728 fprintf(stderr, "%s: %s\n", programName, message);
7730 fprintf(stderr, "%s: %s: %s\n",
7731 programName, message, strerror(error));
7732 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7735 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7736 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7742 void DisplayInformation(message)
7746 ErrorPopUp(_("Information"), message, TRUE);
7749 void DisplayNote(message)
7753 ErrorPopUp(_("Note"), message, FALSE);
7757 NullXErrorCheck(dpy, error_event)
7759 XErrorEvent *error_event;
7764 void DisplayIcsInteractionTitle(message)
7767 if (oldICSInteractionTitle == NULL) {
7768 /* Magic to find the old window title, adapted from vim */
7769 char *wina = getenv("WINDOWID");
7771 Window win = (Window) atoi(wina);
7772 Window root, parent, *children;
7773 unsigned int nchildren;
7774 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7776 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7777 if (!XQueryTree(xDisplay, win, &root, &parent,
7778 &children, &nchildren)) break;
7779 if (children) XFree((void *)children);
7780 if (parent == root || parent == 0) break;
7783 XSetErrorHandler(oldHandler);
7785 if (oldICSInteractionTitle == NULL) {
7786 oldICSInteractionTitle = "xterm";
7789 printf("\033]0;%s\007", message);
7793 char pendingReplyPrefix[MSG_SIZ];
7794 ProcRef pendingReplyPR;
7796 void AskQuestionProc(w, event, prms, nprms)
7803 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7807 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7810 void AskQuestionPopDown()
7812 if (!askQuestionUp) return;
7813 XtPopdown(askQuestionShell);
7814 XtDestroyWidget(askQuestionShell);
7815 askQuestionUp = False;
7818 void AskQuestionReplyAction(w, event, prms, nprms)
7828 reply = XawDialogGetValueString(w = XtParent(w));
7829 strcpy(buf, pendingReplyPrefix);
7830 if (*buf) strcat(buf, " ");
7833 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7834 AskQuestionPopDown();
7836 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7839 void AskQuestionCallback(w, client_data, call_data)
7841 XtPointer client_data, call_data;
7846 XtSetArg(args[0], XtNlabel, &name);
7847 XtGetValues(w, args, 1);
7849 if (strcmp(name, _("cancel")) == 0) {
7850 AskQuestionPopDown();
7852 AskQuestionReplyAction(w, NULL, NULL, NULL);
7856 void AskQuestion(title, question, replyPrefix, pr)
7857 char *title, *question, *replyPrefix;
7861 Widget popup, layout, dialog, edit;
7867 strcpy(pendingReplyPrefix, replyPrefix);
7868 pendingReplyPR = pr;
7871 XtSetArg(args[i], XtNresizable, True); i++;
7872 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7873 askQuestionShell = popup =
7874 XtCreatePopupShell(title, transientShellWidgetClass,
7875 shellWidget, args, i);
7878 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7879 layoutArgs, XtNumber(layoutArgs));
7882 XtSetArg(args[i], XtNlabel, question); i++;
7883 XtSetArg(args[i], XtNvalue, ""); i++;
7884 XtSetArg(args[i], XtNborderWidth, 0); i++;
7885 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7888 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7889 (XtPointer) dialog);
7890 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7891 (XtPointer) dialog);
7893 XtRealizeWidget(popup);
7894 CatchDeleteWindow(popup, "AskQuestionPopDown");
7896 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7897 &x, &y, &win_x, &win_y, &mask);
7899 XtSetArg(args[0], XtNx, x - 10);
7900 XtSetArg(args[1], XtNy, y - 30);
7901 XtSetValues(popup, args, 2);
7903 XtPopup(popup, XtGrabExclusive);
7904 askQuestionUp = True;
7906 edit = XtNameToWidget(dialog, "*value");
7907 XtSetKeyboardFocus(popup, edit);
7915 if (*name == NULLCHAR) {
7917 } else if (strcmp(name, "$") == 0) {
7918 putc(BELLCHAR, stderr);
7921 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7929 PlaySound(appData.soundMove);
7935 PlaySound(appData.soundIcsWin);
7941 PlaySound(appData.soundIcsLoss);
7947 PlaySound(appData.soundIcsDraw);
7951 PlayIcsUnfinishedSound()
7953 PlaySound(appData.soundIcsUnfinished);
7959 PlaySound(appData.soundIcsAlarm);
7965 system("stty echo");
7971 system("stty -echo");
7975 Colorize(cc, continuation)
7980 int count, outCount, error;
7982 if (textColors[(int)cc].bg > 0) {
7983 if (textColors[(int)cc].fg > 0) {
7984 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7985 textColors[(int)cc].fg, textColors[(int)cc].bg);
7987 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7988 textColors[(int)cc].bg);
7991 if (textColors[(int)cc].fg > 0) {
7992 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7993 textColors[(int)cc].fg);
7995 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7998 count = strlen(buf);
7999 outCount = OutputToProcess(NoProc, buf, count, &error);
8000 if (outCount < count) {
8001 DisplayFatalError(_("Error writing to display"), error, 1);
8004 if (continuation) return;
8007 PlaySound(appData.soundShout);
8010 PlaySound(appData.soundSShout);
8013 PlaySound(appData.soundChannel1);
8016 PlaySound(appData.soundChannel);
8019 PlaySound(appData.soundKibitz);
8022 PlaySound(appData.soundTell);
8024 case ColorChallenge:
8025 PlaySound(appData.soundChallenge);
8028 PlaySound(appData.soundRequest);
8031 PlaySound(appData.soundSeek);
8042 return getpwuid(getuid())->pw_name;
8045 static char *ExpandPathName(path)
8048 static char static_buf[2000];
8049 char *d, *s, buf[2000];
8055 while (*s && isspace(*s))
8064 if (*(s+1) == '/') {
8065 strcpy(d, getpwuid(getuid())->pw_dir);
8070 *strchr(buf, '/') = 0;
8071 pwd = getpwnam(buf);
8074 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8078 strcpy(d, pwd->pw_dir);
8079 strcat(d, strchr(s+1, '/'));
8090 static char host_name[MSG_SIZ];
8092 #if HAVE_GETHOSTNAME
8093 gethostname(host_name, MSG_SIZ);
8095 #else /* not HAVE_GETHOSTNAME */
8096 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8097 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8099 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8101 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8102 #endif /* not HAVE_GETHOSTNAME */
8105 XtIntervalId delayedEventTimerXID = 0;
8106 DelayedEventCallback delayedEventCallback = 0;
8111 delayedEventTimerXID = 0;
8112 delayedEventCallback();
8116 ScheduleDelayedEvent(cb, millisec)
8117 DelayedEventCallback cb; long millisec;
8119 if(delayedEventTimerXID && delayedEventCallback == cb)
8120 // [HGM] alive: replace, rather than add or flush identical event
8121 XtRemoveTimeOut(delayedEventTimerXID);
8122 delayedEventCallback = cb;
8123 delayedEventTimerXID =
8124 XtAppAddTimeOut(appContext, millisec,
8125 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8128 DelayedEventCallback
8131 if (delayedEventTimerXID) {
8132 return delayedEventCallback;
8139 CancelDelayedEvent()
8141 if (delayedEventTimerXID) {
8142 XtRemoveTimeOut(delayedEventTimerXID);
8143 delayedEventTimerXID = 0;
8147 XtIntervalId loadGameTimerXID = 0;
8149 int LoadGameTimerRunning()
8151 return loadGameTimerXID != 0;
8154 int StopLoadGameTimer()
8156 if (loadGameTimerXID != 0) {
8157 XtRemoveTimeOut(loadGameTimerXID);
8158 loadGameTimerXID = 0;
8166 LoadGameTimerCallback(arg, id)
8170 loadGameTimerXID = 0;
8175 StartLoadGameTimer(millisec)
8179 XtAppAddTimeOut(appContext, millisec,
8180 (XtTimerCallbackProc) LoadGameTimerCallback,
8184 XtIntervalId analysisClockXID = 0;
8187 AnalysisClockCallback(arg, id)
8191 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8192 || appData.icsEngineAnalyze) { // [DM]
8193 AnalysisPeriodicEvent(0);
8194 StartAnalysisClock();
8199 StartAnalysisClock()
8202 XtAppAddTimeOut(appContext, 2000,
8203 (XtTimerCallbackProc) AnalysisClockCallback,
8207 XtIntervalId clockTimerXID = 0;
8209 int ClockTimerRunning()
8211 return clockTimerXID != 0;
8214 int StopClockTimer()
8216 if (clockTimerXID != 0) {
8217 XtRemoveTimeOut(clockTimerXID);
8226 ClockTimerCallback(arg, id)
8235 StartClockTimer(millisec)
8239 XtAppAddTimeOut(appContext, millisec,
8240 (XtTimerCallbackProc) ClockTimerCallback,
8245 DisplayTimerLabel(w, color, timer, highlight)
8254 /* check for low time warning */
8255 Pixel foregroundOrWarningColor = timerForegroundPixel;
8258 appData.lowTimeWarning &&
8259 (timer / 1000) < appData.icsAlarmTime)
8260 foregroundOrWarningColor = lowTimeWarningColor;
8262 if (appData.clockMode) {
8263 sprintf(buf, "%s: %s", color, TimeString(timer));
8264 XtSetArg(args[0], XtNlabel, buf);
8266 sprintf(buf, "%s ", color);
8267 XtSetArg(args[0], XtNlabel, buf);
8272 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8273 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8275 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8276 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8279 XtSetValues(w, args, 3);
8283 DisplayWhiteClock(timeRemaining, highlight)
8289 if(appData.noGUI) return;
8290 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8291 if (highlight && iconPixmap == bIconPixmap) {
8292 iconPixmap = wIconPixmap;
8293 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8294 XtSetValues(shellWidget, args, 1);
8299 DisplayBlackClock(timeRemaining, highlight)
8305 if(appData.noGUI) return;
8306 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8307 if (highlight && iconPixmap == wIconPixmap) {
8308 iconPixmap = bIconPixmap;
8309 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8310 XtSetValues(shellWidget, args, 1);
8328 int StartChildProcess(cmdLine, dir, pr)
8335 int to_prog[2], from_prog[2];
8339 if (appData.debugMode) {
8340 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8343 /* We do NOT feed the cmdLine to the shell; we just
8344 parse it into blank-separated arguments in the
8345 most simple-minded way possible.
8348 strcpy(buf, cmdLine);
8353 if (p == NULL) break;
8358 SetUpChildIO(to_prog, from_prog);
8361 signal(SIGWINCH, TermSizeSigHandler);
8364 if ((pid = fork()) == 0) {
8366 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8367 close(to_prog[1]); // first close the unused pipe ends
8368 close(from_prog[0]);
8369 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8370 dup2(from_prog[1], 1);
8371 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8372 close(from_prog[1]); // and closing again loses one of the pipes!
8373 if(fileno(stderr) >= 2) // better safe than sorry...
8374 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8376 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8381 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8383 execvp(argv[0], argv);
8385 /* If we get here, exec failed */
8390 /* Parent process */
8392 close(from_prog[1]);
8394 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8397 cp->fdFrom = from_prog[0];
8398 cp->fdTo = to_prog[1];
8403 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8404 static RETSIGTYPE AlarmCallBack(int n)
8410 DestroyChildProcess(pr, signalType)
8414 ChildProc *cp = (ChildProc *) pr;
8416 if (cp->kind != CPReal) return;
8418 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8419 signal(SIGALRM, AlarmCallBack);
8421 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8422 kill(cp->pid, SIGKILL); // kill it forcefully
8423 wait((int *) 0); // and wait again
8427 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8429 /* Process is exiting either because of the kill or because of
8430 a quit command sent by the backend; either way, wait for it to die.
8439 InterruptChildProcess(pr)
8442 ChildProc *cp = (ChildProc *) pr;
8444 if (cp->kind != CPReal) return;
8445 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8448 int OpenTelnet(host, port, pr)
8453 char cmdLine[MSG_SIZ];
8455 if (port[0] == NULLCHAR) {
8456 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8458 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8460 return StartChildProcess(cmdLine, "", pr);
8463 int OpenTCP(host, port, pr)
8469 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8470 #else /* !OMIT_SOCKETS */
8472 struct sockaddr_in sa;
8474 unsigned short uport;
8477 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8481 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8482 sa.sin_family = AF_INET;
8483 sa.sin_addr.s_addr = INADDR_ANY;
8484 uport = (unsigned short) 0;
8485 sa.sin_port = htons(uport);
8486 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8490 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8491 if (!(hp = gethostbyname(host))) {
8493 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8494 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8495 hp->h_addrtype = AF_INET;
8497 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8498 hp->h_addr_list[0] = (char *) malloc(4);
8499 hp->h_addr_list[0][0] = b0;
8500 hp->h_addr_list[0][1] = b1;
8501 hp->h_addr_list[0][2] = b2;
8502 hp->h_addr_list[0][3] = b3;
8507 sa.sin_family = hp->h_addrtype;
8508 uport = (unsigned short) atoi(port);
8509 sa.sin_port = htons(uport);
8510 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8512 if (connect(s, (struct sockaddr *) &sa,
8513 sizeof(struct sockaddr_in)) < 0) {
8517 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8524 #endif /* !OMIT_SOCKETS */
8529 int OpenCommPort(name, pr)
8536 fd = open(name, 2, 0);
8537 if (fd < 0) return errno;
8539 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8549 int OpenLoopback(pr)
8555 SetUpChildIO(to, from);
8557 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8560 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8567 int OpenRcmd(host, user, cmd, pr)
8568 char *host, *user, *cmd;
8571 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8575 #define INPUT_SOURCE_BUF_SIZE 8192
8584 char buf[INPUT_SOURCE_BUF_SIZE];
8589 DoInputCallback(closure, source, xid)
8594 InputSource *is = (InputSource *) closure;
8599 if (is->lineByLine) {
8600 count = read(is->fd, is->unused,
8601 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8603 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8606 is->unused += count;
8608 while (p < is->unused) {
8609 q = memchr(p, '\n', is->unused - p);
8610 if (q == NULL) break;
8612 (is->func)(is, is->closure, p, q - p, 0);
8616 while (p < is->unused) {
8621 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8626 (is->func)(is, is->closure, is->buf, count, error);
8630 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8637 ChildProc *cp = (ChildProc *) pr;
8639 is = (InputSource *) calloc(1, sizeof(InputSource));
8640 is->lineByLine = lineByLine;
8644 is->fd = fileno(stdin);
8646 is->kind = cp->kind;
8647 is->fd = cp->fdFrom;
8650 is->unused = is->buf;
8653 is->xid = XtAppAddInput(appContext, is->fd,
8654 (XtPointer) (XtInputReadMask),
8655 (XtInputCallbackProc) DoInputCallback,
8657 is->closure = closure;
8658 return (InputSourceRef) is;
8662 RemoveInputSource(isr)
8665 InputSource *is = (InputSource *) isr;
8667 if (is->xid == 0) return;
8668 XtRemoveInput(is->xid);
8672 int OutputToProcess(pr, message, count, outError)
8678 ChildProc *cp = (ChildProc *) pr;
8682 outCount = fwrite(message, 1, count, stdout);
8684 outCount = write(cp->fdTo, message, count);
8694 /* Output message to process, with "ms" milliseconds of delay
8695 between each character. This is needed when sending the logon
8696 script to ICC, which for some reason doesn't like the
8697 instantaneous send. */
8698 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8705 ChildProc *cp = (ChildProc *) pr;
8710 r = write(cp->fdTo, message++, 1);
8723 /**** Animation code by Hugh Fisher, DCS, ANU.
8725 Known problem: if a window overlapping the board is
8726 moved away while a piece is being animated underneath,
8727 the newly exposed area won't be updated properly.
8728 I can live with this.
8730 Known problem: if you look carefully at the animation
8731 of pieces in mono mode, they are being drawn as solid
8732 shapes without interior detail while moving. Fixing
8733 this would be a major complication for minimal return.
8736 /* Masks for XPM pieces. Black and white pieces can have
8737 different shapes, but in the interest of retaining my
8738 sanity pieces must have the same outline on both light
8739 and dark squares, and all pieces must use the same
8740 background square colors/images. */
8742 static int xpmDone = 0;
8745 CreateAnimMasks (pieceDepth)
8752 unsigned long plane;
8755 /* Need a bitmap just to get a GC with right depth */
8756 buf = XCreatePixmap(xDisplay, xBoardWindow,
8758 values.foreground = 1;
8759 values.background = 0;
8760 /* Don't use XtGetGC, not read only */
8761 maskGC = XCreateGC(xDisplay, buf,
8762 GCForeground | GCBackground, &values);
8763 XFreePixmap(xDisplay, buf);
8765 buf = XCreatePixmap(xDisplay, xBoardWindow,
8766 squareSize, squareSize, pieceDepth);
8767 values.foreground = XBlackPixel(xDisplay, xScreen);
8768 values.background = XWhitePixel(xDisplay, xScreen);
8769 bufGC = XCreateGC(xDisplay, buf,
8770 GCForeground | GCBackground, &values);
8772 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8773 /* Begin with empty mask */
8774 if(!xpmDone) // [HGM] pieces: keep using existing
8775 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8776 squareSize, squareSize, 1);
8777 XSetFunction(xDisplay, maskGC, GXclear);
8778 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8779 0, 0, squareSize, squareSize);
8781 /* Take a copy of the piece */
8786 XSetFunction(xDisplay, bufGC, GXcopy);
8787 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8789 0, 0, squareSize, squareSize, 0, 0);
8791 /* XOR the background (light) over the piece */
8792 XSetFunction(xDisplay, bufGC, GXxor);
8794 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8795 0, 0, squareSize, squareSize, 0, 0);
8797 XSetForeground(xDisplay, bufGC, lightSquareColor);
8798 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8801 /* We now have an inverted piece image with the background
8802 erased. Construct mask by just selecting all the non-zero
8803 pixels - no need to reconstruct the original image. */
8804 XSetFunction(xDisplay, maskGC, GXor);
8806 /* Might be quicker to download an XImage and create bitmap
8807 data from it rather than this N copies per piece, but it
8808 only takes a fraction of a second and there is a much
8809 longer delay for loading the pieces. */
8810 for (n = 0; n < pieceDepth; n ++) {
8811 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8812 0, 0, squareSize, squareSize,
8818 XFreePixmap(xDisplay, buf);
8819 XFreeGC(xDisplay, bufGC);
8820 XFreeGC(xDisplay, maskGC);
8824 InitAnimState (anim, info)
8826 XWindowAttributes * info;
8831 /* Each buffer is square size, same depth as window */
8832 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8833 squareSize, squareSize, info->depth);
8834 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8835 squareSize, squareSize, info->depth);
8837 /* Create a plain GC for blitting */
8838 mask = GCForeground | GCBackground | GCFunction |
8839 GCPlaneMask | GCGraphicsExposures;
8840 values.foreground = XBlackPixel(xDisplay, xScreen);
8841 values.background = XWhitePixel(xDisplay, xScreen);
8842 values.function = GXcopy;
8843 values.plane_mask = AllPlanes;
8844 values.graphics_exposures = False;
8845 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8847 /* Piece will be copied from an existing context at
8848 the start of each new animation/drag. */
8849 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8851 /* Outline will be a read-only copy of an existing */
8852 anim->outlineGC = None;
8858 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8859 XWindowAttributes info;
8861 if (xpmDone && gameInfo.variant == old) return;
8862 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8863 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8865 InitAnimState(&game, &info);
8866 InitAnimState(&player, &info);
8868 /* For XPM pieces, we need bitmaps to use as masks. */
8870 CreateAnimMasks(info.depth);
8876 static Boolean frameWaiting;
8878 static RETSIGTYPE FrameAlarm (sig)
8881 frameWaiting = False;
8882 /* In case System-V style signals. Needed?? */
8883 signal(SIGALRM, FrameAlarm);
8890 struct itimerval delay;
8892 XSync(xDisplay, False);
8895 frameWaiting = True;
8896 signal(SIGALRM, FrameAlarm);
8897 delay.it_interval.tv_sec =
8898 delay.it_value.tv_sec = time / 1000;
8899 delay.it_interval.tv_usec =
8900 delay.it_value.tv_usec = (time % 1000) * 1000;
8901 setitimer(ITIMER_REAL, &delay, NULL);
8902 while (frameWaiting) pause();
8903 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8904 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8905 setitimer(ITIMER_REAL, &delay, NULL);
8915 XSync(xDisplay, False);
8917 usleep(time * 1000);
8922 /* Convert board position to corner of screen rect and color */
8925 ScreenSquare(column, row, pt, color)
8926 int column; int row; XPoint * pt; int * color;
8929 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8930 pt->y = lineGap + row * (squareSize + lineGap);
8932 pt->x = lineGap + column * (squareSize + lineGap);
8933 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8935 *color = SquareColor(row, column);
8938 /* Convert window coords to square */
8941 BoardSquare(x, y, column, row)
8942 int x; int y; int * column; int * row;
8944 *column = EventToSquare(x, BOARD_WIDTH);
8945 if (flipView && *column >= 0)
8946 *column = BOARD_WIDTH - 1 - *column;
8947 *row = EventToSquare(y, BOARD_HEIGHT);
8948 if (!flipView && *row >= 0)
8949 *row = BOARD_HEIGHT - 1 - *row;
8954 #undef Max /* just in case */
8956 #define Max(a, b) ((a) > (b) ? (a) : (b))
8957 #define Min(a, b) ((a) < (b) ? (a) : (b))
8960 SetRect(rect, x, y, width, height)
8961 XRectangle * rect; int x; int y; int width; int height;
8965 rect->width = width;
8966 rect->height = height;
8969 /* Test if two frames overlap. If they do, return
8970 intersection rect within old and location of
8971 that rect within new. */
8974 Intersect(old, new, size, area, pt)
8975 XPoint * old; XPoint * new;
8976 int size; XRectangle * area; XPoint * pt;
8978 if (old->x > new->x + size || new->x > old->x + size ||
8979 old->y > new->y + size || new->y > old->y + size) {
8982 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8983 size - abs(old->x - new->x), size - abs(old->y - new->y));
8984 pt->x = Max(old->x - new->x, 0);
8985 pt->y = Max(old->y - new->y, 0);
8990 /* For two overlapping frames, return the rect(s)
8991 in the old that do not intersect with the new. */
8994 CalcUpdateRects(old, new, size, update, nUpdates)
8995 XPoint * old; XPoint * new; int size;
8996 XRectangle update[]; int * nUpdates;
9000 /* If old = new (shouldn't happen) then nothing to draw */
9001 if (old->x == new->x && old->y == new->y) {
9005 /* Work out what bits overlap. Since we know the rects
9006 are the same size we don't need a full intersect calc. */
9008 /* Top or bottom edge? */
9009 if (new->y > old->y) {
9010 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9012 } else if (old->y > new->y) {
9013 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9014 size, old->y - new->y);
9017 /* Left or right edge - don't overlap any update calculated above. */
9018 if (new->x > old->x) {
9019 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9020 new->x - old->x, size - abs(new->y - old->y));
9022 } else if (old->x > new->x) {
9023 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9024 old->x - new->x, size - abs(new->y - old->y));
9031 /* Generate a series of frame coords from start->mid->finish.
9032 The movement rate doubles until the half way point is
9033 reached, then halves back down to the final destination,
9034 which gives a nice slow in/out effect. The algorithmn
9035 may seem to generate too many intermediates for short
9036 moves, but remember that the purpose is to attract the
9037 viewers attention to the piece about to be moved and
9038 then to where it ends up. Too few frames would be less
9042 Tween(start, mid, finish, factor, frames, nFrames)
9043 XPoint * start; XPoint * mid;
9044 XPoint * finish; int factor;
9045 XPoint frames[]; int * nFrames;
9047 int fraction, n, count;
9051 /* Slow in, stepping 1/16th, then 1/8th, ... */
9053 for (n = 0; n < factor; n++)
9055 for (n = 0; n < factor; n++) {
9056 frames[count].x = start->x + (mid->x - start->x) / fraction;
9057 frames[count].y = start->y + (mid->y - start->y) / fraction;
9059 fraction = fraction / 2;
9063 frames[count] = *mid;
9066 /* Slow out, stepping 1/2, then 1/4, ... */
9068 for (n = 0; n < factor; n++) {
9069 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9070 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9072 fraction = fraction * 2;
9077 /* Draw a piece on the screen without disturbing what's there */
9080 SelectGCMask(piece, clip, outline, mask)
9081 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9085 /* Bitmap for piece being moved. */
9086 if (appData.monoMode) {
9087 *mask = *pieceToSolid(piece);
9088 } else if (useImages) {
9090 *mask = xpmMask[piece];
9092 *mask = ximMaskPm[piece];
9095 *mask = *pieceToSolid(piece);
9098 /* GC for piece being moved. Square color doesn't matter, but
9099 since it gets modified we make a copy of the original. */
9101 if (appData.monoMode)
9106 if (appData.monoMode)
9111 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9113 /* Outline only used in mono mode and is not modified */
9115 *outline = bwPieceGC;
9117 *outline = wbPieceGC;
9121 OverlayPiece(piece, clip, outline, dest)
9122 ChessSquare piece; GC clip; GC outline; Drawable dest;
9127 /* Draw solid rectangle which will be clipped to shape of piece */
9128 XFillRectangle(xDisplay, dest, clip,
9129 0, 0, squareSize, squareSize);
9130 if (appData.monoMode)
9131 /* Also draw outline in contrasting color for black
9132 on black / white on white cases */
9133 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9134 0, 0, squareSize, squareSize, 0, 0, 1);
9136 /* Copy the piece */
9141 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9143 0, 0, squareSize, squareSize,
9148 /* Animate the movement of a single piece */
9151 BeginAnimation(anim, piece, startColor, start)
9159 /* The old buffer is initialised with the start square (empty) */
9160 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9161 anim->prevFrame = *start;
9163 /* The piece will be drawn using its own bitmap as a matte */
9164 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9165 XSetClipMask(xDisplay, anim->pieceGC, mask);
9169 AnimationFrame(anim, frame, piece)
9174 XRectangle updates[4];
9179 /* Save what we are about to draw into the new buffer */
9180 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9181 frame->x, frame->y, squareSize, squareSize,
9184 /* Erase bits of the previous frame */
9185 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9186 /* Where the new frame overlapped the previous,
9187 the contents in newBuf are wrong. */
9188 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9189 overlap.x, overlap.y,
9190 overlap.width, overlap.height,
9192 /* Repaint the areas in the old that don't overlap new */
9193 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9194 for (i = 0; i < count; i++)
9195 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9196 updates[i].x - anim->prevFrame.x,
9197 updates[i].y - anim->prevFrame.y,
9198 updates[i].width, updates[i].height,
9199 updates[i].x, updates[i].y);
9201 /* Easy when no overlap */
9202 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9203 0, 0, squareSize, squareSize,
9204 anim->prevFrame.x, anim->prevFrame.y);
9207 /* Save this frame for next time round */
9208 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9209 0, 0, squareSize, squareSize,
9211 anim->prevFrame = *frame;
9213 /* Draw piece over original screen contents, not current,
9214 and copy entire rect. Wipes out overlapping piece images. */
9215 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9216 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9217 0, 0, squareSize, squareSize,
9218 frame->x, frame->y);
9222 EndAnimation (anim, finish)
9226 XRectangle updates[4];
9231 /* The main code will redraw the final square, so we
9232 only need to erase the bits that don't overlap. */
9233 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9234 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9235 for (i = 0; i < count; i++)
9236 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9237 updates[i].x - anim->prevFrame.x,
9238 updates[i].y - anim->prevFrame.y,
9239 updates[i].width, updates[i].height,
9240 updates[i].x, updates[i].y);
9242 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9243 0, 0, squareSize, squareSize,
9244 anim->prevFrame.x, anim->prevFrame.y);
9249 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9251 ChessSquare piece; int startColor;
9252 XPoint * start; XPoint * finish;
9253 XPoint frames[]; int nFrames;
9257 BeginAnimation(anim, piece, startColor, start);
9258 for (n = 0; n < nFrames; n++) {
9259 AnimationFrame(anim, &(frames[n]), piece);
9260 FrameDelay(appData.animSpeed);
9262 EndAnimation(anim, finish);
9265 /* Main control logic for deciding what to animate and how */
9268 AnimateMove(board, fromX, fromY, toX, toY)
9277 XPoint start, finish, mid;
9278 XPoint frames[kFactor * 2 + 1];
9279 int nFrames, startColor, endColor;
9281 /* Are we animating? */
9282 if (!appData.animate || appData.blindfold)
9285 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9286 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9287 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9289 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9290 piece = board[fromY][fromX];
9291 if (piece >= EmptySquare) return;
9296 hop = (piece == WhiteKnight || piece == BlackKnight);
9299 if (appData.debugMode) {
9300 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9301 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9302 piece, fromX, fromY, toX, toY); }
9304 ScreenSquare(fromX, fromY, &start, &startColor);
9305 ScreenSquare(toX, toY, &finish, &endColor);
9308 /* Knight: make diagonal movement then straight */
9309 if (abs(toY - fromY) < abs(toX - fromX)) {
9310 mid.x = start.x + (finish.x - start.x) / 2;
9314 mid.y = start.y + (finish.y - start.y) / 2;
9317 mid.x = start.x + (finish.x - start.x) / 2;
9318 mid.y = start.y + (finish.y - start.y) / 2;
9321 /* Don't use as many frames for very short moves */
9322 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9323 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9325 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9326 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9328 /* Be sure end square is redrawn */
9329 damage[toY][toX] = True;
9333 DragPieceBegin(x, y)
9336 int boardX, boardY, color;
9339 /* Are we animating? */
9340 if (!appData.animateDragging || appData.blindfold)
9343 /* Figure out which square we start in and the
9344 mouse position relative to top left corner. */
9345 BoardSquare(x, y, &boardX, &boardY);
9346 player.startBoardX = boardX;
9347 player.startBoardY = boardY;
9348 ScreenSquare(boardX, boardY, &corner, &color);
9349 player.startSquare = corner;
9350 player.startColor = color;
9351 /* As soon as we start dragging, the piece will jump slightly to
9352 be centered over the mouse pointer. */
9353 player.mouseDelta.x = squareSize/2;
9354 player.mouseDelta.y = squareSize/2;
9355 /* Initialise animation */
9356 player.dragPiece = PieceForSquare(boardX, boardY);
9358 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9359 player.dragActive = True;
9360 BeginAnimation(&player, player.dragPiece, color, &corner);
9361 /* Mark this square as needing to be redrawn. Note that
9362 we don't remove the piece though, since logically (ie
9363 as seen by opponent) the move hasn't been made yet. */
9364 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9365 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9366 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9367 corner.x, corner.y, squareSize, squareSize,
9368 0, 0); // [HGM] zh: unstack in stead of grab
9369 damage[boardY][boardX] = True;
9371 player.dragActive = False;
9381 /* Are we animating? */
9382 if (!appData.animateDragging || appData.blindfold)
9386 if (! player.dragActive)
9388 /* Move piece, maintaining same relative position
9389 of mouse within square */
9390 corner.x = x - player.mouseDelta.x;
9391 corner.y = y - player.mouseDelta.y;
9392 AnimationFrame(&player, &corner, player.dragPiece);
9394 if (appData.highlightDragging) {
9396 BoardSquare(x, y, &boardX, &boardY);
9397 SetHighlights(fromX, fromY, boardX, boardY);
9406 int boardX, boardY, color;
9409 /* Are we animating? */
9410 if (!appData.animateDragging || appData.blindfold)
9414 if (! player.dragActive)
9416 /* Last frame in sequence is square piece is
9417 placed on, which may not match mouse exactly. */
9418 BoardSquare(x, y, &boardX, &boardY);
9419 ScreenSquare(boardX, boardY, &corner, &color);
9420 EndAnimation(&player, &corner);
9422 /* Be sure end square is redrawn */
9423 damage[boardY][boardX] = True;
9425 /* This prevents weird things happening with fast successive
9426 clicks which on my Sun at least can cause motion events
9427 without corresponding press/release. */
9428 player.dragActive = False;
9431 /* Handle expose event while piece being dragged */
9436 if (!player.dragActive || appData.blindfold)
9439 /* What we're doing: logically, the move hasn't been made yet,
9440 so the piece is still in it's original square. But visually
9441 it's being dragged around the board. So we erase the square
9442 that the piece is on and draw it at the last known drag point. */
9443 BlankSquare(player.startSquare.x, player.startSquare.y,
9444 player.startColor, EmptySquare, xBoardWindow);
9445 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9446 damage[player.startBoardY][player.startBoardX] = TRUE;
9450 SetProgramStats( FrontEndProgramStats * stats )
9453 // [HGM] done, but perhaps backend should call this directly?
9454 EngineOutputUpdate( stats );
9457 #include <sys/ioctl.h>
9458 int get_term_width()
9460 int fd, default_width;
9463 default_width = 79; // this is FICS default anyway...
9465 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9467 if (!ioctl(fd, TIOCGSIZE, &win))
9468 default_width = win.ts_cols;
9469 #elif defined(TIOCGWINSZ)
9471 if (!ioctl(fd, TIOCGWINSZ, &win))
9472 default_width = win.ws_col;
9474 return default_width;
9477 void update_ics_width()
9479 static int old_width = 0;
9480 int new_width = get_term_width();
9482 if (old_width != new_width)
9483 ics_printf("set width %d\n", new_width);
9484 old_width = new_width;
9487 void NotifyFrontendLogin()