2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
147 #include <X11/Xmu/Atoms.h>
149 #include <X11/Xaw3d/Dialog.h>
150 #include <X11/Xaw3d/Form.h>
151 #include <X11/Xaw3d/List.h>
152 #include <X11/Xaw3d/Label.h>
153 #include <X11/Xaw3d/SimpleMenu.h>
154 #include <X11/Xaw3d/SmeBSB.h>
155 #include <X11/Xaw3d/SmeLine.h>
156 #include <X11/Xaw3d/Box.h>
157 #include <X11/Xaw3d/MenuButton.h>
158 #include <X11/Xaw3d/Text.h>
159 #include <X11/Xaw3d/AsciiText.h>
161 #include <X11/Xaw/Dialog.h>
162 #include <X11/Xaw/Form.h>
163 #include <X11/Xaw/List.h>
164 #include <X11/Xaw/Label.h>
165 #include <X11/Xaw/SimpleMenu.h>
166 #include <X11/Xaw/SmeBSB.h>
167 #include <X11/Xaw/SmeLine.h>
168 #include <X11/Xaw/Box.h>
169 #include <X11/Xaw/MenuButton.h>
170 #include <X11/Xaw/Text.h>
171 #include <X11/Xaw/AsciiText.h>
174 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
179 #include "pixmaps/pixmaps.h"
180 #define IMAGE_EXT "xpm"
182 #define IMAGE_EXT "xim"
183 #include "bitmaps/bitmaps.h"
186 #include "bitmaps/icon_white.bm"
187 #include "bitmaps/icon_black.bm"
188 #include "bitmaps/checkmark.bm"
190 #include "frontend.h"
195 #include "xgamelist.h"
196 #include "xhistory.h"
197 #include "xedittags.h"
200 // must be moved to xengineoutput.h
202 void EngineOutputProc P((Widget w, XEvent *event,
203 String *prms, Cardinal *nprms));
205 void EngineOutputPopDown();
212 #define usleep(t) _sleep2(((t)+500)/1000)
216 # define _(s) gettext (s)
217 # define N_(s) gettext_noop (s)
233 int main P((int argc, char **argv));
234 RETSIGTYPE CmailSigHandler P((int sig));
235 RETSIGTYPE IntSigHandler P((int sig));
236 RETSIGTYPE TermSizeSigHandler P((int sig));
237 void CreateGCs P((void));
238 void CreateXIMPieces P((void));
239 void CreateXPMPieces P((void));
240 void CreatePieces P((void));
241 void CreatePieceMenus P((void));
242 Widget CreateMenuBar P((Menu *mb));
243 Widget CreateButtonBar P ((MenuItem *mi));
244 char *FindFont P((char *pattern, int targetPxlSize));
245 void PieceMenuPopup P((Widget w, XEvent *event,
246 String *params, Cardinal *num_params));
247 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
248 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
249 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
250 u_int wreq, u_int hreq));
251 void CreateGrid P((void));
252 int EventToSquare P((int x, int limit));
253 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
254 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
255 void HandleUserMove P((Widget w, XEvent *event,
256 String *prms, Cardinal *nprms));
257 void AnimateUserMove P((Widget w, XEvent * event,
258 String * params, Cardinal * nParams));
259 void WhiteClock P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void BlackClock P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void DrawPositionProc P((Widget w, XEvent *event,
264 String *prms, Cardinal *nprms));
265 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
267 void CommentPopUp P((char *title, char *label));
268 void CommentPopDown P((void));
269 void CommentCallback P((Widget w, XtPointer client_data,
270 XtPointer call_data));
271 void ICSInputBoxPopUp P((void));
272 void ICSInputBoxPopDown P((void));
273 void FileNamePopUp P((char *label, char *def,
274 FileProc proc, char *openMode));
275 void FileNamePopDown P((void));
276 void FileNameCallback P((Widget w, XtPointer client_data,
277 XtPointer call_data));
278 void FileNameAction P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void AskQuestionReplyAction P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionProc P((Widget w, XEvent *event,
283 String *prms, Cardinal *nprms));
284 void AskQuestionPopDown 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 DragPieceMove P((int x, int y));
432 static void DrawDragPiece P((void));
433 char *ModeToWidgetName P((GameMode mode));
434 void EngineOutputUpdate( FrontEndProgramStats * stats );
435 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void ShufflePopDown P(());
443 void EnginePopDown P(());
444 void UciPopDown P(());
445 void TimeControlPopDown P(());
446 void NewVariantPopDown P(());
447 void SettingsPopDown P(());
448 void update_ics_width P(());
449 int get_term_width P(());
451 * XBoard depends on Xt R4 or higher
453 int xtVersion = XtSpecificationRelease;
458 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
459 jailSquareColor, highlightSquareColor, premoveHighlightColor;
460 Pixel lowTimeWarningColor;
461 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
462 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
463 wjPieceGC, bjPieceGC, prelineGC, countGC;
464 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
465 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
466 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
467 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
468 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
469 ICSInputShell, fileNameShell, askQuestionShell;
470 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
471 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
472 Font clockFontID, coordFontID, countFontID;
473 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
474 XtAppContext appContext;
476 char *oldICSInteractionTitle;
480 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
482 Position commentX = -1, commentY = -1;
483 Dimension commentW, commentH;
485 int squareSize, smallLayout = 0, tinyLayout = 0,
486 marginW, marginH, // [HGM] for run-time resizing
487 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
488 ICSInputBoxUp = False, askQuestionUp = False,
489 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
490 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
491 Pixel timerForegroundPixel, timerBackgroundPixel;
492 Pixel buttonForegroundPixel, buttonBackgroundPixel;
493 char *chessDir, *programName, *programVersion,
494 *gameCopyFilename, *gamePasteFilename;
498 Pixmap pieceBitmap[2][(int)BlackPawn];
499 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
500 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
501 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
502 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
503 int useImages, useImageSqs;
504 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
505 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
506 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
507 XImage *ximLightSquare, *ximDarkSquare;
510 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
511 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
513 #define White(piece) ((int)(piece) < (int)BlackPawn)
515 /* Variables for doing smooth animation. This whole thing
516 would be much easier if the board was double-buffered,
517 but that would require a fairly major rewrite. */
522 GC blitGC, pieceGC, outlineGC;
523 XPoint startSquare, prevFrame, mouseDelta;
527 int startBoardX, startBoardY;
530 /* There can be two pieces being animated at once: a player
531 can begin dragging a piece before the remote opponent has moved. */
533 static AnimState game, player;
535 /* Bitmaps for use as masks when drawing XPM pieces.
536 Need one for each black and white piece. */
537 static Pixmap xpmMask[BlackKing + 1];
539 /* This magic number is the number of intermediate frames used
540 in each half of the animation. For short moves it's reduced
541 by 1. The total number of frames will be factor * 2 + 1. */
544 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
546 MenuItem fileMenu[] = {
547 {N_("New Game"), ResetProc},
548 {N_("New Shuffle Game ..."), ShuffleMenuProc},
549 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
550 {"----", NothingProc},
551 {N_("Load Game"), LoadGameProc},
552 {N_("Load Next Game"), LoadNextGameProc},
553 {N_("Load Previous Game"), LoadPrevGameProc},
554 {N_("Reload Same Game"), ReloadGameProc},
555 {N_("Save Game"), SaveGameProc},
556 {"----", NothingProc},
557 {N_("Copy Game"), CopyGameProc},
558 {N_("Paste Game"), PasteGameProc},
559 {"----", NothingProc},
560 {N_("Load Position"), LoadPositionProc},
561 {N_("Load Next Position"), LoadNextPositionProc},
562 {N_("Load Previous Position"), LoadPrevPositionProc},
563 {N_("Reload Same Position"), ReloadPositionProc},
564 {N_("Save Position"), SavePositionProc},
565 {"----", NothingProc},
566 {N_("Copy Position"), CopyPositionProc},
567 {N_("Paste Position"), PastePositionProc},
568 {"----", NothingProc},
569 {N_("Mail Move"), MailMoveProc},
570 {N_("Reload CMail Message"), ReloadCmailMsgProc},
571 {"----", NothingProc},
572 {N_("Exit"), QuitProc},
576 MenuItem modeMenu[] = {
577 {N_("Machine White"), MachineWhiteProc},
578 {N_("Machine Black"), MachineBlackProc},
579 {N_("Two Machines"), TwoMachinesProc},
580 {N_("Analysis Mode"), AnalyzeModeProc},
581 {N_("Analyze File"), AnalyzeFileProc },
582 {N_("ICS Client"), IcsClientProc},
583 {N_("Edit Game"), EditGameProc},
584 {N_("Edit Position"), EditPositionProc},
585 {N_("Training"), TrainingProc},
586 {"----", NothingProc},
587 {N_("Show Engine Output"), EngineOutputProc},
588 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
589 {N_("Show Game List"), ShowGameListProc},
590 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
591 {"----", NothingProc},
592 {N_("Edit Tags"), EditTagsProc},
593 {N_("Edit Comment"), EditCommentProc},
594 {N_("ICS Input Box"), IcsInputBoxProc},
595 {N_("Pause"), PauseProc},
599 MenuItem actionMenu[] = {
600 {N_("Accept"), AcceptProc},
601 {N_("Decline"), DeclineProc},
602 {N_("Rematch"), RematchProc},
603 {"----", NothingProc},
604 {N_("Call Flag"), CallFlagProc},
605 {N_("Draw"), DrawProc},
606 {N_("Adjourn"), AdjournProc},
607 {N_("Abort"), AbortProc},
608 {N_("Resign"), ResignProc},
609 {"----", NothingProc},
610 {N_("Stop Observing"), StopObservingProc},
611 {N_("Stop Examining"), StopExaminingProc},
612 {"----", NothingProc},
613 {N_("Adjudicate to White"), AdjuWhiteProc},
614 {N_("Adjudicate to Black"), AdjuBlackProc},
615 {N_("Adjudicate Draw"), AdjuDrawProc},
619 MenuItem stepMenu[] = {
620 {N_("Backward"), BackwardProc},
621 {N_("Forward"), ForwardProc},
622 {N_("Back to Start"), ToStartProc},
623 {N_("Forward to End"), ToEndProc},
624 {N_("Revert"), RevertProc},
625 {N_("Truncate Game"), TruncateGameProc},
626 {"----", NothingProc},
627 {N_("Move Now"), MoveNowProc},
628 {N_("Retract Move"), RetractMoveProc},
632 MenuItem optionsMenu[] = {
633 {N_("Flip View"), FlipViewProc},
634 {"----", NothingProc},
635 {N_("Adjudications ..."), EngineMenuProc},
636 {N_("General Settings ..."), UciMenuProc},
637 {N_("Engine #1 Settings ..."), FirstSettingsProc},
638 {N_("Engine #2 Settings ..."), SecondSettingsProc},
639 {N_("Time Control ..."), TimeControlProc},
640 {"----", NothingProc},
641 {N_("Always Queen"), AlwaysQueenProc},
642 {N_("Animate Dragging"), AnimateDraggingProc},
643 {N_("Animate Moving"), AnimateMovingProc},
644 {N_("Auto Comment"), AutocommProc},
645 {N_("Auto Flag"), AutoflagProc},
646 {N_("Auto Flip View"), AutoflipProc},
647 {N_("Auto Observe"), AutobsProc},
648 {N_("Auto Raise Board"), AutoraiseProc},
649 {N_("Auto Save"), AutosaveProc},
650 {N_("Blindfold"), BlindfoldProc},
651 {N_("Flash Moves"), FlashMovesProc},
652 {N_("Get Move List"), GetMoveListProc},
654 {N_("Highlight Dragging"), HighlightDraggingProc},
656 {N_("Highlight Last Move"), HighlightLastMoveProc},
657 {N_("Move Sound"), MoveSoundProc},
658 {N_("ICS Alarm"), IcsAlarmProc},
659 {N_("Old Save Style"), OldSaveStyleProc},
660 {N_("Periodic Updates"), PeriodicUpdatesProc},
661 {N_("Ponder Next Move"), PonderNextMoveProc},
662 {N_("Popup Exit Message"), PopupExitMessageProc},
663 {N_("Popup Move Errors"), PopupMoveErrorsProc},
664 {N_("Premove"), PremoveProc},
665 {N_("Quiet Play"), QuietPlayProc},
666 {N_("Show Coords"), ShowCoordsProc},
667 {N_("Hide Thinking"), HideThinkingProc},
668 {N_("Test Legality"), TestLegalityProc},
672 MenuItem helpMenu[] = {
673 {N_("Info XBoard"), InfoProc},
674 {N_("Man XBoard"), ManProc},
675 {"----", NothingProc},
676 {N_("Hint"), HintProc},
677 {N_("Book"), BookProc},
678 {"----", NothingProc},
679 {N_("About XBoard"), AboutProc},
684 {N_("File"), fileMenu},
685 {N_("Mode"), modeMenu},
686 {N_("Action"), actionMenu},
687 {N_("Step"), stepMenu},
688 {N_("Options"), optionsMenu},
689 {N_("Help"), helpMenu},
693 #define PAUSE_BUTTON N_("P")
694 MenuItem buttonBar[] = {
697 {PAUSE_BUTTON, PauseProc},
703 #define PIECE_MENU_SIZE 18
704 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
705 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
706 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
707 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
708 N_("Empty square"), N_("Clear board") },
709 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
710 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
711 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
712 N_("Empty square"), N_("Clear board") }
714 /* must be in same order as PieceMenuStrings! */
715 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
716 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
717 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
718 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
719 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
720 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
721 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
722 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
723 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
726 #define DROP_MENU_SIZE 6
727 String dropMenuStrings[DROP_MENU_SIZE] = {
728 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
730 /* must be in same order as PieceMenuStrings! */
731 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
732 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
733 WhiteRook, WhiteQueen
741 DropMenuEnables dmEnables[] = {
759 { XtNborderWidth, 0 },
760 { XtNdefaultDistance, 0 },
764 { XtNborderWidth, 0 },
765 { XtNresizable, (XtArgVal) True },
769 { XtNborderWidth, 0 },
775 { XtNjustify, (XtArgVal) XtJustifyRight },
776 { XtNlabel, (XtArgVal) "..." },
777 { XtNresizable, (XtArgVal) True },
778 { XtNresize, (XtArgVal) False }
781 Arg messageArgs[] = {
782 { XtNjustify, (XtArgVal) XtJustifyLeft },
783 { XtNlabel, (XtArgVal) "..." },
784 { XtNresizable, (XtArgVal) True },
785 { XtNresize, (XtArgVal) False }
789 { XtNborderWidth, 0 },
790 { XtNjustify, (XtArgVal) XtJustifyLeft }
793 XtResource clientResources[] = {
794 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
795 XtOffset(AppDataPtr, whitePieceColor), XtRString,
797 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
798 XtOffset(AppDataPtr, blackPieceColor), XtRString,
800 { "lightSquareColor", "lightSquareColor", XtRString,
801 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
802 XtRString, LIGHT_SQUARE_COLOR },
803 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
804 XtOffset(AppDataPtr, darkSquareColor), XtRString,
806 { "highlightSquareColor", "highlightSquareColor", XtRString,
807 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
808 XtRString, HIGHLIGHT_SQUARE_COLOR },
809 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
810 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
811 XtRString, PREMOVE_HIGHLIGHT_COLOR },
812 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
813 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
814 (XtPointer) MOVES_PER_SESSION },
815 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
816 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
817 (XtPointer) TIME_INCREMENT },
818 { "initString", "initString", XtRString, sizeof(String),
819 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
820 { "secondInitString", "secondInitString", XtRString, sizeof(String),
821 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
822 { "firstComputerString", "firstComputerString", XtRString,
823 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
825 { "secondComputerString", "secondComputerString", XtRString,
826 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
828 { "firstChessProgram", "firstChessProgram", XtRString,
829 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
830 XtRString, FIRST_CHESS_PROGRAM },
831 { "secondChessProgram", "secondChessProgram", XtRString,
832 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
833 XtRString, SECOND_CHESS_PROGRAM },
834 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
835 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
836 XtRImmediate, (XtPointer) False },
837 { "noChessProgram", "noChessProgram", XtRBoolean,
838 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
839 XtRImmediate, (XtPointer) False },
840 { "firstHost", "firstHost", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
842 { "secondHost", "secondHost", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
844 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
846 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
847 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
848 { "bitmapDirectory", "bitmapDirectory", XtRString,
849 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
851 { "remoteShell", "remoteShell", XtRString, sizeof(String),
852 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
853 { "remoteUser", "remoteUser", XtRString, sizeof(String),
854 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
855 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
856 XtOffset(AppDataPtr, timeDelay), XtRString,
857 (XtPointer) TIME_DELAY_QUOTE },
858 { "timeControl", "timeControl", XtRString, sizeof(String),
859 XtOffset(AppDataPtr, timeControl), XtRString,
860 (XtPointer) TIME_CONTROL },
861 { "internetChessServerMode", "internetChessServerMode",
862 XtRBoolean, sizeof(Boolean),
863 XtOffset(AppDataPtr, icsActive), XtRImmediate,
865 { "internetChessServerHost", "internetChessServerHost",
866 XtRString, sizeof(String),
867 XtOffset(AppDataPtr, icsHost),
868 XtRString, (XtPointer) ICS_HOST },
869 { "internetChessServerPort", "internetChessServerPort",
870 XtRString, sizeof(String),
871 XtOffset(AppDataPtr, icsPort), XtRString,
872 (XtPointer) ICS_PORT },
873 { "internetChessServerCommPort", "internetChessServerCommPort",
874 XtRString, sizeof(String),
875 XtOffset(AppDataPtr, icsCommPort), XtRString,
877 { "internetChessServerLogonScript", "internetChessServerLogonScript",
878 XtRString, sizeof(String),
879 XtOffset(AppDataPtr, icsLogon), XtRString,
881 { "internetChessServerHelper", "internetChessServerHelper",
882 XtRString, sizeof(String),
883 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
884 { "internetChessServerInputBox", "internetChessServerInputBox",
885 XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
888 { "icsAlarm", "icsAlarm",
889 XtRBoolean, sizeof(Boolean),
890 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
892 { "icsAlarmTime", "icsAlarmTime",
894 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
896 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
897 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
899 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
900 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
901 { "gateway", "gateway", XtRString, sizeof(String),
902 XtOffset(AppDataPtr, gateway), XtRString, "" },
903 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
904 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
905 { "loadGameIndex", "loadGameIndex",
907 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
909 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
910 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
911 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
912 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
913 XtRImmediate, (XtPointer) True },
914 { "autoSaveGames", "autoSaveGames", XtRBoolean,
915 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
916 XtRImmediate, (XtPointer) False },
917 { "blindfold", "blindfold", XtRBoolean,
918 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
919 XtRImmediate, (XtPointer) False },
920 { "loadPositionFile", "loadPositionFile", XtRString,
921 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
923 { "loadPositionIndex", "loadPositionIndex",
925 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
927 { "savePositionFile", "savePositionFile", XtRString,
928 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
930 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
931 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
932 { "matchGames", "matchGames", XtRInt, sizeof(int),
933 XtOffset(AppDataPtr, matchGames), XtRImmediate,
935 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
936 XtOffset(AppDataPtr, monoMode), XtRImmediate,
938 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
939 XtOffset(AppDataPtr, debugMode), XtRImmediate,
941 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
942 XtOffset(AppDataPtr, clockMode), XtRImmediate,
944 { "boardSize", "boardSize", XtRString, sizeof(String),
945 XtOffset(AppDataPtr, boardSize), XtRString, "" },
946 { "searchTime", "searchTime", XtRString, sizeof(String),
947 XtOffset(AppDataPtr, searchTime), XtRString,
949 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
950 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
952 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
953 XtOffset(AppDataPtr, showCoords), XtRImmediate,
955 { "showJail", "showJail", XtRInt, sizeof(int),
956 XtOffset(AppDataPtr, showJail), XtRImmediate,
958 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
959 XtOffset(AppDataPtr, showThinking), XtRImmediate,
961 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
962 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
964 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
965 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
967 { "clockFont", "clockFont", XtRString, sizeof(String),
968 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
969 { "coordFont", "coordFont", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
971 { "font", "font", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
973 { "ringBellAfterMoves", "ringBellAfterMoves",
974 XtRBoolean, sizeof(Boolean),
975 XtOffset(AppDataPtr, ringBellAfterMoves),
976 XtRImmediate, (XtPointer) False },
977 { "autoCallFlag", "autoCallFlag", XtRBoolean,
978 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
979 XtRImmediate, (XtPointer) False },
980 { "autoFlipView", "autoFlipView", XtRBoolean,
981 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
982 XtRImmediate, (XtPointer) True },
983 { "autoObserve", "autoObserve", XtRBoolean,
984 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
985 XtRImmediate, (XtPointer) False },
986 { "autoComment", "autoComment", XtRBoolean,
987 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
988 XtRImmediate, (XtPointer) False },
989 { "getMoveList", "getMoveList", XtRBoolean,
990 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
991 XtRImmediate, (XtPointer) True },
993 { "highlightDragging", "highlightDragging", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
995 XtRImmediate, (XtPointer) False },
997 { "highlightLastMove", "highlightLastMove", XtRBoolean,
998 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
999 XtRImmediate, (XtPointer) False },
1000 { "premove", "premove", XtRBoolean,
1001 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1002 XtRImmediate, (XtPointer) True },
1003 { "testLegality", "testLegality", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1005 XtRImmediate, (XtPointer) True },
1006 { "flipView", "flipView", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1008 XtRImmediate, (XtPointer) False },
1009 { "cmail", "cmailGameName", XtRString, sizeof(String),
1010 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1011 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1012 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1013 XtRImmediate, (XtPointer) False },
1014 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1015 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1016 XtRImmediate, (XtPointer) False },
1017 { "quietPlay", "quietPlay", XtRBoolean,
1018 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1019 XtRImmediate, (XtPointer) False },
1020 { "titleInWindow", "titleInWindow", XtRBoolean,
1021 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1022 XtRImmediate, (XtPointer) False },
1023 { "localLineEditing", "localLineEditing", XtRBoolean,
1024 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1025 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1027 { "zippyTalk", "zippyTalk", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1029 XtRImmediate, (XtPointer) ZIPPY_TALK },
1030 { "zippyPlay", "zippyPlay", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1032 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1033 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1034 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1035 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1037 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1039 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1041 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1042 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1043 ZIPPY_WRONG_PASSWORD },
1044 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1045 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1046 { "zippyUseI", "zippyUseI", XtRBoolean,
1047 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1048 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1049 { "zippyBughouse", "zippyBughouse", XtRInt,
1050 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1051 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1052 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1053 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1054 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1055 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1056 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1057 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1058 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1059 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1060 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1061 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1062 { "zippyAbort", "zippyAbort", XtRBoolean,
1063 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1064 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1065 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1066 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1067 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1068 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1069 (XtPointer) ZIPPY_MAX_GAMES },
1070 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1071 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1072 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1073 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1074 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1077 { "flashCount", "flashCount", XtRInt, sizeof(int),
1078 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1079 (XtPointer) FLASH_COUNT },
1080 { "flashRate", "flashRate", XtRInt, sizeof(int),
1081 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1082 (XtPointer) FLASH_RATE },
1083 { "pixmapDirectory", "pixmapDirectory", XtRString,
1084 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1086 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1087 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1088 (XtPointer) MS_LOGIN_DELAY },
1089 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1090 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1091 XtRImmediate, (XtPointer) False },
1092 { "colorShout", "colorShout", XtRString,
1093 sizeof(String), XtOffset(AppDataPtr, colorShout),
1094 XtRString, COLOR_SHOUT },
1095 { "colorSShout", "colorSShout", XtRString,
1096 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1097 XtRString, COLOR_SSHOUT },
1098 { "colorChannel1", "colorChannel1", XtRString,
1099 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1100 XtRString, COLOR_CHANNEL1 },
1101 { "colorChannel", "colorChannel", XtRString,
1102 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1103 XtRString, COLOR_CHANNEL },
1104 { "colorKibitz", "colorKibitz", XtRString,
1105 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1106 XtRString, COLOR_KIBITZ },
1107 { "colorTell", "colorTell", XtRString,
1108 sizeof(String), XtOffset(AppDataPtr, colorTell),
1109 XtRString, COLOR_TELL },
1110 { "colorChallenge", "colorChallenge", XtRString,
1111 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1112 XtRString, COLOR_CHALLENGE },
1113 { "colorRequest", "colorRequest", XtRString,
1114 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1115 XtRString, COLOR_REQUEST },
1116 { "colorSeek", "colorSeek", XtRString,
1117 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1118 XtRString, COLOR_SEEK },
1119 { "colorNormal", "colorNormal", XtRString,
1120 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1121 XtRString, COLOR_NORMAL },
1122 { "soundProgram", "soundProgram", XtRString,
1123 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1124 XtRString, "play" },
1125 { "soundShout", "soundShout", XtRString,
1126 sizeof(String), XtOffset(AppDataPtr, soundShout),
1128 { "soundSShout", "soundSShout", XtRString,
1129 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1131 { "soundChannel1", "soundChannel1", XtRString,
1132 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1134 { "soundChannel", "soundChannel", XtRString,
1135 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1137 { "soundKibitz", "soundKibitz", XtRString,
1138 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1140 { "soundTell", "soundTell", XtRString,
1141 sizeof(String), XtOffset(AppDataPtr, soundTell),
1143 { "soundChallenge", "soundChallenge", XtRString,
1144 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1146 { "soundRequest", "soundRequest", XtRString,
1147 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1149 { "soundSeek", "soundSeek", XtRString,
1150 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1152 { "soundMove", "soundMove", XtRString,
1153 sizeof(String), XtOffset(AppDataPtr, soundMove),
1155 { "soundIcsWin", "soundIcsWin", XtRString,
1156 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1158 { "soundIcsLoss", "soundIcsLoss", XtRString,
1159 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1161 { "soundIcsDraw", "soundIcsDraw", XtRString,
1162 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1164 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1165 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1167 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1168 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1170 { "reuseFirst", "reuseFirst", XtRBoolean,
1171 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1172 XtRImmediate, (XtPointer) True },
1173 { "reuseSecond", "reuseSecond", XtRBoolean,
1174 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1175 XtRImmediate, (XtPointer) True },
1176 { "animateDragging", "animateDragging", XtRBoolean,
1177 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1178 XtRImmediate, (XtPointer) True },
1179 { "animateMoving", "animateMoving", XtRBoolean,
1180 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1181 XtRImmediate, (XtPointer) True },
1182 { "animateSpeed", "animateSpeed", XtRInt,
1183 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1184 XtRImmediate, (XtPointer)10 },
1185 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1186 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1187 XtRImmediate, (XtPointer) True },
1188 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1189 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1190 XtRImmediate, (XtPointer) False },
1191 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1192 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1193 XtRImmediate, (XtPointer)4 },
1194 { "initialMode", "initialMode", XtRString,
1195 sizeof(String), XtOffset(AppDataPtr, initialMode),
1196 XtRImmediate, (XtPointer) "" },
1197 { "variant", "variant", XtRString,
1198 sizeof(String), XtOffset(AppDataPtr, variant),
1199 XtRImmediate, (XtPointer) "normal" },
1200 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1201 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1202 XtRImmediate, (XtPointer)PROTOVER },
1203 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1204 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1205 XtRImmediate, (XtPointer)PROTOVER },
1206 { "showButtonBar", "showButtonBar", XtRBoolean,
1207 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1208 XtRImmediate, (XtPointer) True },
1209 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1210 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1211 XtRString, COLOR_LOWTIMEWARNING },
1212 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1213 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1214 XtRImmediate, (XtPointer) False },
1215 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1216 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1217 XtRImmediate, (XtPointer) False },
1218 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1219 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1220 XtRImmediate, (XtPointer) False },
1221 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1222 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1223 XtRImmediate, (XtPointer) False },
1224 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1225 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1226 XtRImmediate, (XtPointer) False },
1227 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1229 XtRImmediate, (XtPointer) True },
1230 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1232 XtRImmediate, (XtPointer) 0},
1233 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1234 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1235 XtRImmediate, (XtPointer) 0},
1236 { "pgnEventHeader", "pgnEventHeader", XtRString,
1237 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1238 XtRImmediate, (XtPointer) "Computer Chess Game" },
1239 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1240 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1241 XtRImmediate, (XtPointer) -1},
1242 { "gameListTags", "gameListTags", XtRString,
1243 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1244 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1246 // [HGM] 4.3.xx options
1247 { "boardWidth", "boardWidth", XtRInt,
1248 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1249 XtRImmediate, (XtPointer) -1},
1250 { "boardHeight", "boardHeight", XtRInt,
1251 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1252 XtRImmediate, (XtPointer) -1},
1253 { "matchPause", "matchPause", XtRInt,
1254 sizeof(int), XtOffset(AppDataPtr, matchPause),
1255 XtRImmediate, (XtPointer) 10000},
1256 { "holdingsSize", "holdingsSize", XtRInt,
1257 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1258 XtRImmediate, (XtPointer) -1},
1259 { "flipBlack", "flipBlack", XtRBoolean,
1260 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1261 XtRImmediate, (XtPointer) False},
1262 { "allWhite", "allWhite", XtRBoolean,
1263 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1264 XtRImmediate, (XtPointer) False},
1265 { "pieceToCharTable", "pieceToCharTable", XtRString,
1266 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1267 XtRImmediate, (XtPointer) 0},
1268 { "alphaRank", "alphaRank", XtRBoolean,
1269 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1270 XtRImmediate, (XtPointer) False},
1271 { "testClaims", "testClaims", XtRBoolean,
1272 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1273 XtRImmediate, (XtPointer) True},
1274 { "checkMates", "checkMates", XtRBoolean,
1275 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1276 XtRImmediate, (XtPointer) True},
1277 { "materialDraws", "materialDraws", XtRBoolean,
1278 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1279 XtRImmediate, (XtPointer) True},
1280 { "trivialDraws", "trivialDraws", XtRBoolean,
1281 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1282 XtRImmediate, (XtPointer) False},
1283 { "ruleMoves", "ruleMoves", XtRInt,
1284 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1285 XtRImmediate, (XtPointer) 51},
1286 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1287 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1288 XtRImmediate, (XtPointer) 6},
1289 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1290 sizeof(int), XtOffset(AppDataPtr, engineComments),
1291 XtRImmediate, (XtPointer) 1},
1292 { "userName", "userName", XtRString,
1293 sizeof(int), XtOffset(AppDataPtr, userName),
1294 XtRImmediate, (XtPointer) 0},
1295 { "autoKibitz", "autoKibitz", XtRBoolean,
1296 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1297 XtRImmediate, (XtPointer) False},
1298 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1299 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1300 XtRImmediate, (XtPointer) 1},
1301 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1302 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1303 XtRImmediate, (XtPointer) 1},
1304 { "timeOddsMode", "timeOddsMode", XtRInt,
1305 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1306 XtRImmediate, (XtPointer) 0},
1307 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1308 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1309 XtRImmediate, (XtPointer) 1},
1310 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1311 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1312 XtRImmediate, (XtPointer) 1},
1313 { "firstNPS", "firstNPS", XtRInt,
1314 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1315 XtRImmediate, (XtPointer) -1},
1316 { "secondNPS", "secondNPS", XtRInt,
1317 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1318 XtRImmediate, (XtPointer) -1},
1319 { "serverMoves", "serverMoves", XtRString,
1320 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1321 XtRImmediate, (XtPointer) 0},
1322 { "serverPause", "serverPause", XtRInt,
1323 sizeof(int), XtOffset(AppDataPtr, serverPause),
1324 XtRImmediate, (XtPointer) 0},
1325 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1326 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1327 XtRImmediate, (XtPointer) False},
1328 { "userName", "userName", XtRString,
1329 sizeof(String), XtOffset(AppDataPtr, userName),
1330 XtRImmediate, (XtPointer) 0},
1331 { "egtFormats", "egtFormats", XtRString,
1332 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1333 XtRImmediate, (XtPointer) 0},
1334 { "rewindIndex", "rewindIndex", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1336 XtRImmediate, (XtPointer) 0},
1337 { "sameColorGames", "sameColorGames", XtRInt,
1338 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1339 XtRImmediate, (XtPointer) 0},
1340 { "smpCores", "smpCores", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, smpCores),
1342 XtRImmediate, (XtPointer) 1},
1343 { "niceEngines", "niceEngines", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1345 XtRImmediate, (XtPointer) 0},
1346 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1347 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1348 XtRImmediate, (XtPointer) "xboard.debug"},
1349 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1350 sizeof(int), XtOffset(AppDataPtr, engineComments),
1351 XtRImmediate, (XtPointer) 1},
1352 { "noGUI", "noGUI", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1354 XtRImmediate, (XtPointer) 0},
1355 { "firstOptions", "firstOptions", XtRString,
1356 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1357 XtRImmediate, (XtPointer) "" },
1358 { "secondOptions", "secondOptions", XtRString,
1359 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1360 XtRImmediate, (XtPointer) "" },
1361 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1362 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1363 XtRImmediate, (XtPointer) 0 },
1364 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1365 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1366 XtRImmediate, (XtPointer) 0 },
1368 // [HGM] Winboard_x UCI options
1369 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1370 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1371 XtRImmediate, (XtPointer) False},
1372 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1373 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1374 XtRImmediate, (XtPointer) False},
1375 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1376 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1377 XtRImmediate, (XtPointer) True},
1378 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1379 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1380 XtRImmediate, (XtPointer) True},
1381 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1382 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1383 XtRImmediate, (XtPointer) False},
1384 { "defaultHashSize", "defaultHashSize", XtRInt,
1385 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1386 XtRImmediate, (XtPointer) 64},
1387 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1388 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1389 XtRImmediate, (XtPointer) 4},
1390 { "polyglotDir", "polyglotDir", XtRString,
1391 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1392 XtRImmediate, (XtPointer) "." },
1393 { "polyglotBook", "polyglotBook", XtRString,
1394 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1395 XtRImmediate, (XtPointer) "" },
1396 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1397 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1398 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1399 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1400 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1401 XtRImmediate, (XtPointer) 0},
1402 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1403 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1404 XtRImmediate, (XtPointer) 0},
1405 { "keepAlive", "keepAlive", XtRInt,
1406 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1407 XtRImmediate, (XtPointer) 0},
1408 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1409 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1410 XtRImmediate, (XtPointer) False},
1411 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1412 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1413 XtRImmediate, (XtPointer) False},
1414 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1415 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1417 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1418 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1419 XtRImmediate, (XtPointer) True},
1420 { "autoDisplayTags", "autoDisplayTags", XtRBoolean,
1421 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayTags),
1422 XtRImmediate, (XtPointer) True},
1423 { "autoDisplayComment", "autoDisplayComment", XtRBoolean,
1424 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayComment),
1425 XtRImmediate, (XtPointer) True},
1426 { "pasteSelection", "pasteSelection", XtRBoolean,
1427 sizeof(Boolean), XtOffset(AppDataPtr, pasteSelection),
1428 XtRImmediate, (XtPointer) False},
1431 XrmOptionDescRec shellOptions[] = {
1432 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1433 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1434 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1435 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1436 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1437 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1438 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1439 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1440 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1441 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1442 { "-initString", "initString", XrmoptionSepArg, NULL },
1443 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1444 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1445 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1446 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1447 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1448 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1449 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1450 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1451 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1452 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1453 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1454 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1455 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1456 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1457 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1458 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1459 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1460 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1461 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1462 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1463 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1464 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1465 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1466 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1467 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1468 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1469 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1470 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1471 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1472 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1473 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1474 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1475 { "-internetChessServerMode", "internetChessServerMode",
1476 XrmoptionSepArg, NULL },
1477 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1478 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1479 { "-internetChessServerHost", "internetChessServerHost",
1480 XrmoptionSepArg, NULL },
1481 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1482 { "-internetChessServerPort", "internetChessServerPort",
1483 XrmoptionSepArg, NULL },
1484 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1485 { "-internetChessServerCommPort", "internetChessServerCommPort",
1486 XrmoptionSepArg, NULL },
1487 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1488 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1489 XrmoptionSepArg, NULL },
1490 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1491 { "-internetChessServerHelper", "internetChessServerHelper",
1492 XrmoptionSepArg, NULL },
1493 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1494 { "-internetChessServerInputBox", "internetChessServerInputBox",
1495 XrmoptionSepArg, NULL },
1496 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1497 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1498 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1499 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1500 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1501 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1502 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1503 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1504 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1505 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1506 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1507 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1508 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1509 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1510 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1511 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1512 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1513 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1514 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1515 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1516 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1517 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1518 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1519 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1520 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1521 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1522 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1523 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1524 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1525 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1526 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1527 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1528 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1529 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1530 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1531 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1532 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1533 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1534 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1535 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1536 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1537 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1538 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1539 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1540 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1541 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1542 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1543 { "-size", "boardSize", XrmoptionSepArg, NULL },
1544 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1545 { "-st", "searchTime", XrmoptionSepArg, NULL },
1546 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1547 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1548 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1549 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1550 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1552 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1553 { "-jail", "showJail", XrmoptionNoArg, "1" },
1554 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1555 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1557 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1558 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1559 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1560 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1561 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1562 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1563 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1564 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1565 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1566 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1567 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1568 { "-font", "font", XrmoptionSepArg, NULL },
1569 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1570 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1571 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1572 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1573 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1574 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1575 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1576 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1577 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1578 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1579 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1580 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1581 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1582 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1583 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1584 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1585 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1586 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1587 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1588 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1590 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1591 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1592 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1594 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1595 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1596 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1597 { "-premove", "premove", XrmoptionSepArg, NULL },
1598 { "-pre", "premove", XrmoptionNoArg, "True" },
1599 { "-xpre", "premove", XrmoptionNoArg, "False" },
1600 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1601 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1602 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1603 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1604 { "-flip", "flipView", XrmoptionNoArg, "True" },
1605 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1606 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1607 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1608 XrmoptionSepArg, NULL },
1609 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1610 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1611 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1612 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1613 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1614 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1615 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1616 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1617 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1618 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1619 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1621 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1622 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1623 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1624 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1625 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1626 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1627 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1628 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1629 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1630 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1631 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1632 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1633 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1634 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1635 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1636 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1637 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1638 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1639 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1640 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1641 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1642 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1643 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1644 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1645 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1646 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1647 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1648 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1649 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1650 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1651 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1653 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1654 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1655 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1656 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1657 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1658 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1659 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1660 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1661 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1662 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1663 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1664 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1665 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1666 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1667 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1668 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1669 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1670 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1671 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1672 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1673 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1674 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1675 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1676 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1677 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1678 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1679 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1680 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1681 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1682 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1683 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1684 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1685 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1686 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1687 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1688 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1689 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1690 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1691 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1692 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1693 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1694 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1695 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1696 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1697 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1698 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1699 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1700 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1701 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1702 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1703 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1704 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1705 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1706 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1707 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1708 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1709 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1710 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1711 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1712 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1713 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1714 { "-variant", "variant", XrmoptionSepArg, NULL },
1715 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1716 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1717 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1718 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1719 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1720 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1721 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1722 /* [AS,HR] New features */
1723 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1724 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1725 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1726 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1727 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1728 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1729 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1730 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1731 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1732 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1733 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1734 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1735 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1736 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1737 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1738 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1739 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1740 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1741 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1742 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1743 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1744 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1745 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1746 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1747 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1748 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1750 /* [HGM,HR] User-selectable board size */
1751 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1752 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1753 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1755 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1756 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1757 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1758 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1759 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1760 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1761 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1762 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1763 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1764 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1765 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1766 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1767 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1768 { "-userName", "userName", XrmoptionSepArg, NULL },
1769 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1770 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1771 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1772 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1773 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1774 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1775 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1776 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1777 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1778 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1779 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1780 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1781 { "-userName", "userName", XrmoptionSepArg, NULL },
1782 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1783 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1784 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1785 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1786 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1787 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1788 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1789 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1790 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1791 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1792 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1793 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1794 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1795 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1796 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1797 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1798 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1799 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1800 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1801 { "-autoDisplayTags", "autoDisplayTags", XrmoptionSepArg, NULL },
1802 { "-autoDisplayComment", "autoDisplayComment", XrmoptionSepArg, NULL },
1803 { "-pasteSelection", "pasteSelection", XrmoptionSepArg, NULL },
1806 XtActionsRec boardActions[] = {
1807 { "DrawPosition", DrawPositionProc },
1808 { "HandleUserMove", HandleUserMove },
1809 { "AnimateUserMove", AnimateUserMove },
1810 { "FileNameAction", FileNameAction },
1811 { "AskQuestionProc", AskQuestionProc },
1812 { "AskQuestionReplyAction", AskQuestionReplyAction },
1813 { "PieceMenuPopup", PieceMenuPopup },
1814 { "WhiteClock", WhiteClock },
1815 { "BlackClock", BlackClock },
1816 { "Iconify", Iconify },
1817 { "ResetProc", ResetProc },
1818 { "LoadGameProc", LoadGameProc },
1819 { "LoadNextGameProc", LoadNextGameProc },
1820 { "LoadPrevGameProc", LoadPrevGameProc },
1821 { "LoadSelectedProc", LoadSelectedProc },
1822 { "ReloadGameProc", ReloadGameProc },
1823 { "LoadPositionProc", LoadPositionProc },
1824 { "LoadNextPositionProc", LoadNextPositionProc },
1825 { "LoadPrevPositionProc", LoadPrevPositionProc },
1826 { "ReloadPositionProc", ReloadPositionProc },
1827 { "CopyPositionProc", CopyPositionProc },
1828 { "PastePositionProc", PastePositionProc },
1829 { "CopyGameProc", CopyGameProc },
1830 { "PasteGameProc", PasteGameProc },
1831 { "SaveGameProc", SaveGameProc },
1832 { "SavePositionProc", SavePositionProc },
1833 { "MailMoveProc", MailMoveProc },
1834 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1835 { "QuitProc", QuitProc },
1836 { "MachineWhiteProc", MachineWhiteProc },
1837 { "MachineBlackProc", MachineBlackProc },
1838 { "AnalysisModeProc", AnalyzeModeProc },
1839 { "AnalyzeFileProc", AnalyzeFileProc },
1840 { "TwoMachinesProc", TwoMachinesProc },
1841 { "IcsClientProc", IcsClientProc },
1842 { "EditGameProc", EditGameProc },
1843 { "EditPositionProc", EditPositionProc },
1844 { "TrainingProc", EditPositionProc },
1845 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1846 { "ShowGameListProc", ShowGameListProc },
1847 { "ShowMoveListProc", HistoryShowProc},
1848 { "EditTagsProc", EditCommentProc },
1849 { "EditCommentProc", EditCommentProc },
1850 { "IcsAlarmProc", IcsAlarmProc },
1851 { "IcsInputBoxProc", IcsInputBoxProc },
1852 { "PauseProc", PauseProc },
1853 { "AcceptProc", AcceptProc },
1854 { "DeclineProc", DeclineProc },
1855 { "RematchProc", RematchProc },
1856 { "CallFlagProc", CallFlagProc },
1857 { "DrawProc", DrawProc },
1858 { "AdjournProc", AdjournProc },
1859 { "AbortProc", AbortProc },
1860 { "ResignProc", ResignProc },
1861 { "AdjuWhiteProc", AdjuWhiteProc },
1862 { "AdjuBlackProc", AdjuBlackProc },
1863 { "AdjuDrawProc", AdjuDrawProc },
1864 { "EnterKeyProc", EnterKeyProc },
1865 { "StopObservingProc", StopObservingProc },
1866 { "StopExaminingProc", StopExaminingProc },
1867 { "BackwardProc", BackwardProc },
1868 { "ForwardProc", ForwardProc },
1869 { "ToStartProc", ToStartProc },
1870 { "ToEndProc", ToEndProc },
1871 { "RevertProc", RevertProc },
1872 { "TruncateGameProc", TruncateGameProc },
1873 { "MoveNowProc", MoveNowProc },
1874 { "RetractMoveProc", RetractMoveProc },
1875 { "AlwaysQueenProc", AlwaysQueenProc },
1876 { "AnimateDraggingProc", AnimateDraggingProc },
1877 { "AnimateMovingProc", AnimateMovingProc },
1878 { "AutoflagProc", AutoflagProc },
1879 { "AutoflipProc", AutoflipProc },
1880 { "AutobsProc", AutobsProc },
1881 { "AutoraiseProc", AutoraiseProc },
1882 { "AutosaveProc", AutosaveProc },
1883 { "BlindfoldProc", BlindfoldProc },
1884 { "FlashMovesProc", FlashMovesProc },
1885 { "FlipViewProc", FlipViewProc },
1886 { "GetMoveListProc", GetMoveListProc },
1888 { "HighlightDraggingProc", HighlightDraggingProc },
1890 { "HighlightLastMoveProc", HighlightLastMoveProc },
1891 { "IcsAlarmProc", IcsAlarmProc },
1892 { "MoveSoundProc", MoveSoundProc },
1893 { "OldSaveStyleProc", OldSaveStyleProc },
1894 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1895 { "PonderNextMoveProc", PonderNextMoveProc },
1896 { "PopupExitMessageProc", PopupExitMessageProc },
1897 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1898 { "PremoveProc", PremoveProc },
1899 { "QuietPlayProc", QuietPlayProc },
1900 { "ShowCoordsProc", ShowCoordsProc },
1901 { "ShowThinkingProc", ShowThinkingProc },
1902 { "HideThinkingProc", HideThinkingProc },
1903 { "TestLegalityProc", TestLegalityProc },
1904 { "InfoProc", InfoProc },
1905 { "ManProc", ManProc },
1906 { "HintProc", HintProc },
1907 { "BookProc", BookProc },
1908 { "AboutGameProc", AboutGameProc },
1909 { "AboutProc", AboutProc },
1910 { "DebugProc", DebugProc },
1911 { "NothingProc", NothingProc },
1912 { "CommentPopDown", (XtActionProc) CommentPopDown },
1913 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1914 { "TagsPopDown", (XtActionProc) TagsPopDown },
1915 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1916 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1917 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1918 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1919 { "GameListPopDown", (XtActionProc) GameListPopDown },
1920 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1921 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1922 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1923 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1924 { "EnginePopDown", (XtActionProc) EnginePopDown },
1925 { "UciPopDown", (XtActionProc) UciPopDown },
1926 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1927 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1928 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1931 char globalTranslations[] =
1932 ":<Key>R: ResignProc() \n \
1933 :<Key>r: ResetProc() \n \
1934 :<Key>g: LoadGameProc() \n \
1935 :<Key>N: LoadNextGameProc() \n \
1936 :<Key>P: LoadPrevGameProc() \n \
1937 :<Key>Q: QuitProc() \n \
1938 :<Key>F: ToEndProc() \n \
1939 :<Key>f: ForwardProc() \n \
1940 :<Key>B: ToStartProc() \n \
1941 :<Key>b: BackwardProc() \n \
1942 :<Key>p: PauseProc() \n \
1943 :<Key>d: DrawProc() \n \
1944 :<Key>t: CallFlagProc() \n \
1945 :<Key>i: Iconify() \n \
1946 :<Key>c: Iconify() \n \
1947 :<Key>v: FlipViewProc() \n \
1948 <KeyDown>Control_L: BackwardProc() \n \
1949 <KeyUp>Control_L: ForwardProc() \n \
1950 <KeyDown>Control_R: BackwardProc() \n \
1951 <KeyUp>Control_R: ForwardProc() \n \
1952 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1953 \"Send to chess program:\",,1) \n \
1954 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1955 \"Send to second chess program:\",,2) \n";
1957 char boardTranslations[] =
1958 "<Btn1Down>: HandleUserMove() \n \
1959 <Btn1Up>: HandleUserMove() \n \
1960 <Btn1Motion>: AnimateUserMove() \n \
1961 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1962 PieceMenuPopup(menuB) \n \
1963 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1964 PieceMenuPopup(menuW) \n \
1965 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1966 PieceMenuPopup(menuW) \n \
1967 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1968 PieceMenuPopup(menuB) \n";
1970 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1971 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1973 char ICSInputTranslations[] =
1974 "<Key>Return: EnterKeyProc() \n";
1976 String xboardResources[] = {
1977 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1978 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1979 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1984 /* Max possible square size */
1985 #define MAXSQSIZE 256
1987 static int xpm_avail[MAXSQSIZE];
1989 #ifdef HAVE_DIR_STRUCT
1991 /* Extract piece size from filename */
1993 xpm_getsize(name, len, ext)
2004 if ((p=strchr(name, '.')) == NULL ||
2005 StrCaseCmp(p+1, ext) != 0)
2011 while (*p && isdigit(*p))
2018 /* Setup xpm_avail */
2020 xpm_getavail(dirname, ext)
2028 for (i=0; i<MAXSQSIZE; ++i)
2031 if (appData.debugMode)
2032 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2034 dir = opendir(dirname);
2037 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2038 programName, dirname);
2042 while ((ent=readdir(dir)) != NULL) {
2043 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2044 if (i > 0 && i < MAXSQSIZE)
2054 xpm_print_avail(fp, ext)
2060 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2061 for (i=1; i<MAXSQSIZE; ++i) {
2067 /* Return XPM piecesize closest to size */
2069 xpm_closest_to(dirname, size, ext)
2075 int sm_diff = MAXSQSIZE;
2079 xpm_getavail(dirname, ext);
2081 if (appData.debugMode)
2082 xpm_print_avail(stderr, ext);
2084 for (i=1; i<MAXSQSIZE; ++i) {
2087 diff = (diff<0) ? -diff : diff;
2088 if (diff < sm_diff) {
2096 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2102 #else /* !HAVE_DIR_STRUCT */
2103 /* If we are on a system without a DIR struct, we can't
2104 read the directory, so we can't collect a list of
2105 filenames, etc., so we can't do any size-fitting. */
2107 xpm_closest_to(dirname, size, ext)
2112 fprintf(stderr, _("\
2113 Warning: No DIR structure found on this system --\n\
2114 Unable to autosize for XPM/XIM pieces.\n\
2115 Please report this error to frankm@hiwaay.net.\n\
2116 Include system type & operating system in message.\n"));
2119 #endif /* HAVE_DIR_STRUCT */
2121 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2122 "magenta", "cyan", "white" };
2126 TextColors textColors[(int)NColorClasses];
2128 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2130 parse_color(str, which)
2134 char *p, buf[100], *d;
2137 if (strlen(str) > 99) /* watch bounds on buf */
2142 for (i=0; i<which; ++i) {
2149 /* Could be looking at something like:
2151 .. in which case we want to stop on a comma also */
2152 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2156 return -1; /* Use default for empty field */
2159 if (which == 2 || isdigit(*p))
2162 while (*p && isalpha(*p))
2167 for (i=0; i<8; ++i) {
2168 if (!StrCaseCmp(buf, cnames[i]))
2169 return which? (i+40) : (i+30);
2171 if (!StrCaseCmp(buf, "default")) return -1;
2173 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2178 parse_cpair(cc, str)
2182 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2183 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2188 /* bg and attr are optional */
2189 textColors[(int)cc].bg = parse_color(str, 1);
2190 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2191 textColors[(int)cc].attr = 0;
2197 /* Arrange to catch delete-window events */
2198 Atom wm_delete_window;
2200 CatchDeleteWindow(Widget w, String procname)
2203 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2204 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2205 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2212 XtSetArg(args[0], XtNiconic, False);
2213 XtSetValues(shellWidget, args, 1);
2215 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2219 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2221 #define BoardSize int
2222 void InitDrawingSizes(BoardSize boardSize, int flags)
2223 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2224 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2226 XtGeometryResult gres;
2229 if(!formWidget) return;
2232 * Enable shell resizing.
2234 shellArgs[0].value = (XtArgVal) &w;
2235 shellArgs[1].value = (XtArgVal) &h;
2236 XtGetValues(shellWidget, shellArgs, 2);
2238 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2239 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2240 XtSetValues(shellWidget, &shellArgs[2], 4);
2242 XtSetArg(args[0], XtNdefaultDistance, &sep);
2243 XtGetValues(formWidget, args, 1);
2245 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2246 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2249 XtSetArg(args[0], XtNwidth, boardWidth);
2250 XtSetArg(args[1], XtNheight, boardHeight);
2251 XtSetValues(boardWidget, args, 2);
2253 timerWidth = (boardWidth - sep) / 2;
2254 XtSetArg(args[0], XtNwidth, timerWidth);
2255 XtSetValues(whiteTimerWidget, args, 1);
2256 XtSetValues(blackTimerWidget, args, 1);
2258 XawFormDoLayout(formWidget, False);
2260 if (appData.titleInWindow) {
2262 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2263 XtSetArg(args[i], XtNheight, &h); i++;
2264 XtGetValues(titleWidget, args, i);
2266 w = boardWidth - 2*bor;
2268 XtSetArg(args[0], XtNwidth, &w);
2269 XtGetValues(menuBarWidget, args, 1);
2270 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2273 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2274 if (gres != XtGeometryYes && appData.debugMode) {
2276 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2277 programName, gres, w, h, wr, hr);
2281 XawFormDoLayout(formWidget, True);
2284 * Inhibit shell resizing.
2286 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2287 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2288 shellArgs[4].value = shellArgs[2].value = w;
2289 shellArgs[5].value = shellArgs[3].value = h;
2290 XtSetValues(shellWidget, &shellArgs[0], 6);
2292 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2295 for(i=0; i<4; i++) {
2297 for(p=0; p<=(int)WhiteKing; p++)
2298 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2299 if(gameInfo.variant == VariantShogi) {
2300 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2301 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2302 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2303 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2304 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2307 if(gameInfo.variant == VariantGothic) {
2308 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2312 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2313 for(p=0; p<=(int)WhiteKing; p++)
2314 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2315 if(gameInfo.variant == VariantShogi) {
2316 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2317 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2318 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2319 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2320 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2323 if(gameInfo.variant == VariantGothic) {
2324 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2330 for(i=0; i<2; i++) {
2332 for(p=0; p<=(int)WhiteKing; p++)
2333 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2334 if(gameInfo.variant == VariantShogi) {
2335 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2336 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2337 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2338 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2339 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2342 if(gameInfo.variant == VariantGothic) {
2343 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2354 void EscapeExpand(char *p, char *q)
2355 { // [HGM] initstring: routine to shape up string arguments
2356 while(*p++ = *q++) if(p[-1] == '\\')
2358 case 'n': p[-1] = '\n'; break;
2359 case 'r': p[-1] = '\r'; break;
2360 case 't': p[-1] = '\t'; break;
2361 case '\\': p[-1] = '\\'; break;
2362 case 0: *p = 0; return;
2363 default: p[-1] = q[-1]; break;
2372 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2373 XSetWindowAttributes window_attributes;
2375 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2376 XrmValue vFrom, vTo;
2377 XtGeometryResult gres;
2380 int forceMono = False;
2383 // [HGM] before anything else, expand any indirection files amongst options
2384 char *argvCopy[1000]; // 1000 seems enough
2385 char newArgs[10000]; // holds actual characters
2388 srandom(time(0)); // [HGM] book: make random truly random
2391 for(i=0; i<argc; i++) {
2392 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2393 //fprintf(stderr, "arg %s\n", argv[i]);
2394 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2396 FILE *f = fopen(argv[i]+1, "rb");
2397 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2398 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2399 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2401 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2402 newArgs[k++] = 0; // terminate current arg
2403 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2404 argvCopy[j++] = newArgs + k; // get ready for next
2406 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2420 setbuf(stdout, NULL);
2421 setbuf(stderr, NULL);
2424 programName = strrchr(argv[0], '/');
2425 if (programName == NULL)
2426 programName = argv[0];
2431 XtSetLanguageProc(NULL, NULL, NULL);
2432 bindtextdomain(PACKAGE, LOCALEDIR);
2433 textdomain(PACKAGE);
2437 XtAppInitialize(&appContext, "XBoard", shellOptions,
2438 XtNumber(shellOptions),
2439 &argc, argv, xboardResources, NULL, 0);
2441 { /* left over command line arguments, print out help and exit.
2442 * Use two columns to print help
2444 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2445 programName, argv[1]);
2447 fprintf(stderr, "Recognized options:\n");
2448 for(i = 0; i < XtNumber(shellOptions); i++)
2450 /* print first column */
2451 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2452 (shellOptions[i].argKind == XrmoptionSepArg
2454 /* print second column and end line */
2455 if (++i < XtNumber(shellOptions))
2457 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2458 shellOptions[i].option,
2459 (shellOptions[i].argKind == XrmoptionSepArg
2464 fprintf(stderr, "\n");
2471 if (p == NULL) p = "/tmp";
2472 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2473 gameCopyFilename = (char*) malloc(i);
2474 gamePasteFilename = (char*) malloc(i);
2475 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2476 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2478 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2479 clientResources, XtNumber(clientResources),
2482 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2483 static char buf[MSG_SIZ];
2484 EscapeExpand(buf, appData.initString);
2485 appData.initString = strdup(buf);
2486 EscapeExpand(buf, appData.secondInitString);
2487 appData.secondInitString = strdup(buf);
2488 EscapeExpand(buf, appData.firstComputerString);
2489 appData.firstComputerString = strdup(buf);
2490 EscapeExpand(buf, appData.secondComputerString);
2491 appData.secondComputerString = strdup(buf);
2494 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2497 if (chdir(chessDir) != 0) {
2498 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2504 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2505 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2506 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2507 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2510 setbuf(debugFP, NULL);
2513 /* [HGM,HR] make sure board size is acceptable */
2514 if(appData.NrFiles > BOARD_FILES ||
2515 appData.NrRanks > BOARD_RANKS )
2516 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2519 /* This feature does not work; animation needs a rewrite */
2520 appData.highlightDragging = FALSE;
2524 xDisplay = XtDisplay(shellWidget);
2525 xScreen = DefaultScreen(xDisplay);
2526 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2528 gameInfo.variant = StringToVariant(appData.variant);
2529 InitPosition(FALSE);
2532 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2534 if (isdigit(appData.boardSize[0])) {
2535 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2536 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2537 &fontPxlSize, &smallLayout, &tinyLayout);
2539 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2540 programName, appData.boardSize);
2544 /* Find some defaults; use the nearest known size */
2545 SizeDefaults *szd, *nearest;
2546 int distance = 99999;
2547 nearest = szd = sizeDefaults;
2548 while (szd->name != NULL) {
2549 if (abs(szd->squareSize - squareSize) < distance) {
2551 distance = abs(szd->squareSize - squareSize);
2552 if (distance == 0) break;
2556 if (i < 2) lineGap = nearest->lineGap;
2557 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2558 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2559 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2560 if (i < 6) smallLayout = nearest->smallLayout;
2561 if (i < 7) tinyLayout = nearest->tinyLayout;
2564 SizeDefaults *szd = sizeDefaults;
2565 if (*appData.boardSize == NULLCHAR) {
2566 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2567 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2570 if (szd->name == NULL) szd--;
2572 while (szd->name != NULL &&
2573 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2574 if (szd->name == NULL) {
2575 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2576 programName, appData.boardSize);
2580 squareSize = szd->squareSize;
2581 lineGap = szd->lineGap;
2582 clockFontPxlSize = szd->clockFontPxlSize;
2583 coordFontPxlSize = szd->coordFontPxlSize;
2584 fontPxlSize = szd->fontPxlSize;
2585 smallLayout = szd->smallLayout;
2586 tinyLayout = szd->tinyLayout;
2589 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2590 if (strlen(appData.pixmapDirectory) > 0) {
2591 p = ExpandPathName(appData.pixmapDirectory);
2593 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2594 appData.pixmapDirectory);
2597 if (appData.debugMode) {
2598 fprintf(stderr, _("\
2599 XBoard square size (hint): %d\n\
2600 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2602 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2603 if (appData.debugMode) {
2604 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2608 /* [HR] height treated separately (hacked) */
2609 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2610 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2611 if (appData.showJail == 1) {
2612 /* Jail on top and bottom */
2613 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2614 XtSetArg(boardArgs[2], XtNheight,
2615 boardHeight + 2*(lineGap + squareSize));
2616 } else if (appData.showJail == 2) {
2618 XtSetArg(boardArgs[1], XtNwidth,
2619 boardWidth + 2*(lineGap + squareSize));
2620 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2623 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2624 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2628 * Determine what fonts to use.
2630 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2631 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2632 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2633 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2634 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2635 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2636 appData.font = FindFont(appData.font, fontPxlSize);
2637 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2638 countFontStruct = XQueryFont(xDisplay, countFontID);
2639 // appData.font = FindFont(appData.font, fontPxlSize);
2641 xdb = XtDatabase(xDisplay);
2642 XrmPutStringResource(&xdb, "*font", appData.font);
2645 * Detect if there are not enough colors available and adapt.
2647 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2648 appData.monoMode = True;
2651 if (!appData.monoMode) {
2652 vFrom.addr = (caddr_t) appData.lightSquareColor;
2653 vFrom.size = strlen(appData.lightSquareColor);
2654 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2655 if (vTo.addr == NULL) {
2656 appData.monoMode = True;
2659 lightSquareColor = *(Pixel *) vTo.addr;
2662 if (!appData.monoMode) {
2663 vFrom.addr = (caddr_t) appData.darkSquareColor;
2664 vFrom.size = strlen(appData.darkSquareColor);
2665 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2666 if (vTo.addr == NULL) {
2667 appData.monoMode = True;
2670 darkSquareColor = *(Pixel *) vTo.addr;
2673 if (!appData.monoMode) {
2674 vFrom.addr = (caddr_t) appData.whitePieceColor;
2675 vFrom.size = strlen(appData.whitePieceColor);
2676 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2677 if (vTo.addr == NULL) {
2678 appData.monoMode = True;
2681 whitePieceColor = *(Pixel *) vTo.addr;
2684 if (!appData.monoMode) {
2685 vFrom.addr = (caddr_t) appData.blackPieceColor;
2686 vFrom.size = strlen(appData.blackPieceColor);
2687 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2688 if (vTo.addr == NULL) {
2689 appData.monoMode = True;
2692 blackPieceColor = *(Pixel *) vTo.addr;
2696 if (!appData.monoMode) {
2697 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2698 vFrom.size = strlen(appData.highlightSquareColor);
2699 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2700 if (vTo.addr == NULL) {
2701 appData.monoMode = True;
2704 highlightSquareColor = *(Pixel *) vTo.addr;
2708 if (!appData.monoMode) {
2709 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2710 vFrom.size = strlen(appData.premoveHighlightColor);
2711 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2712 if (vTo.addr == NULL) {
2713 appData.monoMode = True;
2716 premoveHighlightColor = *(Pixel *) vTo.addr;
2721 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2724 if (appData.bitmapDirectory == NULL ||
2725 appData.bitmapDirectory[0] == NULLCHAR)
2726 appData.bitmapDirectory = DEF_BITMAP_DIR;
2729 if (appData.lowTimeWarning && !appData.monoMode) {
2730 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2731 vFrom.size = strlen(appData.lowTimeWarningColor);
2732 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2733 if (vTo.addr == NULL)
2734 appData.monoMode = True;
2736 lowTimeWarningColor = *(Pixel *) vTo.addr;
2739 if (appData.monoMode && appData.debugMode) {
2740 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2741 (unsigned long) XWhitePixel(xDisplay, xScreen),
2742 (unsigned long) XBlackPixel(xDisplay, xScreen));
2745 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2746 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2747 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2748 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2749 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2750 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2751 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2752 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2753 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2754 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2756 if (appData.colorize) {
2758 _("%s: can't parse color names; disabling colorization\n"),
2761 appData.colorize = FALSE;
2763 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2764 textColors[ColorNone].attr = 0;
2766 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2772 layoutName = "tinyLayout";
2773 } else if (smallLayout) {
2774 layoutName = "smallLayout";
2776 layoutName = "normalLayout";
2778 /* Outer layoutWidget is there only to provide a name for use in
2779 resources that depend on the layout style */
2781 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2782 layoutArgs, XtNumber(layoutArgs));
2784 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2785 formArgs, XtNumber(formArgs));
2786 XtSetArg(args[0], XtNdefaultDistance, &sep);
2787 XtGetValues(formWidget, args, 1);
2790 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2791 XtSetArg(args[0], XtNtop, XtChainTop);
2792 XtSetArg(args[1], XtNbottom, XtChainTop);
2793 XtSetArg(args[2], XtNright, XtChainLeft);
2794 XtSetValues(menuBarWidget, args, 3);
2796 widgetList[j++] = whiteTimerWidget =
2797 XtCreateWidget("whiteTime", labelWidgetClass,
2798 formWidget, timerArgs, XtNumber(timerArgs));
2799 XtSetArg(args[0], XtNfont, clockFontStruct);
2800 XtSetArg(args[1], XtNtop, XtChainTop);
2801 XtSetArg(args[2], XtNbottom, XtChainTop);
2802 XtSetValues(whiteTimerWidget, args, 3);
2804 widgetList[j++] = blackTimerWidget =
2805 XtCreateWidget("blackTime", labelWidgetClass,
2806 formWidget, timerArgs, XtNumber(timerArgs));
2807 XtSetArg(args[0], XtNfont, clockFontStruct);
2808 XtSetArg(args[1], XtNtop, XtChainTop);
2809 XtSetArg(args[2], XtNbottom, XtChainTop);
2810 XtSetValues(blackTimerWidget, args, 3);
2812 if (appData.titleInWindow) {
2813 widgetList[j++] = titleWidget =
2814 XtCreateWidget("title", labelWidgetClass, formWidget,
2815 titleArgs, XtNumber(titleArgs));
2816 XtSetArg(args[0], XtNtop, XtChainTop);
2817 XtSetArg(args[1], XtNbottom, XtChainTop);
2818 XtSetValues(titleWidget, args, 2);
2821 if (appData.showButtonBar) {
2822 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2823 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2824 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2825 XtSetArg(args[2], XtNtop, XtChainTop);
2826 XtSetArg(args[3], XtNbottom, XtChainTop);
2827 XtSetValues(buttonBarWidget, args, 4);
2830 widgetList[j++] = messageWidget =
2831 XtCreateWidget("message", labelWidgetClass, formWidget,
2832 messageArgs, XtNumber(messageArgs));
2833 XtSetArg(args[0], XtNtop, XtChainTop);
2834 XtSetArg(args[1], XtNbottom, XtChainTop);
2835 XtSetValues(messageWidget, args, 2);
2837 widgetList[j++] = boardWidget =
2838 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2839 XtNumber(boardArgs));
2841 XtManageChildren(widgetList, j);
2843 timerWidth = (boardWidth - sep) / 2;
2844 XtSetArg(args[0], XtNwidth, timerWidth);
2845 XtSetValues(whiteTimerWidget, args, 1);
2846 XtSetValues(blackTimerWidget, args, 1);
2848 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2849 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2850 XtGetValues(whiteTimerWidget, args, 2);
2852 if (appData.showButtonBar) {
2853 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2854 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2855 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2859 * formWidget uses these constraints but they are stored
2863 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2864 XtSetValues(menuBarWidget, args, i);
2865 if (appData.titleInWindow) {
2868 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2869 XtSetValues(whiteTimerWidget, args, i);
2871 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2872 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2873 XtSetValues(blackTimerWidget, args, i);
2875 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2876 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2877 XtSetValues(titleWidget, args, i);
2879 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2880 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2881 XtSetValues(messageWidget, args, i);
2882 if (appData.showButtonBar) {
2884 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2885 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2886 XtSetValues(buttonBarWidget, args, i);
2890 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2891 XtSetValues(whiteTimerWidget, args, i);
2893 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2894 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2895 XtSetValues(blackTimerWidget, args, i);
2897 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2898 XtSetValues(titleWidget, args, i);
2900 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2901 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2902 XtSetValues(messageWidget, args, i);
2903 if (appData.showButtonBar) {
2905 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2906 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2907 XtSetValues(buttonBarWidget, args, i);
2912 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2913 XtSetValues(whiteTimerWidget, args, i);
2915 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2916 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2917 XtSetValues(blackTimerWidget, args, i);
2919 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2920 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2921 XtSetValues(messageWidget, args, i);
2922 if (appData.showButtonBar) {
2924 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2925 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2926 XtSetValues(buttonBarWidget, args, i);
2930 XtSetArg(args[0], XtNfromVert, messageWidget);
2931 XtSetArg(args[1], XtNtop, XtChainTop);
2932 XtSetArg(args[2], XtNbottom, XtChainBottom);
2933 XtSetArg(args[3], XtNleft, XtChainLeft);
2934 XtSetArg(args[4], XtNright, XtChainRight);
2935 XtSetValues(boardWidget, args, 5);
2937 XtRealizeWidget(shellWidget);
2940 * Correct the width of the message and title widgets.
2941 * It is not known why some systems need the extra fudge term.
2942 * The value "2" is probably larger than needed.
2944 XawFormDoLayout(formWidget, False);
2946 #define WIDTH_FUDGE 2
2948 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2949 XtSetArg(args[i], XtNheight, &h); i++;
2950 XtGetValues(messageWidget, args, i);
2951 if (appData.showButtonBar) {
2953 XtSetArg(args[i], XtNwidth, &w); i++;
2954 XtGetValues(buttonBarWidget, args, i);
2955 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2957 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2960 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2961 if (gres != XtGeometryYes && appData.debugMode) {
2962 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2963 programName, gres, w, h, wr, hr);
2966 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2967 /* The size used for the child widget in layout lags one resize behind
2968 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2970 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2971 if (gres != XtGeometryYes && appData.debugMode) {
2972 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2973 programName, gres, w, h, wr, hr);
2976 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2977 XtSetArg(args[1], XtNright, XtChainRight);
2978 XtSetValues(messageWidget, args, 2);
2980 if (appData.titleInWindow) {
2982 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2983 XtSetArg(args[i], XtNheight, &h); i++;
2984 XtGetValues(titleWidget, args, i);
2986 w = boardWidth - 2*bor;
2988 XtSetArg(args[0], XtNwidth, &w);
2989 XtGetValues(menuBarWidget, args, 1);
2990 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2993 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2994 if (gres != XtGeometryYes && appData.debugMode) {
2996 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2997 programName, gres, w, h, wr, hr);
3000 XawFormDoLayout(formWidget, True);
3002 xBoardWindow = XtWindow(boardWidget);
3004 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
3005 // not need to go into InitDrawingSizes().
3009 * Create X checkmark bitmap and initialize option menu checks.
3011 ReadBitmap(&xMarkPixmap, "checkmark.bm",
3012 checkmark_bits, checkmark_width, checkmark_height);
3013 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
3014 if (appData.alwaysPromoteToQueen) {
3015 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3018 if (appData.animateDragging) {
3019 XtSetValues(XtNameToWidget(menuBarWidget,
3020 "menuOptions.Animate Dragging"),
3023 if (appData.animate) {
3024 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3027 if (appData.autoComment) {
3028 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3031 if (appData.autoCallFlag) {
3032 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3035 if (appData.autoFlipView) {
3036 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3039 if (appData.autoObserve) {
3040 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3043 if (appData.autoRaiseBoard) {
3044 XtSetValues(XtNameToWidget(menuBarWidget,
3045 "menuOptions.Auto Raise Board"), args, 1);
3047 if (appData.autoSaveGames) {
3048 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3051 if (appData.saveGameFile[0] != NULLCHAR) {
3052 /* Can't turn this off from menu */
3053 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3055 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3059 if (appData.blindfold) {
3060 XtSetValues(XtNameToWidget(menuBarWidget,
3061 "menuOptions.Blindfold"), args, 1);
3063 if (appData.flashCount > 0) {
3064 XtSetValues(XtNameToWidget(menuBarWidget,
3065 "menuOptions.Flash Moves"),
3068 if (appData.getMoveList) {
3069 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3073 if (appData.highlightDragging) {
3074 XtSetValues(XtNameToWidget(menuBarWidget,
3075 "menuOptions.Highlight Dragging"),
3079 if (appData.highlightLastMove) {
3080 XtSetValues(XtNameToWidget(menuBarWidget,
3081 "menuOptions.Highlight Last Move"),
3084 if (appData.icsAlarm) {
3085 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3088 if (appData.ringBellAfterMoves) {
3089 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3092 if (appData.oldSaveStyle) {
3093 XtSetValues(XtNameToWidget(menuBarWidget,
3094 "menuOptions.Old Save Style"), args, 1);
3096 if (appData.periodicUpdates) {
3097 XtSetValues(XtNameToWidget(menuBarWidget,
3098 "menuOptions.Periodic Updates"), args, 1);
3100 if (appData.ponderNextMove) {
3101 XtSetValues(XtNameToWidget(menuBarWidget,
3102 "menuOptions.Ponder Next Move"), args, 1);
3104 if (appData.popupExitMessage) {
3105 XtSetValues(XtNameToWidget(menuBarWidget,
3106 "menuOptions.Popup Exit Message"), args, 1);
3108 if (appData.popupMoveErrors) {
3109 XtSetValues(XtNameToWidget(menuBarWidget,
3110 "menuOptions.Popup Move Errors"), args, 1);
3112 if (appData.premove) {
3113 XtSetValues(XtNameToWidget(menuBarWidget,
3114 "menuOptions.Premove"), args, 1);
3116 if (appData.quietPlay) {
3117 XtSetValues(XtNameToWidget(menuBarWidget,
3118 "menuOptions.Quiet Play"), args, 1);
3120 if (appData.showCoords) {
3121 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3124 if (appData.hideThinkingFromHuman) {
3125 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3128 if (appData.testLegality) {
3129 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3136 ReadBitmap(&wIconPixmap, "icon_white.bm",
3137 icon_white_bits, icon_white_width, icon_white_height);
3138 ReadBitmap(&bIconPixmap, "icon_black.bm",
3139 icon_black_bits, icon_black_width, icon_black_height);
3140 iconPixmap = wIconPixmap;
3142 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3143 XtSetValues(shellWidget, args, i);
3146 * Create a cursor for the board widget.
3148 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3149 XChangeWindowAttributes(xDisplay, xBoardWindow,
3150 CWCursor, &window_attributes);
3153 * Inhibit shell resizing.
3155 shellArgs[0].value = (XtArgVal) &w;
3156 shellArgs[1].value = (XtArgVal) &h;
3157 XtGetValues(shellWidget, shellArgs, 2);
3158 shellArgs[4].value = shellArgs[2].value = w;
3159 shellArgs[5].value = shellArgs[3].value = h;
3160 XtSetValues(shellWidget, &shellArgs[2], 4);
3161 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3162 marginH = h - boardHeight;
3164 CatchDeleteWindow(shellWidget, "QuitProc");
3169 if (appData.bitmapDirectory[0] != NULLCHAR) {
3176 /* Create regular pieces */
3177 if (!useImages) CreatePieces();
3182 if (appData.animate || appData.animateDragging)
3185 XtAugmentTranslations(formWidget,
3186 XtParseTranslationTable(globalTranslations));
3187 XtAugmentTranslations(boardWidget,
3188 XtParseTranslationTable(boardTranslations));
3189 XtAugmentTranslations(whiteTimerWidget,
3190 XtParseTranslationTable(whiteTranslations));
3191 XtAugmentTranslations(blackTimerWidget,
3192 XtParseTranslationTable(blackTranslations));
3194 /* Why is the following needed on some versions of X instead
3195 * of a translation? */
3196 XtAddEventHandler(boardWidget, ExposureMask, False,
3197 (XtEventHandler) EventProc, NULL);
3202 if (errorExitStatus == -1) {
3203 if (appData.icsActive) {
3204 /* We now wait until we see "login:" from the ICS before
3205 sending the logon script (problems with timestamp otherwise) */
3206 /*ICSInitScript();*/
3207 if (appData.icsInputBox) ICSInputBoxPopUp();
3211 signal(SIGWINCH, TermSizeSigHandler);
3213 signal(SIGINT, IntSigHandler);
3214 signal(SIGTERM, IntSigHandler);
3215 if (*appData.cmailGameName != NULLCHAR) {
3216 signal(SIGUSR1, CmailSigHandler);
3219 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3222 XtAppMainLoop(appContext);
3223 if (appData.debugMode) fclose(debugFP); // [DM] debug
3230 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3231 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3233 unlink(gameCopyFilename);
3234 unlink(gamePasteFilename);
3237 RETSIGTYPE TermSizeSigHandler(int sig)
3250 CmailSigHandler(sig)
3256 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3258 /* Activate call-back function CmailSigHandlerCallBack() */
3259 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3261 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3265 CmailSigHandlerCallBack(isr, closure, message, count, error)
3273 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3275 /**** end signal code ****/
3285 f = fopen(appData.icsLogon, "r");
3291 strcat(buf, appData.icsLogon);
3292 f = fopen(buf, "r");
3296 ProcessICSInitScript(f);
3303 EditCommentPopDown();
3318 if (!menuBarWidget) return;
3319 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
3321 DisplayError("menuStep.Revert", 0);
3323 XtSetSensitive(w, !grey);
3328 SetMenuEnables(enab)
3332 if (!menuBarWidget) return;
3333 while (enab->name != NULL) {
3334 w = XtNameToWidget(menuBarWidget, enab->name);
3336 DisplayError(enab->name, 0);
3338 XtSetSensitive(w, enab->value);
3344 Enables icsEnables[] = {
3345 { "menuFile.Mail Move", False },
3346 { "menuFile.Reload CMail Message", False },
3347 { "menuMode.Machine Black", False },
3348 { "menuMode.Machine White", False },
3349 { "menuMode.Analysis Mode", False },
3350 { "menuMode.Analyze File", False },
3351 { "menuMode.Two Machines", False },
3353 { "menuHelp.Hint", False },
3354 { "menuHelp.Book", False },
3355 { "menuStep.Move Now", False },
3356 { "menuOptions.Periodic Updates", False },
3357 { "menuOptions.Hide Thinking", False },
3358 { "menuOptions.Ponder Next Move", False },
3363 Enables ncpEnables[] = {
3364 { "menuFile.Mail Move", False },
3365 { "menuFile.Reload CMail Message", False },
3366 { "menuMode.Machine White", False },
3367 { "menuMode.Machine Black", False },
3368 { "menuMode.Analysis Mode", False },
3369 { "menuMode.Analyze File", False },
3370 { "menuMode.Two Machines", False },
3371 { "menuMode.ICS Client", False },
3372 { "menuMode.ICS Input Box", False },
3373 { "Action", False },
3374 { "menuStep.Revert", False },
3375 { "menuStep.Move Now", False },
3376 { "menuStep.Retract Move", False },
3377 { "menuOptions.Auto Comment", False },
3378 { "menuOptions.Auto Flag", False },
3379 { "menuOptions.Auto Flip View", False },
3380 { "menuOptions.Auto Observe", False },
3381 { "menuOptions.Auto Raise Board", False },
3382 { "menuOptions.Get Move List", False },
3383 { "menuOptions.ICS Alarm", False },
3384 { "menuOptions.Move Sound", False },
3385 { "menuOptions.Quiet Play", False },
3386 { "menuOptions.Hide Thinking", False },
3387 { "menuOptions.Periodic Updates", False },
3388 { "menuOptions.Ponder Next Move", False },
3389 { "menuHelp.Hint", False },
3390 { "menuHelp.Book", False },
3394 Enables gnuEnables[] = {
3395 { "menuMode.ICS Client", False },
3396 { "menuMode.ICS Input Box", False },
3397 { "menuAction.Accept", False },
3398 { "menuAction.Decline", False },
3399 { "menuAction.Rematch", False },
3400 { "menuAction.Adjourn", False },
3401 { "menuAction.Stop Examining", False },
3402 { "menuAction.Stop Observing", False },
3403 { "menuStep.Revert", False },
3404 { "menuOptions.Auto Comment", False },
3405 { "menuOptions.Auto Observe", False },
3406 { "menuOptions.Auto Raise Board", False },
3407 { "menuOptions.Get Move List", False },
3408 { "menuOptions.Premove", False },
3409 { "menuOptions.Quiet Play", False },
3411 /* The next two options rely on SetCmailMode being called *after* */
3412 /* SetGNUMode so that when GNU is being used to give hints these */
3413 /* menu options are still available */
3415 { "menuFile.Mail Move", False },
3416 { "menuFile.Reload CMail Message", False },
3420 Enables cmailEnables[] = {
3422 { "menuAction.Call Flag", False },
3423 { "menuAction.Draw", True },
3424 { "menuAction.Adjourn", False },
3425 { "menuAction.Abort", False },
3426 { "menuAction.Stop Observing", False },
3427 { "menuAction.Stop Examining", False },
3428 { "menuFile.Mail Move", True },
3429 { "menuFile.Reload CMail Message", True },
3433 Enables trainingOnEnables[] = {
3434 { "menuMode.Edit Comment", False },
3435 { "menuMode.Pause", False },
3436 { "menuStep.Forward", False },
3437 { "menuStep.Backward", False },
3438 { "menuStep.Forward to End", False },
3439 { "menuStep.Back to Start", False },
3440 { "menuStep.Move Now", False },
3441 { "menuStep.Truncate Game", False },
3445 Enables trainingOffEnables[] = {
3446 { "menuMode.Edit Comment", True },
3447 { "menuMode.Pause", True },
3448 { "menuStep.Forward", True },
3449 { "menuStep.Backward", True },
3450 { "menuStep.Forward to End", True },
3451 { "menuStep.Back to Start", True },
3452 { "menuStep.Move Now", True },
3453 { "menuStep.Truncate Game", True },
3457 Enables machineThinkingEnables[] = {
3458 { "menuFile.Load Game", False },
3459 { "menuFile.Load Next Game", False },
3460 { "menuFile.Load Previous Game", False },
3461 { "menuFile.Reload Same Game", False },
3462 { "menuFile.Paste Game", False },
3463 { "menuFile.Load Position", False },
3464 { "menuFile.Load Next Position", False },
3465 { "menuFile.Load Previous Position", False },
3466 { "menuFile.Reload Same Position", False },
3467 { "menuFile.Paste Position", False },
3468 { "menuMode.Machine White", False },
3469 { "menuMode.Machine Black", False },
3470 { "menuMode.Two Machines", False },
3471 { "menuStep.Retract Move", False },
3475 Enables userThinkingEnables[] = {
3476 { "menuFile.Load Game", True },
3477 { "menuFile.Load Next Game", True },
3478 { "menuFile.Load Previous Game", True },
3479 { "menuFile.Reload Same Game", True },
3480 { "menuFile.Paste Game", True },
3481 { "menuFile.Load Position", True },
3482 { "menuFile.Load Next Position", True },
3483 { "menuFile.Load Previous Position", True },
3484 { "menuFile.Reload Same Position", True },
3485 { "menuFile.Paste Position", True },
3486 { "menuMode.Machine White", True },
3487 { "menuMode.Machine Black", True },
3488 { "menuMode.Two Machines", True },
3489 { "menuStep.Retract Move", True },
3495 SetMenuEnables(icsEnables);
3498 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3499 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3506 SetMenuEnables(ncpEnables);
3512 SetMenuEnables(gnuEnables);
3518 SetMenuEnables(cmailEnables);
3524 SetMenuEnables(trainingOnEnables);
3525 if (appData.showButtonBar) {
3526 XtSetSensitive(buttonBarWidget, False);
3532 SetTrainingModeOff()
3534 SetMenuEnables(trainingOffEnables);
3535 if (appData.showButtonBar) {
3536 XtSetSensitive(buttonBarWidget, True);
3541 SetUserThinkingEnables()
3543 if (appData.noChessProgram) return;
3544 SetMenuEnables(userThinkingEnables);
3548 SetMachineThinkingEnables()
3550 if (appData.noChessProgram) return;
3551 SetMenuEnables(machineThinkingEnables);
3553 case MachinePlaysBlack:
3554 case MachinePlaysWhite:
3555 case TwoMachinesPlay:
3556 XtSetSensitive(XtNameToWidget(menuBarWidget,
3557 ModeToWidgetName(gameMode)), True);
3564 #define Abs(n) ((n)<0 ? -(n) : (n))
3567 * Find a font that matches "pattern" that is as close as
3568 * possible to the targetPxlSize. Prefer fonts that are k
3569 * pixels smaller to fonts that are k pixels larger. The
3570 * pattern must be in the X Consortium standard format,
3571 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3572 * The return value should be freed with XtFree when no
3575 char *FindFont(pattern, targetPxlSize)
3579 char **fonts, *p, *best, *scalable, *scalableTail;
3580 int i, j, nfonts, minerr, err, pxlSize;
3583 char **missing_list;
3585 char *def_string, *base_fnt_lst, strInt[3];
3587 XFontStruct **fnt_list;
3589 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3590 sprintf(strInt, "%d", targetPxlSize);
3591 p = strstr(pattern, "--");
3592 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3593 strcat(base_fnt_lst, strInt);
3594 strcat(base_fnt_lst, strchr(p + 2, '-'));
3596 if ((fntSet = XCreateFontSet(xDisplay,
3600 &def_string)) == NULL) {
3602 fprintf(stderr, _("Unable to create font set.\n"));
3606 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3608 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3610 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3611 programName, pattern);
3619 for (i=0; i<nfonts; i++) {
3622 if (*p != '-') continue;
3624 if (*p == NULLCHAR) break;
3625 if (*p++ == '-') j++;
3627 if (j < 7) continue;
3630 scalable = fonts[i];
3633 err = pxlSize - targetPxlSize;
3634 if (Abs(err) < Abs(minerr) ||
3635 (minerr > 0 && err < 0 && -err == minerr)) {
3641 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3642 /* If the error is too big and there is a scalable font,
3643 use the scalable font. */
3644 int headlen = scalableTail - scalable;
3645 p = (char *) XtMalloc(strlen(scalable) + 10);
3646 while (isdigit(*scalableTail)) scalableTail++;
3647 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3649 p = (char *) XtMalloc(strlen(best) + 1);
3652 if (appData.debugMode) {
3653 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3654 pattern, targetPxlSize, p);
3657 if (missing_count > 0)
3658 XFreeStringList(missing_list);
3659 XFreeFontSet(xDisplay, fntSet);
3661 XFreeFontNames(fonts);
3668 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3669 | GCBackground | GCFunction | GCPlaneMask;
3670 XGCValues gc_values;
3673 gc_values.plane_mask = AllPlanes;
3674 gc_values.line_width = lineGap;
3675 gc_values.line_style = LineSolid;
3676 gc_values.function = GXcopy;
3678 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3679 gc_values.background = XBlackPixel(xDisplay, xScreen);
3680 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3682 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3683 gc_values.background = XWhitePixel(xDisplay, xScreen);
3684 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3685 XSetFont(xDisplay, coordGC, coordFontID);
3687 // [HGM] make font for holdings counts (white on black0
3688 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3689 gc_values.background = XBlackPixel(xDisplay, xScreen);
3690 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3691 XSetFont(xDisplay, countGC, countFontID);
3693 if (appData.monoMode) {
3694 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3695 gc_values.background = XWhitePixel(xDisplay, xScreen);
3696 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3698 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3699 gc_values.background = XBlackPixel(xDisplay, xScreen);
3700 lightSquareGC = wbPieceGC
3701 = XtGetGC(shellWidget, value_mask, &gc_values);
3703 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3704 gc_values.background = XWhitePixel(xDisplay, xScreen);
3705 darkSquareGC = bwPieceGC
3706 = XtGetGC(shellWidget, value_mask, &gc_values);
3708 if (DefaultDepth(xDisplay, xScreen) == 1) {
3709 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3710 gc_values.function = GXcopyInverted;
3711 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.function = GXcopy;
3713 if (XBlackPixel(xDisplay, xScreen) == 1) {
3714 bwPieceGC = darkSquareGC;
3715 wbPieceGC = copyInvertedGC;
3717 bwPieceGC = copyInvertedGC;
3718 wbPieceGC = lightSquareGC;
3722 gc_values.foreground = highlightSquareColor;
3723 gc_values.background = highlightSquareColor;
3724 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3726 gc_values.foreground = premoveHighlightColor;
3727 gc_values.background = premoveHighlightColor;
3728 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3730 gc_values.foreground = lightSquareColor;
3731 gc_values.background = darkSquareColor;
3732 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3734 gc_values.foreground = darkSquareColor;
3735 gc_values.background = lightSquareColor;
3736 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3738 gc_values.foreground = jailSquareColor;
3739 gc_values.background = jailSquareColor;
3740 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3742 gc_values.foreground = whitePieceColor;
3743 gc_values.background = darkSquareColor;
3744 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3746 gc_values.foreground = whitePieceColor;
3747 gc_values.background = lightSquareColor;
3748 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3750 gc_values.foreground = whitePieceColor;
3751 gc_values.background = jailSquareColor;
3752 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3754 gc_values.foreground = blackPieceColor;
3755 gc_values.background = darkSquareColor;
3756 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3758 gc_values.foreground = blackPieceColor;
3759 gc_values.background = lightSquareColor;
3760 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3762 gc_values.foreground = blackPieceColor;
3763 gc_values.background = jailSquareColor;
3764 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3768 void loadXIM(xim, xmask, filename, dest, mask)
3781 fp = fopen(filename, "rb");
3783 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3790 for (y=0; y<h; ++y) {
3791 for (x=0; x<h; ++x) {
3796 XPutPixel(xim, x, y, blackPieceColor);
3798 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3801 XPutPixel(xim, x, y, darkSquareColor);
3803 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3806 XPutPixel(xim, x, y, whitePieceColor);
3808 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3811 XPutPixel(xim, x, y, lightSquareColor);
3813 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3819 /* create Pixmap of piece */
3820 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3822 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3825 /* create Pixmap of clipmask
3826 Note: We assume the white/black pieces have the same
3827 outline, so we make only 6 masks. This is okay
3828 since the XPM clipmask routines do the same. */
3830 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3832 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3835 /* now create the 1-bit version */
3836 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3839 values.foreground = 1;
3840 values.background = 0;
3842 /* Don't use XtGetGC, not read only */
3843 maskGC = XCreateGC(xDisplay, *mask,
3844 GCForeground | GCBackground, &values);
3845 XCopyPlane(xDisplay, temp, *mask, maskGC,
3846 0, 0, squareSize, squareSize, 0, 0, 1);
3847 XFreePixmap(xDisplay, temp);
3852 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3854 void CreateXIMPieces()
3859 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3864 /* The XSynchronize calls were copied from CreatePieces.
3865 Not sure if needed, but can't hurt */
3866 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3869 /* temp needed by loadXIM() */
3870 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3871 0, 0, ss, ss, AllPlanes, XYPixmap);
3873 if (strlen(appData.pixmapDirectory) == 0) {
3877 if (appData.monoMode) {
3878 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3882 fprintf(stderr, _("\nLoading XIMs...\n"));
3884 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3885 fprintf(stderr, "%d", piece+1);
3886 for (kind=0; kind<4; kind++) {
3887 fprintf(stderr, ".");
3888 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3889 ExpandPathName(appData.pixmapDirectory),
3890 piece <= (int) WhiteKing ? "" : "w",
3891 pieceBitmapNames[piece],
3893 ximPieceBitmap[kind][piece] =
3894 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3895 0, 0, ss, ss, AllPlanes, XYPixmap);
3896 if (appData.debugMode)
3897 fprintf(stderr, _("(File:%s:) "), buf);
3898 loadXIM(ximPieceBitmap[kind][piece],
3900 &(xpmPieceBitmap2[kind][piece]),
3901 &(ximMaskPm2[piece]));
3902 if(piece <= (int)WhiteKing)
3903 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3905 fprintf(stderr," ");
3907 /* Load light and dark squares */
3908 /* If the LSQ and DSQ pieces don't exist, we will
3909 draw them with solid squares. */
3910 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3911 if (access(buf, 0) != 0) {
3915 fprintf(stderr, _("light square "));
3917 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3918 0, 0, ss, ss, AllPlanes, XYPixmap);
3919 if (appData.debugMode)
3920 fprintf(stderr, _("(File:%s:) "), buf);
3922 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3923 fprintf(stderr, _("dark square "));
3924 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3925 ExpandPathName(appData.pixmapDirectory), ss);
3926 if (appData.debugMode)
3927 fprintf(stderr, _("(File:%s:) "), buf);
3929 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3930 0, 0, ss, ss, AllPlanes, XYPixmap);
3931 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3932 xpmJailSquare = xpmLightSquare;
3934 fprintf(stderr, _("Done.\n"));
3936 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3940 void CreateXPMPieces()
3944 u_int ss = squareSize;
3946 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3947 XpmColorSymbol symbols[4];
3949 /* The XSynchronize calls were copied from CreatePieces.
3950 Not sure if needed, but can't hurt */
3951 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3953 /* Setup translations so piece colors match square colors */
3954 symbols[0].name = "light_piece";
3955 symbols[0].value = appData.whitePieceColor;
3956 symbols[1].name = "dark_piece";
3957 symbols[1].value = appData.blackPieceColor;
3958 symbols[2].name = "light_square";
3959 symbols[2].value = appData.lightSquareColor;
3960 symbols[3].name = "dark_square";
3961 symbols[3].value = appData.darkSquareColor;
3963 attr.valuemask = XpmColorSymbols;
3964 attr.colorsymbols = symbols;
3965 attr.numsymbols = 4;
3967 if (appData.monoMode) {
3968 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3972 if (strlen(appData.pixmapDirectory) == 0) {
3973 XpmPieces* pieces = builtInXpms;
3976 while (pieces->size != squareSize && pieces->size) pieces++;
3977 if (!pieces->size) {
3978 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3981 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3982 for (kind=0; kind<4; kind++) {
3984 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3985 pieces->xpm[piece][kind],
3986 &(xpmPieceBitmap2[kind][piece]),
3987 NULL, &attr)) != 0) {
3988 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3992 if(piece <= (int) WhiteKing)
3993 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3997 xpmJailSquare = xpmLightSquare;
4001 fprintf(stderr, _("\nLoading XPMs...\n"));
4004 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4005 fprintf(stderr, "%d ", piece+1);
4006 for (kind=0; kind<4; kind++) {
4007 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
4008 ExpandPathName(appData.pixmapDirectory),
4009 piece > (int) WhiteKing ? "w" : "",
4010 pieceBitmapNames[piece],
4012 if (appData.debugMode) {
4013 fprintf(stderr, _("(File:%s:) "), buf);
4015 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4016 &(xpmPieceBitmap2[kind][piece]),
4017 NULL, &attr)) != 0) {
4018 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
4019 // [HGM] missing: read of unorthodox piece failed; substitute King.
4020 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
4021 ExpandPathName(appData.pixmapDirectory),
4023 if (appData.debugMode) {
4024 fprintf(stderr, _("(Replace by File:%s:) "), buf);
4026 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4027 &(xpmPieceBitmap2[kind][piece]),
4031 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4036 if(piece <= (int) WhiteKing)
4037 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4040 /* Load light and dark squares */
4041 /* If the LSQ and DSQ pieces don't exist, we will
4042 draw them with solid squares. */
4043 fprintf(stderr, _("light square "));
4044 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4045 if (access(buf, 0) != 0) {
4049 if (appData.debugMode)
4050 fprintf(stderr, _("(File:%s:) "), buf);
4052 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4053 &xpmLightSquare, NULL, &attr)) != 0) {
4054 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4057 fprintf(stderr, _("dark square "));
4058 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4059 ExpandPathName(appData.pixmapDirectory), ss);
4060 if (appData.debugMode) {
4061 fprintf(stderr, _("(File:%s:) "), buf);
4063 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4064 &xpmDarkSquare, NULL, &attr)) != 0) {
4065 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4069 xpmJailSquare = xpmLightSquare;
4070 fprintf(stderr, _("Done.\n"));
4072 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4075 #endif /* HAVE_LIBXPM */
4078 /* No built-in bitmaps */
4083 u_int ss = squareSize;
4085 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4088 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4089 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4090 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4091 pieceBitmapNames[piece],
4092 ss, kind == SOLID ? 's' : 'o');
4093 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4094 if(piece <= (int)WhiteKing)
4095 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4099 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4103 /* With built-in bitmaps */
4106 BuiltInBits* bib = builtInBits;
4109 u_int ss = squareSize;
4111 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4114 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4116 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4117 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4118 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4119 pieceBitmapNames[piece],
4120 ss, kind == SOLID ? 's' : 'o');
4121 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4122 bib->bits[kind][piece], ss, ss);
4123 if(piece <= (int)WhiteKing)
4124 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4128 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4133 void ReadBitmap(pm, name, bits, wreq, hreq)
4136 unsigned char bits[];
4142 char msg[MSG_SIZ], fullname[MSG_SIZ];
4144 if (*appData.bitmapDirectory != NULLCHAR) {
4145 strcpy(fullname, appData.bitmapDirectory);
4146 strcat(fullname, "/");
4147 strcat(fullname, name);
4148 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4149 &w, &h, pm, &x_hot, &y_hot);
4150 fprintf(stderr, "load %s\n", name);
4151 if (errcode != BitmapSuccess) {
4153 case BitmapOpenFailed:
4154 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4156 case BitmapFileInvalid:
4157 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4159 case BitmapNoMemory:
4160 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4164 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4168 fprintf(stderr, _("%s: %s...using built-in\n"),
4170 } else if (w != wreq || h != hreq) {
4172 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4173 programName, fullname, w, h, wreq, hreq);
4179 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4188 if (lineGap == 0) return;
4190 /* [HR] Split this into 2 loops for non-square boards. */
4192 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4193 gridSegments[i].x1 = 0;
4194 gridSegments[i].x2 =
4195 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4196 gridSegments[i].y1 = gridSegments[i].y2
4197 = lineGap / 2 + (i * (squareSize + lineGap));
4200 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4201 gridSegments[j + i].y1 = 0;
4202 gridSegments[j + i].y2 =
4203 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4204 gridSegments[j + i].x1 = gridSegments[j + i].x2
4205 = lineGap / 2 + (j * (squareSize + lineGap));
4209 static void MenuBarSelect(w, addr, index)
4214 XtActionProc proc = (XtActionProc) addr;
4216 (proc)(NULL, NULL, NULL, NULL);
4219 void CreateMenuBarPopup(parent, name, mb)
4229 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4232 XtSetArg(args[j], XtNleftMargin, 20); j++;
4233 XtSetArg(args[j], XtNrightMargin, 20); j++;
4235 while (mi->string != NULL) {
4236 if (strcmp(mi->string, "----") == 0) {
4237 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4240 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4241 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4243 XtAddCallback(entry, XtNcallback,
4244 (XtCallbackProc) MenuBarSelect,
4245 (caddr_t) mi->proc);
4251 Widget CreateMenuBar(mb)
4255 Widget anchor, menuBar;
4257 char menuName[MSG_SIZ];
4260 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4261 XtSetArg(args[j], XtNvSpace, 0); j++;
4262 XtSetArg(args[j], XtNborderWidth, 0); j++;
4263 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4264 formWidget, args, j);
4266 while (mb->name != NULL) {
4267 strcpy(menuName, "menu");
4268 strcat(menuName, mb->name);
4270 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4273 shortName[0] = _(mb->name)[0];
4274 shortName[1] = NULLCHAR;
4275 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4278 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4281 XtSetArg(args[j], XtNborderWidth, 0); j++;
4282 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4284 CreateMenuBarPopup(menuBar, menuName, mb);
4290 Widget CreateButtonBar(mi)
4294 Widget button, buttonBar;
4298 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4300 XtSetArg(args[j], XtNhSpace, 0); j++;
4302 XtSetArg(args[j], XtNborderWidth, 0); j++;
4303 XtSetArg(args[j], XtNvSpace, 0); j++;
4304 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4305 formWidget, args, j);
4307 while (mi->string != NULL) {
4310 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4311 XtSetArg(args[j], XtNborderWidth, 0); j++;
4313 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4314 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4315 buttonBar, args, j);
4316 XtAddCallback(button, XtNcallback,
4317 (XtCallbackProc) MenuBarSelect,
4318 (caddr_t) mi->proc);
4325 CreatePieceMenu(name, color)
4332 ChessSquare selection;
4334 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4335 boardWidget, args, 0);
4337 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4338 String item = pieceMenuStrings[color][i];
4340 if (strcmp(item, "----") == 0) {
4341 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4344 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4345 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4347 selection = pieceMenuTranslation[color][i];
4348 XtAddCallback(entry, XtNcallback,
4349 (XtCallbackProc) PieceMenuSelect,
4350 (caddr_t) selection);
4351 if (selection == WhitePawn || selection == BlackPawn) {
4352 XtSetArg(args[0], XtNpopupOnEntry, entry);
4353 XtSetValues(menu, args, 1);
4366 ChessSquare selection;
4368 whitePieceMenu = CreatePieceMenu("menuW", 0);
4369 blackPieceMenu = CreatePieceMenu("menuB", 1);
4371 XtRegisterGrabAction(PieceMenuPopup, True,
4372 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4373 GrabModeAsync, GrabModeAsync);
4375 XtSetArg(args[0], XtNlabel, _("Drop"));
4376 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4377 boardWidget, args, 1);
4378 for (i = 0; i < DROP_MENU_SIZE; i++) {
4379 String item = dropMenuStrings[i];
4381 if (strcmp(item, "----") == 0) {
4382 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4385 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4386 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4388 selection = dropMenuTranslation[i];
4389 XtAddCallback(entry, XtNcallback,
4390 (XtCallbackProc) DropMenuSelect,
4391 (caddr_t) selection);
4396 void SetupDropMenu()
4404 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4405 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4406 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4407 dmEnables[i].piece);
4408 XtSetSensitive(entry, p != NULL || !appData.testLegality
4409 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4410 && !appData.icsActive));
4412 while (p && *p++ == dmEnables[i].piece) count++;
4413 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4415 XtSetArg(args[j], XtNlabel, label); j++;
4416 XtSetValues(entry, args, j);
4420 void PieceMenuPopup(w, event, params, num_params)
4424 Cardinal *num_params;
4427 if (event->type != ButtonPress) return;
4428 if (errorUp) ErrorPopDown();
4432 whichMenu = params[0];
4434 case IcsPlayingWhite:
4435 case IcsPlayingBlack:
4437 case MachinePlaysWhite:
4438 case MachinePlaysBlack:
4439 if (appData.testLegality &&
4440 gameInfo.variant != VariantBughouse &&
4441 gameInfo.variant != VariantCrazyhouse) return;
4443 whichMenu = "menuD";
4449 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4450 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4451 pmFromX = pmFromY = -1;
4455 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4457 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4459 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4462 static void PieceMenuSelect(w, piece, junk)
4467 if (pmFromX < 0 || pmFromY < 0) return;
4468 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4471 static void DropMenuSelect(w, piece, junk)
4476 if (pmFromX < 0 || pmFromY < 0) return;
4477 DropMenuEvent(piece, pmFromX, pmFromY);
4480 void WhiteClock(w, event, prms, nprms)
4486 if (gameMode == EditPosition || gameMode == IcsExamining) {
4487 SetWhiteToPlayEvent();
4488 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4493 void BlackClock(w, event, prms, nprms)
4499 if (gameMode == EditPosition || gameMode == IcsExamining) {
4500 SetBlackToPlayEvent();
4501 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4508 * If the user selects on a border boundary, return -1; if off the board,
4509 * return -2. Otherwise map the event coordinate to the square.
4511 int EventToSquare(x, limit)
4519 if ((x % (squareSize + lineGap)) >= squareSize)
4521 x /= (squareSize + lineGap);
4527 static void do_flash_delay(msec)
4533 static void drawHighlight(file, rank, gc)
4539 if (lineGap == 0 || appData.blindfold) return;
4542 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4543 (squareSize + lineGap);
4544 y = lineGap/2 + rank * (squareSize + lineGap);
4546 x = lineGap/2 + file * (squareSize + lineGap);
4547 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4548 (squareSize + lineGap);
4551 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4552 squareSize+lineGap, squareSize+lineGap);
4555 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4556 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4559 SetHighlights(fromX, fromY, toX, toY)
4560 int fromX, fromY, toX, toY;
4562 if (hi1X != fromX || hi1Y != fromY) {
4563 if (hi1X >= 0 && hi1Y >= 0) {
4564 drawHighlight(hi1X, hi1Y, lineGC);
4566 if (fromX >= 0 && fromY >= 0) {
4567 drawHighlight(fromX, fromY, highlineGC);
4570 if (hi2X != toX || hi2Y != toY) {
4571 if (hi2X >= 0 && hi2Y >= 0) {
4572 drawHighlight(hi2X, hi2Y, lineGC);
4574 if (toX >= 0 && toY >= 0) {
4575 drawHighlight(toX, toY, highlineGC);
4587 SetHighlights(-1, -1, -1, -1);
4592 SetPremoveHighlights(fromX, fromY, toX, toY)
4593 int fromX, fromY, toX, toY;
4595 if (pm1X != fromX || pm1Y != fromY) {
4596 if (pm1X >= 0 && pm1Y >= 0) {
4597 drawHighlight(pm1X, pm1Y, lineGC);
4599 if (fromX >= 0 && fromY >= 0) {
4600 drawHighlight(fromX, fromY, prelineGC);
4603 if (pm2X != toX || pm2Y != toY) {
4604 if (pm2X >= 0 && pm2Y >= 0) {
4605 drawHighlight(pm2X, pm2Y, lineGC);
4607 if (toX >= 0 && toY >= 0) {
4608 drawHighlight(toX, toY, prelineGC);
4618 ClearPremoveHighlights()
4620 SetPremoveHighlights(-1, -1, -1, -1);
4623 static void BlankSquare(x, y, color, piece, dest)
4628 if (useImages && useImageSqs) {
4632 pm = xpmLightSquare;
4637 case 2: /* neutral */
4642 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4643 squareSize, squareSize, x, y);
4653 case 2: /* neutral */
4658 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4663 I split out the routines to draw a piece so that I could
4664 make a generic flash routine.
4666 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4668 int square_color, x, y;
4671 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4672 switch (square_color) {
4674 case 2: /* neutral */
4676 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4677 ? *pieceToOutline(piece)
4678 : *pieceToSolid(piece),
4679 dest, bwPieceGC, 0, 0,
4680 squareSize, squareSize, x, y);
4683 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4684 ? *pieceToSolid(piece)
4685 : *pieceToOutline(piece),
4686 dest, wbPieceGC, 0, 0,
4687 squareSize, squareSize, x, y);
4692 static void monoDrawPiece(piece, square_color, x, y, dest)
4694 int square_color, x, y;
4697 switch (square_color) {
4699 case 2: /* neutral */
4701 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4702 ? *pieceToOutline(piece)
4703 : *pieceToSolid(piece),
4704 dest, bwPieceGC, 0, 0,
4705 squareSize, squareSize, x, y, 1);
4708 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4709 ? *pieceToSolid(piece)
4710 : *pieceToOutline(piece),
4711 dest, wbPieceGC, 0, 0,
4712 squareSize, squareSize, x, y, 1);
4717 static void colorDrawPiece(piece, square_color, x, y, dest)
4719 int square_color, x, y;
4722 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4723 switch (square_color) {
4725 XCopyPlane(xDisplay, *pieceToSolid(piece),
4726 dest, (int) piece < (int) BlackPawn
4727 ? wlPieceGC : blPieceGC, 0, 0,
4728 squareSize, squareSize, x, y, 1);
4731 XCopyPlane(xDisplay, *pieceToSolid(piece),
4732 dest, (int) piece < (int) BlackPawn
4733 ? wdPieceGC : bdPieceGC, 0, 0,
4734 squareSize, squareSize, x, y, 1);
4736 case 2: /* neutral */
4738 XCopyPlane(xDisplay, *pieceToSolid(piece),
4739 dest, (int) piece < (int) BlackPawn
4740 ? wjPieceGC : bjPieceGC, 0, 0,
4741 squareSize, squareSize, x, y, 1);
4746 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4748 int square_color, x, y;
4753 switch (square_color) {
4755 case 2: /* neutral */
4757 if ((int)piece < (int) BlackPawn) {
4765 if ((int)piece < (int) BlackPawn) {
4773 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4774 dest, wlPieceGC, 0, 0,
4775 squareSize, squareSize, x, y);
4778 typedef void (*DrawFunc)();
4780 DrawFunc ChooseDrawFunc()
4782 if (appData.monoMode) {
4783 if (DefaultDepth(xDisplay, xScreen) == 1) {
4784 return monoDrawPiece_1bit;
4786 return monoDrawPiece;
4790 return colorDrawPieceImage;
4792 return colorDrawPiece;
4796 /* [HR] determine square color depending on chess variant. */
4797 static int SquareColor(row, column)
4802 if (gameInfo.variant == VariantXiangqi) {
4803 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4805 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4807 } else if (row <= 4) {
4813 square_color = ((column + row) % 2) == 1;
4816 /* [hgm] holdings: next line makes all holdings squares light */
4817 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4819 return square_color;
4822 void DrawSquare(row, column, piece, do_flash)
4823 int row, column, do_flash;
4826 int square_color, x, y, direction, font_ascent, font_descent;
4829 XCharStruct overall;
4833 /* Calculate delay in milliseconds (2-delays per complete flash) */
4834 flash_delay = 500 / appData.flashRate;
4837 x = lineGap + ((BOARD_WIDTH-1)-column) *
4838 (squareSize + lineGap);
4839 y = lineGap + row * (squareSize + lineGap);
4841 x = lineGap + column * (squareSize + lineGap);
4842 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4843 (squareSize + lineGap);
4846 square_color = SquareColor(row, column);
4848 if ( // [HGM] holdings: blank out area between board and holdings
4849 column == BOARD_LEFT-1 || column == BOARD_RGHT
4850 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4851 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4852 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4854 // [HGM] print piece counts next to holdings
4855 string[1] = NULLCHAR;
4856 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4857 string[0] = '0' + piece;
4858 XTextExtents(countFontStruct, string, 1, &direction,
4859 &font_ascent, &font_descent, &overall);
4860 if (appData.monoMode) {
4861 XDrawImageString(xDisplay, xBoardWindow, countGC,
4862 x + squareSize - overall.width - 2,
4863 y + font_ascent + 1, string, 1);
4865 XDrawString(xDisplay, xBoardWindow, countGC,
4866 x + squareSize - overall.width - 2,
4867 y + font_ascent + 1, string, 1);
4870 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4871 string[0] = '0' + piece;
4872 XTextExtents(countFontStruct, string, 1, &direction,
4873 &font_ascent, &font_descent, &overall);
4874 if (appData.monoMode) {
4875 XDrawImageString(xDisplay, xBoardWindow, countGC,
4876 x + 2, y + font_ascent + 1, string, 1);
4878 XDrawString(xDisplay, xBoardWindow, countGC,
4879 x + 2, y + font_ascent + 1, string, 1);
4883 if (piece == EmptySquare || appData.blindfold) {
4884 BlankSquare(x, y, square_color, piece, xBoardWindow);
4886 drawfunc = ChooseDrawFunc();
4887 if (do_flash && appData.flashCount > 0) {
4888 for (i=0; i<appData.flashCount; ++i) {
4890 drawfunc(piece, square_color, x, y, xBoardWindow);
4891 XSync(xDisplay, False);
4892 do_flash_delay(flash_delay);
4894 BlankSquare(x, y, square_color, piece, xBoardWindow);
4895 XSync(xDisplay, False);
4896 do_flash_delay(flash_delay);
4899 drawfunc(piece, square_color, x, y, xBoardWindow);
4903 string[1] = NULLCHAR;
4904 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4905 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4906 string[0] = 'a' + column - BOARD_LEFT;
4907 XTextExtents(coordFontStruct, string, 1, &direction,
4908 &font_ascent, &font_descent, &overall);
4909 if (appData.monoMode) {
4910 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4911 x + squareSize - overall.width - 2,
4912 y + squareSize - font_descent - 1, string, 1);
4914 XDrawString(xDisplay, xBoardWindow, coordGC,
4915 x + squareSize - overall.width - 2,
4916 y + squareSize - font_descent - 1, string, 1);
4919 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4920 string[0] = ONE + row;
4921 XTextExtents(coordFontStruct, string, 1, &direction,
4922 &font_ascent, &font_descent, &overall);
4923 if (appData.monoMode) {
4924 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4925 x + 2, y + font_ascent + 1, string, 1);
4927 XDrawString(xDisplay, xBoardWindow, coordGC,
4928 x + 2, y + font_ascent + 1, string, 1);
4934 /* Why is this needed on some versions of X? */
4935 void EventProc(widget, unused, event)
4940 if (!XtIsRealized(widget))
4943 switch (event->type) {
4945 if (event->xexpose.count > 0) return; /* no clipping is done */
4946 XDrawPosition(widget, True, NULL);
4954 void DrawPosition(fullRedraw, board)
4955 /*Boolean*/int fullRedraw;
4958 XDrawPosition(boardWidget, fullRedraw, board);
4961 /* Returns 1 if there are "too many" differences between b1 and b2
4962 (i.e. more than 1 move was made) */
4963 static int too_many_diffs(b1, b2)
4969 for (i=0; i<BOARD_HEIGHT; ++i) {
4970 for (j=0; j<BOARD_WIDTH; ++j) {
4971 if (b1[i][j] != b2[i][j]) {
4972 if (++c > 4) /* Castling causes 4 diffs */
4981 /* Matrix describing castling maneuvers */
4982 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4983 static int castling_matrix[4][5] = {
4984 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4985 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4986 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4987 { 7, 7, 4, 5, 6 } /* 0-0, black */
4990 /* Checks whether castling occurred. If it did, *rrow and *rcol
4991 are set to the destination (row,col) of the rook that moved.
4993 Returns 1 if castling occurred, 0 if not.
4995 Note: Only handles a max of 1 castling move, so be sure
4996 to call too_many_diffs() first.
4998 static int check_castle_draw(newb, oldb, rrow, rcol)
5005 /* For each type of castling... */
5006 for (i=0; i<4; ++i) {
5007 r = castling_matrix[i];
5009 /* Check the 4 squares involved in the castling move */
5011 for (j=1; j<=4; ++j) {
5012 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
5019 /* All 4 changed, so it must be a castling move */
5028 static int damage[BOARD_RANKS][BOARD_FILES];
5031 * event handler for redrawing the board
5033 void XDrawPosition(w, repaint, board)
5035 /*Boolean*/int repaint;
5039 static int lastFlipView = 0;
5040 static int lastBoardValid = 0;
5041 static Board lastBoard;
5045 if (board == NULL) {
5046 if (!lastBoardValid) return;
5049 if (!lastBoardValid || lastFlipView != flipView) {
5050 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5051 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5056 * It would be simpler to clear the window with XClearWindow()
5057 * but this causes a very distracting flicker.
5060 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5062 /* If too much changes (begin observing new game, etc.), don't
5064 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5066 /* Special check for castling so we don't flash both the king
5067 and the rook (just flash the king). */
5069 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5070 /* Draw rook with NO flashing. King will be drawn flashing later */
5071 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5072 lastBoard[rrow][rcol] = board[rrow][rcol];
5076 /* First pass -- Draw (newly) empty squares and repair damage.
5077 This prevents you from having a piece show up twice while it
5078 is flashing on its new square */
5079 for (i = 0; i < BOARD_HEIGHT; i++)
5080 for (j = 0; j < BOARD_WIDTH; j++)
5081 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5083 DrawSquare(i, j, board[i][j], 0);
5084 damage[i][j] = False;
5087 /* Second pass -- Draw piece(s) in new position and flash them */
5088 for (i = 0; i < BOARD_HEIGHT; i++)
5089 for (j = 0; j < BOARD_WIDTH; j++)
5090 if (board[i][j] != lastBoard[i][j]) {
5091 DrawSquare(i, j, board[i][j], do_flash);
5095 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5096 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5098 for (i = 0; i < BOARD_HEIGHT; i++)
5099 for (j = 0; j < BOARD_WIDTH; j++) {
5100 DrawSquare(i, j, board[i][j], 0);
5101 damage[i][j] = False;
5105 CopyBoard(lastBoard, board);
5107 lastFlipView = flipView;
5109 /* Draw highlights */
5110 if (pm1X >= 0 && pm1Y >= 0) {
5111 drawHighlight(pm1X, pm1Y, prelineGC);
5113 if (pm2X >= 0 && pm2Y >= 0) {
5114 drawHighlight(pm2X, pm2Y, prelineGC);
5116 if (hi1X >= 0 && hi1Y >= 0) {
5117 drawHighlight(hi1X, hi1Y, highlineGC);
5119 if (hi2X >= 0 && hi2Y >= 0) {
5120 drawHighlight(hi2X, hi2Y, highlineGC);
5123 /* If piece being dragged around board, must redraw that too */
5126 XSync(xDisplay, False);
5131 * event handler for redrawing the board
5133 void DrawPositionProc(w, event, prms, nprms)
5139 XDrawPosition(w, True, NULL);
5144 * event handler for parsing user moves
5146 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5147 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5148 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5149 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5150 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5151 // and at the end FinishMove() to perform the move after optional promotion popups.
5152 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5153 void HandleUserMove(w, event, prms, nprms)
5159 if (w != boardWidget || errorExitStatus != -1) return;
5162 if (event->type == ButtonPress) {
5163 XtPopdown(promotionShell);
5164 XtDestroyWidget(promotionShell);
5165 promotionUp = False;
5173 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5174 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5175 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5178 void AnimateUserMove (Widget w, XEvent * event,
5179 String * params, Cardinal * nParams)
5181 DragPieceMove(event->xmotion.x, event->xmotion.y);
5184 Widget CommentCreate(name, text, mutable, callback, lines)
5186 int /*Boolean*/ mutable;
5187 XtCallbackProc callback;
5191 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5196 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5197 XtGetValues(boardWidget, args, j);
5200 XtSetArg(args[j], XtNresizable, True); j++;
5203 XtCreatePopupShell(name, topLevelShellWidgetClass,
5204 shellWidget, args, j);
5207 XtCreatePopupShell(name, transientShellWidgetClass,
5208 shellWidget, args, j);
5211 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5212 layoutArgs, XtNumber(layoutArgs));
5214 XtCreateManagedWidget("form", formWidgetClass, layout,
5215 formArgs, XtNumber(formArgs));
5219 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5220 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5222 XtSetArg(args[j], XtNstring, text); j++;
5223 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5224 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5225 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5226 XtSetArg(args[j], XtNright, XtChainRight); j++;
5227 XtSetArg(args[j], XtNresizable, True); j++;
5228 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5229 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5230 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5231 XtSetArg(args[j], XtNautoFill, True); j++;
5232 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5234 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5238 XtSetArg(args[j], XtNfromVert, edit); j++;
5239 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5240 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5241 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5242 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5244 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5245 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5248 XtSetArg(args[j], XtNfromVert, edit); j++;
5249 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5250 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5251 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5252 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5253 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5255 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5256 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5259 XtSetArg(args[j], XtNfromVert, edit); j++;
5260 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5261 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5262 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5263 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5264 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5266 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5267 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5270 XtSetArg(args[j], XtNfromVert, edit); j++;
5271 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5272 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5273 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5274 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5276 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5277 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5280 XtSetArg(args[j], XtNfromVert, edit); j++;
5281 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5282 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5283 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5284 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5285 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5287 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5288 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5291 XtRealizeWidget(shell);
5293 if (commentX == -1) {
5296 Dimension pw_height;
5297 Dimension ew_height;
5300 XtSetArg(args[j], XtNheight, &ew_height); j++;
5301 XtGetValues(edit, args, j);
5304 XtSetArg(args[j], XtNheight, &pw_height); j++;
5305 XtGetValues(shell, args, j);
5306 commentH = pw_height + (lines - 1) * ew_height;
5307 commentW = bw_width - 16;
5309 XSync(xDisplay, False);
5311 /* This code seems to tickle an X bug if it is executed too soon
5312 after xboard starts up. The coordinates get transformed as if
5313 the main window was positioned at (0, 0).
5315 XtTranslateCoords(shellWidget,
5316 (bw_width - commentW) / 2, 0 - commentH / 2,
5317 &commentX, &commentY);
5319 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5320 RootWindowOfScreen(XtScreen(shellWidget)),
5321 (bw_width - commentW) / 2, 0 - commentH / 2,
5326 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5329 XtSetArg(args[j], XtNheight, commentH); j++;
5330 XtSetArg(args[j], XtNwidth, commentW); j++;
5331 XtSetArg(args[j], XtNx, commentX); j++;
5332 XtSetArg(args[j], XtNy, commentY); j++;
5333 XtSetValues(shell, args, j);
5334 XtSetKeyboardFocus(shell, edit);
5339 /* Used for analysis window and ICS input window */
5340 Widget MiscCreate(name, text, mutable, callback, lines)
5342 int /*Boolean*/ mutable;
5343 XtCallbackProc callback;
5347 Widget shell, layout, form, edit;
5349 Dimension bw_width, pw_height, ew_height, w, h;
5355 XtSetArg(args[j], XtNresizable, True); j++;
5358 XtCreatePopupShell(name, topLevelShellWidgetClass,
5359 shellWidget, args, j);
5362 XtCreatePopupShell(name, transientShellWidgetClass,
5363 shellWidget, args, j);
5366 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5367 layoutArgs, XtNumber(layoutArgs));
5369 XtCreateManagedWidget("form", formWidgetClass, layout,
5370 formArgs, XtNumber(formArgs));
5374 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5375 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5377 XtSetArg(args[j], XtNstring, text); j++;
5378 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5379 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5380 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5381 XtSetArg(args[j], XtNright, XtChainRight); j++;
5382 XtSetArg(args[j], XtNresizable, True); j++;
5383 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5384 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5385 XtSetArg(args[j], XtNautoFill, True); j++;
5386 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5388 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5390 XtRealizeWidget(shell);
5393 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5394 XtGetValues(boardWidget, args, j);
5397 XtSetArg(args[j], XtNheight, &ew_height); j++;
5398 XtGetValues(edit, args, j);
5401 XtSetArg(args[j], XtNheight, &pw_height); j++;
5402 XtGetValues(shell, args, j);
5403 h = pw_height + (lines - 1) * ew_height;
5406 XSync(xDisplay, False);
5408 /* This code seems to tickle an X bug if it is executed too soon
5409 after xboard starts up. The coordinates get transformed as if
5410 the main window was positioned at (0, 0).
5412 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5414 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5415 RootWindowOfScreen(XtScreen(shellWidget)),
5416 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5420 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5423 XtSetArg(args[j], XtNheight, h); j++;
5424 XtSetArg(args[j], XtNwidth, w); j++;
5425 XtSetArg(args[j], XtNx, x); j++;
5426 XtSetArg(args[j], XtNy, y); j++;
5427 XtSetValues(shell, args, j);
5433 static int savedIndex; /* gross that this is global */
5435 void EditCommentPopUp(index, title, text)
5444 if (text == NULL) text = "";
5446 if (editShell == NULL) {
5448 CommentCreate(title, text, True, EditCommentCallback, 4);
5449 XtRealizeWidget(editShell);
5450 CatchDeleteWindow(editShell, "EditCommentPopDown");
5452 edit = XtNameToWidget(editShell, "*form.text");
5454 XtSetArg(args[j], XtNstring, text); j++;
5455 XtSetValues(edit, args, j);
5457 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5458 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5459 XtSetValues(editShell, args, j);
5462 XtPopup(editShell, XtGrabNone);
5466 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5467 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5471 void EditCommentCallback(w, client_data, call_data)
5473 XtPointer client_data, call_data;
5481 XtSetArg(args[j], XtNlabel, &name); j++;
5482 XtGetValues(w, args, j);
5484 if (strcmp(name, _("ok")) == 0) {
5485 edit = XtNameToWidget(editShell, "*form.text");
5487 XtSetArg(args[j], XtNstring, &val); j++;
5488 XtGetValues(edit, args, j);
5489 ReplaceComment(savedIndex, val);
5490 EditCommentPopDown();
5491 } else if (strcmp(name, _("cancel")) == 0) {
5492 EditCommentPopDown();
5493 } else if (strcmp(name, _("clear")) == 0) {
5494 edit = XtNameToWidget(editShell, "*form.text");
5495 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5496 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5500 void EditCommentPopDown()
5505 if (!editUp) return;
5507 XtSetArg(args[j], XtNx, &commentX); j++;
5508 XtSetArg(args[j], XtNy, &commentY); j++;
5509 XtSetArg(args[j], XtNheight, &commentH); j++;
5510 XtSetArg(args[j], XtNwidth, &commentW); j++;
5511 XtGetValues(editShell, args, j);
5512 XtPopdown(editShell);
5515 XtSetArg(args[j], XtNleftBitmap, None); j++;
5516 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5520 void ICSInputBoxPopUp()
5525 char *title = _("ICS Input");
5528 if (ICSInputShell == NULL) {
5529 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5530 tr = XtParseTranslationTable(ICSInputTranslations);
5531 edit = XtNameToWidget(ICSInputShell, "*form.text");
5532 XtOverrideTranslations(edit, tr);
5533 XtRealizeWidget(ICSInputShell);
5534 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5537 edit = XtNameToWidget(ICSInputShell, "*form.text");
5539 XtSetArg(args[j], XtNstring, ""); j++;
5540 XtSetValues(edit, args, j);
5542 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5543 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5544 XtSetValues(ICSInputShell, args, j);
5547 XtPopup(ICSInputShell, XtGrabNone);
5548 XtSetKeyboardFocus(ICSInputShell, edit);
5550 ICSInputBoxUp = True;
5552 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5553 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5557 void ICSInputSendText()
5564 edit = XtNameToWidget(ICSInputShell, "*form.text");
5566 XtSetArg(args[j], XtNstring, &val); j++;
5567 XtGetValues(edit, args, j);
5568 SendMultiLineToICS(val);
5569 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5570 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5573 void ICSInputBoxPopDown()
5578 if (!ICSInputBoxUp) return;
5580 XtPopdown(ICSInputShell);
5581 ICSInputBoxUp = False;
5583 XtSetArg(args[j], XtNleftBitmap, None); j++;
5584 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5588 void CommentPopUp(title, text)
5595 if (commentShell == NULL) {
5597 CommentCreate(title, text, False, CommentCallback, 4);
5598 XtRealizeWidget(commentShell);
5599 CatchDeleteWindow(commentShell, "CommentPopDown");
5601 edit = XtNameToWidget(commentShell, "*form.text");
5603 XtSetArg(args[j], XtNstring, text); j++;
5604 XtSetValues(edit, args, j);
5606 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5607 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5608 XtSetValues(commentShell, args, j);
5611 XtPopup(commentShell, XtGrabNone);
5612 XSync(xDisplay, False);
5617 void CommentCallback(w, client_data, call_data)
5619 XtPointer client_data, call_data;
5626 XtSetArg(args[j], XtNlabel, &name); j++;
5627 XtGetValues(w, args, j);
5629 if (strcmp(name, _("close")) == 0) {
5631 } else if (strcmp(name, _("edit")) == 0) {
5638 void CommentPopDown()
5643 if (!commentUp) return;
5645 XtSetArg(args[j], XtNx, &commentX); j++;
5646 XtSetArg(args[j], XtNy, &commentY); j++;
5647 XtSetArg(args[j], XtNwidth, &commentW); j++;
5648 XtSetArg(args[j], XtNheight, &commentH); j++;
5649 XtGetValues(commentShell, args, j);
5650 XtPopdown(commentShell);
5651 XSync(xDisplay, False);
5655 void FileNamePopUp(label, def, proc, openMode)
5662 Widget popup, layout, dialog, edit;
5668 fileProc = proc; /* I can't see a way not */
5669 fileOpenMode = openMode; /* to use globals here */
5672 XtSetArg(args[i], XtNresizable, True); i++;
5673 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5674 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5675 fileNameShell = popup =
5676 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5677 shellWidget, args, i);
5680 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5681 layoutArgs, XtNumber(layoutArgs));
5684 XtSetArg(args[i], XtNlabel, label); i++;
5685 XtSetArg(args[i], XtNvalue, def); i++;
5686 XtSetArg(args[i], XtNborderWidth, 0); i++;
5687 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5690 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5691 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5692 (XtPointer) dialog);
5694 XtRealizeWidget(popup);
5695 CatchDeleteWindow(popup, "FileNamePopDown");
5697 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5698 &x, &y, &win_x, &win_y, &mask);
5700 XtSetArg(args[0], XtNx, x - 10);
5701 XtSetArg(args[1], XtNy, y - 30);
5702 XtSetValues(popup, args, 2);
5704 XtPopup(popup, XtGrabExclusive);
5707 edit = XtNameToWidget(dialog, "*value");
5708 XtSetKeyboardFocus(popup, edit);
5711 void FileNamePopDown()
5713 if (!filenameUp) return;
5714 XtPopdown(fileNameShell);
5715 XtDestroyWidget(fileNameShell);
5720 void FileNameCallback(w, client_data, call_data)
5722 XtPointer client_data, call_data;
5727 XtSetArg(args[0], XtNlabel, &name);
5728 XtGetValues(w, args, 1);
5730 if (strcmp(name, _("cancel")) == 0) {
5735 FileNameAction(w, NULL, NULL, NULL);
5738 void FileNameAction(w, event, prms, nprms)
5750 name = XawDialogGetValueString(w = XtParent(w));
5752 if ((name != NULL) && (*name != NULLCHAR)) {
5754 XtPopdown(w = XtParent(XtParent(w)));
5758 p = strrchr(buf, ' ');
5765 fullname = ExpandPathName(buf);
5767 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5770 f = fopen(fullname, fileOpenMode);
5772 DisplayError(_("Failed to open file"), errno);
5774 (void) (*fileProc)(f, index, buf);
5781 XtPopdown(w = XtParent(XtParent(w)));
5787 void PromotionPopUp()
5790 Widget dialog, layout;
5792 Dimension bw_width, pw_width;
5796 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5797 XtGetValues(boardWidget, args, j);
5800 XtSetArg(args[j], XtNresizable, True); j++;
5801 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5803 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5804 shellWidget, args, j);
5806 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5807 layoutArgs, XtNumber(layoutArgs));
5810 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5811 XtSetArg(args[j], XtNborderWidth, 0); j++;
5812 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5815 if(gameInfo.variant != VariantShogi) {
5816 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5817 (XtPointer) dialog);
5818 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5819 (XtPointer) dialog);
5820 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5821 (XtPointer) dialog);
5822 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5823 (XtPointer) dialog);
5824 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5825 gameInfo.variant == VariantGiveaway) {
5826 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5827 (XtPointer) dialog);
5829 if(gameInfo.variant == VariantCapablanca ||
5830 gameInfo.variant == VariantGothic ||
5831 gameInfo.variant == VariantCapaRandom) {
5832 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5833 (XtPointer) dialog);
5834 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5835 (XtPointer) dialog);
5837 } else // [HGM] shogi
5839 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5840 (XtPointer) dialog);
5841 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5842 (XtPointer) dialog);
5844 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5845 (XtPointer) dialog);
5847 XtRealizeWidget(promotionShell);
5848 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5851 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5852 XtGetValues(promotionShell, args, j);
5854 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5855 lineGap + squareSize/3 +
5856 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5857 0 : 6*(squareSize + lineGap)), &x, &y);
5860 XtSetArg(args[j], XtNx, x); j++;
5861 XtSetArg(args[j], XtNy, y); j++;
5862 XtSetValues(promotionShell, args, j);
5864 XtPopup(promotionShell, XtGrabNone);
5869 void PromotionPopDown()
5871 if (!promotionUp) return;
5872 XtPopdown(promotionShell);
5873 XtDestroyWidget(promotionShell);
5874 promotionUp = False;
5877 void PromotionCallback(w, client_data, call_data)
5879 XtPointer client_data, call_data;
5885 XtSetArg(args[0], XtNlabel, &name);
5886 XtGetValues(w, args, 1);
5890 if (fromX == -1) return;
5892 if (strcmp(name, _("cancel")) == 0) {
5896 } else if (strcmp(name, _("Knight")) == 0) {
5898 } else if (strcmp(name, _("Promote")) == 0) {
5900 } else if (strcmp(name, _("Defer")) == 0) {
5903 promoChar = ToLower(name[0]);
5906 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5908 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5909 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5914 void ErrorCallback(w, client_data, call_data)
5916 XtPointer client_data, call_data;
5919 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5921 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5927 if (!errorUp) return;
5929 XtPopdown(errorShell);
5930 XtDestroyWidget(errorShell);
5931 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5934 void ErrorPopUp(title, label, modal)
5935 char *title, *label;
5939 Widget dialog, layout;
5943 Dimension bw_width, pw_width;
5944 Dimension pw_height;
5948 XtSetArg(args[i], XtNresizable, True); i++;
5949 XtSetArg(args[i], XtNtitle, title); i++;
5951 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5952 shellWidget, args, i);
5954 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5955 layoutArgs, XtNumber(layoutArgs));
5958 XtSetArg(args[i], XtNlabel, label); i++;
5959 XtSetArg(args[i], XtNborderWidth, 0); i++;
5960 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5963 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5965 XtRealizeWidget(errorShell);
5966 CatchDeleteWindow(errorShell, "ErrorPopDown");
5969 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5970 XtGetValues(boardWidget, args, i);
5972 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5973 XtSetArg(args[i], XtNheight, &pw_height); i++;
5974 XtGetValues(errorShell, args, i);
5977 /* This code seems to tickle an X bug if it is executed too soon
5978 after xboard starts up. The coordinates get transformed as if
5979 the main window was positioned at (0, 0).
5981 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5982 0 - pw_height + squareSize / 3, &x, &y);
5984 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5985 RootWindowOfScreen(XtScreen(boardWidget)),
5986 (bw_width - pw_width) / 2,
5987 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5991 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5994 XtSetArg(args[i], XtNx, x); i++;
5995 XtSetArg(args[i], XtNy, y); i++;
5996 XtSetValues(errorShell, args, i);
5999 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6002 /* Disable all user input other than deleting the window */
6003 static int frozen = 0;
6007 /* Grab by a widget that doesn't accept input */
6008 XtAddGrab(messageWidget, TRUE, FALSE);
6012 /* Undo a FreezeUI */
6015 if (!frozen) return;
6016 XtRemoveGrab(messageWidget);
6020 char *ModeToWidgetName(mode)
6024 case BeginningOfGame:
6025 if (appData.icsActive)
6026 return "menuMode.ICS Client";
6027 else if (appData.noChessProgram ||
6028 *appData.cmailGameName != NULLCHAR)
6029 return "menuMode.Edit Game";
6031 return "menuMode.Machine Black";
6032 case MachinePlaysBlack:
6033 return "menuMode.Machine Black";
6034 case MachinePlaysWhite:
6035 return "menuMode.Machine White";
6037 return "menuMode.Analysis Mode";
6039 return "menuMode.Analyze File";
6040 case TwoMachinesPlay:
6041 return "menuMode.Two Machines";
6043 return "menuMode.Edit Game";
6044 case PlayFromGameFile:
6045 return "menuFile.Load Game";
6047 return "menuMode.Edit Position";
6049 return "menuMode.Training";
6050 case IcsPlayingWhite:
6051 case IcsPlayingBlack:
6055 return "menuMode.ICS Client";
6062 void ModeHighlight()
6065 static int oldPausing = FALSE;
6066 static GameMode oldmode = (GameMode) -1;
6069 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6071 if (pausing != oldPausing) {
6072 oldPausing = pausing;
6074 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6076 XtSetArg(args[0], XtNleftBitmap, None);
6078 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6081 if (appData.showButtonBar) {
6082 /* Always toggle, don't set. Previous code messes up when
6083 invoked while the button is pressed, as releasing it
6084 toggles the state again. */
6087 XtSetArg(args[0], XtNbackground, &oldbg);
6088 XtSetArg(args[1], XtNforeground, &oldfg);
6089 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6091 XtSetArg(args[0], XtNbackground, oldfg);
6092 XtSetArg(args[1], XtNforeground, oldbg);
6094 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6098 wname = ModeToWidgetName(oldmode);
6099 if (wname != NULL) {
6100 XtSetArg(args[0], XtNleftBitmap, None);
6101 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6103 wname = ModeToWidgetName(gameMode);
6104 if (wname != NULL) {
6105 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6106 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6110 /* Maybe all the enables should be handled here, not just this one */
6111 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6112 gameMode == Training || gameMode == PlayFromGameFile);
6117 * Button/menu procedures
6119 void ResetProc(w, event, prms, nprms)
6128 int LoadGamePopUp(f, gameNumber, title)
6133 cmailMsgLoaded = FALSE;
6134 if (gameNumber == 0) {
6135 int error = GameListBuild(f);
6137 DisplayError(_("Cannot build game list"), error);
6138 } else if (!ListEmpty(&gameList) &&
6139 ((ListGame *) gameList.tailPred)->number > 1) {
6140 GameListPopUp(f, title);
6146 return LoadGame(f, gameNumber, title, FALSE);
6149 void LoadGameProc(w, event, prms, nprms)
6155 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6158 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6161 void LoadNextGameProc(w, event, prms, nprms)
6170 void LoadPrevGameProc(w, event, prms, nprms)
6179 void ReloadGameProc(w, event, prms, nprms)
6188 void LoadNextPositionProc(w, event, prms, nprms)
6197 void LoadPrevPositionProc(w, event, prms, nprms)
6206 void ReloadPositionProc(w, event, prms, nprms)
6215 void LoadPositionProc(w, event, prms, nprms)
6221 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6224 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6227 void SaveGameProc(w, event, prms, nprms)
6233 FileNamePopUp(_("Save game file name?"),
6234 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6238 void SavePositionProc(w, event, prms, nprms)
6244 FileNamePopUp(_("Save position file name?"),
6245 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6249 void ReloadCmailMsgProc(w, event, prms, nprms)
6255 ReloadCmailMsgEvent(FALSE);
6258 void MailMoveProc(w, event, prms, nprms)
6267 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6268 static char *selected_fen_position=NULL;
6271 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6272 Atom *type_return, XtPointer *value_return,
6273 unsigned long *length_return, int *format_return)
6275 char *selection_tmp;
6277 if (!selected_fen_position) return False; /* should never happen */
6278 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
6279 /* note: since no XtSelectionDoneProc was registered, Xt will
6280 * automatically call XtFree on the value returned. So have to
6281 * make a copy of it allocated with XtMalloc */
6282 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6283 strcpy(selection_tmp, selected_fen_position);
6285 *value_return=selection_tmp;
6286 *length_return=strlen(selection_tmp);
6287 *type_return=*target;
6288 *format_return = 8; /* bits per byte */
6290 } else if (*target == XA_TARGETS(xDisplay)) {
6291 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
6292 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
6293 targets_tmp[1] = XA_STRING;
6294 *value_return = targets_tmp;
6295 *type_return = XA_ATOM;
6297 *format_return = 8 * sizeof(Atom);
6298 if (*format_return > 32) {
6299 *length_return *= *format_return / 32;
6300 *format_return = 32;
6308 /* note: when called from menu all parameters are NULL, so no clue what the
6309 * Widget which was clicked on was, or what the click event was
6311 void CopyPositionProc(w, event, prms, nprms)
6318 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
6319 * have a notion of a position that is selected but not copied.
6320 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
6322 if (selected_fen_position) free(selected_fen_position);
6323 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6324 if (!selected_fen_position) return;
6325 XtOwnSelection(menuBarWidget, XA_PRIMARY,
6327 SendPositionSelection,
6328 NULL/* lose_ownership_proc */ ,
6329 NULL/* transfer_done_proc */);
6330 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
6332 SendPositionSelection,
6333 NULL/* lose_ownership_proc */ ,
6334 NULL/* transfer_done_proc */);
6337 /* function called when the data to Paste is ready */
6339 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6340 Atom *type, XtPointer value, unsigned long *len, int *format)
6343 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6344 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6345 EditPositionPasteFEN(fenstr);
6349 /* called when Paste Position button is pressed,
6350 * all parameters will be NULL */
6351 void PastePositionProc(w, event, prms, nprms)
6357 XtGetSelectionValue(menuBarWidget,
6358 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
6359 /* (XtSelectionCallbackProc) */ PastePositionCB,
6360 NULL, /* client_data passed to PastePositionCB */
6362 /* better to use the time field from the event that triggered the
6363 * call to this function, but that isn't trivial to get
6371 SendGameSelection(Widget w, Atom *selection, Atom *target,
6372 Atom *type_return, XtPointer *value_return,
6373 unsigned long *length_return, int *format_return)
6375 char *selection_tmp;
6377 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
6378 FILE* f = fopen(gameCopyFilename, "r");
6381 if (f == NULL) return False;
6385 selection_tmp = XtMalloc(len + 1);
6386 count = fread(selection_tmp, 1, len, f);
6388 XtFree(selection_tmp);
6391 selection_tmp[len] = NULLCHAR;
6392 *value_return = selection_tmp;
6393 *length_return = len;
6394 *type_return = *target;
6395 *format_return = 8; /* bits per byte */
6397 } else if (*target == XA_TARGETS(xDisplay)) {
6398 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
6399 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
6400 targets_tmp[1] = XA_STRING;
6401 *value_return = targets_tmp;
6402 *type_return = XA_ATOM;
6404 *format_return = 8 * sizeof(Atom);
6405 if (*format_return > 32) {
6406 *length_return *= *format_return / 32;
6407 *format_return = 32;
6415 /* note: when called from menu all parameters are NULL, so no clue what the
6416 * Widget which was clicked on was, or what the click event was
6418 void CopyGameProc(w, event, prms, nprms)
6426 ret = SaveGameToFile(gameCopyFilename, FALSE);
6430 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
6431 * have a notion of a game that is selected but not copied.
6432 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
6434 XtOwnSelection(menuBarWidget, XA_PRIMARY,
6437 NULL/* lose_ownership_proc */ ,
6438 NULL/* transfer_done_proc */);
6439 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
6442 NULL/* lose_ownership_proc */ ,
6443 NULL/* transfer_done_proc */);
6446 /* function called when the data to Paste is ready */
6448 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6449 Atom *type, XtPointer value, unsigned long *len, int *format)
6452 if (value == NULL || *len == 0) {
6453 return; /* nothing had been selected to copy */
6455 f = fopen(gamePasteFilename, "w");
6457 DisplayError(_("Can't open temp file"), errno);
6460 fwrite(value, 1, *len, f);
6463 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6466 /* called when Paste Game button is pressed,
6467 * all parameters will be NULL */
6468 void PasteGameProc(w, event, prms, nprms)
6474 XtGetSelectionValue(menuBarWidget,
6475 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
6476 /* (XtSelectionCallbackProc) */ PasteGameCB,
6477 NULL, /* client_data passed to PasteGameCB */
6479 /* better to use the time field from the event that triggered the
6480 * call to this function, but that isn't trivial to get
6490 SaveGameProc(NULL, NULL, NULL, NULL);
6494 void QuitProc(w, event, prms, nprms)
6503 void PauseProc(w, event, prms, nprms)
6513 void MachineBlackProc(w, event, prms, nprms)
6519 MachineBlackEvent();
6522 void MachineWhiteProc(w, event, prms, nprms)
6528 MachineWhiteEvent();
6531 void AnalyzeModeProc(w, event, prms, nprms)
6539 if (!first.analysisSupport) {
6540 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6541 DisplayError(buf, 0);
6544 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6545 if (appData.icsActive) {
6546 if (gameMode != IcsObserving) {
6547 sprintf(buf,_("You are not observing a game"));
6548 DisplayError(buf, 0);
6550 if (appData.icsEngineAnalyze) {
6551 if (appData.debugMode)
6552 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6558 /* if enable, use want disable icsEngineAnalyze */
6559 if (appData.icsEngineAnalyze) {
6564 appData.icsEngineAnalyze = TRUE;
6565 if (appData.debugMode)
6566 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6568 if (!appData.showThinking)
6569 ShowThinkingProc(w,event,prms,nprms);
6574 void AnalyzeFileProc(w, event, prms, nprms)
6580 if (!first.analysisSupport) {
6582 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6583 DisplayError(buf, 0);
6588 if (!appData.showThinking)
6589 ShowThinkingProc(w,event,prms,nprms);
6592 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6593 AnalysisPeriodicEvent(1);
6596 void TwoMachinesProc(w, event, prms, nprms)
6605 void IcsClientProc(w, event, prms, nprms)
6614 void EditGameProc(w, event, prms, nprms)
6623 void EditPositionProc(w, event, prms, nprms)
6629 EditPositionEvent();
6632 void TrainingProc(w, event, prms, nprms)
6641 void EditCommentProc(w, event, prms, nprms)
6648 EditCommentPopDown();
6654 void IcsInputBoxProc(w, event, prms, nprms)
6660 if (ICSInputBoxUp) {
6661 ICSInputBoxPopDown();
6667 void AcceptProc(w, event, prms, nprms)
6676 void DeclineProc(w, event, prms, nprms)
6685 void RematchProc(w, event, prms, nprms)
6694 void CallFlagProc(w, event, prms, nprms)
6703 void DrawProc(w, event, prms, nprms)
6712 void AbortProc(w, event, prms, nprms)
6721 void AdjournProc(w, event, prms, nprms)
6730 void ResignProc(w, event, prms, nprms)
6739 void AdjuWhiteProc(w, event, prms, nprms)
6745 UserAdjudicationEvent(+1);
6748 void AdjuBlackProc(w, event, prms, nprms)
6754 UserAdjudicationEvent(-1);
6757 void AdjuDrawProc(w, event, prms, nprms)
6763 UserAdjudicationEvent(0);
6766 void EnterKeyProc(w, event, prms, nprms)
6772 if (ICSInputBoxUp == True)
6776 void StopObservingProc(w, event, prms, nprms)
6782 StopObservingEvent();
6785 void StopExaminingProc(w, event, prms, nprms)
6791 StopExaminingEvent();
6795 void ForwardProc(w, event, prms, nprms)
6805 void BackwardProc(w, event, prms, nprms)
6814 void ToStartProc(w, event, prms, nprms)
6823 void ToEndProc(w, event, prms, nprms)
6832 void RevertProc(w, event, prms, nprms)
6841 void TruncateGameProc(w, event, prms, nprms)
6847 TruncateGameEvent();
6849 void RetractMoveProc(w, event, prms, nprms)
6858 void MoveNowProc(w, event, prms, nprms)
6868 void AlwaysQueenProc(w, event, prms, nprms)
6876 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6878 if (appData.alwaysPromoteToQueen) {
6879 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6881 XtSetArg(args[0], XtNleftBitmap, None);
6883 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6887 void AnimateDraggingProc(w, event, prms, nprms)
6895 appData.animateDragging = !appData.animateDragging;
6897 if (appData.animateDragging) {
6898 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6901 XtSetArg(args[0], XtNleftBitmap, None);
6903 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6907 void AnimateMovingProc(w, event, prms, nprms)
6915 appData.animate = !appData.animate;
6917 if (appData.animate) {
6918 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6921 XtSetArg(args[0], XtNleftBitmap, None);
6923 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6927 void AutocommProc(w, event, prms, nprms)
6935 appData.autoComment = !appData.autoComment;
6937 if (appData.autoComment) {
6938 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6940 XtSetArg(args[0], XtNleftBitmap, None);
6942 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6947 void AutoflagProc(w, event, prms, nprms)
6955 appData.autoCallFlag = !appData.autoCallFlag;
6957 if (appData.autoCallFlag) {
6958 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6960 XtSetArg(args[0], XtNleftBitmap, None);
6962 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6966 void AutoflipProc(w, event, prms, nprms)
6974 appData.autoFlipView = !appData.autoFlipView;
6976 if (appData.autoFlipView) {
6977 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6979 XtSetArg(args[0], XtNleftBitmap, None);
6981 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6985 void AutobsProc(w, event, prms, nprms)
6993 appData.autoObserve = !appData.autoObserve;
6995 if (appData.autoObserve) {
6996 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6998 XtSetArg(args[0], XtNleftBitmap, None);
7000 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7004 void AutoraiseProc(w, event, prms, nprms)
7012 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7014 if (appData.autoRaiseBoard) {
7015 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7017 XtSetArg(args[0], XtNleftBitmap, None);
7019 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7023 void AutosaveProc(w, event, prms, nprms)
7031 appData.autoSaveGames = !appData.autoSaveGames;
7033 if (appData.autoSaveGames) {
7034 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7036 XtSetArg(args[0], XtNleftBitmap, None);
7038 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7042 void BlindfoldProc(w, event, prms, nprms)
7050 appData.blindfold = !appData.blindfold;
7052 if (appData.blindfold) {
7053 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7055 XtSetArg(args[0], XtNleftBitmap, None);
7057 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7060 DrawPosition(True, NULL);
7063 void TestLegalityProc(w, event, prms, nprms)
7071 appData.testLegality = !appData.testLegality;
7073 if (appData.testLegality) {
7074 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7076 XtSetArg(args[0], XtNleftBitmap, None);
7078 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7083 void FlashMovesProc(w, event, prms, nprms)
7091 if (appData.flashCount == 0) {
7092 appData.flashCount = 3;
7094 appData.flashCount = -appData.flashCount;
7097 if (appData.flashCount > 0) {
7098 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7100 XtSetArg(args[0], XtNleftBitmap, None);
7102 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7106 void FlipViewProc(w, event, prms, nprms)
7112 flipView = !flipView;
7113 DrawPosition(True, NULL);
7116 void GetMoveListProc(w, event, prms, nprms)
7124 appData.getMoveList = !appData.getMoveList;
7126 if (appData.getMoveList) {
7127 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7130 XtSetArg(args[0], XtNleftBitmap, None);
7132 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7137 void HighlightDraggingProc(w, event, prms, nprms)
7145 appData.highlightDragging = !appData.highlightDragging;
7147 if (appData.highlightDragging) {
7148 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7150 XtSetArg(args[0], XtNleftBitmap, None);
7152 XtSetValues(XtNameToWidget(menuBarWidget,
7153 "menuOptions.Highlight Dragging"), args, 1);
7157 void HighlightLastMoveProc(w, event, prms, nprms)
7165 appData.highlightLastMove = !appData.highlightLastMove;
7167 if (appData.highlightLastMove) {
7168 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7170 XtSetArg(args[0], XtNleftBitmap, None);
7172 XtSetValues(XtNameToWidget(menuBarWidget,
7173 "menuOptions.Highlight Last Move"), args, 1);
7176 void IcsAlarmProc(w, event, prms, nprms)
7184 appData.icsAlarm = !appData.icsAlarm;
7186 if (appData.icsAlarm) {
7187 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7189 XtSetArg(args[0], XtNleftBitmap, None);
7191 XtSetValues(XtNameToWidget(menuBarWidget,
7192 "menuOptions.ICS Alarm"), args, 1);
7195 void MoveSoundProc(w, event, prms, nprms)
7203 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7205 if (appData.ringBellAfterMoves) {
7206 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7208 XtSetArg(args[0], XtNleftBitmap, None);
7210 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7215 void OldSaveStyleProc(w, event, prms, nprms)
7223 appData.oldSaveStyle = !appData.oldSaveStyle;
7225 if (appData.oldSaveStyle) {
7226 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7228 XtSetArg(args[0], XtNleftBitmap, None);
7230 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7234 void PeriodicUpdatesProc(w, event, prms, nprms)
7242 PeriodicUpdatesEvent(!appData.periodicUpdates);
7244 if (appData.periodicUpdates) {
7245 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7247 XtSetArg(args[0], XtNleftBitmap, None);
7249 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7253 void PonderNextMoveProc(w, event, prms, nprms)
7261 PonderNextMoveEvent(!appData.ponderNextMove);
7263 if (appData.ponderNextMove) {
7264 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7266 XtSetArg(args[0], XtNleftBitmap, None);
7268 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7272 void PopupExitMessageProc(w, event, prms, nprms)
7280 appData.popupExitMessage = !appData.popupExitMessage;
7282 if (appData.popupExitMessage) {
7283 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7285 XtSetArg(args[0], XtNleftBitmap, None);
7287 XtSetValues(XtNameToWidget(menuBarWidget,
7288 "menuOptions.Popup Exit Message"), args, 1);
7291 void PopupMoveErrorsProc(w, event, prms, nprms)
7299 appData.popupMoveErrors = !appData.popupMoveErrors;
7301 if (appData.popupMoveErrors) {
7302 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7304 XtSetArg(args[0], XtNleftBitmap, None);
7306 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7310 void PremoveProc(w, event, prms, nprms)
7318 appData.premove = !appData.premove;
7320 if (appData.premove) {
7321 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7323 XtSetArg(args[0], XtNleftBitmap, None);
7325 XtSetValues(XtNameToWidget(menuBarWidget,
7326 "menuOptions.Premove"), args, 1);
7329 void QuietPlayProc(w, event, prms, nprms)
7337 appData.quietPlay = !appData.quietPlay;
7339 if (appData.quietPlay) {
7340 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7342 XtSetArg(args[0], XtNleftBitmap, None);
7344 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7348 void ShowCoordsProc(w, event, prms, nprms)
7356 appData.showCoords = !appData.showCoords;
7358 if (appData.showCoords) {
7359 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7361 XtSetArg(args[0], XtNleftBitmap, None);
7363 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7366 DrawPosition(True, NULL);
7369 void ShowThinkingProc(w, event, prms, nprms)
7375 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7376 ShowThinkingEvent();
7379 void HideThinkingProc(w, event, prms, nprms)
7387 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7388 ShowThinkingEvent();
7390 if (appData.hideThinkingFromHuman) {
7391 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7393 XtSetArg(args[0], XtNleftBitmap, None);
7395 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7399 void InfoProc(w, event, prms, nprms)
7406 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7411 void ManProc(w, event, prms, nprms)
7419 if (nprms && *nprms > 0)
7423 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7427 void HintProc(w, event, prms, nprms)
7436 void BookProc(w, event, prms, nprms)
7445 void AboutProc(w, event, prms, nprms)
7453 char *zippy = " (with Zippy code)";
7457 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7458 programVersion, zippy,
7459 "Copyright 1991 Digital Equipment Corporation",
7460 "Enhancements Copyright 1992-2009 Free Software Foundation",
7461 "Enhancements Copyright 2005 Alessandro Scotti",
7462 PACKAGE, " is free software and carries NO WARRANTY;",
7463 "see the file COPYING for more information.");
7464 ErrorPopUp(_("About XBoard"), buf, FALSE);
7467 void DebugProc(w, event, prms, nprms)
7473 appData.debugMode = !appData.debugMode;
7476 void AboutGameProc(w, event, prms, nprms)
7485 void NothingProc(w, event, prms, nprms)
7494 void Iconify(w, event, prms, nprms)
7503 XtSetArg(args[0], XtNiconic, True);
7504 XtSetValues(shellWidget, args, 1);
7507 void DisplayMessage(message, extMessage)
7508 char *message, *extMessage;
7510 /* display a message in the message widget */
7519 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7524 message = extMessage;
7528 /* need to test if messageWidget already exists, since this function
7529 can also be called during the startup, if for example a Xresource
7530 is not set up correctly */
7533 XtSetArg(arg, XtNlabel, message);
7534 XtSetValues(messageWidget, &arg, 1);
7540 void DisplayTitle(text)
7545 char title[MSG_SIZ];
7548 if (text == NULL) text = "";
7550 if (appData.titleInWindow) {
7552 XtSetArg(args[i], XtNlabel, text); i++;
7553 XtSetValues(titleWidget, args, i);
7556 if (*text != NULLCHAR) {
7558 strcpy(title, text);
7559 } else if (appData.icsActive) {
7560 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7561 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7562 } else if (appData.cmailGameName[0] != NULLCHAR) {
7563 snprintf(icon, sizeof(icon), "%s", "CMail");
7564 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7566 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7567 } else if (gameInfo.variant == VariantGothic) {
7568 strcpy(icon, programName);
7569 strcpy(title, GOTHIC);
7572 } else if (gameInfo.variant == VariantFalcon) {
7573 strcpy(icon, programName);
7574 strcpy(title, FALCON);
7576 } else if (appData.noChessProgram) {
7577 strcpy(icon, programName);
7578 strcpy(title, programName);
7580 strcpy(icon, first.tidy);
7581 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7584 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7585 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7586 XtSetValues(shellWidget, args, i);
7590 void DisplayError(message, error)
7597 if (appData.debugMode || appData.matchMode) {
7598 fprintf(stderr, "%s: %s\n", programName, message);
7601 if (appData.debugMode || appData.matchMode) {
7602 fprintf(stderr, "%s: %s: %s\n",
7603 programName, message, strerror(error));
7605 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7608 ErrorPopUp(_("Error"), message, FALSE);
7612 void DisplayMoveError(message)
7617 DrawPosition(FALSE, NULL);
7618 if (appData.debugMode || appData.matchMode) {
7619 fprintf(stderr, "%s: %s\n", programName, message);
7621 if (appData.popupMoveErrors) {
7622 ErrorPopUp(_("Error"), message, FALSE);
7624 DisplayMessage(message, "");
7629 void DisplayFatalError(message, error, status)
7635 errorExitStatus = status;
7637 fprintf(stderr, "%s: %s\n", programName, message);
7639 fprintf(stderr, "%s: %s: %s\n",
7640 programName, message, strerror(error));
7641 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7644 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7645 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7651 void DisplayInformation(message)
7655 ErrorPopUp(_("Information"), message, TRUE);
7658 void DisplayNote(message)
7662 ErrorPopUp(_("Note"), message, FALSE);
7666 NullXErrorCheck(dpy, error_event)
7668 XErrorEvent *error_event;
7673 void DisplayIcsInteractionTitle(message)
7676 if (oldICSInteractionTitle == NULL) {
7677 /* Magic to find the old window title, adapted from vim */
7678 char *wina = getenv("WINDOWID");
7680 Window win = (Window) atoi(wina);
7681 Window root, parent, *children;
7682 unsigned int nchildren;
7683 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7685 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7686 if (!XQueryTree(xDisplay, win, &root, &parent,
7687 &children, &nchildren)) break;
7688 if (children) XFree((void *)children);
7689 if (parent == root || parent == 0) break;
7692 XSetErrorHandler(oldHandler);
7694 if (oldICSInteractionTitle == NULL) {
7695 oldICSInteractionTitle = "xterm";
7698 printf("\033]0;%s\007", message);
7702 char pendingReplyPrefix[MSG_SIZ];
7703 ProcRef pendingReplyPR;
7705 void AskQuestionProc(w, event, prms, nprms)
7712 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7716 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7719 void AskQuestionPopDown()
7721 if (!askQuestionUp) return;
7722 XtPopdown(askQuestionShell);
7723 XtDestroyWidget(askQuestionShell);
7724 askQuestionUp = False;
7727 void AskQuestionReplyAction(w, event, prms, nprms)
7737 reply = XawDialogGetValueString(w = XtParent(w));
7738 strcpy(buf, pendingReplyPrefix);
7739 if (*buf) strcat(buf, " ");
7742 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7743 AskQuestionPopDown();
7745 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7748 void AskQuestionCallback(w, client_data, call_data)
7750 XtPointer client_data, call_data;
7755 XtSetArg(args[0], XtNlabel, &name);
7756 XtGetValues(w, args, 1);
7758 if (strcmp(name, _("cancel")) == 0) {
7759 AskQuestionPopDown();
7761 AskQuestionReplyAction(w, NULL, NULL, NULL);
7765 void AskQuestion(title, question, replyPrefix, pr)
7766 char *title, *question, *replyPrefix;
7770 Widget popup, layout, dialog, edit;
7776 strcpy(pendingReplyPrefix, replyPrefix);
7777 pendingReplyPR = pr;
7780 XtSetArg(args[i], XtNresizable, True); i++;
7781 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7782 askQuestionShell = popup =
7783 XtCreatePopupShell(title, transientShellWidgetClass,
7784 shellWidget, args, i);
7787 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7788 layoutArgs, XtNumber(layoutArgs));
7791 XtSetArg(args[i], XtNlabel, question); i++;
7792 XtSetArg(args[i], XtNvalue, ""); i++;
7793 XtSetArg(args[i], XtNborderWidth, 0); i++;
7794 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7797 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7798 (XtPointer) dialog);
7799 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7800 (XtPointer) dialog);
7802 XtRealizeWidget(popup);
7803 CatchDeleteWindow(popup, "AskQuestionPopDown");
7805 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7806 &x, &y, &win_x, &win_y, &mask);
7808 XtSetArg(args[0], XtNx, x - 10);
7809 XtSetArg(args[1], XtNy, y - 30);
7810 XtSetValues(popup, args, 2);
7812 XtPopup(popup, XtGrabExclusive);
7813 askQuestionUp = True;
7815 edit = XtNameToWidget(dialog, "*value");
7816 XtSetKeyboardFocus(popup, edit);
7824 if (*name == NULLCHAR) {
7826 } else if (strcmp(name, "$") == 0) {
7827 putc(BELLCHAR, stderr);
7830 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7838 PlaySound(appData.soundMove);
7844 PlaySound(appData.soundIcsWin);
7850 PlaySound(appData.soundIcsLoss);
7856 PlaySound(appData.soundIcsDraw);
7860 PlayIcsUnfinishedSound()
7862 PlaySound(appData.soundIcsUnfinished);
7868 PlaySound(appData.soundIcsAlarm);
7874 system("stty echo");
7880 system("stty -echo");
7884 Colorize(cc, continuation)
7889 int count, outCount, error;
7891 if (textColors[(int)cc].bg > 0) {
7892 if (textColors[(int)cc].fg > 0) {
7893 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7894 textColors[(int)cc].fg, textColors[(int)cc].bg);
7896 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7897 textColors[(int)cc].bg);
7900 if (textColors[(int)cc].fg > 0) {
7901 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7902 textColors[(int)cc].fg);
7904 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7907 count = strlen(buf);
7908 outCount = OutputToProcess(NoProc, buf, count, &error);
7909 if (outCount < count) {
7910 DisplayFatalError(_("Error writing to display"), error, 1);
7913 if (continuation) return;
7916 PlaySound(appData.soundShout);
7919 PlaySound(appData.soundSShout);
7922 PlaySound(appData.soundChannel1);
7925 PlaySound(appData.soundChannel);
7928 PlaySound(appData.soundKibitz);
7931 PlaySound(appData.soundTell);
7933 case ColorChallenge:
7934 PlaySound(appData.soundChallenge);
7937 PlaySound(appData.soundRequest);
7940 PlaySound(appData.soundSeek);
7951 return getpwuid(getuid())->pw_name;
7954 static char *ExpandPathName(path)
7957 static char static_buf[2000];
7958 char *d, *s, buf[2000];
7964 while (*s && isspace(*s))
7973 if (*(s+1) == '/') {
7974 strcpy(d, getpwuid(getuid())->pw_dir);
7979 *strchr(buf, '/') = 0;
7980 pwd = getpwnam(buf);
7983 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7987 strcpy(d, pwd->pw_dir);
7988 strcat(d, strchr(s+1, '/'));
7999 static char host_name[MSG_SIZ];
8001 #if HAVE_GETHOSTNAME
8002 gethostname(host_name, MSG_SIZ);
8004 #else /* not HAVE_GETHOSTNAME */
8005 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8006 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8008 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8010 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8011 #endif /* not HAVE_GETHOSTNAME */
8014 XtIntervalId delayedEventTimerXID = 0;
8015 DelayedEventCallback delayedEventCallback = 0;
8020 delayedEventTimerXID = 0;
8021 delayedEventCallback();
8025 ScheduleDelayedEvent(cb, millisec)
8026 DelayedEventCallback cb; long millisec;
8028 if(delayedEventTimerXID && delayedEventCallback == cb)
8029 // [HGM] alive: replace, rather than add or flush identical event
8030 XtRemoveTimeOut(delayedEventTimerXID);
8031 delayedEventCallback = cb;
8032 delayedEventTimerXID =
8033 XtAppAddTimeOut(appContext, millisec,
8034 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8037 DelayedEventCallback
8040 if (delayedEventTimerXID) {
8041 return delayedEventCallback;
8048 CancelDelayedEvent()
8050 if (delayedEventTimerXID) {
8051 XtRemoveTimeOut(delayedEventTimerXID);
8052 delayedEventTimerXID = 0;
8056 XtIntervalId loadGameTimerXID = 0;
8058 int LoadGameTimerRunning()
8060 return loadGameTimerXID != 0;
8063 int StopLoadGameTimer()
8065 if (loadGameTimerXID != 0) {
8066 XtRemoveTimeOut(loadGameTimerXID);
8067 loadGameTimerXID = 0;
8075 LoadGameTimerCallback(arg, id)
8079 loadGameTimerXID = 0;
8084 StartLoadGameTimer(millisec)
8088 XtAppAddTimeOut(appContext, millisec,
8089 (XtTimerCallbackProc) LoadGameTimerCallback,
8093 XtIntervalId analysisClockXID = 0;
8096 AnalysisClockCallback(arg, id)
8100 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8101 || appData.icsEngineAnalyze) { // [DM]
8102 AnalysisPeriodicEvent(0);
8103 StartAnalysisClock();
8108 StartAnalysisClock()
8111 XtAppAddTimeOut(appContext, 2000,
8112 (XtTimerCallbackProc) AnalysisClockCallback,
8116 XtIntervalId clockTimerXID = 0;
8118 int ClockTimerRunning()
8120 return clockTimerXID != 0;
8123 int StopClockTimer()
8125 if (clockTimerXID != 0) {
8126 XtRemoveTimeOut(clockTimerXID);
8135 ClockTimerCallback(arg, id)
8144 StartClockTimer(millisec)
8148 XtAppAddTimeOut(appContext, millisec,
8149 (XtTimerCallbackProc) ClockTimerCallback,
8154 DisplayTimerLabel(w, color, timer, highlight)
8163 /* check for low time warning */
8164 Pixel foregroundOrWarningColor = timerForegroundPixel;
8167 appData.lowTimeWarning &&
8168 (timer / 1000) < appData.icsAlarmTime)
8169 foregroundOrWarningColor = lowTimeWarningColor;
8171 if (appData.clockMode) {
8172 sprintf(buf, "%s: %s", color, TimeString(timer));
8173 XtSetArg(args[0], XtNlabel, buf);
8175 sprintf(buf, "%s ", color);
8176 XtSetArg(args[0], XtNlabel, buf);
8181 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8182 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8184 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8185 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8188 XtSetValues(w, args, 3);
8192 DisplayWhiteClock(timeRemaining, highlight)
8198 if(appData.noGUI) return;
8199 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8200 if (highlight && iconPixmap == bIconPixmap) {
8201 iconPixmap = wIconPixmap;
8202 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8203 XtSetValues(shellWidget, args, 1);
8208 DisplayBlackClock(timeRemaining, highlight)
8214 if(appData.noGUI) return;
8215 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8216 if (highlight && iconPixmap == wIconPixmap) {
8217 iconPixmap = bIconPixmap;
8218 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8219 XtSetValues(shellWidget, args, 1);
8237 int StartChildProcess(cmdLine, dir, pr)
8244 int to_prog[2], from_prog[2];
8248 if (appData.debugMode) {
8249 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8252 /* We do NOT feed the cmdLine to the shell; we just
8253 parse it into blank-separated arguments in the
8254 most simple-minded way possible.
8257 strcpy(buf, cmdLine);
8262 if (p == NULL) break;
8267 SetUpChildIO(to_prog, from_prog);
8269 if ((pid = fork()) == 0) {
8271 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8272 close(to_prog[1]); // first close the unused pipe ends
8273 close(from_prog[0]);
8274 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8275 dup2(from_prog[1], 1);
8276 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8277 close(from_prog[1]); // and closing again loses one of the pipes!
8278 if(fileno(stderr) >= 2) // better safe than sorry...
8279 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8281 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8286 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8288 execvp(argv[0], argv);
8290 /* If we get here, exec failed */
8295 /* Parent process */
8297 close(from_prog[1]);
8299 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8302 cp->fdFrom = from_prog[0];
8303 cp->fdTo = to_prog[1];
8308 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8309 static RETSIGTYPE AlarmCallBack(int n)
8315 DestroyChildProcess(pr, signalType)
8319 ChildProc *cp = (ChildProc *) pr;
8321 if (cp->kind != CPReal) return;
8323 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8324 signal(SIGALRM, AlarmCallBack);
8326 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8327 kill(cp->pid, SIGKILL); // kill it forcefully
8328 wait((int *) 0); // and wait again
8332 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8334 /* Process is exiting either because of the kill or because of
8335 a quit command sent by the backend; either way, wait for it to die.
8344 InterruptChildProcess(pr)
8347 ChildProc *cp = (ChildProc *) pr;
8349 if (cp->kind != CPReal) return;
8350 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8353 int OpenTelnet(host, port, pr)
8358 char cmdLine[MSG_SIZ];
8360 if (port[0] == NULLCHAR) {
8361 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8363 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8365 return StartChildProcess(cmdLine, "", pr);
8368 int OpenTCP(host, port, pr)
8374 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8375 #else /* !OMIT_SOCKETS */
8377 struct sockaddr_in sa;
8379 unsigned short uport;
8382 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8386 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8387 sa.sin_family = AF_INET;
8388 sa.sin_addr.s_addr = INADDR_ANY;
8389 uport = (unsigned short) 0;
8390 sa.sin_port = htons(uport);
8391 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8395 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8396 if (!(hp = gethostbyname(host))) {
8398 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8399 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8400 hp->h_addrtype = AF_INET;
8402 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8403 hp->h_addr_list[0] = (char *) malloc(4);
8404 hp->h_addr_list[0][0] = b0;
8405 hp->h_addr_list[0][1] = b1;
8406 hp->h_addr_list[0][2] = b2;
8407 hp->h_addr_list[0][3] = b3;
8412 sa.sin_family = hp->h_addrtype;
8413 uport = (unsigned short) atoi(port);
8414 sa.sin_port = htons(uport);
8415 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8417 if (connect(s, (struct sockaddr *) &sa,
8418 sizeof(struct sockaddr_in)) < 0) {
8422 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8429 #endif /* !OMIT_SOCKETS */
8434 int OpenCommPort(name, pr)
8441 fd = open(name, 2, 0);
8442 if (fd < 0) return errno;
8444 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8454 int OpenLoopback(pr)
8460 SetUpChildIO(to, from);
8462 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8465 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8472 int OpenRcmd(host, user, cmd, pr)
8473 char *host, *user, *cmd;
8476 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8480 #define INPUT_SOURCE_BUF_SIZE 8192
8489 char buf[INPUT_SOURCE_BUF_SIZE];
8494 DoInputCallback(closure, source, xid)
8499 InputSource *is = (InputSource *) closure;
8504 if (is->lineByLine) {
8505 count = read(is->fd, is->unused,
8506 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8508 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8511 is->unused += count;
8513 while (p < is->unused) {
8514 q = memchr(p, '\n', is->unused - p);
8515 if (q == NULL) break;
8517 (is->func)(is, is->closure, p, q - p, 0);
8521 while (p < is->unused) {
8526 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8531 (is->func)(is, is->closure, is->buf, count, error);
8535 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8542 ChildProc *cp = (ChildProc *) pr;
8544 is = (InputSource *) calloc(1, sizeof(InputSource));
8545 is->lineByLine = lineByLine;
8549 is->fd = fileno(stdin);
8551 is->kind = cp->kind;
8552 is->fd = cp->fdFrom;
8555 is->unused = is->buf;
8558 is->xid = XtAppAddInput(appContext, is->fd,
8559 (XtPointer) (XtInputReadMask),
8560 (XtInputCallbackProc) DoInputCallback,
8562 is->closure = closure;
8563 return (InputSourceRef) is;
8567 RemoveInputSource(isr)
8570 InputSource *is = (InputSource *) isr;
8572 if (is->xid == 0) return;
8573 XtRemoveInput(is->xid);
8577 int OutputToProcess(pr, message, count, outError)
8583 static int line = 0;
8584 ChildProc *cp = (ChildProc *) pr;
8589 if (appData.noJoin || !appData.useInternalWrap)
8590 outCount = fwrite(message, 1, count, stdout);
8593 int width = get_term_width();
8594 int len = wrap(NULL, message, count, width, &line);
8595 char *msg = malloc(len);
8599 outCount = fwrite(message, 1, count, stdout);
8602 dbgchk = wrap(msg, message, count, width, &line);
8603 if (dbgchk != len && appData.debugMode)
8604 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
8605 outCount = fwrite(msg, 1, dbgchk, stdout);
8611 outCount = write(cp->fdTo, message, count);
8621 /* Output message to process, with "ms" milliseconds of delay
8622 between each character. This is needed when sending the logon
8623 script to ICC, which for some reason doesn't like the
8624 instantaneous send. */
8625 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8632 ChildProc *cp = (ChildProc *) pr;
8637 r = write(cp->fdTo, message++, 1);
8650 /**** Animation code by Hugh Fisher, DCS, ANU.
8652 Known problem: if a window overlapping the board is
8653 moved away while a piece is being animated underneath,
8654 the newly exposed area won't be updated properly.
8655 I can live with this.
8657 Known problem: if you look carefully at the animation
8658 of pieces in mono mode, they are being drawn as solid
8659 shapes without interior detail while moving. Fixing
8660 this would be a major complication for minimal return.
8663 /* Masks for XPM pieces. Black and white pieces can have
8664 different shapes, but in the interest of retaining my
8665 sanity pieces must have the same outline on both light
8666 and dark squares, and all pieces must use the same
8667 background square colors/images. */
8669 static int xpmDone = 0;
8672 CreateAnimMasks (pieceDepth)
8679 unsigned long plane;
8682 /* Need a bitmap just to get a GC with right depth */
8683 buf = XCreatePixmap(xDisplay, xBoardWindow,
8685 values.foreground = 1;
8686 values.background = 0;
8687 /* Don't use XtGetGC, not read only */
8688 maskGC = XCreateGC(xDisplay, buf,
8689 GCForeground | GCBackground, &values);
8690 XFreePixmap(xDisplay, buf);
8692 buf = XCreatePixmap(xDisplay, xBoardWindow,
8693 squareSize, squareSize, pieceDepth);
8694 values.foreground = XBlackPixel(xDisplay, xScreen);
8695 values.background = XWhitePixel(xDisplay, xScreen);
8696 bufGC = XCreateGC(xDisplay, buf,
8697 GCForeground | GCBackground, &values);
8699 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8700 /* Begin with empty mask */
8701 if(!xpmDone) // [HGM] pieces: keep using existing
8702 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8703 squareSize, squareSize, 1);
8704 XSetFunction(xDisplay, maskGC, GXclear);
8705 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8706 0, 0, squareSize, squareSize);
8708 /* Take a copy of the piece */
8713 XSetFunction(xDisplay, bufGC, GXcopy);
8714 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8716 0, 0, squareSize, squareSize, 0, 0);
8718 /* XOR the background (light) over the piece */
8719 XSetFunction(xDisplay, bufGC, GXxor);
8721 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8722 0, 0, squareSize, squareSize, 0, 0);
8724 XSetForeground(xDisplay, bufGC, lightSquareColor);
8725 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8728 /* We now have an inverted piece image with the background
8729 erased. Construct mask by just selecting all the non-zero
8730 pixels - no need to reconstruct the original image. */
8731 XSetFunction(xDisplay, maskGC, GXor);
8733 /* Might be quicker to download an XImage and create bitmap
8734 data from it rather than this N copies per piece, but it
8735 only takes a fraction of a second and there is a much
8736 longer delay for loading the pieces. */
8737 for (n = 0; n < pieceDepth; n ++) {
8738 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8739 0, 0, squareSize, squareSize,
8745 XFreePixmap(xDisplay, buf);
8746 XFreeGC(xDisplay, bufGC);
8747 XFreeGC(xDisplay, maskGC);
8751 InitAnimState (anim, info)
8753 XWindowAttributes * info;
8758 /* Each buffer is square size, same depth as window */
8759 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8760 squareSize, squareSize, info->depth);
8761 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8762 squareSize, squareSize, info->depth);
8764 /* Create a plain GC for blitting */
8765 mask = GCForeground | GCBackground | GCFunction |
8766 GCPlaneMask | GCGraphicsExposures;
8767 values.foreground = XBlackPixel(xDisplay, xScreen);
8768 values.background = XWhitePixel(xDisplay, xScreen);
8769 values.function = GXcopy;
8770 values.plane_mask = AllPlanes;
8771 values.graphics_exposures = False;
8772 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8774 /* Piece will be copied from an existing context at
8775 the start of each new animation/drag. */
8776 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8778 /* Outline will be a read-only copy of an existing */
8779 anim->outlineGC = None;
8785 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8786 XWindowAttributes info;
8788 if (xpmDone && gameInfo.variant == old) return;
8789 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8790 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8792 InitAnimState(&game, &info);
8793 InitAnimState(&player, &info);
8795 /* For XPM pieces, we need bitmaps to use as masks. */
8797 CreateAnimMasks(info.depth);
8803 static Boolean frameWaiting;
8805 static RETSIGTYPE FrameAlarm (sig)
8808 frameWaiting = False;
8809 /* In case System-V style signals. Needed?? */
8810 signal(SIGALRM, FrameAlarm);
8817 struct itimerval delay;
8819 XSync(xDisplay, False);
8822 frameWaiting = True;
8823 signal(SIGALRM, FrameAlarm);
8824 delay.it_interval.tv_sec =
8825 delay.it_value.tv_sec = time / 1000;
8826 delay.it_interval.tv_usec =
8827 delay.it_value.tv_usec = (time % 1000) * 1000;
8828 setitimer(ITIMER_REAL, &delay, NULL);
8829 while (frameWaiting) pause();
8830 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8831 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8832 setitimer(ITIMER_REAL, &delay, NULL);
8842 XSync(xDisplay, False);
8844 usleep(time * 1000);
8849 /* Convert board position to corner of screen rect and color */
8852 ScreenSquare(column, row, pt, color)
8853 int column; int row; XPoint * pt; int * color;
8856 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8857 pt->y = lineGap + row * (squareSize + lineGap);
8859 pt->x = lineGap + column * (squareSize + lineGap);
8860 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8862 *color = SquareColor(row, column);
8865 /* Convert window coords to square */
8868 BoardSquare(x, y, column, row)
8869 int x; int y; int * column; int * row;
8871 *column = EventToSquare(x, BOARD_WIDTH);
8872 if (flipView && *column >= 0)
8873 *column = BOARD_WIDTH - 1 - *column;
8874 *row = EventToSquare(y, BOARD_HEIGHT);
8875 if (!flipView && *row >= 0)
8876 *row = BOARD_HEIGHT - 1 - *row;
8881 #undef Max /* just in case */
8883 #define Max(a, b) ((a) > (b) ? (a) : (b))
8884 #define Min(a, b) ((a) < (b) ? (a) : (b))
8887 SetRect(rect, x, y, width, height)
8888 XRectangle * rect; int x; int y; int width; int height;
8892 rect->width = width;
8893 rect->height = height;
8896 /* Test if two frames overlap. If they do, return
8897 intersection rect within old and location of
8898 that rect within new. */
8901 Intersect(old, new, size, area, pt)
8902 XPoint * old; XPoint * new;
8903 int size; XRectangle * area; XPoint * pt;
8905 if (old->x > new->x + size || new->x > old->x + size ||
8906 old->y > new->y + size || new->y > old->y + size) {
8909 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8910 size - abs(old->x - new->x), size - abs(old->y - new->y));
8911 pt->x = Max(old->x - new->x, 0);
8912 pt->y = Max(old->y - new->y, 0);
8917 /* For two overlapping frames, return the rect(s)
8918 in the old that do not intersect with the new. */
8921 CalcUpdateRects(old, new, size, update, nUpdates)
8922 XPoint * old; XPoint * new; int size;
8923 XRectangle update[]; int * nUpdates;
8927 /* If old = new (shouldn't happen) then nothing to draw */
8928 if (old->x == new->x && old->y == new->y) {
8932 /* Work out what bits overlap. Since we know the rects
8933 are the same size we don't need a full intersect calc. */
8935 /* Top or bottom edge? */
8936 if (new->y > old->y) {
8937 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8939 } else if (old->y > new->y) {
8940 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8941 size, old->y - new->y);
8944 /* Left or right edge - don't overlap any update calculated above. */
8945 if (new->x > old->x) {
8946 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8947 new->x - old->x, size - abs(new->y - old->y));
8949 } else if (old->x > new->x) {
8950 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8951 old->x - new->x, size - abs(new->y - old->y));
8958 /* Generate a series of frame coords from start->mid->finish.
8959 The movement rate doubles until the half way point is
8960 reached, then halves back down to the final destination,
8961 which gives a nice slow in/out effect. The algorithmn
8962 may seem to generate too many intermediates for short
8963 moves, but remember that the purpose is to attract the
8964 viewers attention to the piece about to be moved and
8965 then to where it ends up. Too few frames would be less
8969 Tween(start, mid, finish, factor, frames, nFrames)
8970 XPoint * start; XPoint * mid;
8971 XPoint * finish; int factor;
8972 XPoint frames[]; int * nFrames;
8974 int fraction, n, count;
8978 /* Slow in, stepping 1/16th, then 1/8th, ... */
8980 for (n = 0; n < factor; n++)
8982 for (n = 0; n < factor; n++) {
8983 frames[count].x = start->x + (mid->x - start->x) / fraction;
8984 frames[count].y = start->y + (mid->y - start->y) / fraction;
8986 fraction = fraction / 2;
8990 frames[count] = *mid;
8993 /* Slow out, stepping 1/2, then 1/4, ... */
8995 for (n = 0; n < factor; n++) {
8996 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8997 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8999 fraction = fraction * 2;
9004 /* Draw a piece on the screen without disturbing what's there */
9007 SelectGCMask(piece, clip, outline, mask)
9008 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9012 /* Bitmap for piece being moved. */
9013 if (appData.monoMode) {
9014 *mask = *pieceToSolid(piece);
9015 } else if (useImages) {
9017 *mask = xpmMask[piece];
9019 *mask = ximMaskPm[piece];
9022 *mask = *pieceToSolid(piece);
9025 /* GC for piece being moved. Square color doesn't matter, but
9026 since it gets modified we make a copy of the original. */
9028 if (appData.monoMode)
9033 if (appData.monoMode)
9038 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9040 /* Outline only used in mono mode and is not modified */
9042 *outline = bwPieceGC;
9044 *outline = wbPieceGC;
9048 OverlayPiece(piece, clip, outline, dest)
9049 ChessSquare piece; GC clip; GC outline; Drawable dest;
9054 /* Draw solid rectangle which will be clipped to shape of piece */
9055 XFillRectangle(xDisplay, dest, clip,
9056 0, 0, squareSize, squareSize);
9057 if (appData.monoMode)
9058 /* Also draw outline in contrasting color for black
9059 on black / white on white cases */
9060 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9061 0, 0, squareSize, squareSize, 0, 0, 1);
9063 /* Copy the piece */
9068 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9070 0, 0, squareSize, squareSize,
9075 /* Animate the movement of a single piece */
9078 BeginAnimation(anim, piece, startColor, start)
9086 /* The old buffer is initialised with the start square (empty) */
9087 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9088 anim->prevFrame = *start;
9090 /* The piece will be drawn using its own bitmap as a matte */
9091 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9092 XSetClipMask(xDisplay, anim->pieceGC, mask);
9096 AnimationFrame(anim, frame, piece)
9101 XRectangle updates[4];
9106 /* Save what we are about to draw into the new buffer */
9107 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9108 frame->x, frame->y, squareSize, squareSize,
9111 /* Erase bits of the previous frame */
9112 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9113 /* Where the new frame overlapped the previous,
9114 the contents in newBuf are wrong. */
9115 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9116 overlap.x, overlap.y,
9117 overlap.width, overlap.height,
9119 /* Repaint the areas in the old that don't overlap new */
9120 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9121 for (i = 0; i < count; i++)
9122 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9123 updates[i].x - anim->prevFrame.x,
9124 updates[i].y - anim->prevFrame.y,
9125 updates[i].width, updates[i].height,
9126 updates[i].x, updates[i].y);
9128 /* Easy when no overlap */
9129 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9130 0, 0, squareSize, squareSize,
9131 anim->prevFrame.x, anim->prevFrame.y);
9134 /* Save this frame for next time round */
9135 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9136 0, 0, squareSize, squareSize,
9138 anim->prevFrame = *frame;
9140 /* Draw piece over original screen contents, not current,
9141 and copy entire rect. Wipes out overlapping piece images. */
9142 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9143 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9144 0, 0, squareSize, squareSize,
9145 frame->x, frame->y);
9149 EndAnimation (anim, finish)
9153 XRectangle updates[4];
9158 /* The main code will redraw the final square, so we
9159 only need to erase the bits that don't overlap. */
9160 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9161 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9162 for (i = 0; i < count; i++)
9163 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9164 updates[i].x - anim->prevFrame.x,
9165 updates[i].y - anim->prevFrame.y,
9166 updates[i].width, updates[i].height,
9167 updates[i].x, updates[i].y);
9169 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9170 0, 0, squareSize, squareSize,
9171 anim->prevFrame.x, anim->prevFrame.y);
9176 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9178 ChessSquare piece; int startColor;
9179 XPoint * start; XPoint * finish;
9180 XPoint frames[]; int nFrames;
9184 BeginAnimation(anim, piece, startColor, start);
9185 for (n = 0; n < nFrames; n++) {
9186 AnimationFrame(anim, &(frames[n]), piece);
9187 FrameDelay(appData.animSpeed);
9189 EndAnimation(anim, finish);
9192 /* Main control logic for deciding what to animate and how */
9195 AnimateMove(board, fromX, fromY, toX, toY)
9204 XPoint start, finish, mid;
9205 XPoint frames[kFactor * 2 + 1];
9206 int nFrames, startColor, endColor;
9208 /* Are we animating? */
9209 if (!appData.animate || appData.blindfold)
9212 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9213 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9214 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9216 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9217 piece = board[fromY][fromX];
9218 if (piece >= EmptySquare) return;
9223 hop = (piece == WhiteKnight || piece == BlackKnight);
9226 if (appData.debugMode) {
9227 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9228 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9229 piece, fromX, fromY, toX, toY); }
9231 ScreenSquare(fromX, fromY, &start, &startColor);
9232 ScreenSquare(toX, toY, &finish, &endColor);
9235 /* Knight: make diagonal movement then straight */
9236 if (abs(toY - fromY) < abs(toX - fromX)) {
9237 mid.x = start.x + (finish.x - start.x) / 2;
9241 mid.y = start.y + (finish.y - start.y) / 2;
9244 mid.x = start.x + (finish.x - start.x) / 2;
9245 mid.y = start.y + (finish.y - start.y) / 2;
9248 /* Don't use as many frames for very short moves */
9249 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9250 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9252 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9253 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9255 /* Be sure end square is redrawn */
9256 damage[toY][toX] = True;
9260 DragPieceBegin(x, y)
9263 int boardX, boardY, color;
9266 /* Are we animating? */
9267 if (!appData.animateDragging || appData.blindfold)
9270 /* Figure out which square we start in and the
9271 mouse position relative to top left corner. */
9272 BoardSquare(x, y, &boardX, &boardY);
9273 player.startBoardX = boardX;
9274 player.startBoardY = boardY;
9275 ScreenSquare(boardX, boardY, &corner, &color);
9276 player.startSquare = corner;
9277 player.startColor = color;
9278 /* As soon as we start dragging, the piece will jump slightly to
9279 be centered over the mouse pointer. */
9280 player.mouseDelta.x = squareSize/2;
9281 player.mouseDelta.y = squareSize/2;
9282 /* Initialise animation */
9283 player.dragPiece = PieceForSquare(boardX, boardY);
9285 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9286 player.dragActive = True;
9287 BeginAnimation(&player, player.dragPiece, color, &corner);
9288 /* Mark this square as needing to be redrawn. Note that
9289 we don't remove the piece though, since logically (ie
9290 as seen by opponent) the move hasn't been made yet. */
9291 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9292 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9293 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9294 corner.x, corner.y, squareSize, squareSize,
9295 0, 0); // [HGM] zh: unstack in stead of grab
9296 damage[boardY][boardX] = True;
9298 player.dragActive = False;
9308 /* Are we animating? */
9309 if (!appData.animateDragging || appData.blindfold)
9313 if (! player.dragActive)
9315 /* Move piece, maintaining same relative position
9316 of mouse within square */
9317 corner.x = x - player.mouseDelta.x;
9318 corner.y = y - player.mouseDelta.y;
9319 AnimationFrame(&player, &corner, player.dragPiece);
9321 if (appData.highlightDragging) {
9323 BoardSquare(x, y, &boardX, &boardY);
9324 SetHighlights(fromX, fromY, boardX, boardY);
9333 int boardX, boardY, color;
9336 /* Are we animating? */
9337 if (!appData.animateDragging || appData.blindfold)
9341 if (! player.dragActive)
9343 /* Last frame in sequence is square piece is
9344 placed on, which may not match mouse exactly. */
9345 BoardSquare(x, y, &boardX, &boardY);
9346 ScreenSquare(boardX, boardY, &corner, &color);
9347 EndAnimation(&player, &corner);
9349 /* Be sure end square is redrawn */
9350 damage[boardY][boardX] = True;
9352 /* This prevents weird things happening with fast successive
9353 clicks which on my Sun at least can cause motion events
9354 without corresponding press/release. */
9355 player.dragActive = False;
9358 /* Handle expose event while piece being dragged */
9363 if (!player.dragActive || appData.blindfold)
9366 /* What we're doing: logically, the move hasn't been made yet,
9367 so the piece is still in it's original square. But visually
9368 it's being dragged around the board. So we erase the square
9369 that the piece is on and draw it at the last known drag point. */
9370 BlankSquare(player.startSquare.x, player.startSquare.y,
9371 player.startColor, EmptySquare, xBoardWindow);
9372 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9373 damage[player.startBoardY][player.startBoardX] = TRUE;
9377 SetProgramStats( FrontEndProgramStats * stats )
9380 // [HGM] done, but perhaps backend should call this directly?
9381 EngineOutputUpdate( stats );
9384 #include <sys/ioctl.h>
9385 int get_term_width()
9387 int fd, default_width;
9390 default_width = 79; // this is FICS default anyway...
9392 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9394 if (!ioctl(fd, TIOCGSIZE, &win))
9395 default_width = win.ts_cols;
9396 #elif defined(TIOCGWINSZ)
9398 if (!ioctl(fd, TIOCGWINSZ, &win))
9399 default_width = win.ws_col;
9401 return default_width;
9404 void update_ics_width()
9406 static int old_width = 0;
9407 int new_width = get_term_width();
9409 if (old_width != new_width)
9410 ics_printf("set width %d\n", new_width);
9411 old_width = new_width;
9414 void NotifyFrontendLogin()