2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
65 # if HAVE_SYS_SOCKET_H
66 # include <sys/socket.h>
67 # include <netinet/in.h>
69 # else /* not HAVE_SYS_SOCKET_H */
70 # if HAVE_LAN_SOCKET_H
71 # include <lan/socket.h>
73 # include <lan/netdb.h>
74 # else /* not HAVE_LAN_SOCKET_H */
75 # define OMIT_SOCKETS 1
76 # endif /* not HAVE_LAN_SOCKET_H */
77 # endif /* not HAVE_SYS_SOCKET_H */
78 #endif /* !OMIT_SOCKETS */
83 #else /* not STDC_HEADERS */
84 extern char *getenv();
87 # else /* not HAVE_STRING_H */
89 # endif /* not HAVE_STRING_H */
90 #endif /* not STDC_HEADERS */
93 # include <sys/fcntl.h>
94 #else /* not HAVE_SYS_FCNTL_H */
97 # endif /* HAVE_FCNTL_H */
98 #endif /* not HAVE_SYS_FCNTL_H */
100 #if HAVE_SYS_SYSTEMINFO_H
101 # include <sys/systeminfo.h>
102 #endif /* HAVE_SYS_SYSTEMINFO_H */
104 #if TIME_WITH_SYS_TIME
105 # include <sys/time.h>
109 # include <sys/time.h>
120 # include <sys/wait.h>
125 # define NAMLEN(dirent) strlen((dirent)->d_name)
126 # define HAVE_DIR_STRUCT
128 # define dirent direct
129 # define NAMLEN(dirent) (dirent)->d_namlen
131 # include <sys/ndir.h>
132 # define HAVE_DIR_STRUCT
135 # include <sys/dir.h>
136 # define HAVE_DIR_STRUCT
140 # define HAVE_DIR_STRUCT
144 #include <X11/Intrinsic.h>
145 #include <X11/StringDefs.h>
146 #include <X11/Shell.h>
147 #include <X11/cursorfont.h>
148 #include <X11/Xatom.h>
149 #include <X11/Xmu/Atoms.h>
151 #include <X11/Xaw3d/Dialog.h>
152 #include <X11/Xaw3d/Form.h>
153 #include <X11/Xaw3d/List.h>
154 #include <X11/Xaw3d/Label.h>
155 #include <X11/Xaw3d/SimpleMenu.h>
156 #include <X11/Xaw3d/SmeBSB.h>
157 #include <X11/Xaw3d/SmeLine.h>
158 #include <X11/Xaw3d/Box.h>
159 #include <X11/Xaw3d/MenuButton.h>
160 #include <X11/Xaw3d/Text.h>
161 #include <X11/Xaw3d/AsciiText.h>
163 #include <X11/Xaw/Dialog.h>
164 #include <X11/Xaw/Form.h>
165 #include <X11/Xaw/List.h>
166 #include <X11/Xaw/Label.h>
167 #include <X11/Xaw/SimpleMenu.h>
168 #include <X11/Xaw/SmeBSB.h>
169 #include <X11/Xaw/SmeLine.h>
170 #include <X11/Xaw/Box.h>
171 #include <X11/Xaw/MenuButton.h>
172 #include <X11/Xaw/Text.h>
173 #include <X11/Xaw/AsciiText.h>
176 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
181 #include "pixmaps/pixmaps.h"
182 #define IMAGE_EXT "xpm"
184 #define IMAGE_EXT "xim"
185 #include "bitmaps/bitmaps.h"
188 #include "bitmaps/icon_white.bm"
189 #include "bitmaps/icon_black.bm"
190 #include "bitmaps/checkmark.bm"
192 #include "frontend.h"
194 #include "backendz.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
203 // must be moved to xengineoutput.h
205 void EngineOutputProc P((Widget w, XEvent *event,
206 String *prms, Cardinal *nprms));
207 void EvalGraphProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
215 #define usleep(t) _sleep2(((t)+500)/1000)
219 # define _(s) gettext (s)
220 # define N_(s) gettext_noop (s)
238 int main P((int argc, char **argv));
239 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
240 char *init_path, char *mode, int (*show_entry)(), char **name_return));
241 RETSIGTYPE CmailSigHandler P((int sig));
242 RETSIGTYPE IntSigHandler P((int sig));
243 RETSIGTYPE TermSizeSigHandler P((int sig));
244 void CreateGCs P((void));
245 void CreateXIMPieces P((void));
246 void CreateXPMPieces P((void));
247 void CreateXPMBoard P((char *s, int n));
248 void CreatePieces P((void));
249 void CreatePieceMenus P((void));
250 Widget CreateMenuBar P((Menu *mb));
251 Widget CreateButtonBar P ((MenuItem *mi));
252 char *FindFont P((char *pattern, int targetPxlSize));
253 void PieceMenuPopup P((Widget w, XEvent *event,
254 String *params, Cardinal *num_params));
255 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
256 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
257 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
258 u_int wreq, u_int hreq));
259 void CreateGrid P((void));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
263 void HandleUserMove P((Widget w, XEvent *event,
264 String *prms, Cardinal *nprms));
265 void AnimateUserMove P((Widget w, XEvent * event,
266 String * params, Cardinal * nParams));
267 void HandlePV P((Widget w, XEvent * event,
268 String * params, Cardinal * nParams));
269 void SelectPV P((Widget w, XEvent * event,
270 String * params, Cardinal * nParams));
271 void StopPV P((Widget w, XEvent * event,
272 String * params, Cardinal * nParams));
273 void WhiteClock P((Widget w, XEvent *event,
274 String *prms, Cardinal *nprms));
275 void BlackClock P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void DrawPositionProc P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
281 void CommentClick P((Widget w, XEvent * event,
282 String * params, Cardinal * nParams));
283 void CommentPopUp P((char *title, char *label));
284 void CommentPopDown P((void));
285 void CommentCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void ICSInputBoxPopUp P((void));
288 void ICSInputBoxPopDown P((void));
289 void FileNamePopUp P((char *label, char *def,
290 FileProc proc, char *openMode));
291 void FileNamePopDown P((void));
292 void FileNameCallback P((Widget w, XtPointer client_data,
293 XtPointer call_data));
294 void FileNameAction P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void AskQuestionReplyAction P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void AskQuestionProc P((Widget w, XEvent *event,
299 String *prms, Cardinal *nprms));
300 void AskQuestionPopDown P((void));
301 void PromotionPopDown P((void));
302 void PromotionCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void EditCommentPopDown P((void));
305 void EditCommentCallback P((Widget w, XtPointer client_data,
306 XtPointer call_data));
307 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
308 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
312 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
314 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
316 void LoadPositionProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
320 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
322 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
324 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
326 void PastePositionProc P((Widget w, XEvent *event, String *prms,
328 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void SavePositionProc P((Widget w, XEvent *event,
332 String *prms, Cardinal *nprms));
333 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
336 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
340 void MachineWhiteProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void AnalyzeModeProc P((Widget w, XEvent *event,
343 String *prms, Cardinal *nprms));
344 void AnalyzeFileProc P((Widget w, XEvent *event,
345 String *prms, Cardinal *nprms));
346 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
348 void IcsClientProc P((Widget w, XEvent *event, String *prms,
350 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void EditPositionProc P((Widget w, XEvent *event,
352 String *prms, Cardinal *nprms));
353 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void EditCommentProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void IcsInputBoxProc P((Widget w, XEvent *event,
357 String *prms, Cardinal *nprms));
358 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void StopObservingProc P((Widget w, XEvent *event, String *prms,
374 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
376 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
385 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
387 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
390 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
392 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
394 void AutocommProc P((Widget w, XEvent *event, String *prms,
396 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void AutobsProc P((Widget w, XEvent *event, String *prms,
400 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
405 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
408 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
410 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
412 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
416 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
418 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
420 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
422 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
424 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
428 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
430 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
432 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
434 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void DisplayMove P((int moveNumber));
446 void DisplayTitle P((char *title));
447 void ICSInitScript P((void));
448 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
449 void ErrorPopUp P((char *title, char *text, int modal));
450 void ErrorPopDown P((void));
451 static char *ExpandPathName P((char *path));
452 static void CreateAnimVars P((void));
453 static void DragPieceMove P((int x, int y));
454 static void DrawDragPiece P((void));
455 char *ModeToWidgetName P((GameMode mode));
456 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void GameListOptionsPopDown P(());
465 void ShufflePopDown P(());
466 void EnginePopDown P(());
467 void UciPopDown P(());
468 void TimeControlPopDown P(());
469 void NewVariantPopDown P(());
470 void SettingsPopDown P(());
471 void update_ics_width P(());
472 int get_term_width P(());
473 int CopyMemoProc P(());
475 * XBoard depends on Xt R4 or higher
477 int xtVersion = XtSpecificationRelease;
482 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
483 jailSquareColor, highlightSquareColor, premoveHighlightColor;
484 Pixel lowTimeWarningColor;
485 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
486 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
487 wjPieceGC, bjPieceGC, prelineGC, countGC;
488 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
489 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
490 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
491 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
492 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
493 ICSInputShell, fileNameShell, askQuestionShell;
494 Widget historyShell, evalGraphShell, gameListShell;
495 int hOffset; // [HGM] dual
496 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
497 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
498 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
499 Font clockFontID, coordFontID, countFontID;
500 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
501 XtAppContext appContext;
503 char *oldICSInteractionTitle;
507 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
509 Position commentX = -1, commentY = -1;
510 Dimension commentW, commentH;
511 typedef unsigned int BoardSize;
513 Boolean chessProgram;
515 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
516 int squareSize, smallLayout = 0, tinyLayout = 0,
517 marginW, marginH, // [HGM] for run-time resizing
518 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
519 ICSInputBoxUp = False, askQuestionUp = False,
520 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
521 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
522 Pixel timerForegroundPixel, timerBackgroundPixel;
523 Pixel buttonForegroundPixel, buttonBackgroundPixel;
524 char *chessDir, *programName, *programVersion,
525 *gameCopyFilename, *gamePasteFilename;
526 Boolean alwaysOnTop = False;
527 Boolean saveSettingsOnExit;
528 char *settingsFileName;
529 char *icsTextMenuString;
531 char *firstChessProgramNames;
532 char *secondChessProgramNames;
534 WindowPlacement wpMain;
535 WindowPlacement wpConsole;
536 WindowPlacement wpComment;
537 WindowPlacement wpMoveHistory;
538 WindowPlacement wpEvalGraph;
539 WindowPlacement wpEngineOutput;
540 WindowPlacement wpGameList;
541 WindowPlacement wpTags;
545 Pixmap pieceBitmap[2][(int)BlackPawn];
546 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
547 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
548 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
549 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
550 Pixmap xpmBoardBitmap[2];
551 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
552 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
553 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
554 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
555 XImage *ximLightSquare, *ximDarkSquare;
558 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
559 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
561 #define White(piece) ((int)(piece) < (int)BlackPawn)
563 /* Variables for doing smooth animation. This whole thing
564 would be much easier if the board was double-buffered,
565 but that would require a fairly major rewrite. */
570 GC blitGC, pieceGC, outlineGC;
571 XPoint startSquare, prevFrame, mouseDelta;
575 int startBoardX, startBoardY;
578 /* There can be two pieces being animated at once: a player
579 can begin dragging a piece before the remote opponent has moved. */
581 static AnimState game, player;
583 /* Bitmaps for use as masks when drawing XPM pieces.
584 Need one for each black and white piece. */
585 static Pixmap xpmMask[BlackKing + 1];
587 /* This magic number is the number of intermediate frames used
588 in each half of the animation. For short moves it's reduced
589 by 1. The total number of frames will be factor * 2 + 1. */
592 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
594 MenuItem fileMenu[] = {
595 {"New Game", "New Game", ResetProc},
596 {"New Shuffle Game ...", "New Shuffle Game", ShuffleMenuProc},
597 {"New Variant ...", "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
598 {"----", NULL, NothingProc},
599 {"Load Game", "Load Game", LoadGameProc},
600 {"Load Position", "Load Position", LoadPositionProc},
601 // {"Load Next Game", "Load Next Game", LoadNextGameProc},
602 // {"Load Previous Game", "Load Previous Game", LoadPrevGameProc},
603 // {"Reload Same Game", "Reload Same Game", ReloadGameProc},
604 {"----", NULL, NothingProc},
605 // {"Load Next Position", "Load Next Position", LoadNextPositionProc},
606 // {"Load Previous Position", "Load Previous Position", LoadPrevPositionProc},
607 // {"Reload Same Position", "Reload Same Position", ReloadPositionProc},
608 {"Save Game", "Save Game", SaveGameProc},
609 {"Save Position", "Save Position", SavePositionProc},
610 {"----", NULL, NothingProc},
611 {"Mail Move", "Mail Move", MailMoveProc},
612 {"Reload CMail Message", "Reload CMail Message", ReloadCmailMsgProc},
613 {"----", NULL, NothingProc},
614 {"Exit", "Exit", QuitProc},
618 MenuItem editMenu[] = {
619 {"Copy Game", "Copy Game", CopyGameProc},
620 {"Copy Position", "Copy Position", CopyPositionProc},
621 {"----", NULL, NothingProc},
622 {"Paste Game", "Paste Game", PasteGameProc},
623 {"Paste Position", "Paste Position", PastePositionProc},
624 {"----", NULL, NothingProc},
625 {"Edit Game", "Edit Game", EditGameProc},
626 {"Edit Position", "Edit Position", EditPositionProc},
627 {"----", NULL, NothingProc},
628 {"Edit Tags", "Edit Tags", EditTagsProc},
629 {"Edit Comment", "Edit Comment", EditCommentProc},
630 {"----", NULL, NothingProc},
631 {"Revert", "Revert", RevertProc},
632 {"Annotate", "Annotate", AnnotateProc},
633 {"Truncate Game", "Truncate Game", TruncateGameProc},
634 {"----", NULL, NothingProc},
635 {"Backward", "Backward", BackwardProc},
636 {"Forward", "Forward", ForwardProc},
637 {"Back to Start", "Back to Start", ToStartProc},
638 {"Forward to End", "Forward to End", ToEndProc},
642 MenuItem viewMenu[] = {
643 {"Flip View", "Flip View", FlipViewProc},
644 {"----", NULL, NothingProc},
645 {"Show Engine Output", "Show Engine Output", EngineOutputProc},
646 {"Show Evaluation Graph", "Show Evaluation Graph", EvalGraphProc},
647 {"Show Game List", "Show Game List", ShowGameListProc},
648 {"Show Move History", "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
649 {"----", NULL, NothingProc},
650 {"Show Tags", "Show Tags", EditTagsProc},
651 {"Show Comments", "Show Comments", EditCommentProc},
652 {"ICS Input Box", "ICS Input Box", IcsInputBoxProc},
656 MenuItem modeMenu[] = {
657 {"Machine White", "Machine White", MachineWhiteProc},
658 {"Machine Black", "Machine Black", MachineBlackProc},
659 {"Two Machines", "Two Machines", TwoMachinesProc},
660 {"Analysis Mode", "Analysis Mode", AnalyzeModeProc},
661 {"Analyze File", "Analyze File", AnalyzeFileProc },
662 {"Edit Game", "Edit Game", EditGameProc},
663 {"Edit Position", "Edit Position", EditPositionProc},
664 {"Training", "Training", TrainingProc},
665 {"ICS Client", "ICS Client", IcsClientProc},
666 {"----", NULL, NothingProc},
667 {"Pause", "Pause", PauseProc},
671 MenuItem actionMenu[] = {
672 {"Accept", "Accept", AcceptProc},
673 {"Decline", "Decline", DeclineProc},
674 {"Rematch", "Rematch", RematchProc},
675 {"----", NULL, NothingProc},
676 {"Call Flag", "Call Flag", CallFlagProc},
677 {"Draw", "Draw", DrawProc},
678 {"Adjourn", "Adjourn", AdjournProc},
679 {"Abort", "Abort", AbortProc},
680 {"Resign", "Resign", ResignProc},
681 {"----", NULL, NothingProc},
682 {"Stop Observing", "Stop Observing", StopObservingProc},
683 {"Stop Examining", "Stop Examining", StopExaminingProc},
684 {"Upload to Examine", "Upload to Examine", UploadProc},
685 {"----", NULL, NothingProc},
686 {"Adjudicate to White", "Adjudicate to White", AdjuWhiteProc},
687 {"Adjudicate to Black", "Adjudicate to Black", AdjuBlackProc},
688 {"Adjudicate Draw", "Adjudicate Draw", AdjuDrawProc},
692 MenuItem engineMenu[] = {
693 {"Engine #1 Settings", "Engine #1 Settings", FirstSettingsProc},
694 {"Engine #2 Settings", "Engine #2 Settings", SecondSettingsProc},
695 {"----", NULL, NothingProc},
696 {"Move Now", "Move Now", MoveNowProc},
697 {"Retract Move", "Retract Move", RetractMoveProc},
701 MenuItem optionsMenu[] = {
702 {"Time Control ...", "Time Control ...", TimeControlProc},
703 {"Common Engine ...", "Common Engine ...", UciMenuProc},
704 {"Adjudications ...", "Adjudications ...", EngineMenuProc},
705 {"Game List ...", "Game List ...", GameListOptionsPopUp},
706 {"----", NULL, NothingProc},
707 {"Always Queen", "Always Queen", AlwaysQueenProc},
708 {"Animate Dragging", "Animate Dragging", AnimateDraggingProc},
709 {"Animate Moving", "Animate Moving", AnimateMovingProc},
710 {"Auto Comment", "Auto Comment", AutocommProc},
711 {"Auto Flag", "Auto Flag", AutoflagProc},
712 {"Auto Flip View", "Auto Flip View", AutoflipProc},
713 {"Auto Observe", "Auto Observe", AutobsProc},
714 {"Auto Raise Board", "Auto Raise Board", AutoraiseProc},
715 {"Auto Save", "Auto Save", AutosaveProc},
716 {"Blindfold", "Blindfold", BlindfoldProc},
717 {"Flash Moves", "Flash Moves", FlashMovesProc},
718 {"Get Move List", "Get Move List", GetMoveListProc},
720 {"Highlight Dragging", "Highlight Dragging", HighlightDraggingProc},
722 {"Highlight Last Move", "Highlight Last Move", HighlightLastMoveProc},
723 {"Move Sound", "Move Sound", MoveSoundProc},
724 {"ICS Alarm", "ICS Alarm", IcsAlarmProc},
725 {"Old Save Style", "Old Save Style", OldSaveStyleProc},
726 {"Periodic Updates", "Periodic Updates", PeriodicUpdatesProc},
727 {"Ponder Next Move", "Ponder Next Move", PonderNextMoveProc},
728 {"Popup Exit Message", "Popup Exit Message", PopupExitMessageProc},
729 {"Popup Move Errors", "Popup Move Errors", PopupMoveErrorsProc},
730 {"Premove", "Premove", PremoveProc},
731 {"Quiet Play", "Quiet Play", QuietPlayProc},
732 {"Show Coords", "Show Coords", ShowCoordsProc},
733 {"Hide Thinking", "Hide Thinking", HideThinkingProc},
734 {"Test Legality", "Test Legality", TestLegalityProc},
735 {"----", NULL, NothingProc},
736 {"Save Settings Now", "Save Settings Now", SaveSettingsProc},
737 {"Save Settings on Exit", "Save Settings on Exit", SaveOnExitProc},
741 MenuItem helpMenu[] = {
742 {"Info XBoard", "Info XBoard", InfoProc},
743 {"Man XBoard", "Man XBoard", ManProc},
744 {"----", NULL, NothingProc},
745 {"Hint", "Hint", HintProc},
746 {"Book", "Book", BookProc},
747 {"----", NULL, NothingProc},
748 {"About XBoard", "About XBoard", AboutProc},
753 {"File", "File", fileMenu},
754 {"Edit", "Edit", editMenu},
755 {"View", "View", viewMenu},
756 {"Mode", "Mode", modeMenu},
757 {"Action", "Action", actionMenu},
758 {"Engine", "Engine", engineMenu},
759 {"Options", "Options", optionsMenu},
760 {"Help", "Help", helpMenu},
764 #define PAUSE_BUTTON "P"
765 MenuItem buttonBar[] = {
766 {"<<", "<<", ToStartProc},
767 {"<", "<", BackwardProc},
768 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
769 {">", ">", ForwardProc},
770 {">>", ">>", ToEndProc},
774 #define PIECE_MENU_SIZE 18
775 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
776 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
777 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
778 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
779 N_("Empty square"), N_("Clear board") },
780 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
781 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
782 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
783 N_("Empty square"), N_("Clear board") }
785 /* must be in same order as PieceMenuStrings! */
786 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
787 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
788 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
789 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
790 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
791 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
792 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
793 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
794 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
797 #define DROP_MENU_SIZE 6
798 String dropMenuStrings[DROP_MENU_SIZE] = {
799 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
801 /* must be in same order as PieceMenuStrings! */
802 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
803 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
804 WhiteRook, WhiteQueen
812 DropMenuEnables dmEnables[] = {
830 { XtNborderWidth, 0 },
831 { XtNdefaultDistance, 0 },
835 { XtNborderWidth, 0 },
836 { XtNresizable, (XtArgVal) True },
840 { XtNborderWidth, 0 },
846 { XtNjustify, (XtArgVal) XtJustifyRight },
847 { XtNlabel, (XtArgVal) "..." },
848 { XtNresizable, (XtArgVal) True },
849 { XtNresize, (XtArgVal) False }
852 Arg messageArgs[] = {
853 { XtNjustify, (XtArgVal) XtJustifyLeft },
854 { XtNlabel, (XtArgVal) "..." },
855 { XtNresizable, (XtArgVal) True },
856 { XtNresize, (XtArgVal) False }
860 { XtNborderWidth, 0 },
861 { XtNjustify, (XtArgVal) XtJustifyLeft }
864 XtResource clientResources[] = {
865 { "flashCount", "flashCount", XtRInt, sizeof(int),
866 XtOffset(AppDataPtr, flashCount), XtRImmediate,
867 (XtPointer) FLASH_COUNT },
870 XrmOptionDescRec shellOptions[] = {
871 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
872 { "-flash", "flashCount", XrmoptionNoArg, "3" },
873 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
876 XtActionsRec boardActions[] = {
877 { "DrawPosition", DrawPositionProc },
878 { "HandleUserMove", HandleUserMove },
879 { "AnimateUserMove", AnimateUserMove },
880 { "HandlePV", HandlePV },
881 { "SelectPV", SelectPV },
882 { "StopPV", StopPV },
883 { "FileNameAction", FileNameAction },
884 { "AskQuestionProc", AskQuestionProc },
885 { "AskQuestionReplyAction", AskQuestionReplyAction },
886 { "PieceMenuPopup", PieceMenuPopup },
887 { "WhiteClock", WhiteClock },
888 { "BlackClock", BlackClock },
889 { "Iconify", Iconify },
890 { "ResetProc", ResetProc },
891 { "NewVariantProc", NewVariantProc },
892 { "LoadGameProc", LoadGameProc },
893 { "LoadNextGameProc", LoadNextGameProc },
894 { "LoadPrevGameProc", LoadPrevGameProc },
895 { "LoadSelectedProc", LoadSelectedProc },
896 { "SetFilterProc", SetFilterProc },
897 { "ReloadGameProc", ReloadGameProc },
898 { "LoadPositionProc", LoadPositionProc },
899 { "LoadNextPositionProc", LoadNextPositionProc },
900 { "LoadPrevPositionProc", LoadPrevPositionProc },
901 { "ReloadPositionProc", ReloadPositionProc },
902 { "CopyPositionProc", CopyPositionProc },
903 { "PastePositionProc", PastePositionProc },
904 { "CopyGameProc", CopyGameProc },
905 { "PasteGameProc", PasteGameProc },
906 { "SaveGameProc", SaveGameProc },
907 { "SavePositionProc", SavePositionProc },
908 { "MailMoveProc", MailMoveProc },
909 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
910 { "QuitProc", QuitProc },
911 { "MachineWhiteProc", MachineWhiteProc },
912 { "MachineBlackProc", MachineBlackProc },
913 { "AnalysisModeProc", AnalyzeModeProc },
914 { "AnalyzeFileProc", AnalyzeFileProc },
915 { "TwoMachinesProc", TwoMachinesProc },
916 { "IcsClientProc", IcsClientProc },
917 { "EditGameProc", EditGameProc },
918 { "EditPositionProc", EditPositionProc },
919 { "TrainingProc", EditPositionProc },
920 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
921 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
922 { "ShowGameListProc", ShowGameListProc },
923 { "ShowMoveListProc", HistoryShowProc},
924 { "EditTagsProc", EditCommentProc },
925 { "EditCommentProc", EditCommentProc },
926 { "IcsAlarmProc", IcsAlarmProc },
927 { "IcsInputBoxProc", IcsInputBoxProc },
928 { "PauseProc", PauseProc },
929 { "AcceptProc", AcceptProc },
930 { "DeclineProc", DeclineProc },
931 { "RematchProc", RematchProc },
932 { "CallFlagProc", CallFlagProc },
933 { "DrawProc", DrawProc },
934 { "AdjournProc", AdjournProc },
935 { "AbortProc", AbortProc },
936 { "ResignProc", ResignProc },
937 { "AdjuWhiteProc", AdjuWhiteProc },
938 { "AdjuBlackProc", AdjuBlackProc },
939 { "AdjuDrawProc", AdjuDrawProc },
940 { "EnterKeyProc", EnterKeyProc },
941 { "UpKeyProc", UpKeyProc },
942 { "DownKeyProc", DownKeyProc },
943 { "StopObservingProc", StopObservingProc },
944 { "StopExaminingProc", StopExaminingProc },
945 { "UploadProc", UploadProc },
946 { "BackwardProc", BackwardProc },
947 { "ForwardProc", ForwardProc },
948 { "ToStartProc", ToStartProc },
949 { "ToEndProc", ToEndProc },
950 { "RevertProc", RevertProc },
951 { "AnnotateProc", AnnotateProc },
952 { "TruncateGameProc", TruncateGameProc },
953 { "MoveNowProc", MoveNowProc },
954 { "RetractMoveProc", RetractMoveProc },
955 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
956 { "UciMenuProc", (XtActionProc) UciMenuProc },
957 { "TimeControlProc", (XtActionProc) TimeControlProc },
958 { "AlwaysQueenProc", AlwaysQueenProc },
959 { "AnimateDraggingProc", AnimateDraggingProc },
960 { "AnimateMovingProc", AnimateMovingProc },
961 { "AutoflagProc", AutoflagProc },
962 { "AutoflipProc", AutoflipProc },
963 { "AutobsProc", AutobsProc },
964 { "AutoraiseProc", AutoraiseProc },
965 { "AutosaveProc", AutosaveProc },
966 { "BlindfoldProc", BlindfoldProc },
967 { "FlashMovesProc", FlashMovesProc },
968 { "FlipViewProc", FlipViewProc },
969 { "GetMoveListProc", GetMoveListProc },
971 { "HighlightDraggingProc", HighlightDraggingProc },
973 { "HighlightLastMoveProc", HighlightLastMoveProc },
974 { "IcsAlarmProc", IcsAlarmProc },
975 { "MoveSoundProc", MoveSoundProc },
976 { "OldSaveStyleProc", OldSaveStyleProc },
977 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
978 { "PonderNextMoveProc", PonderNextMoveProc },
979 { "PopupExitMessageProc", PopupExitMessageProc },
980 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
981 { "PremoveProc", PremoveProc },
982 { "QuietPlayProc", QuietPlayProc },
983 { "ShowCoordsProc", ShowCoordsProc },
984 { "ShowThinkingProc", ShowThinkingProc },
985 { "HideThinkingProc", HideThinkingProc },
986 { "TestLegalityProc", TestLegalityProc },
987 { "SaveSettingsProc", SaveSettingsProc },
988 { "SaveOnExitProc", SaveOnExitProc },
989 { "InfoProc", InfoProc },
990 { "ManProc", ManProc },
991 { "HintProc", HintProc },
992 { "BookProc", BookProc },
993 { "AboutGameProc", AboutGameProc },
994 { "AboutProc", AboutProc },
995 { "DebugProc", DebugProc },
996 { "NothingProc", NothingProc },
997 { "CommentClick", (XtActionProc) CommentClick },
998 { "CommentPopDown", (XtActionProc) CommentPopDown },
999 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1000 { "TagsPopDown", (XtActionProc) TagsPopDown },
1001 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1002 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1003 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1004 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1005 { "GameListPopDown", (XtActionProc) GameListPopDown },
1006 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1007 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1008 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1009 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1010 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1011 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1012 { "EnginePopDown", (XtActionProc) EnginePopDown },
1013 { "UciPopDown", (XtActionProc) UciPopDown },
1014 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1015 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1016 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1017 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1020 char globalTranslations[] =
1021 ":<Key>F9: ResignProc() \n \
1022 :Ctrl<Key>n: ResetProc() \n \
1023 :Meta<Key>V: NewVariantProc() \n \
1024 :Ctrl<Key>o: LoadGameProc() \n \
1025 :Meta<Key>Next: LoadNextGameProc() \n \
1026 :Meta<Key>Prior: LoadPrevGameProc() \n \
1027 :Ctrl<Key>s: SaveGameProc() \n \
1028 :Ctrl<Key>c: CopyGameProc() \n \
1029 :Ctrl<Key>v: PasteGameProc() \n \
1030 :Ctrl<Key>O: LoadPositionProc() \n \
1031 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1032 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1033 :Ctrl<Key>S: SavePositionProc() \n \
1034 :Ctrl<Key>C: CopyPositionProc() \n \
1035 :Ctrl<Key>V: PastePositionProc() \n \
1036 :Ctrl<Key>q: QuitProc() \n \
1037 :Ctrl<Key>w: MachineWhiteProc() \n \
1038 :Ctrl<Key>b: MachineBlackProc() \n \
1039 :Ctrl<Key>t: TwoMachinesProc() \n \
1040 :Ctrl<Key>a: AnalysisModeProc() \n \
1041 :Ctrl<Key>f: AnalyzeFileProc() \n \
1042 :Ctrl<Key>e: EditGameProc() \n \
1043 :Ctrl<Key>E: EditPositionProc() \n \
1044 :Meta<Key>O: EngineOutputProc() \n \
1045 :Meta<Key>E: EvalGraphProc() \n \
1046 :Meta<Key>G: ShowGameListProc() \n \
1047 :Meta<Key>H: ShowMoveListProc() \n \
1048 :<Key>Pause: PauseProc() \n \
1049 :<Key>F3: AcceptProc() \n \
1050 :<Key>F4: DeclineProc() \n \
1051 :<Key>F12: RematchProc() \n \
1052 :<Key>F5: CallFlagProc() \n \
1053 :<Key>F6: DrawProc() \n \
1054 :<Key>F7: AdjournProc() \n \
1055 :<Key>F8: AbortProc() \n \
1056 :<Key>F10: StopObservingProc() \n \
1057 :<Key>F11: StopExaminingProc() \n \
1058 :Meta Ctrl<Key>F12: DebugProc() \n \
1059 :Meta<Key>End: ToEndProc() \n \
1060 :Meta<Key>Right: ForwardProc() \n \
1061 :Meta<Key>Home: ToStartProc() \n \
1062 :Meta<Key>Left: BackwardProc() \n \
1063 :Ctrl<Key>m: MoveNowProc() \n \
1064 :Ctrl<Key>x: RetractMoveProc() \n \
1065 :Meta<Key>J: EngineMenuProc() \n \
1066 :Meta<Key>U: UciMenuProc() \n \
1067 :Meta<Key>T: TimeControlProc() \n \
1068 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1069 :Ctrl<Key>F: AutoflagProc() \n \
1070 :Ctrl<Key>A: AnimateMovingProc() \n \
1071 :Ctrl<Key>P: PonderNextMoveProc() \n \
1072 :Ctrl<Key>L: TestLegalityProc() \n \
1073 :Ctrl<Key>H: HideThinkingProc() \n \
1074 :<Key>-: Iconify() \n \
1075 :<Key>F1: ManProc() \n \
1076 :<Key>F2: FlipViewProc() \n \
1077 <KeyDown>.: BackwardProc() \n \
1078 <KeyUp>.: ForwardProc() \n \
1079 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1080 \"Send to chess program:\",,1) \n \
1081 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1082 \"Send to second chess program:\",,2) \n";
1084 char boardTranslations[] =
1085 "<Btn1Down>: HandleUserMove(0) \n \
1086 Shift<Btn1Up>: HandleUserMove(1) \n \
1087 <Btn1Up>: HandleUserMove(0) \n \
1088 <Btn1Motion>: AnimateUserMove() \n \
1089 <Btn3Motion>: HandlePV() \n \
1090 <Btn3Up>: PieceMenuPopup(menuB) \n \
1091 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1092 PieceMenuPopup(menuB) \n \
1093 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1094 PieceMenuPopup(menuW) \n \
1095 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1096 PieceMenuPopup(menuW) \n \
1097 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1098 PieceMenuPopup(menuB) \n";
1100 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1101 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1103 char ICSInputTranslations[] =
1104 "<Key>Up: UpKeyProc() \n "
1105 "<Key>Down: DownKeyProc() \n "
1106 "<Key>Return: EnterKeyProc() \n";
1108 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1109 // as the widget is destroyed before the up-click can call extend-end
1110 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1112 String xboardResources[] = {
1113 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1114 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1115 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1120 /* Max possible square size */
1121 #define MAXSQSIZE 256
1123 static int xpm_avail[MAXSQSIZE];
1125 #ifdef HAVE_DIR_STRUCT
1127 /* Extract piece size from filename */
1129 xpm_getsize(name, len, ext)
1140 if ((p=strchr(name, '.')) == NULL ||
1141 StrCaseCmp(p+1, ext) != 0)
1147 while (*p && isdigit(*p))
1154 /* Setup xpm_avail */
1156 xpm_getavail(dirname, ext)
1164 for (i=0; i<MAXSQSIZE; ++i)
1167 if (appData.debugMode)
1168 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1170 dir = opendir(dirname);
1173 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1174 programName, dirname);
1178 while ((ent=readdir(dir)) != NULL) {
1179 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1180 if (i > 0 && i < MAXSQSIZE)
1190 xpm_print_avail(fp, ext)
1196 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1197 for (i=1; i<MAXSQSIZE; ++i) {
1203 /* Return XPM piecesize closest to size */
1205 xpm_closest_to(dirname, size, ext)
1211 int sm_diff = MAXSQSIZE;
1215 xpm_getavail(dirname, ext);
1217 if (appData.debugMode)
1218 xpm_print_avail(stderr, ext);
1220 for (i=1; i<MAXSQSIZE; ++i) {
1223 diff = (diff<0) ? -diff : diff;
1224 if (diff < sm_diff) {
1232 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1238 #else /* !HAVE_DIR_STRUCT */
1239 /* If we are on a system without a DIR struct, we can't
1240 read the directory, so we can't collect a list of
1241 filenames, etc., so we can't do any size-fitting. */
1243 xpm_closest_to(dirname, size, ext)
1248 fprintf(stderr, _("\
1249 Warning: No DIR structure found on this system --\n\
1250 Unable to autosize for XPM/XIM pieces.\n\
1251 Please report this error to frankm@hiwaay.net.\n\
1252 Include system type & operating system in message.\n"));
1255 #endif /* HAVE_DIR_STRUCT */
1257 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1258 "magenta", "cyan", "white" };
1262 TextColors textColors[(int)NColorClasses];
1264 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1266 parse_color(str, which)
1270 char *p, buf[100], *d;
1273 if (strlen(str) > 99) /* watch bounds on buf */
1278 for (i=0; i<which; ++i) {
1285 /* Could be looking at something like:
1287 .. in which case we want to stop on a comma also */
1288 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1292 return -1; /* Use default for empty field */
1295 if (which == 2 || isdigit(*p))
1298 while (*p && isalpha(*p))
1303 for (i=0; i<8; ++i) {
1304 if (!StrCaseCmp(buf, cnames[i]))
1305 return which? (i+40) : (i+30);
1307 if (!StrCaseCmp(buf, "default")) return -1;
1309 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1314 parse_cpair(cc, str)
1318 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1319 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1324 /* bg and attr are optional */
1325 textColors[(int)cc].bg = parse_color(str, 1);
1326 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1327 textColors[(int)cc].attr = 0;
1333 /* Arrange to catch delete-window events */
1334 Atom wm_delete_window;
1336 CatchDeleteWindow(Widget w, String procname)
1339 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1340 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1341 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1348 XtSetArg(args[0], XtNiconic, False);
1349 XtSetValues(shellWidget, args, 1);
1351 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1354 //---------------------------------------------------------------------------------------------------------
1355 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1358 #define CW_USEDEFAULT (1<<31)
1359 #define ICS_TEXT_MENU_SIZE 90
1360 #define DEBUG_FILE "xboard.debug"
1361 #define SetCurrentDirectory chdir
1362 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1366 // these two must some day move to frontend.h, when they are implemented
1367 Boolean GameListIsUp();
1369 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1372 // front-end part of option handling
1374 // [HGM] This platform-dependent table provides the location for storing the color info
1375 extern char *crWhite, * crBlack;
1379 &appData.whitePieceColor,
1380 &appData.blackPieceColor,
1381 &appData.lightSquareColor,
1382 &appData.darkSquareColor,
1383 &appData.highlightSquareColor,
1384 &appData.premoveHighlightColor,
1385 &appData.lowTimeWarningColor,
1396 // [HGM] font: keep a font for each square size, even non-stndard ones
1397 #define NUM_SIZES 18
1398 #define MAX_SIZE 130
1399 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1400 char *fontTable[NUM_FONTS][MAX_SIZE];
1403 ParseFont(char *name, int number)
1404 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1406 if(sscanf(name, "size%d:", &size)) {
1407 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1408 // defer processing it until we know if it matches our board size
1409 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1410 fontTable[number][size] = strdup(strchr(name, ':')+1);
1411 fontValid[number][size] = True;
1416 case 0: // CLOCK_FONT
1417 appData.clockFont = strdup(name);
1419 case 1: // MESSAGE_FONT
1420 appData.font = strdup(name);
1422 case 2: // COORD_FONT
1423 appData.coordFont = strdup(name);
1428 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1433 { // only 2 fonts currently
1434 appData.clockFont = CLOCK_FONT_NAME;
1435 appData.coordFont = COORD_FONT_NAME;
1436 appData.font = DEFAULT_FONT_NAME;
1441 { // no-op, until we identify the code for this already in XBoard and move it here
1445 ParseColor(int n, char *name)
1446 { // in XBoard, just copy the color-name string
1447 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1451 ParseTextAttribs(ColorClass cc, char *s)
1453 (&appData.colorShout)[cc] = strdup(s);
1457 ParseBoardSize(void *addr, char *name)
1459 appData.boardSize = strdup(name);
1464 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1468 SetCommPortDefaults()
1469 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1472 // [HGM] args: these three cases taken out to stay in front-end
1474 SaveFontArg(FILE *f, ArgDescriptor *ad)
1477 int i, n = (int)ad->argLoc;
1479 case 0: // CLOCK_FONT
1480 name = appData.clockFont;
1482 case 1: // MESSAGE_FONT
1483 name = appData.font;
1485 case 2: // COORD_FONT
1486 name = appData.coordFont;
1491 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1492 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1493 fontTable[n][squareSize] = strdup(name);
1494 fontValid[n][squareSize] = True;
1497 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1498 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1503 { // nothing to do, as the sounds are at all times represented by their text-string names already
1507 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1508 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1509 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1513 SaveColor(FILE *f, ArgDescriptor *ad)
1514 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1515 if(colorVariable[(int)ad->argLoc])
1516 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1520 SaveBoardSize(FILE *f, char *name, void *addr)
1521 { // wrapper to shield back-end from BoardSize & sizeInfo
1522 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1526 ParseCommPortSettings(char *s)
1527 { // no such option in XBoard (yet)
1530 extern Widget engineOutputShell;
1531 extern Widget tagsShell, editTagsShell;
1533 GetActualPlacement(Widget wg, WindowPlacement *wp)
1543 XtSetArg(args[i], XtNx, &x); i++;
1544 XtSetArg(args[i], XtNy, &y); i++;
1545 XtSetArg(args[i], XtNwidth, &w); i++;
1546 XtSetArg(args[i], XtNheight, &h); i++;
1547 XtGetValues(wg, args, i);
1556 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1557 // In XBoard this will have to wait until awareness of window parameters is implemented
1558 GetActualPlacement(shellWidget, &wpMain);
1559 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1560 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1561 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1562 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1563 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1564 else GetActualPlacement(editShell, &wpComment);
1565 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1566 else GetActualPlacement(editTagsShell, &wpTags);
1570 PrintCommPortSettings(FILE *f, char *name)
1571 { // This option does not exist in XBoard
1575 MySearchPath(char *installDir, char *name, char *fullname)
1576 { // just append installDir and name. Perhaps ExpandPath should be used here?
1577 name = ExpandPathName(name);
1578 if(name && name[0] == '/')
1579 safeStrCpy(fullname, name, MSG_SIZ );
1581 sprintf(fullname, "%s%c%s", installDir, '/', name);
1587 MyGetFullPathName(char *name, char *fullname)
1588 { // should use ExpandPath?
1589 name = ExpandPathName(name);
1590 safeStrCpy(fullname, name, MSG_SIZ );
1595 EnsureOnScreen(int *x, int *y, int minX, int minY)
1602 { // [HGM] args: allows testing if main window is realized from back-end
1603 return xBoardWindow != 0;
1607 PopUpStartupDialog()
1608 { // start menu not implemented in XBoard
1612 ConvertToLine(int argc, char **argv)
1614 static char line[128*1024], buf[1024];
1618 for(i=1; i<argc; i++)
1620 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1621 && argv[i][0] != '{' )
1622 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1624 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1625 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1628 line[strlen(line)-1] = NULLCHAR;
1632 //--------------------------------------------------------------------------------------------
1634 extern Boolean twoBoards, partnerUp;
1637 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1639 #define BoardSize int
1640 void InitDrawingSizes(BoardSize boardSize, int flags)
1641 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1642 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1644 XtGeometryResult gres;
1647 if(!formWidget) return;
1650 * Enable shell resizing.
1652 shellArgs[0].value = (XtArgVal) &w;
1653 shellArgs[1].value = (XtArgVal) &h;
1654 XtGetValues(shellWidget, shellArgs, 2);
1656 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1657 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1658 XtSetValues(shellWidget, &shellArgs[2], 4);
1660 XtSetArg(args[0], XtNdefaultDistance, &sep);
1661 XtGetValues(formWidget, args, 1);
1663 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1664 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1666 hOffset = boardWidth + 10;
1667 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1668 secondSegments[i] = gridSegments[i];
1669 secondSegments[i].x1 += hOffset;
1670 secondSegments[i].x2 += hOffset;
1673 XtSetArg(args[0], XtNwidth, boardWidth);
1674 XtSetArg(args[1], XtNheight, boardHeight);
1675 XtSetValues(boardWidget, args, 2);
1677 timerWidth = (boardWidth - sep) / 2;
1678 XtSetArg(args[0], XtNwidth, timerWidth);
1679 XtSetValues(whiteTimerWidget, args, 1);
1680 XtSetValues(blackTimerWidget, args, 1);
1682 XawFormDoLayout(formWidget, False);
1684 if (appData.titleInWindow) {
1686 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1687 XtSetArg(args[i], XtNheight, &h); i++;
1688 XtGetValues(titleWidget, args, i);
1690 w = boardWidth - 2*bor;
1692 XtSetArg(args[0], XtNwidth, &w);
1693 XtGetValues(menuBarWidget, args, 1);
1694 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1697 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1698 if (gres != XtGeometryYes && appData.debugMode) {
1700 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1701 programName, gres, w, h, wr, hr);
1705 XawFormDoLayout(formWidget, True);
1708 * Inhibit shell resizing.
1710 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1711 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1712 shellArgs[4].value = shellArgs[2].value = w;
1713 shellArgs[5].value = shellArgs[3].value = h;
1714 XtSetValues(shellWidget, &shellArgs[0], 6);
1716 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1719 for(i=0; i<4; i++) {
1721 for(p=0; p<=(int)WhiteKing; p++)
1722 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1723 if(gameInfo.variant == VariantShogi) {
1724 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1725 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1726 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1727 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1728 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1731 if(gameInfo.variant == VariantGothic) {
1732 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1735 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1736 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1737 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1740 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1741 for(p=0; p<=(int)WhiteKing; p++)
1742 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1743 if(gameInfo.variant == VariantShogi) {
1744 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1745 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1746 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1747 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1748 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1751 if(gameInfo.variant == VariantGothic) {
1752 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1755 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1756 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1757 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1762 for(i=0; i<2; i++) {
1764 for(p=0; p<=(int)WhiteKing; p++)
1765 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1766 if(gameInfo.variant == VariantShogi) {
1767 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1768 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1769 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1770 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1771 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1774 if(gameInfo.variant == VariantGothic) {
1775 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1778 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1779 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1780 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1795 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1796 XSetWindowAttributes window_attributes;
1798 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1799 XrmValue vFrom, vTo;
1800 XtGeometryResult gres;
1803 int forceMono = False;
1805 srandom(time(0)); // [HGM] book: make random truly random
1807 setbuf(stdout, NULL);
1808 setbuf(stderr, NULL);
1811 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1812 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1816 programName = strrchr(argv[0], '/');
1817 if (programName == NULL)
1818 programName = argv[0];
1823 XtSetLanguageProc(NULL, NULL, NULL);
1824 bindtextdomain(PACKAGE, LOCALEDIR);
1825 textdomain(PACKAGE);
1829 XtAppInitialize(&appContext, "XBoard", shellOptions,
1830 XtNumber(shellOptions),
1831 &argc, argv, xboardResources, NULL, 0);
1832 appData.boardSize = "";
1833 InitAppData(ConvertToLine(argc, argv));
1835 if (p == NULL) p = "/tmp";
1836 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1837 gameCopyFilename = (char*) malloc(i);
1838 gamePasteFilename = (char*) malloc(i);
1839 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1840 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1842 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1843 clientResources, XtNumber(clientResources),
1846 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1847 static char buf[MSG_SIZ];
1848 EscapeExpand(buf, appData.initString);
1849 appData.initString = strdup(buf);
1850 EscapeExpand(buf, appData.secondInitString);
1851 appData.secondInitString = strdup(buf);
1852 EscapeExpand(buf, appData.firstComputerString);
1853 appData.firstComputerString = strdup(buf);
1854 EscapeExpand(buf, appData.secondComputerString);
1855 appData.secondComputerString = strdup(buf);
1858 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1861 if (chdir(chessDir) != 0) {
1862 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1868 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1869 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1870 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1871 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1874 setbuf(debugFP, NULL);
1877 /* [HGM,HR] make sure board size is acceptable */
1878 if(appData.NrFiles > BOARD_FILES ||
1879 appData.NrRanks > BOARD_RANKS )
1880 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1883 /* This feature does not work; animation needs a rewrite */
1884 appData.highlightDragging = FALSE;
1888 xDisplay = XtDisplay(shellWidget);
1889 xScreen = DefaultScreen(xDisplay);
1890 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1892 gameInfo.variant = StringToVariant(appData.variant);
1893 InitPosition(FALSE);
1896 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1898 if (isdigit(appData.boardSize[0])) {
1899 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1900 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1901 &fontPxlSize, &smallLayout, &tinyLayout);
1903 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1904 programName, appData.boardSize);
1908 /* Find some defaults; use the nearest known size */
1909 SizeDefaults *szd, *nearest;
1910 int distance = 99999;
1911 nearest = szd = sizeDefaults;
1912 while (szd->name != NULL) {
1913 if (abs(szd->squareSize - squareSize) < distance) {
1915 distance = abs(szd->squareSize - squareSize);
1916 if (distance == 0) break;
1920 if (i < 2) lineGap = nearest->lineGap;
1921 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1922 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1923 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1924 if (i < 6) smallLayout = nearest->smallLayout;
1925 if (i < 7) tinyLayout = nearest->tinyLayout;
1928 SizeDefaults *szd = sizeDefaults;
1929 if (*appData.boardSize == NULLCHAR) {
1930 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1931 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1934 if (szd->name == NULL) szd--;
1935 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1937 while (szd->name != NULL &&
1938 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1939 if (szd->name == NULL) {
1940 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1941 programName, appData.boardSize);
1945 squareSize = szd->squareSize;
1946 lineGap = szd->lineGap;
1947 clockFontPxlSize = szd->clockFontPxlSize;
1948 coordFontPxlSize = szd->coordFontPxlSize;
1949 fontPxlSize = szd->fontPxlSize;
1950 smallLayout = szd->smallLayout;
1951 tinyLayout = szd->tinyLayout;
1952 // [HGM] font: use defaults from settings file if available and not overruled
1954 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1955 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1956 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1957 appData.font = fontTable[MESSAGE_FONT][squareSize];
1958 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1959 appData.coordFont = fontTable[COORD_FONT][squareSize];
1961 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1962 if (strlen(appData.pixmapDirectory) > 0) {
1963 p = ExpandPathName(appData.pixmapDirectory);
1965 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1966 appData.pixmapDirectory);
1969 if (appData.debugMode) {
1970 fprintf(stderr, _("\
1971 XBoard square size (hint): %d\n\
1972 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1974 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1975 if (appData.debugMode) {
1976 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1979 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1981 /* [HR] height treated separately (hacked) */
1982 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1983 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1984 if (appData.showJail == 1) {
1985 /* Jail on top and bottom */
1986 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1987 XtSetArg(boardArgs[2], XtNheight,
1988 boardHeight + 2*(lineGap + squareSize));
1989 } else if (appData.showJail == 2) {
1991 XtSetArg(boardArgs[1], XtNwidth,
1992 boardWidth + 2*(lineGap + squareSize));
1993 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1996 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1997 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2001 * Determine what fonts to use.
2003 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2004 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2005 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2006 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2007 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2008 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2009 appData.font = FindFont(appData.font, fontPxlSize);
2010 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2011 countFontStruct = XQueryFont(xDisplay, countFontID);
2012 // appData.font = FindFont(appData.font, fontPxlSize);
2014 xdb = XtDatabase(xDisplay);
2015 XrmPutStringResource(&xdb, "*font", appData.font);
2018 * Detect if there are not enough colors available and adapt.
2020 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2021 appData.monoMode = True;
2024 if (!appData.monoMode) {
2025 vFrom.addr = (caddr_t) appData.lightSquareColor;
2026 vFrom.size = strlen(appData.lightSquareColor);
2027 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2028 if (vTo.addr == NULL) {
2029 appData.monoMode = True;
2032 lightSquareColor = *(Pixel *) vTo.addr;
2035 if (!appData.monoMode) {
2036 vFrom.addr = (caddr_t) appData.darkSquareColor;
2037 vFrom.size = strlen(appData.darkSquareColor);
2038 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2039 if (vTo.addr == NULL) {
2040 appData.monoMode = True;
2043 darkSquareColor = *(Pixel *) vTo.addr;
2046 if (!appData.monoMode) {
2047 vFrom.addr = (caddr_t) appData.whitePieceColor;
2048 vFrom.size = strlen(appData.whitePieceColor);
2049 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2050 if (vTo.addr == NULL) {
2051 appData.monoMode = True;
2054 whitePieceColor = *(Pixel *) vTo.addr;
2057 if (!appData.monoMode) {
2058 vFrom.addr = (caddr_t) appData.blackPieceColor;
2059 vFrom.size = strlen(appData.blackPieceColor);
2060 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2061 if (vTo.addr == NULL) {
2062 appData.monoMode = True;
2065 blackPieceColor = *(Pixel *) vTo.addr;
2069 if (!appData.monoMode) {
2070 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2071 vFrom.size = strlen(appData.highlightSquareColor);
2072 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2073 if (vTo.addr == NULL) {
2074 appData.monoMode = True;
2077 highlightSquareColor = *(Pixel *) vTo.addr;
2081 if (!appData.monoMode) {
2082 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2083 vFrom.size = strlen(appData.premoveHighlightColor);
2084 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2085 if (vTo.addr == NULL) {
2086 appData.monoMode = True;
2089 premoveHighlightColor = *(Pixel *) vTo.addr;
2094 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2097 if (appData.bitmapDirectory == NULL ||
2098 appData.bitmapDirectory[0] == NULLCHAR)
2099 appData.bitmapDirectory = DEF_BITMAP_DIR;
2102 if (appData.lowTimeWarning && !appData.monoMode) {
2103 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2104 vFrom.size = strlen(appData.lowTimeWarningColor);
2105 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2106 if (vTo.addr == NULL)
2107 appData.monoMode = True;
2109 lowTimeWarningColor = *(Pixel *) vTo.addr;
2112 if (appData.monoMode && appData.debugMode) {
2113 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2114 (unsigned long) XWhitePixel(xDisplay, xScreen),
2115 (unsigned long) XBlackPixel(xDisplay, xScreen));
2118 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2119 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2120 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2121 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2122 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2123 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2124 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2125 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2126 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2127 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2129 if (appData.colorize) {
2131 _("%s: can't parse color names; disabling colorization\n"),
2134 appData.colorize = FALSE;
2136 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2137 textColors[ColorNone].attr = 0;
2139 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2145 layoutName = "tinyLayout";
2146 } else if (smallLayout) {
2147 layoutName = "smallLayout";
2149 layoutName = "normalLayout";
2151 /* Outer layoutWidget is there only to provide a name for use in
2152 resources that depend on the layout style */
2154 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2155 layoutArgs, XtNumber(layoutArgs));
2157 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2158 formArgs, XtNumber(formArgs));
2159 XtSetArg(args[0], XtNdefaultDistance, &sep);
2160 XtGetValues(formWidget, args, 1);
2163 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2164 XtSetArg(args[0], XtNtop, XtChainTop);
2165 XtSetArg(args[1], XtNbottom, XtChainTop);
2166 XtSetArg(args[2], XtNright, XtChainLeft);
2167 XtSetValues(menuBarWidget, args, 3);
2169 widgetList[j++] = whiteTimerWidget =
2170 XtCreateWidget("whiteTime", labelWidgetClass,
2171 formWidget, timerArgs, XtNumber(timerArgs));
2172 XtSetArg(args[0], XtNfont, clockFontStruct);
2173 XtSetArg(args[1], XtNtop, XtChainTop);
2174 XtSetArg(args[2], XtNbottom, XtChainTop);
2175 XtSetValues(whiteTimerWidget, args, 3);
2177 widgetList[j++] = blackTimerWidget =
2178 XtCreateWidget("blackTime", labelWidgetClass,
2179 formWidget, timerArgs, XtNumber(timerArgs));
2180 XtSetArg(args[0], XtNfont, clockFontStruct);
2181 XtSetArg(args[1], XtNtop, XtChainTop);
2182 XtSetArg(args[2], XtNbottom, XtChainTop);
2183 XtSetValues(blackTimerWidget, args, 3);
2185 if (appData.titleInWindow) {
2186 widgetList[j++] = titleWidget =
2187 XtCreateWidget("title", labelWidgetClass, formWidget,
2188 titleArgs, XtNumber(titleArgs));
2189 XtSetArg(args[0], XtNtop, XtChainTop);
2190 XtSetArg(args[1], XtNbottom, XtChainTop);
2191 XtSetValues(titleWidget, args, 2);
2194 if (appData.showButtonBar) {
2195 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2196 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2197 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2198 XtSetArg(args[2], XtNtop, XtChainTop);
2199 XtSetArg(args[3], XtNbottom, XtChainTop);
2200 XtSetValues(buttonBarWidget, args, 4);
2203 widgetList[j++] = messageWidget =
2204 XtCreateWidget("message", labelWidgetClass, formWidget,
2205 messageArgs, XtNumber(messageArgs));
2206 XtSetArg(args[0], XtNtop, XtChainTop);
2207 XtSetArg(args[1], XtNbottom, XtChainTop);
2208 XtSetValues(messageWidget, args, 2);
2210 widgetList[j++] = boardWidget =
2211 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2212 XtNumber(boardArgs));
2214 XtManageChildren(widgetList, j);
2216 timerWidth = (boardWidth - sep) / 2;
2217 XtSetArg(args[0], XtNwidth, timerWidth);
2218 XtSetValues(whiteTimerWidget, args, 1);
2219 XtSetValues(blackTimerWidget, args, 1);
2221 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2222 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2223 XtGetValues(whiteTimerWidget, args, 2);
2225 if (appData.showButtonBar) {
2226 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2227 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2228 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2232 * formWidget uses these constraints but they are stored
2236 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2237 XtSetValues(menuBarWidget, args, i);
2238 if (appData.titleInWindow) {
2241 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2242 XtSetValues(whiteTimerWidget, args, i);
2244 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2245 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2246 XtSetValues(blackTimerWidget, args, i);
2248 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2249 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2250 XtSetValues(titleWidget, args, i);
2252 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2253 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2254 XtSetValues(messageWidget, args, i);
2255 if (appData.showButtonBar) {
2257 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2258 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2259 XtSetValues(buttonBarWidget, args, i);
2263 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2264 XtSetValues(whiteTimerWidget, args, i);
2266 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2267 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2268 XtSetValues(blackTimerWidget, args, i);
2270 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2271 XtSetValues(titleWidget, args, i);
2273 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2274 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2275 XtSetValues(messageWidget, args, i);
2276 if (appData.showButtonBar) {
2278 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2279 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2280 XtSetValues(buttonBarWidget, args, i);
2285 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2286 XtSetValues(whiteTimerWidget, args, i);
2288 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2289 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2290 XtSetValues(blackTimerWidget, args, i);
2292 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2293 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2294 XtSetValues(messageWidget, args, i);
2295 if (appData.showButtonBar) {
2297 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2298 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2299 XtSetValues(buttonBarWidget, args, i);
2303 XtSetArg(args[0], XtNfromVert, messageWidget);
2304 XtSetArg(args[1], XtNtop, XtChainTop);
2305 XtSetArg(args[2], XtNbottom, XtChainBottom);
2306 XtSetArg(args[3], XtNleft, XtChainLeft);
2307 XtSetArg(args[4], XtNright, XtChainRight);
2308 XtSetValues(boardWidget, args, 5);
2310 XtRealizeWidget(shellWidget);
2313 XtSetArg(args[0], XtNx, wpMain.x);
2314 XtSetArg(args[1], XtNy, wpMain.y);
2315 XtSetValues(shellWidget, args, 2);
2319 * Correct the width of the message and title widgets.
2320 * It is not known why some systems need the extra fudge term.
2321 * The value "2" is probably larger than needed.
2323 XawFormDoLayout(formWidget, False);
2325 #define WIDTH_FUDGE 2
2327 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2328 XtSetArg(args[i], XtNheight, &h); i++;
2329 XtGetValues(messageWidget, args, i);
2330 if (appData.showButtonBar) {
2332 XtSetArg(args[i], XtNwidth, &w); i++;
2333 XtGetValues(buttonBarWidget, args, i);
2334 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2336 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2339 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2340 if (gres != XtGeometryYes && appData.debugMode) {
2341 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2342 programName, gres, w, h, wr, hr);
2345 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2346 /* The size used for the child widget in layout lags one resize behind
2347 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2349 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2350 if (gres != XtGeometryYes && appData.debugMode) {
2351 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2352 programName, gres, w, h, wr, hr);
2355 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2356 XtSetArg(args[1], XtNright, XtChainRight);
2357 XtSetValues(messageWidget, args, 2);
2359 if (appData.titleInWindow) {
2361 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2362 XtSetArg(args[i], XtNheight, &h); i++;
2363 XtGetValues(titleWidget, args, i);
2365 w = boardWidth - 2*bor;
2367 XtSetArg(args[0], XtNwidth, &w);
2368 XtGetValues(menuBarWidget, args, 1);
2369 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2372 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2373 if (gres != XtGeometryYes && appData.debugMode) {
2375 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2376 programName, gres, w, h, wr, hr);
2379 XawFormDoLayout(formWidget, True);
2381 xBoardWindow = XtWindow(boardWidget);
2383 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2384 // not need to go into InitDrawingSizes().
2388 * Create X checkmark bitmap and initialize option menu checks.
2390 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2391 checkmark_bits, checkmark_width, checkmark_height);
2392 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2393 if (appData.alwaysPromoteToQueen) {
2394 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2397 if (appData.animateDragging) {
2398 XtSetValues(XtNameToWidget(menuBarWidget,
2399 "menuOptions.Animate Dragging"),
2402 if (appData.animate) {
2403 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2406 if (appData.autoComment) {
2407 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2410 if (appData.autoCallFlag) {
2411 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2414 if (appData.autoFlipView) {
2415 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2418 if (appData.autoObserve) {
2419 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2422 if (appData.autoRaiseBoard) {
2423 XtSetValues(XtNameToWidget(menuBarWidget,
2424 "menuOptions.Auto Raise Board"), args, 1);
2426 if (appData.autoSaveGames) {
2427 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2430 if (appData.saveGameFile[0] != NULLCHAR) {
2431 /* Can't turn this off from menu */
2432 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2434 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2438 if (appData.blindfold) {
2439 XtSetValues(XtNameToWidget(menuBarWidget,
2440 "menuOptions.Blindfold"), args, 1);
2442 if (appData.flashCount > 0) {
2443 XtSetValues(XtNameToWidget(menuBarWidget,
2444 "menuOptions.Flash Moves"),
2447 if (appData.getMoveList) {
2448 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2452 if (appData.highlightDragging) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,
2454 "menuOptions.Highlight Dragging"),
2458 if (appData.highlightLastMove) {
2459 XtSetValues(XtNameToWidget(menuBarWidget,
2460 "menuOptions.Highlight Last Move"),
2463 if (appData.icsAlarm) {
2464 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2467 if (appData.ringBellAfterMoves) {
2468 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2471 if (appData.oldSaveStyle) {
2472 XtSetValues(XtNameToWidget(menuBarWidget,
2473 "menuOptions.Old Save Style"), args, 1);
2475 if (appData.periodicUpdates) {
2476 XtSetValues(XtNameToWidget(menuBarWidget,
2477 "menuOptions.Periodic Updates"), args, 1);
2479 if (appData.ponderNextMove) {
2480 XtSetValues(XtNameToWidget(menuBarWidget,
2481 "menuOptions.Ponder Next Move"), args, 1);
2483 if (appData.popupExitMessage) {
2484 XtSetValues(XtNameToWidget(menuBarWidget,
2485 "menuOptions.Popup Exit Message"), args, 1);
2487 if (appData.popupMoveErrors) {
2488 XtSetValues(XtNameToWidget(menuBarWidget,
2489 "menuOptions.Popup Move Errors"), args, 1);
2491 if (appData.premove) {
2492 XtSetValues(XtNameToWidget(menuBarWidget,
2493 "menuOptions.Premove"), args, 1);
2495 if (appData.quietPlay) {
2496 XtSetValues(XtNameToWidget(menuBarWidget,
2497 "menuOptions.Quiet Play"), args, 1);
2499 if (appData.showCoords) {
2500 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2503 if (appData.hideThinkingFromHuman) {
2504 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2507 if (appData.testLegality) {
2508 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2511 if (saveSettingsOnExit) {
2512 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2519 ReadBitmap(&wIconPixmap, "icon_white.bm",
2520 icon_white_bits, icon_white_width, icon_white_height);
2521 ReadBitmap(&bIconPixmap, "icon_black.bm",
2522 icon_black_bits, icon_black_width, icon_black_height);
2523 iconPixmap = wIconPixmap;
2525 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2526 XtSetValues(shellWidget, args, i);
2529 * Create a cursor for the board widget.
2531 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2532 XChangeWindowAttributes(xDisplay, xBoardWindow,
2533 CWCursor, &window_attributes);
2536 * Inhibit shell resizing.
2538 shellArgs[0].value = (XtArgVal) &w;
2539 shellArgs[1].value = (XtArgVal) &h;
2540 XtGetValues(shellWidget, shellArgs, 2);
2541 shellArgs[4].value = shellArgs[2].value = w;
2542 shellArgs[5].value = shellArgs[3].value = h;
2543 XtSetValues(shellWidget, &shellArgs[2], 4);
2544 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2545 marginH = h - boardHeight;
2547 CatchDeleteWindow(shellWidget, "QuitProc");
2552 if (appData.bitmapDirectory[0] != NULLCHAR) {
2556 CreateXPMBoard(appData.liteBackTextureFile, 1);
2557 CreateXPMBoard(appData.darkBackTextureFile, 0);
2561 /* Create regular pieces */
2562 if (!useImages) CreatePieces();
2567 if (appData.animate || appData.animateDragging)
2570 XtAugmentTranslations(formWidget,
2571 XtParseTranslationTable(globalTranslations));
2572 XtAugmentTranslations(boardWidget,
2573 XtParseTranslationTable(boardTranslations));
2574 XtAugmentTranslations(whiteTimerWidget,
2575 XtParseTranslationTable(whiteTranslations));
2576 XtAugmentTranslations(blackTimerWidget,
2577 XtParseTranslationTable(blackTranslations));
2579 /* Why is the following needed on some versions of X instead
2580 * of a translation? */
2581 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2582 (XtEventHandler) EventProc, NULL);
2585 /* [AS] Restore layout */
2586 if( wpMoveHistory.visible ) {
2590 if( wpEvalGraph.visible )
2595 if( wpEngineOutput.visible ) {
2596 EngineOutputPopUp();
2601 if (errorExitStatus == -1) {
2602 if (appData.icsActive) {
2603 /* We now wait until we see "login:" from the ICS before
2604 sending the logon script (problems with timestamp otherwise) */
2605 /*ICSInitScript();*/
2606 if (appData.icsInputBox) ICSInputBoxPopUp();
2610 signal(SIGWINCH, TermSizeSigHandler);
2612 signal(SIGINT, IntSigHandler);
2613 signal(SIGTERM, IntSigHandler);
2614 if (*appData.cmailGameName != NULLCHAR) {
2615 signal(SIGUSR1, CmailSigHandler);
2618 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2620 XtSetKeyboardFocus(shellWidget, formWidget);
2622 XtAppMainLoop(appContext);
2623 if (appData.debugMode) fclose(debugFP); // [DM] debug
2630 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2631 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2633 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2634 unlink(gameCopyFilename);
2635 unlink(gamePasteFilename);
2638 RETSIGTYPE TermSizeSigHandler(int sig)
2651 CmailSigHandler(sig)
2657 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2659 /* Activate call-back function CmailSigHandlerCallBack() */
2660 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2662 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2666 CmailSigHandlerCallBack(isr, closure, message, count, error)
2674 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2676 /**** end signal code ****/
2682 /* try to open the icsLogon script, either in the location given
2683 * or in the users HOME directory
2690 f = fopen(appData.icsLogon, "r");
2693 homedir = getenv("HOME");
2694 if (homedir != NULL)
2696 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2697 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2698 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2699 f = fopen(buf, "r");
2704 ProcessICSInitScript(f);
2706 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2715 EditCommentPopDown();
2730 if (!menuBarWidget) return;
2731 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2733 DisplayError("menuEdit.Revert", 0);
2735 XtSetSensitive(w, !grey);
2737 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2739 DisplayError("menuEdit.Annotate", 0);
2741 XtSetSensitive(w, !grey);
2746 SetMenuEnables(enab)
2750 if (!menuBarWidget) return;
2751 while (enab->name != NULL) {
2752 w = XtNameToWidget(menuBarWidget, enab->name);
2754 DisplayError(enab->name, 0);
2756 XtSetSensitive(w, enab->value);
2762 Enables icsEnables[] = {
2763 { "menuFile.Mail Move", False },
2764 { "menuFile.Reload CMail Message", False },
2765 { "menuMode.Machine Black", False },
2766 { "menuMode.Machine White", False },
2767 { "menuMode.Analysis Mode", False },
2768 { "menuMode.Analyze File", False },
2769 { "menuMode.Two Machines", False },
2771 { "menuHelp.Hint", False },
2772 { "menuHelp.Book", False },
2773 { "menuEngine.Move Now", False },
2774 { "menuOptions.Periodic Updates", False },
2775 { "menuOptions.Hide Thinking", False },
2776 { "menuOptions.Ponder Next Move", False },
2777 { "menuEngine.Engine #1 Settings", False },
2779 { "menuEngine.Engine #2 Settings", False },
2780 { "menuEdit.Annotate", False },
2784 Enables ncpEnables[] = {
2785 { "menuFile.Mail Move", False },
2786 { "menuFile.Reload CMail Message", False },
2787 { "menuMode.Machine White", False },
2788 { "menuMode.Machine Black", False },
2789 { "menuMode.Analysis Mode", False },
2790 { "menuMode.Analyze File", False },
2791 { "menuMode.Two Machines", False },
2792 { "menuMode.ICS Client", False },
2793 { "menuView.ICS Input Box", False },
2794 { "Action", False },
2795 { "menuEdit.Revert", False },
2796 { "menuEdit.Annotate", False },
2797 { "menuEngine.Engine #1 Settings", False },
2798 { "menuEngine.Engine #2 Settings", False },
2799 { "menuEngine.Move Now", False },
2800 { "menuEngine.Retract Move", False },
2801 { "menuOptions.Auto Comment", False },
2802 { "menuOptions.Auto Flag", False },
2803 { "menuOptions.Auto Flip View", False },
2804 { "menuOptions.Auto Observe", False },
2805 { "menuOptions.Auto Raise Board", False },
2806 { "menuOptions.Get Move List", False },
2807 { "menuOptions.ICS Alarm", False },
2808 { "menuOptions.Move Sound", False },
2809 { "menuOptions.Quiet Play", False },
2810 { "menuOptions.Hide Thinking", False },
2811 { "menuOptions.Periodic Updates", False },
2812 { "menuOptions.Ponder Next Move", False },
2813 { "menuHelp.Hint", False },
2814 { "menuHelp.Book", False },
2818 Enables gnuEnables[] = {
2819 { "menuMode.ICS Client", False },
2820 { "menuView.ICS Input Box", False },
2821 { "menuAction.Accept", False },
2822 { "menuAction.Decline", False },
2823 { "menuAction.Rematch", False },
2824 { "menuAction.Adjourn", False },
2825 { "menuAction.Stop Examining", False },
2826 { "menuAction.Stop Observing", False },
2827 { "menuAction.Upload to Examine", False },
2828 { "menuEdit.Revert", False },
2829 { "menuEdit.Annotate", False },
2830 { "menuOptions.Auto Comment", False },
2831 { "menuOptions.Auto Observe", False },
2832 { "menuOptions.Auto Raise Board", False },
2833 { "menuOptions.Get Move List", False },
2834 { "menuOptions.Premove", False },
2835 { "menuOptions.Quiet Play", False },
2837 /* The next two options rely on SetCmailMode being called *after* */
2838 /* SetGNUMode so that when GNU is being used to give hints these */
2839 /* menu options are still available */
2841 { "menuFile.Mail Move", False },
2842 { "menuFile.Reload CMail Message", False },
2846 Enables cmailEnables[] = {
2848 { "menuAction.Call Flag", False },
2849 { "menuAction.Draw", True },
2850 { "menuAction.Adjourn", False },
2851 { "menuAction.Abort", False },
2852 { "menuAction.Stop Observing", False },
2853 { "menuAction.Stop Examining", False },
2854 { "menuFile.Mail Move", True },
2855 { "menuFile.Reload CMail Message", True },
2859 Enables trainingOnEnables[] = {
2860 { "menuMode.Edit Comment", False },
2861 { "menuMode.Pause", False },
2862 { "menuEdit.Forward", False },
2863 { "menuEdit.Backward", False },
2864 { "menuEdit.Forward to End", False },
2865 { "menuEdit.Back to Start", False },
2866 { "menuEngine.Move Now", False },
2867 { "menuEdit.Truncate Game", False },
2871 Enables trainingOffEnables[] = {
2872 { "menuMode.Edit Comment", True },
2873 { "menuMode.Pause", True },
2874 { "menuEdit.Forward", True },
2875 { "menuEdit.Backward", True },
2876 { "menuEdit.Forward to End", True },
2877 { "menuEdit.Back to Start", True },
2878 { "menuEngine.Move Now", True },
2879 { "menuEdit.Truncate Game", True },
2883 Enables machineThinkingEnables[] = {
2884 { "menuFile.Load Game", False },
2885 // { "menuFile.Load Next Game", False },
2886 // { "menuFile.Load Previous Game", False },
2887 // { "menuFile.Reload Same Game", False },
2888 { "menuEdit.Paste Game", False },
2889 { "menuFile.Load Position", False },
2890 // { "menuFile.Load Next Position", False },
2891 // { "menuFile.Load Previous Position", False },
2892 // { "menuFile.Reload Same Position", False },
2893 { "menuEdit.Paste Position", False },
2894 { "menuMode.Machine White", False },
2895 { "menuMode.Machine Black", False },
2896 { "menuMode.Two Machines", False },
2897 { "menuEngine.Retract Move", False },
2901 Enables userThinkingEnables[] = {
2902 { "menuFile.Load Game", True },
2903 // { "menuFile.Load Next Game", True },
2904 // { "menuFile.Load Previous Game", True },
2905 // { "menuFile.Reload Same Game", True },
2906 { "menuEdit.Paste Game", True },
2907 { "menuFile.Load Position", True },
2908 // { "menuFile.Load Next Position", True },
2909 // { "menuFile.Load Previous Position", True },
2910 // { "menuFile.Reload Same Position", True },
2911 { "menuEdit.Paste Position", True },
2912 { "menuMode.Machine White", True },
2913 { "menuMode.Machine Black", True },
2914 { "menuMode.Two Machines", True },
2915 { "menuEngine.Retract Move", True },
2921 SetMenuEnables(icsEnables);
2924 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2925 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2932 SetMenuEnables(ncpEnables);
2938 SetMenuEnables(gnuEnables);
2944 SetMenuEnables(cmailEnables);
2950 SetMenuEnables(trainingOnEnables);
2951 if (appData.showButtonBar) {
2952 XtSetSensitive(buttonBarWidget, False);
2958 SetTrainingModeOff()
2960 SetMenuEnables(trainingOffEnables);
2961 if (appData.showButtonBar) {
2962 XtSetSensitive(buttonBarWidget, True);
2967 SetUserThinkingEnables()
2969 if (appData.noChessProgram) return;
2970 SetMenuEnables(userThinkingEnables);
2974 SetMachineThinkingEnables()
2976 if (appData.noChessProgram) return;
2977 SetMenuEnables(machineThinkingEnables);
2979 case MachinePlaysBlack:
2980 case MachinePlaysWhite:
2981 case TwoMachinesPlay:
2982 XtSetSensitive(XtNameToWidget(menuBarWidget,
2983 ModeToWidgetName(gameMode)), True);
2990 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2991 #define HISTORY_SIZE 64
\r
2992 static char *history[HISTORY_SIZE];
\r
2993 int histIn = 0, histP = 0;
\r
2996 SaveInHistory(char *cmd)
\r
2998 if (history[histIn] != NULL) {
\r
2999 free(history[histIn]);
\r
3000 history[histIn] = NULL;
\r
3002 if (*cmd == NULLCHAR) return;
\r
3003 history[histIn] = StrSave(cmd);
\r
3004 histIn = (histIn + 1) % HISTORY_SIZE;
\r
3005 if (history[histIn] != NULL) {
\r
3006 free(history[histIn]);
\r
3007 history[histIn] = NULL;
\r
3013 PrevInHistory(char *cmd)
\r
3016 if (histP == histIn) {
\r
3017 if (history[histIn] != NULL) free(history[histIn]);
\r
3018 history[histIn] = StrSave(cmd);
\r
3020 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
3021 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
3023 return history[histP];
\r
3029 if (histP == histIn) return NULL;
\r
3030 histP = (histP + 1) % HISTORY_SIZE;
\r
3031 return history[histP];
\r
3033 // end of borrowed code
\r
3035 #define Abs(n) ((n)<0 ? -(n) : (n))
3038 * Find a font that matches "pattern" that is as close as
3039 * possible to the targetPxlSize. Prefer fonts that are k
3040 * pixels smaller to fonts that are k pixels larger. The
3041 * pattern must be in the X Consortium standard format,
3042 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3043 * The return value should be freed with XtFree when no
3047 FindFont(pattern, targetPxlSize)
3051 char **fonts, *p, *best, *scalable, *scalableTail;
3052 int i, j, nfonts, minerr, err, pxlSize;
3055 char **missing_list;
3057 char *def_string, *base_fnt_lst, strInt[3];
3059 XFontStruct **fnt_list;
3061 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3062 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3063 p = strstr(pattern, "--");
3064 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3065 strcat(base_fnt_lst, strInt);
3066 strcat(base_fnt_lst, strchr(p + 2, '-'));
3068 if ((fntSet = XCreateFontSet(xDisplay,
3072 &def_string)) == NULL) {
3074 fprintf(stderr, _("Unable to create font set.\n"));
3078 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3080 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3082 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3083 programName, pattern);
3091 for (i=0; i<nfonts; i++) {
3094 if (*p != '-') continue;
3096 if (*p == NULLCHAR) break;
3097 if (*p++ == '-') j++;
3099 if (j < 7) continue;
3102 scalable = fonts[i];
3105 err = pxlSize - targetPxlSize;
3106 if (Abs(err) < Abs(minerr) ||
3107 (minerr > 0 && err < 0 && -err == minerr)) {
3113 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3114 /* If the error is too big and there is a scalable font,
3115 use the scalable font. */
3116 int headlen = scalableTail - scalable;
3117 p = (char *) XtMalloc(strlen(scalable) + 10);
3118 while (isdigit(*scalableTail)) scalableTail++;
3119 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3121 p = (char *) XtMalloc(strlen(best) + 2);
3122 safeStrCpy(p, best, strlen(best)+1 );
3124 if (appData.debugMode) {
3125 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3126 pattern, targetPxlSize, p);
3129 if (missing_count > 0)
3130 XFreeStringList(missing_list);
3131 XFreeFontSet(xDisplay, fntSet);
3133 XFreeFontNames(fonts);
3140 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3141 | GCBackground | GCFunction | GCPlaneMask;
3142 XGCValues gc_values;
3145 gc_values.plane_mask = AllPlanes;
3146 gc_values.line_width = lineGap;
3147 gc_values.line_style = LineSolid;
3148 gc_values.function = GXcopy;
3150 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3151 gc_values.background = XBlackPixel(xDisplay, xScreen);
3152 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3154 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3155 gc_values.background = XWhitePixel(xDisplay, xScreen);
3156 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3157 XSetFont(xDisplay, coordGC, coordFontID);
3159 // [HGM] make font for holdings counts (white on black0
3160 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3161 gc_values.background = XBlackPixel(xDisplay, xScreen);
3162 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3163 XSetFont(xDisplay, countGC, countFontID);
3165 if (appData.monoMode) {
3166 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3167 gc_values.background = XWhitePixel(xDisplay, xScreen);
3168 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3170 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3171 gc_values.background = XBlackPixel(xDisplay, xScreen);
3172 lightSquareGC = wbPieceGC
3173 = XtGetGC(shellWidget, value_mask, &gc_values);
3175 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3176 gc_values.background = XWhitePixel(xDisplay, xScreen);
3177 darkSquareGC = bwPieceGC
3178 = XtGetGC(shellWidget, value_mask, &gc_values);
3180 if (DefaultDepth(xDisplay, xScreen) == 1) {
3181 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3182 gc_values.function = GXcopyInverted;
3183 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3184 gc_values.function = GXcopy;
3185 if (XBlackPixel(xDisplay, xScreen) == 1) {
3186 bwPieceGC = darkSquareGC;
3187 wbPieceGC = copyInvertedGC;
3189 bwPieceGC = copyInvertedGC;
3190 wbPieceGC = lightSquareGC;
3194 gc_values.foreground = highlightSquareColor;
3195 gc_values.background = highlightSquareColor;
3196 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3198 gc_values.foreground = premoveHighlightColor;
3199 gc_values.background = premoveHighlightColor;
3200 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3202 gc_values.foreground = lightSquareColor;
3203 gc_values.background = darkSquareColor;
3204 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3206 gc_values.foreground = darkSquareColor;
3207 gc_values.background = lightSquareColor;
3208 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3210 gc_values.foreground = jailSquareColor;
3211 gc_values.background = jailSquareColor;
3212 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3214 gc_values.foreground = whitePieceColor;
3215 gc_values.background = darkSquareColor;
3216 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3218 gc_values.foreground = whitePieceColor;
3219 gc_values.background = lightSquareColor;
3220 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3222 gc_values.foreground = whitePieceColor;
3223 gc_values.background = jailSquareColor;
3224 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3226 gc_values.foreground = blackPieceColor;
3227 gc_values.background = darkSquareColor;
3228 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3230 gc_values.foreground = blackPieceColor;
3231 gc_values.background = lightSquareColor;
3232 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3234 gc_values.foreground = blackPieceColor;
3235 gc_values.background = jailSquareColor;
3236 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3240 void loadXIM(xim, xmask, filename, dest, mask)
3253 fp = fopen(filename, "rb");
3255 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3262 for (y=0; y<h; ++y) {
3263 for (x=0; x<h; ++x) {
3268 XPutPixel(xim, x, y, blackPieceColor);
3270 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3273 XPutPixel(xim, x, y, darkSquareColor);
3275 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3278 XPutPixel(xim, x, y, whitePieceColor);
3280 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3283 XPutPixel(xim, x, y, lightSquareColor);
3285 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3291 /* create Pixmap of piece */
3292 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3294 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3297 /* create Pixmap of clipmask
3298 Note: We assume the white/black pieces have the same
3299 outline, so we make only 6 masks. This is okay
3300 since the XPM clipmask routines do the same. */
3302 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3304 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3307 /* now create the 1-bit version */
3308 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3311 values.foreground = 1;
3312 values.background = 0;
3314 /* Don't use XtGetGC, not read only */
3315 maskGC = XCreateGC(xDisplay, *mask,
3316 GCForeground | GCBackground, &values);
3317 XCopyPlane(xDisplay, temp, *mask, maskGC,
3318 0, 0, squareSize, squareSize, 0, 0, 1);
3319 XFreePixmap(xDisplay, temp);
3324 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3326 void CreateXIMPieces()
3331 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3336 /* The XSynchronize calls were copied from CreatePieces.
3337 Not sure if needed, but can't hurt */
3338 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3341 /* temp needed by loadXIM() */
3342 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3343 0, 0, ss, ss, AllPlanes, XYPixmap);
3345 if (strlen(appData.pixmapDirectory) == 0) {
3349 if (appData.monoMode) {
3350 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3354 fprintf(stderr, _("\nLoading XIMs...\n"));
3356 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3357 fprintf(stderr, "%d", piece+1);
3358 for (kind=0; kind<4; kind++) {
3359 fprintf(stderr, ".");
3360 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3361 ExpandPathName(appData.pixmapDirectory),
3362 piece <= (int) WhiteKing ? "" : "w",
3363 pieceBitmapNames[piece],
3365 ximPieceBitmap[kind][piece] =
3366 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3367 0, 0, ss, ss, AllPlanes, XYPixmap);
3368 if (appData.debugMode)
3369 fprintf(stderr, _("(File:%s:) "), buf);
3370 loadXIM(ximPieceBitmap[kind][piece],
3372 &(xpmPieceBitmap2[kind][piece]),
3373 &(ximMaskPm2[piece]));
3374 if(piece <= (int)WhiteKing)
3375 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3377 fprintf(stderr," ");
3379 /* Load light and dark squares */
3380 /* If the LSQ and DSQ pieces don't exist, we will
3381 draw them with solid squares. */
3382 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3383 if (access(buf, 0) != 0) {
3387 fprintf(stderr, _("light square "));
3389 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3390 0, 0, ss, ss, AllPlanes, XYPixmap);
3391 if (appData.debugMode)
3392 fprintf(stderr, _("(File:%s:) "), buf);
3394 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3395 fprintf(stderr, _("dark square "));
3396 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3397 ExpandPathName(appData.pixmapDirectory), ss);
3398 if (appData.debugMode)
3399 fprintf(stderr, _("(File:%s:) "), buf);
3401 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3402 0, 0, ss, ss, AllPlanes, XYPixmap);
3403 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3404 xpmJailSquare = xpmLightSquare;
3406 fprintf(stderr, _("Done.\n"));
3408 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3412 void CreateXPMBoard(char *s, int kind)
3416 if(s == NULL || *s == 0 || *s == '*') return;
3417 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3418 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3422 void CreateXPMPieces()
3426 u_int ss = squareSize;
3428 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3429 XpmColorSymbol symbols[4];
3431 /* The XSynchronize calls were copied from CreatePieces.
3432 Not sure if needed, but can't hurt */
3433 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3435 /* Setup translations so piece colors match square colors */
3436 symbols[0].name = "light_piece";
3437 symbols[0].value = appData.whitePieceColor;
3438 symbols[1].name = "dark_piece";
3439 symbols[1].value = appData.blackPieceColor;
3440 symbols[2].name = "light_square";
3441 symbols[2].value = appData.lightSquareColor;
3442 symbols[3].name = "dark_square";
3443 symbols[3].value = appData.darkSquareColor;
3445 attr.valuemask = XpmColorSymbols;
3446 attr.colorsymbols = symbols;
3447 attr.numsymbols = 4;
3449 if (appData.monoMode) {
3450 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3454 if (strlen(appData.pixmapDirectory) == 0) {
3455 XpmPieces* pieces = builtInXpms;
3458 while (pieces->size != squareSize && pieces->size) pieces++;
3459 if (!pieces->size) {
3460 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3463 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3464 for (kind=0; kind<4; kind++) {
3466 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3467 pieces->xpm[piece][kind],
3468 &(xpmPieceBitmap2[kind][piece]),
3469 NULL, &attr)) != 0) {
3470 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3474 if(piece <= (int) WhiteKing)
3475 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3479 xpmJailSquare = xpmLightSquare;
3483 fprintf(stderr, _("\nLoading XPMs...\n"));
3486 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3487 fprintf(stderr, "%d ", piece+1);
3488 for (kind=0; kind<4; kind++) {
3489 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3490 ExpandPathName(appData.pixmapDirectory),
3491 piece > (int) WhiteKing ? "w" : "",
3492 pieceBitmapNames[piece],
3494 if (appData.debugMode) {
3495 fprintf(stderr, _("(File:%s:) "), buf);
3497 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3498 &(xpmPieceBitmap2[kind][piece]),
3499 NULL, &attr)) != 0) {
3500 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3501 // [HGM] missing: read of unorthodox piece failed; substitute King.
3502 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3503 ExpandPathName(appData.pixmapDirectory),
3505 if (appData.debugMode) {
3506 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3508 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3509 &(xpmPieceBitmap2[kind][piece]),
3513 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3518 if(piece <= (int) WhiteKing)
3519 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3522 /* Load light and dark squares */
3523 /* If the LSQ and DSQ pieces don't exist, we will
3524 draw them with solid squares. */
3525 fprintf(stderr, _("light square "));
3526 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3527 if (access(buf, 0) != 0) {
3531 if (appData.debugMode)
3532 fprintf(stderr, _("(File:%s:) "), buf);
3534 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3535 &xpmLightSquare, NULL, &attr)) != 0) {
3536 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3539 fprintf(stderr, _("dark square "));
3540 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3541 ExpandPathName(appData.pixmapDirectory), ss);
3542 if (appData.debugMode) {
3543 fprintf(stderr, _("(File:%s:) "), buf);
3545 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3546 &xpmDarkSquare, NULL, &attr)) != 0) {
3547 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3551 xpmJailSquare = xpmLightSquare;
3552 fprintf(stderr, _("Done.\n"));
3554 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3557 #endif /* HAVE_LIBXPM */
3560 /* No built-in bitmaps */
3565 u_int ss = squareSize;
3567 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3570 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3571 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3572 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3573 pieceBitmapNames[piece],
3574 ss, kind == SOLID ? 's' : 'o');
3575 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3576 if(piece <= (int)WhiteKing)
3577 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3581 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3585 /* With built-in bitmaps */
3588 BuiltInBits* bib = builtInBits;
3591 u_int ss = squareSize;
3593 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3596 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3598 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3599 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3600 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3601 pieceBitmapNames[piece],
3602 ss, kind == SOLID ? 's' : 'o');
3603 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3604 bib->bits[kind][piece], ss, ss);
3605 if(piece <= (int)WhiteKing)
3606 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3610 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3615 void ReadBitmap(pm, name, bits, wreq, hreq)