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, 2011 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
66 # if HAVE_SYS_SOCKET_H
67 # include <sys/socket.h>
68 # include <netinet/in.h>
70 # else /* not HAVE_SYS_SOCKET_H */
71 # if HAVE_LAN_SOCKET_H
72 # include <lan/socket.h>
74 # include <lan/netdb.h>
75 # else /* not HAVE_LAN_SOCKET_H */
76 # define OMIT_SOCKETS 1
77 # endif /* not HAVE_LAN_SOCKET_H */
78 # endif /* not HAVE_SYS_SOCKET_H */
79 #endif /* !OMIT_SOCKETS */
84 #else /* not STDC_HEADERS */
85 extern char *getenv();
88 # else /* not HAVE_STRING_H */
90 # endif /* not HAVE_STRING_H */
91 #endif /* not STDC_HEADERS */
94 # include <sys/fcntl.h>
95 #else /* not HAVE_SYS_FCNTL_H */
98 # endif /* HAVE_FCNTL_H */
99 #endif /* not HAVE_SYS_FCNTL_H */
101 #if HAVE_SYS_SYSTEMINFO_H
102 # include <sys/systeminfo.h>
103 #endif /* HAVE_SYS_SYSTEMINFO_H */
105 #if TIME_WITH_SYS_TIME
106 # include <sys/time.h>
110 # include <sys/time.h>
121 # include <sys/wait.h>
126 # define NAMLEN(dirent) strlen((dirent)->d_name)
127 # define HAVE_DIR_STRUCT
129 # define dirent direct
130 # define NAMLEN(dirent) (dirent)->d_namlen
132 # include <sys/ndir.h>
133 # define HAVE_DIR_STRUCT
136 # include <sys/dir.h>
137 # define HAVE_DIR_STRUCT
141 # define HAVE_DIR_STRUCT
145 #include <X11/Intrinsic.h>
146 #include <X11/StringDefs.h>
147 #include <X11/Shell.h>
148 #include <X11/cursorfont.h>
149 #include <X11/Xatom.h>
150 #include <X11/Xmu/Atoms.h>
152 #include <X11/Xaw3d/Dialog.h>
153 #include <X11/Xaw3d/Form.h>
154 #include <X11/Xaw3d/List.h>
155 #include <X11/Xaw3d/Label.h>
156 #include <X11/Xaw3d/SimpleMenu.h>
157 #include <X11/Xaw3d/SmeBSB.h>
158 #include <X11/Xaw3d/SmeLine.h>
159 #include <X11/Xaw3d/Box.h>
160 #include <X11/Xaw3d/MenuButton.h>
161 #include <X11/Xaw3d/Text.h>
162 #include <X11/Xaw3d/AsciiText.h>
164 #include <X11/Xaw/Dialog.h>
165 #include <X11/Xaw/Form.h>
166 #include <X11/Xaw/List.h>
167 #include <X11/Xaw/Label.h>
168 #include <X11/Xaw/SimpleMenu.h>
169 #include <X11/Xaw/SmeBSB.h>
170 #include <X11/Xaw/SmeLine.h>
171 #include <X11/Xaw/Box.h>
172 #include <X11/Xaw/MenuButton.h>
173 #include <X11/Xaw/Text.h>
174 #include <X11/Xaw/AsciiText.h>
177 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
182 #include "pixmaps/pixmaps.h"
183 #define IMAGE_EXT "xpm"
185 #define IMAGE_EXT "xim"
186 #include "bitmaps/bitmaps.h"
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
195 #include "backendz.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
204 // must be moved to xengineoutput.h
206 void EngineOutputProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
208 void EvalGraphProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
216 #define usleep(t) _sleep2(((t)+500)/1000)
220 # define _(s) gettext (s)
221 # define N_(s) gettext_noop (s)
239 int main P((int argc, char **argv));
240 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
241 char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
242 RETSIGTYPE CmailSigHandler P((int sig));
243 RETSIGTYPE IntSigHandler P((int sig));
244 RETSIGTYPE TermSizeSigHandler P((int sig));
245 void CreateGCs P((int redo));
246 void CreateXIMPieces P((void));
247 void CreateXPMPieces P((void));
248 void CreateXPMBoard P((char *s, int n));
249 void CreatePieces P((void));
250 void CreatePieceMenus P((void));
251 Widget CreateMenuBar P((Menu *mb));
252 Widget CreateButtonBar P ((MenuItem *mi));
253 char *FindFont P((char *pattern, int targetPxlSize));
254 void PieceMenuPopup P((Widget w, XEvent *event,
255 String *params, Cardinal *num_params));
256 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
257 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
259 u_int wreq, u_int hreq));
260 void CreateGrid P((void));
261 int EventToSquare P((int x, int limit));
262 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
263 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
264 void HandleUserMove P((Widget w, XEvent *event,
265 String *prms, Cardinal *nprms));
266 void AnimateUserMove P((Widget w, XEvent * event,
267 String * params, Cardinal * nParams));
268 void HandlePV P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void SelectPV P((Widget w, XEvent * event,
271 String * params, Cardinal * nParams));
272 void StopPV P((Widget w, XEvent * event,
273 String * params, Cardinal * nParams));
274 void WhiteClock P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void BlackClock P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void DrawPositionProc P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
282 void CommentClick P((Widget w, XEvent * event,
283 String * params, Cardinal * nParams));
284 void CommentPopUp P((char *title, char *label));
285 void CommentPopDown P((void));
286 void ICSInputBoxPopUp P((void));
287 void ICSInputBoxPopDown P((void));
288 void FileNamePopUp P((char *label, char *def, char *filter,
289 FileProc proc, char *openMode));
290 void FileNamePopDown P((void));
291 void FileNameCallback P((Widget w, XtPointer client_data,
292 XtPointer call_data));
293 void FileNameAction P((Widget w, XEvent *event,
294 String *prms, Cardinal *nprms));
295 void AskQuestionReplyAction P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void AskQuestionProc P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void AskQuestionPopDown P((void));
300 void PromotionPopDown P((void));
301 void PromotionCallback P((Widget w, XtPointer client_data,
302 XtPointer call_data));
303 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
304 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
308 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
310 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
312 void LoadPositionProc P((Widget w, XEvent *event,
313 String *prms, Cardinal *nprms));
314 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
316 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
318 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
320 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
322 void PastePositionProc P((Widget w, XEvent *event, String *prms,
324 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void SavePositionProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
332 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
336 void MachineWhiteProc P((Widget w, XEvent *event,
337 String *prms, Cardinal *nprms));
338 void AnalyzeModeProc P((Widget w, XEvent *event,
339 String *prms, Cardinal *nprms));
340 void AnalyzeFileProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
344 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void IcsClientProc P((Widget w, XEvent *event, String *prms,
348 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void EditPositionProc P((Widget w, XEvent *event,
350 String *prms, Cardinal *nprms));
351 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EditCommentProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void IcsInputBoxProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void StopObservingProc P((Widget w, XEvent *event, String *prms,
372 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
374 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
383 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
385 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
388 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
390 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
392 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
397 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
400 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
402 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
404 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
409 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
411 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
413 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
415 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
418 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
420 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
422 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
424 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void DisplayMove P((int moveNumber));
436 void DisplayTitle P((char *title));
437 void ICSInitScript P((void));
438 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
439 void ErrorPopUp P((char *title, char *text, int modal));
440 void ErrorPopDown P((void));
441 static char *ExpandPathName P((char *path));
442 static void CreateAnimVars P((void));
443 static void DragPieceMove P((int x, int y));
444 static void DrawDragPiece P((void));
445 char *ModeToWidgetName P((GameMode mode));
446 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
449 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
450 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void GameListOptionsPopDown P(());
462 void ShufflePopDown P(());
463 void TimeControlPopDown P(());
464 void GenericPopDown P(());
465 void update_ics_width P(());
466 int get_term_width P(());
467 int CopyMemoProc P(());
468 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
469 Boolean IsDrawArrowEnabled P(());
472 * XBoard depends on Xt R4 or higher
474 int xtVersion = XtSpecificationRelease;
479 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
480 jailSquareColor, highlightSquareColor, premoveHighlightColor;
481 Pixel lowTimeWarningColor;
482 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
483 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
484 wjPieceGC, bjPieceGC, prelineGC, countGC;
485 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
486 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
487 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
488 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
489 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
490 ICSInputShell, fileNameShell, askQuestionShell;
491 Widget historyShell, evalGraphShell, gameListShell;
492 int hOffset; // [HGM] dual
493 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
494 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
495 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
496 Font clockFontID, coordFontID, countFontID;
497 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
498 XtAppContext appContext;
500 char *oldICSInteractionTitle;
504 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
506 Position commentX = -1, commentY = -1;
507 Dimension commentW, commentH;
508 typedef unsigned int BoardSize;
510 Boolean chessProgram;
512 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
513 int squareSize, smallLayout = 0, tinyLayout = 0,
514 marginW, marginH, // [HGM] for run-time resizing
515 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
516 ICSInputBoxUp = False, askQuestionUp = False,
517 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
518 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
519 Pixel timerForegroundPixel, timerBackgroundPixel;
520 Pixel buttonForegroundPixel, buttonBackgroundPixel;
521 char *chessDir, *programName, *programVersion,
522 *gameCopyFilename, *gamePasteFilename;
523 Boolean alwaysOnTop = False;
524 Boolean saveSettingsOnExit;
525 char *settingsFileName;
526 char *icsTextMenuString;
528 char *firstChessProgramNames;
529 char *secondChessProgramNames;
531 WindowPlacement wpMain;
532 WindowPlacement wpConsole;
533 WindowPlacement wpComment;
534 WindowPlacement wpMoveHistory;
535 WindowPlacement wpEvalGraph;
536 WindowPlacement wpEngineOutput;
537 WindowPlacement wpGameList;
538 WindowPlacement wpTags;
540 extern Widget shells[];
541 extern Boolean shellUp[];
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 {N_("New Game Ctrl+N"), "New Game", ResetProc},
596 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
597 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
598 {"----", NULL, NothingProc},
599 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
600 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
601 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
602 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
603 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
604 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
605 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
606 {"----", NULL, NothingProc},
607 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
608 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
609 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
610 {"----", NULL, NothingProc},
611 {N_("Mail Move"), "Mail Move", MailMoveProc},
612 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
613 {"----", NULL, NothingProc},
614 {N_("Quit Ctr+Q"), "Exit", QuitProc},
618 MenuItem editMenu[] = {
619 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
620 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
621 {"----", NULL, NothingProc},
622 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
623 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
624 {"----", NULL, NothingProc},
625 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
626 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
627 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
628 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
629 {"----", NULL, NothingProc},
630 {N_("Revert Home"), "Revert", RevertProc},
631 {N_("Annotate"), "Annotate", AnnotateProc},
632 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
633 {"----", NULL, NothingProc},
634 {N_("Backward Alt+Left"), "Backward", BackwardProc},
635 {N_("Forward Alt+Right"), "Forward", ForwardProc},
636 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
637 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
641 MenuItem viewMenu[] = {
642 {N_("Flip View F2"), "Flip View", FlipViewProc},
643 {"----", NULL, NothingProc},
644 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
645 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
646 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
647 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
648 {N_("ICS text menu"), "ICStex", IcsTextProc},
649 {"----", NULL, NothingProc},
650 {N_("Tags"), "Show Tags", EditTagsProc},
651 {N_("Comments"), "Show Comments", EditCommentProc},
652 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
653 {"----", NULL, NothingProc},
654 {N_("Board..."), "Board Options", BoardOptionsProc},
655 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
659 MenuItem modeMenu[] = {
660 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
661 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
662 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
663 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
664 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
665 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
666 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
667 {N_("Training"), "Training", TrainingProc},
668 {N_("ICS Client"), "ICS Client", IcsClientProc},
669 {"----", NULL, NothingProc},
670 {N_("Machine Match"), "Machine Match", MatchProc},
671 {N_("Pause Pause"), "Pause", PauseProc},
675 MenuItem actionMenu[] = {
676 {N_("Accept F3"), "Accept", AcceptProc},
677 {N_("Decline F4"), "Decline", DeclineProc},
678 {N_("Rematch F12"), "Rematch", RematchProc},
679 {"----", NULL, NothingProc},
680 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
681 {N_("Draw F6"), "Draw", DrawProc},
682 {N_("Adjourn F7"), "Adjourn", AdjournProc},
683 {N_("Abort F8"),"Abort", AbortProc},
684 {N_("Resign F9"), "Resign", ResignProc},
685 {"----", NULL, NothingProc},
686 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
687 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
688 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
689 {"----", NULL, NothingProc},
690 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
691 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
692 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
696 MenuItem engineMenu[] = {
697 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
698 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
699 {"----", NULL, NothingProc},
700 {N_("Hint"), "Hint", HintProc},
701 {N_("Book"), "Book", BookProc},
702 {"----", NULL, NothingProc},
703 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
704 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
708 MenuItem optionsMenu[] = {
709 #define OPTIONSDIALOG
711 {N_("General ..."), "General", OptionsProc},
713 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
714 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
715 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
716 {N_("ICS ..."), "ICS", IcsOptionsProc},
717 {N_("Match ..."), "Match", MatchOptionsProc},
718 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
719 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
720 // {N_(" ..."), "", OptionsProc},
721 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
722 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
723 {"----", NULL, NothingProc},
724 #ifndef OPTIONSDIALOG
725 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
726 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
727 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
728 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
729 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
730 {N_("Blindfold"), "Blindfold", BlindfoldProc},
731 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
733 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
735 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
736 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
737 {N_("Move Sound"), "Move Sound", MoveSoundProc},
738 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
739 {N_("One-Click Moving"), "OneClick", OneClickProc},
740 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
741 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
742 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
743 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
744 // {N_("Premove"), "Premove", PremoveProc},
745 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
746 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
747 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
748 {"----", NULL, NothingProc},
750 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
751 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
755 MenuItem helpMenu[] = {
756 {N_("Info XBoard"), "Info XBoard", InfoProc},
757 {N_("Man XBoard F1"), "Man XBoard", ManProc},
758 {"----", NULL, NothingProc},
759 {N_("About XBoard"), "About XBoard", AboutProc},
764 {N_("File"), "File", fileMenu},
765 {N_("Edit"), "Edit", editMenu},
766 {N_("View"), "View", viewMenu},
767 {N_("Mode"), "Mode", modeMenu},
768 {N_("Action"), "Action", actionMenu},
769 {N_("Engine"), "Engine", engineMenu},
770 {N_("Options"), "Options", optionsMenu},
771 {N_("Help"), "Help", helpMenu},
775 #define PAUSE_BUTTON "P"
776 MenuItem buttonBar[] = {
777 {"<<", "<<", ToStartProc},
778 {"<", "<", BackwardProc},
779 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
780 {">", ">", ForwardProc},
781 {">>", ">>", ToEndProc},
785 #define PIECE_MENU_SIZE 18
786 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
787 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
788 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
789 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
790 N_("Empty square"), N_("Clear board") },
791 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
792 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
793 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
794 N_("Empty square"), N_("Clear board") }
796 /* must be in same order as PieceMenuStrings! */
797 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
798 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
799 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
800 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
801 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
802 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
803 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
804 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
805 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
808 #define DROP_MENU_SIZE 6
809 String dropMenuStrings[DROP_MENU_SIZE] = {
810 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
812 /* must be in same order as PieceMenuStrings! */
813 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
814 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
815 WhiteRook, WhiteQueen
823 DropMenuEnables dmEnables[] = {
841 { XtNborderWidth, 0 },
842 { XtNdefaultDistance, 0 },
846 { XtNborderWidth, 0 },
847 { XtNresizable, (XtArgVal) True },
851 { XtNborderWidth, 0 },
857 { XtNjustify, (XtArgVal) XtJustifyRight },
858 { XtNlabel, (XtArgVal) "..." },
859 { XtNresizable, (XtArgVal) True },
860 { XtNresize, (XtArgVal) False }
863 Arg messageArgs[] = {
864 { XtNjustify, (XtArgVal) XtJustifyLeft },
865 { XtNlabel, (XtArgVal) "..." },
866 { XtNresizable, (XtArgVal) True },
867 { XtNresize, (XtArgVal) False }
871 { XtNborderWidth, 0 },
872 { XtNjustify, (XtArgVal) XtJustifyLeft }
875 XtResource clientResources[] = {
876 { "flashCount", "flashCount", XtRInt, sizeof(int),
877 XtOffset(AppDataPtr, flashCount), XtRImmediate,
878 (XtPointer) FLASH_COUNT },
881 XrmOptionDescRec shellOptions[] = {
882 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
883 { "-flash", "flashCount", XrmoptionNoArg, "3" },
884 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
887 XtActionsRec boardActions[] = {
888 { "DrawPosition", DrawPositionProc },
889 { "HandleUserMove", HandleUserMove },
890 { "AnimateUserMove", AnimateUserMove },
891 { "HandlePV", HandlePV },
892 { "SelectPV", SelectPV },
893 { "StopPV", StopPV },
894 { "FileNameAction", FileNameAction },
895 { "AskQuestionProc", AskQuestionProc },
896 { "AskQuestionReplyAction", AskQuestionReplyAction },
897 { "PieceMenuPopup", PieceMenuPopup },
898 { "WhiteClock", WhiteClock },
899 { "BlackClock", BlackClock },
900 { "Iconify", Iconify },
901 { "ResetProc", ResetProc },
902 { "NewVariantProc", NewVariantProc },
903 { "LoadGameProc", LoadGameProc },
904 { "LoadNextGameProc", LoadNextGameProc },
905 { "LoadPrevGameProc", LoadPrevGameProc },
906 { "LoadSelectedProc", LoadSelectedProc },
907 { "SetFilterProc", SetFilterProc },
908 { "ReloadGameProc", ReloadGameProc },
909 { "LoadPositionProc", LoadPositionProc },
910 { "LoadNextPositionProc", LoadNextPositionProc },
911 { "LoadPrevPositionProc", LoadPrevPositionProc },
912 { "ReloadPositionProc", ReloadPositionProc },
913 { "CopyPositionProc", CopyPositionProc },
914 { "PastePositionProc", PastePositionProc },
915 { "CopyGameProc", CopyGameProc },
916 { "PasteGameProc", PasteGameProc },
917 { "SaveGameProc", SaveGameProc },
918 { "SavePositionProc", SavePositionProc },
919 { "MailMoveProc", MailMoveProc },
920 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
921 { "QuitProc", QuitProc },
922 { "MachineWhiteProc", MachineWhiteProc },
923 { "MachineBlackProc", MachineBlackProc },
924 { "AnalysisModeProc", AnalyzeModeProc },
925 { "AnalyzeFileProc", AnalyzeFileProc },
926 { "TwoMachinesProc", TwoMachinesProc },
927 { "IcsClientProc", IcsClientProc },
928 { "EditGameProc", EditGameProc },
929 { "EditPositionProc", EditPositionProc },
930 { "TrainingProc", EditPositionProc },
931 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
932 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
933 { "ShowGameListProc", ShowGameListProc },
934 { "ShowMoveListProc", HistoryShowProc},
935 { "EditTagsProc", EditCommentProc },
936 { "EditCommentProc", EditCommentProc },
937 { "IcsInputBoxProc", IcsInputBoxProc },
938 { "PauseProc", PauseProc },
939 { "AcceptProc", AcceptProc },
940 { "DeclineProc", DeclineProc },
941 { "RematchProc", RematchProc },
942 { "CallFlagProc", CallFlagProc },
943 { "DrawProc", DrawProc },
944 { "AdjournProc", AdjournProc },
945 { "AbortProc", AbortProc },
946 { "ResignProc", ResignProc },
947 { "AdjuWhiteProc", AdjuWhiteProc },
948 { "AdjuBlackProc", AdjuBlackProc },
949 { "AdjuDrawProc", AdjuDrawProc },
950 { "EnterKeyProc", EnterKeyProc },
951 { "UpKeyProc", UpKeyProc },
952 { "DownKeyProc", DownKeyProc },
953 { "StopObservingProc", StopObservingProc },
954 { "StopExaminingProc", StopExaminingProc },
955 { "UploadProc", UploadProc },
956 { "BackwardProc", BackwardProc },
957 { "ForwardProc", ForwardProc },
958 { "ToStartProc", ToStartProc },
959 { "ToEndProc", ToEndProc },
960 { "RevertProc", RevertProc },
961 { "AnnotateProc", AnnotateProc },
962 { "TruncateGameProc", TruncateGameProc },
963 { "MoveNowProc", MoveNowProc },
964 { "RetractMoveProc", RetractMoveProc },
965 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
966 { "UciMenuProc", (XtActionProc) UciMenuProc },
967 { "TimeControlProc", (XtActionProc) TimeControlProc },
968 { "FlipViewProc", FlipViewProc },
969 { "PonderNextMoveProc", PonderNextMoveProc },
970 #ifndef OPTIONSDIALOG
971 { "AlwaysQueenProc", AlwaysQueenProc },
972 { "AnimateDraggingProc", AnimateDraggingProc },
973 { "AnimateMovingProc", AnimateMovingProc },
974 { "AutoflagProc", AutoflagProc },
975 { "AutoflipProc", AutoflipProc },
976 { "BlindfoldProc", BlindfoldProc },
977 { "FlashMovesProc", FlashMovesProc },
979 { "HighlightDraggingProc", HighlightDraggingProc },
981 { "HighlightLastMoveProc", HighlightLastMoveProc },
982 // { "IcsAlarmProc", IcsAlarmProc },
983 { "MoveSoundProc", MoveSoundProc },
984 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
985 { "PopupExitMessageProc", PopupExitMessageProc },
986 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
987 // { "PremoveProc", PremoveProc },
988 { "ShowCoordsProc", ShowCoordsProc },
989 { "ShowThinkingProc", ShowThinkingProc },
990 { "HideThinkingProc", HideThinkingProc },
991 { "TestLegalityProc", TestLegalityProc },
993 { "SaveSettingsProc", SaveSettingsProc },
994 { "SaveOnExitProc", SaveOnExitProc },
995 { "InfoProc", InfoProc },
996 { "ManProc", ManProc },
997 { "HintProc", HintProc },
998 { "BookProc", BookProc },
999 { "AboutGameProc", AboutGameProc },
1000 { "AboutProc", AboutProc },
1001 { "DebugProc", DebugProc },
1002 { "NothingProc", NothingProc },
1003 { "CommentClick", (XtActionProc) CommentClick },
1004 { "CommentPopDown", (XtActionProc) CommentPopDown },
1005 { "TagsPopDown", (XtActionProc) TagsPopDown },
1006 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1007 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1008 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1009 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1010 { "GameListPopDown", (XtActionProc) GameListPopDown },
1011 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1012 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1013 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1014 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1015 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1016 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1017 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1018 { "GenericPopDown", (XtActionProc) GenericPopDown },
1019 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1022 char globalTranslations[] =
1023 ":<Key>F9: ResignProc() \n \
1024 :Ctrl<Key>n: ResetProc() \n \
1025 :Meta<Key>V: NewVariantProc() \n \
1026 :Ctrl<Key>o: LoadGameProc() \n \
1027 :Meta<Key>Next: LoadNextGameProc() \n \
1028 :Meta<Key>Prior: LoadPrevGameProc() \n \
1029 :Ctrl<Key>s: SaveGameProc() \n \
1030 :Ctrl<Key>c: CopyGameProc() \n \
1031 :Ctrl<Key>v: PasteGameProc() \n \
1032 :Ctrl<Key>O: LoadPositionProc() \n \
1033 :Shift<Key>Next: LoadNextPositionProc() \n \
1034 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1035 :Ctrl<Key>S: SavePositionProc() \n \
1036 :Ctrl<Key>C: CopyPositionProc() \n \
1037 :Ctrl<Key>V: PastePositionProc() \n \
1038 :Ctrl<Key>q: QuitProc() \n \
1039 :Ctrl<Key>w: MachineWhiteProc() \n \
1040 :Ctrl<Key>b: MachineBlackProc() \n \
1041 :Ctrl<Key>t: TwoMachinesProc() \n \
1042 :Ctrl<Key>a: AnalysisModeProc() \n \
1043 :Ctrl<Key>f: AnalyzeFileProc() \n \
1044 :Ctrl<Key>e: EditGameProc() \n \
1045 :Ctrl<Key>E: EditPositionProc() \n \
1046 :Meta<Key>O: EngineOutputProc() \n \
1047 :Meta<Key>E: EvalGraphProc() \n \
1048 :Meta<Key>G: ShowGameListProc() \n \
1049 :Meta<Key>H: ShowMoveListProc() \n \
1050 :<Key>Pause: PauseProc() \n \
1051 :<Key>F3: AcceptProc() \n \
1052 :<Key>F4: DeclineProc() \n \
1053 :<Key>F12: RematchProc() \n \
1054 :<Key>F5: CallFlagProc() \n \
1055 :<Key>F6: DrawProc() \n \
1056 :<Key>F7: AdjournProc() \n \
1057 :<Key>F8: AbortProc() \n \
1058 :<Key>F10: StopObservingProc() \n \
1059 :<Key>F11: StopExaminingProc() \n \
1060 :Meta Ctrl<Key>F12: DebugProc() \n \
1061 :Meta<Key>End: ToEndProc() \n \
1062 :Meta<Key>Right: ForwardProc() \n \
1063 :Meta<Key>Home: ToStartProc() \n \
1064 :Meta<Key>Left: BackwardProc() \n \
1065 :<Key>Home: RevertProc() \n \
1066 :<Key>End: TruncateGameProc() \n \
1067 :Ctrl<Key>m: MoveNowProc() \n \
1068 :Ctrl<Key>x: RetractMoveProc() \n \
1069 :Meta<Key>J: EngineMenuProc() \n \
1070 :Meta<Key>U: UciMenuProc() \n \
1071 :Meta<Key>T: TimeControlProc() \n \
1072 :Ctrl<Key>P: PonderNextMoveProc() \n "
1073 #ifndef OPTIONSDIALOG
1075 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1076 :Ctrl<Key>F: AutoflagProc() \n \
1077 :Ctrl<Key>A: AnimateMovingProc() \n \
1078 :Ctrl<Key>L: TestLegalityProc() \n \
1079 :Ctrl<Key>H: HideThinkingProc() \n "
1082 :<Key>-: Iconify() \n \
1083 :<Key>F1: ManProc() \n \
1084 :<Key>F2: FlipViewProc() \n \
1085 <KeyDown>.: BackwardProc() \n \
1086 <KeyUp>.: ForwardProc() \n \
1087 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1088 \"Send to chess program:\",,1) \n \
1089 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1090 \"Send to second chess program:\",,2) \n";
1092 char boardTranslations[] =
1093 "<Btn1Down>: HandleUserMove(0) \n \
1094 Shift<Btn1Up>: HandleUserMove(1) \n \
1095 <Btn1Up>: HandleUserMove(0) \n \
1096 <Btn1Motion>: AnimateUserMove() \n \
1097 <Btn3Motion>: HandlePV() \n \
1098 <Btn3Up>: PieceMenuPopup(menuB) \n \
1099 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1100 PieceMenuPopup(menuB) \n \
1101 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1102 PieceMenuPopup(menuW) \n \
1103 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1104 PieceMenuPopup(menuW) \n \
1105 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1106 PieceMenuPopup(menuB) \n";
1108 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1109 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1111 char ICSInputTranslations[] =
1112 "<Key>Up: UpKeyProc() \n "
1113 "<Key>Down: DownKeyProc() \n "
1114 "<Key>Return: EnterKeyProc() \n";
1116 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1117 // as the widget is destroyed before the up-click can call extend-end
1118 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1120 String xboardResources[] = {
1121 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1122 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1123 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1128 /* Max possible square size */
1129 #define MAXSQSIZE 256
1131 static int xpm_avail[MAXSQSIZE];
1133 #ifdef HAVE_DIR_STRUCT
1135 /* Extract piece size from filename */
1137 xpm_getsize(name, len, ext)
1148 if ((p=strchr(name, '.')) == NULL ||
1149 StrCaseCmp(p+1, ext) != 0)
1155 while (*p && isdigit(*p))
1162 /* Setup xpm_avail */
1164 xpm_getavail(dirname, ext)
1172 for (i=0; i<MAXSQSIZE; ++i)
1175 if (appData.debugMode)
1176 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1178 dir = opendir(dirname);
1181 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1182 programName, dirname);
1186 while ((ent=readdir(dir)) != NULL) {
1187 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1188 if (i > 0 && i < MAXSQSIZE)
1198 xpm_print_avail(fp, ext)
1204 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1205 for (i=1; i<MAXSQSIZE; ++i) {
1211 /* Return XPM piecesize closest to size */
1213 xpm_closest_to(dirname, size, ext)
1219 int sm_diff = MAXSQSIZE;
1223 xpm_getavail(dirname, ext);
1225 if (appData.debugMode)
1226 xpm_print_avail(stderr, ext);
1228 for (i=1; i<MAXSQSIZE; ++i) {
1231 diff = (diff<0) ? -diff : diff;
1232 if (diff < sm_diff) {
1240 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1246 #else /* !HAVE_DIR_STRUCT */
1247 /* If we are on a system without a DIR struct, we can't
1248 read the directory, so we can't collect a list of
1249 filenames, etc., so we can't do any size-fitting. */
1251 xpm_closest_to(dirname, size, ext)
1256 fprintf(stderr, _("\
1257 Warning: No DIR structure found on this system --\n\
1258 Unable to autosize for XPM/XIM pieces.\n\
1259 Please report this error to frankm@hiwaay.net.\n\
1260 Include system type & operating system in message.\n"));
1263 #endif /* HAVE_DIR_STRUCT */
1265 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1266 "magenta", "cyan", "white" };
1270 TextColors textColors[(int)NColorClasses];
1272 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1274 parse_color(str, which)
1278 char *p, buf[100], *d;
1281 if (strlen(str) > 99) /* watch bounds on buf */
1286 for (i=0; i<which; ++i) {
1293 /* Could be looking at something like:
1295 .. in which case we want to stop on a comma also */
1296 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1300 return -1; /* Use default for empty field */
1303 if (which == 2 || isdigit(*p))
1306 while (*p && isalpha(*p))
1311 for (i=0; i<8; ++i) {
1312 if (!StrCaseCmp(buf, cnames[i]))
1313 return which? (i+40) : (i+30);
1315 if (!StrCaseCmp(buf, "default")) return -1;
1317 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1322 parse_cpair(cc, str)
1326 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1327 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1332 /* bg and attr are optional */
1333 textColors[(int)cc].bg = parse_color(str, 1);
1334 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1335 textColors[(int)cc].attr = 0;
1341 /* Arrange to catch delete-window events */
1342 Atom wm_delete_window;
1344 CatchDeleteWindow(Widget w, String procname)
1347 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1348 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1349 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1356 XtSetArg(args[0], XtNiconic, False);
1357 XtSetValues(shellWidget, args, 1);
1359 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1362 //---------------------------------------------------------------------------------------------------------
1363 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1366 #define CW_USEDEFAULT (1<<31)
1367 #define ICS_TEXT_MENU_SIZE 90
1368 #define DEBUG_FILE "xboard.debug"
1369 #define SetCurrentDirectory chdir
1370 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1374 // these two must some day move to frontend.h, when they are implemented
1375 Boolean GameListIsUp();
1377 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1380 // front-end part of option handling
1382 // [HGM] This platform-dependent table provides the location for storing the color info
1383 extern char *crWhite, * crBlack;
1387 &appData.whitePieceColor,
1388 &appData.blackPieceColor,
1389 &appData.lightSquareColor,
1390 &appData.darkSquareColor,
1391 &appData.highlightSquareColor,
1392 &appData.premoveHighlightColor,
1393 &appData.lowTimeWarningColor,
1404 // [HGM] font: keep a font for each square size, even non-stndard ones
1405 #define NUM_SIZES 18
1406 #define MAX_SIZE 130
1407 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1408 char *fontTable[NUM_FONTS][MAX_SIZE];
1411 ParseFont(char *name, int number)
1412 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1414 if(sscanf(name, "size%d:", &size)) {
1415 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1416 // defer processing it until we know if it matches our board size
1417 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1418 fontTable[number][size] = strdup(strchr(name, ':')+1);
1419 fontValid[number][size] = True;
1424 case 0: // CLOCK_FONT
1425 appData.clockFont = strdup(name);
1427 case 1: // MESSAGE_FONT
1428 appData.font = strdup(name);
1430 case 2: // COORD_FONT
1431 appData.coordFont = strdup(name);
1436 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1441 { // only 2 fonts currently
1442 appData.clockFont = CLOCK_FONT_NAME;
1443 appData.coordFont = COORD_FONT_NAME;
1444 appData.font = DEFAULT_FONT_NAME;
1449 { // no-op, until we identify the code for this already in XBoard and move it here
1453 ParseColor(int n, char *name)
1454 { // in XBoard, just copy the color-name string
1455 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1459 ParseTextAttribs(ColorClass cc, char *s)
1461 (&appData.colorShout)[cc] = strdup(s);
1465 ParseBoardSize(void *addr, char *name)
1467 appData.boardSize = strdup(name);
1472 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1476 SetCommPortDefaults()
1477 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1480 // [HGM] args: these three cases taken out to stay in front-end
1482 SaveFontArg(FILE *f, ArgDescriptor *ad)
1485 int i, n = (int)(intptr_t)ad->argLoc;
1487 case 0: // CLOCK_FONT
1488 name = appData.clockFont;
1490 case 1: // MESSAGE_FONT
1491 name = appData.font;
1493 case 2: // COORD_FONT
1494 name = appData.coordFont;
1499 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1500 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1501 fontTable[n][squareSize] = strdup(name);
1502 fontValid[n][squareSize] = True;
1505 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1506 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1511 { // nothing to do, as the sounds are at all times represented by their text-string names already
1515 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1516 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1517 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1521 SaveColor(FILE *f, ArgDescriptor *ad)
1522 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1523 if(colorVariable[(int)(intptr_t)ad->argLoc])
1524 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1528 SaveBoardSize(FILE *f, char *name, void *addr)
1529 { // wrapper to shield back-end from BoardSize & sizeInfo
1530 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1534 ParseCommPortSettings(char *s)
1535 { // no such option in XBoard (yet)
1538 extern Widget engineOutputShell;
1541 GetActualPlacement(Widget wg, WindowPlacement *wp)
1551 XtSetArg(args[i], XtNx, &x); i++;
1552 XtSetArg(args[i], XtNy, &y); i++;
1553 XtSetArg(args[i], XtNwidth, &w); i++;
1554 XtSetArg(args[i], XtNheight, &h); i++;
1555 XtGetValues(wg, args, i);
1564 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1565 // In XBoard this will have to wait until awareness of window parameters is implemented
1566 GetActualPlacement(shellWidget, &wpMain);
1567 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1568 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1569 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1570 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1571 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1572 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1576 PrintCommPortSettings(FILE *f, char *name)
1577 { // This option does not exist in XBoard
1581 MySearchPath(char *installDir, char *name, char *fullname)
1582 { // just append installDir and name. Perhaps ExpandPath should be used here?
1583 name = ExpandPathName(name);
1584 if(name && name[0] == '/')
1585 safeStrCpy(fullname, name, MSG_SIZ );
1587 sprintf(fullname, "%s%c%s", installDir, '/', name);
1593 MyGetFullPathName(char *name, char *fullname)
1594 { // should use ExpandPath?
1595 name = ExpandPathName(name);
1596 safeStrCpy(fullname, name, MSG_SIZ );
1601 EnsureOnScreen(int *x, int *y, int minX, int minY)
1608 { // [HGM] args: allows testing if main window is realized from back-end
1609 return xBoardWindow != 0;
1613 PopUpStartupDialog()
1614 { // start menu not implemented in XBoard
1618 ConvertToLine(int argc, char **argv)
1620 static char line[128*1024], buf[1024];
1624 for(i=1; i<argc; i++)
1626 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1627 && argv[i][0] != '{' )
1628 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1630 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1631 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1634 line[strlen(line)-1] = NULLCHAR;
1638 //--------------------------------------------------------------------------------------------
1640 extern Boolean twoBoards, partnerUp;
1643 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1645 #define BoardSize int
1646 void InitDrawingSizes(BoardSize boardSize, int flags)
1647 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1648 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1650 XtGeometryResult gres;
1653 if(!formWidget) return;
1656 * Enable shell resizing.
1658 shellArgs[0].value = (XtArgVal) &w;
1659 shellArgs[1].value = (XtArgVal) &h;
1660 XtGetValues(shellWidget, shellArgs, 2);
1662 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1663 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1664 XtSetValues(shellWidget, &shellArgs[2], 4);
1666 XtSetArg(args[0], XtNdefaultDistance, &sep);
1667 XtGetValues(formWidget, args, 1);
1669 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1670 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1671 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1673 hOffset = boardWidth + 10;
1674 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1675 secondSegments[i] = gridSegments[i];
1676 secondSegments[i].x1 += hOffset;
1677 secondSegments[i].x2 += hOffset;
1680 XtSetArg(args[0], XtNwidth, boardWidth);
1681 XtSetArg(args[1], XtNheight, boardHeight);
1682 XtSetValues(boardWidget, args, 2);
1684 timerWidth = (boardWidth - sep) / 2;
1685 XtSetArg(args[0], XtNwidth, timerWidth);
1686 XtSetValues(whiteTimerWidget, args, 1);
1687 XtSetValues(blackTimerWidget, args, 1);
1689 XawFormDoLayout(formWidget, False);
1691 if (appData.titleInWindow) {
1693 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1694 XtSetArg(args[i], XtNheight, &h); i++;
1695 XtGetValues(titleWidget, args, i);
1697 w = boardWidth - 2*bor;
1699 XtSetArg(args[0], XtNwidth, &w);
1700 XtGetValues(menuBarWidget, args, 1);
1701 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1704 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1705 if (gres != XtGeometryYes && appData.debugMode) {
1707 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1708 programName, gres, w, h, wr, hr);
1712 XawFormDoLayout(formWidget, True);
1715 * Inhibit shell resizing.
1717 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1718 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1719 shellArgs[4].value = shellArgs[2].value = w;
1720 shellArgs[5].value = shellArgs[3].value = h;
1721 XtSetValues(shellWidget, &shellArgs[0], 6);
1723 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1726 for(i=0; i<4; i++) {
1728 for(p=0; p<=(int)WhiteKing; p++)
1729 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1730 if(gameInfo.variant == VariantShogi) {
1731 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1732 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1733 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1734 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1735 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1738 if(gameInfo.variant == VariantGothic) {
1739 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1742 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1743 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1744 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1747 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1748 for(p=0; p<=(int)WhiteKing; p++)
1749 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1750 if(gameInfo.variant == VariantShogi) {
1751 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1752 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1753 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1754 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1755 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1758 if(gameInfo.variant == VariantGothic) {
1759 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1762 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1763 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1764 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1769 for(i=0; i<2; i++) {
1771 for(p=0; p<=(int)WhiteKing; p++)
1772 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1773 if(gameInfo.variant == VariantShogi) {
1774 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1775 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1776 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1777 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1778 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1781 if(gameInfo.variant == VariantGothic) {
1782 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1785 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1786 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1787 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1797 void ParseIcsTextColors()
1798 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1799 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1800 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1801 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1802 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1803 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1804 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1805 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1806 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1807 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1808 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1810 if (appData.colorize) {
1812 _("%s: can't parse color names; disabling colorization\n"),
1815 appData.colorize = FALSE;
1820 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1821 XrmValue vFrom, vTo;
1822 int forceMono = False;
1824 if (!appData.monoMode) {
1825 vFrom.addr = (caddr_t) appData.lightSquareColor;
1826 vFrom.size = strlen(appData.lightSquareColor);
1827 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1828 if (vTo.addr == NULL) {
1829 appData.monoMode = True;
1832 lightSquareColor = *(Pixel *) vTo.addr;
1835 if (!appData.monoMode) {
1836 vFrom.addr = (caddr_t) appData.darkSquareColor;
1837 vFrom.size = strlen(appData.darkSquareColor);
1838 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1839 if (vTo.addr == NULL) {
1840 appData.monoMode = True;
1843 darkSquareColor = *(Pixel *) vTo.addr;
1846 if (!appData.monoMode) {
1847 vFrom.addr = (caddr_t) appData.whitePieceColor;
1848 vFrom.size = strlen(appData.whitePieceColor);
1849 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1850 if (vTo.addr == NULL) {
1851 appData.monoMode = True;
1854 whitePieceColor = *(Pixel *) vTo.addr;
1857 if (!appData.monoMode) {
1858 vFrom.addr = (caddr_t) appData.blackPieceColor;
1859 vFrom.size = strlen(appData.blackPieceColor);
1860 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1861 if (vTo.addr == NULL) {
1862 appData.monoMode = True;
1865 blackPieceColor = *(Pixel *) vTo.addr;
1869 if (!appData.monoMode) {
1870 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1871 vFrom.size = strlen(appData.highlightSquareColor);
1872 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1873 if (vTo.addr == NULL) {
1874 appData.monoMode = True;
1877 highlightSquareColor = *(Pixel *) vTo.addr;
1881 if (!appData.monoMode) {
1882 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1883 vFrom.size = strlen(appData.premoveHighlightColor);
1884 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1885 if (vTo.addr == NULL) {
1886 appData.monoMode = True;
1889 premoveHighlightColor = *(Pixel *) vTo.addr;
1900 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1901 XSetWindowAttributes window_attributes;
1903 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1904 XrmValue vFrom, vTo;
1905 XtGeometryResult gres;
1908 int forceMono = False;
1910 srandom(time(0)); // [HGM] book: make random truly random
1912 setbuf(stdout, NULL);
1913 setbuf(stderr, NULL);
1916 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1917 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1921 programName = strrchr(argv[0], '/');
1922 if (programName == NULL)
1923 programName = argv[0];
1928 XtSetLanguageProc(NULL, NULL, NULL);
1929 bindtextdomain(PACKAGE, LOCALEDIR);
1930 textdomain(PACKAGE);
1934 XtAppInitialize(&appContext, "XBoard", shellOptions,
1935 XtNumber(shellOptions),
1936 &argc, argv, xboardResources, NULL, 0);
1937 appData.boardSize = "";
1938 InitAppData(ConvertToLine(argc, argv));
1940 if (p == NULL) p = "/tmp";
1941 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1942 gameCopyFilename = (char*) malloc(i);
1943 gamePasteFilename = (char*) malloc(i);
1944 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1945 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1947 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1948 clientResources, XtNumber(clientResources),
1951 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1952 static char buf[MSG_SIZ];
1953 EscapeExpand(buf, appData.initString);
1954 appData.initString = strdup(buf);
1955 EscapeExpand(buf, appData.secondInitString);
1956 appData.secondInitString = strdup(buf);
1957 EscapeExpand(buf, appData.firstComputerString);
1958 appData.firstComputerString = strdup(buf);
1959 EscapeExpand(buf, appData.secondComputerString);
1960 appData.secondComputerString = strdup(buf);
1963 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1966 if (chdir(chessDir) != 0) {
1967 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1973 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1974 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1975 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1976 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1979 setbuf(debugFP, NULL);
1982 /* [HGM,HR] make sure board size is acceptable */
1983 if(appData.NrFiles > BOARD_FILES ||
1984 appData.NrRanks > BOARD_RANKS )
1985 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1988 /* This feature does not work; animation needs a rewrite */
1989 appData.highlightDragging = FALSE;
1993 xDisplay = XtDisplay(shellWidget);
1994 xScreen = DefaultScreen(xDisplay);
1995 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1997 gameInfo.variant = StringToVariant(appData.variant);
1998 InitPosition(FALSE);
2001 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2003 if (isdigit(appData.boardSize[0])) {
2004 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2005 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2006 &fontPxlSize, &smallLayout, &tinyLayout);
2008 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2009 programName, appData.boardSize);
2013 /* Find some defaults; use the nearest known size */
2014 SizeDefaults *szd, *nearest;
2015 int distance = 99999;
2016 nearest = szd = sizeDefaults;
2017 while (szd->name != NULL) {
2018 if (abs(szd->squareSize - squareSize) < distance) {
2020 distance = abs(szd->squareSize - squareSize);
2021 if (distance == 0) break;
2025 if (i < 2) lineGap = nearest->lineGap;
2026 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2027 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2028 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2029 if (i < 6) smallLayout = nearest->smallLayout;
2030 if (i < 7) tinyLayout = nearest->tinyLayout;
2033 SizeDefaults *szd = sizeDefaults;
2034 if (*appData.boardSize == NULLCHAR) {
2035 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2036 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2039 if (szd->name == NULL) szd--;
2040 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2042 while (szd->name != NULL &&
2043 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2044 if (szd->name == NULL) {
2045 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2046 programName, appData.boardSize);
2050 squareSize = szd->squareSize;
2051 lineGap = szd->lineGap;
2052 clockFontPxlSize = szd->clockFontPxlSize;
2053 coordFontPxlSize = szd->coordFontPxlSize;
2054 fontPxlSize = szd->fontPxlSize;
2055 smallLayout = szd->smallLayout;
2056 tinyLayout = szd->tinyLayout;
2057 // [HGM] font: use defaults from settings file if available and not overruled
2059 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2060 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2061 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2062 appData.font = fontTable[MESSAGE_FONT][squareSize];
2063 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2064 appData.coordFont = fontTable[COORD_FONT][squareSize];
2066 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2067 if (strlen(appData.pixmapDirectory) > 0) {
2068 p = ExpandPathName(appData.pixmapDirectory);
2070 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2071 appData.pixmapDirectory);
2074 if (appData.debugMode) {
2075 fprintf(stderr, _("\
2076 XBoard square size (hint): %d\n\
2077 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2079 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2080 if (appData.debugMode) {
2081 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2084 defaultLineGap = lineGap;
2085 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2087 /* [HR] height treated separately (hacked) */
2088 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2089 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2090 if (appData.showJail == 1) {
2091 /* Jail on top and bottom */
2092 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2093 XtSetArg(boardArgs[2], XtNheight,
2094 boardHeight + 2*(lineGap + squareSize));
2095 } else if (appData.showJail == 2) {
2097 XtSetArg(boardArgs[1], XtNwidth,
2098 boardWidth + 2*(lineGap + squareSize));
2099 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2102 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2103 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2107 * Determine what fonts to use.
2109 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2110 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2111 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2112 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2113 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2114 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2115 appData.font = FindFont(appData.font, fontPxlSize);
2116 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2117 countFontStruct = XQueryFont(xDisplay, countFontID);
2118 // appData.font = FindFont(appData.font, fontPxlSize);
2120 xdb = XtDatabase(xDisplay);
2121 XrmPutStringResource(&xdb, "*font", appData.font);
2124 * Detect if there are not enough colors available and adapt.
2126 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2127 appData.monoMode = True;
2130 forceMono = MakeColors();
2133 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2136 if (appData.bitmapDirectory == NULL ||
2137 appData.bitmapDirectory[0] == NULLCHAR)
2138 appData.bitmapDirectory = DEF_BITMAP_DIR;
2141 if (appData.lowTimeWarning && !appData.monoMode) {
2142 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2143 vFrom.size = strlen(appData.lowTimeWarningColor);
2144 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2145 if (vTo.addr == NULL)
2146 appData.monoMode = True;
2148 lowTimeWarningColor = *(Pixel *) vTo.addr;
2151 if (appData.monoMode && appData.debugMode) {
2152 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2153 (unsigned long) XWhitePixel(xDisplay, xScreen),
2154 (unsigned long) XBlackPixel(xDisplay, xScreen));
2157 ParseIcsTextColors();
2158 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2159 textColors[ColorNone].attr = 0;
2161 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2167 layoutName = "tinyLayout";
2168 } else if (smallLayout) {
2169 layoutName = "smallLayout";
2171 layoutName = "normalLayout";
2173 /* Outer layoutWidget is there only to provide a name for use in
2174 resources that depend on the layout style */
2176 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2177 layoutArgs, XtNumber(layoutArgs));
2179 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2180 formArgs, XtNumber(formArgs));
2181 XtSetArg(args[0], XtNdefaultDistance, &sep);
2182 XtGetValues(formWidget, args, 1);
2185 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2186 XtSetArg(args[0], XtNtop, XtChainTop);
2187 XtSetArg(args[1], XtNbottom, XtChainTop);
2188 XtSetArg(args[2], XtNright, XtChainLeft);
2189 XtSetValues(menuBarWidget, args, 3);
2191 widgetList[j++] = whiteTimerWidget =
2192 XtCreateWidget("whiteTime", labelWidgetClass,
2193 formWidget, timerArgs, XtNumber(timerArgs));
2194 XtSetArg(args[0], XtNfont, clockFontStruct);
2195 XtSetArg(args[1], XtNtop, XtChainTop);
2196 XtSetArg(args[2], XtNbottom, XtChainTop);
2197 XtSetValues(whiteTimerWidget, args, 3);
2199 widgetList[j++] = blackTimerWidget =
2200 XtCreateWidget("blackTime", labelWidgetClass,
2201 formWidget, timerArgs, XtNumber(timerArgs));
2202 XtSetArg(args[0], XtNfont, clockFontStruct);
2203 XtSetArg(args[1], XtNtop, XtChainTop);
2204 XtSetArg(args[2], XtNbottom, XtChainTop);
2205 XtSetValues(blackTimerWidget, args, 3);
2207 if (appData.titleInWindow) {
2208 widgetList[j++] = titleWidget =
2209 XtCreateWidget("title", labelWidgetClass, formWidget,
2210 titleArgs, XtNumber(titleArgs));
2211 XtSetArg(args[0], XtNtop, XtChainTop);
2212 XtSetArg(args[1], XtNbottom, XtChainTop);
2213 XtSetValues(titleWidget, args, 2);
2216 if (appData.showButtonBar) {
2217 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2218 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2219 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2220 XtSetArg(args[2], XtNtop, XtChainTop);
2221 XtSetArg(args[3], XtNbottom, XtChainTop);
2222 XtSetValues(buttonBarWidget, args, 4);
2225 widgetList[j++] = messageWidget =
2226 XtCreateWidget("message", labelWidgetClass, formWidget,
2227 messageArgs, XtNumber(messageArgs));
2228 XtSetArg(args[0], XtNtop, XtChainTop);
2229 XtSetArg(args[1], XtNbottom, XtChainTop);
2230 XtSetValues(messageWidget, args, 2);
2232 widgetList[j++] = boardWidget =
2233 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2234 XtNumber(boardArgs));
2236 XtManageChildren(widgetList, j);
2238 timerWidth = (boardWidth - sep) / 2;
2239 XtSetArg(args[0], XtNwidth, timerWidth);
2240 XtSetValues(whiteTimerWidget, args, 1);
2241 XtSetValues(blackTimerWidget, args, 1);
2243 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2244 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2245 XtGetValues(whiteTimerWidget, args, 2);
2247 if (appData.showButtonBar) {
2248 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2249 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2250 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2254 * formWidget uses these constraints but they are stored
2258 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2259 XtSetValues(menuBarWidget, args, i);
2260 if (appData.titleInWindow) {
2263 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2264 XtSetValues(whiteTimerWidget, args, i);
2266 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2267 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2268 XtSetValues(blackTimerWidget, args, i);
2270 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2271 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2272 XtSetValues(titleWidget, args, i);
2274 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2275 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2276 XtSetValues(messageWidget, args, i);
2277 if (appData.showButtonBar) {
2279 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2280 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2281 XtSetValues(buttonBarWidget, args, i);
2285 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2286 XtSetValues(whiteTimerWidget, args, i);
2288 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2289 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2290 XtSetValues(blackTimerWidget, args, i);
2292 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2293 XtSetValues(titleWidget, args, i);
2295 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2296 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2297 XtSetValues(messageWidget, args, i);
2298 if (appData.showButtonBar) {
2300 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2301 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2302 XtSetValues(buttonBarWidget, args, i);
2307 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2308 XtSetValues(whiteTimerWidget, args, i);
2310 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2311 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2312 XtSetValues(blackTimerWidget, args, i);
2314 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2315 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2316 XtSetValues(messageWidget, args, i);
2317 if (appData.showButtonBar) {
2319 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2320 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2321 XtSetValues(buttonBarWidget, args, i);
2325 XtSetArg(args[0], XtNfromVert, messageWidget);
2326 XtSetArg(args[1], XtNtop, XtChainTop);
2327 XtSetArg(args[2], XtNbottom, XtChainBottom);
2328 XtSetArg(args[3], XtNleft, XtChainLeft);
2329 XtSetArg(args[4], XtNright, XtChainRight);
2330 XtSetValues(boardWidget, args, 5);
2332 XtRealizeWidget(shellWidget);
2335 XtSetArg(args[0], XtNx, wpMain.x);
2336 XtSetArg(args[1], XtNy, wpMain.y);
2337 XtSetValues(shellWidget, args, 2);
2341 * Correct the width of the message and title widgets.
2342 * It is not known why some systems need the extra fudge term.
2343 * The value "2" is probably larger than needed.
2345 XawFormDoLayout(formWidget, False);
2347 #define WIDTH_FUDGE 2
2349 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2350 XtSetArg(args[i], XtNheight, &h); i++;
2351 XtGetValues(messageWidget, args, i);
2352 if (appData.showButtonBar) {
2354 XtSetArg(args[i], XtNwidth, &w); i++;
2355 XtGetValues(buttonBarWidget, args, i);
2356 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2358 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2361 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2362 if (gres != XtGeometryYes && appData.debugMode) {
2363 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2364 programName, gres, w, h, wr, hr);
2367 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2368 /* The size used for the child widget in layout lags one resize behind
2369 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2371 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2372 if (gres != XtGeometryYes && appData.debugMode) {
2373 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2374 programName, gres, w, h, wr, hr);
2377 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2378 XtSetArg(args[1], XtNright, XtChainRight);
2379 XtSetValues(messageWidget, args, 2);
2381 if (appData.titleInWindow) {
2383 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2384 XtSetArg(args[i], XtNheight, &h); i++;
2385 XtGetValues(titleWidget, args, i);
2387 w = boardWidth - 2*bor;
2389 XtSetArg(args[0], XtNwidth, &w);
2390 XtGetValues(menuBarWidget, args, 1);
2391 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2394 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2395 if (gres != XtGeometryYes && appData.debugMode) {
2397 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2398 programName, gres, w, h, wr, hr);
2401 XawFormDoLayout(formWidget, True);
2403 xBoardWindow = XtWindow(boardWidget);
2405 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2406 // not need to go into InitDrawingSizes().
2410 * Create X checkmark bitmap and initialize option menu checks.
2412 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2413 checkmark_bits, checkmark_width, checkmark_height);
2414 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2415 #ifndef OPTIONSDIALOG
2416 if (appData.alwaysPromoteToQueen) {
2417 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2420 if (appData.animateDragging) {
2421 XtSetValues(XtNameToWidget(menuBarWidget,
2422 "menuOptions.Animate Dragging"),
2425 if (appData.animate) {
2426 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2429 if (appData.autoCallFlag) {
2430 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2433 if (appData.autoFlipView) {
2434 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2437 if (appData.blindfold) {
2438 XtSetValues(XtNameToWidget(menuBarWidget,
2439 "menuOptions.Blindfold"), args, 1);
2441 if (appData.flashCount > 0) {
2442 XtSetValues(XtNameToWidget(menuBarWidget,
2443 "menuOptions.Flash Moves"),
2447 if (appData.highlightDragging) {
2448 XtSetValues(XtNameToWidget(menuBarWidget,
2449 "menuOptions.Highlight Dragging"),
2453 if (appData.highlightLastMove) {
2454 XtSetValues(XtNameToWidget(menuBarWidget,
2455 "menuOptions.Highlight Last Move"),
2458 if (appData.highlightMoveWithArrow) {
2459 XtSetValues(XtNameToWidget(menuBarWidget,
2460 "menuOptions.Arrow"),
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.oneClick) {
2472 XtSetValues(XtNameToWidget(menuBarWidget,
2473 "menuOptions.OneClick"), 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.showCoords) {
2496 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2499 if (appData.hideThinkingFromHuman) {
2500 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2503 if (appData.testLegality) {
2504 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2508 if (saveSettingsOnExit) {
2509 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2516 ReadBitmap(&wIconPixmap, "icon_white.bm",
2517 icon_white_bits, icon_white_width, icon_white_height);
2518 ReadBitmap(&bIconPixmap, "icon_black.bm",
2519 icon_black_bits, icon_black_width, icon_black_height);
2520 iconPixmap = wIconPixmap;
2522 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2523 XtSetValues(shellWidget, args, i);
2526 * Create a cursor for the board widget.
2528 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2529 XChangeWindowAttributes(xDisplay, xBoardWindow,
2530 CWCursor, &window_attributes);
2533 * Inhibit shell resizing.
2535 shellArgs[0].value = (XtArgVal) &w;
2536 shellArgs[1].value = (XtArgVal) &h;
2537 XtGetValues(shellWidget, shellArgs, 2);
2538 shellArgs[4].value = shellArgs[2].value = w;
2539 shellArgs[5].value = shellArgs[3].value = h;
2540 XtSetValues(shellWidget, &shellArgs[2], 4);
2541 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2542 marginH = h - boardHeight;
2544 CatchDeleteWindow(shellWidget, "QuitProc");
2549 if (appData.bitmapDirectory[0] != NULLCHAR) {
2553 CreateXPMBoard(appData.liteBackTextureFile, 1);
2554 CreateXPMBoard(appData.darkBackTextureFile, 0);
2558 /* Create regular pieces */
2559 if (!useImages) CreatePieces();
2564 if (appData.animate || appData.animateDragging)
2567 XtAugmentTranslations(formWidget,
2568 XtParseTranslationTable(globalTranslations));
2569 XtAugmentTranslations(boardWidget,
2570 XtParseTranslationTable(boardTranslations));
2571 XtAugmentTranslations(whiteTimerWidget,
2572 XtParseTranslationTable(whiteTranslations));
2573 XtAugmentTranslations(blackTimerWidget,
2574 XtParseTranslationTable(blackTranslations));
2576 /* Why is the following needed on some versions of X instead
2577 * of a translation? */
2578 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2579 (XtEventHandler) EventProc, NULL);
2582 /* [AS] Restore layout */
2583 if( wpMoveHistory.visible ) {
2587 if( wpEvalGraph.visible )
2592 if( wpEngineOutput.visible ) {
2593 EngineOutputPopUp();
2598 if (errorExitStatus == -1) {
2599 if (appData.icsActive) {
2600 /* We now wait until we see "login:" from the ICS before
2601 sending the logon script (problems with timestamp otherwise) */
2602 /*ICSInitScript();*/
2603 if (appData.icsInputBox) ICSInputBoxPopUp();
2607 signal(SIGWINCH, TermSizeSigHandler);
2609 signal(SIGINT, IntSigHandler);
2610 signal(SIGTERM, IntSigHandler);
2611 if (*appData.cmailGameName != NULLCHAR) {
2612 signal(SIGUSR1, CmailSigHandler);
2615 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2617 XtSetKeyboardFocus(shellWidget, formWidget);
2619 XtAppMainLoop(appContext);
2620 if (appData.debugMode) fclose(debugFP); // [DM] debug
2627 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2628 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2630 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2631 unlink(gameCopyFilename);
2632 unlink(gamePasteFilename);
2635 RETSIGTYPE TermSizeSigHandler(int sig)
2648 CmailSigHandler(sig)
2654 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2656 /* Activate call-back function CmailSigHandlerCallBack() */
2657 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2659 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2663 CmailSigHandlerCallBack(isr, closure, message, count, error)
2671 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2673 /**** end signal code ****/
2679 /* try to open the icsLogon script, either in the location given
2680 * or in the users HOME directory
2687 f = fopen(appData.icsLogon, "r");
2690 homedir = getenv("HOME");
2691 if (homedir != NULL)
2693 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2694 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2695 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2696 f = fopen(buf, "r");
2701 ProcessICSInitScript(f);
2703 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2726 if (!menuBarWidget) return;
2727 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2729 DisplayError("menuEdit.Revert", 0);
2731 XtSetSensitive(w, !grey);
2733 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2735 DisplayError("menuEdit.Annotate", 0);
2737 XtSetSensitive(w, !grey);
2742 SetMenuEnables(enab)
2746 if (!menuBarWidget) return;
2747 while (enab->name != NULL) {
2748 w = XtNameToWidget(menuBarWidget, enab->name);
2750 DisplayError(enab->name, 0);
2752 XtSetSensitive(w, enab->value);
2758 Enables icsEnables[] = {
2759 { "menuFile.Mail Move", False },
2760 { "menuFile.Reload CMail Message", False },
2761 { "menuMode.Machine Black", False },
2762 { "menuMode.Machine White", False },
2763 { "menuMode.Analysis Mode", False },
2764 { "menuMode.Analyze File", False },
2765 { "menuMode.Two Machines", False },
2766 { "menuMode.Machine Match", False },
2768 { "menuEngine.Hint", False },
2769 { "menuEngine.Book", False },
2770 { "menuEngine.Move Now", False },
2771 #ifndef OPTIONSDIALOG
2772 { "menuOptions.Periodic Updates", False },
2773 { "menuOptions.Hide Thinking", False },
2774 { "menuOptions.Ponder Next Move", False },
2776 { "menuEngine.Engine #1 Settings", False },
2778 { "menuEngine.Engine #2 Settings", False },
2779 { "menuEdit.Annotate", False },
2783 Enables ncpEnables[] = {
2784 { "menuFile.Mail Move", False },
2785 { "menuFile.Reload CMail Message", False },
2786 { "menuMode.Machine White", False },
2787 { "menuMode.Machine Black", False },
2788 { "menuMode.Analysis Mode", False },
2789 { "menuMode.Analyze File", False },
2790 { "menuMode.Two Machines", False },
2791 { "menuMode.Machine Match", False },
2792 { "menuMode.ICS Client", False },
2793 { "menuView.ICStex", False },
2794 { "menuView.ICS Input Box", False },
2795 { "Action", False },
2796 { "menuEdit.Revert", False },
2797 { "menuEdit.Annotate", False },
2798 { "menuEngine.Engine #1 Settings", False },
2799 { "menuEngine.Engine #2 Settings", False },
2800 { "menuEngine.Move Now", False },
2801 { "menuEngine.Retract Move", False },
2802 { "menuOptions.ICS", False },
2803 #ifndef OPTIONSDIALOG
2804 { "menuOptions.Auto Flag", False },
2805 { "menuOptions.Auto Flip View", False },
2806 // { "menuOptions.ICS Alarm", False },
2807 { "menuOptions.Move Sound", False },
2808 { "menuOptions.Hide Thinking", False },
2809 { "menuOptions.Periodic Updates", False },
2810 { "menuOptions.Ponder Next Move", False },
2812 { "menuEngine.Hint", False },
2813 { "menuEngine.Book", False },
2817 Enables gnuEnables[] = {
2818 { "menuMode.ICS Client", False },
2819 { "menuView.ICStex", 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.ICS", False },
2832 /* The next two options rely on SetCmailMode being called *after* */
2833 /* SetGNUMode so that when GNU is being used to give hints these */
2834 /* menu options are still available */
2836 { "menuFile.Mail Move", False },
2837 { "menuFile.Reload CMail Message", False },
2841 Enables cmailEnables[] = {
2843 { "menuAction.Call Flag", False },
2844 { "menuAction.Draw", True },
2845 { "menuAction.Adjourn", False },
2846 { "menuAction.Abort", False },
2847 { "menuAction.Stop Observing", False },
2848 { "menuAction.Stop Examining", False },
2849 { "menuFile.Mail Move", True },
2850 { "menuFile.Reload CMail Message", True },
2854 Enables trainingOnEnables[] = {
2855 { "menuMode.Edit Comment", False },
2856 { "menuMode.Pause", False },
2857 { "menuEdit.Forward", False },
2858 { "menuEdit.Backward", False },
2859 { "menuEdit.Forward to End", False },
2860 { "menuEdit.Back to Start", False },
2861 { "menuEngine.Move Now", False },
2862 { "menuEdit.Truncate Game", False },
2866 Enables trainingOffEnables[] = {
2867 { "menuMode.Edit Comment", True },
2868 { "menuMode.Pause", True },
2869 { "menuEdit.Forward", True },
2870 { "menuEdit.Backward", True },
2871 { "menuEdit.Forward to End", True },
2872 { "menuEdit.Back to Start", True },
2873 { "menuEngine.Move Now", True },
2874 { "menuEdit.Truncate Game", True },
2878 Enables machineThinkingEnables[] = {
2879 { "menuFile.Load Game", False },
2880 // { "menuFile.Load Next Game", False },
2881 // { "menuFile.Load Previous Game", False },
2882 // { "menuFile.Reload Same Game", False },
2883 { "menuEdit.Paste Game", False },
2884 { "menuFile.Load Position", False },
2885 // { "menuFile.Load Next Position", False },
2886 // { "menuFile.Load Previous Position", False },
2887 // { "menuFile.Reload Same Position", False },
2888 { "menuEdit.Paste Position", False },
2889 { "menuMode.Machine White", False },
2890 { "menuMode.Machine Black", False },
2891 { "menuMode.Two Machines", False },
2892 { "menuMode.Machine Match", False },
2893 { "menuEngine.Retract Move", False },
2897 Enables userThinkingEnables[] = {
2898 { "menuFile.Load Game", True },
2899 // { "menuFile.Load Next Game", True },
2900 // { "menuFile.Load Previous Game", True },
2901 // { "menuFile.Reload Same Game", True },
2902 { "menuEdit.Paste Game", True },
2903 { "menuFile.Load Position", True },
2904 // { "menuFile.Load Next Position", True },
2905 // { "menuFile.Load Previous Position", True },
2906 // { "menuFile.Reload Same Position", True },
2907 { "menuEdit.Paste Position", True },
2908 { "menuMode.Machine White", True },
2909 { "menuMode.Machine Black", True },
2910 { "menuMode.Two Machines", True },
2911 { "menuMode.Machine Match", True },
2912 { "menuEngine.Retract Move", True },
2918 SetMenuEnables(icsEnables);
2921 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2922 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2929 SetMenuEnables(ncpEnables);
2935 SetMenuEnables(gnuEnables);
2941 SetMenuEnables(cmailEnables);
2947 SetMenuEnables(trainingOnEnables);
2948 if (appData.showButtonBar) {
2949 XtSetSensitive(buttonBarWidget, False);
2955 SetTrainingModeOff()
2957 SetMenuEnables(trainingOffEnables);
2958 if (appData.showButtonBar) {
2959 XtSetSensitive(buttonBarWidget, True);
2964 SetUserThinkingEnables()
2966 if (appData.noChessProgram) return;
2967 SetMenuEnables(userThinkingEnables);
2971 SetMachineThinkingEnables()
2973 if (appData.noChessProgram) return;
2974 SetMenuEnables(machineThinkingEnables);
2976 case MachinePlaysBlack:
2977 case MachinePlaysWhite:
2978 case TwoMachinesPlay:
2979 XtSetSensitive(XtNameToWidget(menuBarWidget,
2980 ModeToWidgetName(gameMode)), True);
2987 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2988 #define HISTORY_SIZE 64
2989 static char *history[HISTORY_SIZE];
2990 int histIn = 0, histP = 0;
2993 SaveInHistory(char *cmd)
2995 if (history[histIn] != NULL) {
2996 free(history[histIn]);
2997 history[histIn] = NULL;
2999 if (*cmd == NULLCHAR) return;
3000 history[histIn] = StrSave(cmd);
3001 histIn = (histIn + 1) % HISTORY_SIZE;
3002 if (history[histIn] != NULL) {
3003 free(history[histIn]);
3004 history[histIn] = NULL;
3010 PrevInHistory(char *cmd)
3013 if (histP == histIn) {
3014 if (history[histIn] != NULL) free(history[histIn]);
3015 history[histIn] = StrSave(cmd);
3017 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3018 if (newhp == histIn || history[newhp] == NULL) return NULL;
3020 return history[histP];
3026 if (histP == histIn) return NULL;
3027 histP = (histP + 1) % HISTORY_SIZE;
3028 return history[histP];
3030 // end of borrowed code
3032 #define Abs(n) ((n)<0 ? -(n) : (n))
3035 * Find a font that matches "pattern" that is as close as
3036 * possible to the targetPxlSize. Prefer fonts that are k
3037 * pixels smaller to fonts that are k pixels larger. The
3038 * pattern must be in the X Consortium standard format,
3039 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3040 * The return value should be freed with XtFree when no
3044 FindFont(pattern, targetPxlSize)
3048 char **fonts, *p, *best, *scalable, *scalableTail;
3049 int i, j, nfonts, minerr, err, pxlSize;
3052 char **missing_list;
3054 char *def_string, *base_fnt_lst, strInt[3];
3056 XFontStruct **fnt_list;
3058 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3059 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3060 p = strstr(pattern, "--");
3061 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3062 strcat(base_fnt_lst, strInt);
3063 strcat(base_fnt_lst, strchr(p + 2, '-'));
3065 if ((fntSet = XCreateFontSet(xDisplay,
3069 &def_string)) == NULL) {
3071 fprintf(stderr, _("Unable to create font set.\n"));
3075 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3077 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3079 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3080 programName, pattern);
3088 for (i=0; i<nfonts; i++) {
3091 if (*p != '-') continue;
3093 if (*p == NULLCHAR) break;
3094 if (*p++ == '-') j++;
3096 if (j < 7) continue;
3099 scalable = fonts[i];
3102 err = pxlSize - targetPxlSize;
3103 if (Abs(err) < Abs(minerr) ||
3104 (minerr > 0 && err < 0 && -err == minerr)) {
3110 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3111 /* If the error is too big and there is a scalable font,
3112 use the scalable font. */
3113 int headlen = scalableTail - scalable;
3114 p = (char *) XtMalloc(strlen(scalable) + 10);
3115 while (isdigit(*scalableTail)) scalableTail++;
3116 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3118 p = (char *) XtMalloc(strlen(best) + 2);
3119 safeStrCpy(p, best, strlen(best)+1 );
3121 if (appData.debugMode) {
3122 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3123 pattern, targetPxlSize, p);
3126 if (missing_count > 0)
3127 XFreeStringList(missing_list);
3128 XFreeFontSet(xDisplay, fntSet);
3130 XFreeFontNames(fonts);
3136 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3137 // must be called before all non-first callse to CreateGCs()
3138 XtReleaseGC(shellWidget, highlineGC);
3139 XtReleaseGC(shellWidget, lightSquareGC);
3140 XtReleaseGC(shellWidget, darkSquareGC);
3141 XtReleaseGC(shellWidget, lineGC);
3142 if (appData.monoMode) {
3143 if (DefaultDepth(xDisplay, xScreen) == 1) {
3144 XtReleaseGC(shellWidget, wbPieceGC);
3146 XtReleaseGC(shellWidget, bwPieceGC);
3149 XtReleaseGC(shellWidget, prelineGC);
3150 XtReleaseGC(shellWidget, jailSquareGC);
3151 XtReleaseGC(shellWidget, wdPieceGC);
3152 XtReleaseGC(shellWidget, wlPieceGC);
3153 XtReleaseGC(shellWidget, wjPieceGC);
3154 XtReleaseGC(shellWidget, bdPieceGC);
3155 XtReleaseGC(shellWidget, blPieceGC);
3156 XtReleaseGC(shellWidget, bjPieceGC);
3160 void CreateGCs(int redo)
3162 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3163 | GCBackground | GCFunction | GCPlaneMask;
3164 XGCValues gc_values;
3167 gc_values.plane_mask = AllPlanes;
3168 gc_values.line_width = lineGap;
3169 gc_values.line_style = LineSolid;
3170 gc_values.function = GXcopy;
3173 DeleteGCs(); // called a second time; clean up old GCs first
3174 } else { // [HGM] grid and font GCs created on first call only
3175 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3176 gc_values.background = XWhitePixel(xDisplay, xScreen);
3177 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3178 XSetFont(xDisplay, coordGC, coordFontID);
3180 // [HGM] make font for holdings counts (white on black)
3181 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3182 gc_values.background = XBlackPixel(xDisplay, xScreen);
3183 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3184 XSetFont(xDisplay, countGC, countFontID);
3186 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3187 gc_values.background = XBlackPixel(xDisplay, xScreen);
3188 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3190 if (appData.monoMode) {
3191 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3192 gc_values.background = XWhitePixel(xDisplay, xScreen);
3193 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3195 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3196 gc_values.background = XBlackPixel(xDisplay, xScreen);
3197 lightSquareGC = wbPieceGC
3198 = XtGetGC(shellWidget, value_mask, &gc_values);
3200 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3201 gc_values.background = XWhitePixel(xDisplay, xScreen);
3202 darkSquareGC = bwPieceGC
3203 = XtGetGC(shellWidget, value_mask, &gc_values);
3205 if (DefaultDepth(xDisplay, xScreen) == 1) {
3206 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3207 gc_values.function = GXcopyInverted;
3208 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3209 gc_values.function = GXcopy;
3210 if (XBlackPixel(xDisplay, xScreen) == 1) {
3211 bwPieceGC = darkSquareGC;
3212 wbPieceGC = copyInvertedGC;
3214 bwPieceGC = copyInvertedGC;
3215 wbPieceGC = lightSquareGC;
3219 gc_values.foreground = highlightSquareColor;
3220 gc_values.background = highlightSquareColor;
3221 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3223 gc_values.foreground = premoveHighlightColor;
3224 gc_values.background = premoveHighlightColor;
3225 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3227 gc_values.foreground = lightSquareColor;
3228 gc_values.background = darkSquareColor;
3229 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3231 gc_values.foreground = darkSquareColor;
3232 gc_values.background = lightSquareColor;
3233 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3235 gc_values.foreground = jailSquareColor;
3236 gc_values.background = jailSquareColor;
3237 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3239 gc_values.foreground = whitePieceColor;
3240 gc_values.background = darkSquareColor;
3241 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3243 gc_values.foreground = whitePieceColor;
3244 gc_values.background = lightSquareColor;
3245 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3247 gc_values.foreground = whitePieceColor;
3248 gc_values.background = jailSquareColor;
3249 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3251 gc_values.foreground = blackPieceColor;
3252 gc_values.background = darkSquareColor;
3253 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3255 gc_values.foreground = blackPieceColor;
3256 gc_values.background = lightSquareColor;
3257 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3259 gc_values.foreground = blackPieceColor;
3260 gc_values.background = jailSquareColor;
3261 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3265 void loadXIM(xim, xmask, filename, dest, mask)
3278 fp = fopen(filename, "rb");
3280 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3287 for (y=0; y<h; ++y) {
3288 for (x=0; x<h; ++x) {
3293 XPutPixel(xim, x, y, blackPieceColor);
3295 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3298 XPutPixel(xim, x, y, darkSquareColor);
3300 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3303 XPutPixel(xim, x, y, whitePieceColor);
3305 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3308 XPutPixel(xim, x, y, lightSquareColor);
3310 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3318 /* create Pixmap of piece */
3319 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3321 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3324 /* create Pixmap of clipmask
3325 Note: We assume the white/black pieces have the same
3326 outline, so we make only 6 masks. This is okay
3327 since the XPM clipmask routines do the same. */
3329 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3331 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3334 /* now create the 1-bit version */
3335 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3338 values.foreground = 1;
3339 values.background = 0;
3341 /* Don't use XtGetGC, not read only */
3342 maskGC = XCreateGC(xDisplay, *mask,
3343 GCForeground | GCBackground, &values);
3344 XCopyPlane(xDisplay, temp, *mask, maskGC,
3345 0, 0, squareSize, squareSize, 0, 0, 1);
3346 XFreePixmap(xDisplay, temp);
3351 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3353 void CreateXIMPieces()
3358 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3363 /* The XSynchronize calls were copied from CreatePieces.
3364 Not sure if needed, but can't hurt */
3365 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3368 /* temp needed by loadXIM() */
3369 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3370 0, 0, ss, ss, AllPlanes, XYPixmap);
3372 if (strlen(appData.pixmapDirectory) == 0) {
3376 if (appData.monoMode) {
3377 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3381 fprintf(stderr, _("\nLoading XIMs...\n"));
3383 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3384 fprintf(stderr, "%d", piece+1);
3385 for (kind=0; kind<4; kind++) {
3386 fprintf(stderr, ".");
3387 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3388 ExpandPathName(appData.pixmapDirectory),
3389 piece <= (int) WhiteKing ? "" : "w",
3390 pieceBitmapNames[piece],
3392 ximPieceBitmap[kind][piece] =
3393 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3394 0, 0, ss, ss, AllPlanes, XYPixmap);
3395 if (appData.debugMode)
3396 fprintf(stderr, _("(File:%s:) "), buf);
3397 loadXIM(ximPieceBitmap[kind][piece],
3399 &(xpmPieceBitmap2[kind][piece]),
3400 &(ximMaskPm2[piece]));
3401 if(piece <= (int)WhiteKing)
3402 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3404 fprintf(stderr," ");
3406 /* Load light and dark squares */
3407 /* If the LSQ and DSQ pieces don't exist, we will
3408 draw them with solid squares. */
3409 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3410 if (access(buf, 0) != 0) {
3414 fprintf(stderr, _("light square "));
3416 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3417 0, 0, ss, ss, AllPlanes, XYPixmap);
3418 if (appData.debugMode)
3419 fprintf(stderr, _("(File:%s:) "), buf);
3421 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3422 fprintf(stderr, _("dark square "));
3423 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3424 ExpandPathName(appData.pixmapDirectory), ss);
3425 if (appData.debugMode)
3426 fprintf(stderr, _("(File:%s:) "), buf);
3428 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3429 0, 0, ss, ss, AllPlanes, XYPixmap);
3430 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3431 xpmJailSquare = xpmLightSquare;
3433 fprintf(stderr, _("Done.\n"));
3435 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3438 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3441 void CreateXPMBoard(char *s, int kind)
3445 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3446 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3447 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3451 void FreeXPMPieces()
3452 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3453 // thisroutine has to be called t free the old piece pixmaps
3455 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3456 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3458 XFreePixmap(xDisplay, xpmLightSquare);
3459 XFreePixmap(xDisplay, xpmDarkSquare);
3463 void CreateXPMPieces()
3467 u_int ss = squareSize;
3469 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3470 XpmColorSymbol symbols[4];
3471 static int redo = False;
3473 if(redo) FreeXPMPieces(); else redo = 1;
3475 /* The XSynchronize calls were copied from CreatePieces.
3476 Not sure if needed, but can't hurt */
3477 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3479 /* Setup translations so piece colors match square colors */
3480 symbols[0].name = "light_piece";
3481 symbols[0].value = appData.whitePieceColor;
3482 symbols[1].name = "dark_piece";
3483 symbols[1].value = appData.blackPieceColor;
3484 symbols[2].name = "light_square";
3485 symbols[2].value = appData.lightSquareColor;
3486 symbols[3].name = "dark_square";
3487 symbols[3].value = appData.darkSquareColor;
3489 attr.valuemask = XpmColorSymbols;
3490 attr.colorsymbols = symbols;
3491 attr.numsymbols = 4;
3493 if (appData.monoMode) {
3494 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3498 if (strlen(appData.pixmapDirectory) == 0) {
3499 XpmPieces* pieces = builtInXpms;
3502 while (pieces->size != squareSize && pieces->size) pieces++;
3503 if (!pieces->size) {
3504 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3507 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3508 for (kind=0; kind<4; kind++) {
3510 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3511 pieces->xpm[piece][kind],
3512 &(xpmPieceBitmap2[kind][piece]),
3513 NULL, &attr)) != 0) {
3514 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3518 if(piece <= (int) WhiteKing)
3519 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3523 xpmJailSquare = xpmLightSquare;
3527 fprintf(stderr, _("\nLoading XPMs...\n"));
3530 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3531 fprintf(stderr, "%d ", piece+1);
3532 for (kind=0; kind<4; kind++) {
3533 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3534 ExpandPathName(appData.pixmapDirectory),
3535 piece > (int) WhiteKing ? "w" : "",
3536 pieceBitmapNames[piece],
3538 if (appData.debugMode) {
3539 fprintf(stderr, _("(File:%s:) "), buf);
3541 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3542 &(xpmPieceBitmap2[kind][piece]),
3543 NULL, &attr)) != 0) {
3544 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3545 // [HGM] missing: read of unorthodox piece failed; substitute King.
3546 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3547 ExpandPathName(appData.pixmapDirectory),
3549 if (appData.debugMode) {
3550 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3552 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3553 &(xpmPieceBitmap2[kind][piece]),
3557 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3562 if(piece <= (int) WhiteKing)
3563 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3566 /* Load light and dark squares */
3567 /* If the LSQ and DSQ pieces don't exist, we will
3568 draw them with solid squares. */
3569 fprintf(stderr, _("light square "));
3570 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3571 if (access(buf, 0) != 0) {
3575 if (appData.debugMode)
3576 fprintf(stderr, _("(File:%s:) "), buf);
3578 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3579 &xpmLightSquare, NULL, &attr)) != 0) {
3580 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3583 fprintf(stderr, _("dark square "));
3584 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3585 ExpandPathName(appData.pixmapDirectory), ss);
3586 if (appData.debugMode) {
3587 fprintf(stderr, _("(File:%s:) "), buf);
3589 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3590 &xpmDarkSquare, NULL, &attr)) != 0) {
3591 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3595 xpmJailSquare = xpmLightSquare;
3596 fprintf(stderr, _("Done.\n"));
3598 oldVariant = -1; // kludge to force re-makig of animation masks
3599 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3602 #endif /* HAVE_LIBXPM */
3605 /* No built-in bitmaps */
3610 u_int ss = squareSize;
3612 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3615 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3616 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3617 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3618 pieceBitmapNames[piece],
3619 ss, kind == SOLID ? 's' : 'o');