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 TruncateGameProc P((Widget w, XEvent *event, String *prms,
374 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
376 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
379 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
381 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
383 void AutocommProc P((Widget w, XEvent *event, String *prms,
385 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void AutobsProc P((Widget w, XEvent *event, String *prms,
389 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
394 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
397 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
399 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
401 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
405 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
407 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
409 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
411 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
413 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
417 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
419 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
421 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
423 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
424 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void DisplayMove P((int moveNumber));
435 void DisplayTitle P((char *title));
436 void ICSInitScript P((void));
437 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
438 void ErrorPopUp P((char *title, char *text, int modal));
439 void ErrorPopDown P((void));
440 static char *ExpandPathName P((char *path));
441 static void CreateAnimVars P((void));
442 static void DragPieceMove P((int x, int y));
443 static void DrawDragPiece P((void));
444 char *ModeToWidgetName P((GameMode mode));
445 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
449 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
450 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void GameListOptionsPopDown P(());
454 void ShufflePopDown P(());
455 void EnginePopDown P(());
456 void UciPopDown P(());
457 void TimeControlPopDown P(());
458 void NewVariantPopDown P(());
459 void SettingsPopDown P(());
460 void update_ics_width P(());
461 int get_term_width P(());
462 int CopyMemoProc P(());
464 * XBoard depends on Xt R4 or higher
466 int xtVersion = XtSpecificationRelease;
471 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
472 jailSquareColor, highlightSquareColor, premoveHighlightColor;
473 Pixel lowTimeWarningColor;
474 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
475 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
476 wjPieceGC, bjPieceGC, prelineGC, countGC;
477 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
478 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
479 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
480 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
481 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
482 ICSInputShell, fileNameShell, askQuestionShell;
483 Widget historyShell, evalGraphShell, gameListShell;
484 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
485 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
486 Font clockFontID, coordFontID, countFontID;
487 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
488 XtAppContext appContext;
490 char *oldICSInteractionTitle;
494 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
496 Position commentX = -1, commentY = -1;
497 Dimension commentW, commentH;
498 typedef unsigned int BoardSize;
500 Boolean chessProgram;
502 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
503 int squareSize, smallLayout = 0, tinyLayout = 0,
504 marginW, marginH, // [HGM] for run-time resizing
505 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
506 ICSInputBoxUp = False, askQuestionUp = False,
507 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
508 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
509 Pixel timerForegroundPixel, timerBackgroundPixel;
510 Pixel buttonForegroundPixel, buttonBackgroundPixel;
511 char *chessDir, *programName, *programVersion,
512 *gameCopyFilename, *gamePasteFilename;
513 Boolean alwaysOnTop = False;
514 Boolean saveSettingsOnExit;
515 char *settingsFileName;
516 char *icsTextMenuString;
518 char *firstChessProgramNames;
519 char *secondChessProgramNames;
521 WindowPlacement wpMain;
522 WindowPlacement wpConsole;
523 WindowPlacement wpComment;
524 WindowPlacement wpMoveHistory;
525 WindowPlacement wpEvalGraph;
526 WindowPlacement wpEngineOutput;
527 WindowPlacement wpGameList;
528 WindowPlacement wpTags;
532 Pixmap pieceBitmap[2][(int)BlackPawn];
533 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
534 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
535 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
536 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
537 int useImages, useImageSqs;
538 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
539 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
540 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
541 XImage *ximLightSquare, *ximDarkSquare;
544 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
545 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
547 #define White(piece) ((int)(piece) < (int)BlackPawn)
549 /* Variables for doing smooth animation. This whole thing
550 would be much easier if the board was double-buffered,
551 but that would require a fairly major rewrite. */
556 GC blitGC, pieceGC, outlineGC;
557 XPoint startSquare, prevFrame, mouseDelta;
561 int startBoardX, startBoardY;
564 /* There can be two pieces being animated at once: a player
565 can begin dragging a piece before the remote opponent has moved. */
567 static AnimState game, player;
569 /* Bitmaps for use as masks when drawing XPM pieces.
570 Need one for each black and white piece. */
571 static Pixmap xpmMask[BlackKing + 1];
573 /* This magic number is the number of intermediate frames used
574 in each half of the animation. For short moves it's reduced
575 by 1. The total number of frames will be factor * 2 + 1. */
578 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
580 MenuItem fileMenu[] = {
581 {N_("New Game"), ResetProc},
582 {N_("New Shuffle Game ..."), ShuffleMenuProc},
583 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
584 {"----", NothingProc},
585 {N_("Load Game"), LoadGameProc},
586 {N_("Load Next Game"), LoadNextGameProc},
587 {N_("Load Previous Game"), LoadPrevGameProc},
588 {N_("Reload Same Game"), ReloadGameProc},
589 {N_("Save Game"), SaveGameProc},
590 {"----", NothingProc},
591 {N_("Copy Game"), CopyGameProc},
592 {N_("Paste Game"), PasteGameProc},
593 {"----", NothingProc},
594 {N_("Load Position"), LoadPositionProc},
595 {N_("Load Next Position"), LoadNextPositionProc},
596 {N_("Load Previous Position"), LoadPrevPositionProc},
597 {N_("Reload Same Position"), ReloadPositionProc},
598 {N_("Save Position"), SavePositionProc},
599 {"----", NothingProc},
600 {N_("Copy Position"), CopyPositionProc},
601 {N_("Paste Position"), PastePositionProc},
602 {"----", NothingProc},
603 {N_("Mail Move"), MailMoveProc},
604 {N_("Reload CMail Message"), ReloadCmailMsgProc},
605 {"----", NothingProc},
606 {N_("Exit"), QuitProc},
610 MenuItem modeMenu[] = {
611 {N_("Machine White"), MachineWhiteProc},
612 {N_("Machine Black"), MachineBlackProc},
613 {N_("Two Machines"), TwoMachinesProc},
614 {N_("Analysis Mode"), AnalyzeModeProc},
615 {N_("Analyze File"), AnalyzeFileProc },
616 {N_("ICS Client"), IcsClientProc},
617 {N_("Edit Game"), EditGameProc},
618 {N_("Edit Position"), EditPositionProc},
619 {N_("Training"), TrainingProc},
620 {"----", NothingProc},
621 {N_("Show Engine Output"), EngineOutputProc},
622 {N_("Show Evaluation Graph"), EvalGraphProc},
623 {N_("Show Game List"), ShowGameListProc},
624 {N_("Show Move History"), HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
625 {"----", NothingProc},
626 {N_("Edit Tags"), EditTagsProc},
627 {N_("Edit Comment"), EditCommentProc},
628 {N_("ICS Input Box"), IcsInputBoxProc},
629 {N_("Pause"), PauseProc},
633 MenuItem actionMenu[] = {
634 {N_("Accept"), AcceptProc},
635 {N_("Decline"), DeclineProc},
636 {N_("Rematch"), RematchProc},
637 {"----", NothingProc},
638 {N_("Call Flag"), CallFlagProc},
639 {N_("Draw"), DrawProc},
640 {N_("Adjourn"), AdjournProc},
641 {N_("Abort"), AbortProc},
642 {N_("Resign"), ResignProc},
643 {"----", NothingProc},
644 {N_("Stop Observing"), StopObservingProc},
645 {N_("Stop Examining"), StopExaminingProc},
646 {N_("Upload to Examine"), UploadProc},
647 {"----", NothingProc},
648 {N_("Adjudicate to White"), AdjuWhiteProc},
649 {N_("Adjudicate to Black"), AdjuBlackProc},
650 {N_("Adjudicate Draw"), AdjuDrawProc},
654 MenuItem stepMenu[] = {
655 {N_("Backward"), BackwardProc},
656 {N_("Forward"), ForwardProc},
657 {N_("Back to Start"), ToStartProc},
658 {N_("Forward to End"), ToEndProc},
659 {N_("Revert"), RevertProc},
660 {N_("Truncate Game"), TruncateGameProc},
661 {"----", NothingProc},
662 {N_("Move Now"), MoveNowProc},
663 {N_("Retract Move"), RetractMoveProc},
667 MenuItem optionsMenu[] = {
668 {N_("Flip View"), FlipViewProc},
669 {"----", NothingProc},
670 {N_("Adjudications ..."), EngineMenuProc},
671 {N_("General Settings ..."), UciMenuProc},
672 {N_("Engine #1 Settings ..."), FirstSettingsProc},
673 {N_("Engine #2 Settings ..."), SecondSettingsProc},
674 {N_("Time Control ..."), TimeControlProc},
675 {N_("Game List ..."), GameListOptionsPopUp},
676 {"----", NothingProc},
677 {N_("Always Queen"), AlwaysQueenProc},
678 {N_("Animate Dragging"), AnimateDraggingProc},
679 {N_("Animate Moving"), AnimateMovingProc},
680 {N_("Auto Comment"), AutocommProc},
681 {N_("Auto Flag"), AutoflagProc},
682 {N_("Auto Flip View"), AutoflipProc},
683 {N_("Auto Observe"), AutobsProc},
684 {N_("Auto Raise Board"), AutoraiseProc},
685 {N_("Auto Save"), AutosaveProc},
686 {N_("Blindfold"), BlindfoldProc},
687 {N_("Flash Moves"), FlashMovesProc},
688 {N_("Get Move List"), GetMoveListProc},
690 {N_("Highlight Dragging"), HighlightDraggingProc},
692 {N_("Highlight Last Move"), HighlightLastMoveProc},
693 {N_("Move Sound"), MoveSoundProc},
694 {N_("ICS Alarm"), IcsAlarmProc},
695 {N_("Old Save Style"), OldSaveStyleProc},
696 {N_("Periodic Updates"), PeriodicUpdatesProc},
697 {N_("Ponder Next Move"), PonderNextMoveProc},
698 {N_("Popup Exit Message"), PopupExitMessageProc},
699 {N_("Popup Move Errors"), PopupMoveErrorsProc},
700 {N_("Premove"), PremoveProc},
701 {N_("Quiet Play"), QuietPlayProc},
702 {N_("Show Coords"), ShowCoordsProc},
703 {N_("Hide Thinking"), HideThinkingProc},
704 {N_("Test Legality"), TestLegalityProc},
705 {"----", NothingProc},
706 {N_("Save Settings Now"), SaveSettingsProc},
707 {N_("Save Settings on Exit"), SaveOnExitProc},
711 MenuItem helpMenu[] = {
712 {N_("Info XBoard"), InfoProc},
713 {N_("Man XBoard"), ManProc},
714 {"----", NothingProc},
715 {N_("Hint"), HintProc},
716 {N_("Book"), BookProc},
717 {"----", NothingProc},
718 {N_("About XBoard"), AboutProc},
723 {N_("File"), fileMenu},
724 {N_("Mode"), modeMenu},
725 {N_("Action"), actionMenu},
726 {N_("Step"), stepMenu},
727 {N_("Options"), optionsMenu},
728 {N_("Help"), helpMenu},
732 #define PAUSE_BUTTON N_("P")
733 MenuItem buttonBar[] = {
736 {PAUSE_BUTTON, PauseProc},
742 #define PIECE_MENU_SIZE 18
743 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
744 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
745 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
746 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
747 N_("Empty square"), N_("Clear board") },
748 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
749 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
750 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
751 N_("Empty square"), N_("Clear board") }
753 /* must be in same order as PieceMenuStrings! */
754 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
755 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
756 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
757 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
758 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
759 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
760 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
761 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
762 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
765 #define DROP_MENU_SIZE 6
766 String dropMenuStrings[DROP_MENU_SIZE] = {
767 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
769 /* must be in same order as PieceMenuStrings! */
770 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
771 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
772 WhiteRook, WhiteQueen
780 DropMenuEnables dmEnables[] = {
798 { XtNborderWidth, 0 },
799 { XtNdefaultDistance, 0 },
803 { XtNborderWidth, 0 },
804 { XtNresizable, (XtArgVal) True },
808 { XtNborderWidth, 0 },
814 { XtNjustify, (XtArgVal) XtJustifyRight },
815 { XtNlabel, (XtArgVal) "..." },
816 { XtNresizable, (XtArgVal) True },
817 { XtNresize, (XtArgVal) False }
820 Arg messageArgs[] = {
821 { XtNjustify, (XtArgVal) XtJustifyLeft },
822 { XtNlabel, (XtArgVal) "..." },
823 { XtNresizable, (XtArgVal) True },
824 { XtNresize, (XtArgVal) False }
828 { XtNborderWidth, 0 },
829 { XtNjustify, (XtArgVal) XtJustifyLeft }
832 XtResource clientResources[] = {
833 { "flashCount", "flashCount", XtRInt, sizeof(int),
834 XtOffset(AppDataPtr, flashCount), XtRImmediate,
835 (XtPointer) FLASH_COUNT },
838 XrmOptionDescRec shellOptions[] = {
839 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
840 { "-flash", "flashCount", XrmoptionNoArg, "3" },
841 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
844 XtActionsRec boardActions[] = {
845 { "DrawPosition", DrawPositionProc },
846 { "HandleUserMove", HandleUserMove },
847 { "AnimateUserMove", AnimateUserMove },
848 { "HandlePV", HandlePV },
849 { "UnLoadPV", UnLoadPV },
850 { "FileNameAction", FileNameAction },
851 { "AskQuestionProc", AskQuestionProc },
852 { "AskQuestionReplyAction", AskQuestionReplyAction },
853 { "PieceMenuPopup", PieceMenuPopup },
854 { "WhiteClock", WhiteClock },
855 { "BlackClock", BlackClock },
856 { "Iconify", Iconify },
857 { "ResetProc", ResetProc },
858 { "LoadGameProc", LoadGameProc },
859 { "LoadNextGameProc", LoadNextGameProc },
860 { "LoadPrevGameProc", LoadPrevGameProc },
861 { "LoadSelectedProc", LoadSelectedProc },
862 { "SetFilterProc", SetFilterProc },
863 { "ReloadGameProc", ReloadGameProc },
864 { "LoadPositionProc", LoadPositionProc },
865 { "LoadNextPositionProc", LoadNextPositionProc },
866 { "LoadPrevPositionProc", LoadPrevPositionProc },
867 { "ReloadPositionProc", ReloadPositionProc },
868 { "CopyPositionProc", CopyPositionProc },
869 { "PastePositionProc", PastePositionProc },
870 { "CopyGameProc", CopyGameProc },
871 { "PasteGameProc", PasteGameProc },
872 { "SaveGameProc", SaveGameProc },
873 { "SavePositionProc", SavePositionProc },
874 { "MailMoveProc", MailMoveProc },
875 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
876 { "QuitProc", QuitProc },
877 { "MachineWhiteProc", MachineWhiteProc },
878 { "MachineBlackProc", MachineBlackProc },
879 { "AnalysisModeProc", AnalyzeModeProc },
880 { "AnalyzeFileProc", AnalyzeFileProc },
881 { "TwoMachinesProc", TwoMachinesProc },
882 { "IcsClientProc", IcsClientProc },
883 { "EditGameProc", EditGameProc },
884 { "EditPositionProc", EditPositionProc },
885 { "TrainingProc", EditPositionProc },
886 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
887 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
888 { "ShowGameListProc", ShowGameListProc },
889 { "ShowMoveListProc", HistoryShowProc},
890 { "EditTagsProc", EditCommentProc },
891 { "EditCommentProc", EditCommentProc },
892 { "IcsAlarmProc", IcsAlarmProc },
893 { "IcsInputBoxProc", IcsInputBoxProc },
894 { "PauseProc", PauseProc },
895 { "AcceptProc", AcceptProc },
896 { "DeclineProc", DeclineProc },
897 { "RematchProc", RematchProc },
898 { "CallFlagProc", CallFlagProc },
899 { "DrawProc", DrawProc },
900 { "AdjournProc", AdjournProc },
901 { "AbortProc", AbortProc },
902 { "ResignProc", ResignProc },
903 { "AdjuWhiteProc", AdjuWhiteProc },
904 { "AdjuBlackProc", AdjuBlackProc },
905 { "AdjuDrawProc", AdjuDrawProc },
906 { "EnterKeyProc", EnterKeyProc },
907 { "UpKeyProc", UpKeyProc },
908 { "DownKeyProc", DownKeyProc },
909 { "StopObservingProc", StopObservingProc },
910 { "StopExaminingProc", StopExaminingProc },
911 { "UploadProc", UploadProc },
912 { "BackwardProc", BackwardProc },
913 { "ForwardProc", ForwardProc },
914 { "ToStartProc", ToStartProc },
915 { "ToEndProc", ToEndProc },
916 { "RevertProc", RevertProc },
917 { "TruncateGameProc", TruncateGameProc },
918 { "MoveNowProc", MoveNowProc },
919 { "RetractMoveProc", RetractMoveProc },
920 { "AlwaysQueenProc", AlwaysQueenProc },
921 { "AnimateDraggingProc", AnimateDraggingProc },
922 { "AnimateMovingProc", AnimateMovingProc },
923 { "AutoflagProc", AutoflagProc },
924 { "AutoflipProc", AutoflipProc },
925 { "AutobsProc", AutobsProc },
926 { "AutoraiseProc", AutoraiseProc },
927 { "AutosaveProc", AutosaveProc },
928 { "BlindfoldProc", BlindfoldProc },
929 { "FlashMovesProc", FlashMovesProc },
930 { "FlipViewProc", FlipViewProc },
931 { "GetMoveListProc", GetMoveListProc },
933 { "HighlightDraggingProc", HighlightDraggingProc },
935 { "HighlightLastMoveProc", HighlightLastMoveProc },
936 { "IcsAlarmProc", IcsAlarmProc },
937 { "MoveSoundProc", MoveSoundProc },
938 { "OldSaveStyleProc", OldSaveStyleProc },
939 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
940 { "PonderNextMoveProc", PonderNextMoveProc },
941 { "PopupExitMessageProc", PopupExitMessageProc },
942 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
943 { "PremoveProc", PremoveProc },
944 { "QuietPlayProc", QuietPlayProc },
945 { "ShowCoordsProc", ShowCoordsProc },
946 { "ShowThinkingProc", ShowThinkingProc },
947 { "HideThinkingProc", HideThinkingProc },
948 { "TestLegalityProc", TestLegalityProc },
949 { "SaveSettingsProc", SaveSettingsProc },
950 { "SaveOnExitProc", SaveOnExitProc },
951 { "InfoProc", InfoProc },
952 { "ManProc", ManProc },
953 { "HintProc", HintProc },
954 { "BookProc", BookProc },
955 { "AboutGameProc", AboutGameProc },
956 { "AboutProc", AboutProc },
957 { "DebugProc", DebugProc },
958 { "NothingProc", NothingProc },
959 { "CommentPopDown", (XtActionProc) CommentPopDown },
960 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
961 { "TagsPopDown", (XtActionProc) TagsPopDown },
962 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
963 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
964 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
965 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
966 { "GameListPopDown", (XtActionProc) GameListPopDown },
967 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
968 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
969 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
970 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
971 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
972 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
973 { "EnginePopDown", (XtActionProc) EnginePopDown },
974 { "UciPopDown", (XtActionProc) UciPopDown },
975 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
976 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
977 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
978 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
981 char globalTranslations[] =
982 ":<Key>R: ResignProc() \n \
983 :<Key>r: ResetProc() \n \
984 :<Key>g: LoadGameProc() \n \
985 :<Key>N: LoadNextGameProc() \n \
986 :<Key>P: LoadPrevGameProc() \n \
987 :<Key>Q: QuitProc() \n \
988 :<Key>F: ToEndProc() \n \
989 :<Key>f: ForwardProc() \n \
990 :<Key>B: ToStartProc() \n \
991 :<Key>b: BackwardProc() \n \
992 :<Key>p: PauseProc() \n \
993 :<Key>d: DrawProc() \n \
994 :<Key>t: CallFlagProc() \n \
995 :<Key>i: Iconify() \n \
996 :<Key>c: Iconify() \n \
997 :<Key>v: FlipViewProc() \n \
998 <KeyDown>Control_L: BackwardProc() \n \
999 <KeyUp>Control_L: ForwardProc() \n \
1000 <KeyDown>Control_R: BackwardProc() \n \
1001 <KeyUp>Control_R: ForwardProc() \n \
1002 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1003 \"Send to chess program:\",,1) \n \
1004 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1005 \"Send to second chess program:\",,2) \n";
1007 char boardTranslations[] =
1008 "<Btn1Down>: HandleUserMove() \n \
1009 <Btn1Up>: HandleUserMove() \n \
1010 <Btn1Motion>: AnimateUserMove() \n \
1011 <Btn3Motion>: HandlePV() \n \
1012 <Btn3Up>: PieceMenuPopup(menuB) \n \
1013 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1014 PieceMenuPopup(menuB) \n \
1015 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1016 PieceMenuPopup(menuW) \n \
1017 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1018 PieceMenuPopup(menuW) \n \
1019 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1020 PieceMenuPopup(menuB) \n";
1022 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1023 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1025 char ICSInputTranslations[] =
1026 "<Key>Up: UpKeyProc() \n "
1027 "<Key>Down: DownKeyProc() \n "
1028 "<Key>Return: EnterKeyProc() \n";
1030 String xboardResources[] = {
1031 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1032 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1033 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1038 /* Max possible square size */
1039 #define MAXSQSIZE 256
1041 static int xpm_avail[MAXSQSIZE];
1043 #ifdef HAVE_DIR_STRUCT
1045 /* Extract piece size from filename */
1047 xpm_getsize(name, len, ext)
1058 if ((p=strchr(name, '.')) == NULL ||
1059 StrCaseCmp(p+1, ext) != 0)
1065 while (*p && isdigit(*p))
1072 /* Setup xpm_avail */
1074 xpm_getavail(dirname, ext)
1082 for (i=0; i<MAXSQSIZE; ++i)
1085 if (appData.debugMode)
1086 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1088 dir = opendir(dirname);
1091 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1092 programName, dirname);
1096 while ((ent=readdir(dir)) != NULL) {
1097 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1098 if (i > 0 && i < MAXSQSIZE)
1108 xpm_print_avail(fp, ext)
1114 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1115 for (i=1; i<MAXSQSIZE; ++i) {
1121 /* Return XPM piecesize closest to size */
1123 xpm_closest_to(dirname, size, ext)
1129 int sm_diff = MAXSQSIZE;
1133 xpm_getavail(dirname, ext);
1135 if (appData.debugMode)
1136 xpm_print_avail(stderr, ext);
1138 for (i=1; i<MAXSQSIZE; ++i) {
1141 diff = (diff<0) ? -diff : diff;
1142 if (diff < sm_diff) {
1150 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1156 #else /* !HAVE_DIR_STRUCT */
1157 /* If we are on a system without a DIR struct, we can't
1158 read the directory, so we can't collect a list of
1159 filenames, etc., so we can't do any size-fitting. */
1161 xpm_closest_to(dirname, size, ext)
1166 fprintf(stderr, _("\
1167 Warning: No DIR structure found on this system --\n\
1168 Unable to autosize for XPM/XIM pieces.\n\
1169 Please report this error to frankm@hiwaay.net.\n\
1170 Include system type & operating system in message.\n"));
1173 #endif /* HAVE_DIR_STRUCT */
1175 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1176 "magenta", "cyan", "white" };
1180 TextColors textColors[(int)NColorClasses];
1182 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1184 parse_color(str, which)
1188 char *p, buf[100], *d;
1191 if (strlen(str) > 99) /* watch bounds on buf */
1196 for (i=0; i<which; ++i) {
1203 /* Could be looking at something like:
1205 .. in which case we want to stop on a comma also */
1206 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1210 return -1; /* Use default for empty field */
1213 if (which == 2 || isdigit(*p))
1216 while (*p && isalpha(*p))
1221 for (i=0; i<8; ++i) {
1222 if (!StrCaseCmp(buf, cnames[i]))
1223 return which? (i+40) : (i+30);
1225 if (!StrCaseCmp(buf, "default")) return -1;
1227 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1232 parse_cpair(cc, str)
1236 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1237 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1242 /* bg and attr are optional */
1243 textColors[(int)cc].bg = parse_color(str, 1);
1244 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1245 textColors[(int)cc].attr = 0;
1251 /* Arrange to catch delete-window events */
1252 Atom wm_delete_window;
1254 CatchDeleteWindow(Widget w, String procname)
1257 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1258 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1259 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1266 XtSetArg(args[0], XtNiconic, False);
1267 XtSetValues(shellWidget, args, 1);
1269 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1272 //---------------------------------------------------------------------------------------------------------
1273 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1276 #define CW_USEDEFAULT (1<<31)
1277 #define ICS_TEXT_MENU_SIZE 90
1278 #define DEBUG_FILE "xboard.debug"
1279 #define SetCurrentDirectory chdir
1280 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1284 // these two must some day move to frontend.h, when they are implemented
1285 Boolean GameListIsUp();
1287 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1290 // front-end part of option handling
1292 // [HGM] This platform-dependent table provides the location for storing the color info
1293 extern char *crWhite, * crBlack;
1297 &appData.whitePieceColor,
1298 &appData.blackPieceColor,
1299 &appData.lightSquareColor,
1300 &appData.darkSquareColor,
1301 &appData.highlightSquareColor,
1302 &appData.premoveHighlightColor,
1303 &appData.lowTimeWarningColor,
1314 // [HGM] font: keep a font for each square size, even non-stndard ones
1315 #define NUM_SIZES 18
1316 #define MAX_SIZE 130
1317 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1318 char *fontTable[NUM_FONTS][MAX_SIZE];
1321 ParseFont(char *name, int number)
1322 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1324 if(sscanf(name, "size%d:", &size)) {
1325 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1326 // defer processing it until we know if it matches our board size
1327 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1328 fontTable[number][size] = strdup(strchr(name, ':')+1);
1329 fontValid[number][size] = True;
1334 case 0: // CLOCK_FONT
1335 appData.clockFont = strdup(name);
1337 case 1: // MESSAGE_FONT
1338 appData.font = strdup(name);
1340 case 2: // COORD_FONT
1341 appData.coordFont = strdup(name);
1346 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1351 { // only 2 fonts currently
1352 appData.clockFont = CLOCK_FONT_NAME;
1353 appData.coordFont = COORD_FONT_NAME;
1354 appData.font = DEFAULT_FONT_NAME;
1359 { // no-op, until we identify the code for this already in XBoard and move it here
1363 ParseColor(int n, char *name)
1364 { // in XBoard, just copy the color-name string
1365 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1369 ParseTextAttribs(ColorClass cc, char *s)
1371 (&appData.colorShout)[cc] = strdup(s);
1375 ParseBoardSize(void *addr, char *name)
1377 appData.boardSize = strdup(name);
1382 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1386 SetCommPortDefaults()
1387 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1390 // [HGM] args: these three cases taken out to stay in front-end
1392 SaveFontArg(FILE *f, ArgDescriptor *ad)
1394 char *name, buf[MSG_SIZ];
1395 int i, n = (int)ad->argLoc;
1397 case 0: // CLOCK_FONT
1398 name = appData.clockFont;
1400 case 1: // MESSAGE_FONT
1401 name = appData.font;
1403 case 2: // COORD_FONT
1404 name = appData.coordFont;
1409 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1410 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1411 fontTable[n][squareSize] = strdup(name);
1412 fontValid[n][squareSize] = True;
1415 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1416 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1421 { // nothing to do, as the sounds are at all times represented by their text-string names already
1425 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1426 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1427 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1431 SaveColor(FILE *f, ArgDescriptor *ad)
1432 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1433 if(colorVariable[(int)ad->argLoc])
1434 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1438 SaveBoardSize(FILE *f, char *name, void *addr)
1439 { // wrapper to shield back-end from BoardSize & sizeInfo
1440 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1444 ParseCommPortSettings(char *s)
1445 { // no such option in XBoard (yet)
1448 extern Widget engineOutputShell;
1449 extern Widget tagsShell, editTagsShell;
1451 GetActualPlacement(Widget wg, WindowPlacement *wp)
1461 XtSetArg(args[i], XtNx, &x); i++;
1462 XtSetArg(args[i], XtNy, &y); i++;
1463 XtSetArg(args[i], XtNwidth, &w); i++;
1464 XtSetArg(args[i], XtNheight, &h); i++;
1465 XtGetValues(wg, args, i);
1474 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1475 // In XBoard this will have to wait until awareness of window parameters is implemented
1476 GetActualPlacement(shellWidget, &wpMain);
1477 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1478 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1479 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1480 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1481 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1482 else GetActualPlacement(editShell, &wpComment);
1483 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1484 else GetActualPlacement(editTagsShell, &wpTags);
1488 PrintCommPortSettings(FILE *f, char *name)
1489 { // This option does not exist in XBoard
1493 MySearchPath(char *installDir, char *name, char *fullname)
1494 { // just append installDir and name. Perhaps ExpandPath should be used here?
1495 name = ExpandPathName(name);
1496 if(name && name[0] == '/') strcpy(fullname, name); else {
1497 sprintf(fullname, "%s%c%s", installDir, '/', name);
1503 MyGetFullPathName(char *name, char *fullname)
1504 { // should use ExpandPath?
1505 name = ExpandPathName(name);
1506 strcpy(fullname, name);
1511 EnsureOnScreen(int *x, int *y, int minX, int minY)
1518 { // [HGM] args: allows testing if main window is realized from back-end
1519 return xBoardWindow != 0;
1523 PopUpStartupDialog()
1524 { // start menu not implemented in XBoard
1527 ConvertToLine(int argc, char **argv)
1529 static char line[128*1024], buf[1024];
1533 for(i=1; i<argc; i++) {
1534 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1535 && argv[i][0] != '{' )
1536 sprintf(buf, "{%s} ", argv[i]);
1537 else sprintf(buf, "%s ", argv[i]);
1540 line[strlen(line)-1] = NULLCHAR;
1544 //--------------------------------------------------------------------------------------------
1547 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1549 #define BoardSize int
1550 void InitDrawingSizes(BoardSize boardSize, int flags)
1551 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1552 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1554 XtGeometryResult gres;
1557 if(!formWidget) return;
1560 * Enable shell resizing.
1562 shellArgs[0].value = (XtArgVal) &w;
1563 shellArgs[1].value = (XtArgVal) &h;
1564 XtGetValues(shellWidget, shellArgs, 2);
1566 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
1567 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1568 XtSetValues(shellWidget, &shellArgs[2], 4);
1570 XtSetArg(args[0], XtNdefaultDistance, &sep);
1571 XtGetValues(formWidget, args, 1);
1573 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1574 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1577 XtSetArg(args[0], XtNwidth, boardWidth);
1578 XtSetArg(args[1], XtNheight, boardHeight);
1579 XtSetValues(boardWidget, args, 2);
1581 timerWidth = (boardWidth - sep) / 2;
1582 XtSetArg(args[0], XtNwidth, timerWidth);
1583 XtSetValues(whiteTimerWidget, args, 1);
1584 XtSetValues(blackTimerWidget, args, 1);
1586 XawFormDoLayout(formWidget, False);
1588 if (appData.titleInWindow) {
1590 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1591 XtSetArg(args[i], XtNheight, &h); i++;
1592 XtGetValues(titleWidget, args, i);
1594 w = boardWidth - 2*bor;
1596 XtSetArg(args[0], XtNwidth, &w);
1597 XtGetValues(menuBarWidget, args, 1);
1598 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1601 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1602 if (gres != XtGeometryYes && appData.debugMode) {
1604 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1605 programName, gres, w, h, wr, hr);
1609 XawFormDoLayout(formWidget, True);
1612 * Inhibit shell resizing.
1614 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
1615 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1616 shellArgs[4].value = shellArgs[2].value = w;
1617 shellArgs[5].value = shellArgs[3].value = h;
1618 XtSetValues(shellWidget, &shellArgs[0], 6);
1620 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1623 for(i=0; i<4; i++) {
1625 for(p=0; p<=(int)WhiteKing; p++)
1626 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1627 if(gameInfo.variant == VariantShogi) {
1628 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1629 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1630 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1631 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1632 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1635 if(gameInfo.variant == VariantGothic) {
1636 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1640 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1641 for(p=0; p<=(int)WhiteKing; p++)
1642 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1643 if(gameInfo.variant == VariantShogi) {
1644 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1645 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1646 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1647 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1648 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1651 if(gameInfo.variant == VariantGothic) {
1652 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1658 for(i=0; i<2; i++) {
1660 for(p=0; p<=(int)WhiteKing; p++)
1661 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1662 if(gameInfo.variant == VariantShogi) {
1663 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1664 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1665 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1666 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1667 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1670 if(gameInfo.variant == VariantGothic) {
1671 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1682 void EscapeExpand(char *p, char *q)
1683 { // [HGM] initstring: routine to shape up string arguments
1684 while(*p++ = *q++) if(p[-1] == '\\')
1686 case 'n': p[-1] = '\n'; break;
1687 case 'r': p[-1] = '\r'; break;
1688 case 't': p[-1] = '\t'; break;
1689 case '\\': p[-1] = '\\'; break;
1690 case 0: *p = 0; return;
1691 default: p[-1] = q[-1]; break;
1700 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1701 XSetWindowAttributes window_attributes;
1703 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1704 XrmValue vFrom, vTo;
1705 XtGeometryResult gres;
1708 int forceMono = False;
1710 srandom(time(0)); // [HGM] book: make random truly random
1712 setbuf(stdout, NULL);
1713 setbuf(stderr, NULL);
1716 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1717 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1721 programName = strrchr(argv[0], '/');
1722 if (programName == NULL)
1723 programName = argv[0];
1728 XtSetLanguageProc(NULL, NULL, NULL);
1729 bindtextdomain(PACKAGE, LOCALEDIR);
1730 textdomain(PACKAGE);
1734 XtAppInitialize(&appContext, "XBoard", shellOptions,
1735 XtNumber(shellOptions),
1736 &argc, argv, xboardResources, NULL, 0);
1737 appData.boardSize = "";
1738 InitAppData(ConvertToLine(argc, argv));
1740 if (p == NULL) p = "/tmp";
1741 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1742 gameCopyFilename = (char*) malloc(i);
1743 gamePasteFilename = (char*) malloc(i);
1744 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1745 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1747 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1748 clientResources, XtNumber(clientResources),
1751 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1752 static char buf[MSG_SIZ];
1753 EscapeExpand(buf, appData.initString);
1754 appData.initString = strdup(buf);
1755 EscapeExpand(buf, appData.secondInitString);
1756 appData.secondInitString = strdup(buf);
1757 EscapeExpand(buf, appData.firstComputerString);
1758 appData.firstComputerString = strdup(buf);
1759 EscapeExpand(buf, appData.secondComputerString);
1760 appData.secondComputerString = strdup(buf);
1763 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1766 if (chdir(chessDir) != 0) {
1767 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1773 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1774 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1775 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1776 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1779 setbuf(debugFP, NULL);
1782 /* [HGM,HR] make sure board size is acceptable */
1783 if(appData.NrFiles > BOARD_FILES ||
1784 appData.NrRanks > BOARD_RANKS )
1785 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1788 /* This feature does not work; animation needs a rewrite */
1789 appData.highlightDragging = FALSE;
1793 xDisplay = XtDisplay(shellWidget);
1794 xScreen = DefaultScreen(xDisplay);
1795 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1797 gameInfo.variant = StringToVariant(appData.variant);
1798 InitPosition(FALSE);
1801 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1803 if (isdigit(appData.boardSize[0])) {
1804 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1805 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1806 &fontPxlSize, &smallLayout, &tinyLayout);
1808 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1809 programName, appData.boardSize);
1813 /* Find some defaults; use the nearest known size */
1814 SizeDefaults *szd, *nearest;
1815 int distance = 99999;
1816 nearest = szd = sizeDefaults;
1817 while (szd->name != NULL) {
1818 if (abs(szd->squareSize - squareSize) < distance) {
1820 distance = abs(szd->squareSize - squareSize);
1821 if (distance == 0) break;
1825 if (i < 2) lineGap = nearest->lineGap;
1826 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1827 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1828 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1829 if (i < 6) smallLayout = nearest->smallLayout;
1830 if (i < 7) tinyLayout = nearest->tinyLayout;
1833 SizeDefaults *szd = sizeDefaults;
1834 if (*appData.boardSize == NULLCHAR) {
1835 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1836 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1839 if (szd->name == NULL) szd--;
1840 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1842 while (szd->name != NULL &&
1843 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1844 if (szd->name == NULL) {
1845 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1846 programName, appData.boardSize);
1850 squareSize = szd->squareSize;
1851 lineGap = szd->lineGap;
1852 clockFontPxlSize = szd->clockFontPxlSize;
1853 coordFontPxlSize = szd->coordFontPxlSize;
1854 fontPxlSize = szd->fontPxlSize;
1855 smallLayout = szd->smallLayout;
1856 tinyLayout = szd->tinyLayout;
1857 // [HGM] font: use defaults from settings file if available and not overruled
1859 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1860 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1861 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1862 appData.font = fontTable[MESSAGE_FONT][squareSize];
1863 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1864 appData.coordFont = fontTable[COORD_FONT][squareSize];
1866 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1867 if (strlen(appData.pixmapDirectory) > 0) {
1868 p = ExpandPathName(appData.pixmapDirectory);
1870 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1871 appData.pixmapDirectory);
1874 if (appData.debugMode) {
1875 fprintf(stderr, _("\
1876 XBoard square size (hint): %d\n\
1877 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1879 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1880 if (appData.debugMode) {
1881 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1885 /* [HR] height treated separately (hacked) */
1886 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1887 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1888 if (appData.showJail == 1) {
1889 /* Jail on top and bottom */
1890 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1891 XtSetArg(boardArgs[2], XtNheight,
1892 boardHeight + 2*(lineGap + squareSize));
1893 } else if (appData.showJail == 2) {
1895 XtSetArg(boardArgs[1], XtNwidth,
1896 boardWidth + 2*(lineGap + squareSize));
1897 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1900 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1901 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1905 * Determine what fonts to use.
1907 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1908 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1909 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1910 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1911 coordFontID = XLoadFont(xDisplay, appData.coordFont);
1912 coordFontStruct = XQueryFont(xDisplay, coordFontID);
1913 appData.font = FindFont(appData.font, fontPxlSize);
1914 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
1915 countFontStruct = XQueryFont(xDisplay, countFontID);
1916 // appData.font = FindFont(appData.font, fontPxlSize);
1918 xdb = XtDatabase(xDisplay);
1919 XrmPutStringResource(&xdb, "*font", appData.font);
1922 * Detect if there are not enough colors available and adapt.
1924 if (DefaultDepth(xDisplay, xScreen) <= 2) {
1925 appData.monoMode = True;
1928 if (!appData.monoMode) {
1929 vFrom.addr = (caddr_t) appData.lightSquareColor;
1930 vFrom.size = strlen(appData.lightSquareColor);
1931 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1932 if (vTo.addr == NULL) {
1933 appData.monoMode = True;
1936 lightSquareColor = *(Pixel *) vTo.addr;
1939 if (!appData.monoMode) {
1940 vFrom.addr = (caddr_t) appData.darkSquareColor;
1941 vFrom.size = strlen(appData.darkSquareColor);
1942 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1943 if (vTo.addr == NULL) {
1944 appData.monoMode = True;
1947 darkSquareColor = *(Pixel *) vTo.addr;
1950 if (!appData.monoMode) {
1951 vFrom.addr = (caddr_t) appData.whitePieceColor;
1952 vFrom.size = strlen(appData.whitePieceColor);
1953 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1954 if (vTo.addr == NULL) {
1955 appData.monoMode = True;
1958 whitePieceColor = *(Pixel *) vTo.addr;
1961 if (!appData.monoMode) {
1962 vFrom.addr = (caddr_t) appData.blackPieceColor;
1963 vFrom.size = strlen(appData.blackPieceColor);
1964 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1965 if (vTo.addr == NULL) {
1966 appData.monoMode = True;
1969 blackPieceColor = *(Pixel *) vTo.addr;
1973 if (!appData.monoMode) {
1974 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1975 vFrom.size = strlen(appData.highlightSquareColor);
1976 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1977 if (vTo.addr == NULL) {
1978 appData.monoMode = True;
1981 highlightSquareColor = *(Pixel *) vTo.addr;
1985 if (!appData.monoMode) {
1986 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1987 vFrom.size = strlen(appData.premoveHighlightColor);
1988 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1989 if (vTo.addr == NULL) {
1990 appData.monoMode = True;
1993 premoveHighlightColor = *(Pixel *) vTo.addr;
1998 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2001 if (appData.bitmapDirectory == NULL ||
2002 appData.bitmapDirectory[0] == NULLCHAR)
2003 appData.bitmapDirectory = DEF_BITMAP_DIR;
2006 if (appData.lowTimeWarning && !appData.monoMode) {
2007 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2008 vFrom.size = strlen(appData.lowTimeWarningColor);
2009 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2010 if (vTo.addr == NULL)
2011 appData.monoMode = True;
2013 lowTimeWarningColor = *(Pixel *) vTo.addr;
2016 if (appData.monoMode && appData.debugMode) {
2017 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2018 (unsigned long) XWhitePixel(xDisplay, xScreen),
2019 (unsigned long) XBlackPixel(xDisplay, xScreen));
2022 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2023 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2024 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2025 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2026 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2027 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2028 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2029 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2030 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2031 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2033 if (appData.colorize) {
2035 _("%s: can't parse color names; disabling colorization\n"),
2038 appData.colorize = FALSE;
2040 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2041 textColors[ColorNone].attr = 0;
2043 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2049 layoutName = "tinyLayout";
2050 } else if (smallLayout) {
2051 layoutName = "smallLayout";
2053 layoutName = "normalLayout";
2055 /* Outer layoutWidget is there only to provide a name for use in
2056 resources that depend on the layout style */
2058 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2059 layoutArgs, XtNumber(layoutArgs));
2061 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2062 formArgs, XtNumber(formArgs));
2063 XtSetArg(args[0], XtNdefaultDistance, &sep);
2064 XtGetValues(formWidget, args, 1);
2067 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2068 XtSetArg(args[0], XtNtop, XtChainTop);
2069 XtSetArg(args[1], XtNbottom, XtChainTop);
2070 XtSetArg(args[2], XtNright, XtChainLeft);
2071 XtSetValues(menuBarWidget, args, 3);
2073 widgetList[j++] = whiteTimerWidget =
2074 XtCreateWidget("whiteTime", labelWidgetClass,
2075 formWidget, timerArgs, XtNumber(timerArgs));
2076 XtSetArg(args[0], XtNfont, clockFontStruct);
2077 XtSetArg(args[1], XtNtop, XtChainTop);
2078 XtSetArg(args[2], XtNbottom, XtChainTop);
2079 XtSetValues(whiteTimerWidget, args, 3);
2081 widgetList[j++] = blackTimerWidget =
2082 XtCreateWidget("blackTime", labelWidgetClass,
2083 formWidget, timerArgs, XtNumber(timerArgs));
2084 XtSetArg(args[0], XtNfont, clockFontStruct);
2085 XtSetArg(args[1], XtNtop, XtChainTop);
2086 XtSetArg(args[2], XtNbottom, XtChainTop);
2087 XtSetValues(blackTimerWidget, args, 3);
2089 if (appData.titleInWindow) {
2090 widgetList[j++] = titleWidget =
2091 XtCreateWidget("title", labelWidgetClass, formWidget,
2092 titleArgs, XtNumber(titleArgs));
2093 XtSetArg(args[0], XtNtop, XtChainTop);
2094 XtSetArg(args[1], XtNbottom, XtChainTop);
2095 XtSetValues(titleWidget, args, 2);
2098 if (appData.showButtonBar) {
2099 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2100 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2101 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2102 XtSetArg(args[2], XtNtop, XtChainTop);
2103 XtSetArg(args[3], XtNbottom, XtChainTop);
2104 XtSetValues(buttonBarWidget, args, 4);
2107 widgetList[j++] = messageWidget =
2108 XtCreateWidget("message", labelWidgetClass, formWidget,
2109 messageArgs, XtNumber(messageArgs));
2110 XtSetArg(args[0], XtNtop, XtChainTop);
2111 XtSetArg(args[1], XtNbottom, XtChainTop);
2112 XtSetValues(messageWidget, args, 2);
2114 widgetList[j++] = boardWidget =
2115 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2116 XtNumber(boardArgs));
2118 XtManageChildren(widgetList, j);
2120 timerWidth = (boardWidth - sep) / 2;
2121 XtSetArg(args[0], XtNwidth, timerWidth);
2122 XtSetValues(whiteTimerWidget, args, 1);
2123 XtSetValues(blackTimerWidget, args, 1);
2125 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2126 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2127 XtGetValues(whiteTimerWidget, args, 2);
2129 if (appData.showButtonBar) {
2130 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2131 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2132 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2136 * formWidget uses these constraints but they are stored
2140 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2141 XtSetValues(menuBarWidget, args, i);
2142 if (appData.titleInWindow) {
2145 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2146 XtSetValues(whiteTimerWidget, args, i);
2148 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2149 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2150 XtSetValues(blackTimerWidget, args, i);
2152 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2153 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2154 XtSetValues(titleWidget, args, i);
2156 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2157 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2158 XtSetValues(messageWidget, args, i);
2159 if (appData.showButtonBar) {
2161 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2162 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2163 XtSetValues(buttonBarWidget, args, i);
2167 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2168 XtSetValues(whiteTimerWidget, args, i);
2170 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2171 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2172 XtSetValues(blackTimerWidget, args, i);
2174 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2175 XtSetValues(titleWidget, args, i);
2177 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2178 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2179 XtSetValues(messageWidget, args, i);
2180 if (appData.showButtonBar) {
2182 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2183 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2184 XtSetValues(buttonBarWidget, args, i);
2189 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2190 XtSetValues(whiteTimerWidget, args, i);
2192 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2193 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2194 XtSetValues(blackTimerWidget, args, i);
2196 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2197 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2198 XtSetValues(messageWidget, args, i);
2199 if (appData.showButtonBar) {
2201 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2202 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2203 XtSetValues(buttonBarWidget, args, i);
2207 XtSetArg(args[0], XtNfromVert, messageWidget);
2208 XtSetArg(args[1], XtNtop, XtChainTop);
2209 XtSetArg(args[2], XtNbottom, XtChainBottom);
2210 XtSetArg(args[3], XtNleft, XtChainLeft);
2211 XtSetArg(args[4], XtNright, XtChainRight);
2212 XtSetValues(boardWidget, args, 5);
2214 XtRealizeWidget(shellWidget);
2217 XtSetArg(args[0], XtNx, wpMain.x);
2218 XtSetArg(args[1], XtNy, wpMain.y);
2219 XtSetValues(shellWidget, args, 2);
2223 * Correct the width of the message and title widgets.
2224 * It is not known why some systems need the extra fudge term.
2225 * The value "2" is probably larger than needed.
2227 XawFormDoLayout(formWidget, False);
2229 #define WIDTH_FUDGE 2
2231 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2232 XtSetArg(args[i], XtNheight, &h); i++;
2233 XtGetValues(messageWidget, args, i);
2234 if (appData.showButtonBar) {
2236 XtSetArg(args[i], XtNwidth, &w); i++;
2237 XtGetValues(buttonBarWidget, args, i);
2238 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2240 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2243 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2244 if (gres != XtGeometryYes && appData.debugMode) {
2245 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2246 programName, gres, w, h, wr, hr);
2249 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2250 /* The size used for the child widget in layout lags one resize behind
2251 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2253 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2254 if (gres != XtGeometryYes && appData.debugMode) {
2255 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2256 programName, gres, w, h, wr, hr);
2259 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2260 XtSetArg(args[1], XtNright, XtChainRight);
2261 XtSetValues(messageWidget, args, 2);
2263 if (appData.titleInWindow) {
2265 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2266 XtSetArg(args[i], XtNheight, &h); i++;
2267 XtGetValues(titleWidget, args, i);
2269 w = boardWidth - 2*bor;
2271 XtSetArg(args[0], XtNwidth, &w);
2272 XtGetValues(menuBarWidget, args, 1);
2273 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2276 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2277 if (gres != XtGeometryYes && appData.debugMode) {
2279 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2280 programName, gres, w, h, wr, hr);
2283 XawFormDoLayout(formWidget, True);
2285 xBoardWindow = XtWindow(boardWidget);
2287 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2288 // not need to go into InitDrawingSizes().
2292 * Create X checkmark bitmap and initialize option menu checks.
2294 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2295 checkmark_bits, checkmark_width, checkmark_height);
2296 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2297 if (appData.alwaysPromoteToQueen) {
2298 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2301 if (appData.animateDragging) {
2302 XtSetValues(XtNameToWidget(menuBarWidget,
2303 "menuOptions.Animate Dragging"),
2306 if (appData.animate) {
2307 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2310 if (appData.autoComment) {
2311 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2314 if (appData.autoCallFlag) {
2315 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2318 if (appData.autoFlipView) {
2319 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2322 if (appData.autoObserve) {
2323 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2326 if (appData.autoRaiseBoard) {
2327 XtSetValues(XtNameToWidget(menuBarWidget,
2328 "menuOptions.Auto Raise Board"), args, 1);
2330 if (appData.autoSaveGames) {
2331 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2334 if (appData.saveGameFile[0] != NULLCHAR) {
2335 /* Can't turn this off from menu */
2336 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2338 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2342 if (appData.blindfold) {
2343 XtSetValues(XtNameToWidget(menuBarWidget,
2344 "menuOptions.Blindfold"), args, 1);
2346 if (appData.flashCount > 0) {
2347 XtSetValues(XtNameToWidget(menuBarWidget,
2348 "menuOptions.Flash Moves"),
2351 if (appData.getMoveList) {
2352 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2356 if (appData.highlightDragging) {
2357 XtSetValues(XtNameToWidget(menuBarWidget,
2358 "menuOptions.Highlight Dragging"),
2362 if (appData.highlightLastMove) {
2363 XtSetValues(XtNameToWidget(menuBarWidget,
2364 "menuOptions.Highlight Last Move"),
2367 if (appData.icsAlarm) {
2368 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2371 if (appData.ringBellAfterMoves) {
2372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2375 if (appData.oldSaveStyle) {
2376 XtSetValues(XtNameToWidget(menuBarWidget,
2377 "menuOptions.Old Save Style"), args, 1);
2379 if (appData.periodicUpdates) {
2380 XtSetValues(XtNameToWidget(menuBarWidget,
2381 "menuOptions.Periodic Updates"), args, 1);
2383 if (appData.ponderNextMove) {
2384 XtSetValues(XtNameToWidget(menuBarWidget,
2385 "menuOptions.Ponder Next Move"), args, 1);
2387 if (appData.popupExitMessage) {
2388 XtSetValues(XtNameToWidget(menuBarWidget,
2389 "menuOptions.Popup Exit Message"), args, 1);
2391 if (appData.popupMoveErrors) {
2392 XtSetValues(XtNameToWidget(menuBarWidget,
2393 "menuOptions.Popup Move Errors"), args, 1);
2395 if (appData.premove) {
2396 XtSetValues(XtNameToWidget(menuBarWidget,
2397 "menuOptions.Premove"), args, 1);
2399 if (appData.quietPlay) {
2400 XtSetValues(XtNameToWidget(menuBarWidget,
2401 "menuOptions.Quiet Play"), args, 1);
2403 if (appData.showCoords) {
2404 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2407 if (appData.hideThinkingFromHuman) {
2408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2411 if (appData.testLegality) {
2412 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2415 if (saveSettingsOnExit) {
2416 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2423 ReadBitmap(&wIconPixmap, "icon_white.bm",
2424 icon_white_bits, icon_white_width, icon_white_height);
2425 ReadBitmap(&bIconPixmap, "icon_black.bm",
2426 icon_black_bits, icon_black_width, icon_black_height);
2427 iconPixmap = wIconPixmap;
2429 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2430 XtSetValues(shellWidget, args, i);
2433 * Create a cursor for the board widget.
2435 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2436 XChangeWindowAttributes(xDisplay, xBoardWindow,
2437 CWCursor, &window_attributes);
2440 * Inhibit shell resizing.
2442 shellArgs[0].value = (XtArgVal) &w;
2443 shellArgs[1].value = (XtArgVal) &h;
2444 XtGetValues(shellWidget, shellArgs, 2);
2445 shellArgs[4].value = shellArgs[2].value = w;
2446 shellArgs[5].value = shellArgs[3].value = h;
2447 XtSetValues(shellWidget, &shellArgs[2], 4);
2448 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2449 marginH = h - boardHeight;
2451 CatchDeleteWindow(shellWidget, "QuitProc");
2456 if (appData.bitmapDirectory[0] != NULLCHAR) {
2463 /* Create regular pieces */
2464 if (!useImages) CreatePieces();
2469 if (appData.animate || appData.animateDragging)
2472 XtAugmentTranslations(formWidget,
2473 XtParseTranslationTable(globalTranslations));
2474 XtAugmentTranslations(boardWidget,
2475 XtParseTranslationTable(boardTranslations));
2476 XtAugmentTranslations(whiteTimerWidget,
2477 XtParseTranslationTable(whiteTranslations));
2478 XtAugmentTranslations(blackTimerWidget,
2479 XtParseTranslationTable(blackTranslations));
2481 /* Why is the following needed on some versions of X instead
2482 * of a translation? */
2483 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2484 (XtEventHandler) EventProc, NULL);
2487 /* [AS] Restore layout */
2488 if( wpMoveHistory.visible ) {
2492 if( wpEvalGraph.visible )
2497 if( wpEngineOutput.visible ) {
2498 EngineOutputPopUp();
2503 if (errorExitStatus == -1) {
2504 if (appData.icsActive) {
2505 /* We now wait until we see "login:" from the ICS before
2506 sending the logon script (problems with timestamp otherwise) */
2507 /*ICSInitScript();*/
2508 if (appData.icsInputBox) ICSInputBoxPopUp();
2512 signal(SIGWINCH, TermSizeSigHandler);
2514 signal(SIGINT, IntSigHandler);
2515 signal(SIGTERM, IntSigHandler);
2516 if (*appData.cmailGameName != NULLCHAR) {
2517 signal(SIGUSR1, CmailSigHandler);
2520 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2523 XtAppMainLoop(appContext);
2524 if (appData.debugMode) fclose(debugFP); // [DM] debug
2531 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2532 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2534 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2535 unlink(gameCopyFilename);
2536 unlink(gamePasteFilename);
2539 RETSIGTYPE TermSizeSigHandler(int sig)
2552 CmailSigHandler(sig)
2558 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2560 /* Activate call-back function CmailSigHandlerCallBack() */
2561 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2563 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2567 CmailSigHandlerCallBack(isr, closure, message, count, error)
2575 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2577 /**** end signal code ****/
2587 f = fopen(appData.icsLogon, "r");
2593 strcat(buf, appData.icsLogon);
2594 f = fopen(buf, "r");
2598 ProcessICSInitScript(f);
2605 EditCommentPopDown();
2620 if (!menuBarWidget) return;
2621 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2623 DisplayError("menuStep.Revert", 0);
2625 XtSetSensitive(w, !grey);
2630 SetMenuEnables(enab)
2634 if (!menuBarWidget) return;
2635 while (enab->name != NULL) {
2636 w = XtNameToWidget(menuBarWidget, enab->name);
2638 DisplayError(enab->name, 0);
2640 XtSetSensitive(w, enab->value);
2646 Enables icsEnables[] = {
2647 { "menuFile.Mail Move", False },
2648 { "menuFile.Reload CMail Message", False },
2649 { "menuMode.Machine Black", False },
2650 { "menuMode.Machine White", False },
2651 { "menuMode.Analysis Mode", False },
2652 { "menuMode.Analyze File", False },
2653 { "menuMode.Two Machines", False },
2655 { "menuHelp.Hint", False },
2656 { "menuHelp.Book", False },
2657 { "menuStep.Move Now", False },
2658 { "menuOptions.Periodic Updates", False },
2659 { "menuOptions.Hide Thinking", False },
2660 { "menuOptions.Ponder Next Move", False },
2665 Enables ncpEnables[] = {
2666 { "menuFile.Mail Move", False },
2667 { "menuFile.Reload CMail Message", False },
2668 { "menuMode.Machine White", False },
2669 { "menuMode.Machine Black", False },
2670 { "menuMode.Analysis Mode", False },
2671 { "menuMode.Analyze File", False },
2672 { "menuMode.Two Machines", False },
2673 { "menuMode.ICS Client", False },
2674 { "menuMode.ICS Input Box", False },
2675 { "Action", False },
2676 { "menuStep.Revert", False },
2677 { "menuStep.Move Now", False },
2678 { "menuStep.Retract Move", False },
2679 { "menuOptions.Auto Comment", False },
2680 { "menuOptions.Auto Flag", False },
2681 { "menuOptions.Auto Flip View", False },
2682 { "menuOptions.Auto Observe", False },
2683 { "menuOptions.Auto Raise Board", False },
2684 { "menuOptions.Get Move List", False },
2685 { "menuOptions.ICS Alarm", False },
2686 { "menuOptions.Move Sound", False },
2687 { "menuOptions.Quiet Play", False },
2688 { "menuOptions.Hide Thinking", False },
2689 { "menuOptions.Periodic Updates", False },
2690 { "menuOptions.Ponder Next Move", False },
2691 { "menuHelp.Hint", False },
2692 { "menuHelp.Book", False },
2696 Enables gnuEnables[] = {
2697 { "menuMode.ICS Client", False },
2698 { "menuMode.ICS Input Box", False },
2699 { "menuAction.Accept", False },
2700 { "menuAction.Decline", False },
2701 { "menuAction.Rematch", False },
2702 { "menuAction.Adjourn", False },
2703 { "menuAction.Stop Examining", False },
2704 { "menuAction.Stop Observing", False },
2705 { "menuAction.Upload to Examine", False },
2706 { "menuStep.Revert", False },
2707 { "menuOptions.Auto Comment", False },
2708 { "menuOptions.Auto Observe", False },
2709 { "menuOptions.Auto Raise Board", False },
2710 { "menuOptions.Get Move List", False },
2711 { "menuOptions.Premove", False },
2712 { "menuOptions.Quiet Play", False },
2714 /* The next two options rely on SetCmailMode being called *after* */
2715 /* SetGNUMode so that when GNU is being used to give hints these */
2716 /* menu options are still available */
2718 { "menuFile.Mail Move", False },
2719 { "menuFile.Reload CMail Message", False },
2723 Enables cmailEnables[] = {
2725 { "menuAction.Call Flag", False },
2726 { "menuAction.Draw", True },
2727 { "menuAction.Adjourn", False },
2728 { "menuAction.Abort", False },
2729 { "menuAction.Stop Observing", False },
2730 { "menuAction.Stop Examining", False },
2731 { "menuFile.Mail Move", True },
2732 { "menuFile.Reload CMail Message", True },
2736 Enables trainingOnEnables[] = {
2737 { "menuMode.Edit Comment", False },
2738 { "menuMode.Pause", False },
2739 { "menuStep.Forward", False },
2740 { "menuStep.Backward", False },
2741 { "menuStep.Forward to End", False },
2742 { "menuStep.Back to Start", False },
2743 { "menuStep.Move Now", False },
2744 { "menuStep.Truncate Game", False },
2748 Enables trainingOffEnables[] = {
2749 { "menuMode.Edit Comment", True },
2750 { "menuMode.Pause", True },
2751 { "menuStep.Forward", True },
2752 { "menuStep.Backward", True },
2753 { "menuStep.Forward to End", True },
2754 { "menuStep.Back to Start", True },
2755 { "menuStep.Move Now", True },
2756 { "menuStep.Truncate Game", True },
2760 Enables machineThinkingEnables[] = {
2761 { "menuFile.Load Game", False },
2762 { "menuFile.Load Next Game", False },
2763 { "menuFile.Load Previous Game", False },
2764 { "menuFile.Reload Same Game", False },
2765 { "menuFile.Paste Game", False },
2766 { "menuFile.Load Position", False },
2767 { "menuFile.Load Next Position", False },
2768 { "menuFile.Load Previous Position", False },
2769 { "menuFile.Reload Same Position", False },
2770 { "menuFile.Paste Position", False },
2771 { "menuMode.Machine White", False },
2772 { "menuMode.Machine Black", False },
2773 { "menuMode.Two Machines", False },
2774 { "menuStep.Retract Move", False },
2778 Enables userThinkingEnables[] = {
2779 { "menuFile.Load Game", True },
2780 { "menuFile.Load Next Game", True },
2781 { "menuFile.Load Previous Game", True },
2782 { "menuFile.Reload Same Game", True },
2783 { "menuFile.Paste Game", True },
2784 { "menuFile.Load Position", True },
2785 { "menuFile.Load Next Position", True },
2786 { "menuFile.Load Previous Position", True },
2787 { "menuFile.Reload Same Position", True },
2788 { "menuFile.Paste Position", True },
2789 { "menuMode.Machine White", True },
2790 { "menuMode.Machine Black", True },
2791 { "menuMode.Two Machines", True },
2792 { "menuStep.Retract Move", True },
2798 SetMenuEnables(icsEnables);
2801 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2802 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2809 SetMenuEnables(ncpEnables);
2815 SetMenuEnables(gnuEnables);
2821 SetMenuEnables(cmailEnables);
2827 SetMenuEnables(trainingOnEnables);
2828 if (appData.showButtonBar) {
2829 XtSetSensitive(buttonBarWidget, False);
2835 SetTrainingModeOff()
2837 SetMenuEnables(trainingOffEnables);
2838 if (appData.showButtonBar) {
2839 XtSetSensitive(buttonBarWidget, True);
2844 SetUserThinkingEnables()
2846 if (appData.noChessProgram) return;
2847 SetMenuEnables(userThinkingEnables);
2851 SetMachineThinkingEnables()
2853 if (appData.noChessProgram) return;
2854 SetMenuEnables(machineThinkingEnables);
2856 case MachinePlaysBlack:
2857 case MachinePlaysWhite:
2858 case TwoMachinesPlay:
2859 XtSetSensitive(XtNameToWidget(menuBarWidget,
2860 ModeToWidgetName(gameMode)), True);
2867 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2868 #define HISTORY_SIZE 64
\r
2869 static char *history[HISTORY_SIZE];
\r
2870 int histIn = 0, histP = 0;
\r
2873 SaveInHistory(char *cmd)
\r
2875 if (history[histIn] != NULL) {
\r
2876 free(history[histIn]);
\r
2877 history[histIn] = NULL;
\r
2879 if (*cmd == NULLCHAR) return;
\r
2880 history[histIn] = StrSave(cmd);
\r
2881 histIn = (histIn + 1) % HISTORY_SIZE;
\r
2882 if (history[histIn] != NULL) {
\r
2883 free(history[histIn]);
\r
2884 history[histIn] = NULL;
\r
2890 PrevInHistory(char *cmd)
\r
2893 if (histP == histIn) {
\r
2894 if (history[histIn] != NULL) free(history[histIn]);
\r
2895 history[histIn] = StrSave(cmd);
\r
2897 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
2898 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
2900 return history[histP];
\r
2906 if (histP == histIn) return NULL;
\r
2907 histP = (histP + 1) % HISTORY_SIZE;
\r
2908 return history[histP];
\r
2910 // end of borrowed code
\r
2912 #define Abs(n) ((n)<0 ? -(n) : (n))
2915 * Find a font that matches "pattern" that is as close as
2916 * possible to the targetPxlSize. Prefer fonts that are k
2917 * pixels smaller to fonts that are k pixels larger. The
2918 * pattern must be in the X Consortium standard format,
2919 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2920 * The return value should be freed with XtFree when no
2923 char *FindFont(pattern, targetPxlSize)
2927 char **fonts, *p, *best, *scalable, *scalableTail;
2928 int i, j, nfonts, minerr, err, pxlSize;
2931 char **missing_list;
2933 char *def_string, *base_fnt_lst, strInt[3];
2935 XFontStruct **fnt_list;
2937 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2938 sprintf(strInt, "%d", targetPxlSize);
2939 p = strstr(pattern, "--");
2940 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2941 strcat(base_fnt_lst, strInt);
2942 strcat(base_fnt_lst, strchr(p + 2, '-'));
2944 if ((fntSet = XCreateFontSet(xDisplay,
2948 &def_string)) == NULL) {
2950 fprintf(stderr, _("Unable to create font set.\n"));
2954 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2956 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2958 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2959 programName, pattern);
2967 for (i=0; i<nfonts; i++) {
2970 if (*p != '-') continue;
2972 if (*p == NULLCHAR) break;
2973 if (*p++ == '-') j++;
2975 if (j < 7) continue;
2978 scalable = fonts[i];
2981 err = pxlSize - targetPxlSize;
2982 if (Abs(err) < Abs(minerr) ||
2983 (minerr > 0 && err < 0 && -err == minerr)) {
2989 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2990 /* If the error is too big and there is a scalable font,
2991 use the scalable font. */
2992 int headlen = scalableTail - scalable;
2993 p = (char *) XtMalloc(strlen(scalable) + 10);
2994 while (isdigit(*scalableTail)) scalableTail++;
2995 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2997 p = (char *) XtMalloc(strlen(best) + 1);
3000 if (appData.debugMode) {
3001 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3002 pattern, targetPxlSize, p);
3005 if (missing_count > 0)
3006 XFreeStringList(missing_list);
3007 XFreeFontSet(xDisplay, fntSet);
3009 XFreeFontNames(fonts);
3016 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3017 | GCBackground | GCFunction | GCPlaneMask;
3018 XGCValues gc_values;
3021 gc_values.plane_mask = AllPlanes;
3022 gc_values.line_width = lineGap;
3023 gc_values.line_style = LineSolid;
3024 gc_values.function = GXcopy;
3026 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3027 gc_values.background = XBlackPixel(xDisplay, xScreen);
3028 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3030 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3031 gc_values.background = XWhitePixel(xDisplay, xScreen);
3032 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3033 XSetFont(xDisplay, coordGC, coordFontID);
3035 // [HGM] make font for holdings counts (white on black0
3036 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3037 gc_values.background = XBlackPixel(xDisplay, xScreen);
3038 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3039 XSetFont(xDisplay, countGC, countFontID);
3041 if (appData.monoMode) {
3042 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3043 gc_values.background = XWhitePixel(xDisplay, xScreen);
3044 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3046 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3047 gc_values.background = XBlackPixel(xDisplay, xScreen);
3048 lightSquareGC = wbPieceGC
3049 = XtGetGC(shellWidget, value_mask, &gc_values);
3051 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3052 gc_values.background = XWhitePixel(xDisplay, xScreen);
3053 darkSquareGC = bwPieceGC
3054 = XtGetGC(shellWidget, value_mask, &gc_values);
3056 if (DefaultDepth(xDisplay, xScreen) == 1) {
3057 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3058 gc_values.function = GXcopyInverted;
3059 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060 gc_values.function = GXcopy;
3061 if (XBlackPixel(xDisplay, xScreen) == 1) {
3062 bwPieceGC = darkSquareGC;
3063 wbPieceGC = copyInvertedGC;
3065 bwPieceGC = copyInvertedGC;
3066 wbPieceGC = lightSquareGC;
3070 gc_values.foreground = highlightSquareColor;
3071 gc_values.background = highlightSquareColor;
3072 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3074 gc_values.foreground = premoveHighlightColor;
3075 gc_values.background = premoveHighlightColor;
3076 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3078 gc_values.foreground = lightSquareColor;
3079 gc_values.background = darkSquareColor;
3080 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3082 gc_values.foreground = darkSquareColor;
3083 gc_values.background = lightSquareColor;
3084 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3086 gc_values.foreground = jailSquareColor;
3087 gc_values.background = jailSquareColor;
3088 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3090 gc_values.foreground = whitePieceColor;
3091 gc_values.background = darkSquareColor;
3092 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3094 gc_values.foreground = whitePieceColor;
3095 gc_values.background = lightSquareColor;
3096 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3098 gc_values.foreground = whitePieceColor;
3099 gc_values.background = jailSquareColor;
3100 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3102 gc_values.foreground = blackPieceColor;
3103 gc_values.background = darkSquareColor;
3104 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3106 gc_values.foreground = blackPieceColor;
3107 gc_values.background = lightSquareColor;
3108 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3110 gc_values.foreground = blackPieceColor;
3111 gc_values.background = jailSquareColor;
3112 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3116 void loadXIM(xim, xmask, filename, dest, mask)
3129 fp = fopen(filename, "rb");
3131 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3138 for (y=0; y<h; ++y) {
3139 for (x=0; x<h; ++x) {
3144 XPutPixel(xim, x, y, blackPieceColor);
3146 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3149 XPutPixel(xim, x, y, darkSquareColor);
3151 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3154 XPutPixel(xim, x, y, whitePieceColor);
3156 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3159 XPutPixel(xim, x, y, lightSquareColor);
3161 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3167 /* create Pixmap of piece */
3168 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3170 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3173 /* create Pixmap of clipmask
3174 Note: We assume the white/black pieces have the same
3175 outline, so we make only 6 masks. This is okay
3176 since the XPM clipmask routines do the same. */
3178 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3180 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3183 /* now create the 1-bit version */
3184 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3187 values.foreground = 1;
3188 values.background = 0;
3190 /* Don't use XtGetGC, not read only */
3191 maskGC = XCreateGC(xDisplay, *mask,
3192 GCForeground | GCBackground, &values);
3193 XCopyPlane(xDisplay, temp, *mask, maskGC,
3194 0, 0, squareSize, squareSize, 0, 0, 1);
3195 XFreePixmap(xDisplay, temp);
3200 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3202 void CreateXIMPieces()
3207 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3212 /* The XSynchronize calls were copied from CreatePieces.
3213 Not sure if needed, but can't hurt */
3214 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3217 /* temp needed by loadXIM() */
3218 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3219 0, 0, ss, ss, AllPlanes, XYPixmap);
3221 if (strlen(appData.pixmapDirectory) == 0) {
3225 if (appData.monoMode) {
3226 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3230 fprintf(stderr, _("\nLoading XIMs...\n"));
3232 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3233 fprintf(stderr, "%d", piece+1);
3234 for (kind=0; kind<4; kind++) {
3235 fprintf(stderr, ".");
3236 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3237 ExpandPathName(appData.pixmapDirectory),
3238 piece <= (int) WhiteKing ? "" : "w",
3239 pieceBitmapNames[piece],
3241 ximPieceBitmap[kind][piece] =
3242 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3243 0, 0, ss, ss, AllPlanes, XYPixmap);
3244 if (appData.debugMode)
3245 fprintf(stderr, _("(File:%s:) "), buf);
3246 loadXIM(ximPieceBitmap[kind][piece],
3248 &(xpmPieceBitmap2[kind][piece]),
3249 &(ximMaskPm2[piece]));
3250 if(piece <= (int)WhiteKing)
3251 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3253 fprintf(stderr," ");
3255 /* Load light and dark squares */
3256 /* If the LSQ and DSQ pieces don't exist, we will
3257 draw them with solid squares. */
3258 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3259 if (access(buf, 0) != 0) {
3263 fprintf(stderr, _("light square "));
3265 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3266 0, 0, ss, ss, AllPlanes, XYPixmap);
3267 if (appData.debugMode)
3268 fprintf(stderr, _("(File:%s:) "), buf);
3270 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3271 fprintf(stderr, _("dark square "));
3272 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3273 ExpandPathName(appData.pixmapDirectory), ss);
3274 if (appData.debugMode)
3275 fprintf(stderr, _("(File:%s:) "), buf);
3277 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3278 0, 0, ss, ss, AllPlanes, XYPixmap);
3279 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3280 xpmJailSquare = xpmLightSquare;
3282 fprintf(stderr, _("Done.\n"));
3284 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3288 void CreateXPMPieces()
3292 u_int ss = squareSize;
3294 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3295 XpmColorSymbol symbols[4];
3297 /* The XSynchronize calls were copied from CreatePieces.
3298 Not sure if needed, but can't hurt */
3299 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3301 /* Setup translations so piece colors match square colors */
3302 symbols[0].name = "light_piece";
3303 symbols[0].value = appData.whitePieceColor;
3304 symbols[1].name = "dark_piece";
3305 symbols[1].value = appData.blackPieceColor;
3306 symbols[2].name = "light_square";
3307 symbols[2].value = appData.lightSquareColor;
3308 symbols[3].name = "dark_square";
3309 symbols[3].value = appData.darkSquareColor;
3311 attr.valuemask = XpmColorSymbols;
3312 attr.colorsymbols = symbols;
3313 attr.numsymbols = 4;
3315 if (appData.monoMode) {
3316 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3320 if (strlen(appData.pixmapDirectory) == 0) {
3321 XpmPieces* pieces = builtInXpms;
3324 while (pieces->size != squareSize && pieces->size) pieces++;
3325 if (!pieces->size) {
3326 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3329 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3330 for (kind=0; kind<4; kind++) {
3332 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3333 pieces->xpm[piece][kind],
3334 &(xpmPieceBitmap2[kind][piece]),
3335 NULL, &attr)) != 0) {
3336 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3340 if(piece <= (int) WhiteKing)
3341 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3345 xpmJailSquare = xpmLightSquare;
3349 fprintf(stderr, _("\nLoading XPMs...\n"));
3352 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3353 fprintf(stderr, "%d ", piece+1);
3354 for (kind=0; kind<4; kind++) {
3355 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3356 ExpandPathName(appData.pixmapDirectory),
3357 piece > (int) WhiteKing ? "w" : "",
3358 pieceBitmapNames[piece],
3360 if (appData.debugMode) {
3361 fprintf(stderr, _("(File:%s:) "), buf);
3363 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3364 &(xpmPieceBitmap2[kind][piece]),
3365 NULL, &attr)) != 0) {
3366 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3367 // [HGM] missing: read of unorthodox piece failed; substitute King.
3368 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3369 ExpandPathName(appData.pixmapDirectory),
3371 if (appData.debugMode) {
3372 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3374 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3375 &(xpmPieceBitmap2[kind][piece]),
3379 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3384 if(piece <= (int) WhiteKing)
3385 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3388 /* Load light and dark squares */
3389 /* If the LSQ and DSQ pieces don't exist, we will
3390 draw them with solid squares. */
3391 fprintf(stderr, _("light square "));
3392 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3393 if (access(buf, 0) != 0) {
3397 if (appData.debugMode)
3398 fprintf(stderr, _("(File:%s:) "), buf);
3400 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3401 &xpmLightSquare, NULL, &attr)) != 0) {
3402 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3405 fprintf(stderr, _("dark square "));
3406 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3407 ExpandPathName(appData.pixmapDirectory), ss);
3408 if (appData.debugMode) {
3409 fprintf(stderr, _("(File:%s:) "), buf);
3411 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3412 &xpmDarkSquare, NULL, &attr)) != 0) {
3413 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3417 xpmJailSquare = xpmLightSquare;
3418 fprintf(stderr, _("Done.\n"));
3420 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3423 #endif /* HAVE_LIBXPM */
3426 /* No built-in bitmaps */
3431 u_int ss = squareSize;
3433 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3436 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3437 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3438 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3439 pieceBitmapNames[piece],
3440 ss, kind == SOLID ? 's' : 'o');
3441 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3442 if(piece <= (int)WhiteKing)
3443 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3447 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3451 /* With built-in bitmaps */
3454 BuiltInBits* bib = builtInBits;
3457 u_int ss = squareSize;
3459 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3462 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3464 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3465 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3466 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3467 pieceBitmapNames[piece],
3468 ss, kind == SOLID ? 's' : 'o');
3469 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3470 bib->bits[kind][piece], ss, ss);
3471 if(piece <= (int)WhiteKing)
3472 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3476 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3481 void ReadBitmap(pm, name, bits, wreq, hreq)
3484 unsigned char bits[];
3490 char msg[MSG_SIZ], fullname[MSG_SIZ];
3492 if (*appData.bitmapDirectory != NULLCHAR) {
3493 strcpy(fullname, appData.bitmapDirectory);
3494 strcat(fullname, "/");
3495 strcat(fullname, name);
3496 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3497 &w, &h, pm, &x_hot, &y_hot);
3498 fprintf(stderr, "load %s\n", name);
3499 if (errcode != BitmapSuccess) {
3501 case BitmapOpenFailed:
3502 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3504 case BitmapFileInvalid:
3505 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3507 case BitmapNoMemory:
3508 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3512 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3516 fprintf(stderr, _("%s: %s...using built-in\n"),
3518 } else if (w != wreq || h != hreq) {
3520 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3521 programName, fullname, w, h, wreq, hreq);
3527 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3536 if (lineGap == 0) return;
3538 /* [HR] Split this into 2 loops for non-square boards. */
3540 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3541 gridSegments[i].x1 = 0;
3542 gridSegments[i].x2 =
3543 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3544 gridSegments[i].y1 = gridSegments[i].y2
3545 = lineGap / 2 + (i * (squareSize + lineGap));
3548 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3549 gridSegments[j + i].y1 = 0;
3550 gridSegments[j + i].y2 =
3551 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3552 gridSegments[j + i].x1 = gridSegments[j + i].x2
3553 = lineGap / 2 + (j * (squareSize + lineGap));
3557 static void MenuBarSelect(w, addr, index)
3562 XtActionProc proc = (XtActionProc) addr;
3564 (proc)(NULL, NULL, NULL, NULL);
3567 void CreateMenuBarPopup(parent, name, mb)
3577 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3580 XtSetArg(args[j], XtNleftMargin, 20); j++;
3581 XtSetArg(args[j], XtNrightMargin, 20); j++;
3583 while (mi->string != NULL) {
3584 if (strcmp(mi->string, "----") == 0) {
3585 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3588 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3589 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3591 XtAddCallback(entry, XtNcallback,
3592 (XtCallbackProc) MenuBarSelect,
3593 (caddr_t) mi->proc);
3599 Widget CreateMenuBar(mb)
3603 Widget anchor, menuBar;
3605 char menuName[MSG_SIZ];
3608 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3609 XtSetArg(args[j], XtNvSpace, 0); j++;
3610 XtSetArg(args[j], XtNborderWidth, 0); j++;
3611 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3612 formWidget, args, j);
3614 while (mb->name != NULL) {
3615 strcpy(menuName, "menu");
3616 strcat(menuName, mb->name);
3618 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3621 shortName[0] = _(mb->name)[0];
3622 shortName[1] = NULLCHAR;
3623 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3626 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3629 XtSetArg(args[j], XtNborderWidth, 0); j++;
3630 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3632 CreateMenuBarPopup(menuBar, menuName, mb);
3638 Widget CreateButtonBar(mi)
3642 Widget button, buttonBar;
3646 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3648 XtSetArg(args[j], XtNhSpace, 0); j++;
3650 XtSetArg(args[j], XtNborderWidth, 0); j++;
3651 XtSetArg(args[j], XtNvSpace, 0); j++;
3652 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3653 formWidget, args, j);
3655 while (mi->string != NULL) {
3658 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3659 XtSetArg(args[j], XtNborderWidth, 0); j++;
3661 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3662 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3663 buttonBar, args, j);
3664 XtAddCallback(button, XtNcallback,
3665 (XtCallbackProc) MenuBarSelect,
3666 (caddr_t) mi->proc);
3673 CreatePieceMenu(name, color)
3680 ChessSquare selection;
3682 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3683 boardWidget, args, 0);
3685 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3686 String item = pieceMenuStrings[color][i];
3688 if (strcmp(item, "----") == 0) {
3689 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3692 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3693 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3695 selection = pieceMenuTranslation[color][i];
3696 XtAddCallback(entry, XtNcallback,
3697 (XtCallbackProc) PieceMenuSelect,
3698 (caddr_t) selection);
3699 if (selection == WhitePawn || selection == BlackPawn) {
3700 XtSetArg(args[0], XtNpopupOnEntry, entry);
3701 XtSetValues(menu, args, 1);
3714 ChessSquare selection;
3716 whitePieceMenu = CreatePieceMenu("menuW", 0);
3717 blackPieceMenu = CreatePieceMenu("menuB", 1);
3719 XtRegisterGrabAction(PieceMenuPopup, True,
3720 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3721 GrabModeAsync, GrabModeAsync);
3723 XtSetArg(args[0], XtNlabel, _("Drop"));
3724 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3725 boardWidget, args, 1);
3726 for (i = 0; i < DROP_MENU_SIZE; i++) {
3727 String item = dropMenuStrings[i];
3729 if (strcmp(item, "----") == 0) {
3730 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3733 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3734 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3736 selection = dropMenuTranslation[i];
3737 XtAddCallback(entry, XtNcallback,
3738 (XtCallbackProc) DropMenuSelect,
3739 (caddr_t) selection);
3744 void SetupDropMenu()
3752 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3753 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3754 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3755 dmEnables[i].piece);
3756 XtSetSensitive(entry, p != NULL || !appData.testLegality
3757 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3758 && !appData.icsActive));
3760 while (p && *p++ == dmEnables[i].piece) count++;
3761 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3763 XtSetArg(args[j], XtNlabel, label); j++;
3764 XtSetValues(entry, args, j);
3768 void PieceMenuPopup(w, event, params, num_params)
3772 Cardinal *num_params;
3774 String whichMenu; int menuNr;
3775 if (event->type == ButtonRelease)
3776 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3777 else if (event->type == ButtonPress)
3778 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3780 case 0: whichMenu = params[0]; break;
3781 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3783 case -1: if (errorUp) ErrorPopDown();
3786 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3789 static void PieceMenuSelect(w, piece, junk)
3794 if (pmFromX < 0 || pmFromY < 0) return;
3795 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3798 static void DropMenuSelect(w, piece, junk)
3803 if (pmFromX < 0 || pmFromY < 0) return;
3804 DropMenuEvent(piece, pmFromX, pmFromY);
3807 void WhiteClock(w, event, prms, nprms)
3813 if (gameMode == EditPosition || gameMode == IcsExamining) {
3814 SetWhiteToPlayEvent();
3815 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3820 void BlackClock(w, event, prms, nprms)
3826 if (gameMode == EditPosition || gameMode == IcsExamining) {
3827 SetBlackToPlayEvent();
3828 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3835 * If the user selects on a border boundary, return -1; if off the board,
3836 * return -2. Otherwise map the event coordinate to the square.
3838 int EventToSquare(x, limit)
3846 if ((x % (squareSize + lineGap)) >= squareSize)
3848 x /= (squareSize + lineGap);
3854 static void do_flash_delay(msec)
3860 static void drawHighlight(file, rank, gc)
3866 if (lineGap == 0 || appData.blindfold) return;
3869 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3870 (squareSize + lineGap);
3871 y = lineGap/2 + rank * (squareSize + lineGap);
3873 x = lineGap/2 + file * (squareSize + lineGap);
3874 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3875 (squareSize + lineGap);
3878 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3879 squareSize+lineGap, squareSize+lineGap);
3882 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3883 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3886 SetHighlights(fromX, fromY, toX, toY)
3887 int fromX, fromY, toX, toY;
3889 if (hi1X != fromX || hi1Y != fromY) {
3890 if (hi1X >= 0 && hi1Y >= 0) {
3891 drawHighlight(hi1X, hi1Y, lineGC);
3893 } // [HGM] first erase both, then draw new!
3894 if (hi2X != toX || hi2Y != toY) {
3895 if (hi2X >= 0 && hi2Y >= 0) {
3896 drawHighlight(hi2X, hi2Y, lineGC);
3899 if (hi1X != fromX || hi1Y != fromY) {
3900 if (fromX >= 0 && fromY >= 0) {
3901 drawHighlight(fromX, fromY, highlineGC);
3904 if (hi2X != toX || hi2Y != toY) {
3905 if (toX >= 0 && toY >= 0) {
3906 drawHighlight(toX, toY, highlineGC);
3918 SetHighlights(-1, -1, -1, -1);
3923 SetPremoveHighlights(fromX, fromY, toX, toY)
3924 int fromX, fromY, toX, toY;
3926 if (pm1X != fromX || pm1Y != fromY) {
3927 if (pm1X >= 0 && pm1Y >= 0) {
3928 drawHighlight(pm1X, pm1Y, lineGC);
3930 if (fromX >= 0 && fromY >= 0) {
3931 drawHighlight(fromX, fromY, prelineGC);
3934 if (pm2X != toX || pm2Y != toY) {
3935 if (pm2X >= 0 && pm2Y >= 0) {
3936 drawHighlight(pm2X, pm2Y, lineGC);
3938 if (toX >= 0 && toY >= 0) {
3939 drawHighlight(toX, toY, prelineGC);
3949 ClearPremoveHighlights()
3951 SetPremoveHighlights(-1, -1, -1, -1);
3954 static void BlankSquare(x, y, color, piece, dest)
3959 if (useImages && useImageSqs) {
3963 pm = xpmLightSquare;
3968 case 2: /* neutral */
3973 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3974 squareSize, squareSize, x, y);
3984 case 2: /* neutral */
3989 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3994 I split out the routines to draw a piece so that I could
3995 make a generic flash routine.
3997 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3999 int square_color, x, y;
4002 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4003 switch (square_color) {
4005 case 2: /* neutral */
4007 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4008 ? *pieceToOutline(piece)
4009 : *pieceToSolid(piece),
4010 dest, bwPieceGC, 0, 0,
4011 squareSize, squareSize, x, y);
4014 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4015 ? *pieceToSolid(piece)
4016 : *pieceToOutline(piece),
4017 dest, wbPieceGC, 0, 0,
4018 squareSize, squareSize, x, y);
4023 static void monoDrawPiece(piece, square_color, x, y, dest)
4025 int square_color, x, y;
4028 switch (square_color) {
4030 case 2: /* neutral */
4032 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4033 ? *pieceToOutline(piece)
4034 : *pieceToSolid(piece),
4035 dest, bwPieceGC, 0, 0,
4036 squareSize, squareSize, x, y, 1);
4039 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4040 ? *pieceToSolid(piece)
4041 : *pieceToOutline(piece),
4042 dest, wbPieceGC, 0, 0,
4043 squareSize, squareSize, x, y, 1);
4048 static void colorDrawPiece(piece, square_color, x, y, dest)
4050 int square_color, x, y;
4053 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4054 switch (square_color) {
4056 XCopyPlane(xDisplay, *pieceToSolid(piece),
4057 dest, (int) piece < (int) BlackPawn
4058 ? wlPieceGC : blPieceGC, 0, 0,
4059 squareSize, squareSize, x, y, 1);
4062 XCopyPlane(xDisplay, *pieceToSolid(piece),
4063 dest, (int) piece < (int) BlackPawn
4064 ? wdPieceGC : bdPieceGC, 0, 0,
4065 squareSize, squareSize, x, y, 1);
4067 case 2: /* neutral */
4069 XCopyPlane(xDisplay, *pieceToSolid(piece),
4070 dest, (int) piece < (int) BlackPawn
4071 ? wjPieceGC : bjPieceGC, 0, 0,
4072 squareSize, squareSize, x, y, 1);
4077 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4079 int square_color, x, y;
4084 switch (square_color) {
4086 case 2: /* neutral */
4088 if ((int)piece < (int) BlackPawn) {
4096 if ((int)piece < (int) BlackPawn) {
4104 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4105 dest, wlPieceGC, 0, 0,
4106 squareSize, squareSize, x, y);
4109 typedef void (*DrawFunc)();
4111 DrawFunc ChooseDrawFunc()
4113 if (appData.monoMode) {
4114 if (DefaultDepth(xDisplay, xScreen) == 1) {
4115 return monoDrawPiece_1bit;
4117 return monoDrawPiece;
4121 return colorDrawPieceImage;
4123 return colorDrawPiece;
4127 /* [HR] determine square color depending on chess variant. */
4128 static int SquareColor(row, column)
4133 if (gameInfo.variant == VariantXiangqi) {
4134 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4136 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4138 } else if (row <= 4) {
4144 square_color = ((column + row) % 2) == 1;
4147 /* [hgm] holdings: next line makes all holdings squares light */
4148 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4150 return square_color;
4153 void DrawSquare(row, column, piece, do_flash)
4154 int row, column, do_flash;
4157 int square_color, x, y, direction, font_ascent, font_descent;
4160 XCharStruct overall;
4164 /* Calculate delay in milliseconds (2-delays per complete flash) */
4165 flash_delay = 500 / appData.flashRate;
4168 x = lineGap + ((BOARD_WIDTH-1)-column) *
4169 (squareSize + lineGap);
4170 y = lineGap + row * (squareSize + lineGap);
4172 x = lineGap + column * (squareSize + lineGap);
4173 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4174 (squareSize + lineGap);
4177 square_color = SquareColor(row, column);
4179 if ( // [HGM] holdings: blank out area between board and holdings
4180 column == BOARD_LEFT-1 || column == BOARD_RGHT
4181 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4182 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4183 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4185 // [HGM] print piece counts next to holdings
4186 string[1] = NULLCHAR;
4187 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4188 string[0] = '0' + piece;
4189 XTextExtents(countFontStruct, string, 1, &direction,
4190 &font_ascent, &font_descent, &overall);
4191 if (appData.monoMode) {
4192 XDrawImageString(xDisplay, xBoardWindow, countGC,
4193 x + squareSize - overall.width - 2,
4194 y + font_ascent + 1, string, 1);
4196 XDrawString(xDisplay, xBoardWindow, countGC,
4197 x + squareSize - overall.width - 2,
4198 y + font_ascent + 1, string, 1);
4201 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4202 string[0] = '0' + piece;
4203 XTextExtents(countFontStruct, string, 1, &direction,
4204 &font_ascent, &font_descent, &overall);
4205 if (appData.monoMode) {
4206 XDrawImageString(xDisplay, xBoardWindow, countGC,
4207 x + 2, y + font_ascent + 1, string, 1);
4209 XDrawString(xDisplay, xBoardWindow, countGC,
4210 x + 2, y + font_ascent + 1, string, 1);
4214 if (piece == EmptySquare || appData.blindfold) {
4215 BlankSquare(x, y, square_color, piece, xBoardWindow);
4217 drawfunc = ChooseDrawFunc();
4218 if (do_flash && appData.flashCount > 0) {
4219 for (i=0; i<appData.flashCount; ++i) {
4221 drawfunc(piece, square_color, x, y, xBoardWindow);
4222 XSync(xDisplay, False);
4223 do_flash_delay(flash_delay);
4225 BlankSquare(x, y, square_color, piece, xBoardWindow);
4226 XSync(xDisplay, False);
4227 do_flash_delay(flash_delay);
4230 drawfunc(piece, square_color, x, y, xBoardWindow);
4234 string[1] = NULLCHAR;
4235 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4236 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4237 string[0] = 'a' + column - BOARD_LEFT;
4238 XTextExtents(coordFontStruct, string, 1, &direction,
4239 &font_ascent, &font_descent, &overall);
4240 if (appData.monoMode) {
4241 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4242 x + squareSize - overall.width - 2,
4243 y + squareSize - font_descent - 1, string, 1);
4245 XDrawString(xDisplay, xB