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. */
60 #include <sys/types.h>
65 # if HAVE_SYS_SOCKET_H
66 # include <sys/socket.h>
67 # include <netinet/in.h>
69 # else /* not HAVE_SYS_SOCKET_H */
70 # if HAVE_LAN_SOCKET_H
71 # include <lan/socket.h>
73 # include <lan/netdb.h>
74 # else /* not HAVE_LAN_SOCKET_H */
75 # define OMIT_SOCKETS 1
76 # endif /* not HAVE_LAN_SOCKET_H */
77 # endif /* not HAVE_SYS_SOCKET_H */
78 #endif /* !OMIT_SOCKETS */
83 #else /* not STDC_HEADERS */
84 extern char *getenv();
87 # else /* not HAVE_STRING_H */
89 # endif /* not HAVE_STRING_H */
90 #endif /* not STDC_HEADERS */
93 # include <sys/fcntl.h>
94 #else /* not HAVE_SYS_FCNTL_H */
97 # endif /* HAVE_FCNTL_H */
98 #endif /* not HAVE_SYS_FCNTL_H */
100 #if HAVE_SYS_SYSTEMINFO_H
101 # include <sys/systeminfo.h>
102 #endif /* HAVE_SYS_SYSTEMINFO_H */
104 #if TIME_WITH_SYS_TIME
105 # include <sys/time.h>
109 # include <sys/time.h>
120 # include <sys/wait.h>
125 # define NAMLEN(dirent) strlen((dirent)->d_name)
126 # define HAVE_DIR_STRUCT
128 # define dirent direct
129 # define NAMLEN(dirent) (dirent)->d_namlen
131 # include <sys/ndir.h>
132 # define HAVE_DIR_STRUCT
135 # include <sys/dir.h>
136 # define HAVE_DIR_STRUCT
140 # define HAVE_DIR_STRUCT
145 # if HAVE_LIBREADLINE /* add gnu-readline support */
146 #include <readline/readline.h>
147 #include <readline/history.h>
150 #include <X11/Intrinsic.h>
151 #include <X11/StringDefs.h>
152 #include <X11/Shell.h>
153 #include <X11/cursorfont.h>
154 #include <X11/Xatom.h>
155 #include <X11/Xmu/Atoms.h>
157 #include <X11/Xaw3d/Dialog.h>
158 #include <X11/Xaw3d/Form.h>
159 #include <X11/Xaw3d/List.h>
160 #include <X11/Xaw3d/Label.h>
161 #include <X11/Xaw3d/SimpleMenu.h>
162 #include <X11/Xaw3d/SmeBSB.h>
163 #include <X11/Xaw3d/SmeLine.h>
164 #include <X11/Xaw3d/Box.h>
165 #include <X11/Xaw3d/MenuButton.h>
166 #include <X11/Xaw3d/Text.h>
167 #include <X11/Xaw3d/AsciiText.h>
169 #include <X11/Xaw/Dialog.h>
170 #include <X11/Xaw/Form.h>
171 #include <X11/Xaw/List.h>
172 #include <X11/Xaw/Label.h>
173 #include <X11/Xaw/SimpleMenu.h>
174 #include <X11/Xaw/SmeBSB.h>
175 #include <X11/Xaw/SmeLine.h>
176 #include <X11/Xaw/Box.h>
177 #include <X11/Xaw/MenuButton.h>
178 #include <X11/Xaw/Text.h>
179 #include <X11/Xaw/AsciiText.h>
182 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
187 #include "pixmaps/pixmaps.h"
188 #define IMAGE_EXT "xpm"
190 #define IMAGE_EXT "xim"
191 #include "bitmaps/bitmaps.h"
194 #include "bitmaps/icon_white.bm"
195 #include "bitmaps/icon_black.bm"
196 #include "bitmaps/checkmark.bm"
198 #include "frontend.h"
200 #include "backendz.h"
204 #include "xgamelist.h"
205 #include "xhistory.h"
206 #include "xedittags.h"
209 // must be moved to xengineoutput.h
211 void EngineOutputProc P((Widget w, XEvent *event,
212 String *prms, Cardinal *nprms));
213 void EvalGraphProc P((Widget w, XEvent *event,
214 String *prms, Cardinal *nprms));
221 #define usleep(t) _sleep2(((t)+500)/1000)
225 # define _(s) gettext (s)
226 # define N_(s) gettext_noop (s)
242 int main P((int argc, char **argv));
243 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
244 char *init_path, char *mode, int (*show_entry)(), char **name_return));
245 RETSIGTYPE CmailSigHandler P((int sig));
246 RETSIGTYPE IntSigHandler P((int sig));
247 RETSIGTYPE TermSizeSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 Widget CreateButtonBar P ((MenuItem *mi));
255 char *FindFont P((char *pattern, int targetPxlSize));
256 void PieceMenuPopup P((Widget w, XEvent *event,
257 String *params, Cardinal *num_params));
258 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
261 u_int wreq, u_int hreq));
262 void CreateGrid P((void));
263 int EventToSquare P((int x, int limit));
264 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
265 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
266 void HandleUserMove P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void AnimateUserMove P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void HandlePV P((Widget w, XEvent * event,
271 String * params, Cardinal * nParams));
272 void SelectPV P((Widget w, XEvent * event,
273 String * params, Cardinal * nParams));
274 void StopPV P((Widget w, XEvent * event,
275 String * params, Cardinal * nParams));
276 void WhiteClock P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void BlackClock P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void DrawPositionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
284 void CommentClick P((Widget w, XEvent * event,
285 String * params, Cardinal * nParams));
286 void CommentPopUp P((char *title, char *label));
287 void CommentPopDown P((void));
288 void CommentCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void ICSInputBoxPopUp P((void));
291 void ICSInputBoxPopDown P((void));
292 void FileNamePopUp P((char *label, char *def,
293 FileProc proc, char *openMode));
294 void FileNamePopDown P((void));
295 void FileNameCallback P((Widget w, XtPointer client_data,
296 XtPointer call_data));
297 void FileNameAction P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void AskQuestionReplyAction P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void AskQuestionProc P((Widget w, XEvent *event,
302 String *prms, Cardinal *nprms));
303 void AskQuestionPopDown P((void));
304 void PromotionPopDown P((void));
305 void PromotionCallback P((Widget w, XtPointer client_data,
306 XtPointer call_data));
307 void EditCommentPopDown P((void));
308 void EditCommentCallback P((Widget w, XtPointer client_data,
309 XtPointer call_data));
310 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
311 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
315 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
317 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
319 void LoadPositionProc P((Widget w, XEvent *event,
320 String *prms, Cardinal *nprms));
321 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
323 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
325 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
327 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
329 void PastePositionProc P((Widget w, XEvent *event, String *prms,
331 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void SavePositionProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
339 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
343 void MachineWhiteProc P((Widget w, XEvent *event,
344 String *prms, Cardinal *nprms));
345 void AnalyzeModeProc P((Widget w, XEvent *event,
346 String *prms, Cardinal *nprms));
347 void AnalyzeFileProc P((Widget w, XEvent *event,
348 String *prms, Cardinal *nprms));
349 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
351 void IcsClientProc P((Widget w, XEvent *event, String *prms,
353 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void EditPositionProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void EditCommentProc P((Widget w, XEvent *event,
358 String *prms, Cardinal *nprms));
359 void IcsInputBoxProc P((Widget w, XEvent *event,
360 String *prms, Cardinal *nprms));
361 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void StopObservingProc P((Widget w, XEvent *event, String *prms,
377 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
379 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
388 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
390 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
393 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
395 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
397 void AutocommProc P((Widget w, XEvent *event, String *prms,
399 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AutobsProc P((Widget w, XEvent *event, String *prms,
403 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
408 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
411 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
413 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
415 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
419 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
421 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
423 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
425 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
427 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
431 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
433 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
435 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
437 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void DisplayMove P((int moveNumber));
449 void DisplayTitle P((char *title));
450 void ICSInitScript P((void));
451 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
452 void ErrorPopUp P((char *title, char *text, int modal));
453 void ErrorPopDown P((void));
454 static char *ExpandPathName P((char *path));
455 static void CreateAnimVars P((void));
456 static void DragPieceMove P((int x, int y));
457 static void DrawDragPiece P((void));
458 char *ModeToWidgetName P((GameMode mode));
459 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
467 void GameListOptionsPopDown P(());
468 void ShufflePopDown P(());
469 void EnginePopDown P(());
470 void UciPopDown P(());
471 void TimeControlPopDown P(());
472 void NewVariantPopDown P(());
473 void SettingsPopDown P(());
474 void update_ics_width P(());
475 int get_term_width P(());
476 int CopyMemoProc P(());
478 # if HAVE_LIBREADLINE /* add gnu-readline support */
479 static void ReadlineCompleteHandler P((char *));
483 * XBoard depends on Xt R4 or higher
485 int xtVersion = XtSpecificationRelease;
490 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
491 jailSquareColor, highlightSquareColor, premoveHighlightColor;
492 Pixel lowTimeWarningColor;
493 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
494 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
495 wjPieceGC, bjPieceGC, prelineGC, countGC;
496 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
497 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
498 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
499 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
500 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
501 ICSInputShell, fileNameShell, askQuestionShell;
502 Widget historyShell, evalGraphShell, gameListShell;
503 int hOffset; // [HGM] dual
504 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
505 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
506 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
507 Font clockFontID, coordFontID, countFontID;
508 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
509 XtAppContext appContext;
511 char *oldICSInteractionTitle;
515 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
517 # if HAVE_LIBREADLINE /* gnu readline support */
518 static char* readline_buffer;
519 static int readline_complete=0;
520 extern int sending_ICS_login;
521 extern int sending_ICS_password;
524 Position commentX = -1, commentY = -1;
525 Dimension commentW, commentH;
526 typedef unsigned int BoardSize;
528 Boolean chessProgram;
530 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
531 int squareSize, smallLayout = 0, tinyLayout = 0,
532 marginW, marginH, // [HGM] for run-time resizing
533 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
534 ICSInputBoxUp = False, askQuestionUp = False,
535 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
536 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
537 Pixel timerForegroundPixel, timerBackgroundPixel;
538 Pixel buttonForegroundPixel, buttonBackgroundPixel;
539 char *chessDir, *programName, *programVersion,
540 *gameCopyFilename, *gamePasteFilename;
541 Boolean alwaysOnTop = False;
542 Boolean saveSettingsOnExit;
543 char *settingsFileName;
544 char *icsTextMenuString;
546 char *firstChessProgramNames;
547 char *secondChessProgramNames;
549 WindowPlacement wpMain;
550 WindowPlacement wpConsole;
551 WindowPlacement wpComment;
552 WindowPlacement wpMoveHistory;
553 WindowPlacement wpEvalGraph;
554 WindowPlacement wpEngineOutput;
555 WindowPlacement wpGameList;
556 WindowPlacement wpTags;
560 Pixmap pieceBitmap[2][(int)BlackPawn];
561 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
562 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
563 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
564 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
565 int useImages, useImageSqs;
566 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
567 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
568 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
569 XImage *ximLightSquare, *ximDarkSquare;
572 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
573 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
575 #define White(piece) ((int)(piece) < (int)BlackPawn)
577 /* Variables for doing smooth animation. This whole thing
578 would be much easier if the board was double-buffered,
579 but that would require a fairly major rewrite. */
584 GC blitGC, pieceGC, outlineGC;
585 XPoint startSquare, prevFrame, mouseDelta;
589 int startBoardX, startBoardY;
592 /* There can be two pieces being animated at once: a player
593 can begin dragging a piece before the remote opponent has moved. */
595 static AnimState game, player;
597 /* Bitmaps for use as masks when drawing XPM pieces.
598 Need one for each black and white piece. */
599 static Pixmap xpmMask[BlackKing + 1];
601 /* This magic number is the number of intermediate frames used
602 in each half of the animation. For short moves it's reduced
603 by 1. The total number of frames will be factor * 2 + 1. */
606 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
608 MenuItem fileMenu[] = {
609 {N_("New Game"), ResetProc},
610 {N_("New Shuffle Game ..."), ShuffleMenuProc},
611 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
612 {"----", NothingProc},
613 {N_("Load Game"), LoadGameProc},
614 {N_("Load Next Game"), LoadNextGameProc},
615 {N_("Load Previous Game"), LoadPrevGameProc},
616 {N_("Reload Same Game"), ReloadGameProc},
617 {N_("Save Game"), SaveGameProc},
618 {"----", NothingProc},
619 {N_("Copy Game"), CopyGameProc},
620 {N_("Paste Game"), PasteGameProc},
621 {"----", NothingProc},
622 {N_("Load Position"), LoadPositionProc},
623 {N_("Load Next Position"), LoadNextPositionProc},
624 {N_("Load Previous Position"), LoadPrevPositionProc},
625 {N_("Reload Same Position"), ReloadPositionProc},
626 {N_("Save Position"), SavePositionProc},
627 {"----", NothingProc},
628 {N_("Copy Position"), CopyPositionProc},
629 {N_("Paste Position"), PastePositionProc},
630 {"----", NothingProc},
631 {N_("Mail Move"), MailMoveProc},
632 {N_("Reload CMail Message"), ReloadCmailMsgProc},
633 {"----", NothingProc},
634 {N_("Exit"), QuitProc},
638 MenuItem modeMenu[] = {
639 {N_("Machine White"), MachineWhiteProc},
640 {N_("Machine Black"), MachineBlackProc},
641 {N_("Two Machines"), TwoMachinesProc},
642 {N_("Analysis Mode"), AnalyzeModeProc},
643 {N_("Analyze File"), AnalyzeFileProc },
644 {N_("ICS Client"), IcsClientProc},
645 {N_("Edit Game"), EditGameProc},
646 {N_("Edit Position"), EditPositionProc},
647 {N_("Training"), TrainingProc},
648 {"----", NothingProc},
649 {N_("Show Engine Output"), EngineOutputProc},
650 {N_("Show Evaluation Graph"), EvalGraphProc},
651 {N_("Show Game List"), ShowGameListProc},
652 {N_("Show Move History"), HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
653 {"----", NothingProc},
654 {N_("Edit Tags"), EditTagsProc},
655 {N_("Edit Comment"), EditCommentProc},
656 {N_("ICS Input Box"), IcsInputBoxProc},
657 {N_("Pause"), PauseProc},
661 MenuItem actionMenu[] = {
662 {N_("Accept"), AcceptProc},
663 {N_("Decline"), DeclineProc},
664 {N_("Rematch"), RematchProc},
665 {"----", NothingProc},
666 {N_("Call Flag"), CallFlagProc},
667 {N_("Draw"), DrawProc},
668 {N_("Adjourn"), AdjournProc},
669 {N_("Abort"), AbortProc},
670 {N_("Resign"), ResignProc},
671 {"----", NothingProc},
672 {N_("Stop Observing"), StopObservingProc},
673 {N_("Stop Examining"), StopExaminingProc},
674 {N_("Upload to Examine"), UploadProc},
675 {"----", NothingProc},
676 {N_("Adjudicate to White"), AdjuWhiteProc},
677 {N_("Adjudicate to Black"), AdjuBlackProc},
678 {N_("Adjudicate Draw"), AdjuDrawProc},
682 MenuItem stepMenu[] = {
683 {N_("Backward"), BackwardProc},
684 {N_("Forward"), ForwardProc},
685 {N_("Back to Start"), ToStartProc},
686 {N_("Forward to End"), ToEndProc},
687 {N_("Revert"), RevertProc},
688 {N_("Annotate"), AnnotateProc},
689 {N_("Truncate Game"), TruncateGameProc},
690 {"----", NothingProc},
691 {N_("Move Now"), MoveNowProc},
692 {N_("Retract Move"), RetractMoveProc},
696 MenuItem optionsMenu[] = {
697 {N_("Flip View"), FlipViewProc},
698 {"----", NothingProc},
699 {N_("Adjudications ..."), EngineMenuProc},
700 {N_("General Settings ..."), UciMenuProc},
701 {N_("Engine #1 Settings ..."), FirstSettingsProc},
702 {N_("Engine #2 Settings ..."), SecondSettingsProc},
703 {N_("Time Control ..."), TimeControlProc},
704 {N_("Game List ..."), GameListOptionsPopUp},
705 {"----", NothingProc},
706 {N_("Always Queen"), AlwaysQueenProc},
707 {N_("Animate Dragging"), AnimateDraggingProc},
708 {N_("Animate Moving"), AnimateMovingProc},
709 {N_("Auto Comment"), AutocommProc},
710 {N_("Auto Flag"), AutoflagProc},
711 {N_("Auto Flip View"), AutoflipProc},
712 {N_("Auto Observe"), AutobsProc},
713 {N_("Auto Raise Board"), AutoraiseProc},
714 {N_("Auto Save"), AutosaveProc},
715 {N_("Blindfold"), BlindfoldProc},
716 {N_("Flash Moves"), FlashMovesProc},
717 {N_("Get Move List"), GetMoveListProc},
719 {N_("Highlight Dragging"), HighlightDraggingProc},
721 {N_("Highlight Last Move"), HighlightLastMoveProc},
722 {N_("Move Sound"), MoveSoundProc},
723 {N_("ICS Alarm"), IcsAlarmProc},
724 {N_("Old Save Style"), OldSaveStyleProc},
725 {N_("Periodic Updates"), PeriodicUpdatesProc},
726 {N_("Ponder Next Move"), PonderNextMoveProc},
727 {N_("Popup Exit Message"), PopupExitMessageProc},
728 {N_("Popup Move Errors"), PopupMoveErrorsProc},
729 {N_("Premove"), PremoveProc},
730 {N_("Quiet Play"), QuietPlayProc},
731 {N_("Show Coords"), ShowCoordsProc},
732 {N_("Hide Thinking"), HideThinkingProc},
733 {N_("Test Legality"), TestLegalityProc},
734 {"----", NothingProc},
735 {N_("Save Settings Now"), SaveSettingsProc},
736 {N_("Save Settings on Exit"), SaveOnExitProc},
740 MenuItem helpMenu[] = {
741 {N_("Info XBoard"), InfoProc},
742 {N_("Man XBoard"), ManProc},
743 {"----", NothingProc},
744 {N_("Hint"), HintProc},
745 {N_("Book"), BookProc},
746 {"----", NothingProc},
747 {N_("About XBoard"), AboutProc},
752 {N_("File"), fileMenu},
753 {N_("Mode"), modeMenu},
754 {N_("Action"), actionMenu},
755 {N_("Step"), stepMenu},
756 {N_("Options"), optionsMenu},
757 {N_("Help"), helpMenu},
761 #define PAUSE_BUTTON N_("P")
762 MenuItem buttonBar[] = {
765 {PAUSE_BUTTON, PauseProc},
771 #define PIECE_MENU_SIZE 18
772 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
773 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
774 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
775 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
776 N_("Empty square"), N_("Clear board") },
777 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
778 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
779 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
780 N_("Empty square"), N_("Clear board") }
782 /* must be in same order as PieceMenuStrings! */
783 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
784 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
785 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
786 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
787 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
788 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
789 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
790 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
791 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
794 #define DROP_MENU_SIZE 6
795 String dropMenuStrings[DROP_MENU_SIZE] = {
796 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
798 /* must be in same order as PieceMenuStrings! */
799 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
800 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
801 WhiteRook, WhiteQueen
809 DropMenuEnables dmEnables[] = {
827 { XtNborderWidth, 0 },
828 { XtNdefaultDistance, 0 },
832 { XtNborderWidth, 0 },
833 { XtNresizable, (XtArgVal) True },
837 { XtNborderWidth, 0 },
843 { XtNjustify, (XtArgVal) XtJustifyRight },
844 { XtNlabel, (XtArgVal) "..." },
845 { XtNresizable, (XtArgVal) True },
846 { XtNresize, (XtArgVal) False }
849 Arg messageArgs[] = {
850 { XtNjustify, (XtArgVal) XtJustifyLeft },
851 { XtNlabel, (XtArgVal) "..." },
852 { XtNresizable, (XtArgVal) True },
853 { XtNresize, (XtArgVal) False }
857 { XtNborderWidth, 0 },
858 { XtNjustify, (XtArgVal) XtJustifyLeft }
861 XtResource clientResources[] = {
862 { "flashCount", "flashCount", XtRInt, sizeof(int),
863 XtOffset(AppDataPtr, flashCount), XtRImmediate,
864 (XtPointer) FLASH_COUNT },
867 XrmOptionDescRec shellOptions[] = {
868 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
869 { "-flash", "flashCount", XrmoptionNoArg, "3" },
870 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
873 XtActionsRec boardActions[] = {
874 { "DrawPosition", DrawPositionProc },
875 { "HandleUserMove", HandleUserMove },
876 { "AnimateUserMove", AnimateUserMove },
877 { "HandlePV", HandlePV },
878 { "SelectPV", SelectPV },
879 { "StopPV", StopPV },
880 { "FileNameAction", FileNameAction },
881 { "AskQuestionProc", AskQuestionProc },
882 { "AskQuestionReplyAction", AskQuestionReplyAction },
883 { "PieceMenuPopup", PieceMenuPopup },
884 { "WhiteClock", WhiteClock },
885 { "BlackClock", BlackClock },
886 { "Iconify", Iconify },
887 { "ResetProc", ResetProc },
888 { "NewVariantProc", NewVariantProc },
889 { "LoadGameProc", LoadGameProc },
890 { "LoadNextGameProc", LoadNextGameProc },
891 { "LoadPrevGameProc", LoadPrevGameProc },
892 { "LoadSelectedProc", LoadSelectedProc },
893 { "SetFilterProc", SetFilterProc },
894 { "ReloadGameProc", ReloadGameProc },
895 { "LoadPositionProc", LoadPositionProc },
896 { "LoadNextPositionProc", LoadNextPositionProc },
897 { "LoadPrevPositionProc", LoadPrevPositionProc },
898 { "ReloadPositionProc", ReloadPositionProc },
899 { "CopyPositionProc", CopyPositionProc },
900 { "PastePositionProc", PastePositionProc },
901 { "CopyGameProc", CopyGameProc },
902 { "PasteGameProc", PasteGameProc },
903 { "SaveGameProc", SaveGameProc },
904 { "SavePositionProc", SavePositionProc },
905 { "MailMoveProc", MailMoveProc },
906 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
907 { "QuitProc", QuitProc },
908 { "MachineWhiteProc", MachineWhiteProc },
909 { "MachineBlackProc", MachineBlackProc },
910 { "AnalysisModeProc", AnalyzeModeProc },
911 { "AnalyzeFileProc", AnalyzeFileProc },
912 { "TwoMachinesProc", TwoMachinesProc },
913 { "IcsClientProc", IcsClientProc },
914 { "EditGameProc", EditGameProc },
915 { "EditPositionProc", EditPositionProc },
916 { "TrainingProc", EditPositionProc },
917 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
918 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
919 { "ShowGameListProc", ShowGameListProc },
920 { "ShowMoveListProc", HistoryShowProc},
921 { "EditTagsProc", EditCommentProc },
922 { "EditCommentProc", EditCommentProc },
923 { "IcsAlarmProc", IcsAlarmProc },
924 { "IcsInputBoxProc", IcsInputBoxProc },
925 { "PauseProc", PauseProc },
926 { "AcceptProc", AcceptProc },
927 { "DeclineProc", DeclineProc },
928 { "RematchProc", RematchProc },
929 { "CallFlagProc", CallFlagProc },
930 { "DrawProc", DrawProc },
931 { "AdjournProc", AdjournProc },
932 { "AbortProc", AbortProc },
933 { "ResignProc", ResignProc },
934 { "AdjuWhiteProc", AdjuWhiteProc },
935 { "AdjuBlackProc", AdjuBlackProc },
936 { "AdjuDrawProc", AdjuDrawProc },
937 { "EnterKeyProc", EnterKeyProc },
938 { "UpKeyProc", UpKeyProc },
939 { "DownKeyProc", DownKeyProc },
940 { "StopObservingProc", StopObservingProc },
941 { "StopExaminingProc", StopExaminingProc },
942 { "UploadProc", UploadProc },
943 { "BackwardProc", BackwardProc },
944 { "ForwardProc", ForwardProc },
945 { "ToStartProc", ToStartProc },
946 { "ToEndProc", ToEndProc },
947 { "RevertProc", RevertProc },
948 { "AnnotateProc", AnnotateProc },
949 { "TruncateGameProc", TruncateGameProc },
950 { "MoveNowProc", MoveNowProc },
951 { "RetractMoveProc", RetractMoveProc },
952 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
953 { "UciMenuProc", (XtActionProc) UciMenuProc },
954 { "TimeControlProc", (XtActionProc) TimeControlProc },
955 { "AlwaysQueenProc", AlwaysQueenProc },
956 { "AnimateDraggingProc", AnimateDraggingProc },
957 { "AnimateMovingProc", AnimateMovingProc },
958 { "AutoflagProc", AutoflagProc },
959 { "AutoflipProc", AutoflipProc },
960 { "AutobsProc", AutobsProc },
961 { "AutoraiseProc", AutoraiseProc },
962 { "AutosaveProc", AutosaveProc },
963 { "BlindfoldProc", BlindfoldProc },
964 { "FlashMovesProc", FlashMovesProc },
965 { "FlipViewProc", FlipViewProc },
966 { "GetMoveListProc", GetMoveListProc },
968 { "HighlightDraggingProc", HighlightDraggingProc },
970 { "HighlightLastMoveProc", HighlightLastMoveProc },
971 { "IcsAlarmProc", IcsAlarmProc },
972 { "MoveSoundProc", MoveSoundProc },
973 { "OldSaveStyleProc", OldSaveStyleProc },
974 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
975 { "PonderNextMoveProc", PonderNextMoveProc },
976 { "PopupExitMessageProc", PopupExitMessageProc },
977 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
978 { "PremoveProc", PremoveProc },
979 { "QuietPlayProc", QuietPlayProc },
980 { "ShowCoordsProc", ShowCoordsProc },
981 { "ShowThinkingProc", ShowThinkingProc },
982 { "HideThinkingProc", HideThinkingProc },
983 { "TestLegalityProc", TestLegalityProc },
984 { "SaveSettingsProc", SaveSettingsProc },
985 { "SaveOnExitProc", SaveOnExitProc },
986 { "InfoProc", InfoProc },
987 { "ManProc", ManProc },
988 { "HintProc", HintProc },
989 { "BookProc", BookProc },
990 { "AboutGameProc", AboutGameProc },
991 { "AboutProc", AboutProc },
992 { "DebugProc", DebugProc },
993 { "NothingProc", NothingProc },
994 { "CommentClick", (XtActionProc) CommentClick },
995 { "CommentPopDown", (XtActionProc) CommentPopDown },
996 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
997 { "TagsPopDown", (XtActionProc) TagsPopDown },
998 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
999 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1000 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1001 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1002 { "GameListPopDown", (XtActionProc) GameListPopDown },
1003 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1004 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1005 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1006 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1007 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1008 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1009 { "EnginePopDown", (XtActionProc) EnginePopDown },
1010 { "UciPopDown", (XtActionProc) UciPopDown },
1011 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1012 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1013 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1014 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1017 char globalTranslations[] =
1018 ":<Key>F9: ResignProc() \n \
1019 :Ctrl<Key>n: ResetProc() \n \
1020 :Meta<Key>V: NewVariantProc() \n \
1021 :Ctrl<Key>o: LoadGameProc() \n \
1022 :Meta<Key>Next: LoadNextGameProc() \n \
1023 :Meta<Key>Prior: LoadPrevGameProc() \n \
1024 :Ctrl<Key>s: SaveGameProc() \n \
1025 :Ctrl<Key>c: CopyGameProc() \n \
1026 :Ctrl<Key>v: PasteGameProc() \n \
1027 :Ctrl<Key>O: LoadPositionProc() \n \
1028 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1029 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1030 :Ctrl<Key>S: SavePositionProc() \n \
1031 :Ctrl<Key>C: CopyPositionProc() \n \
1032 :Ctrl<Key>V: PastePositionProc() \n \
1033 :Ctrl<Key>q: QuitProc() \n \
1034 :Ctrl<Key>w: MachineWhiteProc() \n \
1035 :Ctrl<Key>b: MachineBlackProc() \n \
1036 :Ctrl<Key>t: TwoMachinesProc() \n \
1037 :Ctrl<Key>a: AnalysisModeProc() \n \
1038 :Ctrl<Key>f: AnalyzeFileProc() \n \
1039 :Ctrl<Key>e: EditGameProc() \n \
1040 :Ctrl<Key>E: EditPositionProc() \n \
1041 :Meta<Key>O: EngineOutputProc() \n \
1042 :Meta<Key>E: EvalGraphProc() \n \
1043 :Meta<Key>G: ShowGameListProc() \n \
1044 :Meta<Key>H: ShowMoveListProc() \n \
1045 :<Key>Pause: PauseProc() \n \
1046 :<Key>F3: AcceptProc() \n \
1047 :<Key>F4: DeclineProc() \n \
1048 :<Key>F12: RematchProc() \n \
1049 :<Key>F5: CallFlagProc() \n \
1050 :<Key>F6: DrawProc() \n \
1051 :<Key>F7: AdjournProc() \n \
1052 :<Key>F8: AbortProc() \n \
1053 :<Key>F10: StopObservingProc() \n \
1054 :<Key>F11: StopExaminingProc() \n \
1055 :Meta Ctrl<Key>F12: DebugProc() \n \
1056 :Meta<Key>End: ToEndProc() \n \
1057 :Meta<Key>Right: ForwardProc() \n \
1058 :Meta<Key>Home: ToStartProc() \n \
1059 :Meta<Key>Left: BackwardProc() \n \
1060 :Ctrl<Key>m: MoveNowProc() \n \
1061 :Ctrl<Key>x: RetractMoveProc() \n \
1062 :Meta<Key>J: EngineMenuProc() \n \
1063 :Meta<Key>U: UciMenuProc() \n \
1064 :Meta<Key>T: TimeControlProc() \n \
1065 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1066 :Ctrl<Key>F: AutoflagProc() \n \
1067 :Ctrl<Key>A: AnimateMovingProc() \n \
1068 :Ctrl<Key>P: PonderNextMoveProc() \n \
1069 :Ctrl<Key>L: TestLegalityProc() \n \
1070 :Ctrl<Key>H: HideThinkingProc() \n \
1071 :<Key>-: Iconify() \n \
1072 :<Key>F1: ManProc() \n \
1073 :<Key>F2: FlipViewProc() \n \
1074 <KeyDown>.: BackwardProc() \n \
1075 <KeyUp>.: ForwardProc() \n \
1076 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1077 \"Send to chess program:\",,1) \n \
1078 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1079 \"Send to second chess program:\",,2) \n";
1081 char boardTranslations[] =
1082 "<Btn1Down>: HandleUserMove() \n \
1083 <Btn1Up>: HandleUserMove() \n \
1084 <Btn1Motion>: AnimateUserMove() \n \
1085 <Btn3Motion>: HandlePV() \n \
1086 <Btn3Up>: PieceMenuPopup(menuB) \n \
1087 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1088 PieceMenuPopup(menuB) \n \
1089 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1090 PieceMenuPopup(menuW) \n \
1091 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1092 PieceMenuPopup(menuW) \n \
1093 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1094 PieceMenuPopup(menuB) \n";
1096 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1097 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1099 char ICSInputTranslations[] =
1100 "<Key>Up: UpKeyProc() \n "
1101 "<Key>Down: DownKeyProc() \n "
1102 "<Key>Return: EnterKeyProc() \n";
1104 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1105 // as the widget is destroyed before the up-click can call extend-end
1106 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1108 String xboardResources[] = {
1109 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1110 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1111 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1116 /* Max possible square size */
1117 #define MAXSQSIZE 256
1119 static int xpm_avail[MAXSQSIZE];
1121 #ifdef HAVE_DIR_STRUCT
1123 /* Extract piece size from filename */
1125 xpm_getsize(name, len, ext)
1136 if ((p=strchr(name, '.')) == NULL ||
1137 StrCaseCmp(p+1, ext) != 0)
1143 while (*p && isdigit(*p))
1150 /* Setup xpm_avail */
1152 xpm_getavail(dirname, ext)
1160 for (i=0; i<MAXSQSIZE; ++i)
1163 if (appData.debugMode)
1164 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1166 dir = opendir(dirname);
1169 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1170 programName, dirname);
1174 while ((ent=readdir(dir)) != NULL) {
1175 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1176 if (i > 0 && i < MAXSQSIZE)
1186 xpm_print_avail(fp, ext)
1192 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1193 for (i=1; i<MAXSQSIZE; ++i) {
1199 /* Return XPM piecesize closest to size */
1201 xpm_closest_to(dirname, size, ext)
1207 int sm_diff = MAXSQSIZE;
1211 xpm_getavail(dirname, ext);
1213 if (appData.debugMode)
1214 xpm_print_avail(stderr, ext);
1216 for (i=1; i<MAXSQSIZE; ++i) {
1219 diff = (diff<0) ? -diff : diff;
1220 if (diff < sm_diff) {
1228 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1234 #else /* !HAVE_DIR_STRUCT */
1235 /* If we are on a system without a DIR struct, we can't
1236 read the directory, so we can't collect a list of
1237 filenames, etc., so we can't do any size-fitting. */
1239 xpm_closest_to(dirname, size, ext)
1244 fprintf(stderr, _("\
1245 Warning: No DIR structure found on this system --\n\
1246 Unable to autosize for XPM/XIM pieces.\n\
1247 Please report this error to frankm@hiwaay.net.\n\
1248 Include system type & operating system in message.\n"));
1251 #endif /* HAVE_DIR_STRUCT */
1253 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1254 "magenta", "cyan", "white" };
1258 TextColors textColors[(int)NColorClasses];
1260 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1262 parse_color(str, which)
1266 char *p, buf[100], *d;
1269 if (strlen(str) > 99) /* watch bounds on buf */
1274 for (i=0; i<which; ++i) {
1281 /* Could be looking at something like:
1283 .. in which case we want to stop on a comma also */
1284 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1288 return -1; /* Use default for empty field */
1291 if (which == 2 || isdigit(*p))
1294 while (*p && isalpha(*p))
1299 for (i=0; i<8; ++i) {
1300 if (!StrCaseCmp(buf, cnames[i]))
1301 return which? (i+40) : (i+30);
1303 if (!StrCaseCmp(buf, "default")) return -1;
1305 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1310 parse_cpair(cc, str)
1314 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1315 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1320 /* bg and attr are optional */
1321 textColors[(int)cc].bg = parse_color(str, 1);
1322 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1323 textColors[(int)cc].attr = 0;
1329 /* Arrange to catch delete-window events */
1330 Atom wm_delete_window;
1332 CatchDeleteWindow(Widget w, String procname)
1335 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1336 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1337 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1344 XtSetArg(args[0], XtNiconic, False);
1345 XtSetValues(shellWidget, args, 1);
1347 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1350 //---------------------------------------------------------------------------------------------------------
1351 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1354 #define CW_USEDEFAULT (1<<31)
1355 #define ICS_TEXT_MENU_SIZE 90
1356 #define DEBUG_FILE "xboard.debug"
1357 #define SetCurrentDirectory chdir
1358 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1362 // these two must some day move to frontend.h, when they are implemented
1363 Boolean GameListIsUp();
1365 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1368 // front-end part of option handling
1370 // [HGM] This platform-dependent table provides the location for storing the color info
1371 extern char *crWhite, * crBlack;
1375 &appData.whitePieceColor,
1376 &appData.blackPieceColor,
1377 &appData.lightSquareColor,
1378 &appData.darkSquareColor,
1379 &appData.highlightSquareColor,
1380 &appData.premoveHighlightColor,
1381 &appData.lowTimeWarningColor,
1392 // [HGM] font: keep a font for each square size, even non-stndard ones
1393 #define NUM_SIZES 18
1394 #define MAX_SIZE 130
1395 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1396 char *fontTable[NUM_FONTS][MAX_SIZE];
1399 ParseFont(char *name, int number)
1400 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1402 if(sscanf(name, "size%d:", &size)) {
1403 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1404 // defer processing it until we know if it matches our board size
1405 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1406 fontTable[number][size] = strdup(strchr(name, ':')+1);
1407 fontValid[number][size] = True;
1412 case 0: // CLOCK_FONT
1413 appData.clockFont = strdup(name);
1415 case 1: // MESSAGE_FONT
1416 appData.font = strdup(name);
1418 case 2: // COORD_FONT
1419 appData.coordFont = strdup(name);
1424 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1429 { // only 2 fonts currently
1430 appData.clockFont = CLOCK_FONT_NAME;
1431 appData.coordFont = COORD_FONT_NAME;
1432 appData.font = DEFAULT_FONT_NAME;
1437 { // no-op, until we identify the code for this already in XBoard and move it here
1441 ParseColor(int n, char *name)
1442 { // in XBoard, just copy the color-name string
1443 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1447 ParseTextAttribs(ColorClass cc, char *s)
1449 (&appData.colorShout)[cc] = strdup(s);
1453 ParseBoardSize(void *addr, char *name)
1455 appData.boardSize = strdup(name);
1460 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1464 SetCommPortDefaults()
1465 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1468 // [HGM] args: these three cases taken out to stay in front-end
1470 SaveFontArg(FILE *f, ArgDescriptor *ad)
1473 int i, n = (int)ad->argLoc;
1475 case 0: // CLOCK_FONT
1476 name = appData.clockFont;
1478 case 1: // MESSAGE_FONT
1479 name = appData.font;
1481 case 2: // COORD_FONT
1482 name = appData.coordFont;
1487 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1488 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1489 fontTable[n][squareSize] = strdup(name);
1490 fontValid[n][squareSize] = True;
1493 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1494 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1499 { // nothing to do, as the sounds are at all times represented by their text-string names already
1503 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1504 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1505 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1509 SaveColor(FILE *f, ArgDescriptor *ad)
1510 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1511 if(colorVariable[(int)ad->argLoc])
1512 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1516 SaveBoardSize(FILE *f, char *name, void *addr)
1517 { // wrapper to shield back-end from BoardSize & sizeInfo
1518 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1522 ParseCommPortSettings(char *s)
1523 { // no such option in XBoard (yet)
1526 extern Widget engineOutputShell;
1527 extern Widget tagsShell, editTagsShell;
1529 GetActualPlacement(Widget wg, WindowPlacement *wp)
1539 XtSetArg(args[i], XtNx, &x); i++;
1540 XtSetArg(args[i], XtNy, &y); i++;
1541 XtSetArg(args[i], XtNwidth, &w); i++;
1542 XtSetArg(args[i], XtNheight, &h); i++;
1543 XtGetValues(wg, args, i);
1552 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1553 // In XBoard this will have to wait until awareness of window parameters is implemented
1554 GetActualPlacement(shellWidget, &wpMain);
1555 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1556 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1557 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1558 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1559 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1560 else GetActualPlacement(editShell, &wpComment);
1561 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1562 else GetActualPlacement(editTagsShell, &wpTags);
1566 PrintCommPortSettings(FILE *f, char *name)
1567 { // This option does not exist in XBoard
1571 MySearchPath(char *installDir, char *name, char *fullname)
1572 { // just append installDir and name. Perhaps ExpandPath should be used here?
1573 name = ExpandPathName(name);
1574 if(name && name[0] == '/')
1575 safeStrCpy(fullname, name, MSG_SIZ );
1577 sprintf(fullname, "%s%c%s", installDir, '/', name);
1583 MyGetFullPathName(char *name, char *fullname)
1584 { // should use ExpandPath?
1585 name = ExpandPathName(name);
1586 safeStrCpy(fullname, name, MSG_SIZ );
1591 EnsureOnScreen(int *x, int *y, int minX, int minY)
1598 { // [HGM] args: allows testing if main window is realized from back-end
1599 return xBoardWindow != 0;
1603 PopUpStartupDialog()
1604 { // start menu not implemented in XBoard
1608 ConvertToLine(int argc, char **argv)
1610 static char line[128*1024], buf[1024];
1614 for(i=1; i<argc; i++)
1616 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1617 && argv[i][0] != '{' )
1618 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1620 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1621 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1624 line[strlen(line)-1] = NULLCHAR;
1628 //--------------------------------------------------------------------------------------------
1630 extern Boolean twoBoards, partnerUp;
1633 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1635 #define BoardSize int
1636 void InitDrawingSizes(BoardSize boardSize, int flags)
1637 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1638 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1640 XtGeometryResult gres;
1643 if(!formWidget) return;
1646 * Enable shell resizing.
1648 shellArgs[0].value = (XtArgVal) &w;
1649 shellArgs[1].value = (XtArgVal) &h;
1650 XtGetValues(shellWidget, shellArgs, 2);
1652 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1653 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1654 XtSetValues(shellWidget, &shellArgs[2], 4);
1656 XtSetArg(args[0], XtNdefaultDistance, &sep);
1657 XtGetValues(formWidget, args, 1);
1659 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1660 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1662 hOffset = boardWidth + 10;
1663 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1664 secondSegments[i] = gridSegments[i];
1665 secondSegments[i].x1 += hOffset;
1666 secondSegments[i].x2 += hOffset;
1669 XtSetArg(args[0], XtNwidth, boardWidth);
1670 XtSetArg(args[1], XtNheight, boardHeight);
1671 XtSetValues(boardWidget, args, 2);
1673 timerWidth = (boardWidth - sep) / 2;
1674 XtSetArg(args[0], XtNwidth, timerWidth);
1675 XtSetValues(whiteTimerWidget, args, 1);
1676 XtSetValues(blackTimerWidget, args, 1);
1678 XawFormDoLayout(formWidget, False);
1680 if (appData.titleInWindow) {
1682 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1683 XtSetArg(args[i], XtNheight, &h); i++;
1684 XtGetValues(titleWidget, args, i);
1686 w = boardWidth - 2*bor;
1688 XtSetArg(args[0], XtNwidth, &w);
1689 XtGetValues(menuBarWidget, args, 1);
1690 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1693 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1694 if (gres != XtGeometryYes && appData.debugMode) {
1696 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1697 programName, gres, w, h, wr, hr);
1701 XawFormDoLayout(formWidget, True);
1704 * Inhibit shell resizing.
1706 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1707 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1708 shellArgs[4].value = shellArgs[2].value = w;
1709 shellArgs[5].value = shellArgs[3].value = h;
1710 XtSetValues(shellWidget, &shellArgs[0], 6);
1712 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1715 for(i=0; i<4; i++) {
1717 for(p=0; p<=(int)WhiteKing; p++)
1718 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1719 if(gameInfo.variant == VariantShogi) {
1720 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1721 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1722 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1723 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1724 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1727 if(gameInfo.variant == VariantGothic) {
1728 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1732 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1733 for(p=0; p<=(int)WhiteKing; p++)
1734 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1735 if(gameInfo.variant == VariantShogi) {
1736 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1737 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1738 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1739 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1740 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1743 if(gameInfo.variant == VariantGothic) {
1744 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1750 for(i=0; i<2; i++) {
1752 for(p=0; p<=(int)WhiteKing; p++)
1753 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1754 if(gameInfo.variant == VariantShogi) {
1755 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1756 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1757 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1758 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1759 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1762 if(gameInfo.variant == VariantGothic) {
1763 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1779 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1780 XSetWindowAttributes window_attributes;
1782 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1783 XrmValue vFrom, vTo;
1784 XtGeometryResult gres;
1787 int forceMono = False;
1789 srandom(time(0)); // [HGM] book: make random truly random
1791 setbuf(stdout, NULL);
1792 setbuf(stderr, NULL);
1795 # if HAVE_LIBREADLINE
1796 /* install gnu-readline handler */
1797 rl_callback_handler_install("> ", ReadlineCompleteHandler);
1798 rl_readline_name="XBoard";
1801 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1802 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1806 programName = strrchr(argv[0], '/');
1807 if (programName == NULL)
1808 programName = argv[0];
1813 XtSetLanguageProc(NULL, NULL, NULL);
1814 bindtextdomain(PACKAGE, LOCALEDIR);
1815 textdomain(PACKAGE);
1819 XtAppInitialize(&appContext, "XBoard", shellOptions,
1820 XtNumber(shellOptions),
1821 &argc, argv, xboardResources, NULL, 0);
1822 appData.boardSize = "";
1823 InitAppData(ConvertToLine(argc, argv));
1825 if (p == NULL) p = "/tmp";
1826 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1827 gameCopyFilename = (char*) malloc(i);
1828 gamePasteFilename = (char*) malloc(i);
1829 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1830 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1832 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1833 clientResources, XtNumber(clientResources),
1836 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1837 static char buf[MSG_SIZ];
1838 EscapeExpand(buf, appData.initString);
1839 appData.initString = strdup(buf);
1840 EscapeExpand(buf, appData.secondInitString);
1841 appData.secondInitString = strdup(buf);
1842 EscapeExpand(buf, appData.firstComputerString);
1843 appData.firstComputerString = strdup(buf);
1844 EscapeExpand(buf, appData.secondComputerString);
1845 appData.secondComputerString = strdup(buf);
1848 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1851 if (chdir(chessDir) != 0) {
1852 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1858 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1859 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1860 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1861 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1864 setbuf(debugFP, NULL);
1867 /* [HGM,HR] make sure board size is acceptable */
1868 if(appData.NrFiles > BOARD_FILES ||
1869 appData.NrRanks > BOARD_RANKS )
1870 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1873 /* This feature does not work; animation needs a rewrite */
1874 appData.highlightDragging = FALSE;
1878 xDisplay = XtDisplay(shellWidget);
1879 xScreen = DefaultScreen(xDisplay);
1880 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1882 gameInfo.variant = StringToVariant(appData.variant);
1883 InitPosition(FALSE);
1886 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1888 if (isdigit(appData.boardSize[0])) {
1889 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1890 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1891 &fontPxlSize, &smallLayout, &tinyLayout);
1893 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1894 programName, appData.boardSize);
1898 /* Find some defaults; use the nearest known size */
1899 SizeDefaults *szd, *nearest;
1900 int distance = 99999;
1901 nearest = szd = sizeDefaults;
1902 while (szd->name != NULL) {
1903 if (abs(szd->squareSize - squareSize) < distance) {
1905 distance = abs(szd->squareSize - squareSize);
1906 if (distance == 0) break;
1910 if (i < 2) lineGap = nearest->lineGap;
1911 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1912 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1913 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1914 if (i < 6) smallLayout = nearest->smallLayout;
1915 if (i < 7) tinyLayout = nearest->tinyLayout;
1918 SizeDefaults *szd = sizeDefaults;
1919 if (*appData.boardSize == NULLCHAR) {
1920 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1921 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1924 if (szd->name == NULL) szd--;
1925 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1927 while (szd->name != NULL &&
1928 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1929 if (szd->name == NULL) {
1930 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1931 programName, appData.boardSize);
1935 squareSize = szd->squareSize;
1936 lineGap = szd->lineGap;
1937 clockFontPxlSize = szd->clockFontPxlSize;
1938 coordFontPxlSize = szd->coordFontPxlSize;
1939 fontPxlSize = szd->fontPxlSize;
1940 smallLayout = szd->smallLayout;
1941 tinyLayout = szd->tinyLayout;
1942 // [HGM] font: use defaults from settings file if available and not overruled
1944 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1945 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1946 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1947 appData.font = fontTable[MESSAGE_FONT][squareSize];
1948 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1949 appData.coordFont = fontTable[COORD_FONT][squareSize];
1951 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1952 if (strlen(appData.pixmapDirectory) > 0) {
1953 p = ExpandPathName(appData.pixmapDirectory);
1955 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1956 appData.pixmapDirectory);
1959 if (appData.debugMode) {
1960 fprintf(stderr, _("\
1961 XBoard square size (hint): %d\n\
1962 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1964 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1965 if (appData.debugMode) {
1966 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1970 /* [HR] height treated separately (hacked) */
1971 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1972 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1973 if (appData.showJail == 1) {
1974 /* Jail on top and bottom */
1975 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1976 XtSetArg(boardArgs[2], XtNheight,
1977 boardHeight + 2*(lineGap + squareSize));
1978 } else if (appData.showJail == 2) {
1980 XtSetArg(boardArgs[1], XtNwidth,
1981 boardWidth + 2*(lineGap + squareSize));
1982 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1985 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1986 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1990 * Determine what fonts to use.
1992 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1993 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1994 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1995 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1996 coordFontID = XLoadFont(xDisplay, appData.coordFont);
1997 coordFontStruct = XQueryFont(xDisplay, coordFontID);
1998 appData.font = FindFont(appData.font, fontPxlSize);
1999 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2000 countFontStruct = XQueryFont(xDisplay, countFontID);
2001 // appData.font = FindFont(appData.font, fontPxlSize);
2003 xdb = XtDatabase(xDisplay);
2004 XrmPutStringResource(&xdb, "*font", appData.font);
2007 * Detect if there are not enough colors available and adapt.
2009 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2010 appData.monoMode = True;
2013 if (!appData.monoMode) {
2014 vFrom.addr = (caddr_t) appData.lightSquareColor;
2015 vFrom.size = strlen(appData.lightSquareColor);
2016 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2017 if (vTo.addr == NULL) {
2018 appData.monoMode = True;
2021 lightSquareColor = *(Pixel *) vTo.addr;
2024 if (!appData.monoMode) {
2025 vFrom.addr = (caddr_t) appData.darkSquareColor;
2026 vFrom.size = strlen(appData.darkSquareColor);
2027 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2028 if (vTo.addr == NULL) {
2029 appData.monoMode = True;
2032 darkSquareColor = *(Pixel *) vTo.addr;
2035 if (!appData.monoMode) {
2036 vFrom.addr = (caddr_t) appData.whitePieceColor;
2037 vFrom.size = strlen(appData.whitePieceColor);
2038 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2039 if (vTo.addr == NULL) {
2040 appData.monoMode = True;
2043 whitePieceColor = *(Pixel *) vTo.addr;
2046 if (!appData.monoMode) {
2047 vFrom.addr = (caddr_t) appData.blackPieceColor;
2048 vFrom.size = strlen(appData.blackPieceColor);
2049 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2050 if (vTo.addr == NULL) {
2051 appData.monoMode = True;
2054 blackPieceColor = *(Pixel *) vTo.addr;
2058 if (!appData.monoMode) {
2059 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2060 vFrom.size = strlen(appData.highlightSquareColor);
2061 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2062 if (vTo.addr == NULL) {
2063 appData.monoMode = True;
2066 highlightSquareColor = *(Pixel *) vTo.addr;
2070 if (!appData.monoMode) {
2071 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2072 vFrom.size = strlen(appData.premoveHighlightColor);
2073 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2074 if (vTo.addr == NULL) {
2075 appData.monoMode = True;
2078 premoveHighlightColor = *(Pixel *) vTo.addr;
2083 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2086 if (appData.bitmapDirectory == NULL ||
2087 appData.bitmapDirectory[0] == NULLCHAR)
2088 appData.bitmapDirectory = DEF_BITMAP_DIR;
2091 if (appData.lowTimeWarning && !appData.monoMode) {
2092 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2093 vFrom.size = strlen(appData.lowTimeWarningColor);
2094 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2095 if (vTo.addr == NULL)
2096 appData.monoMode = True;
2098 lowTimeWarningColor = *(Pixel *) vTo.addr;
2101 if (appData.monoMode && appData.debugMode) {
2102 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2103 (unsigned long) XWhitePixel(xDisplay, xScreen),
2104 (unsigned long) XBlackPixel(xDisplay, xScreen));
2107 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2108 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2109 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2110 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2111 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2112 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2113 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2114 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2115 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2116 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2118 if (appData.colorize) {
2120 _("%s: can't parse color names; disabling colorization\n"),
2123 appData.colorize = FALSE;
2125 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2126 textColors[ColorNone].attr = 0;
2128 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2134 layoutName = "tinyLayout";
2135 } else if (smallLayout) {
2136 layoutName = "smallLayout";
2138 layoutName = "normalLayout";
2140 /* Outer layoutWidget is there only to provide a name for use in
2141 resources that depend on the layout style */
2143 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2144 layoutArgs, XtNumber(layoutArgs));
2146 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2147 formArgs, XtNumber(formArgs));
2148 XtSetArg(args[0], XtNdefaultDistance, &sep);
2149 XtGetValues(formWidget, args, 1);
2152 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2153 XtSetArg(args[0], XtNtop, XtChainTop);
2154 XtSetArg(args[1], XtNbottom, XtChainTop);
2155 XtSetArg(args[2], XtNright, XtChainLeft);
2156 XtSetValues(menuBarWidget, args, 3);
2158 widgetList[j++] = whiteTimerWidget =
2159 XtCreateWidget("whiteTime", labelWidgetClass,
2160 formWidget, timerArgs, XtNumber(timerArgs));
2161 XtSetArg(args[0], XtNfont, clockFontStruct);
2162 XtSetArg(args[1], XtNtop, XtChainTop);
2163 XtSetArg(args[2], XtNbottom, XtChainTop);
2164 XtSetValues(whiteTimerWidget, args, 3);
2166 widgetList[j++] = blackTimerWidget =
2167 XtCreateWidget("blackTime", labelWidgetClass,
2168 formWidget, timerArgs, XtNumber(timerArgs));
2169 XtSetArg(args[0], XtNfont, clockFontStruct);
2170 XtSetArg(args[1], XtNtop, XtChainTop);
2171 XtSetArg(args[2], XtNbottom, XtChainTop);
2172 XtSetValues(blackTimerWidget, args, 3);
2174 if (appData.titleInWindow) {
2175 widgetList[j++] = titleWidget =
2176 XtCreateWidget("title", labelWidgetClass, formWidget,
2177 titleArgs, XtNumber(titleArgs));
2178 XtSetArg(args[0], XtNtop, XtChainTop);
2179 XtSetArg(args[1], XtNbottom, XtChainTop);
2180 XtSetValues(titleWidget, args, 2);
2183 if (appData.showButtonBar) {
2184 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2185 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2186 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2187 XtSetArg(args[2], XtNtop, XtChainTop);
2188 XtSetArg(args[3], XtNbottom, XtChainTop);
2189 XtSetValues(buttonBarWidget, args, 4);
2192 widgetList[j++] = messageWidget =
2193 XtCreateWidget("message", labelWidgetClass, formWidget,
2194 messageArgs, XtNumber(messageArgs));
2195 XtSetArg(args[0], XtNtop, XtChainTop);
2196 XtSetArg(args[1], XtNbottom, XtChainTop);
2197 XtSetValues(messageWidget, args, 2);
2199 widgetList[j++] = boardWidget =
2200 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2201 XtNumber(boardArgs));
2203 XtManageChildren(widgetList, j);
2205 timerWidth = (boardWidth - sep) / 2;
2206 XtSetArg(args[0], XtNwidth, timerWidth);
2207 XtSetValues(whiteTimerWidget, args, 1);
2208 XtSetValues(blackTimerWidget, args, 1);
2210 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2211 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2212 XtGetValues(whiteTimerWidget, args, 2);
2214 if (appData.showButtonBar) {
2215 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2216 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2217 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2221 * formWidget uses these constraints but they are stored
2225 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2226 XtSetValues(menuBarWidget, args, i);
2227 if (appData.titleInWindow) {
2230 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2231 XtSetValues(whiteTimerWidget, args, i);
2233 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2234 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2235 XtSetValues(blackTimerWidget, args, i);
2237 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2238 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2239 XtSetValues(titleWidget, args, i);
2241 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2242 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2243 XtSetValues(messageWidget, args, i);
2244 if (appData.showButtonBar) {
2246 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2247 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2248 XtSetValues(buttonBarWidget, args, i);
2252 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2253 XtSetValues(whiteTimerWidget, args, i);
2255 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2256 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2257 XtSetValues(blackTimerWidget, args, i);
2259 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2260 XtSetValues(titleWidget, args, i);
2262 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2263 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2264 XtSetValues(messageWidget, args, i);
2265 if (appData.showButtonBar) {
2267 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2268 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2269 XtSetValues(buttonBarWidget, args, i);
2274 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2275 XtSetValues(whiteTimerWidget, args, i);
2277 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2278 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2279 XtSetValues(blackTimerWidget, args, i);
2281 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2282 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2283 XtSetValues(messageWidget, args, i);
2284 if (appData.showButtonBar) {
2286 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2287 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2288 XtSetValues(buttonBarWidget, args, i);
2292 XtSetArg(args[0], XtNfromVert, messageWidget);
2293 XtSetArg(args[1], XtNtop, XtChainTop);
2294 XtSetArg(args[2], XtNbottom, XtChainBottom);
2295 XtSetArg(args[3], XtNleft, XtChainLeft);
2296 XtSetArg(args[4], XtNright, XtChainRight);
2297 XtSetValues(boardWidget, args, 5);
2299 XtRealizeWidget(shellWidget);
2302 XtSetArg(args[0], XtNx, wpMain.x);
2303 XtSetArg(args[1], XtNy, wpMain.y);
2304 XtSetValues(shellWidget, args, 2);
2308 * Correct the width of the message and title widgets.
2309 * It is not known why some systems need the extra fudge term.
2310 * The value "2" is probably larger than needed.
2312 XawFormDoLayout(formWidget, False);
2314 #define WIDTH_FUDGE 2
2316 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2317 XtSetArg(args[i], XtNheight, &h); i++;
2318 XtGetValues(messageWidget, args, i);
2319 if (appData.showButtonBar) {
2321 XtSetArg(args[i], XtNwidth, &w); i++;
2322 XtGetValues(buttonBarWidget, args, i);
2323 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2325 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2328 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2329 if (gres != XtGeometryYes && appData.debugMode) {
2330 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2331 programName, gres, w, h, wr, hr);
2334 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2335 /* The size used for the child widget in layout lags one resize behind
2336 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2338 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2339 if (gres != XtGeometryYes && appData.debugMode) {
2340 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2341 programName, gres, w, h, wr, hr);
2344 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2345 XtSetArg(args[1], XtNright, XtChainRight);
2346 XtSetValues(messageWidget, args, 2);
2348 if (appData.titleInWindow) {
2350 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2351 XtSetArg(args[i], XtNheight, &h); i++;
2352 XtGetValues(titleWidget, args, i);
2354 w = boardWidth - 2*bor;
2356 XtSetArg(args[0], XtNwidth, &w);
2357 XtGetValues(menuBarWidget, args, 1);
2358 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2361 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2362 if (gres != XtGeometryYes && appData.debugMode) {
2364 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2365 programName, gres, w, h, wr, hr);
2368 XawFormDoLayout(formWidget, True);
2370 xBoardWindow = XtWindow(boardWidget);
2372 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2373 // not need to go into InitDrawingSizes().
2377 * Create X checkmark bitmap and initialize option menu checks.
2379 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2380 checkmark_bits, checkmark_width, checkmark_height);
2381 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2382 if (appData.alwaysPromoteToQueen) {
2383 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2386 if (appData.animateDragging) {
2387 XtSetValues(XtNameToWidget(menuBarWidget,
2388 "menuOptions.Animate Dragging"),
2391 if (appData.animate) {
2392 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2395 if (appData.autoComment) {
2396 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2399 if (appData.autoCallFlag) {
2400 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2403 if (appData.autoFlipView) {
2404 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2407 if (appData.autoObserve) {
2408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2411 if (appData.autoRaiseBoard) {
2412 XtSetValues(XtNameToWidget(menuBarWidget,
2413 "menuOptions.Auto Raise Board"), args, 1);
2415 if (appData.autoSaveGames) {
2416 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2419 if (appData.saveGameFile[0] != NULLCHAR) {
2420 /* Can't turn this off from menu */
2421 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2423 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2427 if (appData.blindfold) {
2428 XtSetValues(XtNameToWidget(menuBarWidget,
2429 "menuOptions.Blindfold"), args, 1);
2431 if (appData.flashCount > 0) {
2432 XtSetValues(XtNameToWidget(menuBarWidget,
2433 "menuOptions.Flash Moves"),
2436 if (appData.getMoveList) {
2437 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2441 if (appData.highlightDragging) {
2442 XtSetValues(XtNameToWidget(menuBarWidget,
2443 "menuOptions.Highlight Dragging"),
2447 if (appData.highlightLastMove) {
2448 XtSetValues(XtNameToWidget(menuBarWidget,
2449 "menuOptions.Highlight Last Move"),
2452 if (appData.icsAlarm) {
2453 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2456 if (appData.ringBellAfterMoves) {
2457 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2460 if (appData.oldSaveStyle) {
2461 XtSetValues(XtNameToWidget(menuBarWidget,
2462 "menuOptions.Old Save Style"), args, 1);
2464 if (appData.periodicUpdates) {
2465 XtSetValues(XtNameToWidget(menuBarWidget,
2466 "menuOptions.Periodic Updates"), args, 1);
2468 if (appData.ponderNextMove) {
2469 XtSetValues(XtNameToWidget(menuBarWidget,
2470 "menuOptions.Ponder Next Move"), args, 1);
2472 if (appData.popupExitMessage) {
2473 XtSetValues(XtNameToWidget(menuBarWidget,
2474 "menuOptions.Popup Exit Message"), args, 1);
2476 if (appData.popupMoveErrors) {
2477 XtSetValues(XtNameToWidget(menuBarWidget,
2478 "menuOptions.Popup Move Errors"), args, 1);
2480 if (appData.premove) {
2481 XtSetValues(XtNameToWidget(menuBarWidget,
2482 "menuOptions.Premove"), args, 1);
2484 if (appData.quietPlay) {
2485 XtSetValues(XtNameToWidget(menuBarWidget,
2486 "menuOptions.Quiet Play"), args, 1);
2488 if (appData.showCoords) {
2489 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2492 if (appData.hideThinkingFromHuman) {
2493 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2496 if (appData.testLegality) {
2497 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2500 if (saveSettingsOnExit) {
2501 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2508 ReadBitmap(&wIconPixmap, "icon_white.bm",
2509 icon_white_bits, icon_white_width, icon_white_height);
2510 ReadBitmap(&bIconPixmap, "icon_black.bm",
2511 icon_black_bits, icon_black_width, icon_black_height);
2512 iconPixmap = wIconPixmap;
2514 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2515 XtSetValues(shellWidget, args, i);
2518 * Create a cursor for the board widget.
2520 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2521 XChangeWindowAttributes(xDisplay, xBoardWindow,
2522 CWCursor, &window_attributes);
2525 * Inhibit shell resizing.
2527 shellArgs[0].value = (XtArgVal) &w;
2528 shellArgs[1].value = (XtArgVal) &h;
2529 XtGetValues(shellWidget, shellArgs, 2);
2530 shellArgs[4].value = shellArgs[2].value = w;
2531 shellArgs[5].value = shellArgs[3].value = h;
2532 XtSetValues(shellWidget, &shellArgs[2], 4);
2533 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2534 marginH = h - boardHeight;
2536 CatchDeleteWindow(shellWidget, "QuitProc");
2541 if (appData.bitmapDirectory[0] != NULLCHAR) {
2548 /* Create regular pieces */
2549 if (!useImages) CreatePieces();
2554 if (appData.animate || appData.animateDragging)
2557 XtAugmentTranslations(formWidget,
2558 XtParseTranslationTable(globalTranslations));
2559 XtAugmentTranslations(boardWidget,
2560 XtParseTranslationTable(boardTranslations));
2561 XtAugmentTranslations(whiteTimerWidget,
2562 XtParseTranslationTable(whiteTranslations));
2563 XtAugmentTranslations(blackTimerWidget,
2564 XtParseTranslationTable(blackTranslations));
2566 /* Why is the following needed on some versions of X instead
2567 * of a translation? */
2568 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2569 (XtEventHandler) EventProc, NULL);
2572 /* [AS] Restore layout */
2573 if( wpMoveHistory.visible ) {
2577 if( wpEvalGraph.visible )
2582 if( wpEngineOutput.visible ) {
2583 EngineOutputPopUp();
2588 if (errorExitStatus == -1) {
2589 if (appData.icsActive) {
2590 /* We now wait until we see "login:" from the ICS before
2591 sending the logon script (problems with timestamp otherwise) */
2592 /*ICSInitScript();*/
2593 if (appData.icsInputBox) ICSInputBoxPopUp();
2597 signal(SIGWINCH, TermSizeSigHandler);
2599 signal(SIGINT, IntSigHandler);
2600 signal(SIGTERM, IntSigHandler);
2601 if (*appData.cmailGameName != NULLCHAR) {
2602 signal(SIGUSR1, CmailSigHandler);
2605 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2607 XtSetKeyboardFocus(shellWidget, formWidget);
2609 XtAppMainLoop(appContext);
2610 if (appData.debugMode) fclose(debugFP); // [DM] debug
2617 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2618 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2620 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2621 unlink(gameCopyFilename);
2622 unlink(gamePasteFilename);
2624 # if HAVE_LIBREADLINE
2625 /* remove gnu-readline handler. */
2626 rl_callback_handler_remove();
2632 RETSIGTYPE TermSizeSigHandler(int sig)
2645 CmailSigHandler(sig)
2651 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2653 /* Activate call-back function CmailSigHandlerCallBack() */
2654 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2656 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2660 CmailSigHandlerCallBack(isr, closure, message, count, error)
2668 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2670 /**** end signal code ****/
2676 /* try to open the icsLogon script, either in the location given
2677 * or in the users HOME directory
2684 f = fopen(appData.icsLogon, "r");
2687 homedir = getenv("HOME");
2688 if (homedir != NULL)
2690 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2691 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2692 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2693 f = fopen(buf, "r");
2698 ProcessICSInitScript(f);
2700 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2709 EditCommentPopDown();
2724 if (!menuBarWidget) return;
2725 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2727 DisplayError("menuStep.Revert", 0);
2729 XtSetSensitive(w, !grey);
2731 w = XtNameToWidget(menuBarWidget, "menuStep.Annotate");
2733 DisplayError("menuStep.Annotate", 0);
2735 XtSetSensitive(w, !grey);
2740 SetMenuEnables(enab)
2744 if (!menuBarWidget) return;
2745 while (enab->name != NULL) {
2746 w = XtNameToWidget(menuBarWidget, enab->name);
2748 DisplayError(enab->name, 0);
2750 XtSetSensitive(w, enab->value);
2756 Enables icsEnables[] = {
2757 { "menuFile.Mail Move", False },
2758 { "menuFile.Reload CMail Message", False },
2759 { "menuMode.Machine Black", False },
2760 { "menuMode.Machine White", False },
2761 { "menuMode.Analysis Mode", False },
2762 { "menuMode.Analyze File", False },
2763 { "menuMode.Two Machines", False },
2765 { "menuHelp.Hint", False },
2766 { "menuHelp.Book", False },
2767 { "menuStep.Move Now", False },
2768 { "menuOptions.Periodic Updates", False },
2769 { "menuOptions.Hide Thinking", False },
2770 { "menuOptions.Ponder Next Move", False },
2772 { "menuStep.Annotate", False },
2776 Enables ncpEnables[] = {
2777 { "menuFile.Mail Move", False },
2778 { "menuFile.Reload CMail Message", False },
2779 { "menuMode.Machine White", False },
2780 { "menuMode.Machine Black", False },
2781 { "menuMode.Analysis Mode", False },
2782 { "menuMode.Analyze File", False },
2783 { "menuMode.Two Machines", False },
2784 { "menuMode.ICS Client", False },
2785 { "menuMode.ICS Input Box", False },
2786 { "Action", False },
2787 { "menuStep.Revert", False },
2788 { "menuStep.Annotate", False },
2789 { "menuStep.Move Now", False },
2790 { "menuStep.Retract Move", False },
2791 { "menuOptions.Auto Comment", False },
2792 { "menuOptions.Auto Flag", False },
2793 { "menuOptions.Auto Flip View", False },
2794 { "menuOptions.Auto Observe", False },
2795 { "menuOptions.Auto Raise Board", False },
2796 { "menuOptions.Get Move List", False },
2797 { "menuOptions.ICS Alarm", False },
2798 { "menuOptions.Move Sound", False },
2799 { "menuOptions.Quiet Play", False },
2800 { "menuOptions.Hide Thinking", False },
2801 { "menuOptions.Periodic Updates", False },
2802 { "menuOptions.Ponder Next Move", False },
2803 { "menuHelp.Hint", False },
2804 { "menuHelp.Book", False },
2808 Enables gnuEnables[] = {
2809 { "menuMode.ICS Client", False },
2810 { "menuMode.ICS Input Box", False },
2811 { "menuAction.Accept", False },
2812 { "menuAction.Decline", False },
2813 { "menuAction.Rematch", False },
2814 { "menuAction.Adjourn", False },
2815 { "menuAction.Stop Examining", False },
2816 { "menuAction.Stop Observing", False },
2817 { "menuAction.Upload to Examine", False },
2818 { "menuStep.Revert", False },
2819 { "menuStep.Annotate", False },
2820 { "menuOptions.Auto Comment", False },
2821 { "menuOptions.Auto Observe", False },
2822 { "menuOptions.Auto Raise Board", False },
2823 { "menuOptions.Get Move List", False },
2824 { "menuOptions.Premove", False },
2825 { "menuOptions.Quiet Play", False },
2827 /* The next two options rely on SetCmailMode being called *after* */
2828 /* SetGNUMode so that when GNU is being used to give hints these */
2829 /* menu options are still available */
2831 { "menuFile.Mail Move", False },
2832 { "menuFile.Reload CMail Message", False },
2836 Enables cmailEnables[] = {
2838 { "menuAction.Call Flag", False },
2839 { "menuAction.Draw", True },
2840 { "menuAction.Adjourn", False },
2841 { "menuAction.Abort", False },
2842 { "menuAction.Stop Observing", False },
2843 { "menuAction.Stop Examining", False },
2844 { "menuFile.Mail Move", True },
2845 { "menuFile.Reload CMail Message", True },
2849 Enables trainingOnEnables[] = {
2850 { "menuMode.Edit Comment", False },
2851 { "menuMode.Pause", False },
2852 { "menuStep.Forward", False },
2853 { "menuStep.Backward", False },
2854 { "menuStep.Forward to End", False },
2855 { "menuStep.Back to Start", False },
2856 { "menuStep.Move Now", False },
2857 { "menuStep.Truncate Game", False },
2861 Enables trainingOffEnables[] = {
2862 { "menuMode.Edit Comment", True },
2863 { "menuMode.Pause", True },
2864 { "menuStep.Forward", True },
2865 { "menuStep.Backward", True },
2866 { "menuStep.Forward to End", True },
2867 { "menuStep.Back to Start", True },
2868 { "menuStep.Move Now", True },
2869 { "menuStep.Truncate Game", True },
2873 Enables machineThinkingEnables[] = {
2874 { "menuFile.Load Game", False },
2875 { "menuFile.Load Next Game", False },
2876 { "menuFile.Load Previous Game", False },
2877 { "menuFile.Reload Same Game", False },
2878 { "menuFile.Paste Game", False },
2879 { "menuFile.Load Position", False },
2880 { "menuFile.Load Next Position", False },
2881 { "menuFile.Load Previous Position", False },
2882 { "menuFile.Reload Same Position", False },
2883 { "menuFile.Paste Position", False },
2884 { "menuMode.Machine White", False },
2885 { "menuMode.Machine Black", False },
2886 { "menuMode.Two Machines", False },
2887 { "menuStep.Retract Move", False },
2891 Enables userThinkingEnables[] = {
2892 { "menuFile.Load Game", True },
2893 { "menuFile.Load Next Game", True },
2894 { "menuFile.Load Previous Game", True },
2895 { "menuFile.Reload Same Game", True },
2896 { "menuFile.Paste Game", True },
2897 { "menuFile.Load Position", True },
2898 { "menuFile.Load Next Position", True },
2899 { "menuFile.Load Previous Position", True },
2900 { "menuFile.Reload Same Position", True },
2901 { "menuFile.Paste Position", True },
2902 { "menuMode.Machine White", True },
2903 { "menuMode.Machine Black", True },
2904 { "menuMode.Two Machines", True },
2905 { "menuStep.Retract Move", True },
2911 SetMenuEnables(icsEnables);
2914 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2915 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2922 SetMenuEnables(ncpEnables);
2928 SetMenuEnables(gnuEnables);
2934 SetMenuEnables(cmailEnables);
2940 SetMenuEnables(trainingOnEnables);
2941 if (appData.showButtonBar) {
2942 XtSetSensitive(buttonBarWidget, False);
2948 SetTrainingModeOff()
2950 SetMenuEnables(trainingOffEnables);
2951 if (appData.showButtonBar) {
2952 XtSetSensitive(buttonBarWidget, True);
2957 SetUserThinkingEnables()
2959 if (appData.noChessProgram) return;
2960 SetMenuEnables(userThinkingEnables);
2964 SetMachineThinkingEnables()
2966 if (appData.noChessProgram) return;
2967 SetMenuEnables(machineThinkingEnables);
2969 case MachinePlaysBlack:
2970 case MachinePlaysWhite:
2971 case TwoMachinesPlay:
2972 XtSetSensitive(XtNameToWidget(menuBarWidget,
2973 ModeToWidgetName(gameMode)), True);
2980 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2981 #define HISTORY_SIZE 64
\r
2982 static char *history[HISTORY_SIZE];
\r
2983 int histIn = 0, histP = 0;
\r
2986 SaveInHistory(char *cmd)
\r
2988 if (history[histIn] != NULL) {
\r
2989 free(history[histIn]);
\r
2990 history[histIn] = NULL;
\r
2992 if (*cmd == NULLCHAR) return;
\r
2993 history[histIn] = StrSave(cmd);
\r
2994 histIn = (histIn + 1) % HISTORY_SIZE;
\r
2995 if (history[histIn] != NULL) {
\r
2996 free(history[histIn]);
\r
2997 history[histIn] = NULL;
\r
3003 PrevInHistory(char *cmd)
\r
3006 if (histP == histIn) {
\r
3007 if (history[histIn] != NULL) free(history[histIn]);
\r
3008 history[histIn] = StrSave(cmd);
\r
3010 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
3011 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
3013 return history[histP];
\r
3019 if (histP == histIn) return NULL;
\r
3020 histP = (histP + 1) % HISTORY_SIZE;
\r
3021 return history[histP];
\r
3023 // end of borrowed code
\r
3025 #define Abs(n) ((n)<0 ? -(n) : (n))
3028 * Find a font that matches "pattern" that is as close as
3029 * possible to the targetPxlSize. Prefer fonts that are k
3030 * pixels smaller to fonts that are k pixels larger. The
3031 * pattern must be in the X Consortium standard format,
3032 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3033 * The return value should be freed with XtFree when no
3037 FindFont(pattern, targetPxlSize)
3041 char **fonts, *p, *best, *scalable, *scalableTail;
3042 int i, j, nfonts, minerr, err, pxlSize;
3045 char **missing_list;
3047 char *def_string, *base_fnt_lst, strInt[3];
3049 XFontStruct **fnt_list;
3051 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3052 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3053 p = strstr(pattern, "--");
3054 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3055 strcat(base_fnt_lst, strInt);
3056 strcat(base_fnt_lst, strchr(p + 2, '-'));
3058 if ((fntSet = XCreateFontSet(xDisplay,
3062 &def_string)) == NULL) {
3064 fprintf(stderr, _("Unable to create font set.\n"));
3068 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3070 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3072 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3073 programName, pattern);
3081 for (i=0; i<nfonts; i++) {
3084 if (*p != '-') continue;
3086 if (*p == NULLCHAR) break;
3087 if (*p++ == '-') j++;
3089 if (j < 7) continue;
3092 scalable = fonts[i];
3095 err = pxlSize - targetPxlSize;
3096 if (Abs(err) < Abs(minerr) ||
3097 (minerr > 0 && err < 0 && -err == minerr)) {
3103 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3104 /* If the error is too big and there is a scalable font,
3105 use the scalable font. */
3106 int headlen = scalableTail - scalable;
3107 p = (char *) XtMalloc(strlen(scalable) + 10);
3108 while (isdigit(*scalableTail)) scalableTail++;
3109 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3111 p = (char *) XtMalloc(strlen(best) + 2);
3112 safeStrCpy(p, best, strlen(best)+1 );
3114 if (appData.debugMode) {
3115 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3116 pattern, targetPxlSize, p);
3119 if (missing_count > 0)
3120 XFreeStringList(missing_list);
3121 XFreeFontSet(xDisplay, fntSet);
3123 XFreeFontNames(fonts);
3130 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3131 | GCBackground | GCFunction | GCPlaneMask;
3132 XGCValues gc_values;
3135 gc_values.plane_mask = AllPlanes;
3136 gc_values.line_width = lineGap;
3137 gc_values.line_style = LineSolid;
3138 gc_values.function = GXcopy;
3140 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3141 gc_values.background = XBlackPixel(xDisplay, xScreen);
3142 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3144 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3145 gc_values.background = XWhitePixel(xDisplay, xScreen);
3146 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3147 XSetFont(xDisplay, coordGC, coordFontID);
3149 // [HGM] make font for holdings counts (white on black0
3150 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3151 gc_values.background = XBlackPixel(xDisplay, xScreen);
3152 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3153 XSetFont(xDisplay, countGC, countFontID);
3155 if (appData.monoMode) {
3156 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3157 gc_values.background = XWhitePixel(xDisplay, xScreen);
3158 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3160 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3161 gc_values.background = XBlackPixel(xDisplay, xScreen);
3162 lightSquareGC = wbPieceGC
3163 = XtGetGC(shellWidget, value_mask, &gc_values);
3165 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3166 gc_values.background = XWhitePixel(xDisplay, xScreen);
3167 darkSquareGC = bwPieceGC
3168 = XtGetGC(shellWidget, value_mask, &gc_values);
3170 if (DefaultDepth(xDisplay, xScreen) == 1) {
3171 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3172 gc_values.function = GXcopyInverted;
3173 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3174 gc_values.function = GXcopy;
3175 if (XBlackPixel(xDisplay, xScreen) == 1) {
3176 bwPieceGC = darkSquareGC;
3177 wbPieceGC = copyInvertedGC;
3179 bwPieceGC = copyInvertedGC;
3180 wbPieceGC = lightSquareGC;
3184 gc_values.foreground = highlightSquareColor;
3185 gc_values.background = highlightSquareColor;
3186 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3188 gc_values.foreground = premoveHighlightColor;
3189 gc_values.background = premoveHighlightColor;
3190 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3192 gc_values.foreground = lightSquareColor;
3193 gc_values.background = darkSquareColor;
3194 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3196 gc_values.foreground = darkSquareColor;
3197 gc_values.background = lightSquareColor;
3198 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3200 gc_values.foreground = jailSquareColor;
3201 gc_values.background = jailSquareColor;
3202 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3204 gc_values.foreground = whitePieceColor;
3205 gc_values.background = darkSquareColor;
3206 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3208 gc_values.foreground = whitePieceColor;
3209 gc_values.background = lightSquareColor;
3210 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3212 gc_values.foreground = whitePieceColor;
3213 gc_values.background = jailSquareColor;
3214 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3216 gc_values.foreground = blackPieceColor;
3217 gc_values.background = darkSquareColor;
3218 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3220 gc_values.foreground = blackPieceColor;
3221 gc_values.background = lightSquareColor;
3222 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3224 gc_values.foreground = blackPieceColor;
3225 gc_values.background = jailSquareColor;
3226 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3230 void loadXIM(xim, xmask, filename, dest, mask)
3243 fp = fopen(filename, "rb");
3245 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3252 for (y=0; y<h; ++y) {
3253 for (x=0; x<h; ++x) {
3258 XPutPixel(xim, x, y, blackPieceColor);
3260 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3263 XPutPixel(xim, x, y, darkSquareColor);
3265 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3268 XPutPixel(xim, x, y, whitePieceColor);
3270 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3273 XPutPixel(xim, x, y, lightSquareColor);
3275 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3281 /* create Pixmap of piece */
3282 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3284 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3287 /* create Pixmap of clipmask
3288 Note: We assume the white/black pieces have the same
3289 outline, so we make only 6 masks. This is okay
3290 since the XPM clipmask routines do the same. */
3292 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3294 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3297 /* now create the 1-bit version */
3298 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3301 values.foreground = 1;
3302 values.background = 0;
3304 /* Don't use XtGetGC, not read only */
3305 maskGC = XCreateGC(xDisplay, *mask,
3306 GCForeground | GCBackground, &values);
3307 XCopyPlane(xDisplay, temp, *mask, maskGC,
3308 0, 0, squareSize, squareSize, 0, 0, 1);
3309 XFreePixmap(xDisplay, temp);
3314 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3316 void CreateXIMPieces()
3321 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3326 /* The XSynchronize calls were copied from CreatePieces.
3327 Not sure if needed, but can't hurt */
3328 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3331 /* temp needed by loadXIM() */
3332 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3333 0, 0, ss, ss, AllPlanes, XYPixmap);
3335 if (strlen(appData.pixmapDirectory) == 0) {
3339 if (appData.monoMode) {
3340 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3344 fprintf(stderr, _("\nLoading XIMs...\n"));
3346 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3347 fprintf(stderr, "%d", piece+1);
3348 for (kind=0; kind<4; kind++) {
3349 fprintf(stderr, ".");
3350 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3351 ExpandPathName(appData.pixmapDirectory),
3352 piece <= (int) WhiteKing ? "" : "w",
3353 pieceBitmapNames[piece],
3355 ximPieceBitmap[kind][piece] =
3356 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3357 0, 0, ss, ss, AllPlanes, XYPixmap);
3358 if (appData.debugMode)
3359 fprintf(stderr, _("(File:%s:) "), buf);
3360 loadXIM(ximPieceBitmap[kind][piece],
3362 &(xpmPieceBitmap2[kind][piece]),
3363 &(ximMaskPm2[piece]));
3364 if(piece <= (int)WhiteKing)
3365 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3367 fprintf(stderr," ");
3369 /* Load light and dark squares */
3370 /* If the LSQ and DSQ pieces don't exist, we will
3371 draw them with solid squares. */
3372 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3373 if (access(buf, 0) != 0) {
3377 fprintf(stderr, _("light square "));
3379 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3380 0, 0, ss, ss, AllPlanes, XYPixmap);
3381 if (appData.debugMode)
3382 fprintf(stderr, _("(File:%s:) "), buf);
3384 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3385 fprintf(stderr, _("dark square "));
3386 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3387 ExpandPathName(appData.pixmapDirectory), ss);
3388 if (appData.debugMode)
3389 fprintf(stderr, _("(File:%s:) "), buf);
3391 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3392 0, 0, ss, ss, AllPlanes, XYPixmap);
3393 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3394 xpmJailSquare = xpmLightSquare;
3396 fprintf(stderr, _("Done.\n"));
3398 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3402 void CreateXPMPieces()
3406 u_int ss = squareSize;
3408 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3409 XpmColorSymbol symbols[4];
3411 /* The XSynchronize calls were copied from CreatePieces.
3412 Not sure if needed, but can't hurt */
3413 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3415 /* Setup translations so piece colors match square colors */
3416 symbols[0].name = "light_piece";
3417 symbols[0].value = appData.whitePieceColor;
3418 symbols[1].name = "dark_piece";
3419 symbols[1].value = appData.blackPieceColor;
3420 symbols[2].name = "light_square";
3421 symbols[2].value = appData.lightSquareColor;
3422 symbols[3].name = "dark_square";
3423 symbols[3].value = appData.darkSquareColor;
3425 attr.valuemask = XpmColorSymbols;
3426 attr.colorsymbols = symbols;
3427 attr.numsymbols = 4;
3429 if (appData.monoMode) {
3430 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3434 if (strlen(appData.pixmapDirectory) == 0) {
3435 XpmPieces* pieces = builtInXpms;
3438 while (pieces->size != squareSize && pieces->size) pieces++;
3439 if (!pieces->size) {
3440 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3443 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3444 for (kind=0; kind<4; kind++) {
3446 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3447 pieces->xpm[piece][kind],
3448 &(xpmPieceBitmap2[kind][piece]),
3449 NULL, &attr)) != 0) {
3450 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3454 if(piece <= (int) WhiteKing)
3455 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3459 xpmJailSquare = xpmLightSquare;
3463 fprintf(stderr, _("\nLoading XPMs...\n"));
3466 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3467 fprintf(stderr, "%d ", piece+1);
3468 for (kind=0; kind<4; kind++) {
3469 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3470 ExpandPathName(appData.pixmapDirectory),
3471 piece > (int) WhiteKing ? "w" : "",
3472 pieceBitmapNames[piece],
3474 if (appData.debugMode) {
3475 fprintf(stderr, _("(File:%s:) "), buf);
3477 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3478 &(xpmPieceBitmap2[kind][piece]),
3479 NULL, &attr)) != 0) {
3480 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3481 // [HGM] missing: read of unorthodox piece failed; substitute King.
3482 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3483 ExpandPathName(appData.pixmapDirectory),
3485 if (appData.debugMode) {
3486 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3488 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3489 &(xpmPieceBitmap2[kind][piece]),
3493 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3498 if(piece <= (int) WhiteKing)
3499 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3502 /* Load light and dark squares */
3503 /* If the LSQ and DSQ pieces don't exist, we will
3504 draw them with solid squares. */
3505 fprintf(stderr, _("light square "));
3506 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3507 if (access(buf, 0) != 0) {
3511 if (appData.debugMode)
3512 fprintf(stderr, _("(File:%s:) "), buf);
3514 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3515 &xpmLightSquare, NULL, &attr)) != 0) {
3516 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3519 fprintf(stderr, _("dark square "));
3520 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3521 ExpandPathName(appData.pixmapDirectory), ss);
3522 if (appData.debugMode) {
3523 fprintf(stderr, _("(File:%s:) "), buf);
3525 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3526 &xpmDarkSquare, NULL, &attr)) != 0) {
3527 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3531 xpmJailSquare = xpmLightSquare;
3532 fprintf(stderr, _("Done.\n"));
3534 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3537 #endif /* HAVE_LIBXPM */
3540 /* No built-in bitmaps */
3545 u_int ss = squareSize;
3547 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3550 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3551 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3552 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3553 pieceBitmapNames[piece],
3554 ss, kind == SOLID ? 's' : 'o');
3555 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3556 if(piece <= (int)WhiteKing)
3557 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3561 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3565 /* With built-in bitmaps */
3568 BuiltInBits* bib = builtInBits;
3571 u_int ss = squareSize;
3573 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3576 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3578 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3579 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3580 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3581 pieceBitmapNames[piece],
3582 ss, kind == SOLID ? 's' : 'o');
3583 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3584 bib->bits[kind][piece], ss, ss);
3585 if(piece <= (int)WhiteKing)
3586 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3590 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3595 void ReadBitmap(pm, name, bits, wreq, hreq)
3598 unsigned char bits[];
3604 char msg[MSG_SIZ], fullname[MSG_SIZ];
3606 if (*appData.bitmapDirectory != NULLCHAR) {
3607 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3608 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3609 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3610 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3611 &w, &h, pm, &x_hot, &y_hot);
3612 fprintf(stderr, "load %s\n", name);
3613 if (errcode != BitmapSuccess) {
3615 case BitmapOpenFailed:
3616 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3618 case BitmapFileInvalid:
3619 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3621 case BitmapNoMemory:
3622 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3626 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3630 fprintf(stderr, _("%s: %s...using built-in\n"),
3632 } else if (w != wreq || h != hreq) {
3634 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3635 programName, fullname, w, h, wreq, hreq);