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, 2010 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_SIZE + 1) * 2];
471 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
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_SIZE ||
2515 appData.NrRanks > BOARD_SIZE )
2516 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, 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();
3314 SetMenuEnables(enab)
3318 if (!menuBarWidget) return;
3319 while (enab->name != NULL) {
3320 w = XtNameToWidget(menuBarWidget, enab->name);
3322 DisplayError(enab->name, 0);
3324 XtSetSensitive(w, enab->value);
3330 Enables icsEnables[] = {
3331 { "menuFile.Mail Move", False },
3332 { "menuFile.Reload CMail Message", False },
3333 { "menuMode.Machine Black", False },
3334 { "menuMode.Machine White", False },
3335 { "menuMode.Analysis Mode", False },
3336 { "menuMode.Analyze File", False },
3337 { "menuMode.Two Machines", False },
3339 { "menuHelp.Hint", False },
3340 { "menuHelp.Book", False },
3341 { "menuStep.Move Now", False },
3342 { "menuOptions.Periodic Updates", False },
3343 { "menuOptions.Hide Thinking", False },
3344 { "menuOptions.Ponder Next Move", False },
3349 Enables ncpEnables[] = {
3350 { "menuFile.Mail Move", False },
3351 { "menuFile.Reload CMail Message", False },
3352 { "menuMode.Machine White", False },
3353 { "menuMode.Machine Black", False },
3354 { "menuMode.Analysis Mode", False },
3355 { "menuMode.Analyze File", False },
3356 { "menuMode.Two Machines", False },
3357 { "menuMode.ICS Client", False },
3358 { "menuMode.ICS Input Box", False },
3359 { "Action", False },
3360 { "menuStep.Revert", False },
3361 { "menuStep.Move Now", False },
3362 { "menuStep.Retract Move", False },
3363 { "menuOptions.Auto Comment", False },
3364 { "menuOptions.Auto Flag", False },
3365 { "menuOptions.Auto Flip View", False },
3366 { "menuOptions.Auto Observe", False },
3367 { "menuOptions.Auto Raise Board", False },
3368 { "menuOptions.Get Move List", False },
3369 { "menuOptions.ICS Alarm", False },
3370 { "menuOptions.Move Sound", False },
3371 { "menuOptions.Quiet Play", False },
3372 { "menuOptions.Hide Thinking", False },
3373 { "menuOptions.Periodic Updates", False },
3374 { "menuOptions.Ponder Next Move", False },
3375 { "menuHelp.Hint", False },
3376 { "menuHelp.Book", False },
3380 Enables gnuEnables[] = {
3381 { "menuMode.ICS Client", False },
3382 { "menuMode.ICS Input Box", False },
3383 { "menuAction.Accept", False },
3384 { "menuAction.Decline", False },
3385 { "menuAction.Rematch", False },
3386 { "menuAction.Adjourn", False },
3387 { "menuAction.Stop Examining", False },
3388 { "menuAction.Stop Observing", False },
3389 { "menuStep.Revert", False },
3390 { "menuOptions.Auto Comment", False },
3391 { "menuOptions.Auto Observe", False },
3392 { "menuOptions.Auto Raise Board", False },
3393 { "menuOptions.Get Move List", False },
3394 { "menuOptions.Premove", False },
3395 { "menuOptions.Quiet Play", False },
3397 /* The next two options rely on SetCmailMode being called *after* */
3398 /* SetGNUMode so that when GNU is being used to give hints these */
3399 /* menu options are still available */
3401 { "menuFile.Mail Move", False },
3402 { "menuFile.Reload CMail Message", False },
3406 Enables cmailEnables[] = {
3408 { "menuAction.Call Flag", False },
3409 { "menuAction.Draw", True },
3410 { "menuAction.Adjourn", False },
3411 { "menuAction.Abort", False },
3412 { "menuAction.Stop Observing", False },
3413 { "menuAction.Stop Examining", False },
3414 { "menuFile.Mail Move", True },
3415 { "menuFile.Reload CMail Message", True },
3419 Enables trainingOnEnables[] = {
3420 { "menuMode.Edit Comment", False },
3421 { "menuMode.Pause", False },
3422 { "menuStep.Forward", False },
3423 { "menuStep.Backward", False },
3424 { "menuStep.Forward to End", False },
3425 { "menuStep.Back to Start", False },
3426 { "menuStep.Move Now", False },
3427 { "menuStep.Truncate Game", False },
3431 Enables trainingOffEnables[] = {
3432 { "menuMode.Edit Comment", True },
3433 { "menuMode.Pause", True },
3434 { "menuStep.Forward", True },
3435 { "menuStep.Backward", True },
3436 { "menuStep.Forward to End", True },
3437 { "menuStep.Back to Start", True },
3438 { "menuStep.Move Now", True },
3439 { "menuStep.Truncate Game", True },
3443 Enables machineThinkingEnables[] = {
3444 { "menuFile.Load Game", False },
3445 { "menuFile.Load Next Game", False },
3446 { "menuFile.Load Previous Game", False },
3447 { "menuFile.Reload Same Game", False },
3448 { "menuFile.Paste Game", False },
3449 { "menuFile.Load Position", False },
3450 { "menuFile.Load Next Position", False },
3451 { "menuFile.Load Previous Position", False },
3452 { "menuFile.Reload Same Position", False },
3453 { "menuFile.Paste Position", False },
3454 { "menuMode.Machine White", False },
3455 { "menuMode.Machine Black", False },
3456 { "menuMode.Two Machines", False },
3457 { "menuStep.Retract Move", False },
3461 Enables userThinkingEnables[] = {
3462 { "menuFile.Load Game", True },
3463 { "menuFile.Load Next Game", True },
3464 { "menuFile.Load Previous Game", True },
3465 { "menuFile.Reload Same Game", True },
3466 { "menuFile.Paste Game", True },
3467 { "menuFile.Load Position", True },
3468 { "menuFile.Load Next Position", True },
3469 { "menuFile.Load Previous Position", True },
3470 { "menuFile.Reload Same Position", True },
3471 { "menuFile.Paste Position", True },
3472 { "menuMode.Machine White", True },
3473 { "menuMode.Machine Black", True },
3474 { "menuMode.Two Machines", True },
3475 { "menuStep.Retract Move", True },
3481 SetMenuEnables(icsEnables);
3484 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3485 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3492 SetMenuEnables(ncpEnables);
3498 SetMenuEnables(gnuEnables);
3504 SetMenuEnables(cmailEnables);
3510 SetMenuEnables(trainingOnEnables);
3511 if (appData.showButtonBar) {
3512 XtSetSensitive(buttonBarWidget, False);
3518 SetTrainingModeOff()
3520 SetMenuEnables(trainingOffEnables);
3521 if (appData.showButtonBar) {
3522 XtSetSensitive(buttonBarWidget, True);
3527 SetUserThinkingEnables()
3529 if (appData.noChessProgram) return;
3530 SetMenuEnables(userThinkingEnables);
3534 SetMachineThinkingEnables()
3536 if (appData.noChessProgram) return;
3537 SetMenuEnables(machineThinkingEnables);
3539 case MachinePlaysBlack:
3540 case MachinePlaysWhite:
3541 case TwoMachinesPlay:
3542 XtSetSensitive(XtNameToWidget(menuBarWidget,
3543 ModeToWidgetName(gameMode)), True);
3550 #define Abs(n) ((n)<0 ? -(n) : (n))
3553 * Find a font that matches "pattern" that is as close as
3554 * possible to the targetPxlSize. Prefer fonts that are k
3555 * pixels smaller to fonts that are k pixels larger. The
3556 * pattern must be in the X Consortium standard format,
3557 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3558 * The return value should be freed with XtFree when no
3561 char *FindFont(pattern, targetPxlSize)
3565 char **fonts, *p, *best, *scalable, *scalableTail;
3566 int i, j, nfonts, minerr, err, pxlSize;
3569 char **missing_list;
3571 char *def_string, *base_fnt_lst, strInt[3];
3573 XFontStruct **fnt_list;
3575 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3576 sprintf(strInt, "%d", targetPxlSize);
3577 p = strstr(pattern, "--");
3578 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3579 strcat(base_fnt_lst, strInt);
3580 strcat(base_fnt_lst, strchr(p + 2, '-'));
3582 if ((fntSet = XCreateFontSet(xDisplay,
3586 &def_string)) == NULL) {
3588 fprintf(stderr, _("Unable to create font set.\n"));
3592 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3594 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3596 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3597 programName, pattern);
3605 for (i=0; i<nfonts; i++) {
3608 if (*p != '-') continue;
3610 if (*p == NULLCHAR) break;
3611 if (*p++ == '-') j++;
3613 if (j < 7) continue;
3616 scalable = fonts[i];
3619 err = pxlSize - targetPxlSize;
3620 if (Abs(err) < Abs(minerr) ||
3621 (minerr > 0 && err < 0 && -err == minerr)) {
3627 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3628 /* If the error is too big and there is a scalable font,
3629 use the scalable font. */
3630 int headlen = scalableTail - scalable;
3631 p = (char *) XtMalloc(strlen(scalable) + 10);
3632 while (isdigit(*scalableTail)) scalableTail++;
3633 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3635 p = (char *) XtMalloc(strlen(best) + 1);
3638 if (appData.debugMode) {
3639 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3640 pattern, targetPxlSize, p);
3643 if (missing_count > 0)
3644 XFreeStringList(missing_list);
3645 XFreeFontSet(xDisplay, fntSet);
3647 XFreeFontNames(fonts);
3654 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3655 | GCBackground | GCFunction | GCPlaneMask;
3656 XGCValues gc_values;
3659 gc_values.plane_mask = AllPlanes;
3660 gc_values.line_width = lineGap;
3661 gc_values.line_style = LineSolid;
3662 gc_values.function = GXcopy;
3664 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3665 gc_values.background = XBlackPixel(xDisplay, xScreen);
3666 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3668 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3669 gc_values.background = XWhitePixel(xDisplay, xScreen);
3670 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3671 XSetFont(xDisplay, coordGC, coordFontID);
3673 // [HGM] make font for holdings counts (white on black0
3674 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3675 gc_values.background = XBlackPixel(xDisplay, xScreen);
3676 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3677 XSetFont(xDisplay, countGC, countFontID);
3679 if (appData.monoMode) {
3680 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3681 gc_values.background = XWhitePixel(xDisplay, xScreen);
3682 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3684 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3685 gc_values.background = XBlackPixel(xDisplay, xScreen);
3686 lightSquareGC = wbPieceGC
3687 = XtGetGC(shellWidget, value_mask, &gc_values);
3689 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3690 gc_values.background = XWhitePixel(xDisplay, xScreen);
3691 darkSquareGC = bwPieceGC
3692 = XtGetGC(shellWidget, value_mask, &gc_values);
3694 if (DefaultDepth(xDisplay, xScreen) == 1) {
3695 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3696 gc_values.function = GXcopyInverted;
3697 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3698 gc_values.function = GXcopy;
3699 if (XBlackPixel(xDisplay, xScreen) == 1) {
3700 bwPieceGC = darkSquareGC;
3701 wbPieceGC = copyInvertedGC;
3703 bwPieceGC = copyInvertedGC;
3704 wbPieceGC = lightSquareGC;
3708 gc_values.foreground = highlightSquareColor;
3709 gc_values.background = highlightSquareColor;
3710 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = premoveHighlightColor;
3713 gc_values.background = premoveHighlightColor;
3714 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = lightSquareColor;
3717 gc_values.background = darkSquareColor;
3718 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3720 gc_values.foreground = darkSquareColor;
3721 gc_values.background = lightSquareColor;
3722 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3724 gc_values.foreground = jailSquareColor;
3725 gc_values.background = jailSquareColor;
3726 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3728 gc_values.foreground = whitePieceColor;
3729 gc_values.background = darkSquareColor;
3730 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3732 gc_values.foreground = whitePieceColor;
3733 gc_values.background = lightSquareColor;
3734 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3736 gc_values.foreground = whitePieceColor;
3737 gc_values.background = jailSquareColor;
3738 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3740 gc_values.foreground = blackPieceColor;
3741 gc_values.background = darkSquareColor;
3742 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3744 gc_values.foreground = blackPieceColor;
3745 gc_values.background = lightSquareColor;
3746 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3748 gc_values.foreground = blackPieceColor;
3749 gc_values.background = jailSquareColor;
3750 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3754 void loadXIM(xim, xmask, filename, dest, mask)
3767 fp = fopen(filename, "rb");
3769 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3776 for (y=0; y<h; ++y) {
3777 for (x=0; x<h; ++x) {
3782 XPutPixel(xim, x, y, blackPieceColor);
3784 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3787 XPutPixel(xim, x, y, darkSquareColor);
3789 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3792 XPutPixel(xim, x, y, whitePieceColor);
3794 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3797 XPutPixel(xim, x, y, lightSquareColor);
3799 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3805 /* create Pixmap of piece */
3806 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3808 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3811 /* create Pixmap of clipmask
3812 Note: We assume the white/black pieces have the same
3813 outline, so we make only 6 masks. This is okay
3814 since the XPM clipmask routines do the same. */
3816 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3818 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3821 /* now create the 1-bit version */
3822 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3825 values.foreground = 1;
3826 values.background = 0;
3828 /* Don't use XtGetGC, not read only */
3829 maskGC = XCreateGC(xDisplay, *mask,
3830 GCForeground | GCBackground, &values);
3831 XCopyPlane(xDisplay, temp, *mask, maskGC,
3832 0, 0, squareSize, squareSize, 0, 0, 1);
3833 XFreePixmap(xDisplay, temp);
3838 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3840 void CreateXIMPieces()
3845 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3850 /* The XSynchronize calls were copied from CreatePieces.
3851 Not sure if needed, but can't hurt */
3852 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3855 /* temp needed by loadXIM() */
3856 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3857 0, 0, ss, ss, AllPlanes, XYPixmap);
3859 if (strlen(appData.pixmapDirectory) == 0) {
3863 if (appData.monoMode) {
3864 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3868 fprintf(stderr, _("\nLoading XIMs...\n"));
3870 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3871 fprintf(stderr, "%d", piece+1);
3872 for (kind=0; kind<4; kind++) {
3873 fprintf(stderr, ".");
3874 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3875 ExpandPathName(appData.pixmapDirectory),
3876 piece <= (int) WhiteKing ? "" : "w",
3877 pieceBitmapNames[piece],
3879 ximPieceBitmap[kind][piece] =
3880 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3881 0, 0, ss, ss, AllPlanes, XYPixmap);
3882 if (appData.debugMode)
3883 fprintf(stderr, _("(File:%s:) "), buf);
3884 loadXIM(ximPieceBitmap[kind][piece],
3886 &(xpmPieceBitmap2[kind][piece]),
3887 &(ximMaskPm2[piece]));
3888 if(piece <= (int)WhiteKing)
3889 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3891 fprintf(stderr," ");
3893 /* Load light and dark squares */
3894 /* If the LSQ and DSQ pieces don't exist, we will
3895 draw them with solid squares. */
3896 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3897 if (access(buf, 0) != 0) {
3901 fprintf(stderr, _("light square "));
3903 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3904 0, 0, ss, ss, AllPlanes, XYPixmap);
3905 if (appData.debugMode)
3906 fprintf(stderr, _("(File:%s:) "), buf);
3908 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3909 fprintf(stderr, _("dark square "));
3910 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3911 ExpandPathName(appData.pixmapDirectory), ss);
3912 if (appData.debugMode)
3913 fprintf(stderr, _("(File:%s:) "), buf);
3915 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3916 0, 0, ss, ss, AllPlanes, XYPixmap);
3917 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3918 xpmJailSquare = xpmLightSquare;
3920 fprintf(stderr, _("Done.\n"));
3922 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3926 void CreateXPMPieces()
3930 u_int ss = squareSize;
3932 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3933 XpmColorSymbol symbols[4];
3935 /* The XSynchronize calls were copied from CreatePieces.
3936 Not sure if needed, but can't hurt */
3937 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3939 /* Setup translations so piece colors match square colors */
3940 symbols[0].name = "light_piece";
3941 symbols[0].value = appData.whitePieceColor;
3942 symbols[1].name = "dark_piece";
3943 symbols[1].value = appData.blackPieceColor;
3944 symbols[2].name = "light_square";
3945 symbols[2].value = appData.lightSquareColor;
3946 symbols[3].name = "dark_square";
3947 symbols[3].value = appData.darkSquareColor;
3949 attr.valuemask = XpmColorSymbols;
3950 attr.colorsymbols = symbols;
3951 attr.numsymbols = 4;
3953 if (appData.monoMode) {
3954 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3958 if (strlen(appData.pixmapDirectory) == 0) {
3959 XpmPieces* pieces = builtInXpms;
3962 while (pieces->size != squareSize && pieces->size) pieces++;
3963 if (!pieces->size) {
3964 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3967 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3968 for (kind=0; kind<4; kind++) {
3970 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3971 pieces->xpm[piece][kind],
3972 &(xpmPieceBitmap2[kind][piece]),
3973 NULL, &attr)) != 0) {
3974 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3978 if(piece <= (int) WhiteKing)
3979 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3983 xpmJailSquare = xpmLightSquare;
3987 fprintf(stderr, _("\nLoading XPMs...\n"));
3990 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3991 fprintf(stderr, "%d ", piece+1);
3992 for (kind=0; kind<4; kind++) {
3993 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3994 ExpandPathName(appData.pixmapDirectory),
3995 piece > (int) WhiteKing ? "w" : "",
3996 pieceBitmapNames[piece],
3998 if (appData.debugMode) {
3999 fprintf(stderr, _("(File:%s:) "), buf);
4001 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4002 &(xpmPieceBitmap2[kind][piece]),
4003 NULL, &attr)) != 0) {
4004 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
4005 // [HGM] missing: read of unorthodox piece failed; substitute King.
4006 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
4007 ExpandPathName(appData.pixmapDirectory),
4009 if (appData.debugMode) {
4010 fprintf(stderr, _("(Replace by File:%s:) "), buf);
4012 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4013 &(xpmPieceBitmap2[kind][piece]),
4017 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4022 if(piece <= (int) WhiteKing)
4023 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4026 /* Load light and dark squares */
4027 /* If the LSQ and DSQ pieces don't exist, we will
4028 draw them with solid squares. */
4029 fprintf(stderr, _("light square "));
4030 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4031 if (access(buf, 0) != 0) {
4035 if (appData.debugMode)
4036 fprintf(stderr, _("(File:%s:) "), buf);
4038 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4039 &xpmLightSquare, NULL, &attr)) != 0) {
4040 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4043 fprintf(stderr, _("dark square "));
4044 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4045 ExpandPathName(appData.pixmapDirectory), ss);
4046 if (appData.debugMode) {
4047 fprintf(stderr, _("(File:%s:) "), buf);
4049 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4050 &xpmDarkSquare, NULL, &attr)) != 0) {
4051 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4055 xpmJailSquare = xpmLightSquare;
4056 fprintf(stderr, _("Done.\n"));
4058 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4061 #endif /* HAVE_LIBXPM */
4064 /* No built-in bitmaps */
4069 u_int ss = squareSize;
4071 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4074 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4075 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4076 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4077 pieceBitmapNames[piece],
4078 ss, kind == SOLID ? 's' : 'o');
4079 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4080 if(piece <= (int)WhiteKing)
4081 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4085 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4089 /* With built-in bitmaps */
4092 BuiltInBits* bib = builtInBits;
4095 u_int ss = squareSize;
4097 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4100 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4102 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4103 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4104 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4105 pieceBitmapNames[piece],
4106 ss, kind == SOLID ? 's' : 'o');
4107 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4108 bib->bits[kind][piece], ss, ss);
4109 if(piece <= (int)WhiteKing)
4110 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4114 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4119 void ReadBitmap(pm, name, bits, wreq, hreq)
4122 unsigned char bits[];
4128 char msg[MSG_SIZ], fullname[MSG_SIZ];
4130 if (*appData.bitmapDirectory != NULLCHAR) {
4131 strcpy(fullname, appData.bitmapDirectory);
4132 strcat(fullname, "/");
4133 strcat(fullname, name);
4134 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4135 &w, &h, pm, &x_hot, &y_hot);
4136 fprintf(stderr, "load %s\n", name);
4137 if (errcode != BitmapSuccess) {
4139 case BitmapOpenFailed:
4140 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4142 case BitmapFileInvalid:
4143 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4145 case BitmapNoMemory:
4146 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4150 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4154 fprintf(stderr, _("%s: %s...using built-in\n"),
4156 } else if (w != wreq || h != hreq) {
4158 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4159 programName, fullname, w, h, wreq, hreq);
4165 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4174 if (lineGap == 0) return;
4176 /* [HR] Split this into 2 loops for non-square boards. */
4178 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4179 gridSegments[i].x1 = 0;
4180 gridSegments[i].x2 =
4181 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4182 gridSegments[i].y1 = gridSegments[i].y2
4183 = lineGap / 2 + (i * (squareSize + lineGap));
4186 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4187 gridSegments[j + i].y1 = 0;
4188 gridSegments[j + i].y2 =
4189 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4190 gridSegments[j + i].x1 = gridSegments[j + i].x2
4191 = lineGap / 2 + (j * (squareSize + lineGap));
4195 static void MenuBarSelect(w, addr, index)
4200 XtActionProc proc = (XtActionProc) addr;
4202 (proc)(NULL, NULL, NULL, NULL);
4205 void CreateMenuBarPopup(parent, name, mb)
4215 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4218 XtSetArg(args[j], XtNleftMargin, 20); j++;
4219 XtSetArg(args[j], XtNrightMargin, 20); j++;
4221 while (mi->string != NULL) {
4222 if (strcmp(mi->string, "----") == 0) {
4223 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4226 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4227 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4229 XtAddCallback(entry, XtNcallback,
4230 (XtCallbackProc) MenuBarSelect,
4231 (caddr_t) mi->proc);
4237 Widget CreateMenuBar(mb)
4241 Widget anchor, menuBar;
4243 char menuName[MSG_SIZ];
4246 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4247 XtSetArg(args[j], XtNvSpace, 0); j++;
4248 XtSetArg(args[j], XtNborderWidth, 0); j++;
4249 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4250 formWidget, args, j);
4252 while (mb->name != NULL) {
4253 strcpy(menuName, "menu");
4254 strcat(menuName, mb->name);
4256 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4259 shortName[0] = _(mb->name)[0];
4260 shortName[1] = NULLCHAR;
4261 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4264 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4267 XtSetArg(args[j], XtNborderWidth, 0); j++;
4268 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4270 CreateMenuBarPopup(menuBar, menuName, mb);
4276 Widget CreateButtonBar(mi)
4280 Widget button, buttonBar;
4284 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4286 XtSetArg(args[j], XtNhSpace, 0); j++;
4288 XtSetArg(args[j], XtNborderWidth, 0); j++;
4289 XtSetArg(args[j], XtNvSpace, 0); j++;
4290 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4291 formWidget, args, j);
4293 while (mi->string != NULL) {
4296 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4297 XtSetArg(args[j], XtNborderWidth, 0); j++;
4299 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4300 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4301 buttonBar, args, j);
4302 XtAddCallback(button, XtNcallback,
4303 (XtCallbackProc) MenuBarSelect,
4304 (caddr_t) mi->proc);
4311 CreatePieceMenu(name, color)
4318 ChessSquare selection;
4320 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4321 boardWidget, args, 0);
4323 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4324 String item = pieceMenuStrings[color][i];
4326 if (strcmp(item, "----") == 0) {
4327 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4330 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4331 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4333 selection = pieceMenuTranslation[color][i];
4334 XtAddCallback(entry, XtNcallback,
4335 (XtCallbackProc) PieceMenuSelect,
4336 (caddr_t) selection);
4337 if (selection == WhitePawn || selection == BlackPawn) {
4338 XtSetArg(args[0], XtNpopupOnEntry, entry);
4339 XtSetValues(menu, args, 1);
4352 ChessSquare selection;
4354 whitePieceMenu = CreatePieceMenu("menuW", 0);
4355 blackPieceMenu = CreatePieceMenu("menuB", 1);
4357 XtRegisterGrabAction(PieceMenuPopup, True,
4358 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4359 GrabModeAsync, GrabModeAsync);
4361 XtSetArg(args[0], XtNlabel, _("Drop"));
4362 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4363 boardWidget, args, 1);
4364 for (i = 0; i < DROP_MENU_SIZE; i++) {
4365 String item = dropMenuStrings[i];
4367 if (strcmp(item, "----") == 0) {
4368 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4371 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4372 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4374 selection = dropMenuTranslation[i];
4375 XtAddCallback(entry, XtNcallback,
4376 (XtCallbackProc) DropMenuSelect,
4377 (caddr_t) selection);
4382 void SetupDropMenu()
4390 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4391 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4392 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4393 dmEnables[i].piece);
4394 XtSetSensitive(entry, p != NULL || !appData.testLegality
4395 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4396 && !appData.icsActive));
4398 while (p && *p++ == dmEnables[i].piece) count++;
4399 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4401 XtSetArg(args[j], XtNlabel, label); j++;
4402 XtSetValues(entry, args, j);
4406 void PieceMenuPopup(w, event, params, num_params)
4410 Cardinal *num_params;
4413 if (event->type != ButtonPress) return;
4414 if (errorUp) ErrorPopDown();
4418 whichMenu = params[0];
4420 case IcsPlayingWhite:
4421 case IcsPlayingBlack:
4423 case MachinePlaysWhite:
4424 case MachinePlaysBlack:
4425 if (appData.testLegality &&
4426 gameInfo.variant != VariantBughouse &&
4427 gameInfo.variant != VariantCrazyhouse) return;
4429 whichMenu = "menuD";
4435 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4436 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4437 pmFromX = pmFromY = -1;
4441 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4443 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4445 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4448 static void PieceMenuSelect(w, piece, junk)
4453 if (pmFromX < 0 || pmFromY < 0) return;
4454 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4457 static void DropMenuSelect(w, piece, junk)
4462 if (pmFromX < 0 || pmFromY < 0) return;
4463 DropMenuEvent(piece, pmFromX, pmFromY);
4466 void WhiteClock(w, event, prms, nprms)
4472 if (gameMode == EditPosition || gameMode == IcsExamining) {
4473 SetWhiteToPlayEvent();
4474 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4479 void BlackClock(w, event, prms, nprms)
4485 if (gameMode == EditPosition || gameMode == IcsExamining) {
4486 SetBlackToPlayEvent();
4487 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4494 * If the user selects on a border boundary, return -1; if off the board,
4495 * return -2. Otherwise map the event coordinate to the square.
4497 int EventToSquare(x, limit)
4505 if ((x % (squareSize + lineGap)) >= squareSize)
4507 x /= (squareSize + lineGap);
4513 static void do_flash_delay(msec)
4519 static void drawHighlight(file, rank, gc)
4525 if (lineGap == 0 || appData.blindfold) return;
4528 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4529 (squareSize + lineGap);
4530 y = lineGap/2 + rank * (squareSize + lineGap);
4532 x = lineGap/2 + file * (squareSize + lineGap);
4533 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4534 (squareSize + lineGap);
4537 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4538 squareSize+lineGap, squareSize+lineGap);
4541 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4542 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4545 SetHighlights(fromX, fromY, toX, toY)
4546 int fromX, fromY, toX, toY;
4548 if (hi1X != fromX || hi1Y != fromY) {
4549 if (hi1X >= 0 && hi1Y >= 0) {
4550 drawHighlight(hi1X, hi1Y, lineGC);
4552 } // [HGM] first erase both, then draw new!
4553 if (hi2X != toX || hi2Y != toY) {
4554 if (hi2X >= 0 && hi2Y >= 0) {
4555 drawHighlight(hi2X, hi2Y, lineGC);
4558 if (hi1X != fromX || hi1Y != fromY) {
4559 if (fromX >= 0 && fromY >= 0) {
4560 drawHighlight(fromX, fromY, highlineGC);
4563 if (hi2X != toX || hi2Y != toY) {
4564 if (toX >= 0 && toY >= 0) {
4565 drawHighlight(toX, toY, highlineGC);
4577 SetHighlights(-1, -1, -1, -1);
4582 SetPremoveHighlights(fromX, fromY, toX, toY)
4583 int fromX, fromY, toX, toY;
4585 if (pm1X != fromX || pm1Y != fromY) {
4586 if (pm1X >= 0 && pm1Y >= 0) {
4587 drawHighlight(pm1X, pm1Y, lineGC);
4589 if (fromX >= 0 && fromY >= 0) {
4590 drawHighlight(fromX, fromY, prelineGC);
4593 if (pm2X != toX || pm2Y != toY) {
4594 if (pm2X >= 0 && pm2Y >= 0) {
4595 drawHighlight(pm2X, pm2Y, lineGC);
4597 if (toX >= 0 && toY >= 0) {
4598 drawHighlight(toX, toY, prelineGC);
4608 ClearPremoveHighlights()
4610 SetPremoveHighlights(-1, -1, -1, -1);
4613 static void BlankSquare(x, y, color, piece, dest)
4618 if (useImages && useImageSqs) {
4622 pm = xpmLightSquare;
4627 case 2: /* neutral */
4632 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4633 squareSize, squareSize, x, y);
4643 case 2: /* neutral */
4648 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4653 I split out the routines to draw a piece so that I could
4654 make a generic flash routine.
4656 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4658 int square_color, x, y;
4661 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4662 switch (square_color) {
4664 case 2: /* neutral */
4666 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4667 ? *pieceToOutline(piece)
4668 : *pieceToSolid(piece),
4669 dest, bwPieceGC, 0, 0,
4670 squareSize, squareSize, x, y);
4673 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4674 ? *pieceToSolid(piece)
4675 : *pieceToOutline(piece),
4676 dest, wbPieceGC, 0, 0,
4677 squareSize, squareSize, x, y);
4682 static void monoDrawPiece(piece, square_color, x, y, dest)
4684 int square_color, x, y;
4687 switch (square_color) {
4689 case 2: /* neutral */
4691 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4692 ? *pieceToOutline(piece)
4693 : *pieceToSolid(piece),
4694 dest, bwPieceGC, 0, 0,
4695 squareSize, squareSize, x, y, 1);
4698 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4699 ? *pieceToSolid(piece)
4700 : *pieceToOutline(piece),
4701 dest, wbPieceGC, 0, 0,
4702 squareSize, squareSize, x, y, 1);
4707 static void colorDrawPiece(piece, square_color, x, y, dest)
4709 int square_color, x, y;
4712 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4713 switch (square_color) {
4715 XCopyPlane(xDisplay, *pieceToSolid(piece),
4716 dest, (int) piece < (int) BlackPawn
4717 ? wlPieceGC : blPieceGC, 0, 0,
4718 squareSize, squareSize, x, y, 1);
4721 XCopyPlane(xDisplay, *pieceToSolid(piece),
4722 dest, (int) piece < (int) BlackPawn
4723 ? wdPieceGC : bdPieceGC, 0, 0,
4724 squareSize, squareSize, x, y, 1);
4726 case 2: /* neutral */
4728 XCopyPlane(xDisplay, *pieceToSolid(piece),
4729 dest, (int) piece < (int) BlackPawn
4730 ? wjPieceGC : bjPieceGC, 0, 0,
4731 squareSize, squareSize, x, y, 1);
4736 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4738 int square_color, x, y;
4743 switch (square_color) {
4745 case 2: /* neutral */
4747 if ((int)piece < (int) BlackPawn) {
4755 if ((int)piece < (int) BlackPawn) {
4763 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4764 dest, wlPieceGC, 0, 0,
4765 squareSize, squareSize, x, y);
4768 typedef void (*DrawFunc)();
4770 DrawFunc ChooseDrawFunc()
4772 if (appData.monoMode) {
4773 if (DefaultDepth(xDisplay, xScreen) == 1) {
4774 return monoDrawPiece_1bit;
4776 return monoDrawPiece;
4780 return colorDrawPieceImage;
4782 return colorDrawPiece;
4786 /* [HR] determine square color depending on chess variant. */
4787 static int SquareColor(row, column)
4792 if (gameInfo.variant == VariantXiangqi) {
4793 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4795 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4797 } else if (row <= 4) {
4803 square_color = ((column + row) % 2) == 1;
4806 /* [hgm] holdings: next line makes all holdings squares light */
4807 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4809 return square_color;
4812 void DrawSquare(row, column, piece, do_flash)
4813 int row, column, do_flash;
4816 int square_color, x, y, direction, font_ascent, font_descent;
4819 XCharStruct overall;
4823 /* Calculate delay in milliseconds (2-delays per complete flash) */
4824 flash_delay = 500 / appData.flashRate;
4827 x = lineGap + ((BOARD_WIDTH-1)-column) *
4828 (squareSize + lineGap);
4829 y = lineGap + row * (squareSize + lineGap);
4831 x = lineGap + column * (squareSize + lineGap);
4832 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4833 (squareSize + lineGap);
4836 square_color = SquareColor(row, column);
4838 if ( // [HGM] holdings: blank out area between board and holdings
4839 column == BOARD_LEFT-1 || column == BOARD_RGHT
4840 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4841 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4842 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4844 // [HGM] print piece counts next to holdings
4845 string[1] = NULLCHAR;
4846 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4847 string[0] = '0' + piece;
4848 XTextExtents(countFontStruct, string, 1, &direction,
4849 &font_ascent, &font_descent, &overall);
4850 if (appData.monoMode) {
4851 XDrawImageString(xDisplay, xBoardWindow, countGC,
4852 x + squareSize - overall.width - 2,
4853 y + font_ascent + 1, string, 1);
4855 XDrawString(xDisplay, xBoardWindow, countGC,
4856 x + squareSize - overall.width - 2,
4857 y + font_ascent + 1, string, 1);
4860 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4861 string[0] = '0' + piece;
4862 XTextExtents(countFontStruct, string, 1, &direction,
4863 &font_ascent, &font_descent, &overall);
4864 if (appData.monoMode) {
4865 XDrawImageString(xDisplay, xBoardWindow, countGC,
4866 x + 2, y + font_ascent + 1, string, 1);
4868 XDrawString(xDisplay, xBoardWindow, countGC,
4869 x + 2, y + font_ascent + 1, string, 1);
4873 if (piece == EmptySquare || appData.blindfold) {
4874 BlankSquare(x, y, square_color, piece, xBoardWindow);
4876 drawfunc = ChooseDrawFunc();
4877 if (do_flash && appData.flashCount > 0) {
4878 for (i=0; i<appData.flashCount; ++i) {
4880 drawfunc(piece, square_color, x, y, xBoardWindow);
4881 XSync(xDisplay, False);
4882 do_flash_delay(flash_delay);
4884 BlankSquare(x, y, square_color, piece, xBoardWindow);
4885 XSync(xDisplay, False);
4886 do_flash_delay(flash_delay);
4889 drawfunc(piece, square_color, x, y, xBoardWindow);
4893 string[1] = NULLCHAR;
4894 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4895 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4896 string[0] = 'a' + column - BOARD_LEFT;
4897 XTextExtents(coordFontStruct, string, 1, &direction,
4898 &font_ascent, &font_descent, &overall);
4899 if (appData.monoMode) {
4900 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4901 x + squareSize - overall.width - 2,
4902 y + squareSize - font_descent - 1, string, 1);
4904 XDrawString(xDisplay, xBoardWindow, coordGC,
4905 x + squareSize - overall.width - 2,
4906 y + squareSize - font_descent - 1, string, 1);
4909 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4910 string[0] = ONE + row;
4911 XTextExtents(coordFontStruct, string, 1, &direction,
4912 &font_ascent, &font_descent, &overall);
4913 if (appData.monoMode) {
4914 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4915 x + 2, y + font_ascent + 1, string, 1);
4917 XDrawString(xDisplay, xBoardWindow, coordGC,
4918 x + 2, y + font_ascent + 1, string, 1);
4924 /* Why is this needed on some versions of X? */
4925 void EventProc(widget, unused, event)
4930 if (!XtIsRealized(widget))
4933 switch (event->type) {
4935 if (event->xexpose.count > 0) return; /* no clipping is done */
4936 XDrawPosition(widget, True, NULL);
4944 void DrawPosition(fullRedraw, board)
4945 /*Boolean*/int fullRedraw;
4948 XDrawPosition(boardWidget, fullRedraw, board);
4951 /* Returns 1 if there are "too many" differences between b1 and b2
4952 (i.e. more than 1 move was made) */
4953 static int too_many_diffs(b1, b2)
4959 for (i=0; i<BOARD_HEIGHT; ++i) {
4960 for (j=0; j<BOARD_WIDTH; ++j) {
4961 if (b1[i][j] != b2[i][j]) {
4962 if (++c > 4) /* Castling causes 4 diffs */
4971 /* Matrix describing castling maneuvers */
4972 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4973 static int castling_matrix[4][5] = {
4974 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4975 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4976 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4977 { 7, 7, 4, 5, 6 } /* 0-0, black */
4980 /* Checks whether castling occurred. If it did, *rrow and *rcol
4981 are set to the destination (row,col) of the rook that moved.
4983 Returns 1 if castling occurred, 0 if not.
4985 Note: Only handles a max of 1 castling move, so be sure
4986 to call too_many_diffs() first.
4988 static int check_castle_draw(newb, oldb, rrow, rcol)
4995 /* For each type of castling... */
4996 for (i=0; i<4; ++i) {
4997 r = castling_matrix[i];
4999 /* Check the 4 squares involved in the castling move */
5001 for (j=1; j<=4; ++j) {
5002 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
5009 /* All 4 changed, so it must be a castling move */
5018 static int damage[BOARD_SIZE][BOARD_SIZE];
5021 * event handler for redrawing the board
5023 void XDrawPosition(w, repaint, board)
5025 /*Boolean*/int repaint;
5029 static int lastFlipView = 0;
5030 static int lastBoardValid = 0;
5031 static Board lastBoard;
5035 if (board == NULL) {
5036 if (!lastBoardValid) return;
5039 if (!lastBoardValid || lastFlipView != flipView) {
5040 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5041 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5046 * It would be simpler to clear the window with XClearWindow()
5047 * but this causes a very distracting flicker.
5050 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5052 /* If too much changes (begin observing new game, etc.), don't
5054 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5056 /* Special check for castling so we don't flash both the king
5057 and the rook (just flash the king). */
5059 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5060 /* Draw rook with NO flashing. King will be drawn flashing later */
5061 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5062 lastBoard[rrow][rcol] = board[rrow][rcol];
5066 /* First pass -- Draw (newly) empty squares and repair damage.
5067 This prevents you from having a piece show up twice while it
5068 is flashing on its new square */
5069 for (i = 0; i < BOARD_HEIGHT; i++)
5070 for (j = 0; j < BOARD_WIDTH; j++)
5071 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5073 DrawSquare(i, j, board[i][j], 0);
5074 damage[i][j] = False;
5077 /* Second pass -- Draw piece(s) in new position and flash them */
5078 for (i = 0; i < BOARD_HEIGHT; i++)
5079 for (j = 0; j < BOARD_WIDTH; j++)
5080 if (board[i][j] != lastBoard[i][j]) {
5081 DrawSquare(i, j, board[i][j], do_flash);
5085 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5086 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5088 for (i = 0; i < BOARD_HEIGHT; i++)
5089 for (j = 0; j < BOARD_WIDTH; j++) {
5090 DrawSquare(i, j, board[i][j], 0);
5091 damage[i][j] = False;
5095 CopyBoard(lastBoard, board);
5097 lastFlipView = flipView;
5099 /* Draw highlights */
5100 if (pm1X >= 0 && pm1Y >= 0) {
5101 drawHighlight(pm1X, pm1Y, prelineGC);
5103 if (pm2X >= 0 && pm2Y >= 0) {
5104 drawHighlight(pm2X, pm2Y, prelineGC);
5106 if (hi1X >= 0 && hi1Y >= 0) {
5107 drawHighlight(hi1X, hi1Y, highlineGC);
5109 if (hi2X >= 0 && hi2Y >= 0) {
5110 drawHighlight(hi2X, hi2Y, highlineGC);
5113 /* If piece being dragged around board, must redraw that too */
5116 XSync(xDisplay, False);
5121 * event handler for redrawing the board
5123 void DrawPositionProc(w, event, prms, nprms)
5129 XDrawPosition(w, True, NULL);
5134 * event handler for parsing user moves
5136 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5137 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5138 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5139 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5140 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5141 // and at the end FinishMove() to perform the move after optional promotion popups.
5142 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5143 void HandleUserMove(w, event, prms, nprms)
5149 if (w != boardWidget || errorExitStatus != -1) return;
5152 if (event->type == ButtonPress) {
5153 XtPopdown(promotionShell);
5154 XtDestroyWidget(promotionShell);
5155 promotionUp = False;
5163 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
5164 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
5165 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
5168 void AnimateUserMove (Widget w, XEvent * event,
5169 String * params, Cardinal * nParams)
5171 DragPieceMove(event->xmotion.x, event->xmotion.y);
5174 Widget CommentCreate(name, text, mutable, callback, lines)
5176 int /*Boolean*/ mutable;
5177 XtCallbackProc callback;
5181 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5186 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5187 XtGetValues(boardWidget, args, j);
5190 XtSetArg(args[j], XtNresizable, True); j++;
5193 XtCreatePopupShell(name, topLevelShellWidgetClass,
5194 shellWidget, args, j);
5197 XtCreatePopupShell(name, transientShellWidgetClass,
5198 shellWidget, args, j);
5201 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5202 layoutArgs, XtNumber(layoutArgs));
5204 XtCreateManagedWidget("form", formWidgetClass, layout,
5205 formArgs, XtNumber(formArgs));
5209 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5210 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5212 XtSetArg(args[j], XtNstring, text); j++;
5213 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5214 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5215 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5216 XtSetArg(args[j], XtNright, XtChainRight); j++;
5217 XtSetArg(args[j], XtNresizable, True); j++;
5218 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5219 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5220 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5221 XtSetArg(args[j], XtNautoFill, True); j++;
5222 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5224 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5228 XtSetArg(args[j], XtNfromVert, edit); j++;
5229 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5230 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5231 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5232 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5234 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5235 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5238 XtSetArg(args[j], XtNfromVert, edit); j++;
5239 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5240 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5241 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5242 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5243 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5245 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5246 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5249 XtSetArg(args[j], XtNfromVert, edit); j++;
5250 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5251 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5252 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5253 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5254 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5256 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5257 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5260 XtSetArg(args[j], XtNfromVert, edit); 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(_("close"), commandWidgetClass, form, args, j);
5267 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5270 XtSetArg(args[j], XtNfromVert, edit); j++;
5271 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5272 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5273 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5274 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5275 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5277 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5278 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5281 XtRealizeWidget(shell);
5283 if (commentX == -1) {
5286 Dimension pw_height;
5287 Dimension ew_height;
5290 XtSetArg(args[j], XtNheight, &ew_height); j++;
5291 XtGetValues(edit, args, j);
5294 XtSetArg(args[j], XtNheight, &pw_height); j++;
5295 XtGetValues(shell, args, j);
5296 commentH = pw_height + (lines - 1) * ew_height;
5297 commentW = bw_width - 16;
5299 XSync(xDisplay, False);
5301 /* This code seems to tickle an X bug if it is executed too soon
5302 after xboard starts up. The coordinates get transformed as if
5303 the main window was positioned at (0, 0).
5305 XtTranslateCoords(shellWidget,
5306 (bw_width - commentW) / 2, 0 - commentH / 2,
5307 &commentX, &commentY);
5309 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5310 RootWindowOfScreen(XtScreen(shellWidget)),
5311 (bw_width - commentW) / 2, 0 - commentH / 2,
5316 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5319 XtSetArg(args[j], XtNheight, commentH); j++;
5320 XtSetArg(args[j], XtNwidth, commentW); j++;
5321 XtSetArg(args[j], XtNx, commentX); j++;
5322 XtSetArg(args[j], XtNy, commentY); j++;
5323 XtSetValues(shell, args, j);
5324 XtSetKeyboardFocus(shell, edit);
5329 /* Used for analysis window and ICS input window */
5330 Widget MiscCreate(name, text, mutable, callback, lines)
5332 int /*Boolean*/ mutable;
5333 XtCallbackProc callback;
5337 Widget shell, layout, form, edit;
5339 Dimension bw_width, pw_height, ew_height, w, h;
5345 XtSetArg(args[j], XtNresizable, True); j++;
5348 XtCreatePopupShell(name, topLevelShellWidgetClass,
5349 shellWidget, args, j);
5352 XtCreatePopupShell(name, transientShellWidgetClass,
5353 shellWidget, args, j);
5356 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5357 layoutArgs, XtNumber(layoutArgs));
5359 XtCreateManagedWidget("form", formWidgetClass, layout,
5360 formArgs, XtNumber(formArgs));
5364 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5365 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5367 XtSetArg(args[j], XtNstring, text); j++;
5368 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5369 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5370 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5371 XtSetArg(args[j], XtNright, XtChainRight); j++;
5372 XtSetArg(args[j], XtNresizable, True); j++;
5373 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5374 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5375 XtSetArg(args[j], XtNautoFill, True); j++;
5376 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5378 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5380 XtRealizeWidget(shell);
5383 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5384 XtGetValues(boardWidget, args, j);
5387 XtSetArg(args[j], XtNheight, &ew_height); j++;
5388 XtGetValues(edit, args, j);
5391 XtSetArg(args[j], XtNheight, &pw_height); j++;
5392 XtGetValues(shell, args, j);
5393 h = pw_height + (lines - 1) * ew_height;
5396 XSync(xDisplay, False);
5398 /* This code seems to tickle an X bug if it is executed too soon
5399 after xboard starts up. The coordinates get transformed as if
5400 the main window was positioned at (0, 0).
5402 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5404 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5405 RootWindowOfScreen(XtScreen(shellWidget)),
5406 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5410 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5413 XtSetArg(args[j], XtNheight, h); j++;
5414 XtSetArg(args[j], XtNwidth, w); j++;
5415 XtSetArg(args[j], XtNx, x); j++;
5416 XtSetArg(args[j], XtNy, y); j++;
5417 XtSetValues(shell, args, j);
5423 static int savedIndex; /* gross that this is global */
5425 void EditCommentPopUp(index, title, text)
5434 if (text == NULL) text = "";
5436 if (editShell == NULL) {
5438 CommentCreate(title, text, True, EditCommentCallback, 4);
5439 XtRealizeWidget(editShell);
5440 CatchDeleteWindow(editShell, "EditCommentPopDown");
5442 edit = XtNameToWidget(editShell, "*form.text");
5444 XtSetArg(args[j], XtNstring, text); j++;
5445 XtSetValues(edit, args, j);
5447 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5448 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5449 XtSetValues(editShell, args, j);
5452 XtPopup(editShell, XtGrabNone);
5456 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5457 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5461 void EditCommentCallback(w, client_data, call_data)
5463 XtPointer client_data, call_data;
5471 XtSetArg(args[j], XtNlabel, &name); j++;
5472 XtGetValues(w, args, j);
5474 if (strcmp(name, _("ok")) == 0) {
5475 edit = XtNameToWidget(editShell, "*form.text");
5477 XtSetArg(args[j], XtNstring, &val); j++;
5478 XtGetValues(edit, args, j);
5479 ReplaceComment(savedIndex, val);
5480 EditCommentPopDown();
5481 } else if (strcmp(name, _("cancel")) == 0) {
5482 EditCommentPopDown();
5483 } else if (strcmp(name, _("clear")) == 0) {
5484 edit = XtNameToWidget(editShell, "*form.text");
5485 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5486 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5490 void EditCommentPopDown()
5495 if (!editUp) return;
5497 XtSetArg(args[j], XtNx, &commentX); j++;
5498 XtSetArg(args[j], XtNy, &commentY); j++;
5499 XtSetArg(args[j], XtNheight, &commentH); j++;
5500 XtSetArg(args[j], XtNwidth, &commentW); j++;
5501 XtGetValues(editShell, args, j);
5502 XtPopdown(editShell);
5505 XtSetArg(args[j], XtNleftBitmap, None); j++;
5506 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5510 void ICSInputBoxPopUp()
5515 char *title = _("ICS Input");
5518 if (ICSInputShell == NULL) {
5519 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5520 tr = XtParseTranslationTable(ICSInputTranslations);
5521 edit = XtNameToWidget(ICSInputShell, "*form.text");
5522 XtOverrideTranslations(edit, tr);
5523 XtRealizeWidget(ICSInputShell);
5524 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5527 edit = XtNameToWidget(ICSInputShell, "*form.text");
5529 XtSetArg(args[j], XtNstring, ""); j++;
5530 XtSetValues(edit, args, j);
5532 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5533 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5534 XtSetValues(ICSInputShell, args, j);
5537 XtPopup(ICSInputShell, XtGrabNone);
5538 XtSetKeyboardFocus(ICSInputShell, edit);
5540 ICSInputBoxUp = True;
5542 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5543 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5547 void ICSInputSendText()
5554 edit = XtNameToWidget(ICSInputShell, "*form.text");
5556 XtSetArg(args[j], XtNstring, &val); j++;
5557 XtGetValues(edit, args, j);
5558 SendMultiLineToICS(val);
5559 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5560 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5563 void ICSInputBoxPopDown()
5568 if (!ICSInputBoxUp) return;
5570 XtPopdown(ICSInputShell);
5571 ICSInputBoxUp = False;
5573 XtSetArg(args[j], XtNleftBitmap, None); j++;
5574 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5578 void CommentPopUp(title, text)
5585 if (commentShell == NULL) {
5587 CommentCreate(title, text, False, CommentCallback, 4);
5588 XtRealizeWidget(commentShell);
5589 CatchDeleteWindow(commentShell, "CommentPopDown");
5591 edit = XtNameToWidget(commentShell, "*form.text");
5593 XtSetArg(args[j], XtNstring, text); j++;
5594 XtSetValues(edit, args, j);
5596 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5597 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5598 XtSetValues(commentShell, args, j);
5601 XtPopup(commentShell, XtGrabNone);
5602 XSync(xDisplay, False);
5607 void CommentCallback(w, client_data, call_data)
5609 XtPointer client_data, call_data;
5616 XtSetArg(args[j], XtNlabel, &name); j++;
5617 XtGetValues(w, args, j);
5619 if (strcmp(name, _("close")) == 0) {
5621 } else if (strcmp(name, _("edit")) == 0) {
5628 void CommentPopDown()
5633 if (!commentUp) return;
5635 XtSetArg(args[j], XtNx, &commentX); j++;
5636 XtSetArg(args[j], XtNy, &commentY); j++;
5637 XtSetArg(args[j], XtNwidth, &commentW); j++;
5638 XtSetArg(args[j], XtNheight, &commentH); j++;
5639 XtGetValues(commentShell, args, j);
5640 XtPopdown(commentShell);
5641 XSync(xDisplay, False);
5645 void FileNamePopUp(label, def, proc, openMode)
5652 Widget popup, layout, dialog, edit;
5658 fileProc = proc; /* I can't see a way not */
5659 fileOpenMode = openMode; /* to use globals here */
5662 XtSetArg(args[i], XtNresizable, True); i++;
5663 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5664 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5665 fileNameShell = popup =
5666 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5667 shellWidget, args, i);
5670 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5671 layoutArgs, XtNumber(layoutArgs));
5674 XtSetArg(args[i], XtNlabel, label); i++;
5675 XtSetArg(args[i], XtNvalue, def); i++;
5676 XtSetArg(args[i], XtNborderWidth, 0); i++;
5677 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5680 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5681 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5682 (XtPointer) dialog);
5684 XtRealizeWidget(popup);
5685 CatchDeleteWindow(popup, "FileNamePopDown");
5687 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5688 &x, &y, &win_x, &win_y, &mask);
5690 XtSetArg(args[0], XtNx, x - 10);
5691 XtSetArg(args[1], XtNy, y - 30);
5692 XtSetValues(popup, args, 2);
5694 XtPopup(popup, XtGrabExclusive);
5697 edit = XtNameToWidget(dialog, "*value");
5698 XtSetKeyboardFocus(popup, edit);
5701 void FileNamePopDown()
5703 if (!filenameUp) return;
5704 XtPopdown(fileNameShell);
5705 XtDestroyWidget(fileNameShell);
5710 void FileNameCallback(w, client_data, call_data)
5712 XtPointer client_data, call_data;
5717 XtSetArg(args[0], XtNlabel, &name);
5718 XtGetValues(w, args, 1);
5720 if (strcmp(name, _("cancel")) == 0) {
5725 FileNameAction(w, NULL, NULL, NULL);
5728 void FileNameAction(w, event, prms, nprms)
5740 name = XawDialogGetValueString(w = XtParent(w));
5742 if ((name != NULL) && (*name != NULLCHAR)) {
5744 XtPopdown(w = XtParent(XtParent(w)));
5748 p = strrchr(buf, ' ');
5755 fullname = ExpandPathName(buf);
5757 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5760 f = fopen(fullname, fileOpenMode);
5762 DisplayError(_("Failed to open file"), errno);
5764 (void) (*fileProc)(f, index, buf);
5771 XtPopdown(w = XtParent(XtParent(w)));
5777 void PromotionPopUp()
5780 Widget dialog, layout;
5782 Dimension bw_width, pw_width;
5786 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5787 XtGetValues(boardWidget, args, j);
5790 XtSetArg(args[j], XtNresizable, True); j++;
5791 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5793 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5794 shellWidget, args, j);
5796 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5797 layoutArgs, XtNumber(layoutArgs));
5800 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5801 XtSetArg(args[j], XtNborderWidth, 0); j++;
5802 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5805 if(gameInfo.variant != VariantShogi) {
5806 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5807 (XtPointer) dialog);
5808 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5809 (XtPointer) dialog);
5810 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5811 (XtPointer) dialog);
5812 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5813 (XtPointer) dialog);
5814 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5815 gameInfo.variant == VariantGiveaway) {
5816 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5817 (XtPointer) dialog);
5819 if(gameInfo.variant == VariantCapablanca ||
5820 gameInfo.variant == VariantGothic ||
5821 gameInfo.variant == VariantCapaRandom) {
5822 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
5823 (XtPointer) dialog);
5824 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
5825 (XtPointer) dialog);
5827 } else // [HGM] shogi
5829 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
5830 (XtPointer) dialog);
5831 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
5832 (XtPointer) dialog);
5834 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5835 (XtPointer) dialog);
5837 XtRealizeWidget(promotionShell);
5838 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5841 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5842 XtGetValues(promotionShell, args, j);
5844 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5845 lineGap + squareSize/3 +
5846 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
5847 0 : 6*(squareSize + lineGap)), &x, &y);
5850 XtSetArg(args[j], XtNx, x); j++;
5851 XtSetArg(args[j], XtNy, y); j++;
5852 XtSetValues(promotionShell, args, j);
5854 XtPopup(promotionShell, XtGrabNone);
5859 void PromotionPopDown()
5861 if (!promotionUp) return;
5862 XtPopdown(promotionShell);
5863 XtDestroyWidget(promotionShell);
5864 promotionUp = False;
5867 void PromotionCallback(w, client_data, call_data)
5869 XtPointer client_data, call_data;
5875 XtSetArg(args[0], XtNlabel, &name);
5876 XtGetValues(w, args, 1);
5880 if (fromX == -1) return;
5882 if (strcmp(name, _("cancel")) == 0) {
5886 } else if (strcmp(name, _("Knight")) == 0) {
5888 } else if (strcmp(name, _("Promote")) == 0) {
5890 } else if (strcmp(name, _("Defer")) == 0) {
5893 promoChar = ToLower(name[0]);
5896 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5898 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5899 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5904 void ErrorCallback(w, client_data, call_data)
5906 XtPointer client_data, call_data;
5909 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5911 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5917 if (!errorUp) return;
5919 XtPopdown(errorShell);
5920 XtDestroyWidget(errorShell);
5921 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5924 void ErrorPopUp(title, label, modal)
5925 char *title, *label;
5929 Widget dialog, layout;
5933 Dimension bw_width, pw_width;
5934 Dimension pw_height;
5938 XtSetArg(args[i], XtNresizable, True); i++;
5939 XtSetArg(args[i], XtNtitle, title); i++;
5941 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5942 shellWidget, args, i);
5944 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5945 layoutArgs, XtNumber(layoutArgs));
5948 XtSetArg(args[i], XtNlabel, label); i++;
5949 XtSetArg(args[i], XtNborderWidth, 0); i++;
5950 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5953 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5955 XtRealizeWidget(errorShell);
5956 CatchDeleteWindow(errorShell, "ErrorPopDown");
5959 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5960 XtGetValues(boardWidget, args, i);
5962 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5963 XtSetArg(args[i], XtNheight, &pw_height); i++;
5964 XtGetValues(errorShell, args, i);
5967 /* This code seems to tickle an X bug if it is executed too soon
5968 after xboard starts up. The coordinates get transformed as if
5969 the main window was positioned at (0, 0).
5971 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5972 0 - pw_height + squareSize / 3, &x, &y);
5974 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5975 RootWindowOfScreen(XtScreen(boardWidget)),
5976 (bw_width - pw_width) / 2,
5977 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5981 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5984 XtSetArg(args[i], XtNx, x); i++;
5985 XtSetArg(args[i], XtNy, y); i++;
5986 XtSetValues(errorShell, args, i);
5989 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5992 /* Disable all user input other than deleting the window */
5993 static int frozen = 0;
5997 /* Grab by a widget that doesn't accept input */
5998 XtAddGrab(messageWidget, TRUE, FALSE);
6002 /* Undo a FreezeUI */
6005 if (!frozen) return;
6006 XtRemoveGrab(messageWidget);
6010 char *ModeToWidgetName(mode)
6014 case BeginningOfGame:
6015 if (appData.icsActive)
6016 return "menuMode.ICS Client";
6017 else if (appData.noChessProgram ||
6018 *appData.cmailGameName != NULLCHAR)
6019 return "menuMode.Edit Game";
6021 return "menuMode.Machine Black";
6022 case MachinePlaysBlack:
6023 return "menuMode.Machine Black";
6024 case MachinePlaysWhite:
6025 return "menuMode.Machine White";
6027 return "menuMode.Analysis Mode";
6029 return "menuMode.Analyze File";
6030 case TwoMachinesPlay:
6031 return "menuMode.Two Machines";
6033 return "menuMode.Edit Game";
6034 case PlayFromGameFile:
6035 return "menuFile.Load Game";
6037 return "menuMode.Edit Position";
6039 return "menuMode.Training";
6040 case IcsPlayingWhite:
6041 case IcsPlayingBlack:
6045 return "menuMode.ICS Client";
6052 void ModeHighlight()
6055 static int oldPausing = FALSE;
6056 static GameMode oldmode = (GameMode) -1;
6059 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6061 if (pausing != oldPausing) {
6062 oldPausing = pausing;
6064 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6066 XtSetArg(args[0], XtNleftBitmap, None);
6068 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6071 if (appData.showButtonBar) {
6072 /* Always toggle, don't set. Previous code messes up when
6073 invoked while the button is pressed, as releasing it
6074 toggles the state again. */
6077 XtSetArg(args[0], XtNbackground, &oldbg);
6078 XtSetArg(args[1], XtNforeground, &oldfg);
6079 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6081 XtSetArg(args[0], XtNbackground, oldfg);
6082 XtSetArg(args[1], XtNforeground, oldbg);
6084 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6088 wname = ModeToWidgetName(oldmode);
6089 if (wname != NULL) {
6090 XtSetArg(args[0], XtNleftBitmap, None);
6091 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6093 wname = ModeToWidgetName(gameMode);
6094 if (wname != NULL) {
6095 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6096 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6100 /* Maybe all the enables should be handled here, not just this one */
6101 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6102 gameMode == Training || gameMode == PlayFromGameFile);
6107 * Button/menu procedures
6109 void ResetProc(w, event, prms, nprms)
6118 int LoadGamePopUp(f, gameNumber, title)
6123 cmailMsgLoaded = FALSE;
6124 if (gameNumber == 0) {
6125 int error = GameListBuild(f);
6127 DisplayError(_("Cannot build game list"), error);
6128 } else if (!ListEmpty(&gameList) &&
6129 ((ListGame *) gameList.tailPred)->number > 1) {
6130 GameListPopUp(f, title);
6136 return LoadGame(f, gameNumber, title, FALSE);
6139 void LoadGameProc(w, event, prms, nprms)
6145 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6148 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6151 void LoadNextGameProc(w, event, prms, nprms)
6160 void LoadPrevGameProc(w, event, prms, nprms)
6169 void ReloadGameProc(w, event, prms, nprms)
6178 void LoadNextPositionProc(w, event, prms, nprms)
6187 void LoadPrevPositionProc(w, event, prms, nprms)
6196 void ReloadPositionProc(w, event, prms, nprms)
6205 void LoadPositionProc(w, event, prms, nprms)
6211 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6214 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6217 void SaveGameProc(w, event, prms, nprms)
6223 FileNamePopUp(_("Save game file name?"),
6224 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6228 void SavePositionProc(w, event, prms, nprms)
6234 FileNamePopUp(_("Save position file name?"),
6235 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6239 void ReloadCmailMsgProc(w, event, prms, nprms)
6245 ReloadCmailMsgEvent(FALSE);
6248 void MailMoveProc(w, event, prms, nprms)
6257 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6258 static char *selected_fen_position=NULL;
6261 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6262 Atom *type_return, XtPointer *value_return,
6263 unsigned long *length_return, int *format_return)
6265 char *selection_tmp;
6267 if (!selected_fen_position) return False; /* should never happen */
6268 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
6269 /* note: since no XtSelectionDoneProc was registered, Xt will
6270 * automatically call XtFree on the value returned. So have to
6271 * make a copy of it allocated with XtMalloc */
6272 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6273 strcpy(selection_tmp, selected_fen_position);
6275 *value_return=selection_tmp;
6276 *length_return=strlen(selection_tmp);
6277 *type_return=*target;
6278 *format_return = 8; /* bits per byte */
6280 } else if (*target == XA_TARGETS(xDisplay)) {
6281 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
6282 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
6283 targets_tmp[1] = XA_STRING;
6284 *value_return = targets_tmp;
6285 *type_return = XA_ATOM;
6287 *format_return = 8 * sizeof(Atom);
6288 if (*format_return > 32) {
6289 *length_return *= *format_return / 32;
6290 *format_return = 32;
6298 /* note: when called from menu all parameters are NULL, so no clue what the
6299 * Widget which was clicked on was, or what the click event was
6301 void CopyPositionProc(w, event, prms, nprms)
6308 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
6309 * have a notion of a position that is selected but not copied.
6310 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
6312 if(gameMode == EditPosition) EditPositionDone(TRUE);
6313 if (selected_fen_position) free(selected_fen_position);
6314 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6315 if (!selected_fen_position) return;
6316 XtOwnSelection(menuBarWidget, XA_PRIMARY,
6318 SendPositionSelection,
6319 NULL/* lose_ownership_proc */ ,
6320 NULL/* transfer_done_proc */);
6321 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
6323 SendPositionSelection,
6324 NULL/* lose_ownership_proc */ ,
6325 NULL/* transfer_done_proc */);
6328 /* function called when the data to Paste is ready */
6330 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6331 Atom *type, XtPointer value, unsigned long *len, int *format)
6334 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6335 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6336 EditPositionPasteFEN(fenstr);
6340 /* called when Paste Position button is pressed,
6341 * all parameters will be NULL */
6342 void PastePositionProc(w, event, prms, nprms)
6348 XtGetSelectionValue(menuBarWidget,
6349 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
6350 /* (XtSelectionCallbackProc) */ PastePositionCB,
6351 NULL, /* client_data passed to PastePositionCB */
6353 /* better to use the time field from the event that triggered the
6354 * call to this function, but that isn't trivial to get
6362 SendGameSelection(Widget w, Atom *selection, Atom *target,
6363 Atom *type_return, XtPointer *value_return,
6364 unsigned long *length_return, int *format_return)
6366 char *selection_tmp;
6368 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
6369 FILE* f = fopen(gameCopyFilename, "r");
6372 if (f == NULL) return False;
6376 selection_tmp = XtMalloc(len + 1);
6377 count = fread(selection_tmp, 1, len, f);
6379 XtFree(selection_tmp);
6382 selection_tmp[len] = NULLCHAR;
6383 *value_return = selection_tmp;
6384 *length_return = len;
6385 *type_return = *target;
6386 *format_return = 8; /* bits per byte */
6388 } else if (*target == XA_TARGETS(xDisplay)) {
6389 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
6390 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
6391 targets_tmp[1] = XA_STRING;
6392 *value_return = targets_tmp;
6393 *type_return = XA_ATOM;
6395 *format_return = 8 * sizeof(Atom);
6396 if (*format_return > 32) {
6397 *length_return *= *format_return / 32;
6398 *format_return = 32;
6406 /* note: when called from menu all parameters are NULL, so no clue what the
6407 * Widget which was clicked on was, or what the click event was
6409 void CopyGameProc(w, event, prms, nprms)
6417 ret = SaveGameToFile(gameCopyFilename, FALSE);
6421 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
6422 * have a notion of a game that is selected but not copied.
6423 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
6425 XtOwnSelection(menuBarWidget, XA_PRIMARY,
6428 NULL/* lose_ownership_proc */ ,
6429 NULL/* transfer_done_proc */);
6430 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
6433 NULL/* lose_ownership_proc */ ,
6434 NULL/* transfer_done_proc */);
6437 /* function called when the data to Paste is ready */
6439 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6440 Atom *type, XtPointer value, unsigned long *len, int *format)
6443 if (value == NULL || *len == 0) {
6444 return; /* nothing had been selected to copy */
6446 f = fopen(gamePasteFilename, "w");
6448 DisplayError(_("Can't open temp file"), errno);
6451 fwrite(value, 1, *len, f);
6454 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6457 /* called when Paste Game button is pressed,
6458 * all parameters will be NULL */
6459 void PasteGameProc(w, event, prms, nprms)
6465 XtGetSelectionValue(menuBarWidget,
6466 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
6467 /* (XtSelectionCallbackProc) */ PasteGameCB,
6468 NULL, /* client_data passed to PasteGameCB */
6470 /* better to use the time field from the event that triggered the
6471 * call to this function, but that isn't trivial to get
6481 SaveGameProc(NULL, NULL, NULL, NULL);
6485 void QuitProc(w, event, prms, nprms)
6494 void PauseProc(w, event, prms, nprms)
6504 void MachineBlackProc(w, event, prms, nprms)
6510 MachineBlackEvent();
6513 void MachineWhiteProc(w, event, prms, nprms)
6519 MachineWhiteEvent();
6522 void AnalyzeModeProc(w, event, prms, nprms)
6530 if (!first.analysisSupport) {
6531 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6532 DisplayError(buf, 0);
6535 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6536 if (appData.icsActive) {
6537 if (gameMode != IcsObserving) {
6538 sprintf(buf,_("You are not observing a game"));
6539 DisplayError(buf, 0);
6541 if (appData.icsEngineAnalyze) {
6542 if (appData.debugMode)
6543 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6549 /* if enable, use want disable icsEngineAnalyze */
6550 if (appData.icsEngineAnalyze) {
6555 appData.icsEngineAnalyze = TRUE;
6556 if (appData.debugMode)
6557 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6559 if (!appData.showThinking)
6560 ShowThinkingProc(w,event,prms,nprms);
6565 void AnalyzeFileProc(w, event, prms, nprms)
6571 if (!first.analysisSupport) {
6573 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6574 DisplayError(buf, 0);
6579 if (!appData.showThinking)
6580 ShowThinkingProc(w,event,prms,nprms);
6583 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6584 AnalysisPeriodicEvent(1);
6587 void TwoMachinesProc(w, event, prms, nprms)
6596 void IcsClientProc(w, event, prms, nprms)
6605 void EditGameProc(w, event, prms, nprms)
6614 void EditPositionProc(w, event, prms, nprms)
6620 EditPositionEvent();
6623 void TrainingProc(w, event, prms, nprms)
6632 void EditCommentProc(w, event, prms, nprms)
6639 EditCommentPopDown();
6645 void IcsInputBoxProc(w, event, prms, nprms)
6651 if (ICSInputBoxUp) {
6652 ICSInputBoxPopDown();
6658 void AcceptProc(w, event, prms, nprms)
6667 void DeclineProc(w, event, prms, nprms)
6676 void RematchProc(w, event, prms, nprms)
6685 void CallFlagProc(w, event, prms, nprms)
6694 void DrawProc(w, event, prms, nprms)
6703 void AbortProc(w, event, prms, nprms)
6712 void AdjournProc(w, event, prms, nprms)
6721 void ResignProc(w, event, prms, nprms)
6730 void AdjuWhiteProc(w, event, prms, nprms)
6736 UserAdjudicationEvent(+1);
6739 void AdjuBlackProc(w, event, prms, nprms)
6745 UserAdjudicationEvent(-1);
6748 void AdjuDrawProc(w, event, prms, nprms)
6754 UserAdjudicationEvent(0);
6757 void EnterKeyProc(w, event, prms, nprms)
6763 if (ICSInputBoxUp == True)
6767 void StopObservingProc(w, event, prms, nprms)
6773 StopObservingEvent();
6776 void StopExaminingProc(w, event, prms, nprms)
6782 StopExaminingEvent();
6786 void ForwardProc(w, event, prms, nprms)
6796 void BackwardProc(w, event, prms, nprms)
6805 void ToStartProc(w, event, prms, nprms)
6814 void ToEndProc(w, event, prms, nprms)
6823 void RevertProc(w, event, prms, nprms)
6832 void TruncateGameProc(w, event, prms, nprms)
6838 TruncateGameEvent();
6840 void RetractMoveProc(w, event, prms, nprms)
6849 void MoveNowProc(w, event, prms, nprms)
6859 void AlwaysQueenProc(w, event, prms, nprms)
6867 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6869 if (appData.alwaysPromoteToQueen) {
6870 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6872 XtSetArg(args[0], XtNleftBitmap, None);
6874 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6878 void AnimateDraggingProc(w, event, prms, nprms)
6886 appData.animateDragging = !appData.animateDragging;
6888 if (appData.animateDragging) {
6889 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6892 XtSetArg(args[0], XtNleftBitmap, None);
6894 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6898 void AnimateMovingProc(w, event, prms, nprms)
6906 appData.animate = !appData.animate;
6908 if (appData.animate) {
6909 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6912 XtSetArg(args[0], XtNleftBitmap, None);
6914 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6918 void AutocommProc(w, event, prms, nprms)
6926 appData.autoComment = !appData.autoComment;
6928 if (appData.autoComment) {
6929 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6931 XtSetArg(args[0], XtNleftBitmap, None);
6933 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6938 void AutoflagProc(w, event, prms, nprms)
6946 appData.autoCallFlag = !appData.autoCallFlag;
6948 if (appData.autoCallFlag) {
6949 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6951 XtSetArg(args[0], XtNleftBitmap, None);
6953 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6957 void AutoflipProc(w, event, prms, nprms)
6965 appData.autoFlipView = !appData.autoFlipView;
6967 if (appData.autoFlipView) {
6968 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6970 XtSetArg(args[0], XtNleftBitmap, None);
6972 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6976 void AutobsProc(w, event, prms, nprms)
6984 appData.autoObserve = !appData.autoObserve;
6986 if (appData.autoObserve) {
6987 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6989 XtSetArg(args[0], XtNleftBitmap, None);
6991 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6995 void AutoraiseProc(w, event, prms, nprms)
7003 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7005 if (appData.autoRaiseBoard) {
7006 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7008 XtSetArg(args[0], XtNleftBitmap, None);
7010 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7014 void AutosaveProc(w, event, prms, nprms)
7022 appData.autoSaveGames = !appData.autoSaveGames;
7024 if (appData.autoSaveGames) {
7025 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7027 XtSetArg(args[0], XtNleftBitmap, None);
7029 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7033 void BlindfoldProc(w, event, prms, nprms)
7041 appData.blindfold = !appData.blindfold;
7043 if (appData.blindfold) {
7044 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7046 XtSetArg(args[0], XtNleftBitmap, None);
7048 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7051 DrawPosition(True, NULL);
7054 void TestLegalityProc(w, event, prms, nprms)
7062 appData.testLegality = !appData.testLegality;
7064 if (appData.testLegality) {
7065 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7067 XtSetArg(args[0], XtNleftBitmap, None);
7069 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7074 void FlashMovesProc(w, event, prms, nprms)
7082 if (appData.flashCount == 0) {
7083 appData.flashCount = 3;
7085 appData.flashCount = -appData.flashCount;
7088 if (appData.flashCount > 0) {
7089 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7091 XtSetArg(args[0], XtNleftBitmap, None);
7093 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7097 void FlipViewProc(w, event, prms, nprms)
7103 flipView = !flipView;
7104 DrawPosition(True, NULL);
7107 void GetMoveListProc(w, event, prms, nprms)
7115 appData.getMoveList = !appData.getMoveList;
7117 if (appData.getMoveList) {
7118 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7121 XtSetArg(args[0], XtNleftBitmap, None);
7123 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7128 void HighlightDraggingProc(w, event, prms, nprms)
7136 appData.highlightDragging = !appData.highlightDragging;
7138 if (appData.highlightDragging) {
7139 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7141 XtSetArg(args[0], XtNleftBitmap, None);
7143 XtSetValues(XtNameToWidget(menuBarWidget,
7144 "menuOptions.Highlight Dragging"), args, 1);
7148 void HighlightLastMoveProc(w, event, prms, nprms)
7156 appData.highlightLastMove = !appData.highlightLastMove;
7158 if (appData.highlightLastMove) {
7159 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7161 XtSetArg(args[0], XtNleftBitmap, None);
7163 XtSetValues(XtNameToWidget(menuBarWidget,
7164 "menuOptions.Highlight Last Move"), args, 1);
7167 void IcsAlarmProc(w, event, prms, nprms)
7175 appData.icsAlarm = !appData.icsAlarm;
7177 if (appData.icsAlarm) {
7178 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7180 XtSetArg(args[0], XtNleftBitmap, None);
7182 XtSetValues(XtNameToWidget(menuBarWidget,
7183 "menuOptions.ICS Alarm"), args, 1);
7186 void MoveSoundProc(w, event, prms, nprms)
7194 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7196 if (appData.ringBellAfterMoves) {
7197 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7199 XtSetArg(args[0], XtNleftBitmap, None);
7201 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7206 void OldSaveStyleProc(w, event, prms, nprms)
7214 appData.oldSaveStyle = !appData.oldSaveStyle;
7216 if (appData.oldSaveStyle) {
7217 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7219 XtSetArg(args[0], XtNleftBitmap, None);
7221 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7225 void PeriodicUpdatesProc(w, event, prms, nprms)
7233 PeriodicUpdatesEvent(!appData.periodicUpdates);
7235 if (appData.periodicUpdates) {
7236 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7238 XtSetArg(args[0], XtNleftBitmap, None);
7240 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7244 void PonderNextMoveProc(w, event, prms, nprms)
7252 PonderNextMoveEvent(!appData.ponderNextMove);
7254 if (appData.ponderNextMove) {
7255 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7257 XtSetArg(args[0], XtNleftBitmap, None);
7259 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7263 void PopupExitMessageProc(w, event, prms, nprms)
7271 appData.popupExitMessage = !appData.popupExitMessage;
7273 if (appData.popupExitMessage) {
7274 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7276 XtSetArg(args[0], XtNleftBitmap, None);
7278 XtSetValues(XtNameToWidget(menuBarWidget,
7279 "menuOptions.Popup Exit Message"), args, 1);
7282 void PopupMoveErrorsProc(w, event, prms, nprms)
7290 appData.popupMoveErrors = !appData.popupMoveErrors;
7292 if (appData.popupMoveErrors) {
7293 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7295 XtSetArg(args[0], XtNleftBitmap, None);
7297 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7301 void PremoveProc(w, event, prms, nprms)
7309 appData.premove = !appData.premove;
7311 if (appData.premove) {
7312 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7314 XtSetArg(args[0], XtNleftBitmap, None);
7316 XtSetValues(XtNameToWidget(menuBarWidget,
7317 "menuOptions.Premove"), args, 1);
7320 void QuietPlayProc(w, event, prms, nprms)
7328 appData.quietPlay = !appData.quietPlay;
7330 if (appData.quietPlay) {
7331 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7333 XtSetArg(args[0], XtNleftBitmap, None);
7335 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7339 void ShowCoordsProc(w, event, prms, nprms)
7347 appData.showCoords = !appData.showCoords;
7349 if (appData.showCoords) {
7350 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7352 XtSetArg(args[0], XtNleftBitmap, None);
7354 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7357 DrawPosition(True, NULL);
7360 void ShowThinkingProc(w, event, prms, nprms)
7366 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7367 ShowThinkingEvent();
7370 void HideThinkingProc(w, event, prms, nprms)
7378 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7379 ShowThinkingEvent();
7381 if (appData.hideThinkingFromHuman) {
7382 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7384 XtSetArg(args[0], XtNleftBitmap, None);
7386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7390 void InfoProc(w, event, prms, nprms)
7397 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7402 void ManProc(w, event, prms, nprms)
7410 if (nprms && *nprms > 0)
7414 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7418 void HintProc(w, event, prms, nprms)
7427 void BookProc(w, event, prms, nprms)
7436 void AboutProc(w, event, prms, nprms)
7444 char *zippy = " (with Zippy code)";
7448 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7449 programVersion, zippy,
7450 "Copyright 1991 Digital Equipment Corporation",
7451 "Enhancements Copyright 1992-2009 Free Software Foundation",
7452 "Enhancements Copyright 2005 Alessandro Scotti",
7453 PACKAGE, " is free software and carries NO WARRANTY;",
7454 "see the file COPYING for more information.");
7455 ErrorPopUp(_("About XBoard"), buf, FALSE);
7458 void DebugProc(w, event, prms, nprms)
7464 appData.debugMode = !appData.debugMode;
7467 void AboutGameProc(w, event, prms, nprms)
7476 void NothingProc(w, event, prms, nprms)
7485 void Iconify(w, event, prms, nprms)
7494 XtSetArg(args[0], XtNiconic, True);
7495 XtSetValues(shellWidget, args, 1);
7498 void DisplayMessage(message, extMessage)
7499 char *message, *extMessage;
7501 /* display a message in the message widget */
7510 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7515 message = extMessage;
7519 /* need to test if messageWidget already exists, since this function
7520 can also be called during the startup, if for example a Xresource
7521 is not set up correctly */
7524 XtSetArg(arg, XtNlabel, message);
7525 XtSetValues(messageWidget, &arg, 1);
7531 void DisplayTitle(text)
7536 char title[MSG_SIZ];
7539 if (text == NULL) text = "";
7541 if (appData.titleInWindow) {
7543 XtSetArg(args[i], XtNlabel, text); i++;
7544 XtSetValues(titleWidget, args, i);
7547 if (*text != NULLCHAR) {
7549 strcpy(title, text);
7550 } else if (appData.icsActive) {
7551 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7552 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7553 } else if (appData.cmailGameName[0] != NULLCHAR) {
7554 snprintf(icon, sizeof(icon), "%s", "CMail");
7555 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7557 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7558 } else if (gameInfo.variant == VariantGothic) {
7559 strcpy(icon, programName);
7560 strcpy(title, GOTHIC);
7563 } else if (gameInfo.variant == VariantFalcon) {
7564 strcpy(icon, programName);
7565 strcpy(title, FALCON);
7567 } else if (appData.noChessProgram) {
7568 strcpy(icon, programName);
7569 strcpy(title, programName);
7571 strcpy(icon, first.tidy);
7572 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7575 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7576 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7577 XtSetValues(shellWidget, args, i);
7581 void DisplayError(message, error)
7588 if (appData.debugMode || appData.matchMode) {
7589 fprintf(stderr, "%s: %s\n", programName, message);
7592 if (appData.debugMode || appData.matchMode) {
7593 fprintf(stderr, "%s: %s: %s\n",
7594 programName, message, strerror(error));
7596 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7599 ErrorPopUp(_("Error"), message, FALSE);
7603 void DisplayMoveError(message)
7608 DrawPosition(FALSE, NULL);
7609 if (appData.debugMode || appData.matchMode) {
7610 fprintf(stderr, "%s: %s\n", programName, message);
7612 if (appData.popupMoveErrors) {
7613 ErrorPopUp(_("Error"), message, FALSE);
7615 DisplayMessage(message, "");
7620 void DisplayFatalError(message, error, status)
7626 errorExitStatus = status;
7628 fprintf(stderr, "%s: %s\n", programName, message);
7630 fprintf(stderr, "%s: %s: %s\n",
7631 programName, message, strerror(error));
7632 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7635 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7636 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7642 void DisplayInformation(message)
7646 ErrorPopUp(_("Information"), message, TRUE);
7649 void DisplayNote(message)
7653 ErrorPopUp(_("Note"), message, FALSE);
7657 NullXErrorCheck(dpy, error_event)
7659 XErrorEvent *error_event;
7664 void DisplayIcsInteractionTitle(message)
7667 if (oldICSInteractionTitle == NULL) {
7668 /* Magic to find the old window title, adapted from vim */
7669 char *wina = getenv("WINDOWID");
7671 Window win = (Window) atoi(wina);
7672 Window root, parent, *children;
7673 unsigned int nchildren;
7674 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7676 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7677 if (!XQueryTree(xDisplay, win, &root, &parent,
7678 &children, &nchildren)) break;
7679 if (children) XFree((void *)children);
7680 if (parent == root || parent == 0) break;
7683 XSetErrorHandler(oldHandler);
7685 if (oldICSInteractionTitle == NULL) {
7686 oldICSInteractionTitle = "xterm";
7689 printf("\033]0;%s\007", message);
7693 char pendingReplyPrefix[MSG_SIZ];
7694 ProcRef pendingReplyPR;
7696 void AskQuestionProc(w, event, prms, nprms)
7703 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7707 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7710 void AskQuestionPopDown()
7712 if (!askQuestionUp) return;
7713 XtPopdown(askQuestionShell);
7714 XtDestroyWidget(askQuestionShell);
7715 askQuestionUp = False;
7718 void AskQuestionReplyAction(w, event, prms, nprms)
7728 reply = XawDialogGetValueString(w = XtParent(w));
7729 strcpy(buf, pendingReplyPrefix);
7730 if (*buf) strcat(buf, " ");
7733 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7734 AskQuestionPopDown();
7736 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7739 void AskQuestionCallback(w, client_data, call_data)
7741 XtPointer client_data, call_data;
7746 XtSetArg(args[0], XtNlabel, &name);
7747 XtGetValues(w, args, 1);
7749 if (strcmp(name, _("cancel")) == 0) {
7750 AskQuestionPopDown();
7752 AskQuestionReplyAction(w, NULL, NULL, NULL);
7756 void AskQuestion(title, question, replyPrefix, pr)
7757 char *title, *question, *replyPrefix;
7761 Widget popup, layout, dialog, edit;
7767 strcpy(pendingReplyPrefix, replyPrefix);
7768 pendingReplyPR = pr;
7771 XtSetArg(args[i], XtNresizable, True); i++;
7772 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7773 askQuestionShell = popup =
7774 XtCreatePopupShell(title, transientShellWidgetClass,
7775 shellWidget, args, i);
7778 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7779 layoutArgs, XtNumber(layoutArgs));
7782 XtSetArg(args[i], XtNlabel, question); i++;
7783 XtSetArg(args[i], XtNvalue, ""); i++;
7784 XtSetArg(args[i], XtNborderWidth, 0); i++;
7785 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7788 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7789 (XtPointer) dialog);
7790 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7791 (XtPointer) dialog);
7793 XtRealizeWidget(popup);
7794 CatchDeleteWindow(popup, "AskQuestionPopDown");
7796 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7797 &x, &y, &win_x, &win_y, &mask);
7799 XtSetArg(args[0], XtNx, x - 10);
7800 XtSetArg(args[1], XtNy, y - 30);
7801 XtSetValues(popup, args, 2);
7803 XtPopup(popup, XtGrabExclusive);
7804 askQuestionUp = True;
7806 edit = XtNameToWidget(dialog, "*value");
7807 XtSetKeyboardFocus(popup, edit);
7815 if (*name == NULLCHAR) {
7817 } else if (strcmp(name, "$") == 0) {
7818 putc(BELLCHAR, stderr);
7821 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7829 PlaySound(appData.soundMove);
7835 PlaySound(appData.soundIcsWin);
7841 PlaySound(appData.soundIcsLoss);
7847 PlaySound(appData.soundIcsDraw);
7851 PlayIcsUnfinishedSound()
7853 PlaySound(appData.soundIcsUnfinished);
7859 PlaySound(appData.soundIcsAlarm);
7865 system("stty echo");
7871 system("stty -echo");
7875 Colorize(cc, continuation)
7880 int count, outCount, error;
7882 if (textColors[(int)cc].bg > 0) {
7883 if (textColors[(int)cc].fg > 0) {
7884 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7885 textColors[(int)cc].fg, textColors[(int)cc].bg);
7887 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7888 textColors[(int)cc].bg);
7891 if (textColors[(int)cc].fg > 0) {
7892 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7893 textColors[(int)cc].fg);
7895 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7898 count = strlen(buf);
7899 outCount = OutputToProcess(NoProc, buf, count, &error);
7900 if (outCount < count) {
7901 DisplayFatalError(_("Error writing to display"), error, 1);
7904 if (continuation) return;
7907 PlaySound(appData.soundShout);
7910 PlaySound(appData.soundSShout);
7913 PlaySound(appData.soundChannel1);
7916 PlaySound(appData.soundChannel);
7919 PlaySound(appData.soundKibitz);
7922 PlaySound(appData.soundTell);
7924 case ColorChallenge:
7925 PlaySound(appData.soundChallenge);
7928 PlaySound(appData.soundRequest);
7931 PlaySound(appData.soundSeek);
7942 return getpwuid(getuid())->pw_name;
7945 static char *ExpandPathName(path)
7948 static char static_buf[2000];
7949 char *d, *s, buf[2000];
7955 while (*s && isspace(*s))
7964 if (*(s+1) == '/') {
7965 strcpy(d, getpwuid(getuid())->pw_dir);
7970 *strchr(buf, '/') = 0;
7971 pwd = getpwnam(buf);
7974 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7978 strcpy(d, pwd->pw_dir);
7979 strcat(d, strchr(s+1, '/'));
7990 static char host_name[MSG_SIZ];
7992 #if HAVE_GETHOSTNAME
7993 gethostname(host_name, MSG_SIZ);
7995 #else /* not HAVE_GETHOSTNAME */
7996 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7997 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7999 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8001 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8002 #endif /* not HAVE_GETHOSTNAME */
8005 XtIntervalId delayedEventTimerXID = 0;
8006 DelayedEventCallback delayedEventCallback = 0;
8011 delayedEventTimerXID = 0;
8012 delayedEventCallback();
8016 ScheduleDelayedEvent(cb, millisec)
8017 DelayedEventCallback cb; long millisec;
8019 if(delayedEventTimerXID && delayedEventCallback == cb)
8020 // [HGM] alive: replace, rather than add or flush identical event
8021 XtRemoveTimeOut(delayedEventTimerXID);
8022 delayedEventCallback = cb;
8023 delayedEventTimerXID =
8024 XtAppAddTimeOut(appContext, millisec,
8025 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8028 DelayedEventCallback
8031 if (delayedEventTimerXID) {
8032 return delayedEventCallback;
8039 CancelDelayedEvent()
8041 if (delayedEventTimerXID) {
8042 XtRemoveTimeOut(delayedEventTimerXID);
8043 delayedEventTimerXID = 0;
8047 XtIntervalId loadGameTimerXID = 0;
8049 int LoadGameTimerRunning()
8051 return loadGameTimerXID != 0;
8054 int StopLoadGameTimer()
8056 if (loadGameTimerXID != 0) {
8057 XtRemoveTimeOut(loadGameTimerXID);
8058 loadGameTimerXID = 0;
8066 LoadGameTimerCallback(arg, id)
8070 loadGameTimerXID = 0;
8075 StartLoadGameTimer(millisec)
8079 XtAppAddTimeOut(appContext, millisec,
8080 (XtTimerCallbackProc) LoadGameTimerCallback,
8084 XtIntervalId analysisClockXID = 0;
8087 AnalysisClockCallback(arg, id)
8091 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8092 || appData.icsEngineAnalyze) { // [DM]
8093 AnalysisPeriodicEvent(0);
8094 StartAnalysisClock();
8099 StartAnalysisClock()
8102 XtAppAddTimeOut(appContext, 2000,
8103 (XtTimerCallbackProc) AnalysisClockCallback,
8107 XtIntervalId clockTimerXID = 0;
8109 int ClockTimerRunning()
8111 return clockTimerXID != 0;
8114 int StopClockTimer()
8116 if (clockTimerXID != 0) {
8117 XtRemoveTimeOut(clockTimerXID);
8126 ClockTimerCallback(arg, id)
8135 StartClockTimer(millisec)
8139 XtAppAddTimeOut(appContext, millisec,
8140 (XtTimerCallbackProc) ClockTimerCallback,
8145 DisplayTimerLabel(w, color, timer, highlight)
8154 /* check for low time warning */
8155 Pixel foregroundOrWarningColor = timerForegroundPixel;
8158 appData.lowTimeWarning &&
8159 (timer / 1000) < appData.icsAlarmTime)
8160 foregroundOrWarningColor = lowTimeWarningColor;
8162 if (appData.clockMode) {
8163 sprintf(buf, "%s: %s", color, TimeString(timer));
8164 XtSetArg(args[0], XtNlabel, buf);
8166 sprintf(buf, "%s ", color);
8167 XtSetArg(args[0], XtNlabel, buf);
8172 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8173 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8175 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8176 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8179 XtSetValues(w, args, 3);
8183 DisplayWhiteClock(timeRemaining, highlight)
8189 if(appData.noGUI) return;
8190 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8191 if (highlight && iconPixmap == bIconPixmap) {
8192 iconPixmap = wIconPixmap;
8193 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8194 XtSetValues(shellWidget, args, 1);
8199 DisplayBlackClock(timeRemaining, highlight)
8205 if(appData.noGUI) return;
8206 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8207 if (highlight && iconPixmap == wIconPixmap) {
8208 iconPixmap = bIconPixmap;
8209 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8210 XtSetValues(shellWidget, args, 1);
8228 int StartChildProcess(cmdLine, dir, pr)
8235 int to_prog[2], from_prog[2];
8239 if (appData.debugMode) {
8240 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8243 /* We do NOT feed the cmdLine to the shell; we just
8244 parse it into blank-separated arguments in the
8245 most simple-minded way possible.
8248 strcpy(buf, cmdLine);
8253 if (p == NULL) break;
8258 SetUpChildIO(to_prog, from_prog);
8260 if ((pid = fork()) == 0) {
8262 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8263 close(to_prog[1]); // first close the unused pipe ends
8264 close(from_prog[0]);
8265 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8266 dup2(from_prog[1], 1);
8267 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8268 close(from_prog[1]); // and closing again loses one of the pipes!
8269 if(fileno(stderr) >= 2) // better safe than sorry...
8270 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8272 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8277 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8279 execvp(argv[0], argv);
8281 /* If we get here, exec failed */
8286 /* Parent process */
8288 close(from_prog[1]);
8290 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8293 cp->fdFrom = from_prog[0];
8294 cp->fdTo = to_prog[1];
8299 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8300 static RETSIGTYPE AlarmCallBack(int n)
8306 DestroyChildProcess(pr, signalType)
8310 ChildProc *cp = (ChildProc *) pr;
8312 if (cp->kind != CPReal) return;
8314 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8315 signal(SIGALRM, AlarmCallBack);
8317 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8318 kill(cp->pid, SIGKILL); // kill it forcefully
8319 wait((int *) 0); // and wait again
8323 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8325 /* Process is exiting either because of the kill or because of
8326 a quit command sent by the backend; either way, wait for it to die.
8335 InterruptChildProcess(pr)
8338 ChildProc *cp = (ChildProc *) pr;
8340 if (cp->kind != CPReal) return;
8341 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8344 int OpenTelnet(host, port, pr)
8349 char cmdLine[MSG_SIZ];
8351 if (port[0] == NULLCHAR) {
8352 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8354 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8356 return StartChildProcess(cmdLine, "", pr);
8359 int OpenTCP(host, port, pr)
8365 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8366 #else /* !OMIT_SOCKETS */
8368 struct sockaddr_in sa;
8370 unsigned short uport;
8373 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8377 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8378 sa.sin_family = AF_INET;
8379 sa.sin_addr.s_addr = INADDR_ANY;
8380 uport = (unsigned short) 0;
8381 sa.sin_port = htons(uport);
8382 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8386 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8387 if (!(hp = gethostbyname(host))) {
8389 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8390 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8391 hp->h_addrtype = AF_INET;
8393 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8394 hp->h_addr_list[0] = (char *) malloc(4);
8395 hp->h_addr_list[0][0] = b0;
8396 hp->h_addr_list[0][1] = b1;
8397 hp->h_addr_list[0][2] = b2;
8398 hp->h_addr_list[0][3] = b3;
8403 sa.sin_family = hp->h_addrtype;
8404 uport = (unsigned short) atoi(port);
8405 sa.sin_port = htons(uport);
8406 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8408 if (connect(s, (struct sockaddr *) &sa,
8409 sizeof(struct sockaddr_in)) < 0) {
8413 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8420 #endif /* !OMIT_SOCKETS */
8425 int OpenCommPort(name, pr)
8432 fd = open(name, 2, 0);
8433 if (fd < 0) return errno;
8435 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8445 int OpenLoopback(pr)
8451 SetUpChildIO(to, from);
8453 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8456 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8463 int OpenRcmd(host, user, cmd, pr)
8464 char *host, *user, *cmd;
8467 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8471 #define INPUT_SOURCE_BUF_SIZE 8192
8480 char buf[INPUT_SOURCE_BUF_SIZE];
8485 DoInputCallback(closure, source, xid)
8490 InputSource *is = (InputSource *) closure;
8495 if (is->lineByLine) {
8496 count = read(is->fd, is->unused,
8497 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8499 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8502 is->unused += count;
8504 while (p < is->unused) {
8505 q = memchr(p, '\n', is->unused - p);
8506 if (q == NULL) break;
8508 (is->func)(is, is->closure, p, q - p, 0);
8512 while (p < is->unused) {
8517 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8522 (is->func)(is, is->closure, is->buf, count, error);
8526 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8533 ChildProc *cp = (ChildProc *) pr;
8535 is = (InputSource *) calloc(1, sizeof(InputSource));
8536 is->lineByLine = lineByLine;
8540 is->fd = fileno(stdin);
8542 is->kind = cp->kind;
8543 is->fd = cp->fdFrom;
8546 is->unused = is->buf;
8549 is->xid = XtAppAddInput(appContext, is->fd,
8550 (XtPointer) (XtInputReadMask),
8551 (XtInputCallbackProc) DoInputCallback,
8553 is->closure = closure;
8554 return (InputSourceRef) is;
8558 RemoveInputSource(isr)
8561 InputSource *is = (InputSource *) isr;
8563 if (is->xid == 0) return;
8564 XtRemoveInput(is->xid);
8568 int OutputToProcess(pr, message, count, outError)
8574 static int line = 0;
8575 ChildProc *cp = (ChildProc *) pr;
8580 if (appData.noJoin || !appData.useInternalWrap)
8581 outCount = fwrite(message, 1, count, stdout);
8584 int width = get_term_width();
8585 int len = wrap(NULL, message, count, width, &line);
8586 char *msg = malloc(len);
8590 outCount = fwrite(message, 1, count, stdout);
8593 dbgchk = wrap(msg, message, count, width, &line);
8594 if (dbgchk != len && appData.debugMode)
8595 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
8596 outCount = fwrite(msg, 1, dbgchk, stdout);
8602 outCount = write(cp->fdTo, message, count);
8612 /* Output message to process, with "ms" milliseconds of delay
8613 between each character. This is needed when sending the logon
8614 script to ICC, which for some reason doesn't like the
8615 instantaneous send. */
8616 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8623 ChildProc *cp = (ChildProc *) pr;
8628 r = write(cp->fdTo, message++, 1);
8641 /**** Animation code by Hugh Fisher, DCS, ANU.
8643 Known problem: if a window overlapping the board is
8644 moved away while a piece is being animated underneath,
8645 the newly exposed area won't be updated properly.
8646 I can live with this.
8648 Known problem: if you look carefully at the animation
8649 of pieces in mono mode, they are being drawn as solid
8650 shapes without interior detail while moving. Fixing
8651 this would be a major complication for minimal return.
8654 /* Masks for XPM pieces. Black and white pieces can have
8655 different shapes, but in the interest of retaining my
8656 sanity pieces must have the same outline on both light
8657 and dark squares, and all pieces must use the same
8658 background square colors/images. */
8660 static int xpmDone = 0;
8663 CreateAnimMasks (pieceDepth)
8670 unsigned long plane;
8673 /* Need a bitmap just to get a GC with right depth */
8674 buf = XCreatePixmap(xDisplay, xBoardWindow,
8676 values.foreground = 1;
8677 values.background = 0;
8678 /* Don't use XtGetGC, not read only */
8679 maskGC = XCreateGC(xDisplay, buf,
8680 GCForeground | GCBackground, &values);
8681 XFreePixmap(xDisplay, buf);
8683 buf = XCreatePixmap(xDisplay, xBoardWindow,
8684 squareSize, squareSize, pieceDepth);
8685 values.foreground = XBlackPixel(xDisplay, xScreen);
8686 values.background = XWhitePixel(xDisplay, xScreen);
8687 bufGC = XCreateGC(xDisplay, buf,
8688 GCForeground | GCBackground, &values);
8690 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8691 /* Begin with empty mask */
8692 if(!xpmDone) // [HGM] pieces: keep using existing
8693 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8694 squareSize, squareSize, 1);
8695 XSetFunction(xDisplay, maskGC, GXclear);
8696 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8697 0, 0, squareSize, squareSize);
8699 /* Take a copy of the piece */
8704 XSetFunction(xDisplay, bufGC, GXcopy);
8705 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8707 0, 0, squareSize, squareSize, 0, 0);
8709 /* XOR the background (light) over the piece */
8710 XSetFunction(xDisplay, bufGC, GXxor);
8712 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8713 0, 0, squareSize, squareSize, 0, 0);
8715 XSetForeground(xDisplay, bufGC, lightSquareColor);
8716 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8719 /* We now have an inverted piece image with the background
8720 erased. Construct mask by just selecting all the non-zero
8721 pixels - no need to reconstruct the original image. */
8722 XSetFunction(xDisplay, maskGC, GXor);
8724 /* Might be quicker to download an XImage and create bitmap
8725 data from it rather than this N copies per piece, but it
8726 only takes a fraction of a second and there is a much
8727 longer delay for loading the pieces. */
8728 for (n = 0; n < pieceDepth; n ++) {
8729 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8730 0, 0, squareSize, squareSize,
8736 XFreePixmap(xDisplay, buf);
8737 XFreeGC(xDisplay, bufGC);
8738 XFreeGC(xDisplay, maskGC);
8742 InitAnimState (anim, info)
8744 XWindowAttributes * info;
8749 /* Each buffer is square size, same depth as window */
8750 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8751 squareSize, squareSize, info->depth);
8752 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8753 squareSize, squareSize, info->depth);
8755 /* Create a plain GC for blitting */
8756 mask = GCForeground | GCBackground | GCFunction |
8757 GCPlaneMask | GCGraphicsExposures;
8758 values.foreground = XBlackPixel(xDisplay, xScreen);
8759 values.background = XWhitePixel(xDisplay, xScreen);
8760 values.function = GXcopy;
8761 values.plane_mask = AllPlanes;
8762 values.graphics_exposures = False;
8763 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8765 /* Piece will be copied from an existing context at
8766 the start of each new animation/drag. */
8767 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8769 /* Outline will be a read-only copy of an existing */
8770 anim->outlineGC = None;
8776 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8777 XWindowAttributes info;
8779 if (xpmDone && gameInfo.variant == old) return;
8780 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8781 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8783 InitAnimState(&game, &info);
8784 InitAnimState(&player, &info);
8786 /* For XPM pieces, we need bitmaps to use as masks. */
8788 CreateAnimMasks(info.depth);
8794 static Boolean frameWaiting;
8796 static RETSIGTYPE FrameAlarm (sig)
8799 frameWaiting = False;
8800 /* In case System-V style signals. Needed?? */
8801 signal(SIGALRM, FrameAlarm);
8808 struct itimerval delay;
8810 XSync(xDisplay, False);
8813 frameWaiting = True;
8814 signal(SIGALRM, FrameAlarm);
8815 delay.it_interval.tv_sec =
8816 delay.it_value.tv_sec = time / 1000;
8817 delay.it_interval.tv_usec =
8818 delay.it_value.tv_usec = (time % 1000) * 1000;
8819 setitimer(ITIMER_REAL, &delay, NULL);
8820 while (frameWaiting) pause();
8821 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8822 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8823 setitimer(ITIMER_REAL, &delay, NULL);
8833 XSync(xDisplay, False);
8835 usleep(time * 1000);
8840 /* Convert board position to corner of screen rect and color */
8843 ScreenSquare(column, row, pt, color)
8844 int column; int row; XPoint * pt; int * color;
8847 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8848 pt->y = lineGap + row * (squareSize + lineGap);
8850 pt->x = lineGap + column * (squareSize + lineGap);
8851 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8853 *color = SquareColor(row, column);
8856 /* Convert window coords to square */
8859 BoardSquare(x, y, column, row)
8860 int x; int y; int * column; int * row;
8862 *column = EventToSquare(x, BOARD_WIDTH);
8863 if (flipView && *column >= 0)
8864 *column = BOARD_WIDTH - 1 - *column;
8865 *row = EventToSquare(y, BOARD_HEIGHT);
8866 if (!flipView && *row >= 0)
8867 *row = BOARD_HEIGHT - 1 - *row;
8872 #undef Max /* just in case */
8874 #define Max(a, b) ((a) > (b) ? (a) : (b))
8875 #define Min(a, b) ((a) < (b) ? (a) : (b))
8878 SetRect(rect, x, y, width, height)
8879 XRectangle * rect; int x; int y; int width; int height;
8883 rect->width = width;
8884 rect->height = height;
8887 /* Test if two frames overlap. If they do, return
8888 intersection rect within old and location of
8889 that rect within new. */
8892 Intersect(old, new, size, area, pt)
8893 XPoint * old; XPoint * new;
8894 int size; XRectangle * area; XPoint * pt;
8896 if (old->x > new->x + size || new->x > old->x + size ||
8897 old->y > new->y + size || new->y > old->y + size) {
8900 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8901 size - abs(old->x - new->x), size - abs(old->y - new->y));
8902 pt->x = Max(old->x - new->x, 0);
8903 pt->y = Max(old->y - new->y, 0);
8908 /* For two overlapping frames, return the rect(s)
8909 in the old that do not intersect with the new. */
8912 CalcUpdateRects(old, new, size, update, nUpdates)
8913 XPoint * old; XPoint * new; int size;
8914 XRectangle update[]; int * nUpdates;
8918 /* If old = new (shouldn't happen) then nothing to draw */
8919 if (old->x == new->x && old->y == new->y) {
8923 /* Work out what bits overlap. Since we know the rects
8924 are the same size we don't need a full intersect calc. */
8926 /* Top or bottom edge? */
8927 if (new->y > old->y) {
8928 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8930 } else if (old->y > new->y) {
8931 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8932 size, old->y - new->y);
8935 /* Left or right edge - don't overlap any update calculated above. */
8936 if (new->x > old->x) {
8937 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8938 new->x - old->x, size - abs(new->y - old->y));
8940 } else if (old->x > new->x) {
8941 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8942 old->x - new->x, size - abs(new->y - old->y));
8949 /* Generate a series of frame coords from start->mid->finish.
8950 The movement rate doubles until the half way point is
8951 reached, then halves back down to the final destination,
8952 which gives a nice slow in/out effect. The algorithmn
8953 may seem to generate too many intermediates for short
8954 moves, but remember that the purpose is to attract the
8955 viewers attention to the piece about to be moved and
8956 then to where it ends up. Too few frames would be less
8960 Tween(start, mid, finish, factor, frames, nFrames)
8961 XPoint * start; XPoint * mid;
8962 XPoint * finish; int factor;
8963 XPoint frames[]; int * nFrames;
8965 int fraction, n, count;
8969 /* Slow in, stepping 1/16th, then 1/8th, ... */
8971 for (n = 0; n < factor; n++)
8973 for (n = 0; n < factor; n++) {
8974 frames[count].x = start->x + (mid->x - start->x) / fraction;
8975 frames[count].y = start->y + (mid->y - start->y) / fraction;
8977 fraction = fraction / 2;
8981 frames[count] = *mid;
8984 /* Slow out, stepping 1/2, then 1/4, ... */
8986 for (n = 0; n < factor; n++) {
8987 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8988 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8990 fraction = fraction * 2;
8995 /* Draw a piece on the screen without disturbing what's there */
8998 SelectGCMask(piece, clip, outline, mask)
8999 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9003 /* Bitmap for piece being moved. */
9004 if (appData.monoMode) {
9005 *mask = *pieceToSolid(piece);
9006 } else if (useImages) {
9008 *mask = xpmMask[piece];
9010 *mask = ximMaskPm[piece];
9013 *mask = *pieceToSolid(piece);
9016 /* GC for piece being moved. Square color doesn't matter, but
9017 since it gets modified we make a copy of the original. */
9019 if (appData.monoMode)
9024 if (appData.monoMode)
9029 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9031 /* Outline only used in mono mode and is not modified */
9033 *outline = bwPieceGC;
9035 *outline = wbPieceGC;
9039 OverlayPiece(piece, clip, outline, dest)
9040 ChessSquare piece; GC clip; GC outline; Drawable dest;
9045 /* Draw solid rectangle which will be clipped to shape of piece */
9046 XFillRectangle(xDisplay, dest, clip,
9047 0, 0, squareSize, squareSize);
9048 if (appData.monoMode)
9049 /* Also draw outline in contrasting color for black
9050 on black / white on white cases */
9051 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9052 0, 0, squareSize, squareSize, 0, 0, 1);
9054 /* Copy the piece */
9059 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9061 0, 0, squareSize, squareSize,
9066 /* Animate the movement of a single piece */
9069 BeginAnimation(anim, piece, startColor, start)
9077 /* The old buffer is initialised with the start square (empty) */
9078 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9079 anim->prevFrame = *start;
9081 /* The piece will be drawn using its own bitmap as a matte */
9082 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9083 XSetClipMask(xDisplay, anim->pieceGC, mask);
9087 AnimationFrame(anim, frame, piece)
9092 XRectangle updates[4];
9097 /* Save what we are about to draw into the new buffer */
9098 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9099 frame->x, frame->y, squareSize, squareSize,
9102 /* Erase bits of the previous frame */
9103 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9104 /* Where the new frame overlapped the previous,
9105 the contents in newBuf are wrong. */
9106 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9107 overlap.x, overlap.y,
9108 overlap.width, overlap.height,
9110 /* Repaint the areas in the old that don't overlap new */
9111 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9112 for (i = 0; i < count; i++)
9113 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9114 updates[i].x - anim->prevFrame.x,
9115 updates[i].y - anim->prevFrame.y,
9116 updates[i].width, updates[i].height,
9117 updates[i].x, updates[i].y);
9119 /* Easy when no overlap */
9120 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9121 0, 0, squareSize, squareSize,
9122 anim->prevFrame.x, anim->prevFrame.y);
9125 /* Save this frame for next time round */
9126 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9127 0, 0, squareSize, squareSize,
9129 anim->prevFrame = *frame;
9131 /* Draw piece over original screen contents, not current,
9132 and copy entire rect. Wipes out overlapping piece images. */
9133 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9134 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9135 0, 0, squareSize, squareSize,
9136 frame->x, frame->y);
9140 EndAnimation (anim, finish)
9144 XRectangle updates[4];
9149 /* The main code will redraw the final square, so we
9150 only need to erase the bits that don't overlap. */
9151 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9152 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9153 for (i = 0; i < count; i++)
9154 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9155 updates[i].x - anim->prevFrame.x,
9156 updates[i].y - anim->prevFrame.y,
9157 updates[i].width, updates[i].height,
9158 updates[i].x, updates[i].y);
9160 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9161 0, 0, squareSize, squareSize,
9162 anim->prevFrame.x, anim->prevFrame.y);
9167 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9169 ChessSquare piece; int startColor;
9170 XPoint * start; XPoint * finish;
9171 XPoint frames[]; int nFrames;
9175 BeginAnimation(anim, piece, startColor, start);
9176 for (n = 0; n < nFrames; n++) {
9177 AnimationFrame(anim, &(frames[n]), piece);
9178 FrameDelay(appData.animSpeed);
9180 EndAnimation(anim, finish);
9183 /* Main control logic for deciding what to animate and how */
9186 AnimateMove(board, fromX, fromY, toX, toY)
9195 XPoint start, finish, mid;
9196 XPoint frames[kFactor * 2 + 1];
9197 int nFrames, startColor, endColor;
9199 /* Are we animating? */
9200 if (!appData.animate || appData.blindfold)
9203 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9204 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9205 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9207 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9208 piece = board[fromY][fromX];
9209 if (piece >= EmptySquare) return;
9214 hop = (piece == WhiteKnight || piece == BlackKnight);
9217 if (appData.debugMode) {
9218 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9219 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9220 piece, fromX, fromY, toX, toY); }
9222 ScreenSquare(fromX, fromY, &start, &startColor);
9223 ScreenSquare(toX, toY, &finish, &endColor);
9226 /* Knight: make diagonal movement then straight */
9227 if (abs(toY - fromY) < abs(toX - fromX)) {
9228 mid.x = start.x + (finish.x - start.x) / 2;
9232 mid.y = start.y + (finish.y - start.y) / 2;
9235 mid.x = start.x + (finish.x - start.x) / 2;
9236 mid.y = start.y + (finish.y - start.y) / 2;
9239 /* Don't use as many frames for very short moves */
9240 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9241 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9243 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9244 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9246 /* Be sure end square is redrawn */
9247 damage[toY][toX] = True;
9251 DragPieceBegin(x, y)
9254 int boardX, boardY, color;
9257 /* Are we animating? */
9258 if (!appData.animateDragging || appData.blindfold)
9261 /* Figure out which square we start in and the
9262 mouse position relative to top left corner. */
9263 BoardSquare(x, y, &boardX, &boardY);
9264 player.startBoardX = boardX;
9265 player.startBoardY = boardY;
9266 ScreenSquare(boardX, boardY, &corner, &color);
9267 player.startSquare = corner;
9268 player.startColor = color;
9269 /* As soon as we start dragging, the piece will jump slightly to
9270 be centered over the mouse pointer. */
9271 player.mouseDelta.x = squareSize/2;
9272 player.mouseDelta.y = squareSize/2;
9273 /* Initialise animation */
9274 player.dragPiece = PieceForSquare(boardX, boardY);
9276 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9277 player.dragActive = True;
9278 BeginAnimation(&player, player.dragPiece, color, &corner);
9279 /* Mark this square as needing to be redrawn. Note that
9280 we don't remove the piece though, since logically (ie
9281 as seen by opponent) the move hasn't been made yet. */
9282 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9283 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9284 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9285 corner.x, corner.y, squareSize, squareSize,
9286 0, 0); // [HGM] zh: unstack in stead of grab
9287 damage[boardY][boardX] = True;
9289 player.dragActive = False;
9299 /* Are we animating? */
9300 if (!appData.animateDragging || appData.blindfold)
9304 if (! player.dragActive)
9306 /* Move piece, maintaining same relative position
9307 of mouse within square */
9308 corner.x = x - player.mouseDelta.x;
9309 corner.y = y - player.mouseDelta.y;
9310 AnimationFrame(&player, &corner, player.dragPiece);
9312 if (appData.highlightDragging) {
9314 BoardSquare(x, y, &boardX, &boardY);
9315 SetHighlights(fromX, fromY, boardX, boardY);
9324 int boardX, boardY, color;
9327 /* Are we animating? */
9328 if (!appData.animateDragging || appData.blindfold)
9332 if (! player.dragActive)
9334 /* Last frame in sequence is square piece is
9335 placed on, which may not match mouse exactly. */
9336 BoardSquare(x, y, &boardX, &boardY);
9337 ScreenSquare(boardX, boardY, &corner, &color);
9338 EndAnimation(&player, &corner);
9340 /* Be sure end square is redrawn */
9341 damage[boardY][boardX] = True;
9343 /* This prevents weird things happening with fast successive
9344 clicks which on my Sun at least can cause motion events
9345 without corresponding press/release. */
9346 player.dragActive = False;
9349 /* Handle expose event while piece being dragged */
9354 if (!player.dragActive || appData.blindfold)
9357 /* What we're doing: logically, the move hasn't been made yet,
9358 so the piece is still in it's original square. But visually
9359 it's being dragged around the board. So we erase the square
9360 that the piece is on and draw it at the last known drag point. */
9361 BlankSquare(player.startSquare.x, player.startSquare.y,
9362 player.startColor, EmptySquare, xBoardWindow);
9363 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9364 damage[player.startBoardY][player.startBoardX] = TRUE;
9368 SetProgramStats( FrontEndProgramStats * stats )
9371 // [HGM] done, but perhaps backend should call this directly?
9372 EngineOutputUpdate( stats );
9375 #include <sys/ioctl.h>
9376 int get_term_width()
9378 int fd, default_width;
9381 default_width = 79; // this is FICS default anyway...
9383 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9385 if (!ioctl(fd, TIOCGSIZE, &win))
9386 default_width = win.ts_cols;
9387 #elif defined(TIOCGWINSZ)
9389 if (!ioctl(fd, TIOCGWINSZ, &win))
9390 default_width = win.ws_col;
9392 return default_width;
9395 void update_ics_width()
9397 static int old_width = 0;
9398 int new_width = get_term_width();
9400 if (old_width != new_width)
9401 ics_printf("set width %d\n", new_width);
9402 old_width = new_width;
9405 void NotifyFrontendLogin()