2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
65 # if HAVE_SYS_SOCKET_H
66 # include <sys/socket.h>
67 # include <netinet/in.h>
69 # else /* not HAVE_SYS_SOCKET_H */
70 # if HAVE_LAN_SOCKET_H
71 # include <lan/socket.h>
73 # include <lan/netdb.h>
74 # else /* not HAVE_LAN_SOCKET_H */
75 # define OMIT_SOCKETS 1
76 # endif /* not HAVE_LAN_SOCKET_H */
77 # endif /* not HAVE_SYS_SOCKET_H */
78 #endif /* !OMIT_SOCKETS */
83 #else /* not STDC_HEADERS */
84 extern char *getenv();
87 # else /* not HAVE_STRING_H */
89 # endif /* not HAVE_STRING_H */
90 #endif /* not STDC_HEADERS */
93 # include <sys/fcntl.h>
94 #else /* not HAVE_SYS_FCNTL_H */
97 # endif /* HAVE_FCNTL_H */
98 #endif /* not HAVE_SYS_FCNTL_H */
100 #if HAVE_SYS_SYSTEMINFO_H
101 # include <sys/systeminfo.h>
102 #endif /* HAVE_SYS_SYSTEMINFO_H */
104 #if TIME_WITH_SYS_TIME
105 # include <sys/time.h>
109 # include <sys/time.h>
120 # include <sys/wait.h>
125 # define NAMLEN(dirent) strlen((dirent)->d_name)
126 # define HAVE_DIR_STRUCT
128 # define dirent direct
129 # define NAMLEN(dirent) (dirent)->d_namlen
131 # include <sys/ndir.h>
132 # define HAVE_DIR_STRUCT
135 # include <sys/dir.h>
136 # define HAVE_DIR_STRUCT
140 # define HAVE_DIR_STRUCT
144 #include <X11/Intrinsic.h>
145 #include <X11/StringDefs.h>
146 #include <X11/Shell.h>
147 #include <X11/cursorfont.h>
148 #include <X11/Xatom.h>
149 #include <X11/Xmu/Atoms.h>
151 #include <X11/Xaw3d/Dialog.h>
152 #include <X11/Xaw3d/Form.h>
153 #include <X11/Xaw3d/List.h>
154 #include <X11/Xaw3d/Label.h>
155 #include <X11/Xaw3d/SimpleMenu.h>
156 #include <X11/Xaw3d/SmeBSB.h>
157 #include <X11/Xaw3d/SmeLine.h>
158 #include <X11/Xaw3d/Box.h>
159 #include <X11/Xaw3d/MenuButton.h>
160 #include <X11/Xaw3d/Text.h>
161 #include <X11/Xaw3d/AsciiText.h>
163 #include <X11/Xaw/Dialog.h>
164 #include <X11/Xaw/Form.h>
165 #include <X11/Xaw/List.h>
166 #include <X11/Xaw/Label.h>
167 #include <X11/Xaw/SimpleMenu.h>
168 #include <X11/Xaw/SmeBSB.h>
169 #include <X11/Xaw/SmeLine.h>
170 #include <X11/Xaw/Box.h>
171 #include <X11/Xaw/MenuButton.h>
172 #include <X11/Xaw/Text.h>
173 #include <X11/Xaw/AsciiText.h>
176 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
181 #include "pixmaps/pixmaps.h"
182 #define IMAGE_EXT "xpm"
184 #define IMAGE_EXT "xim"
185 #include "bitmaps/bitmaps.h"
188 #include "bitmaps/icon_white.bm"
189 #include "bitmaps/icon_black.bm"
190 #include "bitmaps/checkmark.bm"
192 #include "frontend.h"
197 #include "xgamelist.h"
198 #include "xhistory.h"
199 #include "xedittags.h"
202 // must be moved to xengineoutput.h
204 void EngineOutputProc P((Widget w, XEvent *event,
205 String *prms, Cardinal *nprms));
206 void EvalGraphProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
214 #define usleep(t) _sleep2(((t)+500)/1000)
218 # define _(s) gettext (s)
219 # define N_(s) gettext_noop (s)
235 int main P((int argc, char **argv));
236 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
237 char *init_path, char *mode, int (*show_entry)(), char **name_return));
238 RETSIGTYPE CmailSigHandler P((int sig));
239 RETSIGTYPE IntSigHandler P((int sig));
240 RETSIGTYPE TermSizeSigHandler P((int sig));
241 void CreateGCs P((void));
242 void CreateXIMPieces P((void));
243 void CreateXPMPieces P((void));
244 void CreatePieces P((void));
245 void CreatePieceMenus P((void));
246 Widget CreateMenuBar P((Menu *mb));
247 Widget CreateButtonBar P ((MenuItem *mi));
248 char *FindFont P((char *pattern, int targetPxlSize));
249 void PieceMenuPopup P((Widget w, XEvent *event,
250 String *params, Cardinal *num_params));
251 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
252 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
253 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
254 u_int wreq, u_int hreq));
255 void CreateGrid P((void));
256 int EventToSquare P((int x, int limit));
257 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
258 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
259 void HandleUserMove P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void AnimateUserMove P((Widget w, XEvent * event,
262 String * params, Cardinal * nParams));
263 void HandlePV P((Widget w, XEvent * event,
264 String * params, Cardinal * nParams));
265 void WhiteClock P((Widget w, XEvent *event,
266 String *prms, Cardinal *nprms));
267 void BlackClock P((Widget w, XEvent *event,
268 String *prms, Cardinal *nprms));
269 void DrawPositionProc P((Widget w, XEvent *event,
270 String *prms, Cardinal *nprms));
271 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
273 void CommentPopUp P((char *title, char *label));
274 void CommentPopDown P((void));
275 void CommentCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void ICSInputBoxPopUp P((void));
278 void ICSInputBoxPopDown P((void));
279 void FileNamePopUp P((char *label, char *def,
280 FileProc proc, char *openMode));
281 void FileNamePopDown P((void));
282 void FileNameCallback P((Widget w, XtPointer client_data,
283 XtPointer call_data));
284 void FileNameAction P((Widget w, XEvent *event,
285 String *prms, Cardinal *nprms));
286 void AskQuestionReplyAction P((Widget w, XEvent *event,
287 String *prms, Cardinal *nprms));
288 void AskQuestionProc P((Widget w, XEvent *event,
289 String *prms, Cardinal *nprms));
290 void AskQuestionPopDown P((void));
291 void PromotionPopDown P((void));
292 void PromotionCallback P((Widget w, XtPointer client_data,
293 XtPointer call_data));
294 void EditCommentPopDown P((void));
295 void EditCommentCallback P((Widget w, XtPointer client_data,
296 XtPointer call_data));
297 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
298 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
299 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
302 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
304 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
306 void LoadPositionProc P((Widget w, XEvent *event,
307 String *prms, Cardinal *nprms));
308 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
310 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
312 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
314 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
316 void PastePositionProc P((Widget w, XEvent *event, String *prms,
318 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
319 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void SavePositionProc P((Widget w, XEvent *event,
322 String *prms, Cardinal *nprms));
323 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
326 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
330 void MachineWhiteProc P((Widget w, XEvent *event,
331 String *prms, Cardinal *nprms));
332 void AnalyzeModeProc P((Widget w, XEvent *event,
333 String *prms, Cardinal *nprms));
334 void AnalyzeFileProc P((Widget w, XEvent *event,
335 String *prms, Cardinal *nprms));
336 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
338 void IcsClientProc P((Widget w, XEvent *event, String *prms,
340 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void EditPositionProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void EditCommentProc P((Widget w, XEvent *event,
345 String *prms, Cardinal *nprms));
346 void IcsInputBoxProc P((Widget w, XEvent *event,
347 String *prms, Cardinal *nprms));
348 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void StopObservingProc P((Widget w, XEvent *event, String *prms,
364 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
366 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
375 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
377 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
380 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
382 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
384 void AutocommProc P((Widget w, XEvent *event, String *prms,
386 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void AutobsProc P((Widget w, XEvent *event, String *prms,
390 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
395 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
398 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
400 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
402 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
406 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
408 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
410 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
412 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
414 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void QuietPlayProc 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 NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void GameListOptionsPopDown P(());
455 void ShufflePopDown P(());
456 void EnginePopDown P(());
457 void UciPopDown P(());
458 void TimeControlPopDown P(());
459 void NewVariantPopDown P(());
460 void SettingsPopDown P(());
461 void update_ics_width P(());
462 int get_term_width P(());
463 int CopyMemoProc P(());
465 * XBoard depends on Xt R4 or higher
467 int xtVersion = XtSpecificationRelease;
472 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
473 jailSquareColor, highlightSquareColor, premoveHighlightColor;
474 Pixel lowTimeWarningColor;
475 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
476 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
477 wjPieceGC, bjPieceGC, prelineGC, countGC;
478 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
479 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
480 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
481 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
482 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
483 ICSInputShell, fileNameShell, askQuestionShell;
484 Widget historyShell, evalGraphShell, gameListShell;
485 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
486 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
487 Font clockFontID, coordFontID, countFontID;
488 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
489 XtAppContext appContext;
491 char *oldICSInteractionTitle;
495 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
497 Position commentX = -1, commentY = -1;
498 Dimension commentW, commentH;
499 typedef unsigned int BoardSize;
501 Boolean chessProgram;
503 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
504 int squareSize, smallLayout = 0, tinyLayout = 0,
505 marginW, marginH, // [HGM] for run-time resizing
506 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
507 ICSInputBoxUp = False, askQuestionUp = False,
508 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
509 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
510 Pixel timerForegroundPixel, timerBackgroundPixel;
511 Pixel buttonForegroundPixel, buttonBackgroundPixel;
512 char *chessDir, *programName, *programVersion,
513 *gameCopyFilename, *gamePasteFilename;
514 Boolean alwaysOnTop = False;
515 Boolean saveSettingsOnExit;
516 char *settingsFileName;
517 char *icsTextMenuString;
519 char *firstChessProgramNames;
520 char *secondChessProgramNames;
522 WindowPlacement wpMain;
523 WindowPlacement wpConsole;
524 WindowPlacement wpComment;
525 WindowPlacement wpMoveHistory;
526 WindowPlacement wpEvalGraph;
527 WindowPlacement wpEngineOutput;
528 WindowPlacement wpGameList;
529 WindowPlacement wpTags;
533 Pixmap pieceBitmap[2][(int)BlackPawn];
534 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
535 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
536 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
537 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
538 int useImages, useImageSqs;
539 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
540 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
541 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
542 XImage *ximLightSquare, *ximDarkSquare;
545 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
546 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
548 #define White(piece) ((int)(piece) < (int)BlackPawn)
550 /* Variables for doing smooth animation. This whole thing
551 would be much easier if the board was double-buffered,
552 but that would require a fairly major rewrite. */
557 GC blitGC, pieceGC, outlineGC;
558 XPoint startSquare, prevFrame, mouseDelta;
562 int startBoardX, startBoardY;
565 /* There can be two pieces being animated at once: a player
566 can begin dragging a piece before the remote opponent has moved. */
568 static AnimState game, player;
570 /* Bitmaps for use as masks when drawing XPM pieces.
571 Need one for each black and white piece. */
572 static Pixmap xpmMask[BlackKing + 1];
574 /* This magic number is the number of intermediate frames used
575 in each half of the animation. For short moves it's reduced
576 by 1. The total number of frames will be factor * 2 + 1. */
579 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
581 MenuItem fileMenu[] = {
582 {N_("New Game"), ResetProc},
583 {N_("New Shuffle Game ..."), ShuffleMenuProc},
584 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
585 {"----", NothingProc},
586 {N_("Load Game"), LoadGameProc},
587 {N_("Load Next Game"), LoadNextGameProc},
588 {N_("Load Previous Game"), LoadPrevGameProc},
589 {N_("Reload Same Game"), ReloadGameProc},
590 {N_("Save Game"), SaveGameProc},
591 {"----", NothingProc},
592 {N_("Copy Game"), CopyGameProc},
593 {N_("Paste Game"), PasteGameProc},
594 {"----", NothingProc},
595 {N_("Load Position"), LoadPositionProc},
596 {N_("Load Next Position"), LoadNextPositionProc},
597 {N_("Load Previous Position"), LoadPrevPositionProc},
598 {N_("Reload Same Position"), ReloadPositionProc},
599 {N_("Save Position"), SavePositionProc},
600 {"----", NothingProc},
601 {N_("Copy Position"), CopyPositionProc},
602 {N_("Paste Position"), PastePositionProc},
603 {"----", NothingProc},
604 {N_("Mail Move"), MailMoveProc},
605 {N_("Reload CMail Message"), ReloadCmailMsgProc},
606 {"----", NothingProc},
607 {N_("Exit"), QuitProc},
611 MenuItem modeMenu[] = {
612 {N_("Machine White"), MachineWhiteProc},
613 {N_("Machine Black"), MachineBlackProc},
614 {N_("Two Machines"), TwoMachinesProc},
615 {N_("Analysis Mode"), AnalyzeModeProc},
616 {N_("Analyze File"), AnalyzeFileProc },
617 {N_("ICS Client"), IcsClientProc},
618 {N_("Edit Game"), EditGameProc},
619 {N_("Edit Position"), EditPositionProc},
620 {N_("Training"), TrainingProc},
621 {"----", NothingProc},
622 {N_("Show Engine Output"), EngineOutputProc},
623 {N_("Show Evaluation Graph"), EvalGraphProc},
624 {N_("Show Game List"), ShowGameListProc},
625 {N_("Show Move History"), HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
626 {"----", NothingProc},
627 {N_("Edit Tags"), EditTagsProc},
628 {N_("Edit Comment"), EditCommentProc},
629 {N_("ICS Input Box"), IcsInputBoxProc},
630 {N_("Pause"), PauseProc},
634 MenuItem actionMenu[] = {
635 {N_("Accept"), AcceptProc},
636 {N_("Decline"), DeclineProc},
637 {N_("Rematch"), RematchProc},
638 {"----", NothingProc},
639 {N_("Call Flag"), CallFlagProc},
640 {N_("Draw"), DrawProc},
641 {N_("Adjourn"), AdjournProc},
642 {N_("Abort"), AbortProc},
643 {N_("Resign"), ResignProc},
644 {"----", NothingProc},
645 {N_("Stop Observing"), StopObservingProc},
646 {N_("Stop Examining"), StopExaminingProc},
647 {N_("Upload to Examine"), UploadProc},
648 {"----", NothingProc},
649 {N_("Adjudicate to White"), AdjuWhiteProc},
650 {N_("Adjudicate to Black"), AdjuBlackProc},
651 {N_("Adjudicate Draw"), AdjuDrawProc},
655 MenuItem stepMenu[] = {
656 {N_("Backward"), BackwardProc},
657 {N_("Forward"), ForwardProc},
658 {N_("Back to Start"), ToStartProc},
659 {N_("Forward to End"), ToEndProc},
660 {N_("Revert"), RevertProc},
661 {N_("Annotate"), AnnotateProc},
662 {N_("Truncate Game"), TruncateGameProc},
663 {"----", NothingProc},
664 {N_("Move Now"), MoveNowProc},
665 {N_("Retract Move"), RetractMoveProc},
669 MenuItem optionsMenu[] = {
670 {N_("Flip View"), FlipViewProc},
671 {"----", NothingProc},
672 {N_("Adjudications ..."), EngineMenuProc},
673 {N_("General Settings ..."), UciMenuProc},
674 {N_("Engine #1 Settings ..."), FirstSettingsProc},
675 {N_("Engine #2 Settings ..."), SecondSettingsProc},
676 {N_("Time Control ..."), TimeControlProc},
677 {N_("Game List ..."), GameListOptionsPopUp},
678 {"----", NothingProc},
679 {N_("Always Queen"), AlwaysQueenProc},
680 {N_("Animate Dragging"), AnimateDraggingProc},
681 {N_("Animate Moving"), AnimateMovingProc},
682 {N_("Auto Comment"), AutocommProc},
683 {N_("Auto Flag"), AutoflagProc},
684 {N_("Auto Flip View"), AutoflipProc},
685 {N_("Auto Observe"), AutobsProc},
686 {N_("Auto Raise Board"), AutoraiseProc},
687 {N_("Auto Save"), AutosaveProc},
688 {N_("Blindfold"), BlindfoldProc},
689 {N_("Flash Moves"), FlashMovesProc},
690 {N_("Get Move List"), GetMoveListProc},
692 {N_("Highlight Dragging"), HighlightDraggingProc},
694 {N_("Highlight Last Move"), HighlightLastMoveProc},
695 {N_("Move Sound"), MoveSoundProc},
696 {N_("ICS Alarm"), IcsAlarmProc},
697 {N_("Old Save Style"), OldSaveStyleProc},
698 {N_("Periodic Updates"), PeriodicUpdatesProc},
699 {N_("Ponder Next Move"), PonderNextMoveProc},
700 {N_("Popup Exit Message"), PopupExitMessageProc},
701 {N_("Popup Move Errors"), PopupMoveErrorsProc},
702 {N_("Premove"), PremoveProc},
703 {N_("Quiet Play"), QuietPlayProc},
704 {N_("Show Coords"), ShowCoordsProc},
705 {N_("Hide Thinking"), HideThinkingProc},
706 {N_("Test Legality"), TestLegalityProc},
707 {"----", NothingProc},
708 {N_("Save Settings Now"), SaveSettingsProc},
709 {N_("Save Settings on Exit"), SaveOnExitProc},
713 MenuItem helpMenu[] = {
714 {N_("Info XBoard"), InfoProc},
715 {N_("Man XBoard"), ManProc},
716 {"----", NothingProc},
717 {N_("Hint"), HintProc},
718 {N_("Book"), BookProc},
719 {"----", NothingProc},
720 {N_("About XBoard"), AboutProc},
725 {N_("File"), fileMenu},
726 {N_("Mode"), modeMenu},
727 {N_("Action"), actionMenu},
728 {N_("Step"), stepMenu},
729 {N_("Options"), optionsMenu},
730 {N_("Help"), helpMenu},
734 #define PAUSE_BUTTON N_("P")
735 MenuItem buttonBar[] = {
738 {PAUSE_BUTTON, PauseProc},
744 #define PIECE_MENU_SIZE 18
745 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
746 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
747 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
748 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
749 N_("Empty square"), N_("Clear board") },
750 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
751 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
752 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
753 N_("Empty square"), N_("Clear board") }
755 /* must be in same order as PieceMenuStrings! */
756 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
757 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
758 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
759 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
760 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
761 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
762 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
763 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
764 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
767 #define DROP_MENU_SIZE 6
768 String dropMenuStrings[DROP_MENU_SIZE] = {
769 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
771 /* must be in same order as PieceMenuStrings! */
772 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
773 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
774 WhiteRook, WhiteQueen
782 DropMenuEnables dmEnables[] = {
800 { XtNborderWidth, 0 },
801 { XtNdefaultDistance, 0 },
805 { XtNborderWidth, 0 },
806 { XtNresizable, (XtArgVal) True },
810 { XtNborderWidth, 0 },
816 { XtNjustify, (XtArgVal) XtJustifyRight },
817 { XtNlabel, (XtArgVal) "..." },
818 { XtNresizable, (XtArgVal) True },
819 { XtNresize, (XtArgVal) False }
822 Arg messageArgs[] = {
823 { XtNjustify, (XtArgVal) XtJustifyLeft },
824 { XtNlabel, (XtArgVal) "..." },
825 { XtNresizable, (XtArgVal) True },
826 { XtNresize, (XtArgVal) False }
830 { XtNborderWidth, 0 },
831 { XtNjustify, (XtArgVal) XtJustifyLeft }
834 XtResource clientResources[] = {
835 { "flashCount", "flashCount", XtRInt, sizeof(int),
836 XtOffset(AppDataPtr, flashCount), XtRImmediate,
837 (XtPointer) FLASH_COUNT },
840 XrmOptionDescRec shellOptions[] = {
841 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
842 { "-flash", "flashCount", XrmoptionNoArg, "3" },
843 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
846 XtActionsRec boardActions[] = {
847 { "DrawPosition", DrawPositionProc },
848 { "HandleUserMove", HandleUserMove },
849 { "AnimateUserMove", AnimateUserMove },
850 { "HandlePV", HandlePV },
851 { "UnLoadPV", UnLoadPV },
852 { "FileNameAction", FileNameAction },
853 { "AskQuestionProc", AskQuestionProc },
854 { "AskQuestionReplyAction", AskQuestionReplyAction },
855 { "PieceMenuPopup", PieceMenuPopup },
856 { "WhiteClock", WhiteClock },
857 { "BlackClock", BlackClock },
858 { "Iconify", Iconify },
859 { "ResetProc", ResetProc },
860 { "LoadGameProc", LoadGameProc },
861 { "LoadNextGameProc", LoadNextGameProc },
862 { "LoadPrevGameProc", LoadPrevGameProc },
863 { "LoadSelectedProc", LoadSelectedProc },
864 { "SetFilterProc", SetFilterProc },
865 { "ReloadGameProc", ReloadGameProc },
866 { "LoadPositionProc", LoadPositionProc },
867 { "LoadNextPositionProc", LoadNextPositionProc },
868 { "LoadPrevPositionProc", LoadPrevPositionProc },
869 { "ReloadPositionProc", ReloadPositionProc },
870 { "CopyPositionProc", CopyPositionProc },
871 { "PastePositionProc", PastePositionProc },
872 { "CopyGameProc", CopyGameProc },
873 { "PasteGameProc", PasteGameProc },
874 { "SaveGameProc", SaveGameProc },
875 { "SavePositionProc", SavePositionProc },
876 { "MailMoveProc", MailMoveProc },
877 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
878 { "QuitProc", QuitProc },
879 { "MachineWhiteProc", MachineWhiteProc },
880 { "MachineBlackProc", MachineBlackProc },
881 { "AnalysisModeProc", AnalyzeModeProc },
882 { "AnalyzeFileProc", AnalyzeFileProc },
883 { "TwoMachinesProc", TwoMachinesProc },
884 { "IcsClientProc", IcsClientProc },
885 { "EditGameProc", EditGameProc },
886 { "EditPositionProc", EditPositionProc },
887 { "TrainingProc", EditPositionProc },
888 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
889 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
890 { "ShowGameListProc", ShowGameListProc },
891 { "ShowMoveListProc", HistoryShowProc},
892 { "EditTagsProc", EditCommentProc },
893 { "EditCommentProc", EditCommentProc },
894 { "IcsAlarmProc", IcsAlarmProc },
895 { "IcsInputBoxProc", IcsInputBoxProc },
896 { "PauseProc", PauseProc },
897 { "AcceptProc", AcceptProc },
898 { "DeclineProc", DeclineProc },
899 { "RematchProc", RematchProc },
900 { "CallFlagProc", CallFlagProc },
901 { "DrawProc", DrawProc },
902 { "AdjournProc", AdjournProc },
903 { "AbortProc", AbortProc },
904 { "ResignProc", ResignProc },
905 { "AdjuWhiteProc", AdjuWhiteProc },
906 { "AdjuBlackProc", AdjuBlackProc },
907 { "AdjuDrawProc", AdjuDrawProc },
908 { "EnterKeyProc", EnterKeyProc },
909 { "UpKeyProc", UpKeyProc },
910 { "DownKeyProc", DownKeyProc },
911 { "StopObservingProc", StopObservingProc },
912 { "StopExaminingProc", StopExaminingProc },
913 { "UploadProc", UploadProc },
914 { "BackwardProc", BackwardProc },
915 { "ForwardProc", ForwardProc },
916 { "ToStartProc", ToStartProc },
917 { "ToEndProc", ToEndProc },
918 { "RevertProc", RevertProc },
919 { "AnnotateProc", AnnotateProc },
920 { "TruncateGameProc", TruncateGameProc },
921 { "MoveNowProc", MoveNowProc },
922 { "RetractMoveProc", RetractMoveProc },
923 { "AlwaysQueenProc", AlwaysQueenProc },
924 { "AnimateDraggingProc", AnimateDraggingProc },
925 { "AnimateMovingProc", AnimateMovingProc },
926 { "AutoflagProc", AutoflagProc },
927 { "AutoflipProc", AutoflipProc },
928 { "AutobsProc", AutobsProc },
929 { "AutoraiseProc", AutoraiseProc },
930 { "AutosaveProc", AutosaveProc },
931 { "BlindfoldProc", BlindfoldProc },
932 { "FlashMovesProc", FlashMovesProc },
933 { "FlipViewProc", FlipViewProc },
934 { "GetMoveListProc", GetMoveListProc },
936 { "HighlightDraggingProc", HighlightDraggingProc },
938 { "HighlightLastMoveProc", HighlightLastMoveProc },
939 { "IcsAlarmProc", IcsAlarmProc },
940 { "MoveSoundProc", MoveSoundProc },
941 { "OldSaveStyleProc", OldSaveStyleProc },
942 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
943 { "PonderNextMoveProc", PonderNextMoveProc },
944 { "PopupExitMessageProc", PopupExitMessageProc },
945 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
946 { "PremoveProc", PremoveProc },
947 { "QuietPlayProc", QuietPlayProc },
948 { "ShowCoordsProc", ShowCoordsProc },
949 { "ShowThinkingProc", ShowThinkingProc },
950 { "HideThinkingProc", HideThinkingProc },
951 { "TestLegalityProc", TestLegalityProc },
952 { "SaveSettingsProc", SaveSettingsProc },
953 { "SaveOnExitProc", SaveOnExitProc },
954 { "InfoProc", InfoProc },
955 { "ManProc", ManProc },
956 { "HintProc", HintProc },
957 { "BookProc", BookProc },
958 { "AboutGameProc", AboutGameProc },
959 { "AboutProc", AboutProc },
960 { "DebugProc", DebugProc },
961 { "NothingProc", NothingProc },
962 { "CommentPopDown", (XtActionProc) CommentPopDown },
963 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
964 { "TagsPopDown", (XtActionProc) TagsPopDown },
965 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
966 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
967 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
968 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
969 { "GameListPopDown", (XtActionProc) GameListPopDown },
970 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
971 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
972 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
973 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
974 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
975 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
976 { "EnginePopDown", (XtActionProc) EnginePopDown },
977 { "UciPopDown", (XtActionProc) UciPopDown },
978 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
979 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
980 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
981 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
984 char globalTranslations[] =
985 ":<Key>R: ResignProc() \n \
986 :<Key>r: ResetProc() \n \
987 :<Key>g: LoadGameProc() \n \
988 :<Key>N: LoadNextGameProc() \n \
989 :<Key>P: LoadPrevGameProc() \n \
990 :<Key>Q: QuitProc() \n \
991 :<Key>F: ToEndProc() \n \
992 :<Key>f: ForwardProc() \n \
993 :<Key>B: ToStartProc() \n \
994 :<Key>b: BackwardProc() \n \
995 :<Key>p: PauseProc() \n \
996 :<Key>d: DrawProc() \n \
997 :<Key>t: CallFlagProc() \n \
998 :<Key>i: Iconify() \n \
999 :<Key>c: Iconify() \n \
1000 :<Key>v: FlipViewProc() \n \
1001 <KeyDown>Control_L: BackwardProc() \n \
1002 <KeyUp>Control_L: ForwardProc() \n \
1003 <KeyDown>Control_R: BackwardProc() \n \
1004 <KeyUp>Control_R: ForwardProc() \n \
1005 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1006 \"Send to chess program:\",,1) \n \
1007 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1008 \"Send to second chess program:\",,2) \n";
1010 char boardTranslations[] =
1011 "<Btn1Down>: HandleUserMove() \n \
1012 <Btn1Up>: HandleUserMove() \n \
1013 <Btn1Motion>: AnimateUserMove() \n \
1014 <Btn3Motion>: HandlePV() \n \
1015 <Btn3Up>: PieceMenuPopup(menuB) \n \
1016 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1017 PieceMenuPopup(menuB) \n \
1018 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1019 PieceMenuPopup(menuW) \n \
1020 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1021 PieceMenuPopup(menuW) \n \
1022 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1023 PieceMenuPopup(menuB) \n";
1025 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1026 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1028 char ICSInputTranslations[] =
1029 "<Key>Up: UpKeyProc() \n "
1030 "<Key>Down: DownKeyProc() \n "
1031 "<Key>Return: EnterKeyProc() \n";
1033 String xboardResources[] = {
1034 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1035 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1036 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1041 /* Max possible square size */
1042 #define MAXSQSIZE 256
1044 static int xpm_avail[MAXSQSIZE];
1046 #ifdef HAVE_DIR_STRUCT
1048 /* Extract piece size from filename */
1050 xpm_getsize(name, len, ext)
1061 if ((p=strchr(name, '.')) == NULL ||
1062 StrCaseCmp(p+1, ext) != 0)
1068 while (*p && isdigit(*p))
1075 /* Setup xpm_avail */
1077 xpm_getavail(dirname, ext)
1085 for (i=0; i<MAXSQSIZE; ++i)
1088 if (appData.debugMode)
1089 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1091 dir = opendir(dirname);
1094 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1095 programName, dirname);
1099 while ((ent=readdir(dir)) != NULL) {
1100 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1101 if (i > 0 && i < MAXSQSIZE)
1111 xpm_print_avail(fp, ext)
1117 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1118 for (i=1; i<MAXSQSIZE; ++i) {
1124 /* Return XPM piecesize closest to size */
1126 xpm_closest_to(dirname, size, ext)
1132 int sm_diff = MAXSQSIZE;
1136 xpm_getavail(dirname, ext);
1138 if (appData.debugMode)
1139 xpm_print_avail(stderr, ext);
1141 for (i=1; i<MAXSQSIZE; ++i) {
1144 diff = (diff<0) ? -diff : diff;
1145 if (diff < sm_diff) {
1153 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1159 #else /* !HAVE_DIR_STRUCT */
1160 /* If we are on a system without a DIR struct, we can't
1161 read the directory, so we can't collect a list of
1162 filenames, etc., so we can't do any size-fitting. */
1164 xpm_closest_to(dirname, size, ext)
1169 fprintf(stderr, _("\
1170 Warning: No DIR structure found on this system --\n\
1171 Unable to autosize for XPM/XIM pieces.\n\
1172 Please report this error to frankm@hiwaay.net.\n\
1173 Include system type & operating system in message.\n"));
1176 #endif /* HAVE_DIR_STRUCT */
1178 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1179 "magenta", "cyan", "white" };
1183 TextColors textColors[(int)NColorClasses];
1185 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1187 parse_color(str, which)
1191 char *p, buf[100], *d;
1194 if (strlen(str) > 99) /* watch bounds on buf */
1199 for (i=0; i<which; ++i) {
1206 /* Could be looking at something like:
1208 .. in which case we want to stop on a comma also */
1209 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1213 return -1; /* Use default for empty field */
1216 if (which == 2 || isdigit(*p))
1219 while (*p && isalpha(*p))
1224 for (i=0; i<8; ++i) {
1225 if (!StrCaseCmp(buf, cnames[i]))
1226 return which? (i+40) : (i+30);
1228 if (!StrCaseCmp(buf, "default")) return -1;
1230 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1235 parse_cpair(cc, str)
1239 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1240 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1245 /* bg and attr are optional */
1246 textColors[(int)cc].bg = parse_color(str, 1);
1247 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1248 textColors[(int)cc].attr = 0;
1254 /* Arrange to catch delete-window events */
1255 Atom wm_delete_window;
1257 CatchDeleteWindow(Widget w, String procname)
1260 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1261 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1262 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1269 XtSetArg(args[0], XtNiconic, False);
1270 XtSetValues(shellWidget, args, 1);
1272 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1275 //---------------------------------------------------------------------------------------------------------
1276 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1279 #define CW_USEDEFAULT (1<<31)
1280 #define ICS_TEXT_MENU_SIZE 90
1281 #define DEBUG_FILE "xboard.debug"
1282 #define SetCurrentDirectory chdir
1283 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1287 // these two must some day move to frontend.h, when they are implemented
1288 Boolean GameListIsUp();
1290 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1293 // front-end part of option handling
1295 // [HGM] This platform-dependent table provides the location for storing the color info
1296 extern char *crWhite, * crBlack;
1300 &appData.whitePieceColor,
1301 &appData.blackPieceColor,
1302 &appData.lightSquareColor,
1303 &appData.darkSquareColor,
1304 &appData.highlightSquareColor,
1305 &appData.premoveHighlightColor,
1306 &appData.lowTimeWarningColor,
1317 // [HGM] font: keep a font for each square size, even non-stndard ones
1318 #define NUM_SIZES 18
1319 #define MAX_SIZE 130
1320 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1321 char *fontTable[NUM_FONTS][MAX_SIZE];
1324 ParseFont(char *name, int number)
1325 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1327 if(sscanf(name, "size%d:", &size)) {
1328 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1329 // defer processing it until we know if it matches our board size
1330 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1331 fontTable[number][size] = strdup(strchr(name, ':')+1);
1332 fontValid[number][size] = True;
1337 case 0: // CLOCK_FONT
1338 appData.clockFont = strdup(name);
1340 case 1: // MESSAGE_FONT
1341 appData.font = strdup(name);
1343 case 2: // COORD_FONT
1344 appData.coordFont = strdup(name);
1349 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1354 { // only 2 fonts currently
1355 appData.clockFont = CLOCK_FONT_NAME;
1356 appData.coordFont = COORD_FONT_NAME;
1357 appData.font = DEFAULT_FONT_NAME;
1362 { // no-op, until we identify the code for this already in XBoard and move it here
1366 ParseColor(int n, char *name)
1367 { // in XBoard, just copy the color-name string
1368 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1372 ParseTextAttribs(ColorClass cc, char *s)
1374 (&appData.colorShout)[cc] = strdup(s);
1378 ParseBoardSize(void *addr, char *name)
1380 appData.boardSize = strdup(name);
1385 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1389 SetCommPortDefaults()
1390 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1393 // [HGM] args: these three cases taken out to stay in front-end
1395 SaveFontArg(FILE *f, ArgDescriptor *ad)
1397 char *name, buf[MSG_SIZ];
1398 int i, n = (int)ad->argLoc;
1400 case 0: // CLOCK_FONT
1401 name = appData.clockFont;
1403 case 1: // MESSAGE_FONT
1404 name = appData.font;
1406 case 2: // COORD_FONT
1407 name = appData.coordFont;
1412 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1413 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1414 fontTable[n][squareSize] = strdup(name);
1415 fontValid[n][squareSize] = True;
1418 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1419 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1424 { // nothing to do, as the sounds are at all times represented by their text-string names already
1428 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1429 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1430 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1434 SaveColor(FILE *f, ArgDescriptor *ad)
1435 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1436 if(colorVariable[(int)ad->argLoc])
1437 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1441 SaveBoardSize(FILE *f, char *name, void *addr)
1442 { // wrapper to shield back-end from BoardSize & sizeInfo
1443 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1447 ParseCommPortSettings(char *s)
1448 { // no such option in XBoard (yet)
1451 extern Widget engineOutputShell;
1452 extern Widget tagsShell, editTagsShell;
1454 GetActualPlacement(Widget wg, WindowPlacement *wp)
1464 XtSetArg(args[i], XtNx, &x); i++;
1465 XtSetArg(args[i], XtNy, &y); i++;
1466 XtSetArg(args[i], XtNwidth, &w); i++;
1467 XtSetArg(args[i], XtNheight, &h); i++;
1468 XtGetValues(wg, args, i);
1477 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1478 // In XBoard this will have to wait until awareness of window parameters is implemented
1479 GetActualPlacement(shellWidget, &wpMain);
1480 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1481 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1482 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1483 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1484 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1485 else GetActualPlacement(editShell, &wpComment);
1486 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1487 else GetActualPlacement(editTagsShell, &wpTags);
1491 PrintCommPortSettings(FILE *f, char *name)
1492 { // This option does not exist in XBoard
1496 MySearchPath(char *installDir, char *name, char *fullname)
1497 { // just append installDir and name. Perhaps ExpandPath should be used here?
1498 name = ExpandPathName(name);
1499 if(name && name[0] == '/') strcpy(fullname, name); else {
1500 sprintf(fullname, "%s%c%s", installDir, '/', name);
1506 MyGetFullPathName(char *name, char *fullname)
1507 { // should use ExpandPath?
1508 name = ExpandPathName(name);
1509 strcpy(fullname, name);
1514 EnsureOnScreen(int *x, int *y, int minX, int minY)
1521 { // [HGM] args: allows testing if main window is realized from back-end
1522 return xBoardWindow != 0;
1526 PopUpStartupDialog()
1527 { // start menu not implemented in XBoard
1530 ConvertToLine(int argc, char **argv)
1532 static char line[128*1024], buf[1024];
1536 for(i=1; i<argc; i++) {
1537 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1538 && argv[i][0] != '{' )
1539 sprintf(buf, "{%s} ", argv[i]);
1540 else sprintf(buf, "%s ", argv[i]);
1543 line[strlen(line)-1] = NULLCHAR;
1547 //--------------------------------------------------------------------------------------------
1550 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1552 #define BoardSize int
1553 void InitDrawingSizes(BoardSize boardSize, int flags)
1554 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1555 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1557 XtGeometryResult gres;
1560 if(!formWidget) return;
1563 * Enable shell resizing.
1565 shellArgs[0].value = (XtArgVal) &w;
1566 shellArgs[1].value = (XtArgVal) &h;
1567 XtGetValues(shellWidget, shellArgs, 2);
1569 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
1570 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1571 XtSetValues(shellWidget, &shellArgs[2], 4);
1573 XtSetArg(args[0], XtNdefaultDistance, &sep);
1574 XtGetValues(formWidget, args, 1);
1576 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1577 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1580 XtSetArg(args[0], XtNwidth, boardWidth);
1581 XtSetArg(args[1], XtNheight, boardHeight);
1582 XtSetValues(boardWidget, args, 2);
1584 timerWidth = (boardWidth - sep) / 2;
1585 XtSetArg(args[0], XtNwidth, timerWidth);
1586 XtSetValues(whiteTimerWidget, args, 1);
1587 XtSetValues(blackTimerWidget, args, 1);
1589 XawFormDoLayout(formWidget, False);
1591 if (appData.titleInWindow) {
1593 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1594 XtSetArg(args[i], XtNheight, &h); i++;
1595 XtGetValues(titleWidget, args, i);
1597 w = boardWidth - 2*bor;
1599 XtSetArg(args[0], XtNwidth, &w);
1600 XtGetValues(menuBarWidget, args, 1);
1601 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1604 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1605 if (gres != XtGeometryYes && appData.debugMode) {
1607 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1608 programName, gres, w, h, wr, hr);
1612 XawFormDoLayout(formWidget, True);
1615 * Inhibit shell resizing.
1617 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
1618 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1619 shellArgs[4].value = shellArgs[2].value = w;
1620 shellArgs[5].value = shellArgs[3].value = h;
1621 XtSetValues(shellWidget, &shellArgs[0], 6);
1623 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1626 for(i=0; i<4; i++) {
1628 for(p=0; p<=(int)WhiteKing; p++)
1629 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1630 if(gameInfo.variant == VariantShogi) {
1631 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1632 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1633 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1634 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1635 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1638 if(gameInfo.variant == VariantGothic) {
1639 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1643 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1644 for(p=0; p<=(int)WhiteKing; p++)
1645 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1646 if(gameInfo.variant == VariantShogi) {
1647 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1648 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1649 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1650 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1651 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1654 if(gameInfo.variant == VariantGothic) {
1655 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1661 for(i=0; i<2; i++) {
1663 for(p=0; p<=(int)WhiteKing; p++)
1664 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1665 if(gameInfo.variant == VariantShogi) {
1666 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1667 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1668 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1669 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1670 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1673 if(gameInfo.variant == VariantGothic) {
1674 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1685 void EscapeExpand(char *p, char *q)
1686 { // [HGM] initstring: routine to shape up string arguments
1687 while(*p++ = *q++) if(p[-1] == '\\')
1689 case 'n': p[-1] = '\n'; break;
1690 case 'r': p[-1] = '\r'; break;
1691 case 't': p[-1] = '\t'; break;
1692 case '\\': p[-1] = '\\'; break;
1693 case 0: *p = 0; return;
1694 default: p[-1] = q[-1]; break;
1703 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1704 XSetWindowAttributes window_attributes;
1706 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1707 XrmValue vFrom, vTo;
1708 XtGeometryResult gres;
1711 int forceMono = False;
1713 srandom(time(0)); // [HGM] book: make random truly random
1715 setbuf(stdout, NULL);
1716 setbuf(stderr, NULL);
1719 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1720 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1724 programName = strrchr(argv[0], '/');
1725 if (programName == NULL)
1726 programName = argv[0];
1731 XtSetLanguageProc(NULL, NULL, NULL);
1732 bindtextdomain(PACKAGE, LOCALEDIR);
1733 textdomain(PACKAGE);
1737 XtAppInitialize(&appContext, "XBoard", shellOptions,
1738 XtNumber(shellOptions),
1739 &argc, argv, xboardResources, NULL, 0);
1740 appData.boardSize = "";
1741 InitAppData(ConvertToLine(argc, argv));
1743 if (p == NULL) p = "/tmp";
1744 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1745 gameCopyFilename = (char*) malloc(i);
1746 gamePasteFilename = (char*) malloc(i);
1747 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1748 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1750 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1751 clientResources, XtNumber(clientResources),
1754 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1755 static char buf[MSG_SIZ];
1756 EscapeExpand(buf, appData.initString);
1757 appData.initString = strdup(buf);
1758 EscapeExpand(buf, appData.secondInitString);
1759 appData.secondInitString = strdup(buf);
1760 EscapeExpand(buf, appData.firstComputerString);
1761 appData.firstComputerString = strdup(buf);
1762 EscapeExpand(buf, appData.secondComputerString);
1763 appData.secondComputerString = strdup(buf);
1766 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1769 if (chdir(chessDir) != 0) {
1770 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1776 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1777 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1778 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1779 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1782 setbuf(debugFP, NULL);
1785 /* [HGM,HR] make sure board size is acceptable */
1786 if(appData.NrFiles > BOARD_FILES ||
1787 appData.NrRanks > BOARD_RANKS )
1788 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1791 /* This feature does not work; animation needs a rewrite */
1792 appData.highlightDragging = FALSE;
1796 xDisplay = XtDisplay(shellWidget);
1797 xScreen = DefaultScreen(xDisplay);
1798 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1800 gameInfo.variant = StringToVariant(appData.variant);
1801 InitPosition(FALSE);
1804 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1806 if (isdigit(appData.boardSize[0])) {
1807 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1808 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1809 &fontPxlSize, &smallLayout, &tinyLayout);
1811 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1812 programName, appData.boardSize);
1816 /* Find some defaults; use the nearest known size */
1817 SizeDefaults *szd, *nearest;
1818 int distance = 99999;
1819 nearest = szd = sizeDefaults;
1820 while (szd->name != NULL) {
1821 if (abs(szd->squareSize - squareSize) < distance) {
1823 distance = abs(szd->squareSize - squareSize);
1824 if (distance == 0) break;
1828 if (i < 2) lineGap = nearest->lineGap;
1829 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1830 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1831 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1832 if (i < 6) smallLayout = nearest->smallLayout;
1833 if (i < 7) tinyLayout = nearest->tinyLayout;
1836 SizeDefaults *szd = sizeDefaults;
1837 if (*appData.boardSize == NULLCHAR) {
1838 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1839 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1842 if (szd->name == NULL) szd--;
1843 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1845 while (szd->name != NULL &&
1846 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1847 if (szd->name == NULL) {
1848 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1849 programName, appData.boardSize);
1853 squareSize = szd->squareSize;
1854 lineGap = szd->lineGap;
1855 clockFontPxlSize = szd->clockFontPxlSize;
1856 coordFontPxlSize = szd->coordFontPxlSize;
1857 fontPxlSize = szd->fontPxlSize;
1858 smallLayout = szd->smallLayout;
1859 tinyLayout = szd->tinyLayout;
1860 // [HGM] font: use defaults from settings file if available and not overruled
1862 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1863 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1864 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1865 appData.font = fontTable[MESSAGE_FONT][squareSize];
1866 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1867 appData.coordFont = fontTable[COORD_FONT][squareSize];
1869 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1870 if (strlen(appData.pixmapDirectory) > 0) {
1871 p = ExpandPathName(appData.pixmapDirectory);
1873 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1874 appData.pixmapDirectory);
1877 if (appData.debugMode) {
1878 fprintf(stderr, _("\
1879 XBoard square size (hint): %d\n\
1880 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1882 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1883 if (appData.debugMode) {
1884 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1888 /* [HR] height treated separately (hacked) */
1889 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1890 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1891 if (appData.showJail == 1) {
1892 /* Jail on top and bottom */
1893 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1894 XtSetArg(boardArgs[2], XtNheight,
1895 boardHeight + 2*(lineGap + squareSize));
1896 } else if (appData.showJail == 2) {
1898 XtSetArg(boardArgs[1], XtNwidth,
1899 boardWidth + 2*(lineGap + squareSize));
1900 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1903 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1904 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1908 * Determine what fonts to use.
1910 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1911 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1912 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1913 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1914 coordFontID = XLoadFont(xDisplay, appData.coordFont);
1915 coordFontStruct = XQueryFont(xDisplay, coordFontID);
1916 appData.font = FindFont(appData.font, fontPxlSize);
1917 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
1918 countFontStruct = XQueryFont(xDisplay, countFontID);
1919 // appData.font = FindFont(appData.font, fontPxlSize);
1921 xdb = XtDatabase(xDisplay);
1922 XrmPutStringResource(&xdb, "*font", appData.font);
1925 * Detect if there are not enough colors available and adapt.
1927 if (DefaultDepth(xDisplay, xScreen) <= 2) {
1928 appData.monoMode = True;
1931 if (!appData.monoMode) {
1932 vFrom.addr = (caddr_t) appData.lightSquareColor;
1933 vFrom.size = strlen(appData.lightSquareColor);
1934 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1935 if (vTo.addr == NULL) {
1936 appData.monoMode = True;
1939 lightSquareColor = *(Pixel *) vTo.addr;
1942 if (!appData.monoMode) {
1943 vFrom.addr = (caddr_t) appData.darkSquareColor;
1944 vFrom.size = strlen(appData.darkSquareColor);
1945 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1946 if (vTo.addr == NULL) {
1947 appData.monoMode = True;
1950 darkSquareColor = *(Pixel *) vTo.addr;
1953 if (!appData.monoMode) {
1954 vFrom.addr = (caddr_t) appData.whitePieceColor;
1955 vFrom.size = strlen(appData.whitePieceColor);
1956 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1957 if (vTo.addr == NULL) {
1958 appData.monoMode = True;
1961 whitePieceColor = *(Pixel *) vTo.addr;
1964 if (!appData.monoMode) {
1965 vFrom.addr = (caddr_t) appData.blackPieceColor;
1966 vFrom.size = strlen(appData.blackPieceColor);
1967 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1968 if (vTo.addr == NULL) {
1969 appData.monoMode = True;
1972 blackPieceColor = *(Pixel *) vTo.addr;
1976 if (!appData.monoMode) {
1977 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1978 vFrom.size = strlen(appData.highlightSquareColor);
1979 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1980 if (vTo.addr == NULL) {
1981 appData.monoMode = True;
1984 highlightSquareColor = *(Pixel *) vTo.addr;
1988 if (!appData.monoMode) {
1989 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1990 vFrom.size = strlen(appData.premoveHighlightColor);
1991 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1992 if (vTo.addr == NULL) {
1993 appData.monoMode = True;
1996 premoveHighlightColor = *(Pixel *) vTo.addr;
2001 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2004 if (appData.bitmapDirectory == NULL ||
2005 appData.bitmapDirectory[0] == NULLCHAR)
2006 appData.bitmapDirectory = DEF_BITMAP_DIR;
2009 if (appData.lowTimeWarning && !appData.monoMode) {
2010 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2011 vFrom.size = strlen(appData.lowTimeWarningColor);
2012 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2013 if (vTo.addr == NULL)
2014 appData.monoMode = True;
2016 lowTimeWarningColor = *(Pixel *) vTo.addr;
2019 if (appData.monoMode && appData.debugMode) {
2020 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2021 (unsigned long) XWhitePixel(xDisplay, xScreen),
2022 (unsigned long) XBlackPixel(xDisplay, xScreen));
2025 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2026 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2027 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2028 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2029 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2030 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2031 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2032 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2033 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2034 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2036 if (appData.colorize) {
2038 _("%s: can't parse color names; disabling colorization\n"),
2041 appData.colorize = FALSE;
2043 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2044 textColors[ColorNone].attr = 0;
2046 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2052 layoutName = "tinyLayout";
2053 } else if (smallLayout) {
2054 layoutName = "smallLayout";
2056 layoutName = "normalLayout";
2058 /* Outer layoutWidget is there only to provide a name for use in
2059 resources that depend on the layout style */
2061 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2062 layoutArgs, XtNumber(layoutArgs));
2064 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2065 formArgs, XtNumber(formArgs));
2066 XtSetArg(args[0], XtNdefaultDistance, &sep);
2067 XtGetValues(formWidget, args, 1);
2070 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2071 XtSetArg(args[0], XtNtop, XtChainTop);
2072 XtSetArg(args[1], XtNbottom, XtChainTop);
2073 XtSetArg(args[2], XtNright, XtChainLeft);
2074 XtSetValues(menuBarWidget, args, 3);
2076 widgetList[j++] = whiteTimerWidget =
2077 XtCreateWidget("whiteTime", labelWidgetClass,
2078 formWidget, timerArgs, XtNumber(timerArgs));
2079 XtSetArg(args[0], XtNfont, clockFontStruct);
2080 XtSetArg(args[1], XtNtop, XtChainTop);
2081 XtSetArg(args[2], XtNbottom, XtChainTop);
2082 XtSetValues(whiteTimerWidget, args, 3);
2084 widgetList[j++] = blackTimerWidget =
2085 XtCreateWidget("blackTime", labelWidgetClass,
2086 formWidget, timerArgs, XtNumber(timerArgs));
2087 XtSetArg(args[0], XtNfont, clockFontStruct);
2088 XtSetArg(args[1], XtNtop, XtChainTop);
2089 XtSetArg(args[2], XtNbottom, XtChainTop);
2090 XtSetValues(blackTimerWidget, args, 3);
2092 if (appData.titleInWindow) {
2093 widgetList[j++] = titleWidget =
2094 XtCreateWidget("title", labelWidgetClass, formWidget,
2095 titleArgs, XtNumber(titleArgs));
2096 XtSetArg(args[0], XtNtop, XtChainTop);
2097 XtSetArg(args[1], XtNbottom, XtChainTop);
2098 XtSetValues(titleWidget, args, 2);
2101 if (appData.showButtonBar) {
2102 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2103 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2104 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2105 XtSetArg(args[2], XtNtop, XtChainTop);
2106 XtSetArg(args[3], XtNbottom, XtChainTop);
2107 XtSetValues(buttonBarWidget, args, 4);
2110 widgetList[j++] = messageWidget =
2111 XtCreateWidget("message", labelWidgetClass, formWidget,
2112 messageArgs, XtNumber(messageArgs));
2113 XtSetArg(args[0], XtNtop, XtChainTop);
2114 XtSetArg(args[1], XtNbottom, XtChainTop);
2115 XtSetValues(messageWidget, args, 2);
2117 widgetList[j++] = boardWidget =
2118 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2119 XtNumber(boardArgs));
2121 XtManageChildren(widgetList, j);
2123 timerWidth = (boardWidth - sep) / 2;
2124 XtSetArg(args[0], XtNwidth, timerWidth);
2125 XtSetValues(whiteTimerWidget, args, 1);
2126 XtSetValues(blackTimerWidget, args, 1);
2128 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2129 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2130 XtGetValues(whiteTimerWidget, args, 2);
2132 if (appData.showButtonBar) {
2133 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2134 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2135 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2139 * formWidget uses these constraints but they are stored
2143 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2144 XtSetValues(menuBarWidget, args, i);
2145 if (appData.titleInWindow) {
2148 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2149 XtSetValues(whiteTimerWidget, args, i);
2151 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2152 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2153 XtSetValues(blackTimerWidget, args, i);
2155 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2156 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2157 XtSetValues(titleWidget, args, i);
2159 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2160 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2161 XtSetValues(messageWidget, args, i);
2162 if (appData.showButtonBar) {
2164 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2165 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2166 XtSetValues(buttonBarWidget, args, i);
2170 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2171 XtSetValues(whiteTimerWidget, args, i);
2173 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2174 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2175 XtSetValues(blackTimerWidget, args, i);
2177 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2178 XtSetValues(titleWidget, args, i);
2180 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2181 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2182 XtSetValues(messageWidget, args, i);
2183 if (appData.showButtonBar) {
2185 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2186 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2187 XtSetValues(buttonBarWidget, args, i);
2192 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2193 XtSetValues(whiteTimerWidget, args, i);
2195 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2196 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2197 XtSetValues(blackTimerWidget, args, i);
2199 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2200 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2201 XtSetValues(messageWidget, args, i);
2202 if (appData.showButtonBar) {
2204 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2205 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2206 XtSetValues(buttonBarWidget, args, i);
2210 XtSetArg(args[0], XtNfromVert, messageWidget);
2211 XtSetArg(args[1], XtNtop, XtChainTop);
2212 XtSetArg(args[2], XtNbottom, XtChainBottom);
2213 XtSetArg(args[3], XtNleft, XtChainLeft);
2214 XtSetArg(args[4], XtNright, XtChainRight);
2215 XtSetValues(boardWidget, args, 5);
2217 XtRealizeWidget(shellWidget);
2220 XtSetArg(args[0], XtNx, wpMain.x);
2221 XtSetArg(args[1], XtNy, wpMain.y);
2222 XtSetValues(shellWidget, args, 2);
2226 * Correct the width of the message and title widgets.
2227 * It is not known why some systems need the extra fudge term.
2228 * The value "2" is probably larger than needed.
2230 XawFormDoLayout(formWidget, False);
2232 #define WIDTH_FUDGE 2
2234 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2235 XtSetArg(args[i], XtNheight, &h); i++;
2236 XtGetValues(messageWidget, args, i);
2237 if (appData.showButtonBar) {
2239 XtSetArg(args[i], XtNwidth, &w); i++;
2240 XtGetValues(buttonBarWidget, args, i);
2241 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2243 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2246 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2247 if (gres != XtGeometryYes && appData.debugMode) {
2248 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2249 programName, gres, w, h, wr, hr);
2252 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2253 /* The size used for the child widget in layout lags one resize behind
2254 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2256 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2257 if (gres != XtGeometryYes && appData.debugMode) {
2258 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2259 programName, gres, w, h, wr, hr);
2262 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2263 XtSetArg(args[1], XtNright, XtChainRight);
2264 XtSetValues(messageWidget, args, 2);
2266 if (appData.titleInWindow) {
2268 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2269 XtSetArg(args[i], XtNheight, &h); i++;
2270 XtGetValues(titleWidget, args, i);
2272 w = boardWidth - 2*bor;
2274 XtSetArg(args[0], XtNwidth, &w);
2275 XtGetValues(menuBarWidget, args, 1);
2276 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2279 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2280 if (gres != XtGeometryYes && appData.debugMode) {
2282 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2283 programName, gres, w, h, wr, hr);
2286 XawFormDoLayout(formWidget, True);
2288 xBoardWindow = XtWindow(boardWidget);
2290 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2291 // not need to go into InitDrawingSizes().
2295 * Create X checkmark bitmap and initialize option menu checks.
2297 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2298 checkmark_bits, checkmark_width, checkmark_height);
2299 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2300 if (appData.alwaysPromoteToQueen) {
2301 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2304 if (appData.animateDragging) {
2305 XtSetValues(XtNameToWidget(menuBarWidget,
2306 "menuOptions.Animate Dragging"),
2309 if (appData.animate) {
2310 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2313 if (appData.autoComment) {
2314 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2317 if (appData.autoCallFlag) {
2318 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2321 if (appData.autoFlipView) {
2322 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2325 if (appData.autoObserve) {
2326 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2329 if (appData.autoRaiseBoard) {
2330 XtSetValues(XtNameToWidget(menuBarWidget,
2331 "menuOptions.Auto Raise Board"), args, 1);
2333 if (appData.autoSaveGames) {
2334 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2337 if (appData.saveGameFile[0] != NULLCHAR) {
2338 /* Can't turn this off from menu */
2339 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2341 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2345 if (appData.blindfold) {
2346 XtSetValues(XtNameToWidget(menuBarWidget,
2347 "menuOptions.Blindfold"), args, 1);
2349 if (appData.flashCount > 0) {
2350 XtSetValues(XtNameToWidget(menuBarWidget,
2351 "menuOptions.Flash Moves"),
2354 if (appData.getMoveList) {
2355 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2359 if (appData.highlightDragging) {
2360 XtSetValues(XtNameToWidget(menuBarWidget,
2361 "menuOptions.Highlight Dragging"),
2365 if (appData.highlightLastMove) {
2366 XtSetValues(XtNameToWidget(menuBarWidget,
2367 "menuOptions.Highlight Last Move"),
2370 if (appData.icsAlarm) {
2371 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2374 if (appData.ringBellAfterMoves) {
2375 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2378 if (appData.oldSaveStyle) {
2379 XtSetValues(XtNameToWidget(menuBarWidget,
2380 "menuOptions.Old Save Style"), args, 1);
2382 if (appData.periodicUpdates) {
2383 XtSetValues(XtNameToWidget(menuBarWidget,
2384 "menuOptions.Periodic Updates"), args, 1);
2386 if (appData.ponderNextMove) {
2387 XtSetValues(XtNameToWidget(menuBarWidget,
2388 "menuOptions.Ponder Next Move"), args, 1);
2390 if (appData.popupExitMessage) {
2391 XtSetValues(XtNameToWidget(menuBarWidget,
2392 "menuOptions.Popup Exit Message"), args, 1);
2394 if (appData.popupMoveErrors) {
2395 XtSetValues(XtNameToWidget(menuBarWidget,
2396 "menuOptions.Popup Move Errors"), args, 1);
2398 if (appData.premove) {
2399 XtSetValues(XtNameToWidget(menuBarWidget,
2400 "menuOptions.Premove"), args, 1);
2402 if (appData.quietPlay) {
2403 XtSetValues(XtNameToWidget(menuBarWidget,
2404 "menuOptions.Quiet Play"), args, 1);
2406 if (appData.showCoords) {
2407 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2410 if (appData.hideThinkingFromHuman) {
2411 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2414 if (appData.testLegality) {
2415 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2418 if (saveSettingsOnExit) {
2419 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2426 ReadBitmap(&wIconPixmap, "icon_white.bm",
2427 icon_white_bits, icon_white_width, icon_white_height);
2428 ReadBitmap(&bIconPixmap, "icon_black.bm",
2429 icon_black_bits, icon_black_width, icon_black_height);
2430 iconPixmap = wIconPixmap;
2432 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2433 XtSetValues(shellWidget, args, i);
2436 * Create a cursor for the board widget.
2438 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2439 XChangeWindowAttributes(xDisplay, xBoardWindow,
2440 CWCursor, &window_attributes);
2443 * Inhibit shell resizing.
2445 shellArgs[0].value = (XtArgVal) &w;
2446 shellArgs[1].value = (XtArgVal) &h;
2447 XtGetValues(shellWidget, shellArgs, 2);
2448 shellArgs[4].value = shellArgs[2].value = w;
2449 shellArgs[5].value = shellArgs[3].value = h;
2450 XtSetValues(shellWidget, &shellArgs[2], 4);
2451 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2452 marginH = h - boardHeight;
2454 CatchDeleteWindow(shellWidget, "QuitProc");
2459 if (appData.bitmapDirectory[0] != NULLCHAR) {
2466 /* Create regular pieces */
2467 if (!useImages) CreatePieces();
2472 if (appData.animate || appData.animateDragging)
2475 XtAugmentTranslations(formWidget,
2476 XtParseTranslationTable(globalTranslations));
2477 XtAugmentTranslations(boardWidget,
2478 XtParseTranslationTable(boardTranslations));
2479 XtAugmentTranslations(whiteTimerWidget,
2480 XtParseTranslationTable(whiteTranslations));
2481 XtAugmentTranslations(blackTimerWidget,
2482 XtParseTranslationTable(blackTranslations));
2484 /* Why is the following needed on some versions of X instead
2485 * of a translation? */
2486 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2487 (XtEventHandler) EventProc, NULL);
2490 /* [AS] Restore layout */
2491 if( wpMoveHistory.visible ) {
2495 if( wpEvalGraph.visible )
2500 if( wpEngineOutput.visible ) {
2501 EngineOutputPopUp();
2506 if (errorExitStatus == -1) {
2507 if (appData.icsActive) {
2508 /* We now wait until we see "login:" from the ICS before
2509 sending the logon script (problems with timestamp otherwise) */
2510 /*ICSInitScript();*/
2511 if (appData.icsInputBox) ICSInputBoxPopUp();
2515 signal(SIGWINCH, TermSizeSigHandler);
2517 signal(SIGINT, IntSigHandler);
2518 signal(SIGTERM, IntSigHandler);
2519 if (*appData.cmailGameName != NULLCHAR) {
2520 signal(SIGUSR1, CmailSigHandler);
2523 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2526 XtAppMainLoop(appContext);
2527 if (appData.debugMode) fclose(debugFP); // [DM] debug
2534 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2535 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2537 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2538 unlink(gameCopyFilename);
2539 unlink(gamePasteFilename);
2542 RETSIGTYPE TermSizeSigHandler(int sig)
2555 CmailSigHandler(sig)
2561 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2563 /* Activate call-back function CmailSigHandlerCallBack() */
2564 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2566 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2570 CmailSigHandlerCallBack(isr, closure, message, count, error)
2578 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2580 /**** end signal code ****/
2590 f = fopen(appData.icsLogon, "r");
2596 strcat(buf, appData.icsLogon);
2597 f = fopen(buf, "r");
2601 ProcessICSInitScript(f);
2608 EditCommentPopDown();
2623 if (!menuBarWidget) return;
2624 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2626 DisplayError("menuStep.Revert", 0);
2628 XtSetSensitive(w, !grey);
2630 w = XtNameToWidget(menuBarWidget, "menuStep.Annotate");
2632 DisplayError("menuStep.Annotate", 0);
2634 XtSetSensitive(w, !grey);
2639 SetMenuEnables(enab)
2643 if (!menuBarWidget) return;
2644 while (enab->name != NULL) {
2645 w = XtNameToWidget(menuBarWidget, enab->name);
2647 DisplayError(enab->name, 0);
2649 XtSetSensitive(w, enab->value);
2655 Enables icsEnables[] = {
2656 { "menuFile.Mail Move", False },
2657 { "menuFile.Reload CMail Message", False },
2658 { "menuMode.Machine Black", False },
2659 { "menuMode.Machine White", False },
2660 { "menuMode.Analysis Mode", False },
2661 { "menuMode.Analyze File", False },
2662 { "menuMode.Two Machines", False },
2664 { "menuHelp.Hint", False },
2665 { "menuHelp.Book", False },
2666 { "menuStep.Move Now", False },
2667 { "menuOptions.Periodic Updates", False },
2668 { "menuOptions.Hide Thinking", False },
2669 { "menuOptions.Ponder Next Move", False },
2671 { "menuStep.Annotate", False },
2675 Enables ncpEnables[] = {
2676 { "menuFile.Mail Move", False },
2677 { "menuFile.Reload CMail Message", False },
2678 { "menuMode.Machine White", False },
2679 { "menuMode.Machine Black", False },
2680 { "menuMode.Analysis Mode", False },
2681 { "menuMode.Analyze File", False },
2682 { "menuMode.Two Machines", False },
2683 { "menuMode.ICS Client", False },
2684 { "menuMode.ICS Input Box", False },
2685 { "Action", False },
2686 { "menuStep.Revert", False },
2687 { "menuStep.Annotate", False },
2688 { "menuStep.Move Now", False },
2689 { "menuStep.Retract Move", False },
2690 { "menuOptions.Auto Comment", False },
2691 { "menuOptions.Auto Flag", False },
2692 { "menuOptions.Auto Flip View", False },
2693 { "menuOptions.Auto Observe", False },
2694 { "menuOptions.Auto Raise Board", False },
2695 { "menuOptions.Get Move List", False },
2696 { "menuOptions.ICS Alarm", False },
2697 { "menuOptions.Move Sound", False },
2698 { "menuOptions.Quiet Play", False },
2699 { "menuOptions.Hide Thinking", False },
2700 { "menuOptions.Periodic Updates", False },
2701 { "menuOptions.Ponder Next Move", False },
2702 { "menuHelp.Hint", False },
2703 { "menuHelp.Book", False },
2707 Enables gnuEnables[] = {
2708 { "menuMode.ICS Client", False },
2709 { "menuMode.ICS Input Box", False },
2710 { "menuAction.Accept", False },
2711 { "menuAction.Decline", False },
2712 { "menuAction.Rematch", False },
2713 { "menuAction.Adjourn", False },
2714 { "menuAction.Stop Examining", False },
2715 { "menuAction.Stop Observing", False },
2716 { "menuAction.Upload to Examine", False },
2717 { "menuStep.Revert", False },
2718 { "menuStep.Annotate", False },
2719 { "menuOptions.Auto Comment", False },
2720 { "menuOptions.Auto Observe", False },
2721 { "menuOptions.Auto Raise Board", False },
2722 { "menuOptions.Get Move List", False },
2723 { "menuOptions.Premove", False },
2724 { "menuOptions.Quiet Play", False },
2726 /* The next two options rely on SetCmailMode being called *after* */
2727 /* SetGNUMode so that when GNU is being used to give hints these */
2728 /* menu options are still available */
2730 { "menuFile.Mail Move", False },
2731 { "menuFile.Reload CMail Message", False },
2735 Enables cmailEnables[] = {
2737 { "menuAction.Call Flag", False },
2738 { "menuAction.Draw", True },
2739 { "menuAction.Adjourn", False },
2740 { "menuAction.Abort", False },
2741 { "menuAction.Stop Observing", False },
2742 { "menuAction.Stop Examining", False },
2743 { "menuFile.Mail Move", True },
2744 { "menuFile.Reload CMail Message", True },
2748 Enables trainingOnEnables[] = {
2749 { "menuMode.Edit Comment", False },
2750 { "menuMode.Pause", False },
2751 { "menuStep.Forward", False },
2752 { "menuStep.Backward", False },
2753 { "menuStep.Forward to End", False },
2754 { "menuStep.Back to Start", False },
2755 { "menuStep.Move Now", False },
2756 { "menuStep.Truncate Game", False },
2760 Enables trainingOffEnables[] = {
2761 { "menuMode.Edit Comment", True },
2762 { "menuMode.Pause", True },
2763 { "menuStep.Forward", True },
2764 { "menuStep.Backward", True },
2765 { "menuStep.Forward to End", True },
2766 { "menuStep.Back to Start", True },
2767 { "menuStep.Move Now", True },
2768 { "menuStep.Truncate Game", True },
2772 Enables machineThinkingEnables[] = {
2773 { "menuFile.Load Game", False },
2774 { "menuFile.Load Next Game", False },
2775 { "menuFile.Load Previous Game", False },
2776 { "menuFile.Reload Same Game", False },
2777 { "menuFile.Paste Game", False },
2778 { "menuFile.Load Position", False },
2779 { "menuFile.Load Next Position", False },
2780 { "menuFile.Load Previous Position", False },
2781 { "menuFile.Reload Same Position", False },
2782 { "menuFile.Paste Position", False },
2783 { "menuMode.Machine White", False },
2784 { "menuMode.Machine Black", False },
2785 { "menuMode.Two Machines", False },
2786 { "menuStep.Retract Move", False },
2790 Enables userThinkingEnables[] = {
2791 { "menuFile.Load Game", True },
2792 { "menuFile.Load Next Game", True },
2793 { "menuFile.Load Previous Game", True },
2794 { "menuFile.Reload Same Game", True },
2795 { "menuFile.Paste Game", True },
2796 { "menuFile.Load Position", True },
2797 { "menuFile.Load Next Position", True },
2798 { "menuFile.Load Previous Position", True },
2799 { "menuFile.Reload Same Position", True },
2800 { "menuFile.Paste Position", True },
2801 { "menuMode.Machine White", True },
2802 { "menuMode.Machine Black", True },
2803 { "menuMode.Two Machines", True },
2804 { "menuStep.Retract Move", True },
2810 SetMenuEnables(icsEnables);
2813 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2814 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2821 SetMenuEnables(ncpEnables);
2827 SetMenuEnables(gnuEnables);
2833 SetMenuEnables(cmailEnables);
2839 SetMenuEnables(trainingOnEnables);
2840 if (appData.showButtonBar) {
2841 XtSetSensitive(buttonBarWidget, False);
2847 SetTrainingModeOff()
2849 SetMenuEnables(trainingOffEnables);
2850 if (appData.showButtonBar) {
2851 XtSetSensitive(buttonBarWidget, True);
2856 SetUserThinkingEnables()
2858 if (appData.noChessProgram) return;
2859 SetMenuEnables(userThinkingEnables);
2863 SetMachineThinkingEnables()
2865 if (appData.noChessProgram) return;
2866 SetMenuEnables(machineThinkingEnables);
2868 case MachinePlaysBlack:
2869 case MachinePlaysWhite:
2870 case TwoMachinesPlay:
2871 XtSetSensitive(XtNameToWidget(menuBarWidget,
2872 ModeToWidgetName(gameMode)), True);
2879 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2880 #define HISTORY_SIZE 64
\r
2881 static char *history[HISTORY_SIZE];
\r
2882 int histIn = 0, histP = 0;
\r
2885 SaveInHistory(char *cmd)
\r
2887 if (history[histIn] != NULL) {
\r
2888 free(history[histIn]);
\r
2889 history[histIn] = NULL;
\r
2891 if (*cmd == NULLCHAR) return;
\r
2892 history[histIn] = StrSave(cmd);
\r
2893 histIn = (histIn + 1) % HISTORY_SIZE;
\r
2894 if (history[histIn] != NULL) {
\r
2895 free(history[histIn]);
\r
2896 history[histIn] = NULL;
\r
2902 PrevInHistory(char *cmd)
\r
2905 if (histP == histIn) {
\r
2906 if (history[histIn] != NULL) free(history[histIn]);
\r
2907 history[histIn] = StrSave(cmd);
\r
2909 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
2910 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
2912 return history[histP];
\r
2918 if (histP == histIn) return NULL;
\r
2919 histP = (histP + 1) % HISTORY_SIZE;
\r
2920 return history[histP];
\r
2922 // end of borrowed code
\r
2924 #define Abs(n) ((n)<0 ? -(n) : (n))
2927 * Find a font that matches "pattern" that is as close as
2928 * possible to the targetPxlSize. Prefer fonts that are k
2929 * pixels smaller to fonts that are k pixels larger. The
2930 * pattern must be in the X Consortium standard format,
2931 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2932 * The return value should be freed with XtFree when no
2935 char *FindFont(pattern, targetPxlSize)
2939 char **fonts, *p, *best, *scalable, *scalableTail;
2940 int i, j, nfonts, minerr, err, pxlSize;
2943 char **missing_list;
2945 char *def_string, *base_fnt_lst, strInt[3];
2947 XFontStruct **fnt_list;
2949 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2950 sprintf(strInt, "%d", targetPxlSize);
2951 p = strstr(pattern, "--");
2952 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2953 strcat(base_fnt_lst, strInt);
2954 strcat(base_fnt_lst, strchr(p + 2, '-'));
2956 if ((fntSet = XCreateFontSet(xDisplay,
2960 &def_string)) == NULL) {
2962 fprintf(stderr, _("Unable to create font set.\n"));
2966 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2968 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2970 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2971 programName, pattern);
2979 for (i=0; i<nfonts; i++) {
2982 if (*p != '-') continue;
2984 if (*p == NULLCHAR) break;
2985 if (*p++ == '-') j++;
2987 if (j < 7) continue;
2990 scalable = fonts[i];
2993 err = pxlSize - targetPxlSize;
2994 if (Abs(err) < Abs(minerr) ||
2995 (minerr > 0 && err < 0 && -err == minerr)) {
3001 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3002 /* If the error is too big and there is a scalable font,
3003 use the scalable font. */
3004 int headlen = scalableTail - scalable;
3005 p = (char *) XtMalloc(strlen(scalable) + 10);
3006 while (isdigit(*scalableTail)) scalableTail++;
3007 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3009 p = (char *) XtMalloc(strlen(best) + 1);
3012 if (appData.debugMode) {
3013 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3014 pattern, targetPxlSize, p);
3017 if (missing_count > 0)
3018 XFreeStringList(missing_list);
3019 XFreeFontSet(xDisplay, fntSet);
3021 XFreeFontNames(fonts);
3028 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3029 | GCBackground | GCFunction | GCPlaneMask;
3030 XGCValues gc_values;
3033 gc_values.plane_mask = AllPlanes;
3034 gc_values.line_width = lineGap;
3035 gc_values.line_style = LineSolid;
3036 gc_values.function = GXcopy;
3038 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3039 gc_values.background = XBlackPixel(xDisplay, xScreen);
3040 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3042 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3043 gc_values.background = XWhitePixel(xDisplay, xScreen);
3044 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 XSetFont(xDisplay, coordGC, coordFontID);
3047 // [HGM] make font for holdings counts (white on black0
3048 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3049 gc_values.background = XBlackPixel(xDisplay, xScreen);
3050 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3051 XSetFont(xDisplay, countGC, countFontID);
3053 if (appData.monoMode) {
3054 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3055 gc_values.background = XWhitePixel(xDisplay, xScreen);
3056 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3058 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3059 gc_values.background = XBlackPixel(xDisplay, xScreen);
3060 lightSquareGC = wbPieceGC
3061 = XtGetGC(shellWidget, value_mask, &gc_values);
3063 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3064 gc_values.background = XWhitePixel(xDisplay, xScreen);
3065 darkSquareGC = bwPieceGC
3066 = XtGetGC(shellWidget, value_mask, &gc_values);
3068 if (DefaultDepth(xDisplay, xScreen) == 1) {
3069 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3070 gc_values.function = GXcopyInverted;
3071 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3072 gc_values.function = GXcopy;
3073 if (XBlackPixel(xDisplay, xScreen) == 1) {
3074 bwPieceGC = darkSquareGC;
3075 wbPieceGC = copyInvertedGC;
3077 bwPieceGC = copyInvertedGC;
3078 wbPieceGC = lightSquareGC;
3082 gc_values.foreground = highlightSquareColor;
3083 gc_values.background = highlightSquareColor;
3084 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3086 gc_values.foreground = premoveHighlightColor;
3087 gc_values.background = premoveHighlightColor;
3088 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3090 gc_values.foreground = lightSquareColor;
3091 gc_values.background = darkSquareColor;
3092 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3094 gc_values.foreground = darkSquareColor;
3095 gc_values.background = lightSquareColor;
3096 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3098 gc_values.foreground = jailSquareColor;
3099 gc_values.background = jailSquareColor;
3100 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3102 gc_values.foreground = whitePieceColor;
3103 gc_values.background = darkSquareColor;
3104 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3106 gc_values.foreground = whitePieceColor;
3107 gc_values.background = lightSquareColor;
3108 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3110 gc_values.foreground = whitePieceColor;
3111 gc_values.background = jailSquareColor;
3112 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3114 gc_values.foreground = blackPieceColor;
3115 gc_values.background = darkSquareColor;
3116 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3118 gc_values.foreground = blackPieceColor;
3119 gc_values.background = lightSquareColor;
3120 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3122 gc_values.foreground = blackPieceColor;
3123 gc_values.background = jailSquareColor;
3124 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3128 void loadXIM(xim, xmask, filename, dest, mask)
3141 fp = fopen(filename, "rb");
3143 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3150 for (y=0; y<h; ++y) {
3151 for (x=0; x<h; ++x) {
3156 XPutPixel(xim, x, y, blackPieceColor);
3158 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3161 XPutPixel(xim, x, y, darkSquareColor);
3163 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3166 XPutPixel(xim, x, y, whitePieceColor);
3168 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3171 XPutPixel(xim, x, y, lightSquareColor);
3173 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3179 /* create Pixmap of piece */
3180 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3182 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3185 /* create Pixmap of clipmask
3186 Note: We assume the white/black pieces have the same
3187 outline, so we make only 6 masks. This is okay
3188 since the XPM clipmask routines do the same. */
3190 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3192 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3195 /* now create the 1-bit version */
3196 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3199 values.foreground = 1;
3200 values.background = 0;
3202 /* Don't use XtGetGC, not read only */
3203 maskGC = XCreateGC(xDisplay, *mask,
3204 GCForeground | GCBackground, &values);
3205 XCopyPlane(xDisplay, temp, *mask, maskGC,
3206 0, 0, squareSize, squareSize, 0, 0, 1);
3207 XFreePixmap(xDisplay, temp);
3212 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3214 void CreateXIMPieces()
3219 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3224 /* The XSynchronize calls were copied from CreatePieces.
3225 Not sure if needed, but can't hurt */
3226 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3229 /* temp needed by loadXIM() */
3230 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3231 0, 0, ss, ss, AllPlanes, XYPixmap);
3233 if (strlen(appData.pixmapDirectory) == 0) {
3237 if (appData.monoMode) {
3238 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3242 fprintf(stderr, _("\nLoading XIMs...\n"));
3244 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3245 fprintf(stderr, "%d", piece+1);
3246 for (kind=0; kind<4; kind++) {
3247 fprintf(stderr, ".");
3248 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3249 ExpandPathName(appData.pixmapDirectory),
3250 piece <= (int) WhiteKing ? "" : "w",
3251 pieceBitmapNames[piece],
3253 ximPieceBitmap[kind][piece] =
3254 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3255 0, 0, ss, ss, AllPlanes, XYPixmap);
3256 if (appData.debugMode)
3257 fprintf(stderr, _("(File:%s:) "), buf);
3258 loadXIM(ximPieceBitmap[kind][piece],
3260 &(xpmPieceBitmap2[kind][piece]),
3261 &(ximMaskPm2[piece]));
3262 if(piece <= (int)WhiteKing)
3263 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3265 fprintf(stderr," ");
3267 /* Load light and dark squares */
3268 /* If the LSQ and DSQ pieces don't exist, we will
3269 draw them with solid squares. */
3270 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3271 if (access(buf, 0) != 0) {
3275 fprintf(stderr, _("light square "));
3277 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3278 0, 0, ss, ss, AllPlanes, XYPixmap);
3279 if (appData.debugMode)
3280 fprintf(stderr, _("(File:%s:) "), buf);
3282 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3283 fprintf(stderr, _("dark square "));
3284 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3285 ExpandPathName(appData.pixmapDirectory), ss);
3286 if (appData.debugMode)
3287 fprintf(stderr, _("(File:%s:) "), buf);
3289 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3290 0, 0, ss, ss, AllPlanes, XYPixmap);
3291 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3292 xpmJailSquare = xpmLightSquare;
3294 fprintf(stderr, _("Done.\n"));
3296 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3300 void CreateXPMPieces()
3304 u_int ss = squareSize;
3306 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3307 XpmColorSymbol symbols[4];
3309 /* The XSynchronize calls were copied from CreatePieces.
3310 Not sure if needed, but can't hurt */
3311 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3313 /* Setup translations so piece colors match square colors */
3314 symbols[0].name = "light_piece";
3315 symbols[0].value = appData.whitePieceColor;
3316 symbols[1].name = "dark_piece";
3317 symbols[1].value = appData.blackPieceColor;
3318 symbols[2].name = "light_square";
3319 symbols[2].value = appData.lightSquareColor;
3320 symbols[3].name = "dark_square";
3321 symbols[3].value = appData.darkSquareColor;
3323 attr.valuemask = XpmColorSymbols;
3324 attr.colorsymbols = symbols;
3325 attr.numsymbols = 4;
3327 if (appData.monoMode) {
3328 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3332 if (strlen(appData.pixmapDirectory) == 0) {
3333 XpmPieces* pieces = builtInXpms;
3336 while (pieces->size != squareSize && pieces->size) pieces++;
3337 if (!pieces->size) {
3338 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3341 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3342 for (kind=0; kind<4; kind++) {
3344 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3345 pieces->xpm[piece][kind],
3346 &(xpmPieceBitmap2[kind][piece]),
3347 NULL, &attr)) != 0) {
3348 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3352 if(piece <= (int) WhiteKing)
3353 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3357 xpmJailSquare = xpmLightSquare;
3361 fprintf(stderr, _("\nLoading XPMs...\n"));
3364 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3365 fprintf(stderr, "%d ", piece+1);
3366 for (kind=0; kind<4; kind++) {
3367 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3368 ExpandPathName(appData.pixmapDirectory),
3369 piece > (int) WhiteKing ? "w" : "",
3370 pieceBitmapNames[piece],
3372 if (appData.debugMode) {
3373 fprintf(stderr, _("(File:%s:) "), buf);
3375 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3376 &(xpmPieceBitmap2[kind][piece]),
3377 NULL, &attr)) != 0) {
3378 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3379 // [HGM] missing: read of unorthodox piece failed; substitute King.
3380 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3381 ExpandPathName(appData.pixmapDirectory),
3383 if (appData.debugMode) {
3384 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3386 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3387 &(xpmPieceBitmap2[kind][piece]),
3391 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3396 if(piece <= (int) WhiteKing)
3397 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3400 /* Load light and dark squares */
3401 /* If the LSQ and DSQ pieces don't exist, we will
3402 draw them with solid squares. */
3403 fprintf(stderr, _("light square "));
3404 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3405 if (access(buf, 0) != 0) {
3409 if (appData.debugMode)
3410 fprintf(stderr, _("(File:%s:) "), buf);
3412 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3413 &xpmLightSquare, NULL, &attr)) != 0) {
3414 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3417 fprintf(stderr, _("dark square "));
3418 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3419 ExpandPathName(appData.pixmapDirectory), ss);
3420 if (appData.debugMode) {
3421 fprintf(stderr, _("(File:%s:) "), buf);
3423 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3424 &xpmDarkSquare, NULL, &attr)) != 0) {
3425 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3429 xpmJailSquare = xpmLightSquare;
3430 fprintf(stderr, _("Done.\n"));
3432 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3435 #endif /* HAVE_LIBXPM */
3438 /* No built-in bitmaps */
3443 u_int ss = squareSize;
3445 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3448 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3449 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3450 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3451 pieceBitmapNames[piece],
3452 ss, kind == SOLID ? 's' : 'o');
3453 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3454 if(piece <= (int)WhiteKing)
3455 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3459 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3463 /* With built-in bitmaps */
3466 BuiltInBits* bib = builtInBits;
3469 u_int ss = squareSize;
3471 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3474 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3476 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3477 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3478 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3479 pieceBitmapNames[piece],
3480 ss, kind == SOLID ? 's' : 'o');
3481 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3482 bib->bits[kind][piece], ss, ss);
3483 if(piece <= (int)WhiteKing)
3484 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3488 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3493 void ReadBitmap(pm, name, bits, wreq, hreq)
3496 unsigned char bits[];
3502 char msg[MSG_SIZ], fullname[MSG_SIZ];
3504 if (*appData.bitmapDirectory != NULLCHAR) {
3505 strcpy(fullname, appData.bitmapDirectory);
3506 strcat(fullname, "/");
3507 strcat(fullname, name);
3508 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3509 &w, &h, pm, &x_hot, &y_hot);
3510 fprintf(stderr, "load %s\n", name);
3511 if (errcode != BitmapSuccess) {
3513 case BitmapOpenFailed:
3514 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3516 case BitmapFileInvalid:
3517 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3519 case BitmapNoMemory:
3520 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3524 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3528 fprintf(stderr, _("%s: %s...using built-in\n"),
3530 } else if (w != wreq || h != hreq) {
3532 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3533 programName, fullname, w, h, wreq, hreq);
3539 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3548 if (lineGap == 0) return;
3550 /* [HR] Split this into 2 loops for non-square boards. */
3552 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3553 gridSegments[i].x1 = 0;
3554 gridSegments[i].x2 =
3555 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3556 gridSegments[i].y1 = gridSegments[i].y2
3557 = lineGap / 2 + (i * (squareSize + lineGap));
3560 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3561 gridSegments[j + i].y1 = 0;
3562 gridSegments[j + i].y2 =
3563 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3564 gridSegments[j + i].x1 = gridSegments[j + i].x2
3565 = lineGap / 2 + (j * (squareSize + lineGap));
3569 static void MenuBarSelect(w, addr, index)
3574 XtActionProc proc = (XtActionProc) addr;
3576 (proc)(NULL, NULL, NULL, NULL);
3579 void CreateMenuBarPopup(parent, name, mb)
3589 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3592 XtSetArg(args[j], XtNleftMargin, 20); j++;
3593 XtSetArg(args[j], XtNrightMargin, 20); j++;
3595 while (mi->string != NULL) {
3596 if (strcmp(mi->string, "----") == 0) {
3597 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3600 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3601 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3603 XtAddCallback(entry, XtNcallback,
3604 (XtCallbackProc) MenuBarSelect,
3605 (caddr_t) mi->proc);
3611 Widget CreateMenuBar(mb)
3615 Widget anchor, menuBar;
3617 char menuName[MSG_SIZ];
3620 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3621 XtSetArg(args[j], XtNvSpace, 0); j++;
3622 XtSetArg(args[j], XtNborderWidth, 0); j++;
3623 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3624 formWidget, args, j);
3626 while (mb->name != NULL) {
3627 strcpy(menuName, "menu");
3628 strcat(menuName, mb->name);
3630 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3633 shortName[0] = _(mb->name)[0];
3634 shortName[1] = NULLCHAR;
3635 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3638 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3641 XtSetArg(args[j], XtNborderWidth, 0); j++;
3642 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3644 CreateMenuBarPopup(menuBar, menuName, mb);
3650 Widget CreateButtonBar(mi)
3654 Widget button, buttonBar;
3658 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3660 XtSetArg(args[j], XtNhSpace, 0); j++;
3662 XtSetArg(args[j], XtNborderWidth, 0); j++;
3663 XtSetArg(args[j], XtNvSpace, 0); j++;
3664 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3665 formWidget, args, j);
3667 while (mi->string != NULL) {
3670 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3671 XtSetArg(args[j], XtNborderWidth, 0); j++;
3673 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3674 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3675 buttonBar, args, j);
3676 XtAddCallback(button, XtNcallback,
3677 (XtCallbackProc) MenuBarSelect,
3678 (caddr_t) mi->proc);
3685 CreatePieceMenu(name, color)
3692 ChessSquare selection;
3694 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3695 boardWidget, args, 0);
3697 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3698 String item = pieceMenuStrings[color][i];
3700 if (strcmp(item, "----") == 0) {
3701 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3704 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3705 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3707 selection = pieceMenuTranslation[color][i];
3708 XtAddCallback(entry, XtNcallback,
3709 (XtCallbackProc) PieceMenuSelect,
3710 (caddr_t) selection);
3711 if (selection == WhitePawn || selection == BlackPawn) {
3712 XtSetArg(args[0], XtNpopupOnEntry, entry);
3713 XtSetValues(menu, args, 1);
3726 ChessSquare selection;
3728 whitePieceMenu = CreatePieceMenu("menuW", 0);
3729 blackPieceMenu = CreatePieceMenu("menuB", 1);
3731 XtRegisterGrabAction(PieceMenuPopup, True,
3732 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3733 GrabModeAsync, GrabModeAsync);
3735 XtSetArg(args[0], XtNlabel, _("Drop"));
3736 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3737 boardWidget, args, 1);
3738 for (i = 0; i < DROP_MENU_SIZE; i++) {
3739 String item = dropMenuStrings[i];
3741 if (strcmp(item, "----") == 0) {
3742 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3745 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3746 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3748 selection = dropMenuTranslation[i];
3749 XtAddCallback(entry, XtNcallback,
3750 (XtCallbackProc) DropMenuSelect,
3751 (caddr_t) selection);
3756 void SetupDropMenu()
3764 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3765 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3766 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3767 dmEnables[i].piece);
3768 XtSetSensitive(entry, p != NULL || !appData.testLegality
3769 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3770 && !appData.icsActive));
3772 while (p && *p++ == dmEnables[i].piece) count++;
3773 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3775 XtSetArg(args[j], XtNlabel, label); j++;
3776 XtSetValues(entry, args, j);
3780 void PieceMenuPopup(w, event, params, num_params)
3784 Cardinal *num_params;
3786 String whichMenu; int menuNr;
3787 if (event->type == ButtonRelease)
3788 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3789 else if (event->type == ButtonPress)
3790 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3792 case 0: whichMenu = params[0]; break;
3793 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3795 case -1: if (errorUp) ErrorPopDown();
3798 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3801 static void PieceMenuSelect(w, piece, junk)
3806 if (pmFromX < 0 || pmFromY < 0) return;
3807 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3810 static void DropMenuSelect(w, piece, junk)
3815 if (pmFromX < 0 || pmFromY < 0) return;
3816 DropMenuEvent(piece, pmFromX, pmFromY);
3819 void WhiteClock(w, event, prms, nprms)
3825 if (gameMode == EditPosition || gameMode == IcsExamining) {
3826 SetWhiteToPlayEvent();
3827 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3832 void BlackClock(w, event, prms, nprms)
3838 if (gameMode == EditPosition || gameMode == IcsExamining) {
3839 SetBlackToPlayEvent();
3840 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3847 * If the user selects on a border boundary, return -1; if off the board,
3848 * return -2. Otherwise map the event coordinate to the square.
3850 int EventToSquare(x, limit)
3858 if ((x % (squareSize + lineGap)) >= squareSize)
3860 x /= (squareSize + lineGap);
3866 static void do_flash_delay(msec)
3872 static void drawHighlight(file, rank, gc)
3878 if (lineGap == 0 || appData.blindfold) return;
3881 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3882 (squareSize + lineGap);
3883 y = lineGap/2 + rank * (squareSize + lineGap);
3885 x = lineGap/2 + file * (squareSize + lineGap);
3886 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3887 (squareSize + lineGap);
3890 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3891 squareSize+lineGap, squareSize+lineGap);
3894 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3895 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3898 SetHighlights(fromX, fromY, toX, toY)
3899 int fromX, fromY, toX, toY;
3901 if (hi1X != fromX || hi1Y != fromY) {
3902 if (hi1X >= 0 && hi1Y >= 0) {
3903 drawHighlight(hi1X, hi1Y, lineGC);
3905 } // [HGM] first erase both, then draw new!
3906 if (hi2X != toX || hi2Y != toY) {
3907 if (hi2X >= 0 && hi2Y >= 0) {
3908 drawHighlight(hi2X, hi2Y, lineGC);
3911 if (hi1X != fromX || hi1Y != fromY) {
3912 if (fromX >= 0 && fromY >= 0) {
3913 drawHighlight(fromX, fromY, highlineGC);
3916 if (hi2X != toX || hi2Y != toY) {
3917 if (toX >= 0 && toY >= 0) {
3918 drawHighlight(toX, toY, highlineGC);
3930 SetHighlights(-1, -1, -1, -1);
3935 SetPremoveHighlights(fromX, fromY, toX, toY)
3936 int fromX, fromY, toX, toY;
3938 if (pm1X != fromX || pm1Y != fromY) {
3939 if (pm1X >= 0 && pm1Y >= 0) {
3940 drawHighlight(pm1X, pm1Y, lineGC);
3942 if (fromX >= 0 && fromY >= 0) {
3943 drawHighlight(fromX, fromY, prelineGC);
3946 if (pm2X != toX || pm2Y != toY) {
3947 if (pm2X >= 0 && pm2Y >= 0) {
3948 drawHighlight(pm2X, pm2Y, lineGC);
3950 if (toX >= 0 && toY >= 0) {
3951 drawHighlight(toX, toY, prelineGC);
3961 ClearPremoveHighlights()
3963 SetPremoveHighlights(-1, -1, -1, -1);
3966 static void BlankSquare(x, y, color, piece, dest)
3971 if (useImages && useImageSqs) {
3975 pm = xpmLightSquare;
3980 case 2: /* neutral */
3985 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3986 squareSize, squareSize, x, y);
3996 case 2: /* neutral */
4001 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4006 I split out the routines to draw a piece so that I could
4007 make a generic flash routine.
4009 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4011 int square_color, x, y;
4014 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4015 switch (square_color) {
4017 case 2: /* neutral */
4019 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4020 ? *pieceToOutline(piece)
4021 : *pieceToSolid(piece),
4022 dest, bwPieceGC, 0, 0,
4023 squareSize, squareSize, x, y);
4026 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4027 ? *pieceToSolid(piece)
4028 : *pieceToOutline(piece),
4029 dest, wbPieceGC, 0, 0,
4030 squareSize, squareSize, x, y);
4035 static void monoDrawPiece(piece, square_color, x, y, dest)
4037 int square_color, x, y;
4040 switch (square_color) {
4042 case 2: /* neutral */
4044 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4045 ? *pieceToOutline(piece)
4046 : *pieceToSolid(piece),
4047 dest, bwPieceGC, 0, 0,
4048 squareSize, squareSize, x, y, 1);
4051 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4052 ? *pieceToSolid(piece)
4053 : *pieceToOutline(piece),
4054 dest, wbPieceGC, 0, 0,
4055 squareSize, squareSize, x, y, 1);
4060 static void colorDrawPiece(piece, square_color, x, y, dest)
4062 int square_color, x, y;
4065 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4066 switch (square_color) {
4068 XCopyPlane(xDisplay, *pieceToSolid(piece),
4069 dest, (int) piece < (int) BlackPawn
4070 ? wlPieceGC : blPieceGC, 0, 0,
4071 squareSize, squareSize, x, y, 1);
4074 XCopyPlane(xDisplay, *pieceToSolid(piece),
4075 dest, (int) piece < (int) BlackPawn
4076 ? wdPieceGC : bdPieceGC, 0, 0,
4077 squareSize, squareSize, x, y, 1);
4079 case 2: /* neutral */
4081 XCopyPlane(xDisplay, *pieceToSolid(piece),
4082 dest, (int) piece < (int) BlackPawn
4083 ? wjPieceGC : bjPieceGC, 0, 0,
4084 squareSize, squareSize, x, y, 1);
4089 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4091 int square_color, x, y;
4096 switch (square_color) {
4098 case 2: /* neutral */
4100 if ((int)piece < (int) BlackPawn) {
4108 if ((int)piece < (int) BlackPawn) {
4116 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4117 dest, wlPieceGC, 0, 0,
4118 squareSize, squareSize, x, y);
4121 typedef void (*DrawFunc)();
4123 DrawFunc ChooseDrawFunc()
4125 if (appData.monoMode) {
4126 if (DefaultDepth(xDisplay, xScreen) == 1) {
4127 return monoDrawPiece_1bit;
4129 return monoDrawPiece;
4133 return colorDrawPieceImage;
4135 return colorDrawPiece;
4139 /* [HR] determine square color depending on chess variant. */
4140 static int SquareColor(row, column)
4145 if (gameInfo.variant == VariantXiangqi) {
4146 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4148 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4150 } else if (row <= 4) {
4156 square_color = ((column + row) % 2) == 1;
4159 /* [hgm] holdings: next line makes all holdings squares light */
4160 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4162 return square_color;
4165 void DrawSquare(row, column, piece, do_flash)
4166 int row, column, do_flash;
4169 int square_color, x, y, direction, font_ascent, font_descent;
4172 XCharStruct overall;
4176 /* Calculate delay in milliseconds (2-delays per complete flash) */
4177 flash_delay = 500 / appData.flashRate;
4180 x = lineGap + ((BOARD_WIDTH-1)-column) *
4181 (squareSize + lineGap);
4182 y = lineGap + row * (squareSize + lineGap);
4184 x = lineGap + column * (squareSize + lineGap);
4185 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4186 (squareSize + lineGap);
4189 square_color = SquareColor(row, column);
4191 if ( // [HGM] holdings: blank out area between board and holdings
4192 column == BOARD_LEFT-1 || column == BOARD_RGHT
4193 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4194 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4195 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4197 // [HGM] print piece counts next to holdings
4198 string[1] = NULLCHAR;
4199 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4200 string[0] = '0' + piece;
4201 XTextExtents(countFontStruct, string, 1, &direction,
4202 &font_ascent, &font_descent, &overall);
4203 if (appData.monoMode) {
4204 XDrawImageString(xDisplay, xBoardWindow, countGC,
4205 x + squareSize - overall.width - 2,
4206 y + font_ascent + 1, string, 1);
4208 XDrawString(xDisplay, xBoardWindow, countGC,
4209 x + squareSize - overall.width - 2,
4210 y + font_ascent + 1, string, 1);
4213 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4214 string[0] = '0' + piece;
4215 XTextExtents(countFontStruct, string, 1, &direction,
4216 &font_ascent, &font_descent, &overall);
4217 if (appData.monoMode) {
4218 XDrawImageString(xDisplay, xBoardWindow, countGC,
4219 x + 2, y + font_ascent + 1, string, 1);
4221 XDrawString(xDisplay, xBoardWindow, countGC,
4222 x + 2, y + font_ascent + 1, string, 1);
4226 if (piece == EmptySquare || appData.blindfold) {
4227 BlankSquare(x, y, square_color, piece, xBoardWindow);
4229 drawfunc = ChooseDrawFunc();
4230 if (do_flash && appData.flashCount > 0) {
4231 for (i=0; i<appData.flashCount; ++i) {
4233 drawfunc(piece, square_color, x, y, xBoardWindow);
4234 XSync(xDisplay, False);
4235 do_flash_delay(flash_delay);
4237 BlankSquare(x, y, square_color, piece, xBoardWindow);
4238 XSync(xDisplay, False);
4239 do_flash_delay(flash_delay);
4242 drawfunc(piece, square_color, x, y, xBoardWindow);
4246 string[1] = NULLCHAR;
4247 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)