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
1590 ConvertToLine(int argc, char **argv)
1592 static char line[128*1024], buf[1024];
1596 for(i=1; i<argc; i++)
1598 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1599 && argv[i][0] != '{' )
1600 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1602 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1603 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1606 line[strlen(line)-1] = NULLCHAR;
1610 //--------------------------------------------------------------------------------------------
1612 extern Boolean twoBoards, partnerUp;
1615 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1617 #define BoardSize int
1618 void InitDrawingSizes(BoardSize boardSize, int flags)
1619 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1620 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1622 XtGeometryResult gres;
1625 if(!formWidget) return;
1628 * Enable shell resizing.
1630 shellArgs[0].value = (XtArgVal) &w;
1631 shellArgs[1].value = (XtArgVal) &h;
1632 XtGetValues(shellWidget, shellArgs, 2);
1634 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1635 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1636 XtSetValues(shellWidget, &shellArgs[2], 4);
1638 XtSetArg(args[0], XtNdefaultDistance, &sep);
1639 XtGetValues(formWidget, args, 1);
1641 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1642 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1644 hOffset = boardWidth + 10;
1645 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1646 secondSegments[i] = gridSegments[i];
1647 secondSegments[i].x1 += hOffset;
1648 secondSegments[i].x2 += hOffset;
1651 XtSetArg(args[0], XtNwidth, boardWidth);
1652 XtSetArg(args[1], XtNheight, boardHeight);
1653 XtSetValues(boardWidget, args, 2);
1655 timerWidth = (boardWidth - sep) / 2;
1656 XtSetArg(args[0], XtNwidth, timerWidth);
1657 XtSetValues(whiteTimerWidget, args, 1);
1658 XtSetValues(blackTimerWidget, args, 1);
1660 XawFormDoLayout(formWidget, False);
1662 if (appData.titleInWindow) {
1664 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1665 XtSetArg(args[i], XtNheight, &h); i++;
1666 XtGetValues(titleWidget, args, i);
1668 w = boardWidth - 2*bor;
1670 XtSetArg(args[0], XtNwidth, &w);
1671 XtGetValues(menuBarWidget, args, 1);
1672 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1675 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1676 if (gres != XtGeometryYes && appData.debugMode) {
1678 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1679 programName, gres, w, h, wr, hr);
1683 XawFormDoLayout(formWidget, True);
1686 * Inhibit shell resizing.
1688 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1689 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1690 shellArgs[4].value = shellArgs[2].value = w;
1691 shellArgs[5].value = shellArgs[3].value = h;
1692 XtSetValues(shellWidget, &shellArgs[0], 6);
1694 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1697 for(i=0; i<4; i++) {
1699 for(p=0; p<=(int)WhiteKing; p++)
1700 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1701 if(gameInfo.variant == VariantShogi) {
1702 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1703 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1704 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1705 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1706 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1709 if(gameInfo.variant == VariantGothic) {
1710 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1714 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1715 for(p=0; p<=(int)WhiteKing; p++)
1716 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1717 if(gameInfo.variant == VariantShogi) {
1718 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1719 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1720 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1721 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1722 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1725 if(gameInfo.variant == VariantGothic) {
1726 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1732 for(i=0; i<2; i++) {
1734 for(p=0; p<=(int)WhiteKing; p++)
1735 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1736 if(gameInfo.variant == VariantShogi) {
1737 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1738 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1739 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1740 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1741 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1744 if(gameInfo.variant == VariantGothic) {
1745 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1761 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1762 XSetWindowAttributes window_attributes;
1764 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1765 XrmValue vFrom, vTo;
1766 XtGeometryResult gres;
1769 int forceMono = False;
1771 srandom(time(0)); // [HGM] book: make random truly random
1773 setbuf(stdout, NULL);
1774 setbuf(stderr, NULL);
1777 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1778 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1782 programName = strrchr(argv[0], '/');
1783 if (programName == NULL)
1784 programName = argv[0];
1789 XtSetLanguageProc(NULL, NULL, NULL);
1790 bindtextdomain(PACKAGE, LOCALEDIR);
1791 textdomain(PACKAGE);
1795 XtAppInitialize(&appContext, "XBoard", shellOptions,
1796 XtNumber(shellOptions),
1797 &argc, argv, xboardResources, NULL, 0);
1798 appData.boardSize = "";
1799 InitAppData(ConvertToLine(argc, argv));
1801 if (p == NULL) p = "/tmp";
1802 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1803 gameCopyFilename = (char*) malloc(i);
1804 gamePasteFilename = (char*) malloc(i);
1805 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1806 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1808 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1809 clientResources, XtNumber(clientResources),
1812 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1813 static char buf[MSG_SIZ];
1814 EscapeExpand(buf, appData.initString);
1815 appData.initString = strdup(buf);
1816 EscapeExpand(buf, appData.secondInitString);
1817 appData.secondInitString = strdup(buf);
1818 EscapeExpand(buf, appData.firstComputerString);
1819 appData.firstComputerString = strdup(buf);
1820 EscapeExpand(buf, appData.secondComputerString);
1821 appData.secondComputerString = strdup(buf);
1824 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1827 if (chdir(chessDir) != 0) {
1828 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1834 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1835 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1836 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1837 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1840 setbuf(debugFP, NULL);
1843 /* [HGM,HR] make sure board size is acceptable */
1844 if(appData.NrFiles > BOARD_FILES ||
1845 appData.NrRanks > BOARD_RANKS )
1846 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1849 /* This feature does not work; animation needs a rewrite */
1850 appData.highlightDragging = FALSE;
1854 xDisplay = XtDisplay(shellWidget);
1855 xScreen = DefaultScreen(xDisplay);
1856 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1858 gameInfo.variant = StringToVariant(appData.variant);
1859 InitPosition(FALSE);
1862 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1864 if (isdigit(appData.boardSize[0])) {
1865 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1866 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1867 &fontPxlSize, &smallLayout, &tinyLayout);
1869 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1870 programName, appData.boardSize);
1874 /* Find some defaults; use the nearest known size */
1875 SizeDefaults *szd, *nearest;
1876 int distance = 99999;
1877 nearest = szd = sizeDefaults;
1878 while (szd->name != NULL) {
1879 if (abs(szd->squareSize - squareSize) < distance) {
1881 distance = abs(szd->squareSize - squareSize);
1882 if (distance == 0) break;
1886 if (i < 2) lineGap = nearest->lineGap;
1887 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1888 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1889 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1890 if (i < 6) smallLayout = nearest->smallLayout;
1891 if (i < 7) tinyLayout = nearest->tinyLayout;
1894 SizeDefaults *szd = sizeDefaults;
1895 if (*appData.boardSize == NULLCHAR) {
1896 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1897 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1900 if (szd->name == NULL) szd--;
1901 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1903 while (szd->name != NULL &&
1904 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1905 if (szd->name == NULL) {
1906 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1907 programName, appData.boardSize);
1911 squareSize = szd->squareSize;
1912 lineGap = szd->lineGap;
1913 clockFontPxlSize = szd->clockFontPxlSize;
1914 coordFontPxlSize = szd->coordFontPxlSize;
1915 fontPxlSize = szd->fontPxlSize;
1916 smallLayout = szd->smallLayout;
1917 tinyLayout = szd->tinyLayout;
1918 // [HGM] font: use defaults from settings file if available and not overruled
1920 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1921 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1922 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1923 appData.font = fontTable[MESSAGE_FONT][squareSize];
1924 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1925 appData.coordFont = fontTable[COORD_FONT][squareSize];
1927 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1928 if (strlen(appData.pixmapDirectory) > 0) {
1929 p = ExpandPathName(appData.pixmapDirectory);
1931 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1932 appData.pixmapDirectory);
1935 if (appData.debugMode) {
1936 fprintf(stderr, _("\
1937 XBoard square size (hint): %d\n\
1938 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1940 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1941 if (appData.debugMode) {
1942 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1946 /* [HR] height treated separately (hacked) */
1947 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1948 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1949 if (appData.showJail == 1) {
1950 /* Jail on top and bottom */
1951 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1952 XtSetArg(boardArgs[2], XtNheight,
1953 boardHeight + 2*(lineGap + squareSize));
1954 } else if (appData.showJail == 2) {
1956 XtSetArg(boardArgs[1], XtNwidth,
1957 boardWidth + 2*(lineGap + squareSize));
1958 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1961 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1962 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1966 * Determine what fonts to use.
1968 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1969 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1970 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1971 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1972 coordFontID = XLoadFont(xDisplay, appData.coordFont);
1973 coordFontStruct = XQueryFont(xDisplay, coordFontID);
1974 appData.font = FindFont(appData.font, fontPxlSize);
1975 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
1976 countFontStruct = XQueryFont(xDisplay, countFontID);
1977 // appData.font = FindFont(appData.font, fontPxlSize);
1979 xdb = XtDatabase(xDisplay);
1980 XrmPutStringResource(&xdb, "*font", appData.font);
1983 * Detect if there are not enough colors available and adapt.
1985 if (DefaultDepth(xDisplay, xScreen) <= 2) {
1986 appData.monoMode = True;
1989 if (!appData.monoMode) {
1990 vFrom.addr = (caddr_t) appData.lightSquareColor;
1991 vFrom.size = strlen(appData.lightSquareColor);
1992 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1993 if (vTo.addr == NULL) {
1994 appData.monoMode = True;
1997 lightSquareColor = *(Pixel *) vTo.addr;
2000 if (!appData.monoMode) {
2001 vFrom.addr = (caddr_t) appData.darkSquareColor;
2002 vFrom.size = strlen(appData.darkSquareColor);
2003 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2004 if (vTo.addr == NULL) {
2005 appData.monoMode = True;
2008 darkSquareColor = *(Pixel *) vTo.addr;
2011 if (!appData.monoMode) {
2012 vFrom.addr = (caddr_t) appData.whitePieceColor;
2013 vFrom.size = strlen(appData.whitePieceColor);
2014 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2015 if (vTo.addr == NULL) {
2016 appData.monoMode = True;
2019 whitePieceColor = *(Pixel *) vTo.addr;
2022 if (!appData.monoMode) {
2023 vFrom.addr = (caddr_t) appData.blackPieceColor;
2024 vFrom.size = strlen(appData.blackPieceColor);
2025 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2026 if (vTo.addr == NULL) {
2027 appData.monoMode = True;
2030 blackPieceColor = *(Pixel *) vTo.addr;
2034 if (!appData.monoMode) {
2035 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2036 vFrom.size = strlen(appData.highlightSquareColor);
2037 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2038 if (vTo.addr == NULL) {
2039 appData.monoMode = True;
2042 highlightSquareColor = *(Pixel *) vTo.addr;
2046 if (!appData.monoMode) {
2047 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2048 vFrom.size = strlen(appData.premoveHighlightColor);
2049 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2050 if (vTo.addr == NULL) {
2051 appData.monoMode = True;
2054 premoveHighlightColor = *(Pixel *) vTo.addr;
2059 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2062 if (appData.bitmapDirectory == NULL ||
2063 appData.bitmapDirectory[0] == NULLCHAR)
2064 appData.bitmapDirectory = DEF_BITMAP_DIR;
2067 if (appData.lowTimeWarning && !appData.monoMode) {
2068 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2069 vFrom.size = strlen(appData.lowTimeWarningColor);
2070 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2071 if (vTo.addr == NULL)
2072 appData.monoMode = True;
2074 lowTimeWarningColor = *(Pixel *) vTo.addr;
2077 if (appData.monoMode && appData.debugMode) {
2078 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2079 (unsigned long) XWhitePixel(xDisplay, xScreen),
2080 (unsigned long) XBlackPixel(xDisplay, xScreen));
2083 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2084 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2085 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2086 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2087 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2088 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2089 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2090 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2091 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2092 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2094 if (appData.colorize) {
2096 _("%s: can't parse color names; disabling colorization\n"),
2099 appData.colorize = FALSE;
2101 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2102 textColors[ColorNone].attr = 0;
2104 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2110 layoutName = "tinyLayout";
2111 } else if (smallLayout) {
2112 layoutName = "smallLayout";
2114 layoutName = "normalLayout";
2116 /* Outer layoutWidget is there only to provide a name for use in
2117 resources that depend on the layout style */
2119 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2120 layoutArgs, XtNumber(layoutArgs));
2122 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2123 formArgs, XtNumber(formArgs));
2124 XtSetArg(args[0], XtNdefaultDistance, &sep);
2125 XtGetValues(formWidget, args, 1);
2128 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2129 XtSetArg(args[0], XtNtop, XtChainTop);
2130 XtSetArg(args[1], XtNbottom, XtChainTop);
2131 XtSetArg(args[2], XtNright, XtChainLeft);
2132 XtSetValues(menuBarWidget, args, 3);
2134 widgetList[j++] = whiteTimerWidget =
2135 XtCreateWidget("whiteTime", labelWidgetClass,
2136 formWidget, timerArgs, XtNumber(timerArgs));
2137 XtSetArg(args[0], XtNfont, clockFontStruct);
2138 XtSetArg(args[1], XtNtop, XtChainTop);
2139 XtSetArg(args[2], XtNbottom, XtChainTop);
2140 XtSetValues(whiteTimerWidget, args, 3);
2142 widgetList[j++] = blackTimerWidget =
2143 XtCreateWidget("blackTime", labelWidgetClass,
2144 formWidget, timerArgs, XtNumber(timerArgs));
2145 XtSetArg(args[0], XtNfont, clockFontStruct);
2146 XtSetArg(args[1], XtNtop, XtChainTop);
2147 XtSetArg(args[2], XtNbottom, XtChainTop);
2148 XtSetValues(blackTimerWidget, args, 3);
2150 if (appData.titleInWindow) {
2151 widgetList[j++] = titleWidget =
2152 XtCreateWidget("title", labelWidgetClass, formWidget,
2153 titleArgs, XtNumber(titleArgs));
2154 XtSetArg(args[0], XtNtop, XtChainTop);
2155 XtSetArg(args[1], XtNbottom, XtChainTop);
2156 XtSetValues(titleWidget, args, 2);
2159 if (appData.showButtonBar) {
2160 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2161 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2162 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2163 XtSetArg(args[2], XtNtop, XtChainTop);
2164 XtSetArg(args[3], XtNbottom, XtChainTop);
2165 XtSetValues(buttonBarWidget, args, 4);
2168 widgetList[j++] = messageWidget =
2169 XtCreateWidget("message", labelWidgetClass, formWidget,
2170 messageArgs, XtNumber(messageArgs));
2171 XtSetArg(args[0], XtNtop, XtChainTop);
2172 XtSetArg(args[1], XtNbottom, XtChainTop);
2173 XtSetValues(messageWidget, args, 2);
2175 widgetList[j++] = boardWidget =
2176 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2177 XtNumber(boardArgs));
2179 XtManageChildren(widgetList, j);
2181 timerWidth = (boardWidth - sep) / 2;
2182 XtSetArg(args[0], XtNwidth, timerWidth);
2183 XtSetValues(whiteTimerWidget, args, 1);
2184 XtSetValues(blackTimerWidget, args, 1);
2186 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2187 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2188 XtGetValues(whiteTimerWidget, args, 2);
2190 if (appData.showButtonBar) {
2191 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2192 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2193 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2197 * formWidget uses these constraints but they are stored
2201 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2202 XtSetValues(menuBarWidget, args, i);
2203 if (appData.titleInWindow) {
2206 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2207 XtSetValues(whiteTimerWidget, args, i);
2209 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2210 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2211 XtSetValues(blackTimerWidget, args, i);
2213 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2214 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2215 XtSetValues(titleWidget, args, i);
2217 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2218 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2219 XtSetValues(messageWidget, args, i);
2220 if (appData.showButtonBar) {
2222 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2223 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2224 XtSetValues(buttonBarWidget, args, i);
2228 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2229 XtSetValues(whiteTimerWidget, args, i);
2231 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2232 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2233 XtSetValues(blackTimerWidget, args, i);
2235 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2236 XtSetValues(titleWidget, args, i);
2238 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2239 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2240 XtSetValues(messageWidget, args, i);
2241 if (appData.showButtonBar) {
2243 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2244 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2245 XtSetValues(buttonBarWidget, args, i);
2250 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2251 XtSetValues(whiteTimerWidget, args, i);
2253 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2254 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2255 XtSetValues(blackTimerWidget, args, i);
2257 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2258 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2259 XtSetValues(messageWidget, args, i);
2260 if (appData.showButtonBar) {
2262 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2263 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2264 XtSetValues(buttonBarWidget, args, i);
2268 XtSetArg(args[0], XtNfromVert, messageWidget);
2269 XtSetArg(args[1], XtNtop, XtChainTop);
2270 XtSetArg(args[2], XtNbottom, XtChainBottom);
2271 XtSetArg(args[3], XtNleft, XtChainLeft);
2272 XtSetArg(args[4], XtNright, XtChainRight);
2273 XtSetValues(boardWidget, args, 5);
2275 XtRealizeWidget(shellWidget);
2278 XtSetArg(args[0], XtNx, wpMain.x);
2279 XtSetArg(args[1], XtNy, wpMain.y);
2280 XtSetValues(shellWidget, args, 2);
2284 * Correct the width of the message and title widgets.
2285 * It is not known why some systems need the extra fudge term.
2286 * The value "2" is probably larger than needed.
2288 XawFormDoLayout(formWidget, False);
2290 #define WIDTH_FUDGE 2
2292 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2293 XtSetArg(args[i], XtNheight, &h); i++;
2294 XtGetValues(messageWidget, args, i);
2295 if (appData.showButtonBar) {
2297 XtSetArg(args[i], XtNwidth, &w); i++;
2298 XtGetValues(buttonBarWidget, args, i);
2299 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2301 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2304 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2305 if (gres != XtGeometryYes && appData.debugMode) {
2306 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2307 programName, gres, w, h, wr, hr);
2310 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2311 /* The size used for the child widget in layout lags one resize behind
2312 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2314 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2315 if (gres != XtGeometryYes && appData.debugMode) {
2316 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2317 programName, gres, w, h, wr, hr);
2320 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2321 XtSetArg(args[1], XtNright, XtChainRight);
2322 XtSetValues(messageWidget, args, 2);
2324 if (appData.titleInWindow) {
2326 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2327 XtSetArg(args[i], XtNheight, &h); i++;
2328 XtGetValues(titleWidget, args, i);
2330 w = boardWidth - 2*bor;
2332 XtSetArg(args[0], XtNwidth, &w);
2333 XtGetValues(menuBarWidget, args, 1);
2334 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2337 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2338 if (gres != XtGeometryYes && appData.debugMode) {
2340 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2341 programName, gres, w, h, wr, hr);
2344 XawFormDoLayout(formWidget, True);
2346 xBoardWindow = XtWindow(boardWidget);
2348 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2349 // not need to go into InitDrawingSizes().
2353 * Create X checkmark bitmap and initialize option menu checks.
2355 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2356 checkmark_bits, checkmark_width, checkmark_height);
2357 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2358 if (appData.alwaysPromoteToQueen) {
2359 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2362 if (appData.animateDragging) {
2363 XtSetValues(XtNameToWidget(menuBarWidget,
2364 "menuOptions.Animate Dragging"),
2367 if (appData.animate) {
2368 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2371 if (appData.autoComment) {
2372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2375 if (appData.autoCallFlag) {
2376 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2379 if (appData.autoFlipView) {
2380 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2383 if (appData.autoObserve) {
2384 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2387 if (appData.autoRaiseBoard) {
2388 XtSetValues(XtNameToWidget(menuBarWidget,
2389 "menuOptions.Auto Raise Board"), args, 1);
2391 if (appData.autoSaveGames) {
2392 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2395 if (appData.saveGameFile[0] != NULLCHAR) {
2396 /* Can't turn this off from menu */
2397 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2399 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2403 if (appData.blindfold) {
2404 XtSetValues(XtNameToWidget(menuBarWidget,
2405 "menuOptions.Blindfold"), args, 1);
2407 if (appData.flashCount > 0) {
2408 XtSetValues(XtNameToWidget(menuBarWidget,
2409 "menuOptions.Flash Moves"),
2412 if (appData.getMoveList) {
2413 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2417 if (appData.highlightDragging) {
2418 XtSetValues(XtNameToWidget(menuBarWidget,
2419 "menuOptions.Highlight Dragging"),
2423 if (appData.highlightLastMove) {
2424 XtSetValues(XtNameToWidget(menuBarWidget,
2425 "menuOptions.Highlight Last Move"),
2428 if (appData.icsAlarm) {
2429 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2432 if (appData.ringBellAfterMoves) {
2433 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2436 if (appData.oldSaveStyle) {
2437 XtSetValues(XtNameToWidget(menuBarWidget,
2438 "menuOptions.Old Save Style"), args, 1);
2440 if (appData.periodicUpdates) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Periodic Updates"), args, 1);
2444 if (appData.ponderNextMove) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Ponder Next Move"), args, 1);
2448 if (appData.popupExitMessage) {
2449 XtSetValues(XtNameToWidget(menuBarWidget,
2450 "menuOptions.Popup Exit Message"), args, 1);
2452 if (appData.popupMoveErrors) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,
2454 "menuOptions.Popup Move Errors"), args, 1);
2456 if (appData.premove) {
2457 XtSetValues(XtNameToWidget(menuBarWidget,
2458 "menuOptions.Premove"), args, 1);
2460 if (appData.quietPlay) {
2461 XtSetValues(XtNameToWidget(menuBarWidget,
2462 "menuOptions.Quiet Play"), args, 1);
2464 if (appData.showCoords) {
2465 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2468 if (appData.hideThinkingFromHuman) {
2469 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2472 if (appData.testLegality) {
2473 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2476 if (saveSettingsOnExit) {
2477 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2484 ReadBitmap(&wIconPixmap, "icon_white.bm",
2485 icon_white_bits, icon_white_width, icon_white_height);
2486 ReadBitmap(&bIconPixmap, "icon_black.bm",
2487 icon_black_bits, icon_black_width, icon_black_height);
2488 iconPixmap = wIconPixmap;
2490 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2491 XtSetValues(shellWidget, args, i);
2494 * Create a cursor for the board widget.
2496 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2497 XChangeWindowAttributes(xDisplay, xBoardWindow,
2498 CWCursor, &window_attributes);
2501 * Inhibit shell resizing.
2503 shellArgs[0].value = (XtArgVal) &w;
2504 shellArgs[1].value = (XtArgVal) &h;
2505 XtGetValues(shellWidget, shellArgs, 2);
2506 shellArgs[4].value = shellArgs[2].value = w;
2507 shellArgs[5].value = shellArgs[3].value = h;
2508 XtSetValues(shellWidget, &shellArgs[2], 4);
2509 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2510 marginH = h - boardHeight;
2512 CatchDeleteWindow(shellWidget, "QuitProc");
2517 if (appData.bitmapDirectory[0] != NULLCHAR) {
2524 /* Create regular pieces */
2525 if (!useImages) CreatePieces();
2530 if (appData.animate || appData.animateDragging)
2533 XtAugmentTranslations(formWidget,
2534 XtParseTranslationTable(globalTranslations));
2535 XtAugmentTranslations(boardWidget,
2536 XtParseTranslationTable(boardTranslations));
2537 XtAugmentTranslations(whiteTimerWidget,
2538 XtParseTranslationTable(whiteTranslations));
2539 XtAugmentTranslations(blackTimerWidget,
2540 XtParseTranslationTable(blackTranslations));
2542 /* Why is the following needed on some versions of X instead
2543 * of a translation? */
2544 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2545 (XtEventHandler) EventProc, NULL);
2548 /* [AS] Restore layout */
2549 if( wpMoveHistory.visible ) {
2553 if( wpEvalGraph.visible )
2558 if( wpEngineOutput.visible ) {
2559 EngineOutputPopUp();
2564 if (errorExitStatus == -1) {
2565 if (appData.icsActive) {
2566 /* We now wait until we see "login:" from the ICS before
2567 sending the logon script (problems with timestamp otherwise) */
2568 /*ICSInitScript();*/
2569 if (appData.icsInputBox) ICSInputBoxPopUp();
2573 signal(SIGWINCH, TermSizeSigHandler);
2575 signal(SIGINT, IntSigHandler);
2576 signal(SIGTERM, IntSigHandler);
2577 if (*appData.cmailGameName != NULLCHAR) {
2578 signal(SIGUSR1, CmailSigHandler);
2581 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2583 XtSetKeyboardFocus(shellWidget, formWidget);
2585 XtAppMainLoop(appContext);
2586 if (appData.debugMode) fclose(debugFP); // [DM] debug
2593 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2594 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2596 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2597 unlink(gameCopyFilename);
2598 unlink(gamePasteFilename);
2601 RETSIGTYPE TermSizeSigHandler(int sig)
2614 CmailSigHandler(sig)
2620 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2622 /* Activate call-back function CmailSigHandlerCallBack() */
2623 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2625 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2629 CmailSigHandlerCallBack(isr, closure, message, count, error)
2637 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2639 /**** end signal code ****/
2649 f = fopen(appData.icsLogon, "r");
2653 safeStrCpy(buf, p, sizeof(buf)/sizeof(buf[0]) );
2654 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2655 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2656 f = fopen(buf, "r");
2661 ProcessICSInitScript(f);
2668 EditCommentPopDown();
2683 if (!menuBarWidget) return;
2684 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2686 DisplayError("menuStep.Revert", 0);
2688 XtSetSensitive(w, !grey);
2690 w = XtNameToWidget(menuBarWidget, "menuStep.Annotate");
2692 DisplayError("menuStep.Annotate", 0);
2694 XtSetSensitive(w, !grey);
2699 SetMenuEnables(enab)
2703 if (!menuBarWidget) return;
2704 while (enab->name != NULL) {
2705 w = XtNameToWidget(menuBarWidget, enab->name);
2707 DisplayError(enab->name, 0);
2709 XtSetSensitive(w, enab->value);
2715 Enables icsEnables[] = {
2716 { "menuFile.Mail Move", False },
2717 { "menuFile.Reload CMail Message", False },
2718 { "menuMode.Machine Black", False },
2719 { "menuMode.Machine White", False },
2720 { "menuMode.Analysis Mode", False },
2721 { "menuMode.Analyze File", False },
2722 { "menuMode.Two Machines", False },
2724 { "menuHelp.Hint", False },
2725 { "menuHelp.Book", False },
2726 { "menuStep.Move Now", False },
2727 { "menuOptions.Periodic Updates", False },
2728 { "menuOptions.Hide Thinking", False },
2729 { "menuOptions.Ponder Next Move", False },
2731 { "menuStep.Annotate", False },
2735 Enables ncpEnables[] = {
2736 { "menuFile.Mail Move", False },
2737 { "menuFile.Reload CMail Message", False },
2738 { "menuMode.Machine White", False },
2739 { "menuMode.Machine Black", False },
2740 { "menuMode.Analysis Mode", False },
2741 { "menuMode.Analyze File", False },
2742 { "menuMode.Two Machines", False },
2743 { "menuMode.ICS Client", False },
2744 { "menuMode.ICS Input Box", False },
2745 { "Action", False },
2746 { "menuStep.Revert", False },
2747 { "menuStep.Annotate", False },
2748 { "menuStep.Move Now", False },
2749 { "menuStep.Retract Move", False },
2750 { "menuOptions.Auto Comment", False },
2751 { "menuOptions.Auto Flag", False },
2752 { "menuOptions.Auto Flip View", False },
2753 { "menuOptions.Auto Observe", False },
2754 { "menuOptions.Auto Raise Board", False },
2755 { "menuOptions.Get Move List", False },
2756 { "menuOptions.ICS Alarm", False },
2757 { "menuOptions.Move Sound", False },
2758 { "menuOptions.Quiet Play", False },
2759 { "menuOptions.Hide Thinking", False },
2760 { "menuOptions.Periodic Updates", False },
2761 { "menuOptions.Ponder Next Move", False },
2762 { "menuHelp.Hint", False },
2763 { "menuHelp.Book", False },
2767 Enables gnuEnables[] = {
2768 { "menuMode.ICS Client", False },
2769 { "menuMode.ICS Input Box", False },
2770 { "menuAction.Accept", False },
2771 { "menuAction.Decline", False },
2772 { "menuAction.Rematch", False },
2773 { "menuAction.Adjourn", False },
2774 { "menuAction.Stop Examining", False },
2775 { "menuAction.Stop Observing", False },
2776 { "menuAction.Upload to Examine", False },
2777 { "menuStep.Revert", False },
2778 { "menuStep.Annotate", False },
2779 { "menuOptions.Auto Comment", False },
2780 { "menuOptions.Auto Observe", False },
2781 { "menuOptions.Auto Raise Board", False },
2782 { "menuOptions.Get Move List", False },
2783 { "menuOptions.Premove", False },
2784 { "menuOptions.Quiet Play", False },
2786 /* The next two options rely on SetCmailMode being called *after* */
2787 /* SetGNUMode so that when GNU is being used to give hints these */
2788 /* menu options are still available */
2790 { "menuFile.Mail Move", False },
2791 { "menuFile.Reload CMail Message", False },
2795 Enables cmailEnables[] = {
2797 { "menuAction.Call Flag", False },
2798 { "menuAction.Draw", True },
2799 { "menuAction.Adjourn", False },
2800 { "menuAction.Abort", False },
2801 { "menuAction.Stop Observing", False },
2802 { "menuAction.Stop Examining", False },
2803 { "menuFile.Mail Move", True },
2804 { "menuFile.Reload CMail Message", True },
2808 Enables trainingOnEnables[] = {
2809 { "menuMode.Edit Comment", False },
2810 { "menuMode.Pause", False },
2811 { "menuStep.Forward", False },
2812 { "menuStep.Backward", False },
2813 { "menuStep.Forward to End", False },
2814 { "menuStep.Back to Start", False },
2815 { "menuStep.Move Now", False },
2816 { "menuStep.Truncate Game", False },
2820 Enables trainingOffEnables[] = {
2821 { "menuMode.Edit Comment", True },
2822 { "menuMode.Pause", True },
2823 { "menuStep.Forward", True },
2824 { "menuStep.Backward", True },
2825 { "menuStep.Forward to End", True },
2826 { "menuStep.Back to Start", True },
2827 { "menuStep.Move Now", True },
2828 { "menuStep.Truncate Game", True },
2832 Enables machineThinkingEnables[] = {
2833 { "menuFile.Load Game", False },
2834 { "menuFile.Load Next Game", False },
2835 { "menuFile.Load Previous Game", False },
2836 { "menuFile.Reload Same Game", False },
2837 { "menuFile.Paste Game", False },
2838 { "menuFile.Load Position", False },
2839 { "menuFile.Load Next Position", False },
2840 { "menuFile.Load Previous Position", False },
2841 { "menuFile.Reload Same Position", False },
2842 { "menuFile.Paste Position", False },
2843 { "menuMode.Machine White", False },
2844 { "menuMode.Machine Black", False },
2845 { "menuMode.Two Machines", False },
2846 { "menuStep.Retract Move", False },
2850 Enables userThinkingEnables[] = {
2851 { "menuFile.Load Game", True },
2852 { "menuFile.Load Next Game", True },
2853 { "menuFile.Load Previous Game", True },
2854 { "menuFile.Reload Same Game", True },
2855 { "menuFile.Paste Game", True },
2856 { "menuFile.Load Position", True },
2857 { "menuFile.Load Next Position", True },
2858 { "menuFile.Load Previous Position", True },
2859 { "menuFile.Reload Same Position", True },
2860 { "menuFile.Paste Position", True },
2861 { "menuMode.Machine White", True },
2862 { "menuMode.Machine Black", True },
2863 { "menuMode.Two Machines", True },
2864 { "menuStep.Retract Move", True },
2870 SetMenuEnables(icsEnables);
2873 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2874 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2881 SetMenuEnables(ncpEnables);
2887 SetMenuEnables(gnuEnables);
2893 SetMenuEnables(cmailEnables);
2899 SetMenuEnables(trainingOnEnables);
2900 if (appData.showButtonBar) {
2901 XtSetSensitive(buttonBarWidget, False);
2907 SetTrainingModeOff()
2909 SetMenuEnables(trainingOffEnables);
2910 if (appData.showButtonBar) {
2911 XtSetSensitive(buttonBarWidget, True);
2916 SetUserThinkingEnables()
2918 if (appData.noChessProgram) return;
2919 SetMenuEnables(userThinkingEnables);
2923 SetMachineThinkingEnables()
2925 if (appData.noChessProgram) return;
2926 SetMenuEnables(machineThinkingEnables);
2928 case MachinePlaysBlack:
2929 case MachinePlaysWhite:
2930 case TwoMachinesPlay:
2931 XtSetSensitive(XtNameToWidget(menuBarWidget,
2932 ModeToWidgetName(gameMode)), True);
2939 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2940 #define HISTORY_SIZE 64
\r
2941 static char *history[HISTORY_SIZE];
\r
2942 int histIn = 0, histP = 0;
\r
2945 SaveInHistory(char *cmd)
\r
2947 if (history[histIn] != NULL) {
\r
2948 free(history[histIn]);
\r
2949 history[histIn] = NULL;
\r
2951 if (*cmd == NULLCHAR) return;
\r
2952 history[histIn] = StrSave(cmd);
\r
2953 histIn = (histIn + 1) % HISTORY_SIZE;
\r
2954 if (history[histIn] != NULL) {
\r
2955 free(history[histIn]);
\r
2956 history[histIn] = NULL;
\r
2962 PrevInHistory(char *cmd)
\r
2965 if (histP == histIn) {
\r
2966 if (history[histIn] != NULL) free(history[histIn]);
\r
2967 history[histIn] = StrSave(cmd);
\r
2969 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
2970 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
2972 return history[histP];
\r
2978 if (histP == histIn) return NULL;
\r
2979 histP = (histP + 1) % HISTORY_SIZE;
\r
2980 return history[histP];
\r
2982 // end of borrowed code
\r
2984 #define Abs(n) ((n)<0 ? -(n) : (n))
2987 * Find a font that matches "pattern" that is as close as
2988 * possible to the targetPxlSize. Prefer fonts that are k
2989 * pixels smaller to fonts that are k pixels larger. The
2990 * pattern must be in the X Consortium standard format,
2991 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2992 * The return value should be freed with XtFree when no
2996 FindFont(pattern, targetPxlSize)
3000 char **fonts, *p, *best, *scalable, *scalableTail;
3001 int i, j, nfonts, minerr, err, pxlSize;
3004 char **missing_list;
3006 char *def_string, *base_fnt_lst, strInt[3];
3008 XFontStruct **fnt_list;
3010 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3011 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3012 p = strstr(pattern, "--");
3013 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3014 strcat(base_fnt_lst, strInt);
3015 strcat(base_fnt_lst, strchr(p + 2, '-'));
3017 if ((fntSet = XCreateFontSet(xDisplay,
3021 &def_string)) == NULL) {
3023 fprintf(stderr, _("Unable to create font set.\n"));
3027 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3029 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3031 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3032 programName, pattern);
3040 for (i=0; i<nfonts; i++) {
3043 if (*p != '-') continue;
3045 if (*p == NULLCHAR) break;
3046 if (*p++ == '-') j++;
3048 if (j < 7) continue;
3051 scalable = fonts[i];
3054 err = pxlSize - targetPxlSize;
3055 if (Abs(err) < Abs(minerr) ||
3056 (minerr > 0 && err < 0 && -err == minerr)) {
3062 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3063 /* If the error is too big and there is a scalable font,
3064 use the scalable font. */
3065 int headlen = scalableTail - scalable;
3066 p = (char *) XtMalloc(strlen(scalable) + 10);
3067 while (isdigit(*scalableTail)) scalableTail++;
3068 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3070 p = (char *) XtMalloc(strlen(best) + 2);
3071 safeStrCpy(p, best, strlen(best)+1 );
3073 if (appData.debugMode) {
3074 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3075 pattern, targetPxlSize, p);
3078 if (missing_count > 0)
3079 XFreeStringList(missing_list);
3080 XFreeFontSet(xDisplay, fntSet);
3082 XFreeFontNames(fonts);
3089 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3090 | GCBackground | GCFunction | GCPlaneMask;
3091 XGCValues gc_values;
3094 gc_values.plane_mask = AllPlanes;
3095 gc_values.line_width = lineGap;
3096 gc_values.line_style = LineSolid;
3097 gc_values.function = GXcopy;
3099 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3100 gc_values.background = XBlackPixel(xDisplay, xScreen);
3101 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3103 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3104 gc_values.background = XWhitePixel(xDisplay, xScreen);
3105 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3106 XSetFont(xDisplay, coordGC, coordFontID);
3108 // [HGM] make font for holdings counts (white on black0
3109 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3110 gc_values.background = XBlackPixel(xDisplay, xScreen);
3111 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3112 XSetFont(xDisplay, countGC, countFontID);
3114 if (appData.monoMode) {
3115 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3116 gc_values.background = XWhitePixel(xDisplay, xScreen);
3117 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3119 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3120 gc_values.background = XBlackPixel(xDisplay, xScreen);
3121 lightSquareGC = wbPieceGC
3122 = XtGetGC(shellWidget, value_mask, &gc_values);
3124 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3125 gc_values.background = XWhitePixel(xDisplay, xScreen);
3126 darkSquareGC = bwPieceGC
3127 = XtGetGC(shellWidget, value_mask, &gc_values);
3129 if (DefaultDepth(xDisplay, xScreen) == 1) {
3130 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3131 gc_values.function = GXcopyInverted;
3132 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3133 gc_values.function = GXcopy;
3134 if (XBlackPixel(xDisplay, xScreen) == 1) {
3135 bwPieceGC = darkSquareGC;
3136 wbPieceGC = copyInvertedGC;
3138 bwPieceGC = copyInvertedGC;
3139 wbPieceGC = lightSquareGC;
3143 gc_values.foreground = highlightSquareColor;
3144 gc_values.background = highlightSquareColor;
3145 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3147 gc_values.foreground = premoveHighlightColor;
3148 gc_values.background = premoveHighlightColor;
3149 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3151 gc_values.foreground = lightSquareColor;
3152 gc_values.background = darkSquareColor;
3153 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3155 gc_values.foreground = darkSquareColor;
3156 gc_values.background = lightSquareColor;
3157 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3159 gc_values.foreground = jailSquareColor;
3160 gc_values.background = jailSquareColor;
3161 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3163 gc_values.foreground = whitePieceColor;
3164 gc_values.background = darkSquareColor;
3165 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3167 gc_values.foreground = whitePieceColor;
3168 gc_values.background = lightSquareColor;
3169 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3171 gc_values.foreground = whitePieceColor;
3172 gc_values.background = jailSquareColor;
3173 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3175 gc_values.foreground = blackPieceColor;
3176 gc_values.background = darkSquareColor;
3177 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3179 gc_values.foreground = blackPieceColor;
3180 gc_values.background = lightSquareColor;
3181 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3183 gc_values.foreground = blackPieceColor;
3184 gc_values.background = jailSquareColor;
3185 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3189 void loadXIM(xim, xmask, filename, dest, mask)
3202 fp = fopen(filename, "rb");
3204 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3211 for (y=0; y<h; ++y) {
3212 for (x=0; x<h; ++x) {
3217 XPutPixel(xim, x, y, blackPieceColor);
3219 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3222 XPutPixel(xim, x, y, darkSquareColor);
3224 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3227 XPutPixel(xim, x, y, whitePieceColor);
3229 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3232 XPutPixel(xim, x, y, lightSquareColor);
3234 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3240 /* create Pixmap of piece */
3241 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3243 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3246 /* create Pixmap of clipmask
3247 Note: We assume the white/black pieces have the same
3248 outline, so we make only 6 masks. This is okay
3249 since the XPM clipmask routines do the same. */
3251 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3253 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3256 /* now create the 1-bit version */
3257 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3260 values.foreground = 1;
3261 values.background = 0;
3263 /* Don't use XtGetGC, not read only */
3264 maskGC = XCreateGC(xDisplay, *mask,
3265 GCForeground | GCBackground, &values);
3266 XCopyPlane(xDisplay, temp, *mask, maskGC,
3267 0, 0, squareSize, squareSize, 0, 0, 1);
3268 XFreePixmap(xDisplay, temp);
3273 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3275 void CreateXIMPieces()
3280 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3285 /* The XSynchronize calls were copied from CreatePieces.
3286 Not sure if needed, but can't hurt */
3287 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3290 /* temp needed by loadXIM() */
3291 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3292 0, 0, ss, ss, AllPlanes, XYPixmap);
3294 if (strlen(appData.pixmapDirectory) == 0) {
3298 if (appData.monoMode) {
3299 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3303 fprintf(stderr, _("\nLoading XIMs...\n"));
3305 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3306 fprintf(stderr, "%d", piece+1);
3307 for (kind=0; kind<4; kind++) {
3308 fprintf(stderr, ".");
3309 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3310 ExpandPathName(appData.pixmapDirectory),
3311 piece <= (int) WhiteKing ? "" : "w",
3312 pieceBitmapNames[piece],
3314 ximPieceBitmap[kind][piece] =
3315 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3316 0, 0, ss, ss, AllPlanes, XYPixmap);
3317 if (appData.debugMode)
3318 fprintf(stderr, _("(File:%s:) "), buf);
3319 loadXIM(ximPieceBitmap[kind][piece],
3321 &(xpmPieceBitmap2[kind][piece]),
3322 &(ximMaskPm2[piece]));
3323 if(piece <= (int)WhiteKing)
3324 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3326 fprintf(stderr," ");
3328 /* Load light and dark squares */
3329 /* If the LSQ and DSQ pieces don't exist, we will
3330 draw them with solid squares. */
3331 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3332 if (access(buf, 0) != 0) {
3336 fprintf(stderr, _("light square "));
3338 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3339 0, 0, ss, ss, AllPlanes, XYPixmap);
3340 if (appData.debugMode)
3341 fprintf(stderr, _("(File:%s:) "), buf);
3343 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3344 fprintf(stderr, _("dark square "));
3345 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3346 ExpandPathName(appData.pixmapDirectory), ss);
3347 if (appData.debugMode)
3348 fprintf(stderr, _("(File:%s:) "), buf);
3350 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3351 0, 0, ss, ss, AllPlanes, XYPixmap);
3352 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3353 xpmJailSquare = xpmLightSquare;
3355 fprintf(stderr, _("Done.\n"));
3357 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3361 void CreateXPMPieces()
3365 u_int ss = squareSize;
3367 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3368 XpmColorSymbol symbols[4];
3370 /* The XSynchronize calls were copied from CreatePieces.
3371 Not sure if needed, but can't hurt */
3372 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3374 /* Setup translations so piece colors match square colors */
3375 symbols[0].name = "light_piece";
3376 symbols[0].value = appData.whitePieceColor;
3377 symbols[1].name = "dark_piece";
3378 symbols[1].value = appData.blackPieceColor;
3379 symbols[2].name = "light_square";
3380 symbols[2].value = appData.lightSquareColor;
3381 symbols[3].name = "dark_square";
3382 symbols[3].value = appData.darkSquareColor;
3384 attr.valuemask = XpmColorSymbols;
3385 attr.colorsymbols = symbols;
3386 attr.numsymbols = 4;
3388 if (appData.monoMode) {
3389 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3393 if (strlen(appData.pixmapDirectory) == 0) {
3394 XpmPieces* pieces = builtInXpms;
3397 while (pieces->size != squareSize && pieces->size) pieces++;
3398 if (!pieces->size) {
3399 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3402 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3403 for (kind=0; kind<4; kind++) {
3405 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3406 pieces->xpm[piece][kind],
3407 &(xpmPieceBitmap2[kind][piece]),
3408 NULL, &attr)) != 0) {
3409 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3413 if(piece <= (int) WhiteKing)
3414 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3418 xpmJailSquare = xpmLightSquare;
3422 fprintf(stderr, _("\nLoading XPMs...\n"));
3425 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3426 fprintf(stderr, "%d ", piece+1);
3427 for (kind=0; kind<4; kind++) {
3428 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3429 ExpandPathName(appData.pixmapDirectory),
3430 piece > (int) WhiteKing ? "w" : "",
3431 pieceBitmapNames[piece],
3433 if (appData.debugMode) {
3434 fprintf(stderr, _("(File:%s:) "), buf);
3436 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3437 &(xpmPieceBitmap2[kind][piece]),
3438 NULL, &attr)) != 0) {
3439 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3440 // [HGM] missing: read of unorthodox piece failed; substitute King.
3441 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3442 ExpandPathName(appData.pixmapDirectory),
3444 if (appData.debugMode) {
3445 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3447 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3448 &(xpmPieceBitmap2[kind][piece]),
3452 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3457 if(piece <= (int) WhiteKing)
3458 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3461 /* Load light and dark squares */
3462 /* If the LSQ and DSQ pieces don't exist, we will
3463 draw them with solid squares. */
3464 fprintf(stderr, _("light square "));
3465 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3466 if (access(buf, 0) != 0) {
3470 if (appData.debugMode)
3471 fprintf(stderr, _("(File:%s:) "), buf);
3473 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3474 &xpmLightSquare, NULL, &attr)) != 0) {
3475 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3478 fprintf(stderr, _("dark square "));
3479 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3480 ExpandPathName(appData.pixmapDirectory), ss);
3481 if (appData.debugMode) {
3482 fprintf(stderr, _("(File:%s:) "), buf);
3484 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3485 &xpmDarkSquare, NULL, &attr)) != 0) {
3486 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3490 xpmJailSquare = xpmLightSquare;
3491 fprintf(stderr, _("Done.\n"));
3493 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3496 #endif /* HAVE_LIBXPM */
3499 /* No built-in bitmaps */
3504 u_int ss = squareSize;
3506 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3509 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3510 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3511 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3512 pieceBitmapNames[piece],
3513 ss, kind == SOLID ? 's' : 'o');
3514 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3515 if(piece <= (int)WhiteKing)
3516 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3520 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3524 /* With built-in bitmaps */
3527 BuiltInBits* bib = builtInBits;
3530 u_int ss = squareSize;
3532 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3535 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3537 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3538 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3539 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3540 pieceBitmapNames[piece],
3541 ss, kind == SOLID ? 's' : 'o');
3542 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3543 bib->bits[kind][piece], ss, ss);
3544 if(piece <= (int)WhiteKing)
3545 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3549 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3554 void ReadBitmap(pm, name, bits, wreq, hreq)
3557 unsigned char bits[];
3563 char msg[MSG_SIZ], fullname[MSG_SIZ];
3565 if (*appData.bitmapDirectory != NULLCHAR) {
3566 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3567 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3568 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3569 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3570 &w, &h, pm, &x_hot, &y_hot);
3571 fprintf(stderr, "load %s\n", name);
3572 if (errcode != BitmapSuccess) {
3574 case BitmapOpenFailed:
3575 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3577 case BitmapFileInvalid:
3578 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3580 case BitmapNoMemory:
3581 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3585 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3589 fprintf(stderr, _("%s: %s...using built-in\n"),
3591 } else if (w != wreq || h != hreq) {
3593 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3594 programName, fullname, w, h, wreq, hreq);
3600 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3609 if (lineGap == 0) return;
3611 /* [HR] Split this into 2 loops for non-square boards. */
3613 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3614 gridSegments[i].x1 = 0;
3615 gridSegments[i].x2 =
3616 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3617 gridSegments[i].y1 = gridSegments[i].y2
3618 = lineGap / 2 + (i * (squareSize + lineGap));
3621 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3622 gridSegments[j + i].y1 = 0;
3623 gridSegments[j + i].y2 =
3624 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3625 gridSegments[j + i].x1 = gridSegments[j + i].x2
3626 = lineGap / 2 + (j * (squareSize + lineGap));
3630 static void MenuBarSelect(w, addr, index)
3635 XtActionProc proc = (XtActionProc) addr;
3637 (proc)(NULL, NULL, NULL, NULL);
3640 void CreateMenuBarPopup(parent, name, mb)
3650 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3653 XtSetArg(args[j], XtNleftMargin, 20); j++;
3654 XtSetArg(args[j], XtNrightMargin, 20); j++;
3656 while (mi->string != NULL) {
3657 if (strcmp(mi->string, "----") == 0) {
3658 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3661 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3662 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3664 XtAddCallback(entry, XtNcallback,
3665 (XtCallbackProc) MenuBarSelect,
3666 (caddr_t) mi->proc);
3672 Widget CreateMenuBar(mb)
3676 Widget anchor, menuBar;
3678 char menuName[MSG_SIZ];
3681 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3682 XtSetArg(args[j], XtNvSpace, 0); j++;
3683 XtSetArg(args[j], XtNborderWidth, 0); j++;
3684 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3685 formWidget, args, j);
3687 while (mb->name != NULL) {
3688 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3689 strncat(menuName, mb->name, MSG_SIZ - strlen(menuName) - 1);
3691 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3694 shortName[0] = _(mb->name)[0];
3695 shortName[1] = NULLCHAR;
3696 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3699 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3702 XtSetArg(args[j], XtNborderWidth, 0); j++;
3703 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3705 CreateMenuBarPopup(menuBar, menuName, mb);
3711 Widget CreateButtonBar(mi)
3715 Widget button, buttonBar;
3719 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3721 XtSetArg(args[j], XtNhSpace, 0); j++;
3723 XtSetArg(args[j], XtNborderWidth, 0); j++;
3724 XtSetArg(args[j], XtNvSpace, 0); j++;
3725 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3726 formWidget, args, j);
3728 while (mi->string != NULL) {
3731 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3732 XtSetArg(args[j], XtNborderWidth, 0); j++;
3734 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3735 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3736 buttonBar, args, j);
3737 XtAddCallback(button, XtNcallback,
3738 (XtCallbackProc) MenuBarSelect,
3739 (caddr_t) mi->proc);
3746 CreatePieceMenu(name, color)
3753 ChessSquare selection;
3755 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3756 boardWidget, args, 0);
3758 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3759 String item = pieceMenuStrings[color][i];
3761 if (strcmp(item, "----") == 0) {
3762 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3765 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3766 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3768 selection = pieceMenuTranslation[color][i];
3769 XtAddCallback(entry, XtNcallback,
3770 (XtCallbackProc) PieceMenuSelect,
3771 (caddr_t) selection);
3772 if (selection == WhitePawn || selection == BlackPawn) {
3773 XtSetArg(args[0], XtNpopupOnEntry, entry);
3774 XtSetValues(menu, args, 1);
3787 ChessSquare selection;
3789 whitePieceMenu = CreatePieceMenu("menuW", 0);
3790 blackPieceMenu = CreatePieceMenu("menuB", 1);
3792 XtRegisterGrabAction(PieceMenuPopup, True,
3793 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3794 GrabModeAsync, GrabModeAsync);
3796 XtSetArg(args[0], XtNlabel, _("Drop"));
3797 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3798 boardWidget, args, 1);
3799 for (i = 0; i < DROP_MENU_SIZE; i++) {
3800 String item = dropMenuStrings[i];
3802 if (strcmp(item, "----") == 0) {
3803 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3806 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3807 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3809 selection = dropMenuTranslation[i];
3810 XtAddCallback(entry, XtNcallback,
3811 (XtCallbackProc) DropMenuSelect,
3812 (caddr_t) selection);
3817 void SetupDropMenu()
3825 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3826 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3827 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3828 dmEnables[i].piece);
3829 XtSetSensitive(entry, p != NULL || !appData.testLegality
3830 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3831 && !appData.icsActive));
3833 while (p && *p++ == dmEnables[i].piece) count++;
3834 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3836 XtSetArg(args[j], XtNlabel, label); j++;
3837 XtSetValues(entry, args, j);
3841 void PieceMenuPopup(w, event, params, num_params)
3845 Cardinal *num_params;
3847 String whichMenu; int menuNr;
3848 if (event->type == ButtonRelease)
3849 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3850 else if (event->type == ButtonPress)
3851 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3853 case 0: whichMenu = params[0]; break;
3854 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3856 case -1: if (errorUp) ErrorPopDown();
3859 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3862 static void PieceMenuSelect(w, piece, junk)
3867 if (pmFromX < 0 || pmFromY < 0) return;
3868 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3871 static void DropMenuSelect(w, piece, junk)
3876 if (pmFromX < 0 || pmFromY < 0) return;
3877 DropMenuEvent(piece, pmFromX, pmFromY);
3880 void WhiteClock(w, event, prms, nprms)
3886 if (gameMode == EditPosition || gameMode == IcsExamining) {
3887 SetWhiteToPlayEvent();
3888 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3893 void BlackClock(w, event, prms, nprms)
3899 if (gameMode == EditPosition || gameMode == IcsExamining) {
3900 SetBlackToPlayEvent();
3901 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3908 * If the user selects on a border boundary, return -1; if off the board,
3909 * return -2. Otherwise map the event coordinate to the square.
3911 int EventToSquare(x, limit)
3919 if ((x % (squareSize + lineGap)) >= squareSize)
3921 x /= (squareSize + lineGap);
3927 static void do_flash_delay(msec)
3933 static void drawHighlight(file, rank, gc)
3939 if (lineGap == 0 || appData.blindfold) return;
3942 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3943 (squareSize + lineGap);
3944 y = lineGap/2 + rank * (squareSize + lineGap);
3946 x = lineGap/2 + file * (squareSize + lineGap);
3947 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3948 (squareSize + lineGap);
3951 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3952 squareSize+lineGap, squareSize+lineGap);
3955 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3956 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3959 SetHighlights(fromX, fromY, toX, toY)
3960 int fromX, fromY, toX, toY;
3962 if (hi1X != fromX || hi1Y != fromY) {
3963 if (hi1X >= 0 && hi1Y >= 0) {
3964 drawHighlight(hi1X, hi1Y, lineGC);
3966 } // [HGM] first erase both, then draw new!
3967 if (hi2X != toX || hi2Y != toY) {
3968 if (hi2X >= 0 && hi2Y >= 0) {
3969 drawHighlight(hi2X, hi2Y, lineGC);
3972 if (hi1X != fromX || hi1Y != fromY) {
3973 if (fromX >= 0 && fromY >= 0) {
3974 drawHighlight(fromX, fromY, highlineGC);
3977 if (hi2X != toX || hi2Y != toY) {
3978 if (toX >= 0 && toY >= 0) {
3979 drawHighlight(toX, toY, highlineGC);
3991 SetHighlights(-1, -1, -1, -1);
3996 SetPremoveHighlights(fromX, fromY, toX, toY)
3997 int fromX, fromY, toX, toY;
3999 if (pm1X != fromX || pm1Y != fromY) {
4000 if (pm1X >= 0 && pm1Y >= 0) {
4001 drawHighlight(pm1X, pm1Y, lineGC);
4003 if (fromX >= 0 && fromY >= 0) {
4004 drawHighlight(fromX, fromY, prelineGC);
4007 if (pm2X != toX || pm2Y != toY) {
4008 if (pm2X >= 0 && pm2Y >= 0) {
4009 drawHighlight(pm2X, pm2Y, lineGC);
4011 if (toX >= 0 && toY >= 0) {
4012 drawHighlight(toX, toY, prelineGC);
4022 ClearPremoveHighlights()
4024 SetPremoveHighlights(-1, -1, -1, -1);
4027 static void BlankSquare(x, y, color, piece, dest)
4032 if (useImages && useImageSqs) {
4036 pm = xpmLightSquare;
4041 case 2: /* neutral */
4046 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4047 squareSize, squareSize, x, y);
4057 case 2: /* neutral */
4062 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4067 I split out the routines to draw a piece so that I could
4068 make a generic flash routine.
4070 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4072 int square_color, x, y;
4075 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4076 switch (square_color) {
4078 case 2: /* neutral */
4080 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4081 ? *pieceToOutline(piece)
4082 : *pieceToSolid(piece),
4083 dest, bwPieceGC, 0, 0,
4084 squareSize, squareSize, x, y);
4087 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4088 ? *pieceToSolid(piece)
4089 : *pieceToOutline(piece),
4090 dest, wbPieceGC, 0, 0,
4091 squareSize, squareSize, x, y);
4096 static void monoDrawPiece(piece, square_color, x, y, dest)
4098 int square_color, x, y;
4101 switch (square_color) {
4103 case 2: /* neutral */
4105 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4106 ? *pieceToOutline(piece)
4107 : *pieceToSolid(piece),
4108 dest, bwPieceGC, 0, 0,
4109 squareSize, squareSize, x, y, 1);
4112 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4113 ? *pieceToSolid(piece)
4114 : *pieceToOutline(piece),
4115 dest, wbPieceGC, 0, 0,
4116 squareSize, squareSize, x, y, 1);
4121 static void colorDrawPiece(piece, square_color, x, y, dest)
4123 int square_color, x, y;
4126 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4127 switch (square_color) {
4129 XCopyPlane(xDisplay, *pieceToSolid(piece),
4130 dest, (int) piece < (int) BlackPawn
4131 ? wlPieceGC : blPieceGC, 0, 0,
4132 squareSize, squareSize, x, y, 1);
4135 XCopyPlane(xDisplay, *pieceToSolid(piece),
4136 dest, (int) piece < (int) BlackPawn
4137 ? wdPieceGC : bdPieceGC, 0, 0,
4138 squareSize, squareSize, x, y, 1);
4140 case 2: /* neutral */
4142 XCopyPlane(xDisplay, *pieceToSolid(piece),
4143 dest, (int) piece < (int) BlackPawn
4144 ? wjPieceGC : bjPieceGC, 0, 0,
4145 squareSize, squareSize, x, y, 1);
4150 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4152 int square_color, x, y;
4157 switch (square_color) {
4159 case 2: /* neutral */
4161 if ((int)piece < (int) BlackPawn) {
4169 if ((int)piece < (int) BlackPawn) {
4177 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4178 dest, wlPieceGC, 0, 0,
4179 squareSize, squareSize, x, y);
4182 typedef void (*DrawFunc)();
4184 DrawFunc ChooseDrawFunc()
4186 if (appData.monoMode) {
4187 if (DefaultDepth(xDisplay, xScreen) == 1) {
4188 return monoDrawPiece_1bit;
4190 return monoDrawPiece;
4194 return colorDrawPieceImage;
4196 return colorDrawPiece;
4200 /* [HR] determine square color depending on chess variant. */
4201 static int SquareColor(row, column)
4206 if (gameInfo.variant == VariantXiangqi) {
4207 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4209 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4211 } else if (row <= 4) {
4217 square_color = ((column + row) % 2) == 1;
4220 /* [hgm] holdings: next line makes all holdings squares light */
4221 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4223 return square_color;
4226 void DrawSquare(row, column, piece, do_flash)
4227 int row, column, do_flash;
4230 int square_color, x, y, direction, font_ascent, font_descent;
4233 XCharStruct overall;
4237 /* Calculate delay in milliseconds (2-delays per complete flash) */
4238 flash_delay = 500 / appData.flashRate;
4241 x = lineGap + ((BOARD_WIDTH-1)-column) *
4242 (squareSize + lineGap);
4243 y = lineGap + row * (squareSize + lineGap);
4245 x = lineGap + column * (squareSize + lineGap);
4246 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4247 (squareSize + lineGap);
4250 if(twoBoards && partnerUp) x += hOffset; // [HGM] dual: draw second board
4252 square_color = SquareColor(row, column);
4254 if ( // [HGM] holdings: blank out area between board and holdings
4255 column == BOARD_LEFT-1 || column == BOARD_RGHT
4256 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4257 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4258 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4260 // [HGM] print piece counts next to holdings
4261 string[1] = NULLCHAR;
4262 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4263 string[0] = '0' + piece;
4264 XTextExtents(countFontStruct, string, 1, &direction,
4265 &font_ascent, &font_descent, &overall);
4266 if (appData.monoMode) {
4267 XDrawImageString(xDisplay, xBoardWindow, countGC,
4268 x + squareSize - overall.width - 2,