2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
65 # if HAVE_SYS_SOCKET_H
66 # include <sys/socket.h>
67 # include <netinet/in.h>
69 # else /* not HAVE_SYS_SOCKET_H */
70 # if HAVE_LAN_SOCKET_H
71 # include <lan/socket.h>
73 # include <lan/netdb.h>
74 # else /* not HAVE_LAN_SOCKET_H */
75 # define OMIT_SOCKETS 1
76 # endif /* not HAVE_LAN_SOCKET_H */
77 # endif /* not HAVE_SYS_SOCKET_H */
78 #endif /* !OMIT_SOCKETS */
83 #else /* not STDC_HEADERS */
84 extern char *getenv();
87 # else /* not HAVE_STRING_H */
89 # endif /* not HAVE_STRING_H */
90 #endif /* not STDC_HEADERS */
93 # include <sys/fcntl.h>
94 #else /* not HAVE_SYS_FCNTL_H */
97 # endif /* HAVE_FCNTL_H */
98 #endif /* not HAVE_SYS_FCNTL_H */
100 #if HAVE_SYS_SYSTEMINFO_H
101 # include <sys/systeminfo.h>
102 #endif /* HAVE_SYS_SYSTEMINFO_H */
104 #if TIME_WITH_SYS_TIME
105 # include <sys/time.h>
109 # include <sys/time.h>
120 # include <sys/wait.h>
125 # define NAMLEN(dirent) strlen((dirent)->d_name)
126 # define HAVE_DIR_STRUCT
128 # define dirent direct
129 # define NAMLEN(dirent) (dirent)->d_namlen
131 # include <sys/ndir.h>
132 # define HAVE_DIR_STRUCT
135 # include <sys/dir.h>
136 # define HAVE_DIR_STRUCT
140 # define HAVE_DIR_STRUCT
144 #include <X11/Intrinsic.h>
145 #include <X11/StringDefs.h>
146 #include <X11/Shell.h>
147 #include <X11/cursorfont.h>
148 #include <X11/Xatom.h>
149 #include <X11/Xmu/Atoms.h>
151 #include <X11/Xaw3d/Dialog.h>
152 #include <X11/Xaw3d/Form.h>
153 #include <X11/Xaw3d/List.h>
154 #include <X11/Xaw3d/Label.h>
155 #include <X11/Xaw3d/SimpleMenu.h>
156 #include <X11/Xaw3d/SmeBSB.h>
157 #include <X11/Xaw3d/SmeLine.h>
158 #include <X11/Xaw3d/Box.h>
159 #include <X11/Xaw3d/MenuButton.h>
160 #include <X11/Xaw3d/Text.h>
161 #include <X11/Xaw3d/AsciiText.h>
163 #include <X11/Xaw/Dialog.h>
164 #include <X11/Xaw/Form.h>
165 #include <X11/Xaw/List.h>
166 #include <X11/Xaw/Label.h>
167 #include <X11/Xaw/SimpleMenu.h>
168 #include <X11/Xaw/SmeBSB.h>
169 #include <X11/Xaw/SmeLine.h>
170 #include <X11/Xaw/Box.h>
171 #include <X11/Xaw/MenuButton.h>
172 #include <X11/Xaw/Text.h>
173 #include <X11/Xaw/AsciiText.h>
176 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
181 #include "pixmaps/pixmaps.h"
182 #define IMAGE_EXT "xpm"
184 #define IMAGE_EXT "xim"
185 #include "bitmaps/bitmaps.h"
188 #include "bitmaps/icon_white.bm"
189 #include "bitmaps/icon_black.bm"
190 #include "bitmaps/checkmark.bm"
192 #include "frontend.h"
194 #include "backendz.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
203 // must be moved to xengineoutput.h
205 void EngineOutputProc P((Widget w, XEvent *event,
206 String *prms, Cardinal *nprms));
207 void EvalGraphProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
215 #define usleep(t) _sleep2(((t)+500)/1000)
219 # define _(s) gettext (s)
220 # define N_(s) gettext_noop (s)
236 int main P((int argc, char **argv));
237 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
238 char *init_path, char *mode, int (*show_entry)(), char **name_return));
239 RETSIGTYPE CmailSigHandler P((int sig));
240 RETSIGTYPE IntSigHandler P((int sig));
241 RETSIGTYPE TermSizeSigHandler P((int sig));
242 void CreateGCs P((void));
243 void CreateXIMPieces P((void));
244 void CreateXPMPieces P((void));
245 void CreatePieces P((void));
246 void CreatePieceMenus P((void));
247 Widget CreateMenuBar P((Menu *mb));
248 Widget CreateButtonBar P ((MenuItem *mi));
249 char *FindFont P((char *pattern, int targetPxlSize));
250 void PieceMenuPopup P((Widget w, XEvent *event,
251 String *params, Cardinal *num_params));
252 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
253 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
254 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
255 u_int wreq, u_int hreq));
256 void CreateGrid P((void));
257 int EventToSquare P((int x, int limit));
258 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
259 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
260 void HandleUserMove P((Widget w, XEvent *event,
261 String *prms, Cardinal *nprms));
262 void AnimateUserMove P((Widget w, XEvent * event,
263 String * params, Cardinal * nParams));
264 void HandlePV P((Widget w, XEvent * event,
265 String * params, Cardinal * nParams));
266 void SelectPV P((Widget w, XEvent * event,
267 String * params, Cardinal * nParams));
268 void StopPV P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void WhiteClock P((Widget w, XEvent *event,
271 String *prms, Cardinal *nprms));
272 void BlackClock P((Widget w, XEvent *event,
273 String *prms, Cardinal *nprms));
274 void DrawPositionProc P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
278 void CommentClick P((Widget w, XEvent * event,
279 String * params, Cardinal * nParams));
280 void CommentPopUp P((char *title, char *label));
281 void CommentPopDown P((void));
282 void CommentCallback P((Widget w, XtPointer client_data,
283 XtPointer call_data));
284 void ICSInputBoxPopUp P((void));
285 void ICSInputBoxPopDown P((void));
286 void FileNamePopUp P((char *label, char *def,
287 FileProc proc, char *openMode));
288 void FileNamePopDown P((void));
289 void FileNameCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void FileNameAction P((Widget w, XEvent *event,
292 String *prms, Cardinal *nprms));
293 void AskQuestionReplyAction P((Widget w, XEvent *event,
294 String *prms, Cardinal *nprms));
295 void AskQuestionProc P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void AskQuestionPopDown P((void));
298 void PromotionPopDown P((void));
299 void PromotionCallback P((Widget w, XtPointer client_data,
300 XtPointer call_data));
301 void EditCommentPopDown P((void));
302 void EditCommentCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
305 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
309 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
311 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
313 void LoadPositionProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
317 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
319 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
321 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
323 void PastePositionProc P((Widget w, XEvent *event, String *prms,
325 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void SavePositionProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
333 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
337 void MachineWhiteProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void AnalyzeModeProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AnalyzeFileProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
345 void IcsClientProc P((Widget w, XEvent *event, String *prms,
347 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void EditPositionProc P((Widget w, XEvent *event,
349 String *prms, Cardinal *nprms));
350 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void EditCommentProc P((Widget w, XEvent *event,
352 String *prms, Cardinal *nprms));
353 void IcsInputBoxProc P((Widget w, XEvent *event,
354 String *prms, Cardinal *nprms));
355 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void StopObservingProc P((Widget w, XEvent *event, String *prms,
371 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
373 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
382 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
384 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
387 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
389 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
391 void AutocommProc P((Widget w, XEvent *event, String *prms,
393 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void AutobsProc P((Widget w, XEvent *event, String *prms,
397 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
402 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
405 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
407 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
409 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
413 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
415 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
417 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
419 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
421 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
423 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
425 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
427 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
429 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
431 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void DisplayMove P((int moveNumber));
443 void DisplayTitle P((char *title));
444 void ICSInitScript P((void));
445 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
446 void ErrorPopUp P((char *title, char *text, int modal));
447 void ErrorPopDown P((void));
448 static char *ExpandPathName P((char *path));
449 static void CreateAnimVars P((void));
450 static void DragPieceMove P((int x, int y));
451 static void DrawDragPiece P((void));
452 char *ModeToWidgetName P((GameMode mode));
453 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void GameListOptionsPopDown P(());
462 void ShufflePopDown P(());
463 void EnginePopDown P(());
464 void UciPopDown P(());
465 void TimeControlPopDown P(());
466 void NewVariantPopDown P(());
467 void SettingsPopDown P(());
468 void update_ics_width P(());
469 int get_term_width P(());
470 int CopyMemoProc P(());
472 * XBoard depends on Xt R4 or higher
474 int xtVersion = XtSpecificationRelease;
479 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
480 jailSquareColor, highlightSquareColor, premoveHighlightColor;
481 Pixel lowTimeWarningColor;
482 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
483 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
484 wjPieceGC, bjPieceGC, prelineGC, countGC;
485 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
486 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
487 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
488 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
489 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
490 ICSInputShell, fileNameShell, askQuestionShell;
491 Widget historyShell, evalGraphShell, gameListShell;
492 int hOffset; // [HGM] dual
493 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
494 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
495 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
496 Font clockFontID, coordFontID, countFontID;
497 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
498 XtAppContext appContext;
500 char *oldICSInteractionTitle;
504 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
506 Position commentX = -1, commentY = -1;
507 Dimension commentW, commentH;
508 typedef unsigned int BoardSize;
510 Boolean chessProgram;
512 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
513 int squareSize, smallLayout = 0, tinyLayout = 0,
514 marginW, marginH, // [HGM] for run-time resizing
515 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
516 ICSInputBoxUp = False, askQuestionUp = False,
517 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
518 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
519 Pixel timerForegroundPixel, timerBackgroundPixel;
520 Pixel buttonForegroundPixel, buttonBackgroundPixel;
521 char *chessDir, *programName, *programVersion,
522 *gameCopyFilename, *gamePasteFilename;
523 Boolean alwaysOnTop = False;
524 Boolean saveSettingsOnExit;
525 char *settingsFileName;
526 char *icsTextMenuString;
528 char *firstChessProgramNames;
529 char *secondChessProgramNames;
531 WindowPlacement wpMain;
532 WindowPlacement wpConsole;
533 WindowPlacement wpComment;
534 WindowPlacement wpMoveHistory;
535 WindowPlacement wpEvalGraph;
536 WindowPlacement wpEngineOutput;
537 WindowPlacement wpGameList;
538 WindowPlacement wpTags;
542 Pixmap pieceBitmap[2][(int)BlackPawn];
543 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
544 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
545 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
546 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
547 int useImages, useImageSqs;
548 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
549 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
550 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
551 XImage *ximLightSquare, *ximDarkSquare;
554 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
555 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
557 #define White(piece) ((int)(piece) < (int)BlackPawn)
559 /* Variables for doing smooth animation. This whole thing
560 would be much easier if the board was double-buffered,
561 but that would require a fairly major rewrite. */
566 GC blitGC, pieceGC, outlineGC;
567 XPoint startSquare, prevFrame, mouseDelta;
571 int startBoardX, startBoardY;
574 /* There can be two pieces being animated at once: a player
575 can begin dragging a piece before the remote opponent has moved. */
577 static AnimState game, player;
579 /* Bitmaps for use as masks when drawing XPM pieces.
580 Need one for each black and white piece. */
581 static Pixmap xpmMask[BlackKing + 1];
583 /* This magic number is the number of intermediate frames used
584 in each half of the animation. For short moves it's reduced
585 by 1. The total number of frames will be factor * 2 + 1. */
588 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
590 MenuItem fileMenu[] = {
591 {N_("New Game"), ResetProc},
592 {N_("New Shuffle Game ..."), ShuffleMenuProc},
593 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
594 {"----", NothingProc},
595 {N_("Load Game"), LoadGameProc},
596 {N_("Load Next Game"), LoadNextGameProc},
597 {N_("Load Previous Game"), LoadPrevGameProc},
598 {N_("Reload Same Game"), ReloadGameProc},
599 {N_("Save Game"), SaveGameProc},
600 {"----", NothingProc},
601 {N_("Copy Game"), CopyGameProc},
602 {N_("Paste Game"), PasteGameProc},
603 {"----", NothingProc},
604 {N_("Load Position"), LoadPositionProc},
605 {N_("Load Next Position"), LoadNextPositionProc},
606 {N_("Load Previous Position"), LoadPrevPositionProc},
607 {N_("Reload Same Position"), ReloadPositionProc},
608 {N_("Save Position"), SavePositionProc},
609 {"----", NothingProc},
610 {N_("Copy Position"), CopyPositionProc},
611 {N_("Paste Position"), PastePositionProc},
612 {"----", NothingProc},
613 {N_("Mail Move"), MailMoveProc},
614 {N_("Reload CMail Message"), ReloadCmailMsgProc},
615 {"----", NothingProc},
616 {N_("Exit"), QuitProc},
620 MenuItem modeMenu[] = {
621 {N_("Machine White"), MachineWhiteProc},
622 {N_("Machine Black"), MachineBlackProc},
623 {N_("Two Machines"), TwoMachinesProc},
624 {N_("Analysis Mode"), AnalyzeModeProc},
625 {N_("Analyze File"), AnalyzeFileProc },
626 {N_("ICS Client"), IcsClientProc},
627 {N_("Edit Game"), EditGameProc},
628 {N_("Edit Position"), EditPositionProc},
629 {N_("Training"), TrainingProc},
630 {"----", NothingProc},
631 {N_("Show Engine Output"), EngineOutputProc},
632 {N_("Show Evaluation Graph"), EvalGraphProc},
633 {N_("Show Game List"), ShowGameListProc},
634 {N_("Show Move History"), HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
635 {"----", NothingProc},
636 {N_("Edit Tags"), EditTagsProc},
637 {N_("Edit Comment"), EditCommentProc},
638 {N_("ICS Input Box"), IcsInputBoxProc},
639 {N_("Pause"), PauseProc},
643 MenuItem actionMenu[] = {
644 {N_("Accept"), AcceptProc},
645 {N_("Decline"), DeclineProc},
646 {N_("Rematch"), RematchProc},
647 {"----", NothingProc},
648 {N_("Call Flag"), CallFlagProc},
649 {N_("Draw"), DrawProc},
650 {N_("Adjourn"), AdjournProc},
651 {N_("Abort"), AbortProc},
652 {N_("Resign"), ResignProc},
653 {"----", NothingProc},
654 {N_("Stop Observing"), StopObservingProc},
655 {N_("Stop Examining"), StopExaminingProc},
656 {N_("Upload to Examine"), UploadProc},
657 {"----", NothingProc},
658 {N_("Adjudicate to White"), AdjuWhiteProc},
659 {N_("Adjudicate to Black"), AdjuBlackProc},
660 {N_("Adjudicate Draw"), AdjuDrawProc},
664 MenuItem stepMenu[] = {
665 {N_("Backward"), BackwardProc},
666 {N_("Forward"), ForwardProc},
667 {N_("Back to Start"), ToStartProc},
668 {N_("Forward to End"), ToEndProc},
669 {N_("Revert"), RevertProc},
670 {N_("Annotate"), AnnotateProc},
671 {N_("Truncate Game"), TruncateGameProc},
672 {"----", NothingProc},
673 {N_("Move Now"), MoveNowProc},
674 {N_("Retract Move"), RetractMoveProc},
678 MenuItem optionsMenu[] = {
679 {N_("Flip View"), FlipViewProc},
680 {"----", NothingProc},
681 {N_("Adjudications ..."), EngineMenuProc},
682 {N_("General Settings ..."), UciMenuProc},
683 {N_("Engine #1 Settings ..."), FirstSettingsProc},
684 {N_("Engine #2 Settings ..."), SecondSettingsProc},
685 {N_("Time Control ..."), TimeControlProc},
686 {N_("Game List ..."), GameListOptionsPopUp},
687 {"----", NothingProc},
688 {N_("Always Queen"), AlwaysQueenProc},
689 {N_("Animate Dragging"), AnimateDraggingProc},
690 {N_("Animate Moving"), AnimateMovingProc},
691 {N_("Auto Comment"), AutocommProc},
692 {N_("Auto Flag"), AutoflagProc},
693 {N_("Auto Flip View"), AutoflipProc},
694 {N_("Auto Observe"), AutobsProc},
695 {N_("Auto Raise Board"), AutoraiseProc},
696 {N_("Auto Save"), AutosaveProc},
697 {N_("Blindfold"), BlindfoldProc},
698 {N_("Flash Moves"), FlashMovesProc},
699 {N_("Get Move List"), GetMoveListProc},
701 {N_("Highlight Dragging"), HighlightDraggingProc},
703 {N_("Highlight Last Move"), HighlightLastMoveProc},
704 {N_("Move Sound"), MoveSoundProc},
705 {N_("ICS Alarm"), IcsAlarmProc},
706 {N_("Old Save Style"), OldSaveStyleProc},
707 {N_("Periodic Updates"), PeriodicUpdatesProc},
708 {N_("Ponder Next Move"), PonderNextMoveProc},
709 {N_("Popup Exit Message"), PopupExitMessageProc},
710 {N_("Popup Move Errors"), PopupMoveErrorsProc},
711 {N_("Premove"), PremoveProc},
712 {N_("Quiet Play"), QuietPlayProc},
713 {N_("Show Coords"), ShowCoordsProc},
714 {N_("Hide Thinking"), HideThinkingProc},
715 {N_("Test Legality"), TestLegalityProc},
716 {"----", NothingProc},
717 {N_("Save Settings Now"), SaveSettingsProc},
718 {N_("Save Settings on Exit"), SaveOnExitProc},
722 MenuItem helpMenu[] = {
723 {N_("Info XBoard"), InfoProc},
724 {N_("Man XBoard"), ManProc},
725 {"----", NothingProc},
726 {N_("Hint"), HintProc},
727 {N_("Book"), BookProc},
728 {"----", NothingProc},
729 {N_("About XBoard"), AboutProc},
734 {N_("File"), fileMenu},
735 {N_("Mode"), modeMenu},
736 {N_("Action"), actionMenu},
737 {N_("Step"), stepMenu},
738 {N_("Options"), optionsMenu},
739 {N_("Help"), helpMenu},
743 #define PAUSE_BUTTON N_("P")
744 MenuItem buttonBar[] = {
747 {PAUSE_BUTTON, PauseProc},
753 #define PIECE_MENU_SIZE 18
754 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
755 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
756 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
757 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
758 N_("Empty square"), N_("Clear board") },
759 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
760 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
761 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
762 N_("Empty square"), N_("Clear board") }
764 /* must be in same order as PieceMenuStrings! */
765 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
766 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
767 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
768 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
769 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
770 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
771 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
772 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
773 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
776 #define DROP_MENU_SIZE 6
777 String dropMenuStrings[DROP_MENU_SIZE] = {
778 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
780 /* must be in same order as PieceMenuStrings! */
781 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
782 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
783 WhiteRook, WhiteQueen
791 DropMenuEnables dmEnables[] = {
809 { XtNborderWidth, 0 },
810 { XtNdefaultDistance, 0 },
814 { XtNborderWidth, 0 },
815 { XtNresizable, (XtArgVal) True },
819 { XtNborderWidth, 0 },
825 { XtNjustify, (XtArgVal) XtJustifyRight },
826 { XtNlabel, (XtArgVal) "..." },
827 { XtNresizable, (XtArgVal) True },
828 { XtNresize, (XtArgVal) False }
831 Arg messageArgs[] = {
832 { XtNjustify, (XtArgVal) XtJustifyLeft },
833 { XtNlabel, (XtArgVal) "..." },
834 { XtNresizable, (XtArgVal) True },
835 { XtNresize, (XtArgVal) False }
839 { XtNborderWidth, 0 },
840 { XtNjustify, (XtArgVal) XtJustifyLeft }
843 XtResource clientResources[] = {
844 { "flashCount", "flashCount", XtRInt, sizeof(int),
845 XtOffset(AppDataPtr, flashCount), XtRImmediate,
846 (XtPointer) FLASH_COUNT },
849 XrmOptionDescRec shellOptions[] = {
850 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
851 { "-flash", "flashCount", XrmoptionNoArg, "3" },
852 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
855 XtActionsRec boardActions[] = {
856 { "DrawPosition", DrawPositionProc },
857 { "HandleUserMove", HandleUserMove },
858 { "AnimateUserMove", AnimateUserMove },
859 { "HandlePV", HandlePV },
860 { "SelectPV", SelectPV },
861 { "StopPV", StopPV },
862 { "FileNameAction", FileNameAction },
863 { "AskQuestionProc", AskQuestionProc },
864 { "AskQuestionReplyAction", AskQuestionReplyAction },
865 { "PieceMenuPopup", PieceMenuPopup },
866 { "WhiteClock", WhiteClock },
867 { "BlackClock", BlackClock },
868 { "Iconify", Iconify },
869 { "ResetProc", ResetProc },
870 { "NewVariantProc", NewVariantProc },
871 { "LoadGameProc", LoadGameProc },
872 { "LoadNextGameProc", LoadNextGameProc },
873 { "LoadPrevGameProc", LoadPrevGameProc },
874 { "LoadSelectedProc", LoadSelectedProc },
875 { "SetFilterProc", SetFilterProc },
876 { "ReloadGameProc", ReloadGameProc },
877 { "LoadPositionProc", LoadPositionProc },
878 { "LoadNextPositionProc", LoadNextPositionProc },
879 { "LoadPrevPositionProc", LoadPrevPositionProc },
880 { "ReloadPositionProc", ReloadPositionProc },
881 { "CopyPositionProc", CopyPositionProc },
882 { "PastePositionProc", PastePositionProc },
883 { "CopyGameProc", CopyGameProc },
884 { "PasteGameProc", PasteGameProc },
885 { "SaveGameProc", SaveGameProc },
886 { "SavePositionProc", SavePositionProc },
887 { "MailMoveProc", MailMoveProc },
888 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
889 { "QuitProc", QuitProc },
890 { "MachineWhiteProc", MachineWhiteProc },
891 { "MachineBlackProc", MachineBlackProc },
892 { "AnalysisModeProc", AnalyzeModeProc },
893 { "AnalyzeFileProc", AnalyzeFileProc },
894 { "TwoMachinesProc", TwoMachinesProc },
895 { "IcsClientProc", IcsClientProc },
896 { "EditGameProc", EditGameProc },
897 { "EditPositionProc", EditPositionProc },
898 { "TrainingProc", EditPositionProc },
899 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
900 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
901 { "ShowGameListProc", ShowGameListProc },
902 { "ShowMoveListProc", HistoryShowProc},
903 { "EditTagsProc", EditCommentProc },
904 { "EditCommentProc", EditCommentProc },
905 { "IcsAlarmProc", IcsAlarmProc },
906 { "IcsInputBoxProc", IcsInputBoxProc },
907 { "PauseProc", PauseProc },
908 { "AcceptProc", AcceptProc },
909 { "DeclineProc", DeclineProc },
910 { "RematchProc", RematchProc },
911 { "CallFlagProc", CallFlagProc },
912 { "DrawProc", DrawProc },
913 { "AdjournProc", AdjournProc },
914 { "AbortProc", AbortProc },
915 { "ResignProc", ResignProc },
916 { "AdjuWhiteProc", AdjuWhiteProc },
917 { "AdjuBlackProc", AdjuBlackProc },
918 { "AdjuDrawProc", AdjuDrawProc },
919 { "EnterKeyProc", EnterKeyProc },
920 { "UpKeyProc", UpKeyProc },
921 { "DownKeyProc", DownKeyProc },
922 { "StopObservingProc", StopObservingProc },
923 { "StopExaminingProc", StopExaminingProc },
924 { "UploadProc", UploadProc },
925 { "BackwardProc", BackwardProc },
926 { "ForwardProc", ForwardProc },
927 { "ToStartProc", ToStartProc },
928 { "ToEndProc", ToEndProc },
929 { "RevertProc", RevertProc },
930 { "AnnotateProc", AnnotateProc },
931 { "TruncateGameProc", TruncateGameProc },
932 { "MoveNowProc", MoveNowProc },
933 { "RetractMoveProc", RetractMoveProc },
934 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
935 { "UciMenuProc", (XtActionProc) UciMenuProc },
936 { "TimeControlProc", (XtActionProc) TimeControlProc },
937 { "AlwaysQueenProc", AlwaysQueenProc },
938 { "AnimateDraggingProc", AnimateDraggingProc },
939 { "AnimateMovingProc", AnimateMovingProc },
940 { "AutoflagProc", AutoflagProc },
941 { "AutoflipProc", AutoflipProc },
942 { "AutobsProc", AutobsProc },
943 { "AutoraiseProc", AutoraiseProc },
944 { "AutosaveProc", AutosaveProc },
945 { "BlindfoldProc", BlindfoldProc },
946 { "FlashMovesProc", FlashMovesProc },
947 { "FlipViewProc", FlipViewProc },
948 { "GetMoveListProc", GetMoveListProc },
950 { "HighlightDraggingProc", HighlightDraggingProc },
952 { "HighlightLastMoveProc", HighlightLastMoveProc },
953 { "IcsAlarmProc", IcsAlarmProc },
954 { "MoveSoundProc", MoveSoundProc },
955 { "OldSaveStyleProc", OldSaveStyleProc },
956 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
957 { "PonderNextMoveProc", PonderNextMoveProc },
958 { "PopupExitMessageProc", PopupExitMessageProc },
959 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
960 { "PremoveProc", PremoveProc },
961 { "QuietPlayProc", QuietPlayProc },
962 { "ShowCoordsProc", ShowCoordsProc },
963 { "ShowThinkingProc", ShowThinkingProc },
964 { "HideThinkingProc", HideThinkingProc },
965 { "TestLegalityProc", TestLegalityProc },
966 { "SaveSettingsProc", SaveSettingsProc },
967 { "SaveOnExitProc", SaveOnExitProc },
968 { "InfoProc", InfoProc },
969 { "ManProc", ManProc },
970 { "HintProc", HintProc },
971 { "BookProc", BookProc },
972 { "AboutGameProc", AboutGameProc },
973 { "AboutProc", AboutProc },
974 { "DebugProc", DebugProc },
975 { "NothingProc", NothingProc },
976 { "CommentClick", (XtActionProc) CommentClick },
977 { "CommentPopDown", (XtActionProc) CommentPopDown },
978 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
979 { "TagsPopDown", (XtActionProc) TagsPopDown },
980 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
981 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
982 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
983 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
984 { "GameListPopDown", (XtActionProc) GameListPopDown },
985 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
986 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
987 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
988 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
989 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
990 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
991 { "EnginePopDown", (XtActionProc) EnginePopDown },
992 { "UciPopDown", (XtActionProc) UciPopDown },
993 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
994 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
995 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
996 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
999 char globalTranslations[] =
1000 ":<Key>F9: ResignProc() \n \
1001 :Ctrl<Key>n: ResetProc() \n \
1002 :Meta<Key>V: NewVariantProc() \n \
1003 :Ctrl<Key>o: LoadGameProc() \n \
1004 :Meta<Key>Next: LoadNextGameProc() \n \
1005 :Meta<Key>Prior: LoadPrevGameProc() \n \
1006 :Ctrl<Key>s: SaveGameProc() \n \
1007 :Ctrl<Key>c: CopyGameProc() \n \
1008 :Ctrl<Key>v: PasteGameProc() \n \
1009 :Ctrl<Key>O: LoadPositionProc() \n \
1010 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1011 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1012 :Ctrl<Key>S: SavePositionProc() \n \
1013 :Ctrl<Key>C: CopyPositionProc() \n \
1014 :Ctrl<Key>V: PastePositionProc() \n \
1015 :Ctrl<Key>q: QuitProc() \n \
1016 :Ctrl<Key>w: MachineWhiteProc() \n \
1017 :Ctrl<Key>b: MachineBlackProc() \n \
1018 :Ctrl<Key>t: TwoMachinesProc() \n \
1019 :Ctrl<Key>a: AnalysisModeProc() \n \
1020 :Ctrl<Key>f: AnalyzeFileProc() \n \
1021 :Ctrl<Key>e: EditGameProc() \n \
1022 :Ctrl<Key>E: EditPositionProc() \n \
1023 :Meta<Key>O: EngineOutputProc() \n \
1024 :Meta<Key>E: EvalGraphProc() \n \
1025 :Meta<Key>G: ShowGameListProc() \n \
1026 :Meta<Key>H: ShowMoveListProc() \n \
1027 :<Key>Pause: PauseProc() \n \
1028 :<Key>F3: AcceptProc() \n \
1029 :<Key>F4: DeclineProc() \n \
1030 :<Key>F12: RematchProc() \n \
1031 :<Key>F5: CallFlagProc() \n \
1032 :<Key>F6: DrawProc() \n \
1033 :<Key>F7: AdjournProc() \n \
1034 :<Key>F8: AbortProc() \n \
1035 :<Key>F10: StopObservingProc() \n \
1036 :<Key>F11: StopExaminingProc() \n \
1037 :Meta Ctrl<Key>F12: DebugProc() \n \
1038 :Meta<Key>End: ToEndProc() \n \
1039 :Meta<Key>Right: ForwardProc() \n \
1040 :Meta<Key>Home: ToStartProc() \n \
1041 :Meta<Key>Left: BackwardProc() \n \
1042 :Ctrl<Key>m: MoveNowProc() \n \
1043 :Ctrl<Key>x: RetractMoveProc() \n \
1044 :Meta<Key>J: EngineMenuProc() \n \
1045 :Meta<Key>U: UciMenuProc() \n \
1046 :Meta<Key>T: TimeControlProc() \n \
1047 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1048 :Ctrl<Key>F: AutoflagProc() \n \
1049 :Ctrl<Key>A: AnimateMovingProc() \n \
1050 :Ctrl<Key>P: PonderNextMoveProc() \n \
1051 :Ctrl<Key>L: TestLegalityProc() \n \
1052 :Ctrl<Key>H: HideThinkingProc() \n \
1053 :<Key>-: Iconify() \n \
1054 :<Key>F1: ManProc() \n \
1055 :<Key>F2: FlipViewProc() \n \
1056 <KeyDown>.: BackwardProc() \n \
1057 <KeyUp>.: ForwardProc() \n \
1058 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1059 \"Send to chess program:\",,1) \n \
1060 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1061 \"Send to second chess program:\",,2) \n";
1063 char boardTranslations[] =
1064 "<Btn1Down>: HandleUserMove() \n \
1065 <Btn1Up>: HandleUserMove() \n \
1066 <Btn1Motion>: AnimateUserMove() \n \
1067 <Btn3Motion>: HandlePV() \n \
1068 <Btn3Up>: PieceMenuPopup(menuB) \n \
1069 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1070 PieceMenuPopup(menuB) \n \
1071 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1072 PieceMenuPopup(menuW) \n \
1073 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1074 PieceMenuPopup(menuW) \n \
1075 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1076 PieceMenuPopup(menuB) \n";
1078 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1079 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1081 char ICSInputTranslations[] =
1082 "<Key>Up: UpKeyProc() \n "
1083 "<Key>Down: DownKeyProc() \n "
1084 "<Key>Return: EnterKeyProc() \n";
1086 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1087 // as the widget is destroyed before the up-click can call extend-end
1088 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1090 String xboardResources[] = {
1091 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1092 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1093 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1098 /* Max possible square size */
1099 #define MAXSQSIZE 256
1101 static int xpm_avail[MAXSQSIZE];
1103 #ifdef HAVE_DIR_STRUCT
1105 /* Extract piece size from filename */
1107 xpm_getsize(name, len, ext)
1118 if ((p=strchr(name, '.')) == NULL ||
1119 StrCaseCmp(p+1, ext) != 0)
1125 while (*p && isdigit(*p))
1132 /* Setup xpm_avail */
1134 xpm_getavail(dirname, ext)
1142 for (i=0; i<MAXSQSIZE; ++i)
1145 if (appData.debugMode)
1146 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1148 dir = opendir(dirname);
1151 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1152 programName, dirname);
1156 while ((ent=readdir(dir)) != NULL) {
1157 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1158 if (i > 0 && i < MAXSQSIZE)
1168 xpm_print_avail(fp, ext)
1174 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1175 for (i=1; i<MAXSQSIZE; ++i) {
1181 /* Return XPM piecesize closest to size */
1183 xpm_closest_to(dirname, size, ext)
1189 int sm_diff = MAXSQSIZE;
1193 xpm_getavail(dirname, ext);
1195 if (appData.debugMode)
1196 xpm_print_avail(stderr, ext);
1198 for (i=1; i<MAXSQSIZE; ++i) {
1201 diff = (diff<0) ? -diff : diff;
1202 if (diff < sm_diff) {
1210 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1216 #else /* !HAVE_DIR_STRUCT */
1217 /* If we are on a system without a DIR struct, we can't
1218 read the directory, so we can't collect a list of
1219 filenames, etc., so we can't do any size-fitting. */
1221 xpm_closest_to(dirname, size, ext)
1226 fprintf(stderr, _("\
1227 Warning: No DIR structure found on this system --\n\
1228 Unable to autosize for XPM/XIM pieces.\n\
1229 Please report this error to frankm@hiwaay.net.\n\
1230 Include system type & operating system in message.\n"));
1233 #endif /* HAVE_DIR_STRUCT */
1235 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1236 "magenta", "cyan", "white" };
1240 TextColors textColors[(int)NColorClasses];
1242 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1244 parse_color(str, which)
1248 char *p, buf[100], *d;
1251 if (strlen(str) > 99) /* watch bounds on buf */
1256 for (i=0; i<which; ++i) {
1263 /* Could be looking at something like:
1265 .. in which case we want to stop on a comma also */
1266 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1270 return -1; /* Use default for empty field */
1273 if (which == 2 || isdigit(*p))
1276 while (*p && isalpha(*p))
1281 for (i=0; i<8; ++i) {
1282 if (!StrCaseCmp(buf, cnames[i]))
1283 return which? (i+40) : (i+30);
1285 if (!StrCaseCmp(buf, "default")) return -1;
1287 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1292 parse_cpair(cc, str)
1296 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1297 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1302 /* bg and attr are optional */
1303 textColors[(int)cc].bg = parse_color(str, 1);
1304 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1305 textColors[(int)cc].attr = 0;
1311 /* Arrange to catch delete-window events */
1312 Atom wm_delete_window;
1314 CatchDeleteWindow(Widget w, String procname)
1317 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1318 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1319 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1326 XtSetArg(args[0], XtNiconic, False);
1327 XtSetValues(shellWidget, args, 1);
1329 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1332 //---------------------------------------------------------------------------------------------------------
1333 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1336 #define CW_USEDEFAULT (1<<31)
1337 #define ICS_TEXT_MENU_SIZE 90
1338 #define DEBUG_FILE "xboard.debug"
1339 #define SetCurrentDirectory chdir
1340 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1344 // these two must some day move to frontend.h, when they are implemented
1345 Boolean GameListIsUp();
1347 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1350 // front-end part of option handling
1352 // [HGM] This platform-dependent table provides the location for storing the color info
1353 extern char *crWhite, * crBlack;
1357 &appData.whitePieceColor,
1358 &appData.blackPieceColor,
1359 &appData.lightSquareColor,
1360 &appData.darkSquareColor,
1361 &appData.highlightSquareColor,
1362 &appData.premoveHighlightColor,
1363 &appData.lowTimeWarningColor,
1374 // [HGM] font: keep a font for each square size, even non-stndard ones
1375 #define NUM_SIZES 18
1376 #define MAX_SIZE 130
1377 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1378 char *fontTable[NUM_FONTS][MAX_SIZE];
1381 ParseFont(char *name, int number)
1382 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1384 if(sscanf(name, "size%d:", &size)) {
1385 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1386 // defer processing it until we know if it matches our board size
1387 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1388 fontTable[number][size] = strdup(strchr(name, ':')+1);
1389 fontValid[number][size] = True;
1394 case 0: // CLOCK_FONT
1395 appData.clockFont = strdup(name);
1397 case 1: // MESSAGE_FONT
1398 appData.font = strdup(name);
1400 case 2: // COORD_FONT
1401 appData.coordFont = strdup(name);
1406 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1411 { // only 2 fonts currently
1412 appData.clockFont = CLOCK_FONT_NAME;
1413 appData.coordFont = COORD_FONT_NAME;
1414 appData.font = DEFAULT_FONT_NAME;
1419 { // no-op, until we identify the code for this already in XBoard and move it here
1423 ParseColor(int n, char *name)
1424 { // in XBoard, just copy the color-name string
1425 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1429 ParseTextAttribs(ColorClass cc, char *s)
1431 (&appData.colorShout)[cc] = strdup(s);
1435 ParseBoardSize(void *addr, char *name)
1437 appData.boardSize = strdup(name);
1442 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1446 SetCommPortDefaults()
1447 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1450 // [HGM] args: these three cases taken out to stay in front-end
1452 SaveFontArg(FILE *f, ArgDescriptor *ad)
1455 int i, n = (int)ad->argLoc;
1457 case 0: // CLOCK_FONT
1458 name = appData.clockFont;
1460 case 1: // MESSAGE_FONT
1461 name = appData.font;
1463 case 2: // COORD_FONT
1464 name = appData.coordFont;
1469 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1470 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1471 fontTable[n][squareSize] = strdup(name);
1472 fontValid[n][squareSize] = True;
1475 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1476 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1481 { // nothing to do, as the sounds are at all times represented by their text-string names already
1485 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1486 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1487 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1491 SaveColor(FILE *f, ArgDescriptor *ad)
1492 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1493 if(colorVariable[(int)ad->argLoc])
1494 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1498 SaveBoardSize(FILE *f, char *name, void *addr)
1499 { // wrapper to shield back-end from BoardSize & sizeInfo
1500 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1504 ParseCommPortSettings(char *s)
1505 { // no such option in XBoard (yet)
1508 extern Widget engineOutputShell;
1509 extern Widget tagsShell, editTagsShell;
1511 GetActualPlacement(Widget wg, WindowPlacement *wp)
1521 XtSetArg(args[i], XtNx, &x); i++;
1522 XtSetArg(args[i], XtNy, &y); i++;
1523 XtSetArg(args[i], XtNwidth, &w); i++;
1524 XtSetArg(args[i], XtNheight, &h); i++;
1525 XtGetValues(wg, args, i);
1534 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1535 // In XBoard this will have to wait until awareness of window parameters is implemented
1536 GetActualPlacement(shellWidget, &wpMain);
1537 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1538 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1539 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1540 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1541 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1542 else GetActualPlacement(editShell, &wpComment);
1543 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1544 else GetActualPlacement(editTagsShell, &wpTags);
1548 PrintCommPortSettings(FILE *f, char *name)
1549 { // This option does not exist in XBoard
1553 MySearchPath(char *installDir, char *name, char *fullname)
1554 { // just append installDir and name. Perhaps ExpandPath should be used here?
1555 name = ExpandPathName(name);
1556 if(name && name[0] == '/')
1557 safeStrCpy(fullname, name, MSG_SIZ );
1559 sprintf(fullname, "%s%c%s", installDir, '/', name);
1565 MyGetFullPathName(char *name, char *fullname)
1566 { // should use ExpandPath?
1567 name = ExpandPathName(name);
1568 safeStrCpy(fullname, name, MSG_SIZ );
1573 EnsureOnScreen(int *x, int *y, int minX, int minY)
1580 { // [HGM] args: allows testing if main window is realized from back-end
1581 return xBoardWindow != 0;
1585 PopUpStartupDialog()
1586 { // start menu not implemented in XBoard
1589 ConvertToLine(int argc, char **argv)
1591 static char line[128*1024], buf[1024];
1595 for(i=1; i<argc; i++) {
1596 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1597 && argv[i][0] != '{' )
1598 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1600 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1603 line[strlen(line)-1] = NULLCHAR;
1607 //--------------------------------------------------------------------------------------------
1609 extern Boolean twoBoards, partnerUp;
1612 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1614 #define BoardSize int
1615 void InitDrawingSizes(BoardSize boardSize, int flags)
1616 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1617 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1619 XtGeometryResult gres;
1622 if(!formWidget) return;
1625 * Enable shell resizing.
1627 shellArgs[0].value = (XtArgVal) &w;
1628 shellArgs[1].value = (XtArgVal) &h;
1629 XtGetValues(shellWidget, shellArgs, 2);
1631 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1632 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1633 XtSetValues(shellWidget, &shellArgs[2], 4);
1635 XtSetArg(args[0], XtNdefaultDistance, &sep);
1636 XtGetValues(formWidget, args, 1);
1638 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1639 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1641 hOffset = boardWidth + 10;
1642 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1643 secondSegments[i] = gridSegments[i];
1644 secondSegments[i].x1 += hOffset;
1645 secondSegments[i].x2 += hOffset;
1648 XtSetArg(args[0], XtNwidth, boardWidth);
1649 XtSetArg(args[1], XtNheight, boardHeight);
1650 XtSetValues(boardWidget, args, 2);
1652 timerWidth = (boardWidth - sep) / 2;
1653 XtSetArg(args[0], XtNwidth, timerWidth);
1654 XtSetValues(whiteTimerWidget, args, 1);
1655 XtSetValues(blackTimerWidget, args, 1);
1657 XawFormDoLayout(formWidget, False);
1659 if (appData.titleInWindow) {
1661 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1662 XtSetArg(args[i], XtNheight, &h); i++;
1663 XtGetValues(titleWidget, args, i);
1665 w = boardWidth - 2*bor;
1667 XtSetArg(args[0], XtNwidth, &w);
1668 XtGetValues(menuBarWidget, args, 1);
1669 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1672 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1673 if (gres != XtGeometryYes && appData.debugMode) {
1675 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1676 programName, gres, w, h, wr, hr);
1680 XawFormDoLayout(formWidget, True);
1683 * Inhibit shell resizing.
1685 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1686 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1687 shellArgs[4].value = shellArgs[2].value = w;
1688 shellArgs[5].value = shellArgs[3].value = h;
1689 XtSetValues(shellWidget, &shellArgs[0], 6);
1691 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1694 for(i=0; i<4; i++) {
1696 for(p=0; p<=(int)WhiteKing; p++)
1697 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1698 if(gameInfo.variant == VariantShogi) {
1699 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1700 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1701 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1702 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1703 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1706 if(gameInfo.variant == VariantGothic) {
1707 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1711 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1712 for(p=0; p<=(int)WhiteKing; p++)
1713 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1714 if(gameInfo.variant == VariantShogi) {
1715 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1716 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1717 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1718 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1719 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1722 if(gameInfo.variant == VariantGothic) {
1723 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1729 for(i=0; i<2; i++) {
1731 for(p=0; p<=(int)WhiteKing; p++)
1732 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1733 if(gameInfo.variant == VariantShogi) {
1734 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1735 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1736 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1737 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1738 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1741 if(gameInfo.variant == VariantGothic) {
1742 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1758 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1759 XSetWindowAttributes window_attributes;
1761 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1762 XrmValue vFrom, vTo;
1763 XtGeometryResult gres;
1766 int forceMono = False;
1768 srandom(time(0)); // [HGM] book: make random truly random
1770 setbuf(stdout, NULL);
1771 setbuf(stderr, NULL);
1774 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1775 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1779 programName = strrchr(argv[0], '/');
1780 if (programName == NULL)
1781 programName = argv[0];
1786 XtSetLanguageProc(NULL, NULL, NULL);
1787 bindtextdomain(PACKAGE, LOCALEDIR);
1788 textdomain(PACKAGE);
1792 XtAppInitialize(&appContext, "XBoard", shellOptions,
1793 XtNumber(shellOptions),
1794 &argc, argv, xboardResources, NULL, 0);
1795 appData.boardSize = "";
1796 InitAppData(ConvertToLine(argc, argv));
1798 if (p == NULL) p = "/tmp";
1799 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1800 gameCopyFilename = (char*) malloc(i);
1801 gamePasteFilename = (char*) malloc(i);
1802 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1803 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1805 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1806 clientResources, XtNumber(clientResources),
1809 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1810 static char buf[MSG_SIZ];
1811 EscapeExpand(buf, appData.initString);
1812 appData.initString = strdup(buf);
1813 EscapeExpand(buf, appData.secondInitString);
1814 appData.secondInitString = strdup(buf);
1815 EscapeExpand(buf, appData.firstComputerString);
1816 appData.firstComputerString = strdup(buf);
1817 EscapeExpand(buf, appData.secondComputerString);
1818 appData.secondComputerString = strdup(buf);
1821 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1824 if (chdir(chessDir) != 0) {
1825 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1831 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1832 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1833 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1834 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1837 setbuf(debugFP, NULL);
1840 /* [HGM,HR] make sure board size is acceptable */
1841 if(appData.NrFiles > BOARD_FILES ||
1842 appData.NrRanks > BOARD_RANKS )
1843 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1846 /* This feature does not work; animation needs a rewrite */
1847 appData.highlightDragging = FALSE;
1851 xDisplay = XtDisplay(shellWidget);
1852 xScreen = DefaultScreen(xDisplay);
1853 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1855 gameInfo.variant = StringToVariant(appData.variant);
1856 InitPosition(FALSE);
1859 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1861 if (isdigit(appData.boardSize[0])) {
1862 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1863 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1864 &fontPxlSize, &smallLayout, &tinyLayout);
1866 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1867 programName, appData.boardSize);
1871 /* Find some defaults; use the nearest known size */
1872 SizeDefaults *szd, *nearest;
1873 int distance = 99999;
1874 nearest = szd = sizeDefaults;
1875 while (szd->name != NULL) {
1876 if (abs(szd->squareSize - squareSize) < distance) {
1878 distance = abs(szd->squareSize - squareSize);
1879 if (distance == 0) break;
1883 if (i < 2) lineGap = nearest->lineGap;
1884 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1885 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1886 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1887 if (i < 6) smallLayout = nearest->smallLayout;
1888 if (i < 7) tinyLayout = nearest->tinyLayout;
1891 SizeDefaults *szd = sizeDefaults;
1892 if (*appData.boardSize == NULLCHAR) {
1893 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1894 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1897 if (szd->name == NULL) szd--;
1898 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1900 while (szd->name != NULL &&
1901 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1902 if (szd->name == NULL) {
1903 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1904 programName, appData.boardSize);
1908 squareSize = szd->squareSize;
1909 lineGap = szd->lineGap;
1910 clockFontPxlSize = szd->clockFontPxlSize;
1911 coordFontPxlSize = szd->coordFontPxlSize;
1912 fontPxlSize = szd->fontPxlSize;
1913 smallLayout = szd->smallLayout;
1914 tinyLayout = szd->tinyLayout;
1915 // [HGM] font: use defaults from settings file if available and not overruled
1917 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1918 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1919 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1920 appData.font = fontTable[MESSAGE_FONT][squareSize];
1921 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1922 appData.coordFont = fontTable[COORD_FONT][squareSize];
1924 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1925 if (strlen(appData.pixmapDirectory) > 0) {
1926 p = ExpandPathName(appData.pixmapDirectory);
1928 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1929 appData.pixmapDirectory);
1932 if (appData.debugMode) {
1933 fprintf(stderr, _("\
1934 XBoard square size (hint): %d\n\
1935 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1937 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1938 if (appData.debugMode) {
1939 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1943 /* [HR] height treated separately (hacked) */
1944 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1945 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1946 if (appData.showJail == 1) {
1947 /* Jail on top and bottom */
1948 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1949 XtSetArg(boardArgs[2], XtNheight,
1950 boardHeight + 2*(lineGap + squareSize));
1951 } else if (appData.showJail == 2) {
1953 XtSetArg(boardArgs[1], XtNwidth,
1954 boardWidth + 2*(lineGap + squareSize));
1955 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1958 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1959 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1963 * Determine what fonts to use.
1965 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1966 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1967 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1968 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1969 coordFontID = XLoadFont(xDisplay, appData.coordFont);
1970 coordFontStruct = XQueryFont(xDisplay, coordFontID);
1971 appData.font = FindFont(appData.font, fontPxlSize);
1972 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
1973 countFontStruct = XQueryFont(xDisplay, countFontID);
1974 // appData.font = FindFont(appData.font, fontPxlSize);
1976 xdb = XtDatabase(xDisplay);
1977 XrmPutStringResource(&xdb, "*font", appData.font);
1980 * Detect if there are not enough colors available and adapt.
1982 if (DefaultDepth(xDisplay, xScreen) <= 2) {
1983 appData.monoMode = True;
1986 if (!appData.monoMode) {
1987 vFrom.addr = (caddr_t) appData.lightSquareColor;
1988 vFrom.size = strlen(appData.lightSquareColor);
1989 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1990 if (vTo.addr == NULL) {
1991 appData.monoMode = True;
1994 lightSquareColor = *(Pixel *) vTo.addr;
1997 if (!appData.monoMode) {
1998 vFrom.addr = (caddr_t) appData.darkSquareColor;
1999 vFrom.size = strlen(appData.darkSquareColor);
2000 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2001 if (vTo.addr == NULL) {
2002 appData.monoMode = True;
2005 darkSquareColor = *(Pixel *) vTo.addr;
2008 if (!appData.monoMode) {
2009 vFrom.addr = (caddr_t) appData.whitePieceColor;
2010 vFrom.size = strlen(appData.whitePieceColor);
2011 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2012 if (vTo.addr == NULL) {
2013 appData.monoMode = True;
2016 whitePieceColor = *(Pixel *) vTo.addr;
2019 if (!appData.monoMode) {
2020 vFrom.addr = (caddr_t) appData.blackPieceColor;
2021 vFrom.size = strlen(appData.blackPieceColor);
2022 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2023 if (vTo.addr == NULL) {
2024 appData.monoMode = True;
2027 blackPieceColor = *(Pixel *) vTo.addr;
2031 if (!appData.monoMode) {
2032 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2033 vFrom.size = strlen(appData.highlightSquareColor);
2034 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2035 if (vTo.addr == NULL) {
2036 appData.monoMode = True;
2039 highlightSquareColor = *(Pixel *) vTo.addr;
2043 if (!appData.monoMode) {
2044 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2045 vFrom.size = strlen(appData.premoveHighlightColor);
2046 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2047 if (vTo.addr == NULL) {
2048 appData.monoMode = True;
2051 premoveHighlightColor = *(Pixel *) vTo.addr;
2056 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2059 if (appData.bitmapDirectory == NULL ||
2060 appData.bitmapDirectory[0] == NULLCHAR)
2061 appData.bitmapDirectory = DEF_BITMAP_DIR;
2064 if (appData.lowTimeWarning && !appData.monoMode) {
2065 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2066 vFrom.size = strlen(appData.lowTimeWarningColor);
2067 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2068 if (vTo.addr == NULL)
2069 appData.monoMode = True;
2071 lowTimeWarningColor = *(Pixel *) vTo.addr;
2074 if (appData.monoMode && appData.debugMode) {
2075 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2076 (unsigned long) XWhitePixel(xDisplay, xScreen),
2077 (unsigned long) XBlackPixel(xDisplay, xScreen));
2080 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2081 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2082 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2083 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2084 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2085 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2086 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2087 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2088 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2089 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2091 if (appData.colorize) {
2093 _("%s: can't parse color names; disabling colorization\n"),
2096 appData.colorize = FALSE;
2098 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2099 textColors[ColorNone].attr = 0;
2101 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2107 layoutName = "tinyLayout";
2108 } else if (smallLayout) {
2109 layoutName = "smallLayout";
2111 layoutName = "normalLayout";
2113 /* Outer layoutWidget is there only to provide a name for use in
2114 resources that depend on the layout style */
2116 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2117 layoutArgs, XtNumber(layoutArgs));
2119 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2120 formArgs, XtNumber(formArgs));
2121 XtSetArg(args[0], XtNdefaultDistance, &sep);
2122 XtGetValues(formWidget, args, 1);
2125 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2126 XtSetArg(args[0], XtNtop, XtChainTop);
2127 XtSetArg(args[1], XtNbottom, XtChainTop);
2128 XtSetArg(args[2], XtNright, XtChainLeft);
2129 XtSetValues(menuBarWidget, args, 3);
2131 widgetList[j++] = whiteTimerWidget =
2132 XtCreateWidget("whiteTime", labelWidgetClass,
2133 formWidget, timerArgs, XtNumber(timerArgs));
2134 XtSetArg(args[0], XtNfont, clockFontStruct);
2135 XtSetArg(args[1], XtNtop, XtChainTop);
2136 XtSetArg(args[2], XtNbottom, XtChainTop);
2137 XtSetValues(whiteTimerWidget, args, 3);
2139 widgetList[j++] = blackTimerWidget =
2140 XtCreateWidget("blackTime", labelWidgetClass,
2141 formWidget, timerArgs, XtNumber(timerArgs));
2142 XtSetArg(args[0], XtNfont, clockFontStruct);
2143 XtSetArg(args[1], XtNtop, XtChainTop);
2144 XtSetArg(args[2], XtNbottom, XtChainTop);
2145 XtSetValues(blackTimerWidget, args, 3);
2147 if (appData.titleInWindow) {
2148 widgetList[j++] = titleWidget =
2149 XtCreateWidget("title", labelWidgetClass, formWidget,
2150 titleArgs, XtNumber(titleArgs));
2151 XtSetArg(args[0], XtNtop, XtChainTop);
2152 XtSetArg(args[1], XtNbottom, XtChainTop);
2153 XtSetValues(titleWidget, args, 2);
2156 if (appData.showButtonBar) {
2157 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2158 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2159 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2160 XtSetArg(args[2], XtNtop, XtChainTop);
2161 XtSetArg(args[3], XtNbottom, XtChainTop);
2162 XtSetValues(buttonBarWidget, args, 4);
2165 widgetList[j++] = messageWidget =
2166 XtCreateWidget("message", labelWidgetClass, formWidget,
2167 messageArgs, XtNumber(messageArgs));
2168 XtSetArg(args[0], XtNtop, XtChainTop);
2169 XtSetArg(args[1], XtNbottom, XtChainTop);
2170 XtSetValues(messageWidget, args, 2);
2172 widgetList[j++] = boardWidget =
2173 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2174 XtNumber(boardArgs));
2176 XtManageChildren(widgetList, j);
2178 timerWidth = (boardWidth - sep) / 2;
2179 XtSetArg(args[0], XtNwidth, timerWidth);
2180 XtSetValues(whiteTimerWidget, args, 1);
2181 XtSetValues(blackTimerWidget, args, 1);
2183 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2184 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2185 XtGetValues(whiteTimerWidget, args, 2);
2187 if (appData.showButtonBar) {
2188 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2189 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2190 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2194 * formWidget uses these constraints but they are stored
2198 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2199 XtSetValues(menuBarWidget, args, i);
2200 if (appData.titleInWindow) {
2203 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2204 XtSetValues(whiteTimerWidget, args, i);
2206 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2207 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2208 XtSetValues(blackTimerWidget, args, i);
2210 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2211 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2212 XtSetValues(titleWidget, args, i);
2214 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2215 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2216 XtSetValues(messageWidget, args, i);
2217 if (appData.showButtonBar) {
2219 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2220 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2221 XtSetValues(buttonBarWidget, args, i);
2225 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2226 XtSetValues(whiteTimerWidget, args, i);
2228 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2229 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2230 XtSetValues(blackTimerWidget, args, i);
2232 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2233 XtSetValues(titleWidget, args, i);
2235 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2236 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2237 XtSetValues(messageWidget, args, i);
2238 if (appData.showButtonBar) {
2240 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2241 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2242 XtSetValues(buttonBarWidget, args, i);
2247 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2248 XtSetValues(whiteTimerWidget, args, i);
2250 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2251 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2252 XtSetValues(blackTimerWidget, args, i);
2254 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2255 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2256 XtSetValues(messageWidget, args, i);
2257 if (appData.showButtonBar) {
2259 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2260 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2261 XtSetValues(buttonBarWidget, args, i);
2265 XtSetArg(args[0], XtNfromVert, messageWidget);
2266 XtSetArg(args[1], XtNtop, XtChainTop);
2267 XtSetArg(args[2], XtNbottom, XtChainBottom);
2268 XtSetArg(args[3], XtNleft, XtChainLeft);
2269 XtSetArg(args[4], XtNright, XtChainRight);
2270 XtSetValues(boardWidget, args, 5);
2272 XtRealizeWidget(shellWidget);
2275 XtSetArg(args[0], XtNx, wpMain.x);
2276 XtSetArg(args[1], XtNy, wpMain.y);
2277 XtSetValues(shellWidget, args, 2);
2281 * Correct the width of the message and title widgets.
2282 * It is not known why some systems need the extra fudge term.
2283 * The value "2" is probably larger than needed.
2285 XawFormDoLayout(formWidget, False);
2287 #define WIDTH_FUDGE 2
2289 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2290 XtSetArg(args[i], XtNheight, &h); i++;
2291 XtGetValues(messageWidget, args, i);
2292 if (appData.showButtonBar) {
2294 XtSetArg(args[i], XtNwidth, &w); i++;
2295 XtGetValues(buttonBarWidget, args, i);
2296 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2298 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2301 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2302 if (gres != XtGeometryYes && appData.debugMode) {
2303 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2304 programName, gres, w, h, wr, hr);
2307 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2308 /* The size used for the child widget in layout lags one resize behind
2309 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2311 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2312 if (gres != XtGeometryYes && appData.debugMode) {
2313 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2314 programName, gres, w, h, wr, hr);
2317 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2318 XtSetArg(args[1], XtNright, XtChainRight);
2319 XtSetValues(messageWidget, args, 2);
2321 if (appData.titleInWindow) {
2323 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2324 XtSetArg(args[i], XtNheight, &h); i++;
2325 XtGetValues(titleWidget, args, i);
2327 w = boardWidth - 2*bor;
2329 XtSetArg(args[0], XtNwidth, &w);
2330 XtGetValues(menuBarWidget, args, 1);
2331 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2334 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2335 if (gres != XtGeometryYes && appData.debugMode) {
2337 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2338 programName, gres, w, h, wr, hr);
2341 XawFormDoLayout(formWidget, True);
2343 xBoardWindow = XtWindow(boardWidget);
2345 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2346 // not need to go into InitDrawingSizes().
2350 * Create X checkmark bitmap and initialize option menu checks.
2352 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2353 checkmark_bits, checkmark_width, checkmark_height);
2354 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2355 if (appData.alwaysPromoteToQueen) {
2356 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2359 if (appData.animateDragging) {
2360 XtSetValues(XtNameToWidget(menuBarWidget,
2361 "menuOptions.Animate Dragging"),
2364 if (appData.animate) {
2365 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2368 if (appData.autoComment) {
2369 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2372 if (appData.autoCallFlag) {
2373 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2376 if (appData.autoFlipView) {
2377 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2380 if (appData.autoObserve) {
2381 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2384 if (appData.autoRaiseBoard) {
2385 XtSetValues(XtNameToWidget(menuBarWidget,
2386 "menuOptions.Auto Raise Board"), args, 1);
2388 if (appData.autoSaveGames) {
2389 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2392 if (appData.saveGameFile[0] != NULLCHAR) {
2393 /* Can't turn this off from menu */
2394 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2396 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2400 if (appData.blindfold) {
2401 XtSetValues(XtNameToWidget(menuBarWidget,
2402 "menuOptions.Blindfold"), args, 1);
2404 if (appData.flashCount > 0) {
2405 XtSetValues(XtNameToWidget(menuBarWidget,
2406 "menuOptions.Flash Moves"),
2409 if (appData.getMoveList) {
2410 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2414 if (appData.highlightDragging) {
2415 XtSetValues(XtNameToWidget(menuBarWidget,
2416 "menuOptions.Highlight Dragging"),
2420 if (appData.highlightLastMove) {
2421 XtSetValues(XtNameToWidget(menuBarWidget,
2422 "menuOptions.Highlight Last Move"),
2425 if (appData.icsAlarm) {
2426 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2429 if (appData.ringBellAfterMoves) {
2430 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2433 if (appData.oldSaveStyle) {
2434 XtSetValues(XtNameToWidget(menuBarWidget,
2435 "menuOptions.Old Save Style"), args, 1);
2437 if (appData.periodicUpdates) {
2438 XtSetValues(XtNameToWidget(menuBarWidget,
2439 "menuOptions.Periodic Updates"), args, 1);
2441 if (appData.ponderNextMove) {
2442 XtSetValues(XtNameToWidget(menuBarWidget,
2443 "menuOptions.Ponder Next Move"), args, 1);
2445 if (appData.popupExitMessage) {
2446 XtSetValues(XtNameToWidget(menuBarWidget,
2447 "menuOptions.Popup Exit Message"), args, 1);
2449 if (appData.popupMoveErrors) {
2450 XtSetValues(XtNameToWidget(menuBarWidget,
2451 "menuOptions.Popup Move Errors"), args, 1);
2453 if (appData.premove) {
2454 XtSetValues(XtNameToWidget(menuBarWidget,
2455 "menuOptions.Premove"), args, 1);
2457 if (appData.quietPlay) {
2458 XtSetValues(XtNameToWidget(menuBarWidget,
2459 "menuOptions.Quiet Play"), args, 1);
2461 if (appData.showCoords) {
2462 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2465 if (appData.hideThinkingFromHuman) {
2466 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2469 if (appData.testLegality) {
2470 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2473 if (saveSettingsOnExit) {
2474 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2481 ReadBitmap(&wIconPixmap, "icon_white.bm",
2482 icon_white_bits, icon_white_width, icon_white_height);
2483 ReadBitmap(&bIconPixmap, "icon_black.bm",
2484 icon_black_bits, icon_black_width, icon_black_height);
2485 iconPixmap = wIconPixmap;
2487 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2488 XtSetValues(shellWidget, args, i);
2491 * Create a cursor for the board widget.
2493 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2494 XChangeWindowAttributes(xDisplay, xBoardWindow,
2495 CWCursor, &window_attributes);
2498 * Inhibit shell resizing.
2500 shellArgs[0].value = (XtArgVal) &w;
2501 shellArgs[1].value = (XtArgVal) &h;
2502 XtGetValues(shellWidget, shellArgs, 2);
2503 shellArgs[4].value = shellArgs[2].value = w;
2504 shellArgs[5].value = shellArgs[3].value = h;
2505 XtSetValues(shellWidget, &shellArgs[2], 4);
2506 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2507 marginH = h - boardHeight;
2509 CatchDeleteWindow(shellWidget, "QuitProc");
2514 if (appData.bitmapDirectory[0] != NULLCHAR) {
2521 /* Create regular pieces */
2522 if (!useImages) CreatePieces();
2527 if (appData.animate || appData.animateDragging)
2530 XtAugmentTranslations(formWidget,
2531 XtParseTranslationTable(globalTranslations));
2532 XtAugmentTranslations(boardWidget,
2533 XtParseTranslationTable(boardTranslations));
2534 XtAugmentTranslations(whiteTimerWidget,
2535 XtParseTranslationTable(whiteTranslations));
2536 XtAugmentTranslations(blackTimerWidget,
2537 XtParseTranslationTable(blackTranslations));
2539 /* Why is the following needed on some versions of X instead
2540 * of a translation? */
2541 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2542 (XtEventHandler) EventProc, NULL);
2545 /* [AS] Restore layout */
2546 if( wpMoveHistory.visible ) {
2550 if( wpEvalGraph.visible )
2555 if( wpEngineOutput.visible ) {
2556 EngineOutputPopUp();
2561 if (errorExitStatus == -1) {
2562 if (appData.icsActive) {
2563 /* We now wait until we see "login:" from the ICS before
2564 sending the logon script (problems with timestamp otherwise) */
2565 /*ICSInitScript();*/
2566 if (appData.icsInputBox) ICSInputBoxPopUp();
2570 signal(SIGWINCH, TermSizeSigHandler);
2572 signal(SIGINT, IntSigHandler);
2573 signal(SIGTERM, IntSigHandler);
2574 if (*appData.cmailGameName != NULLCHAR) {
2575 signal(SIGUSR1, CmailSigHandler);
2578 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2580 XtSetKeyboardFocus(shellWidget, formWidget);
2582 XtAppMainLoop(appContext);
2583 if (appData.debugMode) fclose(debugFP); // [DM] debug
2590 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2591 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2593 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2594 unlink(gameCopyFilename);
2595 unlink(gamePasteFilename);
2598 RETSIGTYPE TermSizeSigHandler(int sig)
2611 CmailSigHandler(sig)
2617 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2619 /* Activate call-back function CmailSigHandlerCallBack() */
2620 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2622 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2626 CmailSigHandlerCallBack(isr, closure, message, count, error)
2634 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2636 /**** end signal code ****/
2646 f = fopen(appData.icsLogon, "r");
2650 safeStrCpy(buf, p, sizeof(buf)/sizeof(buf[0]) );
2652 strcat(buf, appData.icsLogon);
2653 f = fopen(buf, "r");
2657 ProcessICSInitScript(f);
2664 EditCommentPopDown();
2679 if (!menuBarWidget) return;
2680 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2682 DisplayError("menuStep.Revert", 0);
2684 XtSetSensitive(w, !grey);
2686 w = XtNameToWidget(menuBarWidget, "menuStep.Annotate");
2688 DisplayError("menuStep.Annotate", 0);
2690 XtSetSensitive(w, !grey);
2695 SetMenuEnables(enab)
2699 if (!menuBarWidget) return;
2700 while (enab->name != NULL) {
2701 w = XtNameToWidget(menuBarWidget, enab->name);
2703 DisplayError(enab->name, 0);
2705 XtSetSensitive(w, enab->value);
2711 Enables icsEnables[] = {
2712 { "menuFile.Mail Move", False },
2713 { "menuFile.Reload CMail Message", False },
2714 { "menuMode.Machine Black", False },
2715 { "menuMode.Machine White", False },
2716 { "menuMode.Analysis Mode", False },
2717 { "menuMode.Analyze File", False },
2718 { "menuMode.Two Machines", False },
2720 { "menuHelp.Hint", False },
2721 { "menuHelp.Book", False },
2722 { "menuStep.Move Now", False },
2723 { "menuOptions.Periodic Updates", False },
2724 { "menuOptions.Hide Thinking", False },
2725 { "menuOptions.Ponder Next Move", False },
2727 { "menuStep.Annotate", False },
2731 Enables ncpEnables[] = {
2732 { "menuFile.Mail Move", False },
2733 { "menuFile.Reload CMail Message", False },
2734 { "menuMode.Machine White", False },
2735 { "menuMode.Machine Black", False },
2736 { "menuMode.Analysis Mode", False },
2737 { "menuMode.Analyze File", False },
2738 { "menuMode.Two Machines", False },
2739 { "menuMode.ICS Client", False },
2740 { "menuMode.ICS Input Box", False },
2741 { "Action", False },
2742 { "menuStep.Revert", False },
2743 { "menuStep.Annotate", False },
2744 { "menuStep.Move Now", False },
2745 { "menuStep.Retract Move", False },
2746 { "menuOptions.Auto Comment", False },
2747 { "menuOptions.Auto Flag", False },
2748 { "menuOptions.Auto Flip View", False },
2749 { "menuOptions.Auto Observe", False },
2750 { "menuOptions.Auto Raise Board", False },
2751 { "menuOptions.Get Move List", False },
2752 { "menuOptions.ICS Alarm", False },
2753 { "menuOptions.Move Sound", False },
2754 { "menuOptions.Quiet Play", False },
2755 { "menuOptions.Hide Thinking", False },
2756 { "menuOptions.Periodic Updates", False },
2757 { "menuOptions.Ponder Next Move", False },
2758 { "menuHelp.Hint", False },
2759 { "menuHelp.Book", False },
2763 Enables gnuEnables[] = {
2764 { "menuMode.ICS Client", False },
2765 { "menuMode.ICS Input Box", False },
2766 { "menuAction.Accept", False },
2767 { "menuAction.Decline", False },
2768 { "menuAction.Rematch", False },
2769 { "menuAction.Adjourn", False },
2770 { "menuAction.Stop Examining", False },
2771 { "menuAction.Stop Observing", False },
2772 { "menuAction.Upload to Examine", False },
2773 { "menuStep.Revert", False },
2774 { "menuStep.Annotate", False },
2775 { "menuOptions.Auto Comment", False },
2776 { "menuOptions.Auto Observe", False },
2777 { "menuOptions.Auto Raise Board", False },
2778 { "menuOptions.Get Move List", False },
2779 { "menuOptions.Premove", False },
2780 { "menuOptions.Quiet Play", False },
2782 /* The next two options rely on SetCmailMode being called *after* */
2783 /* SetGNUMode so that when GNU is being used to give hints these */
2784 /* menu options are still available */
2786 { "menuFile.Mail Move", False },
2787 { "menuFile.Reload CMail Message", False },
2791 Enables cmailEnables[] = {
2793 { "menuAction.Call Flag", False },
2794 { "menuAction.Draw", True },
2795 { "menuAction.Adjourn", False },
2796 { "menuAction.Abort", False },
2797 { "menuAction.Stop Observing", False },
2798 { "menuAction.Stop Examining", False },
2799 { "menuFile.Mail Move", True },
2800 { "menuFile.Reload CMail Message", True },
2804 Enables trainingOnEnables[] = {
2805 { "menuMode.Edit Comment", False },
2806 { "menuMode.Pause", False },
2807 { "menuStep.Forward", False },
2808 { "menuStep.Backward", False },
2809 { "menuStep.Forward to End", False },
2810 { "menuStep.Back to Start", False },
2811 { "menuStep.Move Now", False },
2812 { "menuStep.Truncate Game", False },
2816 Enables trainingOffEnables[] = {
2817 { "menuMode.Edit Comment", True },
2818 { "menuMode.Pause", True },
2819 { "menuStep.Forward", True },
2820 { "menuStep.Backward", True },
2821 { "menuStep.Forward to End", True },
2822 { "menuStep.Back to Start", True },
2823 { "menuStep.Move Now", True },
2824 { "menuStep.Truncate Game", True },
2828 Enables machineThinkingEnables[] = {
2829 { "menuFile.Load Game", False },
2830 { "menuFile.Load Next Game", False },
2831 { "menuFile.Load Previous Game", False },
2832 { "menuFile.Reload Same Game", False },
2833 { "menuFile.Paste Game", False },
2834 { "menuFile.Load Position", False },
2835 { "menuFile.Load Next Position", False },
2836 { "menuFile.Load Previous Position", False },
2837 { "menuFile.Reload Same Position", False },
2838 { "menuFile.Paste Position", False },
2839 { "menuMode.Machine White", False },
2840 { "menuMode.Machine Black", False },
2841 { "menuMode.Two Machines", False },
2842 { "menuStep.Retract Move", False },
2846 Enables userThinkingEnables[] = {
2847 { "menuFile.Load Game", True },
2848 { "menuFile.Load Next Game", True },
2849 { "menuFile.Load Previous Game", True },
2850 { "menuFile.Reload Same Game", True },
2851 { "menuFile.Paste Game", True },
2852 { "menuFile.Load Position", True },
2853 { "menuFile.Load Next Position", True },
2854 { "menuFile.Load Previous Position", True },
2855 { "menuFile.Reload Same Position", True },
2856 { "menuFile.Paste Position", True },
2857 { "menuMode.Machine White", True },
2858 { "menuMode.Machine Black", True },
2859 { "menuMode.Two Machines", True },
2860 { "menuStep.Retract Move", True },
2866 SetMenuEnables(icsEnables);
2869 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2870 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2877 SetMenuEnables(ncpEnables);
2883 SetMenuEnables(gnuEnables);
2889 SetMenuEnables(cmailEnables);
2895 SetMenuEnables(trainingOnEnables);
2896 if (appData.showButtonBar) {
2897 XtSetSensitive(buttonBarWidget, False);
2903 SetTrainingModeOff()
2905 SetMenuEnables(trainingOffEnables);
2906 if (appData.showButtonBar) {
2907 XtSetSensitive(buttonBarWidget, True);
2912 SetUserThinkingEnables()
2914 if (appData.noChessProgram) return;
2915 SetMenuEnables(userThinkingEnables);
2919 SetMachineThinkingEnables()
2921 if (appData.noChessProgram) return;
2922 SetMenuEnables(machineThinkingEnables);
2924 case MachinePlaysBlack:
2925 case MachinePlaysWhite:
2926 case TwoMachinesPlay:
2927 XtSetSensitive(XtNameToWidget(menuBarWidget,
2928 ModeToWidgetName(gameMode)), True);
2935 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2936 #define HISTORY_SIZE 64
\r
2937 static char *history[HISTORY_SIZE];
\r
2938 int histIn = 0, histP = 0;
\r
2941 SaveInHistory(char *cmd)
\r
2943 if (history[histIn] != NULL) {
\r
2944 free(history[histIn]);
\r
2945 history[histIn] = NULL;
\r
2947 if (*cmd == NULLCHAR) return;
\r
2948 history[histIn] = StrSave(cmd);
\r
2949 histIn = (histIn + 1) % HISTORY_SIZE;
\r
2950 if (history[histIn] != NULL) {
\r
2951 free(history[histIn]);
\r
2952 history[histIn] = NULL;
\r
2958 PrevInHistory(char *cmd)
\r
2961 if (histP == histIn) {
\r
2962 if (history[histIn] != NULL) free(history[histIn]);
\r
2963 history[histIn] = StrSave(cmd);
\r
2965 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
2966 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
2968 return history[histP];
\r
2974 if (histP == histIn) return NULL;
\r
2975 histP = (histP + 1) % HISTORY_SIZE;
\r
2976 return history[histP];
\r
2978 // end of borrowed code
\r
2980 #define Abs(n) ((n)<0 ? -(n) : (n))
2983 * Find a font that matches "pattern" that is as close as
2984 * possible to the targetPxlSize. Prefer fonts that are k
2985 * pixels smaller to fonts that are k pixels larger. The
2986 * pattern must be in the X Consortium standard format,
2987 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2988 * The return value should be freed with XtFree when no
2992 FindFont(pattern, targetPxlSize)
2996 char **fonts, *p, *best, *scalable, *scalableTail;
2997 int i, j, nfonts, minerr, err, pxlSize;
3000 char **missing_list;
3002 char *def_string, *base_fnt_lst, strInt[3];
3004 XFontStruct **fnt_list;
3006 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3007 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3008 p = strstr(pattern, "--");
3009 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3010 strcat(base_fnt_lst, strInt);
3011 strcat(base_fnt_lst, strchr(p + 2, '-'));
3013 if ((fntSet = XCreateFontSet(xDisplay,
3017 &def_string)) == NULL) {
3019 fprintf(stderr, _("Unable to create font set.\n"));
3023 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3025 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3027 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3028 programName, pattern);
3036 for (i=0; i<nfonts; i++) {
3039 if (*p != '-') continue;
3041 if (*p == NULLCHAR) break;
3042 if (*p++ == '-') j++;
3044 if (j < 7) continue;
3047 scalable = fonts[i];
3050 err = pxlSize - targetPxlSize;
3051 if (Abs(err) < Abs(minerr) ||
3052 (minerr > 0 && err < 0 && -err == minerr)) {
3058 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3059 /* If the error is too big and there is a scalable font,
3060 use the scalable font. */
3061 int headlen = scalableTail - scalable;
3062 p = (char *) XtMalloc(strlen(scalable) + 10);
3063 while (isdigit(*scalableTail)) scalableTail++;
3064 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3066 p = (char *) XtMalloc(strlen(best) + 2);
3067 safeStrCpy(p, best, strlen(best)+1 );
3069 if (appData.debugMode) {
3070 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3071 pattern, targetPxlSize, p);
3074 if (missing_count > 0)
3075 XFreeStringList(missing_list);
3076 XFreeFontSet(xDisplay, fntSet);
3078 XFreeFontNames(fonts);
3085 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3086 | GCBackground | GCFunction | GCPlaneMask;
3087 XGCValues gc_values;
3090 gc_values.plane_mask = AllPlanes;
3091 gc_values.line_width = lineGap;
3092 gc_values.line_style = LineSolid;
3093 gc_values.function = GXcopy;
3095 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3096 gc_values.background = XBlackPixel(xDisplay, xScreen);
3097 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3099 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3100 gc_values.background = XWhitePixel(xDisplay, xScreen);
3101 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3102 XSetFont(xDisplay, coordGC, coordFontID);
3104 // [HGM] make font for holdings counts (white on black0
3105 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3106 gc_values.background = XBlackPixel(xDisplay, xScreen);
3107 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3108 XSetFont(xDisplay, countGC, countFontID);
3110 if (appData.monoMode) {
3111 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3112 gc_values.background = XWhitePixel(xDisplay, xScreen);
3113 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3115 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3116 gc_values.background = XBlackPixel(xDisplay, xScreen);
3117 lightSquareGC = wbPieceGC
3118 = XtGetGC(shellWidget, value_mask, &gc_values);
3120 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3121 gc_values.background = XWhitePixel(xDisplay, xScreen);
3122 darkSquareGC = bwPieceGC
3123 = XtGetGC(shellWidget, value_mask, &gc_values);
3125 if (DefaultDepth(xDisplay, xScreen) == 1) {
3126 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3127 gc_values.function = GXcopyInverted;
3128 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3129 gc_values.function = GXcopy;
3130 if (XBlackPixel(xDisplay, xScreen) == 1) {
3131 bwPieceGC = darkSquareGC;
3132 wbPieceGC = copyInvertedGC;
3134 bwPieceGC = copyInvertedGC;
3135 wbPieceGC = lightSquareGC;
3139 gc_values.foreground = highlightSquareColor;
3140 gc_values.background = highlightSquareColor;
3141 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3143 gc_values.foreground = premoveHighlightColor;
3144 gc_values.background = premoveHighlightColor;
3145 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3147 gc_values.foreground = lightSquareColor;
3148 gc_values.background = darkSquareColor;
3149 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3151 gc_values.foreground = darkSquareColor;
3152 gc_values.background = lightSquareColor;
3153 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3155 gc_values.foreground = jailSquareColor;
3156 gc_values.background = jailSquareColor;
3157 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3159 gc_values.foreground = whitePieceColor;
3160 gc_values.background = darkSquareColor;
3161 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3163 gc_values.foreground = whitePieceColor;
3164 gc_values.background = lightSquareColor;
3165 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3167 gc_values.foreground = whitePieceColor;
3168 gc_values.background = jailSquareColor;
3169 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3171 gc_values.foreground = blackPieceColor;
3172 gc_values.background = darkSquareColor;
3173 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3175 gc_values.foreground = blackPieceColor;
3176 gc_values.background = lightSquareColor;
3177 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3179 gc_values.foreground = blackPieceColor;
3180 gc_values.background = jailSquareColor;
3181 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3185 void loadXIM(xim, xmask, filename, dest, mask)
3198 fp = fopen(filename, "rb");
3200 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3207 for (y=0; y<h; ++y) {
3208 for (x=0; x<h; ++x) {
3213 XPutPixel(xim, x, y, blackPieceColor);
3215 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3218 XPutPixel(xim, x, y, darkSquareColor);
3220 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3223 XPutPixel(xim, x, y, whitePieceColor);
3225 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3228 XPutPixel(xim, x, y, lightSquareColor);
3230 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3236 /* create Pixmap of piece */
3237 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3239 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3242 /* create Pixmap of clipmask
3243 Note: We assume the white/black pieces have the same
3244 outline, so we make only 6 masks. This is okay
3245 since the XPM clipmask routines do the same. */
3247 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3249 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3252 /* now create the 1-bit version */
3253 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3256 values.foreground = 1;
3257 values.background = 0;
3259 /* Don't use XtGetGC, not read only */
3260 maskGC = XCreateGC(xDisplay, *mask,
3261 GCForeground | GCBackground, &values);
3262 XCopyPlane(xDisplay, temp, *mask, maskGC,
3263 0, 0, squareSize, squareSize, 0, 0, 1);
3264 XFreePixmap(xDisplay, temp);
3269 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3271 void CreateXIMPieces()
3276 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3281 /* The XSynchronize calls were copied from CreatePieces.
3282 Not sure if needed, but can't hurt */
3283 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3286 /* temp needed by loadXIM() */
3287 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3288 0, 0, ss, ss, AllPlanes, XYPixmap);
3290 if (strlen(appData.pixmapDirectory) == 0) {
3294 if (appData.monoMode) {
3295 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3299 fprintf(stderr, _("\nLoading XIMs...\n"));
3301 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3302 fprintf(stderr, "%d", piece+1);
3303 for (kind=0; kind<4; kind++) {
3304 fprintf(stderr, ".");
3305 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3306 ExpandPathName(appData.pixmapDirectory),
3307 piece <= (int) WhiteKing ? "" : "w",
3308 pieceBitmapNames[piece],
3310 ximPieceBitmap[kind][piece] =
3311 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3312 0, 0, ss, ss, AllPlanes, XYPixmap);
3313 if (appData.debugMode)
3314 fprintf(stderr, _("(File:%s:) "), buf);
3315 loadXIM(ximPieceBitmap[kind][piece],
3317 &(xpmPieceBitmap2[kind][piece]),
3318 &(ximMaskPm2[piece]));
3319 if(piece <= (int)WhiteKing)
3320 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3322 fprintf(stderr," ");
3324 /* Load light and dark squares */
3325 /* If the LSQ and DSQ pieces don't exist, we will
3326 draw them with solid squares. */
3327 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3328 if (access(buf, 0) != 0) {
3332 fprintf(stderr, _("light square "));
3334 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3335 0, 0, ss, ss, AllPlanes, XYPixmap);
3336 if (appData.debugMode)
3337 fprintf(stderr, _("(File:%s:) "), buf);
3339 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3340 fprintf(stderr, _("dark square "));
3341 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3342 ExpandPathName(appData.pixmapDirectory), ss);
3343 if (appData.debugMode)
3344 fprintf(stderr, _("(File:%s:) "), buf);
3346 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3347 0, 0, ss, ss, AllPlanes, XYPixmap);
3348 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3349 xpmJailSquare = xpmLightSquare;
3351 fprintf(stderr, _("Done.\n"));
3353 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3357 void CreateXPMPieces()
3361 u_int ss = squareSize;
3363 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3364 XpmColorSymbol symbols[4];
3366 /* The XSynchronize calls were copied from CreatePieces.
3367 Not sure if needed, but can't hurt */
3368 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3370 /* Setup translations so piece colors match square colors */
3371 symbols[0].name = "light_piece";
3372 symbols[0].value = appData.whitePieceColor;
3373 symbols[1].name = "dark_piece";
3374 symbols[1].value = appData.blackPieceColor;
3375 symbols[2].name = "light_square";
3376 symbols[2].value = appData.lightSquareColor;
3377 symbols[3].name = "dark_square";
3378 symbols[3].value = appData.darkSquareColor;
3380 attr.valuemask = XpmColorSymbols;
3381 attr.colorsymbols = symbols;
3382 attr.numsymbols = 4;
3384 if (appData.monoMode) {
3385 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3389 if (strlen(appData.pixmapDirectory) == 0) {
3390 XpmPieces* pieces = builtInXpms;
3393 while (pieces->size != squareSize && pieces->size) pieces++;
3394 if (!pieces->size) {
3395 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3398 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3399 for (kind=0; kind<4; kind++) {
3401 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3402 pieces->xpm[piece][kind],
3403 &(xpmPieceBitmap2[kind][piece]),
3404 NULL, &attr)) != 0) {
3405 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3409 if(piece <= (int) WhiteKing)
3410 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3414 xpmJailSquare = xpmLightSquare;
3418 fprintf(stderr, _("\nLoading XPMs...\n"));
3421 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3422 fprintf(stderr, "%d ", piece+1);
3423 for (kind=0; kind<4; kind++) {
3424 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3425 ExpandPathName(appData.pixmapDirectory),
3426 piece > (int) WhiteKing ? "w" : "",
3427 pieceBitmapNames[piece],
3429 if (appData.debugMode) {
3430 fprintf(stderr, _("(File:%s:) "), buf);
3432 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3433 &(xpmPieceBitmap2[kind][piece]),
3434 NULL, &attr)) != 0) {
3435 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3436 // [HGM] missing: read of unorthodox piece failed; substitute King.
3437 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3438 ExpandPathName(appData.pixmapDirectory),
3440 if (appData.debugMode) {
3441 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3443 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3444 &(xpmPieceBitmap2[kind][piece]),
3448 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3453 if(piece <= (int) WhiteKing)
3454 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3457 /* Load light and dark squares */
3458 /* If the LSQ and DSQ pieces don't exist, we will
3459 draw them with solid squares. */
3460 fprintf(stderr, _("light square "));
3461 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3462 if (access(buf, 0) != 0) {
3466 if (appData.debugMode)
3467 fprintf(stderr, _("(File:%s:) "), buf);
3469 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3470 &xpmLightSquare, NULL, &attr)) != 0) {
3471 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3474 fprintf(stderr, _("dark square "));
3475 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3476 ExpandPathName(appData.pixmapDirectory), ss);
3477 if (appData.debugMode) {
3478 fprintf(stderr, _("(File:%s:) "), buf);
3480 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3481 &xpmDarkSquare, NULL, &attr)) != 0) {
3482 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3486 xpmJailSquare = xpmLightSquare;
3487 fprintf(stderr, _("Done.\n"));
3489 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3492 #endif /* HAVE_LIBXPM */
3495 /* No built-in bitmaps */
3500 u_int ss = squareSize;
3502 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3505 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3506 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3507 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3508 pieceBitmapNames[piece],
3509 ss, kind == SOLID ? 's' : 'o');
3510 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3511 if(piece <= (int)WhiteKing)
3512 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3516 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3520 /* With built-in bitmaps */
3523 BuiltInBits* bib = builtInBits;
3526 u_int ss = squareSize;
3528 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3531 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3533 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3534 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3535 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3536 pieceBitmapNames[piece],
3537 ss, kind == SOLID ? 's' : 'o');
3538 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3539 bib->bits[kind][piece], ss, ss);
3540 if(piece <= (int)WhiteKing)
3541 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3545 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3550 void ReadBitmap(pm, name, bits, wreq, hreq)
3553 unsigned char bits[];
3559 char msg[MSG_SIZ], fullname[MSG_SIZ];
3561 if (*appData.bitmapDirectory != NULLCHAR) {
3562 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3563 strcat(fullname, "/");
3564 strcat(fullname, name);
3565 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3566 &w, &h, pm, &x_hot, &y_hot);
3567 fprintf(stderr, "load %s\n", name);
3568 if (errcode != BitmapSuccess) {
3570 case BitmapOpenFailed:
3571 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3573 case BitmapFileInvalid:
3574 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3576 case BitmapNoMemory:
3577 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3581 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3585 fprintf(stderr, _("%s: %s...using built-in\n"),
3587 } else if (w != wreq || h != hreq) {
3589 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3590 programName, fullname, w, h, wreq, hreq);
3596 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3605 if (lineGap == 0) return;
3607 /* [HR] Split this into 2 loops for non-square boards. */
3609 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3610 gridSegments[i].x1 = 0;
3611 gridSegments[i].x2 =
3612 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3613 gridSegments[i].y1 = gridSegments[i].y2
3614 = lineGap / 2 + (i * (squareSize + lineGap));
3617 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3618 gridSegments[j + i].y1 = 0;
3619 gridSegments[j + i].y2 =
3620 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3621 gridSegments[j + i].x1 = gridSegments[j + i].x2
3622 = lineGap / 2 + (j * (squareSize + lineGap));
3626 static void MenuBarSelect(w, addr, index)
3631 XtActionProc proc = (XtActionProc) addr;
3633 (proc)(NULL, NULL, NULL, NULL);
3636 void CreateMenuBarPopup(parent, name, mb)
3646 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3649 XtSetArg(args[j], XtNleftMargin, 20); j++;
3650 XtSetArg(args[j], XtNrightMargin, 20); j++;
3652 while (mi->string != NULL) {
3653 if (strcmp(mi->string, "----") == 0) {
3654 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3657 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3658 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3660 XtAddCallback(entry, XtNcallback,
3661 (XtCallbackProc) MenuBarSelect,
3662 (caddr_t) mi->proc);
3668 Widget CreateMenuBar(mb)
3672 Widget anchor, menuBar;
3674 char menuName[MSG_SIZ];
3677 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3678 XtSetArg(args[j], XtNvSpace, 0); j++;
3679 XtSetArg(args[j], XtNborderWidth, 0); j++;
3680 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3681 formWidget, args, j);
3683 while (mb->name != NULL) {
3684 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3685 strcat(menuName, mb->name);
3687 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3690 shortName[0] = _(mb->name)[0];
3691 shortName[1] = NULLCHAR;
3692 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3695 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3698 XtSetArg(args[j], XtNborderWidth, 0); j++;
3699 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3701 CreateMenuBarPopup(menuBar, menuName, mb);
3707 Widget CreateButtonBar(mi)
3711 Widget button, buttonBar;
3715 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3717 XtSetArg(args[j], XtNhSpace, 0); j++;
3719 XtSetArg(args[j], XtNborderWidth, 0); j++;
3720 XtSetArg(args[j], XtNvSpace, 0); j++;
3721 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3722 formWidget, args, j);
3724 while (mi->string != NULL) {
3727 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3728 XtSetArg(args[j], XtNborderWidth, 0); j++;
3730 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3731 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3732 buttonBar, args, j);
3733 XtAddCallback(button, XtNcallback,
3734 (XtCallbackProc) MenuBarSelect,
3735 (caddr_t) mi->proc);
3742 CreatePieceMenu(name, color)
3749 ChessSquare selection;
3751 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3752 boardWidget, args, 0);
3754 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3755 String item = pieceMenuStrings[color][i];
3757 if (strcmp(item, "----") == 0) {
3758 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3761 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3762 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3764 selection = pieceMenuTranslation[color][i];
3765 XtAddCallback(entry, XtNcallback,
3766 (XtCallbackProc) PieceMenuSelect,
3767 (caddr_t) selection);
3768 if (selection == WhitePawn || selection == BlackPawn) {
3769 XtSetArg(args[0], XtNpopupOnEntry, entry);
3770 XtSetValues(menu, args, 1);
3783 ChessSquare selection;
3785 whitePieceMenu = CreatePieceMenu("menuW", 0);
3786 blackPieceMenu = CreatePieceMenu("menuB", 1);
3788 XtRegisterGrabAction(PieceMenuPopup, True,
3789 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3790 GrabModeAsync, GrabModeAsync);
3792 XtSetArg(args[0], XtNlabel, _("Drop"));
3793 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3794 boardWidget, args, 1);
3795 for (i = 0; i < DROP_MENU_SIZE; i++) {
3796 String item = dropMenuStrings[i];
3798 if (strcmp(item, "----") == 0) {
3799 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3802 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3803 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3805 selection = dropMenuTranslation[i];
3806 XtAddCallback(entry, XtNcallback,
3807 (XtCallbackProc) DropMenuSelect,
3808 (caddr_t) selection);
3813 void SetupDropMenu()
3821 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3822 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3823 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3824 dmEnables[i].piece);
3825 XtSetSensitive(entry, p != NULL || !appData.testLegality
3826 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3827 && !appData.icsActive));
3829 while (p && *p++ == dmEnables[i].piece) count++;
3830 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3832 XtSetArg(args[j], XtNlabel, label); j++;
3833 XtSetValues(entry, args, j);
3837 void PieceMenuPopup(w, event, params, num_params)
3841 Cardinal *num_params;
3843 String whichMenu; int menuNr;
3844 if (event->type == ButtonRelease)
3845 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3846 else if (event->type == ButtonPress)
3847 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3849 case 0: whichMenu = params[0]; break;
3850 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3852 case -1: if (errorUp) ErrorPopDown();
3855 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3858 static void PieceMenuSelect(w, piece, junk)
3863 if (pmFromX < 0 || pmFromY < 0) return;
3864 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3867 static void DropMenuSelect(w, piece, junk)
3872 if (pmFromX < 0 || pmFromY < 0) return;
3873 DropMenuEvent(piece, pmFromX, pmFromY);
3876 void WhiteClock(w, event, prms, nprms)
3882 if (gameMode == EditPosition || gameMode == IcsExamining) {
3883 SetWhiteToPlayEvent();
3884 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3889 void BlackClock(w, event, prms, nprms)
3895 if (gameMode == EditPosition || gameMode == IcsExamining) {
3896 SetBlackToPlayEvent();
3897 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3904 * If the user selects on a border boundary, return -1; if off the board,
3905 * return -2. Otherwise map the event coordinate to the square.
3907 int EventToSquare(x, limit)
3915 if ((x % (squareSize + lineGap)) >= squareSize)
3917 x /= (squareSize + lineGap);
3923 static void do_flash_delay(msec)
3929 static void drawHighlight(file, rank, gc)
3935 if (lineGap == 0 || appData.blindfold) return;
3938 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3939 (squareSize + lineGap);
3940 y = lineGap/2 + rank * (squareSize + lineGap);
3942 x = lineGap/2 + file * (squareSize + lineGap);
3943 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3944 (squareSize + lineGap);
3947 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3948 squareSize+lineGap, squareSize+lineGap);
3951 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3952 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3955 SetHighlights(fromX, fromY, toX, toY)
3956 int fromX, fromY, toX, toY;
3958 if (hi1X != fromX || hi1Y != fromY) {
3959 if (hi1X >= 0 && hi1Y >= 0) {
3960 drawHighlight(hi1X, hi1Y, lineGC);
3962 } // [HGM] first erase both, then draw new!
3963 if (hi2X != toX || hi2Y != toY) {
3964 if (hi2X >= 0 && hi2Y >= 0) {
3965 drawHighlight(hi2X, hi2Y, lineGC);
3968 if (hi1X != fromX || hi1Y != fromY) {
3969 if (fromX >= 0 && fromY >= 0) {
3970 drawHighlight(fromX, fromY, highlineGC);
3973 if (hi2X != toX || hi2Y != toY) {
3974 if (toX >= 0 && toY >= 0) {
3975 drawHighlight(toX, toY, highlineGC);
3987 SetHighlights(-1, -1, -1, -1);
3992 SetPremoveHighlights(fromX, fromY, toX, toY)
3993 int fromX, fromY, toX, toY;
3995 if (pm1X != fromX || pm1Y != fromY) {
3996 if (pm1X >= 0 && pm1Y >= 0) {
3997 drawHighlight(pm1X, pm1Y, lineGC);
3999 if (fromX >= 0 && fromY >= 0) {
4000 drawHighlight(fromX, fromY, prelineGC);
4003 if (pm2X != toX || pm2Y != toY) {
4004 if (pm2X >= 0 && pm2Y >= 0) {
4005 drawHighlight(pm2X, pm2Y, lineGC);
4007 if (toX >= 0 && toY >= 0) {
4008 drawHighlight(toX, toY, prelineGC);
4018 ClearPremoveHighlights()
4020 SetPremoveHighlights(-1, -1, -1, -1);
4023 static void BlankSquare(x, y, color, piece, dest)
4028 if (useImages && useImageSqs) {
4032 pm = xpmLightSquare;
4037 case 2: /* neutral */
4042 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4043 squareSize, squareSize, x, y);
4053 case 2: /* neutral */
4058 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4063 I split out the routines to draw a piece so that I could
4064 make a generic flash routine.
4066 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4068 int square_color, x, y;
4071 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4072 switch (square_color) {
4074 case 2: /* neutral */
4076 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4077 ? *pieceToOutline(piece)
4078 : *pieceToSolid(piece),
4079 dest, bwPieceGC, 0, 0,
4080 squareSize, squareSize, x, y);
4083 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4084 ? *pieceToSolid(piece)
4085 : *pieceToOutline(piece),
4086 dest, wbPieceGC, 0, 0,
4087 squareSize, squareSize, x, y);
4092 static void monoDrawPiece(piece, square_color, x, y, dest)
4094 int square_color, x, y;
4097 switch (square_color) {
4099 case 2: /* neutral */
4101 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4102 ? *pieceToOutline(piece)
4103 : *pieceToSolid(piece),
4104 dest, bwPieceGC, 0, 0,
4105 squareSize, squareSize, x, y, 1);
4108 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4109 ? *pieceToSolid(piece)
4110 : *pieceToOutline(piece),
4111 dest, wbPieceGC, 0, 0,
4112 squareSize, squareSize, x, y, 1);
4117 static void colorDrawPiece(piece, square_color, x, y, dest)
4119 int square_color, x, y;
4122 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4123 switch (square_color) {
4125 XCopyPlane(xDisplay, *pieceToSolid(piece),
4126 dest, (int) piece < (int) BlackPawn
4127 ? wlPieceGC : blPieceGC, 0, 0,
4128 squareSize, squareSize, x, y, 1);
4131 XCopyPlane(xDisplay, *pieceToSolid(piece),
4132 dest, (int) piece < (int) BlackPawn
4133 ? wdPieceGC : bdPieceGC, 0, 0,
4134 squareSize, squareSize, x, y, 1);
4136 case 2: /* neutral */
4138 XCopyPlane(xDisplay, *pieceToSolid(piece),
4139 dest, (int) piece < (int) BlackPawn
4140 ? wjPieceGC : bjPieceGC, 0, 0,
4141 squareSize, squareSize, x, y, 1);
4146 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4148 int square_color, x, y;
4153 switch (square_color) {
4155 case 2: /* neutral */
4157 if ((int)piece < (int) BlackPawn) {
4165 if ((int)piece < (int) BlackPawn) {
4173 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4174 dest, wlPieceGC, 0, 0,
4175 squareSize, squareSize, x, y);
4178 typedef void (*DrawFunc)();
4180 DrawFunc ChooseDrawFunc()
4182 if (appData.monoMode) {
4183 if (DefaultDepth(xDisplay, xScreen) == 1) {
4184 return monoDrawPiece_1bit;
4186 return monoDrawPiece;
4190 return colorDrawPieceImage;
4192 return colorDrawPiece;
4196 /* [HR] determine square color depending on chess variant. */
4197 static int SquareColor(row, column)
4202 if (gameInfo.variant == VariantXiangqi) {
4203 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4205 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4207 } else if (row <= 4) {
4213 square_color = ((column + row) % 2) == 1;
4216 /* [hgm] holdings: next line makes all holdings squares light */
4217 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4219 return square_color;
4222 void DrawSquare(row, column, piece, do_flash)
4223 int row, column, do_flash;
4226 int square_color, x, y, direction, font_ascent, font_descent;
4229 XCharStruct overall;
4233 /* Calculate delay in milliseconds (2-delays per complete flash) */
4234 flash_delay = 500 / appData.flashRate;
4237 x = lineGap + ((BOARD_WIDTH-1)-column) *
4238 (squareSize + lineGap);
4239 y = lineGap + row * (squareSize + lineGap);
4241 x = lineGap + column * (squareSize + lineGap);
4242 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4243 (squareSize + lineGap);
4246 if(twoBoards && partnerUp) x += hOffset; // [HGM] dual: draw second board
4248 square_color = SquareColor(row, column);
4250 if ( // [HGM] holdings: blank out area between board and holdings
4251 column == BOARD_LEFT-1 || column == BOARD_RGHT
4252 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4253 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4254 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4256 // [HGM] print piece counts next to holdings
4257 string[1] = NULLCHAR;
4258 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4259 string[0] = '0' + piece;
4260 XTextExtents(countFontStruct, string, 1, &direction,
4261 &font_ascent, &font_descent, &overall);
4262 if (appData.monoMode) {
4263 XDrawImageString(xDisplay, xBoardWindow, countGC,
4264 x + squareSize - overall.width - 2,
4265 y + font_ascent + 1, string, 1);
4267 XDrawString(xDisplay, xBoardWindow, countGC,