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>
66 # if HAVE_SYS_SOCKET_H
67 # include <sys/socket.h>
68 # include <netinet/in.h>
70 # else /* not HAVE_SYS_SOCKET_H */
71 # if HAVE_LAN_SOCKET_H
72 # include <lan/socket.h>
74 # include <lan/netdb.h>
75 # else /* not HAVE_LAN_SOCKET_H */
76 # define OMIT_SOCKETS 1
77 # endif /* not HAVE_LAN_SOCKET_H */
78 # endif /* not HAVE_SYS_SOCKET_H */
79 #endif /* !OMIT_SOCKETS */
84 #else /* not STDC_HEADERS */
85 extern char *getenv();
88 # else /* not HAVE_STRING_H */
90 # endif /* not HAVE_STRING_H */
91 #endif /* not STDC_HEADERS */
94 # include <sys/fcntl.h>
95 #else /* not HAVE_SYS_FCNTL_H */
98 # endif /* HAVE_FCNTL_H */
99 #endif /* not HAVE_SYS_FCNTL_H */
101 #if HAVE_SYS_SYSTEMINFO_H
102 # include <sys/systeminfo.h>
103 #endif /* HAVE_SYS_SYSTEMINFO_H */
105 #if TIME_WITH_SYS_TIME
106 # include <sys/time.h>
110 # include <sys/time.h>
121 # include <sys/wait.h>
126 # define NAMLEN(dirent) strlen((dirent)->d_name)
127 # define HAVE_DIR_STRUCT
129 # define dirent direct
130 # define NAMLEN(dirent) (dirent)->d_namlen
132 # include <sys/ndir.h>
133 # define HAVE_DIR_STRUCT
136 # include <sys/dir.h>
137 # define HAVE_DIR_STRUCT
141 # define HAVE_DIR_STRUCT
145 #include <X11/Intrinsic.h>
146 #include <X11/StringDefs.h>
147 #include <X11/Shell.h>
148 #include <X11/cursorfont.h>
149 #include <X11/Xatom.h>
150 #include <X11/Xmu/Atoms.h>
152 #include <X11/Xaw3d/Dialog.h>
153 #include <X11/Xaw3d/Form.h>
154 #include <X11/Xaw3d/List.h>
155 #include <X11/Xaw3d/Label.h>
156 #include <X11/Xaw3d/SimpleMenu.h>
157 #include <X11/Xaw3d/SmeBSB.h>
158 #include <X11/Xaw3d/SmeLine.h>
159 #include <X11/Xaw3d/Box.h>
160 #include <X11/Xaw3d/MenuButton.h>
161 #include <X11/Xaw3d/Text.h>
162 #include <X11/Xaw3d/AsciiText.h>
164 #include <X11/Xaw/Dialog.h>
165 #include <X11/Xaw/Form.h>
166 #include <X11/Xaw/List.h>
167 #include <X11/Xaw/Label.h>
168 #include <X11/Xaw/SimpleMenu.h>
169 #include <X11/Xaw/SmeBSB.h>
170 #include <X11/Xaw/SmeLine.h>
171 #include <X11/Xaw/Box.h>
172 #include <X11/Xaw/MenuButton.h>
173 #include <X11/Xaw/Text.h>
174 #include <X11/Xaw/AsciiText.h>
177 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
182 #include "pixmaps/pixmaps.h"
183 #define IMAGE_EXT "xpm"
185 #define IMAGE_EXT "xim"
186 #include "bitmaps/bitmaps.h"
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
195 #include "backendz.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
204 // must be moved to xengineoutput.h
206 void EngineOutputProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
208 void EvalGraphProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
216 #define usleep(t) _sleep2(((t)+500)/1000)
220 # define _(s) gettext (s)
221 # define N_(s) gettext_noop (s)
239 int main P((int argc, char **argv));
240 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
241 char *init_path, char *mode, int (*show_entry)(), char **name_return));
242 RETSIGTYPE CmailSigHandler P((int sig));
243 RETSIGTYPE IntSigHandler P((int sig));
244 RETSIGTYPE TermSizeSigHandler P((int sig));
245 void CreateGCs P((void));
246 void CreateXIMPieces P((void));
247 void CreateXPMPieces P((void));
248 void CreateXPMBoard P((char *s, int n));
249 void CreatePieces P((void));
250 void CreatePieceMenus P((void));
251 Widget CreateMenuBar P((Menu *mb));
252 Widget CreateButtonBar P ((MenuItem *mi));
253 char *FindFont P((char *pattern, int targetPxlSize));
254 void PieceMenuPopup P((Widget w, XEvent *event,
255 String *params, Cardinal *num_params));
256 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
257 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
259 u_int wreq, u_int hreq));
260 void CreateGrid P((void));
261 int EventToSquare P((int x, int limit));
262 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
263 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
264 void HandleUserMove P((Widget w, XEvent *event,
265 String *prms, Cardinal *nprms));
266 void AnimateUserMove P((Widget w, XEvent * event,
267 String * params, Cardinal * nParams));
268 void HandlePV P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void SelectPV P((Widget w, XEvent * event,
271 String * params, Cardinal * nParams));
272 void StopPV P((Widget w, XEvent * event,
273 String * params, Cardinal * nParams));
274 void WhiteClock P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void BlackClock P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void DrawPositionProc P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
282 void CommentClick P((Widget w, XEvent * event,
283 String * params, Cardinal * nParams));
284 void CommentPopUp P((char *title, char *label));
285 void CommentPopDown P((void));
286 void CommentCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void ICSInputBoxPopUp P((void));
289 void ICSInputBoxPopDown P((void));
290 void FileNamePopUp P((char *label, char *def,
291 FileProc proc, char *openMode));
292 void FileNamePopDown P((void));
293 void FileNameCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void FileNameAction P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void AskQuestionReplyAction P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void AskQuestionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void AskQuestionPopDown P((void));
302 void PromotionPopDown P((void));
303 void PromotionCallback P((Widget w, XtPointer client_data,
304 XtPointer call_data));
305 void EditCommentPopDown P((void));
306 void EditCommentCallback P((Widget w, XtPointer client_data,
307 XtPointer call_data));
308 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
309 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
313 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
315 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
317 void LoadPositionProc P((Widget w, XEvent *event,
318 String *prms, Cardinal *nprms));
319 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
321 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
323 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
325 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
327 void PastePositionProc P((Widget w, XEvent *event, String *prms,
329 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void SavePositionProc P((Widget w, XEvent *event,
333 String *prms, Cardinal *nprms));
334 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
337 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
341 void MachineWhiteProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void AnalyzeModeProc P((Widget w, XEvent *event,
344 String *prms, Cardinal *nprms));
345 void AnalyzeFileProc P((Widget w, XEvent *event,
346 String *prms, Cardinal *nprms));
347 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
349 void IcsClientProc P((Widget w, XEvent *event, String *prms,
351 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EditPositionProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void EditCommentProc P((Widget w, XEvent *event,
356 String *prms, Cardinal *nprms));
357 void IcsInputBoxProc P((Widget w, XEvent *event,
358 String *prms, Cardinal *nprms));
359 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void StopObservingProc P((Widget w, XEvent *event, String *prms,
375 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
377 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
386 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
388 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
391 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
393 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
395 void AutocommProc P((Widget w, XEvent *event, String *prms,
397 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void AutobsProc P((Widget w, XEvent *event, String *prms,
401 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
406 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
409 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
411 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
413 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
417 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
419 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
421 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
423 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
425 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
429 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
431 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
433 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
435 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void DisplayMove P((int moveNumber));
447 void DisplayTitle P((char *title));
448 void ICSInitScript P((void));
449 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
450 void ErrorPopUp P((char *title, char *text, int modal));
451 void ErrorPopDown P((void));
452 static char *ExpandPathName P((char *path));
453 static void CreateAnimVars P((void));
454 static void DragPieceMove P((int x, int y));
455 static void DrawDragPiece P((void));
456 char *ModeToWidgetName P((GameMode mode));
457 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void GameListOptionsPopDown P(());
466 void ShufflePopDown P(());
467 void EnginePopDown P(());
468 void UciPopDown P(());
469 void TimeControlPopDown P(());
470 void NewVariantPopDown P(());
471 void SettingsPopDown P(());
472 void update_ics_width P(());
473 int get_term_width P(());
474 int CopyMemoProc P(());
475 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
476 Boolean IsDrawArrowEnabled P(());
479 * XBoard depends on Xt R4 or higher
481 int xtVersion = XtSpecificationRelease;
486 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
487 jailSquareColor, highlightSquareColor, premoveHighlightColor;
488 Pixel lowTimeWarningColor;
489 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
490 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
491 wjPieceGC, bjPieceGC, prelineGC, countGC;
492 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
493 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
494 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
495 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
496 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
497 ICSInputShell, fileNameShell, askQuestionShell;
498 Widget historyShell, evalGraphShell, gameListShell;
499 int hOffset; // [HGM] dual
500 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
501 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
502 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
503 Font clockFontID, coordFontID, countFontID;
504 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
505 XtAppContext appContext;
507 char *oldICSInteractionTitle;
511 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
513 Position commentX = -1, commentY = -1;
514 Dimension commentW, commentH;
515 typedef unsigned int BoardSize;
517 Boolean chessProgram;
519 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
520 int squareSize, smallLayout = 0, tinyLayout = 0,
521 marginW, marginH, // [HGM] for run-time resizing
522 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
523 ICSInputBoxUp = False, askQuestionUp = False,
524 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
525 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
526 Pixel timerForegroundPixel, timerBackgroundPixel;
527 Pixel buttonForegroundPixel, buttonBackgroundPixel;
528 char *chessDir, *programName, *programVersion,
529 *gameCopyFilename, *gamePasteFilename;
530 Boolean alwaysOnTop = False;
531 Boolean saveSettingsOnExit;
532 char *settingsFileName;
533 char *icsTextMenuString;
535 char *firstChessProgramNames;
536 char *secondChessProgramNames;
538 WindowPlacement wpMain;
539 WindowPlacement wpConsole;
540 WindowPlacement wpComment;
541 WindowPlacement wpMoveHistory;
542 WindowPlacement wpEvalGraph;
543 WindowPlacement wpEngineOutput;
544 WindowPlacement wpGameList;
545 WindowPlacement wpTags;
549 Pixmap pieceBitmap[2][(int)BlackPawn];
550 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
551 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
552 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
553 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
554 Pixmap xpmBoardBitmap[2];
555 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
556 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
557 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
558 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
559 XImage *ximLightSquare, *ximDarkSquare;
562 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
563 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
565 #define White(piece) ((int)(piece) < (int)BlackPawn)
567 /* Variables for doing smooth animation. This whole thing
568 would be much easier if the board was double-buffered,
569 but that would require a fairly major rewrite. */
574 GC blitGC, pieceGC, outlineGC;
575 XPoint startSquare, prevFrame, mouseDelta;
579 int startBoardX, startBoardY;
582 /* There can be two pieces being animated at once: a player
583 can begin dragging a piece before the remote opponent has moved. */
585 static AnimState game, player;
587 /* Bitmaps for use as masks when drawing XPM pieces.
588 Need one for each black and white piece. */
589 static Pixmap xpmMask[BlackKing + 1];
591 /* This magic number is the number of intermediate frames used
592 in each half of the animation. For short moves it's reduced
593 by 1. The total number of frames will be factor * 2 + 1. */
596 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
598 MenuItem fileMenu[] = {
599 {N_("New Game Ctrl+N"), "New Game", ResetProc},
600 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
601 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
602 {"----", NULL, NothingProc},
603 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
604 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
605 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
606 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
607 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
608 {"----", NULL, NothingProc},
609 // {N_("Load Next Position"), "Load Next Position", LoadNextPositionProc},
610 // {N_("Load Previous Position"), "Load Previous Position", LoadPrevPositionProc},
611 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
612 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
613 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
614 {"----", NULL, NothingProc},
615 {N_("Mail Move"), "Mail Move", MailMoveProc},
616 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
617 {"----", NULL, NothingProc},
618 {N_("Quit Ctr+Q"), "Exit", QuitProc},
622 MenuItem editMenu[] = {
623 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
624 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
625 {"----", NULL, NothingProc},
626 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
627 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
628 {"----", NULL, NothingProc},
629 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
630 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
631 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
632 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
633 {"----", NULL, NothingProc},
634 {N_("Revert Home"), "Revert", RevertProc},
635 {N_("Annotate"), "Annotate", AnnotateProc},
636 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
637 {"----", NULL, NothingProc},
638 {N_("Backward Alt+Left"), "Backward", BackwardProc},
639 {N_("Forward Alt+Right"), "Forward", ForwardProc},
640 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
641 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
645 MenuItem viewMenu[] = {
646 {N_("Flip View F2"), "Flip View", FlipViewProc},
647 {"----", NULL, NothingProc},
648 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
649 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
650 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
651 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
652 {"----", NULL, NothingProc},
653 {N_("Tags"), "Show Tags", EditTagsProc},
654 {N_("Comments"), "Show Comments", EditCommentProc},
655 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
659 MenuItem modeMenu[] = {
660 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
661 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
662 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
663 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
664 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
665 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
666 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
667 {N_("Training"), "Training", TrainingProc},
668 {N_("ICS Client"), "ICS Client", IcsClientProc},
669 {"----", NULL, NothingProc},
670 {N_("Pause Pause"), "Pause", PauseProc},
674 MenuItem actionMenu[] = {
675 {N_("Accept F3"), "Accept", AcceptProc},
676 {N_("Decline F4"), "Decline", DeclineProc},
677 {N_("Rematch F12"), "Rematch", RematchProc},
678 {"----", NULL, NothingProc},
679 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
680 {N_("Draw F6"), "Draw", DrawProc},
681 {N_("Adjourn F7"), "Adjourn", AdjournProc},
682 {N_("Abort F8"),"Abort", AbortProc},
683 {N_("Resign F9"), "Resign", ResignProc},
684 {"----", NULL, NothingProc},
685 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
686 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
687 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
688 {"----", NULL, NothingProc},
689 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
690 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
691 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
695 MenuItem engineMenu[] = {
696 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
697 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
698 {"----", NULL, NothingProc},
699 {N_("Hint"), "Hint", HintProc},
700 {N_("Book"), "Book", BookProc},
701 {"----", NULL, NothingProc},
702 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
703 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
707 MenuItem optionsMenu[] = {
708 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
709 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
710 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
711 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
712 {"----", NULL, NothingProc},
713 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
714 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
715 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
716 {N_("Auto Comment"), "Auto Comment", AutocommProc},
717 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
718 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
719 {N_("Auto Observe"), "Auto Observe", AutobsProc},
720 {N_("Auto Raise Board"), "Auto Raise Board", AutoraiseProc},
721 {N_("Auto Save"), "Auto Save", AutosaveProc},
722 {N_("Blindfold"), "Blindfold", BlindfoldProc},
723 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
724 {N_("Get Move List"), "Get Move List", GetMoveListProc},
726 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
728 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
729 {N_("Move Sound"), "Move Sound", MoveSoundProc},
730 {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
731 {N_("Old Save Style"), "Old Save Style", OldSaveStyleProc},
732 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
733 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
734 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
735 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
736 {N_("Premove"), "Premove", PremoveProc},
737 {N_("Quiet Play"), "Quiet Play", QuietPlayProc},
738 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
739 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
740 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
741 {"----", NULL, NothingProc},
742 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
743 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
747 MenuItem helpMenu[] = {
748 {N_("Info XBoard"), "Info XBoard", InfoProc},
749 {N_("Man XBoard F1"), "Man XBoard", ManProc},
750 {"----", NULL, NothingProc},
751 {N_("About XBoard"), "About XBoard", AboutProc},
756 {N_("File"), "File", fileMenu},
757 {N_("Edit"), "Edit", editMenu},
758 {N_("View"), "View", viewMenu},
759 {N_("Mode"), "Mode", modeMenu},
760 {N_("Action"), "Action", actionMenu},
761 {N_("Engine"), "Engine", engineMenu},
762 {N_("Options"), "Options", optionsMenu},
763 {N_("Help"), "Help", helpMenu},
767 #define PAUSE_BUTTON "P"
768 MenuItem buttonBar[] = {
769 {"<<", "<<", ToStartProc},
770 {"<", "<", BackwardProc},
771 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
772 {">", ">", ForwardProc},
773 {">>", ">>", ToEndProc},
777 #define PIECE_MENU_SIZE 18
778 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
779 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
780 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
781 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
782 N_("Empty square"), N_("Clear board") },
783 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
784 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
785 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
786 N_("Empty square"), N_("Clear board") }
788 /* must be in same order as PieceMenuStrings! */
789 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
790 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
791 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
792 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
793 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
794 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
795 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
796 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
797 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
800 #define DROP_MENU_SIZE 6
801 String dropMenuStrings[DROP_MENU_SIZE] = {
802 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
804 /* must be in same order as PieceMenuStrings! */
805 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
806 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
807 WhiteRook, WhiteQueen
815 DropMenuEnables dmEnables[] = {
833 { XtNborderWidth, 0 },
834 { XtNdefaultDistance, 0 },
838 { XtNborderWidth, 0 },
839 { XtNresizable, (XtArgVal) True },
843 { XtNborderWidth, 0 },
849 { XtNjustify, (XtArgVal) XtJustifyRight },
850 { XtNlabel, (XtArgVal) "..." },
851 { XtNresizable, (XtArgVal) True },
852 { XtNresize, (XtArgVal) False }
855 Arg messageArgs[] = {
856 { XtNjustify, (XtArgVal) XtJustifyLeft },
857 { XtNlabel, (XtArgVal) "..." },
858 { XtNresizable, (XtArgVal) True },
859 { XtNresize, (XtArgVal) False }
863 { XtNborderWidth, 0 },
864 { XtNjustify, (XtArgVal) XtJustifyLeft }
867 XtResource clientResources[] = {
868 { "flashCount", "flashCount", XtRInt, sizeof(int),
869 XtOffset(AppDataPtr, flashCount), XtRImmediate,
870 (XtPointer) FLASH_COUNT },
873 XrmOptionDescRec shellOptions[] = {
874 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
875 { "-flash", "flashCount", XrmoptionNoArg, "3" },
876 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
879 XtActionsRec boardActions[] = {
880 { "DrawPosition", DrawPositionProc },
881 { "HandleUserMove", HandleUserMove },
882 { "AnimateUserMove", AnimateUserMove },
883 { "HandlePV", HandlePV },
884 { "SelectPV", SelectPV },
885 { "StopPV", StopPV },
886 { "FileNameAction", FileNameAction },
887 { "AskQuestionProc", AskQuestionProc },
888 { "AskQuestionReplyAction", AskQuestionReplyAction },
889 { "PieceMenuPopup", PieceMenuPopup },
890 { "WhiteClock", WhiteClock },
891 { "BlackClock", BlackClock },
892 { "Iconify", Iconify },
893 { "ResetProc", ResetProc },
894 { "NewVariantProc", NewVariantProc },
895 { "LoadGameProc", LoadGameProc },
896 { "LoadNextGameProc", LoadNextGameProc },
897 { "LoadPrevGameProc", LoadPrevGameProc },
898 { "LoadSelectedProc", LoadSelectedProc },
899 { "SetFilterProc", SetFilterProc },
900 { "ReloadGameProc", ReloadGameProc },
901 { "LoadPositionProc", LoadPositionProc },
902 { "LoadNextPositionProc", LoadNextPositionProc },
903 { "LoadPrevPositionProc", LoadPrevPositionProc },
904 { "ReloadPositionProc", ReloadPositionProc },
905 { "CopyPositionProc", CopyPositionProc },
906 { "PastePositionProc", PastePositionProc },
907 { "CopyGameProc", CopyGameProc },
908 { "PasteGameProc", PasteGameProc },
909 { "SaveGameProc", SaveGameProc },
910 { "SavePositionProc", SavePositionProc },
911 { "MailMoveProc", MailMoveProc },
912 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
913 { "QuitProc", QuitProc },
914 { "MachineWhiteProc", MachineWhiteProc },
915 { "MachineBlackProc", MachineBlackProc },
916 { "AnalysisModeProc", AnalyzeModeProc },
917 { "AnalyzeFileProc", AnalyzeFileProc },
918 { "TwoMachinesProc", TwoMachinesProc },
919 { "IcsClientProc", IcsClientProc },
920 { "EditGameProc", EditGameProc },
921 { "EditPositionProc", EditPositionProc },
922 { "TrainingProc", EditPositionProc },
923 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
924 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
925 { "ShowGameListProc", ShowGameListProc },
926 { "ShowMoveListProc", HistoryShowProc},
927 { "EditTagsProc", EditCommentProc },
928 { "EditCommentProc", EditCommentProc },
929 { "IcsAlarmProc", IcsAlarmProc },
930 { "IcsInputBoxProc", IcsInputBoxProc },
931 { "PauseProc", PauseProc },
932 { "AcceptProc", AcceptProc },
933 { "DeclineProc", DeclineProc },
934 { "RematchProc", RematchProc },
935 { "CallFlagProc", CallFlagProc },
936 { "DrawProc", DrawProc },
937 { "AdjournProc", AdjournProc },
938 { "AbortProc", AbortProc },
939 { "ResignProc", ResignProc },
940 { "AdjuWhiteProc", AdjuWhiteProc },
941 { "AdjuBlackProc", AdjuBlackProc },
942 { "AdjuDrawProc", AdjuDrawProc },
943 { "EnterKeyProc", EnterKeyProc },
944 { "UpKeyProc", UpKeyProc },
945 { "DownKeyProc", DownKeyProc },
946 { "StopObservingProc", StopObservingProc },
947 { "StopExaminingProc", StopExaminingProc },
948 { "UploadProc", UploadProc },
949 { "BackwardProc", BackwardProc },
950 { "ForwardProc", ForwardProc },
951 { "ToStartProc", ToStartProc },
952 { "ToEndProc", ToEndProc },
953 { "RevertProc", RevertProc },
954 { "AnnotateProc", AnnotateProc },
955 { "TruncateGameProc", TruncateGameProc },
956 { "MoveNowProc", MoveNowProc },
957 { "RetractMoveProc", RetractMoveProc },
958 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
959 { "UciMenuProc", (XtActionProc) UciMenuProc },
960 { "TimeControlProc", (XtActionProc) TimeControlProc },
961 { "AlwaysQueenProc", AlwaysQueenProc },
962 { "AnimateDraggingProc", AnimateDraggingProc },
963 { "AnimateMovingProc", AnimateMovingProc },
964 { "AutoflagProc", AutoflagProc },
965 { "AutoflipProc", AutoflipProc },
966 { "AutobsProc", AutobsProc },
967 { "AutoraiseProc", AutoraiseProc },
968 { "AutosaveProc", AutosaveProc },
969 { "BlindfoldProc", BlindfoldProc },
970 { "FlashMovesProc", FlashMovesProc },
971 { "FlipViewProc", FlipViewProc },
972 { "GetMoveListProc", GetMoveListProc },
974 { "HighlightDraggingProc", HighlightDraggingProc },
976 { "HighlightLastMoveProc", HighlightLastMoveProc },
977 { "IcsAlarmProc", IcsAlarmProc },
978 { "MoveSoundProc", MoveSoundProc },
979 { "OldSaveStyleProc", OldSaveStyleProc },
980 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
981 { "PonderNextMoveProc", PonderNextMoveProc },
982 { "PopupExitMessageProc", PopupExitMessageProc },
983 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
984 { "PremoveProc", PremoveProc },
985 { "QuietPlayProc", QuietPlayProc },
986 { "ShowCoordsProc", ShowCoordsProc },
987 { "ShowThinkingProc", ShowThinkingProc },
988 { "HideThinkingProc", HideThinkingProc },
989 { "TestLegalityProc", TestLegalityProc },
990 { "SaveSettingsProc", SaveSettingsProc },
991 { "SaveOnExitProc", SaveOnExitProc },
992 { "InfoProc", InfoProc },
993 { "ManProc", ManProc },
994 { "HintProc", HintProc },
995 { "BookProc", BookProc },
996 { "AboutGameProc", AboutGameProc },
997 { "AboutProc", AboutProc },
998 { "DebugProc", DebugProc },
999 { "NothingProc", NothingProc },
1000 { "CommentClick", (XtActionProc) CommentClick },
1001 { "CommentPopDown", (XtActionProc) CommentPopDown },
1002 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1003 { "TagsPopDown", (XtActionProc) TagsPopDown },
1004 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1005 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1006 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1007 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1008 { "GameListPopDown", (XtActionProc) GameListPopDown },
1009 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1010 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1011 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1012 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1013 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1014 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1015 { "EnginePopDown", (XtActionProc) EnginePopDown },
1016 { "UciPopDown", (XtActionProc) UciPopDown },
1017 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1018 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1019 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1020 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1023 char globalTranslations[] =
1024 ":<Key>F9: ResignProc() \n \
1025 :Ctrl<Key>n: ResetProc() \n \
1026 :Meta<Key>V: NewVariantProc() \n \
1027 :Ctrl<Key>o: LoadGameProc() \n \
1028 :Meta<Key>Next: LoadNextGameProc() \n \
1029 :Meta<Key>Prior: LoadPrevGameProc() \n \
1030 :Ctrl<Key>s: SaveGameProc() \n \
1031 :Ctrl<Key>c: CopyGameProc() \n \
1032 :Ctrl<Key>v: PasteGameProc() \n \
1033 :Ctrl<Key>O: LoadPositionProc() \n \
1034 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1035 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1036 :Ctrl<Key>S: SavePositionProc() \n \
1037 :Ctrl<Key>C: CopyPositionProc() \n \
1038 :Ctrl<Key>V: PastePositionProc() \n \
1039 :Ctrl<Key>q: QuitProc() \n \
1040 :Ctrl<Key>w: MachineWhiteProc() \n \
1041 :Ctrl<Key>b: MachineBlackProc() \n \
1042 :Ctrl<Key>t: TwoMachinesProc() \n \
1043 :Ctrl<Key>a: AnalysisModeProc() \n \
1044 :Ctrl<Key>f: AnalyzeFileProc() \n \
1045 :Ctrl<Key>e: EditGameProc() \n \
1046 :Ctrl<Key>E: EditPositionProc() \n \
1047 :Meta<Key>O: EngineOutputProc() \n \
1048 :Meta<Key>E: EvalGraphProc() \n \
1049 :Meta<Key>G: ShowGameListProc() \n \
1050 :Meta<Key>H: ShowMoveListProc() \n \
1051 :<Key>Pause: PauseProc() \n \
1052 :<Key>F3: AcceptProc() \n \
1053 :<Key>F4: DeclineProc() \n \
1054 :<Key>F12: RematchProc() \n \
1055 :<Key>F5: CallFlagProc() \n \
1056 :<Key>F6: DrawProc() \n \
1057 :<Key>F7: AdjournProc() \n \
1058 :<Key>F8: AbortProc() \n \
1059 :<Key>F10: StopObservingProc() \n \
1060 :<Key>F11: StopExaminingProc() \n \
1061 :Meta Ctrl<Key>F12: DebugProc() \n \
1062 :Meta<Key>End: ToEndProc() \n \
1063 :Meta<Key>Right: ForwardProc() \n \
1064 :Meta<Key>Home: ToStartProc() \n \
1065 :Meta<Key>Left: BackwardProc() \n \
1066 :<Key>Home: RevertProc() \n \
1067 :<Key>End: TruncateGameProc() \n \
1068 :Ctrl<Key>m: MoveNowProc() \n \
1069 :Ctrl<Key>x: RetractMoveProc() \n \
1070 :Meta<Key>J: EngineMenuProc() \n \
1071 :Meta<Key>U: UciMenuProc() \n \
1072 :Meta<Key>T: TimeControlProc() \n \
1073 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1074 :Ctrl<Key>F: AutoflagProc() \n \
1075 :Ctrl<Key>A: AnimateMovingProc() \n \
1076 :Ctrl<Key>P: PonderNextMoveProc() \n \
1077 :Ctrl<Key>L: TestLegalityProc() \n \
1078 :Ctrl<Key>H: HideThinkingProc() \n \
1079 :<Key>-: Iconify() \n \
1080 :<Key>F1: ManProc() \n \
1081 :<Key>F2: FlipViewProc() \n \
1082 <KeyDown>.: BackwardProc() \n \
1083 <KeyUp>.: ForwardProc() \n \
1084 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1085 \"Send to chess program:\",,1) \n \
1086 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1087 \"Send to second chess program:\",,2) \n";
1089 char boardTranslations[] =
1090 "<Btn1Down>: HandleUserMove(0) \n \
1091 Shift<Btn1Up>: HandleUserMove(1) \n \
1092 <Btn1Up>: HandleUserMove(0) \n \
1093 <Btn1Motion>: AnimateUserMove() \n \
1094 <Btn3Motion>: HandlePV() \n \
1095 <Btn3Up>: PieceMenuPopup(menuB) \n \
1096 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1097 PieceMenuPopup(menuB) \n \
1098 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1099 PieceMenuPopup(menuW) \n \
1100 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1101 PieceMenuPopup(menuW) \n \
1102 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1103 PieceMenuPopup(menuB) \n";
1105 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1106 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1108 char ICSInputTranslations[] =
1109 "<Key>Up: UpKeyProc() \n "
1110 "<Key>Down: DownKeyProc() \n "
1111 "<Key>Return: EnterKeyProc() \n";
1113 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1114 // as the widget is destroyed before the up-click can call extend-end
1115 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1117 String xboardResources[] = {
1118 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1119 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1120 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1125 /* Max possible square size */
1126 #define MAXSQSIZE 256
1128 static int xpm_avail[MAXSQSIZE];
1130 #ifdef HAVE_DIR_STRUCT
1132 /* Extract piece size from filename */
1134 xpm_getsize(name, len, ext)
1145 if ((p=strchr(name, '.')) == NULL ||
1146 StrCaseCmp(p+1, ext) != 0)
1152 while (*p && isdigit(*p))
1159 /* Setup xpm_avail */
1161 xpm_getavail(dirname, ext)
1169 for (i=0; i<MAXSQSIZE; ++i)
1172 if (appData.debugMode)
1173 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1175 dir = opendir(dirname);
1178 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1179 programName, dirname);
1183 while ((ent=readdir(dir)) != NULL) {
1184 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1185 if (i > 0 && i < MAXSQSIZE)
1195 xpm_print_avail(fp, ext)
1201 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1202 for (i=1; i<MAXSQSIZE; ++i) {
1208 /* Return XPM piecesize closest to size */
1210 xpm_closest_to(dirname, size, ext)
1216 int sm_diff = MAXSQSIZE;
1220 xpm_getavail(dirname, ext);
1222 if (appData.debugMode)
1223 xpm_print_avail(stderr, ext);
1225 for (i=1; i<MAXSQSIZE; ++i) {
1228 diff = (diff<0) ? -diff : diff;
1229 if (diff < sm_diff) {
1237 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1243 #else /* !HAVE_DIR_STRUCT */
1244 /* If we are on a system without a DIR struct, we can't
1245 read the directory, so we can't collect a list of
1246 filenames, etc., so we can't do any size-fitting. */
1248 xpm_closest_to(dirname, size, ext)
1253 fprintf(stderr, _("\
1254 Warning: No DIR structure found on this system --\n\
1255 Unable to autosize for XPM/XIM pieces.\n\
1256 Please report this error to frankm@hiwaay.net.\n\
1257 Include system type & operating system in message.\n"));
1260 #endif /* HAVE_DIR_STRUCT */
1262 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1263 "magenta", "cyan", "white" };
1267 TextColors textColors[(int)NColorClasses];
1269 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1271 parse_color(str, which)
1275 char *p, buf[100], *d;
1278 if (strlen(str) > 99) /* watch bounds on buf */
1283 for (i=0; i<which; ++i) {
1290 /* Could be looking at something like:
1292 .. in which case we want to stop on a comma also */
1293 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1297 return -1; /* Use default for empty field */
1300 if (which == 2 || isdigit(*p))
1303 while (*p && isalpha(*p))
1308 for (i=0; i<8; ++i) {
1309 if (!StrCaseCmp(buf, cnames[i]))
1310 return which? (i+40) : (i+30);
1312 if (!StrCaseCmp(buf, "default")) return -1;
1314 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1319 parse_cpair(cc, str)
1323 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1324 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1329 /* bg and attr are optional */
1330 textColors[(int)cc].bg = parse_color(str, 1);
1331 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1332 textColors[(int)cc].attr = 0;
1338 /* Arrange to catch delete-window events */
1339 Atom wm_delete_window;
1341 CatchDeleteWindow(Widget w, String procname)
1344 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1345 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1346 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1353 XtSetArg(args[0], XtNiconic, False);
1354 XtSetValues(shellWidget, args, 1);
1356 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1359 //---------------------------------------------------------------------------------------------------------
1360 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1363 #define CW_USEDEFAULT (1<<31)
1364 #define ICS_TEXT_MENU_SIZE 90
1365 #define DEBUG_FILE "xboard.debug"
1366 #define SetCurrentDirectory chdir
1367 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1371 // these two must some day move to frontend.h, when they are implemented
1372 Boolean GameListIsUp();
1374 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1377 // front-end part of option handling
1379 // [HGM] This platform-dependent table provides the location for storing the color info
1380 extern char *crWhite, * crBlack;
1384 &appData.whitePieceColor,
1385 &appData.blackPieceColor,
1386 &appData.lightSquareColor,
1387 &appData.darkSquareColor,
1388 &appData.highlightSquareColor,
1389 &appData.premoveHighlightColor,
1390 &appData.lowTimeWarningColor,
1401 // [HGM] font: keep a font for each square size, even non-stndard ones
1402 #define NUM_SIZES 18
1403 #define MAX_SIZE 130
1404 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1405 char *fontTable[NUM_FONTS][MAX_SIZE];
1408 ParseFont(char *name, int number)
1409 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1411 if(sscanf(name, "size%d:", &size)) {
1412 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1413 // defer processing it until we know if it matches our board size
1414 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1415 fontTable[number][size] = strdup(strchr(name, ':')+1);
1416 fontValid[number][size] = True;
1421 case 0: // CLOCK_FONT
1422 appData.clockFont = strdup(name);
1424 case 1: // MESSAGE_FONT
1425 appData.font = strdup(name);
1427 case 2: // COORD_FONT
1428 appData.coordFont = strdup(name);
1433 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1438 { // only 2 fonts currently
1439 appData.clockFont = CLOCK_FONT_NAME;
1440 appData.coordFont = COORD_FONT_NAME;
1441 appData.font = DEFAULT_FONT_NAME;
1446 { // no-op, until we identify the code for this already in XBoard and move it here
1450 ParseColor(int n, char *name)
1451 { // in XBoard, just copy the color-name string
1452 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1456 ParseTextAttribs(ColorClass cc, char *s)
1458 (&appData.colorShout)[cc] = strdup(s);
1462 ParseBoardSize(void *addr, char *name)
1464 appData.boardSize = strdup(name);
1469 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1473 SetCommPortDefaults()
1474 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1477 // [HGM] args: these three cases taken out to stay in front-end
1479 SaveFontArg(FILE *f, ArgDescriptor *ad)
1482 int i, n = (int)ad->argLoc;
1484 case 0: // CLOCK_FONT
1485 name = appData.clockFont;
1487 case 1: // MESSAGE_FONT
1488 name = appData.font;
1490 case 2: // COORD_FONT
1491 name = appData.coordFont;
1496 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1497 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1498 fontTable[n][squareSize] = strdup(name);
1499 fontValid[n][squareSize] = True;
1502 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1503 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1508 { // nothing to do, as the sounds are at all times represented by their text-string names already
1512 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1513 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1514 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1518 SaveColor(FILE *f, ArgDescriptor *ad)
1519 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1520 if(colorVariable[(int)ad->argLoc])
1521 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1525 SaveBoardSize(FILE *f, char *name, void *addr)
1526 { // wrapper to shield back-end from BoardSize & sizeInfo
1527 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1531 ParseCommPortSettings(char *s)
1532 { // no such option in XBoard (yet)
1535 extern Widget engineOutputShell;
1536 extern Widget tagsShell, editTagsShell;
1538 GetActualPlacement(Widget wg, WindowPlacement *wp)
1548 XtSetArg(args[i], XtNx, &x); i++;
1549 XtSetArg(args[i], XtNy, &y); i++;
1550 XtSetArg(args[i], XtNwidth, &w); i++;
1551 XtSetArg(args[i], XtNheight, &h); i++;
1552 XtGetValues(wg, args, i);
1561 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1562 // In XBoard this will have to wait until awareness of window parameters is implemented
1563 GetActualPlacement(shellWidget, &wpMain);
1564 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1565 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1566 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1567 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1568 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1569 else GetActualPlacement(editShell, &wpComment);
1570 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1571 else GetActualPlacement(editTagsShell, &wpTags);
1575 PrintCommPortSettings(FILE *f, char *name)
1576 { // This option does not exist in XBoard
1580 MySearchPath(char *installDir, char *name, char *fullname)
1581 { // just append installDir and name. Perhaps ExpandPath should be used here?
1582 name = ExpandPathName(name);
1583 if(name && name[0] == '/')
1584 safeStrCpy(fullname, name, MSG_SIZ );
1586 sprintf(fullname, "%s%c%s", installDir, '/', name);
1592 MyGetFullPathName(char *name, char *fullname)
1593 { // should use ExpandPath?
1594 name = ExpandPathName(name);
1595 safeStrCpy(fullname, name, MSG_SIZ );
1600 EnsureOnScreen(int *x, int *y, int minX, int minY)
1607 { // [HGM] args: allows testing if main window is realized from back-end
1608 return xBoardWindow != 0;
1612 PopUpStartupDialog()
1613 { // start menu not implemented in XBoard
1617 ConvertToLine(int argc, char **argv)
1619 static char line[128*1024], buf[1024];
1623 for(i=1; i<argc; i++)
1625 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1626 && argv[i][0] != '{' )
1627 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1629 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1630 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1633 line[strlen(line)-1] = NULLCHAR;
1637 //--------------------------------------------------------------------------------------------
1639 extern Boolean twoBoards, partnerUp;
1642 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1644 #define BoardSize int
1645 void InitDrawingSizes(BoardSize boardSize, int flags)
1646 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1647 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1649 XtGeometryResult gres;
1652 if(!formWidget) return;
1655 * Enable shell resizing.
1657 shellArgs[0].value = (XtArgVal) &w;
1658 shellArgs[1].value = (XtArgVal) &h;
1659 XtGetValues(shellWidget, shellArgs, 2);
1661 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1662 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1663 XtSetValues(shellWidget, &shellArgs[2], 4);
1665 XtSetArg(args[0], XtNdefaultDistance, &sep);
1666 XtGetValues(formWidget, args, 1);
1668 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1669 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1671 hOffset = boardWidth + 10;
1672 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1673 secondSegments[i] = gridSegments[i];
1674 secondSegments[i].x1 += hOffset;
1675 secondSegments[i].x2 += hOffset;
1678 XtSetArg(args[0], XtNwidth, boardWidth);
1679 XtSetArg(args[1], XtNheight, boardHeight);
1680 XtSetValues(boardWidget, args, 2);
1682 timerWidth = (boardWidth - sep) / 2;
1683 XtSetArg(args[0], XtNwidth, timerWidth);
1684 XtSetValues(whiteTimerWidget, args, 1);
1685 XtSetValues(blackTimerWidget, args, 1);
1687 XawFormDoLayout(formWidget, False);
1689 if (appData.titleInWindow) {
1691 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1692 XtSetArg(args[i], XtNheight, &h); i++;
1693 XtGetValues(titleWidget, args, i);
1695 w = boardWidth - 2*bor;
1697 XtSetArg(args[0], XtNwidth, &w);
1698 XtGetValues(menuBarWidget, args, 1);
1699 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1702 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1703 if (gres != XtGeometryYes && appData.debugMode) {
1705 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1706 programName, gres, w, h, wr, hr);
1710 XawFormDoLayout(formWidget, True);
1713 * Inhibit shell resizing.
1715 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1716 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1717 shellArgs[4].value = shellArgs[2].value = w;
1718 shellArgs[5].value = shellArgs[3].value = h;
1719 XtSetValues(shellWidget, &shellArgs[0], 6);
1721 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1724 for(i=0; i<4; i++) {
1726 for(p=0; p<=(int)WhiteKing; p++)
1727 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1728 if(gameInfo.variant == VariantShogi) {
1729 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1730 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1731 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1732 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1733 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1736 if(gameInfo.variant == VariantGothic) {
1737 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1740 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1741 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1742 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1745 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1746 for(p=0; p<=(int)WhiteKing; p++)
1747 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1748 if(gameInfo.variant == VariantShogi) {
1749 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1750 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1751 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1752 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1753 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1756 if(gameInfo.variant == VariantGothic) {
1757 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1760 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1761 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1762 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1767 for(i=0; i<2; i++) {
1769 for(p=0; p<=(int)WhiteKing; p++)
1770 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1771 if(gameInfo.variant == VariantShogi) {
1772 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1773 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1774 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1775 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1776 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1779 if(gameInfo.variant == VariantGothic) {
1780 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1783 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1784 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1785 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1800 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1801 XSetWindowAttributes window_attributes;
1803 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1804 XrmValue vFrom, vTo;
1805 XtGeometryResult gres;
1808 int forceMono = False;
1810 srandom(time(0)); // [HGM] book: make random truly random
1812 setbuf(stdout, NULL);
1813 setbuf(stderr, NULL);
1816 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1817 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1821 programName = strrchr(argv[0], '/');
1822 if (programName == NULL)
1823 programName = argv[0];
1828 XtSetLanguageProc(NULL, NULL, NULL);
1829 bindtextdomain(PACKAGE, LOCALEDIR);
1830 textdomain(PACKAGE);
1834 XtAppInitialize(&appContext, "XBoard", shellOptions,
1835 XtNumber(shellOptions),
1836 &argc, argv, xboardResources, NULL, 0);
1837 appData.boardSize = "";
1838 InitAppData(ConvertToLine(argc, argv));
1840 if (p == NULL) p = "/tmp";
1841 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1842 gameCopyFilename = (char*) malloc(i);
1843 gamePasteFilename = (char*) malloc(i);
1844 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1845 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1847 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1848 clientResources, XtNumber(clientResources),
1851 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1852 static char buf[MSG_SIZ];
1853 EscapeExpand(buf, appData.initString);
1854 appData.initString = strdup(buf);
1855 EscapeExpand(buf, appData.secondInitString);
1856 appData.secondInitString = strdup(buf);
1857 EscapeExpand(buf, appData.firstComputerString);
1858 appData.firstComputerString = strdup(buf);
1859 EscapeExpand(buf, appData.secondComputerString);
1860 appData.secondComputerString = strdup(buf);
1863 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1866 if (chdir(chessDir) != 0) {
1867 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1873 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1874 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1875 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1876 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1879 setbuf(debugFP, NULL);
1882 /* [HGM,HR] make sure board size is acceptable */
1883 if(appData.NrFiles > BOARD_FILES ||
1884 appData.NrRanks > BOARD_RANKS )
1885 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1888 /* This feature does not work; animation needs a rewrite */
1889 appData.highlightDragging = FALSE;
1893 xDisplay = XtDisplay(shellWidget);
1894 xScreen = DefaultScreen(xDisplay);
1895 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1897 gameInfo.variant = StringToVariant(appData.variant);
1898 InitPosition(FALSE);
1901 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1903 if (isdigit(appData.boardSize[0])) {
1904 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1905 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1906 &fontPxlSize, &smallLayout, &tinyLayout);
1908 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1909 programName, appData.boardSize);
1913 /* Find some defaults; use the nearest known size */
1914 SizeDefaults *szd, *nearest;
1915 int distance = 99999;
1916 nearest = szd = sizeDefaults;
1917 while (szd->name != NULL) {
1918 if (abs(szd->squareSize - squareSize) < distance) {
1920 distance = abs(szd->squareSize - squareSize);
1921 if (distance == 0) break;
1925 if (i < 2) lineGap = nearest->lineGap;
1926 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1927 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1928 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1929 if (i < 6) smallLayout = nearest->smallLayout;
1930 if (i < 7) tinyLayout = nearest->tinyLayout;
1933 SizeDefaults *szd = sizeDefaults;
1934 if (*appData.boardSize == NULLCHAR) {
1935 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1936 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1939 if (szd->name == NULL) szd--;
1940 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1942 while (szd->name != NULL &&
1943 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1944 if (szd->name == NULL) {
1945 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1946 programName, appData.boardSize);
1950 squareSize = szd->squareSize;
1951 lineGap = szd->lineGap;
1952 clockFontPxlSize = szd->clockFontPxlSize;
1953 coordFontPxlSize = szd->coordFontPxlSize;
1954 fontPxlSize = szd->fontPxlSize;
1955 smallLayout = szd->smallLayout;
1956 tinyLayout = szd->tinyLayout;
1957 // [HGM] font: use defaults from settings file if available and not overruled
1959 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1960 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1961 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1962 appData.font = fontTable[MESSAGE_FONT][squareSize];
1963 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1964 appData.coordFont = fontTable[COORD_FONT][squareSize];
1966 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1967 if (strlen(appData.pixmapDirectory) > 0) {
1968 p = ExpandPathName(appData.pixmapDirectory);
1970 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1971 appData.pixmapDirectory);
1974 if (appData.debugMode) {
1975 fprintf(stderr, _("\
1976 XBoard square size (hint): %d\n\
1977 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1979 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1980 if (appData.debugMode) {
1981 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1984 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1986 /* [HR] height treated separately (hacked) */
1987 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1988 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1989 if (appData.showJail == 1) {
1990 /* Jail on top and bottom */
1991 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1992 XtSetArg(boardArgs[2], XtNheight,
1993 boardHeight + 2*(lineGap + squareSize));
1994 } else if (appData.showJail == 2) {
1996 XtSetArg(boardArgs[1], XtNwidth,
1997 boardWidth + 2*(lineGap + squareSize));
1998 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2001 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2002 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2006 * Determine what fonts to use.
2008 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2009 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2010 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2011 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2012 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2013 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2014 appData.font = FindFont(appData.font, fontPxlSize);
2015 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2016 countFontStruct = XQueryFont(xDisplay, countFontID);
2017 // appData.font = FindFont(appData.font, fontPxlSize);
2019 xdb = XtDatabase(xDisplay);
2020 XrmPutStringResource(&xdb, "*font", appData.font);
2023 * Detect if there are not enough colors available and adapt.
2025 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2026 appData.monoMode = True;
2029 if (!appData.monoMode) {
2030 vFrom.addr = (caddr_t) appData.lightSquareColor;
2031 vFrom.size = strlen(appData.lightSquareColor);
2032 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2033 if (vTo.addr == NULL) {
2034 appData.monoMode = True;
2037 lightSquareColor = *(Pixel *) vTo.addr;
2040 if (!appData.monoMode) {
2041 vFrom.addr = (caddr_t) appData.darkSquareColor;
2042 vFrom.size = strlen(appData.darkSquareColor);
2043 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2044 if (vTo.addr == NULL) {
2045 appData.monoMode = True;
2048 darkSquareColor = *(Pixel *) vTo.addr;
2051 if (!appData.monoMode) {
2052 vFrom.addr = (caddr_t) appData.whitePieceColor;
2053 vFrom.size = strlen(appData.whitePieceColor);
2054 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2055 if (vTo.addr == NULL) {
2056 appData.monoMode = True;
2059 whitePieceColor = *(Pixel *) vTo.addr;
2062 if (!appData.monoMode) {
2063 vFrom.addr = (caddr_t) appData.blackPieceColor;
2064 vFrom.size = strlen(appData.blackPieceColor);
2065 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2066 if (vTo.addr == NULL) {
2067 appData.monoMode = True;
2070 blackPieceColor = *(Pixel *) vTo.addr;
2074 if (!appData.monoMode) {
2075 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2076 vFrom.size = strlen(appData.highlightSquareColor);
2077 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2078 if (vTo.addr == NULL) {
2079 appData.monoMode = True;
2082 highlightSquareColor = *(Pixel *) vTo.addr;
2086 if (!appData.monoMode) {
2087 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2088 vFrom.size = strlen(appData.premoveHighlightColor);
2089 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2090 if (vTo.addr == NULL) {
2091 appData.monoMode = True;
2094 premoveHighlightColor = *(Pixel *) vTo.addr;
2099 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2102 if (appData.bitmapDirectory == NULL ||
2103 appData.bitmapDirectory[0] == NULLCHAR)
2104 appData.bitmapDirectory = DEF_BITMAP_DIR;
2107 if (appData.lowTimeWarning && !appData.monoMode) {
2108 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2109 vFrom.size = strlen(appData.lowTimeWarningColor);
2110 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2111 if (vTo.addr == NULL)
2112 appData.monoMode = True;
2114 lowTimeWarningColor = *(Pixel *) vTo.addr;
2117 if (appData.monoMode && appData.debugMode) {
2118 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2119 (unsigned long) XWhitePixel(xDisplay, xScreen),
2120 (unsigned long) XBlackPixel(xDisplay, xScreen));
2123 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2124 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2125 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2126 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2127 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2128 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2129 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2130 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2131 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2132 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2134 if (appData.colorize) {
2136 _("%s: can't parse color names; disabling colorization\n"),
2139 appData.colorize = FALSE;
2141 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2142 textColors[ColorNone].attr = 0;
2144 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2150 layoutName = "tinyLayout";
2151 } else if (smallLayout) {
2152 layoutName = "smallLayout";
2154 layoutName = "normalLayout";
2156 /* Outer layoutWidget is there only to provide a name for use in
2157 resources that depend on the layout style */
2159 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2160 layoutArgs, XtNumber(layoutArgs));
2162 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2163 formArgs, XtNumber(formArgs));
2164 XtSetArg(args[0], XtNdefaultDistance, &sep);
2165 XtGetValues(formWidget, args, 1);
2168 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2169 XtSetArg(args[0], XtNtop, XtChainTop);
2170 XtSetArg(args[1], XtNbottom, XtChainTop);
2171 XtSetArg(args[2], XtNright, XtChainLeft);
2172 XtSetValues(menuBarWidget, args, 3);
2174 widgetList[j++] = whiteTimerWidget =
2175 XtCreateWidget("whiteTime", labelWidgetClass,
2176 formWidget, timerArgs, XtNumber(timerArgs));
2177 XtSetArg(args[0], XtNfont, clockFontStruct);
2178 XtSetArg(args[1], XtNtop, XtChainTop);
2179 XtSetArg(args[2], XtNbottom, XtChainTop);
2180 XtSetValues(whiteTimerWidget, args, 3);
2182 widgetList[j++] = blackTimerWidget =
2183 XtCreateWidget("blackTime", labelWidgetClass,
2184 formWidget, timerArgs, XtNumber(timerArgs));
2185 XtSetArg(args[0], XtNfont, clockFontStruct);
2186 XtSetArg(args[1], XtNtop, XtChainTop);
2187 XtSetArg(args[2], XtNbottom, XtChainTop);
2188 XtSetValues(blackTimerWidget, args, 3);
2190 if (appData.titleInWindow) {
2191 widgetList[j++] = titleWidget =
2192 XtCreateWidget("title", labelWidgetClass, formWidget,
2193 titleArgs, XtNumber(titleArgs));
2194 XtSetArg(args[0], XtNtop, XtChainTop);
2195 XtSetArg(args[1], XtNbottom, XtChainTop);
2196 XtSetValues(titleWidget, args, 2);
2199 if (appData.showButtonBar) {
2200 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2201 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2202 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2203 XtSetArg(args[2], XtNtop, XtChainTop);
2204 XtSetArg(args[3], XtNbottom, XtChainTop);
2205 XtSetValues(buttonBarWidget, args, 4);
2208 widgetList[j++] = messageWidget =
2209 XtCreateWidget("message", labelWidgetClass, formWidget,
2210 messageArgs, XtNumber(messageArgs));
2211 XtSetArg(args[0], XtNtop, XtChainTop);
2212 XtSetArg(args[1], XtNbottom, XtChainTop);
2213 XtSetValues(messageWidget, args, 2);
2215 widgetList[j++] = boardWidget =
2216 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2217 XtNumber(boardArgs));
2219 XtManageChildren(widgetList, j);
2221 timerWidth = (boardWidth - sep) / 2;
2222 XtSetArg(args[0], XtNwidth, timerWidth);
2223 XtSetValues(whiteTimerWidget, args, 1);
2224 XtSetValues(blackTimerWidget, args, 1);
2226 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2227 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2228 XtGetValues(whiteTimerWidget, args, 2);
2230 if (appData.showButtonBar) {
2231 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2232 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2233 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2237 * formWidget uses these constraints but they are stored
2241 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2242 XtSetValues(menuBarWidget, args, i);
2243 if (appData.titleInWindow) {
2246 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2247 XtSetValues(whiteTimerWidget, args, i);
2249 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2250 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2251 XtSetValues(blackTimerWidget, args, i);
2253 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2254 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2255 XtSetValues(titleWidget, args, i);
2257 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2258 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2259 XtSetValues(messageWidget, args, i);
2260 if (appData.showButtonBar) {
2262 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2263 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2264 XtSetValues(buttonBarWidget, args, i);
2268 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2269 XtSetValues(whiteTimerWidget, args, i);
2271 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2272 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2273 XtSetValues(blackTimerWidget, args, i);
2275 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2276 XtSetValues(titleWidget, args, i);
2278 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2279 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2280 XtSetValues(messageWidget, args, i);
2281 if (appData.showButtonBar) {
2283 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2284 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2285 XtSetValues(buttonBarWidget, args, i);
2290 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2291 XtSetValues(whiteTimerWidget, args, i);
2293 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2294 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2295 XtSetValues(blackTimerWidget, args, i);
2297 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2298 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2299 XtSetValues(messageWidget, args, i);
2300 if (appData.showButtonBar) {
2302 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2303 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2304 XtSetValues(buttonBarWidget, args, i);
2308 XtSetArg(args[0], XtNfromVert, messageWidget);
2309 XtSetArg(args[1], XtNtop, XtChainTop);
2310 XtSetArg(args[2], XtNbottom, XtChainBottom);
2311 XtSetArg(args[3], XtNleft, XtChainLeft);
2312 XtSetArg(args[4], XtNright, XtChainRight);
2313 XtSetValues(boardWidget, args, 5);
2315 XtRealizeWidget(shellWidget);
2318 XtSetArg(args[0], XtNx, wpMain.x);
2319 XtSetArg(args[1], XtNy, wpMain.y);
2320 XtSetValues(shellWidget, args, 2);
2324 * Correct the width of the message and title widgets.
2325 * It is not known why some systems need the extra fudge term.
2326 * The value "2" is probably larger than needed.
2328 XawFormDoLayout(formWidget, False);
2330 #define WIDTH_FUDGE 2
2332 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2333 XtSetArg(args[i], XtNheight, &h); i++;
2334 XtGetValues(messageWidget, args, i);
2335 if (appData.showButtonBar) {
2337 XtSetArg(args[i], XtNwidth, &w); i++;
2338 XtGetValues(buttonBarWidget, args, i);
2339 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2341 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2344 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2345 if (gres != XtGeometryYes && appData.debugMode) {
2346 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2347 programName, gres, w, h, wr, hr);
2350 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2351 /* The size used for the child widget in layout lags one resize behind
2352 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2354 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2355 if (gres != XtGeometryYes && appData.debugMode) {
2356 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2357 programName, gres, w, h, wr, hr);
2360 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2361 XtSetArg(args[1], XtNright, XtChainRight);
2362 XtSetValues(messageWidget, args, 2);
2364 if (appData.titleInWindow) {
2366 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2367 XtSetArg(args[i], XtNheight, &h); i++;
2368 XtGetValues(titleWidget, args, i);
2370 w = boardWidth - 2*bor;
2372 XtSetArg(args[0], XtNwidth, &w);
2373 XtGetValues(menuBarWidget, args, 1);
2374 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2377 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2378 if (gres != XtGeometryYes && appData.debugMode) {
2380 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2381 programName, gres, w, h, wr, hr);
2384 XawFormDoLayout(formWidget, True);
2386 xBoardWindow = XtWindow(boardWidget);
2388 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2389 // not need to go into InitDrawingSizes().
2393 * Create X checkmark bitmap and initialize option menu checks.
2395 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2396 checkmark_bits, checkmark_width, checkmark_height);
2397 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2398 if (appData.alwaysPromoteToQueen) {
2399 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2402 if (appData.animateDragging) {
2403 XtSetValues(XtNameToWidget(menuBarWidget,
2404 "menuOptions.Animate Dragging"),
2407 if (appData.animate) {
2408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2411 if (appData.autoComment) {
2412 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2415 if (appData.autoCallFlag) {
2416 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2419 if (appData.autoFlipView) {
2420 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2423 if (appData.autoObserve) {
2424 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2427 if (appData.autoRaiseBoard) {
2428 XtSetValues(XtNameToWidget(menuBarWidget,
2429 "menuOptions.Auto Raise Board"), args, 1);
2431 if (appData.autoSaveGames) {
2432 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2435 if (appData.saveGameFile[0] != NULLCHAR) {
2436 /* Can't turn this off from menu */
2437 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2439 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2443 if (appData.blindfold) {
2444 XtSetValues(XtNameToWidget(menuBarWidget,
2445 "menuOptions.Blindfold"), args, 1);
2447 if (appData.flashCount > 0) {
2448 XtSetValues(XtNameToWidget(menuBarWidget,
2449 "menuOptions.Flash Moves"),
2452 if (appData.getMoveList) {
2453 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2457 if (appData.highlightDragging) {
2458 XtSetValues(XtNameToWidget(menuBarWidget,
2459 "menuOptions.Highlight Dragging"),
2463 if (appData.highlightLastMove) {
2464 XtSetValues(XtNameToWidget(menuBarWidget,
2465 "menuOptions.Highlight Last Move"),
2468 if (appData.icsAlarm) {
2469 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2472 if (appData.ringBellAfterMoves) {
2473 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2476 if (appData.oldSaveStyle) {
2477 XtSetValues(XtNameToWidget(menuBarWidget,
2478 "menuOptions.Old Save Style"), args, 1);
2480 if (appData.periodicUpdates) {
2481 XtSetValues(XtNameToWidget(menuBarWidget,
2482 "menuOptions.Periodic Updates"), args, 1);
2484 if (appData.ponderNextMove) {
2485 XtSetValues(XtNameToWidget(menuBarWidget,
2486 "menuOptions.Ponder Next Move"), args, 1);
2488 if (appData.popupExitMessage) {
2489 XtSetValues(XtNameToWidget(menuBarWidget,
2490 "menuOptions.Popup Exit Message"), args, 1);
2492 if (appData.popupMoveErrors) {
2493 XtSetValues(XtNameToWidget(menuBarWidget,
2494 "menuOptions.Popup Move Errors"), args, 1);
2496 if (appData.premove) {
2497 XtSetValues(XtNameToWidget(menuBarWidget,
2498 "menuOptions.Premove"), args, 1);
2500 if (appData.quietPlay) {
2501 XtSetValues(XtNameToWidget(menuBarWidget,
2502 "menuOptions.Quiet Play"), args, 1);
2504 if (appData.showCoords) {
2505 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2508 if (appData.hideThinkingFromHuman) {
2509 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2512 if (appData.testLegality) {
2513 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2516 if (saveSettingsOnExit) {
2517 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2524 ReadBitmap(&wIconPixmap, "icon_white.bm",
2525 icon_white_bits, icon_white_width, icon_white_height);
2526 ReadBitmap(&bIconPixmap, "icon_black.bm",
2527 icon_black_bits, icon_black_width, icon_black_height);
2528 iconPixmap = wIconPixmap;
2530 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2531 XtSetValues(shellWidget, args, i);
2534 * Create a cursor for the board widget.
2536 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2537 XChangeWindowAttributes(xDisplay, xBoardWindow,
2538 CWCursor, &window_attributes);
2541 * Inhibit shell resizing.
2543 shellArgs[0].value = (XtArgVal) &w;
2544 shellArgs[1].value = (XtArgVal) &h;
2545 XtGetValues(shellWidget, shellArgs, 2);
2546 shellArgs[4].value = shellArgs[2].value = w;
2547 shellArgs[5].value = shellArgs[3].value = h;
2548 XtSetValues(shellWidget, &shellArgs[2], 4);
2549 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2550 marginH = h - boardHeight;
2552 CatchDeleteWindow(shellWidget, "QuitProc");
2557 if (appData.bitmapDirectory[0] != NULLCHAR) {
2561 CreateXPMBoard(appData.liteBackTextureFile, 1);
2562 CreateXPMBoard(appData.darkBackTextureFile, 0);
2566 /* Create regular pieces */
2567 if (!useImages) CreatePieces();
2572 if (appData.animate || appData.animateDragging)
2575 XtAugmentTranslations(formWidget,
2576 XtParseTranslationTable(globalTranslations));
2577 XtAugmentTranslations(boardWidget,
2578 XtParseTranslationTable(boardTranslations));
2579 XtAugmentTranslations(whiteTimerWidget,
2580 XtParseTranslationTable(whiteTranslations));
2581 XtAugmentTranslations(blackTimerWidget,
2582 XtParseTranslationTable(blackTranslations));
2584 /* Why is the following needed on some versions of X instead
2585 * of a translation? */
2586 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2587 (XtEventHandler) EventProc, NULL);
2590 /* [AS] Restore layout */
2591 if( wpMoveHistory.visible ) {
2595 if( wpEvalGraph.visible )
2600 if( wpEngineOutput.visible ) {
2601 EngineOutputPopUp();
2606 if (errorExitStatus == -1) {
2607 if (appData.icsActive) {
2608 /* We now wait until we see "login:" from the ICS before
2609 sending the logon script (problems with timestamp otherwise) */
2610 /*ICSInitScript();*/
2611 if (appData.icsInputBox) ICSInputBoxPopUp();
2615 signal(SIGWINCH, TermSizeSigHandler);
2617 signal(SIGINT, IntSigHandler);
2618 signal(SIGTERM, IntSigHandler);
2619 if (*appData.cmailGameName != NULLCHAR) {
2620 signal(SIGUSR1, CmailSigHandler);
2623 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2625 XtSetKeyboardFocus(shellWidget, formWidget);
2627 XtAppMainLoop(appContext);
2628 if (appData.debugMode) fclose(debugFP); // [DM] debug
2635 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2636 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2638 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2639 unlink(gameCopyFilename);
2640 unlink(gamePasteFilename);
2643 RETSIGTYPE TermSizeSigHandler(int sig)
2656 CmailSigHandler(sig)
2662 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2664 /* Activate call-back function CmailSigHandlerCallBack() */
2665 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2667 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2671 CmailSigHandlerCallBack(isr, closure, message, count, error)
2679 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2681 /**** end signal code ****/
2687 /* try to open the icsLogon script, either in the location given
2688 * or in the users HOME directory
2695 f = fopen(appData.icsLogon, "r");
2698 homedir = getenv("HOME");
2699 if (homedir != NULL)
2701 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2702 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2703 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2704 f = fopen(buf, "r");
2709 ProcessICSInitScript(f);
2711 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2720 EditCommentPopDown();
2735 if (!menuBarWidget) return;
2736 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2738 DisplayError("menuEdit.Revert", 0);
2740 XtSetSensitive(w, !grey);
2742 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2744 DisplayError("menuEdit.Annotate", 0);
2746 XtSetSensitive(w, !grey);
2751 SetMenuEnables(enab)
2755 if (!menuBarWidget) return;
2756 while (enab->name != NULL) {
2757 w = XtNameToWidget(menuBarWidget, enab->name);
2759 DisplayError(enab->name, 0);
2761 XtSetSensitive(w, enab->value);
2767 Enables icsEnables[] = {
2768 { "menuFile.Mail Move", False },
2769 { "menuFile.Reload CMail Message", False },
2770 { "menuMode.Machine Black", False },
2771 { "menuMode.Machine White", False },
2772 { "menuMode.Analysis Mode", False },
2773 { "menuMode.Analyze File", False },
2774 { "menuMode.Two Machines", False },
2776 { "menuEngine.Hint", False },
2777 { "menuEngine.Book", False },
2778 { "menuEngine.Move Now", False },
2779 { "menuOptions.Periodic Updates", False },
2780 { "menuOptions.Hide Thinking", False },
2781 { "menuOptions.Ponder Next Move", False },
2782 { "menuEngine.Engine #1 Settings", False },
2784 { "menuEngine.Engine #2 Settings", False },
2785 { "menuEdit.Annotate", False },
2789 Enables ncpEnables[] = {
2790 { "menuFile.Mail Move", False },
2791 { "menuFile.Reload CMail Message", False },
2792 { "menuMode.Machine White", False },
2793 { "menuMode.Machine Black", False },
2794 { "menuMode.Analysis Mode", False },
2795 { "menuMode.Analyze File", False },
2796 { "menuMode.Two Machines", False },
2797 { "menuMode.ICS Client", False },
2798 { "menuView.ICS Input Box", False },
2799 { "Action", False },
2800 { "menuEdit.Revert", False },
2801 { "menuEdit.Annotate", False },
2802 { "menuEngine.Engine #1 Settings", False },
2803 { "menuEngine.Engine #2 Settings", False },
2804 { "menuEngine.Move Now", False },
2805 { "menuEngine.Retract Move", False },
2806 { "menuOptions.Auto Comment", False },
2807 { "menuOptions.Auto Flag", False },
2808 { "menuOptions.Auto Flip View", False },
2809 { "menuOptions.Auto Observe", False },
2810 { "menuOptions.Auto Raise Board", False },
2811 { "menuOptions.Get Move List", False },
2812 { "menuOptions.ICS Alarm", False },
2813 { "menuOptions.Move Sound", False },
2814 { "menuOptions.Quiet Play", False },
2815 { "menuOptions.Hide Thinking", False },
2816 { "menuOptions.Periodic Updates", False },
2817 { "menuOptions.Ponder Next Move", False },
2818 { "menuEngine.Hint", False },
2819 { "menuEngine.Book", False },
2823 Enables gnuEnables[] = {
2824 { "menuMode.ICS Client", False },
2825 { "menuView.ICS Input Box", False },
2826 { "menuAction.Accept", False },
2827 { "menuAction.Decline", False },
2828 { "menuAction.Rematch", False },
2829 { "menuAction.Adjourn", False },
2830 { "menuAction.Stop Examining", False },
2831 { "menuAction.Stop Observing", False },
2832 { "menuAction.Upload to Examine", False },
2833 { "menuEdit.Revert", False },
2834 { "menuEdit.Annotate", False },
2835 { "menuOptions.Auto Comment", False },
2836 { "menuOptions.Auto Observe", False },
2837 { "menuOptions.Auto Raise Board", False },
2838 { "menuOptions.Get Move List", False },
2839 { "menuOptions.Premove", False },
2840 { "menuOptions.Quiet Play", False },
2842 /* The next two options rely on SetCmailMode being called *after* */
2843 /* SetGNUMode so that when GNU is being used to give hints these */
2844 /* menu options are still available */
2846 { "menuFile.Mail Move", False },
2847 { "menuFile.Reload CMail Message", False },
2851 Enables cmailEnables[] = {
2853 { "menuAction.Call Flag", False },
2854 { "menuAction.Draw", True },
2855 { "menuAction.Adjourn", False },
2856 { "menuAction.Abort", False },
2857 { "menuAction.Stop Observing", False },
2858 { "menuAction.Stop Examining", False },
2859 { "menuFile.Mail Move", True },
2860 { "menuFile.Reload CMail Message", True },
2864 Enables trainingOnEnables[] = {
2865 { "menuMode.Edit Comment", False },
2866 { "menuMode.Pause", False },
2867 { "menuEdit.Forward", False },
2868 { "menuEdit.Backward", False },
2869 { "menuEdit.Forward to End", False },
2870 { "menuEdit.Back to Start", False },
2871 { "menuEngine.Move Now", False },
2872 { "menuEdit.Truncate Game", False },
2876 Enables trainingOffEnables[] = {
2877 { "menuMode.Edit Comment", True },
2878 { "menuMode.Pause", True },
2879 { "menuEdit.Forward", True },
2880 { "menuEdit.Backward", True },
2881 { "menuEdit.Forward to End", True },
2882 { "menuEdit.Back to Start", True },
2883 { "menuEngine.Move Now", True },
2884 { "menuEdit.Truncate Game", True },
2888 Enables machineThinkingEnables[] = {
2889 { "menuFile.Load Game", False },
2890 // { "menuFile.Load Next Game", False },
2891 // { "menuFile.Load Previous Game", False },
2892 // { "menuFile.Reload Same Game", False },
2893 { "menuEdit.Paste Game", False },
2894 { "menuFile.Load Position", False },
2895 // { "menuFile.Load Next Position", False },
2896 // { "menuFile.Load Previous Position", False },
2897 // { "menuFile.Reload Same Position", False },
2898 { "menuEdit.Paste Position", False },
2899 { "menuMode.Machine White", False },
2900 { "menuMode.Machine Black", False },
2901 { "menuMode.Two Machines", False },
2902 { "menuEngine.Retract Move", False },
2906 Enables userThinkingEnables[] = {
2907 { "menuFile.Load Game", True },
2908 // { "menuFile.Load Next Game", True },
2909 // { "menuFile.Load Previous Game", True },
2910 // { "menuFile.Reload Same Game", True },
2911 { "menuEdit.Paste Game", True },
2912 { "menuFile.Load Position", True },
2913 // { "menuFile.Load Next Position", True },
2914 // { "menuFile.Load Previous Position", True },
2915 // { "menuFile.Reload Same Position", True },
2916 { "menuEdit.Paste Position", True },
2917 { "menuMode.Machine White", True },
2918 { "menuMode.Machine Black", True },
2919 { "menuMode.Two Machines", True },
2920 { "menuEngine.Retract Move", True },
2926 SetMenuEnables(icsEnables);
2929 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2930 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2937 SetMenuEnables(ncpEnables);
2943 SetMenuEnables(gnuEnables);
2949 SetMenuEnables(cmailEnables);
2955 SetMenuEnables(trainingOnEnables);
2956 if (appData.showButtonBar) {
2957 XtSetSensitive(buttonBarWidget, False);
2963 SetTrainingModeOff()
2965 SetMenuEnables(trainingOffEnables);
2966 if (appData.showButtonBar) {
2967 XtSetSensitive(buttonBarWidget, True);
2972 SetUserThinkingEnables()
2974 if (appData.noChessProgram) return;
2975 SetMenuEnables(userThinkingEnables);
2979 SetMachineThinkingEnables()
2981 if (appData.noChessProgram) return;
2982 SetMenuEnables(machineThinkingEnables);
2984 case MachinePlaysBlack:
2985 case MachinePlaysWhite:
2986 case TwoMachinesPlay:
2987 XtSetSensitive(XtNameToWidget(menuBarWidget,
2988 ModeToWidgetName(gameMode)), True);
2995 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2996 #define HISTORY_SIZE 64
2997 static char *history[HISTORY_SIZE];
2998 int histIn = 0, histP = 0;
3001 SaveInHistory(char *cmd)
3003 if (history[histIn] != NULL) {
3004 free(history[histIn]);
3005 history[histIn] = NULL;
3007 if (*cmd == NULLCHAR) return;
3008 history[histIn] = StrSave(cmd);
3009 histIn = (histIn + 1) % HISTORY_SIZE;
3010 if (history[histIn] != NULL) {
3011 free(history[histIn]);
3012 history[histIn] = NULL;
3018 PrevInHistory(char *cmd)
3021 if (histP == histIn) {
3022 if (history[histIn] != NULL) free(history[histIn]);
3023 history[histIn] = StrSave(cmd);
3025 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3026 if (newhp == histIn || history[newhp] == NULL) return NULL;
3028 return history[histP];
3034 if (histP == histIn) return NULL;
3035 histP = (histP + 1) % HISTORY_SIZE;
3036 return history[histP];
3038 // end of borrowed code
3040 #define Abs(n) ((n)<0 ? -(n) : (n))
3043 * Find a font that matches "pattern" that is as close as
3044 * possible to the targetPxlSize. Prefer fonts that are k
3045 * pixels smaller to fonts that are k pixels larger. The
3046 * pattern must be in the X Consortium standard format,
3047 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3048 * The return value should be freed with XtFree when no
3052 FindFont(pattern, targetPxlSize)
3056 char **fonts, *p, *best, *scalable, *scalableTail;
3057 int i, j, nfonts, minerr, err, pxlSize;
3060 char **missing_list;
3062 char *def_string, *base_fnt_lst, strInt[3];
3064 XFontStruct **fnt_list;
3066 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3067 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3068 p = strstr(pattern, "--");
3069 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3070 strcat(base_fnt_lst, strInt);
3071 strcat(base_fnt_lst, strchr(p + 2, '-'));
3073 if ((fntSet = XCreateFontSet(xDisplay,
3077 &def_string)) == NULL) {
3079 fprintf(stderr, _("Unable to create font set.\n"));
3083 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3085 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3087 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3088 programName, pattern);
3096 for (i=0; i<nfonts; i++) {
3099 if (*p != '-') continue;
3101 if (*p == NULLCHAR) break;
3102 if (*p++ == '-') j++;
3104 if (j < 7) continue;
3107 scalable = fonts[i];
3110 err = pxlSize - targetPxlSize;
3111 if (Abs(err) < Abs(minerr) ||
3112 (minerr > 0 && err < 0 && -err == minerr)) {
3118 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3119 /* If the error is too big and there is a scalable font,
3120 use the scalable font. */
3121 int headlen = scalableTail - scalable;
3122 p = (char *) XtMalloc(strlen(scalable) + 10);
3123 while (isdigit(*scalableTail)) scalableTail++;
3124 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3126 p = (char *) XtMalloc(strlen(best) + 2);
3127 safeStrCpy(p, best, strlen(best)+1 );
3129 if (appData.debugMode) {
3130 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3131 pattern, targetPxlSize, p);
3134 if (missing_count > 0)
3135 XFreeStringList(missing_list);
3136 XFreeFontSet(xDisplay, fntSet);
3138 XFreeFontNames(fonts);
3145 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3146 | GCBackground | GCFunction | GCPlaneMask;
3147 XGCValues gc_values;
3150 gc_values.plane_mask = AllPlanes;
3151 gc_values.line_width = lineGap;
3152 gc_values.line_style = LineSolid;
3153 gc_values.function = GXcopy;
3155 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3156 gc_values.background = XBlackPixel(xDisplay, xScreen);
3157 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3159 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3160 gc_values.background = XWhitePixel(xDisplay, xScreen);
3161 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3162 XSetFont(xDisplay, coordGC, coordFontID);
3164 // [HGM] make font for holdings counts (white on black0
3165 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3166 gc_values.background = XBlackPixel(xDisplay, xScreen);
3167 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3168 XSetFont(xDisplay, countGC, countFontID);
3170 if (appData.monoMode) {
3171 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3172 gc_values.background = XWhitePixel(xDisplay, xScreen);
3173 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3175 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3176 gc_values.background = XBlackPixel(xDisplay, xScreen);
3177 lightSquareGC = wbPieceGC
3178 = XtGetGC(shellWidget, value_mask, &gc_values);
3180 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3181 gc_values.background = XWhitePixel(xDisplay, xScreen);
3182 darkSquareGC = bwPieceGC
3183 = XtGetGC(shellWidget, value_mask, &gc_values);
3185 if (DefaultDepth(xDisplay, xScreen) == 1) {
3186 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3187 gc_values.function = GXcopyInverted;
3188 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3189 gc_values.function = GXcopy;
3190 if (XBlackPixel(xDisplay, xScreen) == 1) {
3191 bwPieceGC = darkSquareGC;
3192 wbPieceGC = copyInvertedGC;
3194 bwPieceGC = copyInvertedGC;
3195 wbPieceGC = lightSquareGC;
3199 gc_values.foreground = highlightSquareColor;
3200 gc_values.background = highlightSquareColor;
3201 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3203 gc_values.foreground = premoveHighlightColor;
3204 gc_values.background = premoveHighlightColor;
3205 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3207 gc_values.foreground = lightSquareColor;
3208 gc_values.background = darkSquareColor;
3209 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3211 gc_values.foreground = darkSquareColor;
3212 gc_values.background = lightSquareColor;
3213 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3215 gc_values.foreground = jailSquareColor;
3216 gc_values.background = jailSquareColor;
3217 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3219 gc_values.foreground = whitePieceColor;
3220 gc_values.background = darkSquareColor;
3221 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3223 gc_values.foreground = whitePieceColor;
3224 gc_values.background = lightSquareColor;
3225 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3227 gc_values.foreground = whitePieceColor;
3228 gc_values.background = jailSquareColor;
3229 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3231 gc_values.foreground = blackPieceColor;
3232 gc_values.background = darkSquareColor;
3233 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3235 gc_values.foreground = blackPieceColor;
3236 gc_values.background = lightSquareColor;
3237 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3239 gc_values.foreground = blackPieceColor;
3240 gc_values.background = jailSquareColor;
3241 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3245 void loadXIM(xim, xmask, filename, dest, mask)
3258 fp = fopen(filename, "rb");
3260 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3267 for (y=0; y<h; ++y) {
3268 for (x=0; x<h; ++x) {
3273 XPutPixel(xim, x, y, blackPieceColor);
3275 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3278 XPutPixel(xim, x, y, darkSquareColor);
3280 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3283 XPutPixel(xim, x, y, whitePieceColor);
3285 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3288 XPutPixel(xim, x, y, lightSquareColor);
3290 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3296 /* create Pixmap of piece */
3297 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3299 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3302 /* create Pixmap of clipmask
3303 Note: We assume the white/black pieces have the same
3304 outline, so we make only 6 masks. This is okay
3305 since the XPM clipmask routines do the same. */
3307 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3309 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3312 /* now create the 1-bit version */
3313 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3316 values.foreground = 1;
3317 values.background = 0;
3319 /* Don't use XtGetGC, not read only */
3320 maskGC = XCreateGC(xDisplay, *mask,
3321 GCForeground | GCBackground, &values);
3322 XCopyPlane(xDisplay, temp, *mask, maskGC,
3323 0, 0, squareSize, squareSize, 0, 0, 1);
3324 XFreePixmap(xDisplay, temp);
3329 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3331 void CreateXIMPieces()
3336 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3341 /* The XSynchronize calls were copied from CreatePieces.
3342 Not sure if needed, but can't hurt */
3343 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3346 /* temp needed by loadXIM() */
3347 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3348 0, 0, ss, ss, AllPlanes, XYPixmap);
3350 if (strlen(appData.pixmapDirectory) == 0) {
3354 if (appData.monoMode) {
3355 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3359 fprintf(stderr, _("\nLoading XIMs...\n"));
3361 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3362 fprintf(stderr, "%d", piece+1);
3363 for (kind=0; kind<4; kind++) {
3364 fprintf(stderr, ".");
3365 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3366 ExpandPathName(appData.pixmapDirectory),
3367 piece <= (int) WhiteKing ? "" : "w",
3368 pieceBitmapNames[piece],
3370 ximPieceBitmap[kind][piece] =
3371 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3372 0, 0, ss, ss, AllPlanes, XYPixmap);
3373 if (appData.debugMode)
3374 fprintf(stderr, _("(File:%s:) "), buf);
3375 loadXIM(ximPieceBitmap[kind][piece],
3377 &(xpmPieceBitmap2[kind][piece]),
3378 &(ximMaskPm2[piece]));
3379 if(piece <= (int)WhiteKing)
3380 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3382 fprintf(stderr," ");
3384 /* Load light and dark squares */
3385 /* If the LSQ and DSQ pieces don't exist, we will
3386 draw them with solid squares. */
3387 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3388 if (access(buf, 0) != 0) {
3392 fprintf(stderr, _("light square "));
3394 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3395 0, 0, ss, ss, AllPlanes, XYPixmap);
3396 if (appData.debugMode)
3397 fprintf(stderr, _("(File:%s:) "), buf);
3399 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3400 fprintf(stderr, _("dark square "));
3401 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3402 ExpandPathName(appData.pixmapDirectory), ss);
3403 if (appData.debugMode)
3404 fprintf(stderr, _("(File:%s:) "), buf);
3406 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3407 0, 0, ss, ss, AllPlanes, XYPixmap);
3408 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3409 xpmJailSquare = xpmLightSquare;
3411 fprintf(stderr, _("Done.\n"));
3413 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3417 void CreateXPMBoard(char *s, int kind)
3421 if(s == NULL || *s == 0 || *s == '*') return;
3422 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3423 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3427 void CreateXPMPieces()
3431 u_int ss = squareSize;
3433 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3434 XpmColorSymbol symbols[4];
3436 /* The XSynchronize calls were copied from CreatePieces.
3437 Not sure if needed, but can't hurt */
3438 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3440 /* Setup translations so piece colors match square colors */
3441 symbols[0].name = "light_piece";
3442 symbols[0].value = appData.whitePieceColor;
3443 symbols[1].name = "dark_piece";
3444 symbols[1].value = appData.blackPieceColor;
3445 symbols[2].name = "light_square";
3446 symbols[2].value = appData.lightSquareColor;
3447 symbols[3].name = "dark_square";
3448 symbols[3].value = appData.darkSquareColor;
3450 attr.valuemask = XpmColorSymbols;
3451 attr.colorsymbols = symbols;
3452 attr.numsymbols = 4;
3454 if (appData.monoMode) {
3455 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3459 if (strlen(appData.pixmapDirectory) == 0) {
3460 XpmPieces* pieces = builtInXpms;
3463 while (pieces->size != squareSize && pieces->size) pieces++;
3464 if (!pieces->size) {
3465 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3468 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3469 for (kind=0; kind<4; kind++) {
3471 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3472 pieces->xpm[piece][kind],
3473 &(xpmPieceBitmap2[kind][piece]),
3474 NULL, &attr)) != 0) {
3475 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3479 if(piece <= (int) WhiteKing)
3480 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3484 xpmJailSquare = xpmLightSquare;
3488 fprintf(stderr, _("\nLoading XPMs...\n"));
3491 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3492 fprintf(stderr, "%d ", piece+1);
3493 for (kind=0; kind<4; kind++) {
3494 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3495 ExpandPathName(appData.pixmapDirectory),
3496 piece > (int) WhiteKing ? "w" : "",
3497 pieceBitmapNames[piece],
3499 if (appData.debugMode) {
3500 fprintf(stderr, _("(File:%s:) "), buf);
3502 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3503 &(xpmPieceBitmap2[kind][piece]),
3504 NULL, &attr)) != 0) {
3505 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3506 // [HGM] missing: read of unorthodox piece failed; substitute King.
3507 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3508 ExpandPathName(appData.pixmapDirectory),
3510 if (appData.debugMode) {
3511 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3513 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3514 &(xpmPieceBitmap2[kind][piece]),
3518 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3523 if(piece <= (int) WhiteKing)
3524 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3527 /* Load light and dark squares */
3528 /* If the LSQ and DSQ pieces don't exist, we will
3529 draw them with solid squares. */
3530 fprintf(stderr, _("light square "));
3531 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3532 if (access(buf, 0) != 0) {
3536 if (appData.debugMode)
3537 fprintf(stderr, _("(File:%s:) "), buf);
3539 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3540 &xpmLightSquare, NULL, &attr)) != 0) {
3541 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3544 fprintf(stderr, _("dark square "));
3545 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3546 ExpandPathName(appData.pixmapDirectory), ss);
3547 if (appData.debugMode) {
3548 fprintf(stderr, _("(File:%s:) "), buf);
3550 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3551 &xpmDarkSquare, NULL, &attr)) != 0) {
3552 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3556 xpmJailSquare = xpmLightSquare;
3557 fprintf(stderr, _("Done.\n"));
3559 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3562 #endif /* HAVE_LIBXPM */
3565 /* No built-in bitmaps */
3570 u_int ss = squareSize;
3572 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3575 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3576 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3577 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3578 pieceBitmapNames[piece],
3579 ss, kind == SOLID ? 's' : 'o');
3580 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3581 if(piece <= (int)WhiteKing)
3582 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3586 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3590 /* With built-in bitmaps */
3593 BuiltInBits* bib = builtInBits;
3596 u_int ss = squareSize;
3598 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3601 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3603 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3604 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3605 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3606 pieceBitmapNames[piece],
3607 ss, kind == SOLID ? 's' : 'o');
3608 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3609 bib->bits[kind][piece], ss, ss);
3610 if(piece <= (int)WhiteKing)
3611 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];