2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
65 # if HAVE_SYS_SOCKET_H
66 # include <sys/socket.h>
67 # include <netinet/in.h>
69 # else /* not HAVE_SYS_SOCKET_H */
70 # if HAVE_LAN_SOCKET_H
71 # include <lan/socket.h>
73 # include <lan/netdb.h>
74 # else /* not HAVE_LAN_SOCKET_H */
75 # define OMIT_SOCKETS 1
76 # endif /* not HAVE_LAN_SOCKET_H */
77 # endif /* not HAVE_SYS_SOCKET_H */
78 #endif /* !OMIT_SOCKETS */
83 #else /* not STDC_HEADERS */
84 extern char *getenv();
87 # else /* not HAVE_STRING_H */
89 # endif /* not HAVE_STRING_H */
90 #endif /* not STDC_HEADERS */
93 # include <sys/fcntl.h>
94 #else /* not HAVE_SYS_FCNTL_H */
97 # endif /* HAVE_FCNTL_H */
98 #endif /* not HAVE_SYS_FCNTL_H */
100 #if HAVE_SYS_SYSTEMINFO_H
101 # include <sys/systeminfo.h>
102 #endif /* HAVE_SYS_SYSTEMINFO_H */
104 #if TIME_WITH_SYS_TIME
105 # include <sys/time.h>
109 # include <sys/time.h>
120 # include <sys/wait.h>
125 # define NAMLEN(dirent) strlen((dirent)->d_name)
126 # define HAVE_DIR_STRUCT
128 # define dirent direct
129 # define NAMLEN(dirent) (dirent)->d_namlen
131 # include <sys/ndir.h>
132 # define HAVE_DIR_STRUCT
135 # include <sys/dir.h>
136 # define HAVE_DIR_STRUCT
140 # define HAVE_DIR_STRUCT
144 #include <X11/Intrinsic.h>
145 #include <X11/StringDefs.h>
146 #include <X11/Shell.h>
147 #include <X11/cursorfont.h>
148 #include <X11/Xatom.h>
149 #include <X11/Xmu/Atoms.h>
151 #include <X11/Xaw3d/Dialog.h>
152 #include <X11/Xaw3d/Form.h>
153 #include <X11/Xaw3d/List.h>
154 #include <X11/Xaw3d/Label.h>
155 #include <X11/Xaw3d/SimpleMenu.h>
156 #include <X11/Xaw3d/SmeBSB.h>
157 #include <X11/Xaw3d/SmeLine.h>
158 #include <X11/Xaw3d/Box.h>
159 #include <X11/Xaw3d/MenuButton.h>
160 #include <X11/Xaw3d/Text.h>
161 #include <X11/Xaw3d/AsciiText.h>
163 #include <X11/Xaw/Dialog.h>
164 #include <X11/Xaw/Form.h>
165 #include <X11/Xaw/List.h>
166 #include <X11/Xaw/Label.h>
167 #include <X11/Xaw/SimpleMenu.h>
168 #include <X11/Xaw/SmeBSB.h>
169 #include <X11/Xaw/SmeLine.h>
170 #include <X11/Xaw/Box.h>
171 #include <X11/Xaw/MenuButton.h>
172 #include <X11/Xaw/Text.h>
173 #include <X11/Xaw/AsciiText.h>
176 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
181 #include "pixmaps/pixmaps.h"
182 #define IMAGE_EXT "xpm"
184 #define IMAGE_EXT "xim"
185 #include "bitmaps/bitmaps.h"
188 #include "bitmaps/icon_white.bm"
189 #include "bitmaps/icon_black.bm"
190 #include "bitmaps/checkmark.bm"
192 #include "frontend.h"
197 #include "xgamelist.h"
198 #include "xhistory.h"
199 #include "xedittags.h"
202 // must be moved to xengineoutput.h
204 void EngineOutputProc P((Widget w, XEvent *event,
205 String *prms, Cardinal *nprms));
206 void EvalGraphProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
214 #define usleep(t) _sleep2(((t)+500)/1000)
218 # define _(s) gettext (s)
219 # define N_(s) gettext_noop (s)
235 int main P((int argc, char **argv));
236 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
237 char *init_path, char *mode, int (*show_entry)(), char **name_return));
238 RETSIGTYPE CmailSigHandler P((int sig));
239 RETSIGTYPE IntSigHandler P((int sig));
240 RETSIGTYPE TermSizeSigHandler P((int sig));
241 void CreateGCs P((void));
242 void CreateXIMPieces P((void));
243 void CreateXPMPieces P((void));
244 void CreatePieces P((void));
245 void CreatePieceMenus P((void));
246 Widget CreateMenuBar P((Menu *mb));
247 Widget CreateButtonBar P ((MenuItem *mi));
248 char *FindFont P((char *pattern, int targetPxlSize));
249 void PieceMenuPopup P((Widget w, XEvent *event,
250 String *params, Cardinal *num_params));
251 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
252 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
253 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
254 u_int wreq, u_int hreq));
255 void CreateGrid P((void));
256 int EventToSquare P((int x, int limit));
257 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
258 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
259 void HandleUserMove P((Widget w, XEvent *event,
260 String *prms, Cardinal *nprms));
261 void AnimateUserMove P((Widget w, XEvent * event,
262 String * params, Cardinal * nParams));
263 void HandlePV P((Widget w, XEvent * event,
264 String * params, Cardinal * nParams));
265 void SelectPV P((Widget w, XEvent * event,
266 String * params, Cardinal * nParams));
267 void StopPV P((Widget w, XEvent * event,
268 String * params, Cardinal * nParams));
269 void WhiteClock P((Widget w, XEvent *event,
270 String *prms, Cardinal *nprms));
271 void BlackClock P((Widget w, XEvent *event,
272 String *prms, Cardinal *nprms));
273 void DrawPositionProc P((Widget w, XEvent *event,
274 String *prms, Cardinal *nprms));
275 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
277 void CommentClick P((Widget w, XEvent * event,
278 String * params, Cardinal * nParams));
279 void CommentPopUp P((char *title, char *label));
280 void CommentPopDown P((void));
281 void CommentCallback P((Widget w, XtPointer client_data,
282 XtPointer call_data));
283 void ICSInputBoxPopUp P((void));
284 void ICSInputBoxPopDown P((void));
285 void FileNamePopUp P((char *label, char *def,
286 FileProc proc, char *openMode));
287 void FileNamePopDown P((void));
288 void FileNameCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void FileNameAction P((Widget w, XEvent *event,
291 String *prms, Cardinal *nprms));
292 void AskQuestionReplyAction P((Widget w, XEvent *event,
293 String *prms, Cardinal *nprms));
294 void AskQuestionProc P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void AskQuestionPopDown P((void));
297 void PromotionPopDown P((void));
298 void PromotionCallback P((Widget w, XtPointer client_data,
299 XtPointer call_data));
300 void EditCommentPopDown P((void));
301 void EditCommentCallback P((Widget w, XtPointer client_data,
302 XtPointer call_data));
303 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
304 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
308 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
310 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
312 void LoadPositionProc P((Widget w, XEvent *event,
313 String *prms, Cardinal *nprms));
314 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
316 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
318 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
320 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
322 void PastePositionProc P((Widget w, XEvent *event, String *prms,
324 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void SavePositionProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
332 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
336 void MachineWhiteProc P((Widget w, XEvent *event,
337 String *prms, Cardinal *nprms));
338 void AnalyzeModeProc P((Widget w, XEvent *event,
339 String *prms, Cardinal *nprms));
340 void AnalyzeFileProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
344 void IcsClientProc P((Widget w, XEvent *event, String *prms,
346 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void EditPositionProc P((Widget w, XEvent *event,
348 String *prms, Cardinal *nprms));
349 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void EditCommentProc P((Widget w, XEvent *event,
351 String *prms, Cardinal *nprms));
352 void IcsInputBoxProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void StopObservingProc P((Widget w, XEvent *event, String *prms,
370 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
372 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
381 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
383 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
386 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
388 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
390 void AutocommProc P((Widget w, XEvent *event, String *prms,
392 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void AutobsProc P((Widget w, XEvent *event, String *prms,
396 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
401 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
404 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
406 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
408 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
412 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
414 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
416 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
418 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
420 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
424 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
426 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
428 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
430 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void DisplayMove P((int moveNumber));
442 void DisplayTitle P((char *title));
443 void ICSInitScript P((void));
444 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
445 void ErrorPopUp P((char *title, char *text, int modal));
446 void ErrorPopDown P((void));
447 static char *ExpandPathName P((char *path));
448 static void CreateAnimVars P((void));
449 static void DragPieceMove P((int x, int y));
450 static void DrawDragPiece P((void));
451 char *ModeToWidgetName P((GameMode mode));
452 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void GameListOptionsPopDown P(());
461 void ShufflePopDown P(());
462 void EnginePopDown P(());
463 void UciPopDown P(());
464 void TimeControlPopDown P(());
465 void NewVariantPopDown P(());
466 void SettingsPopDown P(());
467 void update_ics_width P(());
468 int get_term_width P(());
469 int CopyMemoProc P(());
471 * XBoard depends on Xt R4 or higher
473 int xtVersion = XtSpecificationRelease;
478 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
479 jailSquareColor, highlightSquareColor, premoveHighlightColor;
480 Pixel lowTimeWarningColor;
481 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
482 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
483 wjPieceGC, bjPieceGC, prelineGC, countGC;
484 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
485 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
486 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
487 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
488 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
489 ICSInputShell, fileNameShell, askQuestionShell;
490 Widget historyShell, evalGraphShell, gameListShell;
491 int hOffset; // [HGM] dual
492 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
493 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
494 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
495 Font clockFontID, coordFontID, countFontID;
496 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
497 XtAppContext appContext;
499 char *oldICSInteractionTitle;
503 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
505 Position commentX = -1, commentY = -1;
506 Dimension commentW, commentH;
507 typedef unsigned int BoardSize;
509 Boolean chessProgram;
511 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
512 int squareSize, smallLayout = 0, tinyLayout = 0,
513 marginW, marginH, // [HGM] for run-time resizing
514 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
515 ICSInputBoxUp = False, askQuestionUp = False,
516 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
517 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
518 Pixel timerForegroundPixel, timerBackgroundPixel;
519 Pixel buttonForegroundPixel, buttonBackgroundPixel;
520 char *chessDir, *programName, *programVersion,
521 *gameCopyFilename, *gamePasteFilename;
522 Boolean alwaysOnTop = False;
523 Boolean saveSettingsOnExit;
524 char *settingsFileName;
525 char *icsTextMenuString;
527 char *firstChessProgramNames;
528 char *secondChessProgramNames;
530 WindowPlacement wpMain;
531 WindowPlacement wpConsole;
532 WindowPlacement wpComment;
533 WindowPlacement wpMoveHistory;
534 WindowPlacement wpEvalGraph;
535 WindowPlacement wpEngineOutput;
536 WindowPlacement wpGameList;
537 WindowPlacement wpTags;
541 Pixmap pieceBitmap[2][(int)BlackPawn];
542 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
543 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
544 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
545 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
546 int useImages, useImageSqs;
547 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
548 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
549 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
550 XImage *ximLightSquare, *ximDarkSquare;
553 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
554 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
556 #define White(piece) ((int)(piece) < (int)BlackPawn)
558 /* Variables for doing smooth animation. This whole thing
559 would be much easier if the board was double-buffered,
560 but that would require a fairly major rewrite. */
565 GC blitGC, pieceGC, outlineGC;
566 XPoint startSquare, prevFrame, mouseDelta;
570 int startBoardX, startBoardY;
573 /* There can be two pieces being animated at once: a player
574 can begin dragging a piece before the remote opponent has moved. */
576 static AnimState game, player;
578 /* Bitmaps for use as masks when drawing XPM pieces.
579 Need one for each black and white piece. */
580 static Pixmap xpmMask[BlackKing + 1];
582 /* This magic number is the number of intermediate frames used
583 in each half of the animation. For short moves it's reduced
584 by 1. The total number of frames will be factor * 2 + 1. */
587 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
589 MenuItem fileMenu[] = {
590 {N_("New Game"), ResetProc},
591 {N_("New Shuffle Game ..."), ShuffleMenuProc},
592 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
593 {"----", NothingProc},
594 {N_("Load Game"), LoadGameProc},
595 {N_("Load Next Game"), LoadNextGameProc},
596 {N_("Load Previous Game"), LoadPrevGameProc},
597 {N_("Reload Same Game"), ReloadGameProc},
598 {N_("Save Game"), SaveGameProc},
599 {"----", NothingProc},
600 {N_("Copy Game"), CopyGameProc},
601 {N_("Paste Game"), PasteGameProc},
602 {"----", NothingProc},
603 {N_("Load Position"), LoadPositionProc},
604 {N_("Load Next Position"), LoadNextPositionProc},
605 {N_("Load Previous Position"), LoadPrevPositionProc},
606 {N_("Reload Same Position"), ReloadPositionProc},
607 {N_("Save Position"), SavePositionProc},
608 {"----", NothingProc},
609 {N_("Copy Position"), CopyPositionProc},
610 {N_("Paste Position"), PastePositionProc},
611 {"----", NothingProc},
612 {N_("Mail Move"), MailMoveProc},
613 {N_("Reload CMail Message"), ReloadCmailMsgProc},
614 {"----", NothingProc},
615 {N_("Exit"), QuitProc},
619 MenuItem modeMenu[] = {
620 {N_("Machine White"), MachineWhiteProc},
621 {N_("Machine Black"), MachineBlackProc},
622 {N_("Two Machines"), TwoMachinesProc},
623 {N_("Analysis Mode"), AnalyzeModeProc},
624 {N_("Analyze File"), AnalyzeFileProc },
625 {N_("ICS Client"), IcsClientProc},
626 {N_("Edit Game"), EditGameProc},
627 {N_("Edit Position"), EditPositionProc},
628 {N_("Training"), TrainingProc},
629 {"----", NothingProc},
630 {N_("Show Engine Output"), EngineOutputProc},
631 {N_("Show Evaluation Graph"), EvalGraphProc},
632 {N_("Show Game List"), ShowGameListProc},
633 {N_("Show Move History"), HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
634 {"----", NothingProc},
635 {N_("Edit Tags"), EditTagsProc},
636 {N_("Edit Comment"), EditCommentProc},
637 {N_("ICS Input Box"), IcsInputBoxProc},
638 {N_("Pause"), PauseProc},
642 MenuItem actionMenu[] = {
643 {N_("Accept"), AcceptProc},
644 {N_("Decline"), DeclineProc},
645 {N_("Rematch"), RematchProc},
646 {"----", NothingProc},
647 {N_("Call Flag"), CallFlagProc},
648 {N_("Draw"), DrawProc},
649 {N_("Adjourn"), AdjournProc},
650 {N_("Abort"), AbortProc},
651 {N_("Resign"), ResignProc},
652 {"----", NothingProc},
653 {N_("Stop Observing"), StopObservingProc},
654 {N_("Stop Examining"), StopExaminingProc},
655 {N_("Upload to Examine"), UploadProc},
656 {"----", NothingProc},
657 {N_("Adjudicate to White"), AdjuWhiteProc},
658 {N_("Adjudicate to Black"), AdjuBlackProc},
659 {N_("Adjudicate Draw"), AdjuDrawProc},
663 MenuItem stepMenu[] = {
664 {N_("Backward"), BackwardProc},
665 {N_("Forward"), ForwardProc},
666 {N_("Back to Start"), ToStartProc},
667 {N_("Forward to End"), ToEndProc},
668 {N_("Revert"), RevertProc},
669 {N_("Annotate"), AnnotateProc},
670 {N_("Truncate Game"), TruncateGameProc},
671 {"----", NothingProc},
672 {N_("Move Now"), MoveNowProc},
673 {N_("Retract Move"), RetractMoveProc},
677 MenuItem optionsMenu[] = {
678 {N_("Flip View"), FlipViewProc},
679 {"----", NothingProc},
680 {N_("Adjudications ..."), EngineMenuProc},
681 {N_("General Settings ..."), UciMenuProc},
682 {N_("Engine #1 Settings ..."), FirstSettingsProc},
683 {N_("Engine #2 Settings ..."), SecondSettingsProc},
684 {N_("Time Control ..."), TimeControlProc},
685 {N_("Game List ..."), GameListOptionsPopUp},
686 {"----", NothingProc},
687 {N_("Always Queen"), AlwaysQueenProc},
688 {N_("Animate Dragging"), AnimateDraggingProc},
689 {N_("Animate Moving"), AnimateMovingProc},
690 {N_("Auto Comment"), AutocommProc},
691 {N_("Auto Flag"), AutoflagProc},
692 {N_("Auto Flip View"), AutoflipProc},
693 {N_("Auto Observe"), AutobsProc},
694 {N_("Auto Raise Board"), AutoraiseProc},
695 {N_("Auto Save"), AutosaveProc},
696 {N_("Blindfold"), BlindfoldProc},
697 {N_("Flash Moves"), FlashMovesProc},
698 {N_("Get Move List"), GetMoveListProc},
700 {N_("Highlight Dragging"), HighlightDraggingProc},
702 {N_("Highlight Last Move"), HighlightLastMoveProc},
703 {N_("Move Sound"), MoveSoundProc},
704 {N_("ICS Alarm"), IcsAlarmProc},
705 {N_("Old Save Style"), OldSaveStyleProc},
706 {N_("Periodic Updates"), PeriodicUpdatesProc},
707 {N_("Ponder Next Move"), PonderNextMoveProc},
708 {N_("Popup Exit Message"), PopupExitMessageProc},
709 {N_("Popup Move Errors"), PopupMoveErrorsProc},
710 {N_("Premove"), PremoveProc},
711 {N_("Quiet Play"), QuietPlayProc},
712 {N_("Show Coords"), ShowCoordsProc},
713 {N_("Hide Thinking"), HideThinkingProc},
714 {N_("Test Legality"), TestLegalityProc},
715 {"----", NothingProc},
716 {N_("Save Settings Now"), SaveSettingsProc},
717 {N_("Save Settings on Exit"), SaveOnExitProc},
721 MenuItem helpMenu[] = {
722 {N_("Info XBoard"), InfoProc},
723 {N_("Man XBoard"), ManProc},
724 {"----", NothingProc},
725 {N_("Hint"), HintProc},
726 {N_("Book"), BookProc},
727 {"----", NothingProc},
728 {N_("About XBoard"), AboutProc},
733 {N_("File"), fileMenu},
734 {N_("Mode"), modeMenu},
735 {N_("Action"), actionMenu},
736 {N_("Step"), stepMenu},
737 {N_("Options"), optionsMenu},
738 {N_("Help"), helpMenu},
742 #define PAUSE_BUTTON N_("P")
743 MenuItem buttonBar[] = {
746 {PAUSE_BUTTON, PauseProc},
752 #define PIECE_MENU_SIZE 18
753 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
754 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
755 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
756 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
757 N_("Empty square"), N_("Clear board") },
758 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
759 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
760 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
761 N_("Empty square"), N_("Clear board") }
763 /* must be in same order as PieceMenuStrings! */
764 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
765 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
766 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
767 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
768 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
769 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
770 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
771 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
772 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
775 #define DROP_MENU_SIZE 6
776 String dropMenuStrings[DROP_MENU_SIZE] = {
777 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
779 /* must be in same order as PieceMenuStrings! */
780 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
781 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
782 WhiteRook, WhiteQueen
790 DropMenuEnables dmEnables[] = {
808 { XtNborderWidth, 0 },
809 { XtNdefaultDistance, 0 },
813 { XtNborderWidth, 0 },
814 { XtNresizable, (XtArgVal) True },
818 { XtNborderWidth, 0 },
824 { XtNjustify, (XtArgVal) XtJustifyRight },
825 { XtNlabel, (XtArgVal) "..." },
826 { XtNresizable, (XtArgVal) True },
827 { XtNresize, (XtArgVal) False }
830 Arg messageArgs[] = {
831 { XtNjustify, (XtArgVal) XtJustifyLeft },
832 { XtNlabel, (XtArgVal) "..." },
833 { XtNresizable, (XtArgVal) True },
834 { XtNresize, (XtArgVal) False }
838 { XtNborderWidth, 0 },
839 { XtNjustify, (XtArgVal) XtJustifyLeft }
842 XtResource clientResources[] = {
843 { "flashCount", "flashCount", XtRInt, sizeof(int),
844 XtOffset(AppDataPtr, flashCount), XtRImmediate,
845 (XtPointer) FLASH_COUNT },
848 XrmOptionDescRec shellOptions[] = {
849 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
850 { "-flash", "flashCount", XrmoptionNoArg, "3" },
851 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
854 XtActionsRec boardActions[] = {
855 { "DrawPosition", DrawPositionProc },
856 { "HandleUserMove", HandleUserMove },
857 { "AnimateUserMove", AnimateUserMove },
858 { "HandlePV", HandlePV },
859 { "SelectPV", SelectPV },
860 { "StopPV", StopPV },
861 { "FileNameAction", FileNameAction },
862 { "AskQuestionProc", AskQuestionProc },
863 { "AskQuestionReplyAction", AskQuestionReplyAction },
864 { "PieceMenuPopup", PieceMenuPopup },
865 { "WhiteClock", WhiteClock },
866 { "BlackClock", BlackClock },
867 { "Iconify", Iconify },
868 { "ResetProc", ResetProc },
869 { "NewVariantProc", NewVariantProc },
870 { "LoadGameProc", LoadGameProc },
871 { "LoadNextGameProc", LoadNextGameProc },
872 { "LoadPrevGameProc", LoadPrevGameProc },
873 { "LoadSelectedProc", LoadSelectedProc },
874 { "SetFilterProc", SetFilterProc },
875 { "ReloadGameProc", ReloadGameProc },
876 { "LoadPositionProc", LoadPositionProc },
877 { "LoadNextPositionProc", LoadNextPositionProc },
878 { "LoadPrevPositionProc", LoadPrevPositionProc },
879 { "ReloadPositionProc", ReloadPositionProc },
880 { "CopyPositionProc", CopyPositionProc },
881 { "PastePositionProc", PastePositionProc },
882 { "CopyGameProc", CopyGameProc },
883 { "PasteGameProc", PasteGameProc },
884 { "SaveGameProc", SaveGameProc },
885 { "SavePositionProc", SavePositionProc },
886 { "MailMoveProc", MailMoveProc },
887 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
888 { "QuitProc", QuitProc },
889 { "MachineWhiteProc", MachineWhiteProc },
890 { "MachineBlackProc", MachineBlackProc },
891 { "AnalysisModeProc", AnalyzeModeProc },
892 { "AnalyzeFileProc", AnalyzeFileProc },
893 { "TwoMachinesProc", TwoMachinesProc },
894 { "IcsClientProc", IcsClientProc },
895 { "EditGameProc", EditGameProc },
896 { "EditPositionProc", EditPositionProc },
897 { "TrainingProc", EditPositionProc },
898 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
899 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
900 { "ShowGameListProc", ShowGameListProc },
901 { "ShowMoveListProc", HistoryShowProc},
902 { "EditTagsProc", EditCommentProc },
903 { "EditCommentProc", EditCommentProc },
904 { "IcsAlarmProc", IcsAlarmProc },
905 { "IcsInputBoxProc", IcsInputBoxProc },
906 { "PauseProc", PauseProc },
907 { "AcceptProc", AcceptProc },
908 { "DeclineProc", DeclineProc },
909 { "RematchProc", RematchProc },
910 { "CallFlagProc", CallFlagProc },
911 { "DrawProc", DrawProc },
912 { "AdjournProc", AdjournProc },
913 { "AbortProc", AbortProc },
914 { "ResignProc", ResignProc },
915 { "AdjuWhiteProc", AdjuWhiteProc },
916 { "AdjuBlackProc", AdjuBlackProc },
917 { "AdjuDrawProc", AdjuDrawProc },
918 { "EnterKeyProc", EnterKeyProc },
919 { "UpKeyProc", UpKeyProc },
920 { "DownKeyProc", DownKeyProc },
921 { "StopObservingProc", StopObservingProc },
922 { "StopExaminingProc", StopExaminingProc },
923 { "UploadProc", UploadProc },
924 { "BackwardProc", BackwardProc },
925 { "ForwardProc", ForwardProc },
926 { "ToStartProc", ToStartProc },
927 { "ToEndProc", ToEndProc },
928 { "RevertProc", RevertProc },
929 { "AnnotateProc", AnnotateProc },
930 { "TruncateGameProc", TruncateGameProc },
931 { "MoveNowProc", MoveNowProc },
932 { "RetractMoveProc", RetractMoveProc },
933 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
934 { "UciMenuProc", (XtActionProc) UciMenuProc },
935 { "TimeControlProc", (XtActionProc) TimeControlProc },
936 { "AlwaysQueenProc", AlwaysQueenProc },
937 { "AnimateDraggingProc", AnimateDraggingProc },
938 { "AnimateMovingProc", AnimateMovingProc },
939 { "AutoflagProc", AutoflagProc },
940 { "AutoflipProc", AutoflipProc },
941 { "AutobsProc", AutobsProc },
942 { "AutoraiseProc", AutoraiseProc },
943 { "AutosaveProc", AutosaveProc },
944 { "BlindfoldProc", BlindfoldProc },
945 { "FlashMovesProc", FlashMovesProc },
946 { "FlipViewProc", FlipViewProc },
947 { "GetMoveListProc", GetMoveListProc },
949 { "HighlightDraggingProc", HighlightDraggingProc },
951 { "HighlightLastMoveProc", HighlightLastMoveProc },
952 { "IcsAlarmProc", IcsAlarmProc },
953 { "MoveSoundProc", MoveSoundProc },
954 { "OldSaveStyleProc", OldSaveStyleProc },
955 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
956 { "PonderNextMoveProc", PonderNextMoveProc },
957 { "PopupExitMessageProc", PopupExitMessageProc },
958 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
959 { "PremoveProc", PremoveProc },
960 { "QuietPlayProc", QuietPlayProc },
961 { "ShowCoordsProc", ShowCoordsProc },
962 { "ShowThinkingProc", ShowThinkingProc },
963 { "HideThinkingProc", HideThinkingProc },
964 { "TestLegalityProc", TestLegalityProc },
965 { "SaveSettingsProc", SaveSettingsProc },
966 { "SaveOnExitProc", SaveOnExitProc },
967 { "InfoProc", InfoProc },
968 { "ManProc", ManProc },
969 { "HintProc", HintProc },
970 { "BookProc", BookProc },
971 { "AboutGameProc", AboutGameProc },
972 { "AboutProc", AboutProc },
973 { "DebugProc", DebugProc },
974 { "NothingProc", NothingProc },
975 { "CommentClick", (XtActionProc) CommentClick },
976 { "CommentPopDown", (XtActionProc) CommentPopDown },
977 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
978 { "TagsPopDown", (XtActionProc) TagsPopDown },
979 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
980 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
981 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
982 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
983 { "GameListPopDown", (XtActionProc) GameListPopDown },
984 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
985 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
986 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
987 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
988 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
989 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
990 { "EnginePopDown", (XtActionProc) EnginePopDown },
991 { "UciPopDown", (XtActionProc) UciPopDown },
992 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
993 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
994 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
995 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
998 char globalTranslations[] =
999 ":<Key>F9: ResignProc() \n \
1000 :Ctrl<Key>n: ResetProc() \n \
1001 :Meta<Key>V: NewVariantProc() \n \
1002 :Ctrl<Key>o: LoadGameProc() \n \
1003 :Meta<Key>Next: LoadNextGameProc() \n \
1004 :Meta<Key>Prior: LoadPrevGameProc() \n \
1005 :Ctrl<Key>s: SaveGameProc() \n \
1006 :Ctrl<Key>c: CopyGameProc() \n \
1007 :Ctrl<Key>v: PasteGameProc() \n \
1008 :Ctrl<Key>O: LoadPositionProc() \n \
1009 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1010 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1011 :Ctrl<Key>S: SavePositionProc() \n \
1012 :Ctrl<Key>C: CopyPositionProc() \n \
1013 :Ctrl<Key>V: PastePositionProc() \n \
1014 :Ctrl<Key>q: QuitProc() \n \
1015 :Ctrl<Key>w: MachineWhiteProc() \n \
1016 :Ctrl<Key>b: MachineBlackProc() \n \
1017 :Ctrl<Key>t: TwoMachinesProc() \n \
1018 :Ctrl<Key>a: AnalysisModeProc() \n \
1019 :Ctrl<Key>f: AnalyzeFileProc() \n \
1020 :Ctrl<Key>e: EditGameProc() \n \
1021 :Ctrl<Key>E: EditPositionProc() \n \
1022 :Meta<Key>O: EngineOutputProc() \n \
1023 :Meta<Key>E: EvalGraphProc() \n \
1024 :Meta<Key>G: ShowGameListProc() \n \
1025 :Meta<Key>H: ShowMoveListProc() \n \
1026 :<Key>Pause: PauseProc() \n \
1027 :<Key>F3: AcceptProc() \n \
1028 :<Key>F4: DeclineProc() \n \
1029 :<Key>F12: RematchProc() \n \
1030 :<Key>F5: CallFlagProc() \n \
1031 :<Key>F6: DrawProc() \n \
1032 :<Key>F7: AdjournProc() \n \
1033 :<Key>F8: AbortProc() \n \
1034 :<Key>F10: StopObservingProc() \n \
1035 :<Key>F11: StopExaminingProc() \n \
1036 :Meta Ctrl<Key>F12: DebugProc() \n \
1037 :Meta<Key>End: ToEndProc() \n \
1038 :Meta<Key>Right: ForwardProc() \n \
1039 :Meta<Key>Home: ToStartProc() \n \
1040 :Meta<Key>Left: BackwardProc() \n \
1041 :Ctrl<Key>m: MoveNowProc() \n \
1042 :Ctrl<Key>x: RetractMoveProc() \n \
1043 :Meta<Key>J: EngineMenuProc() \n \
1044 :Meta<Key>U: UciMenuProc() \n \
1045 :Meta<Key>T: TimeControlProc() \n \
1046 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1047 :Ctrl<Key>F: AutoflagProc() \n \
1048 :Ctrl<Key>A: AnimateMovingProc() \n \
1049 :Ctrl<Key>P: PonderNextMoveProc() \n \
1050 :Ctrl<Key>L: TestLegalityProc() \n \
1051 :Ctrl<Key>H: HideThinkingProc() \n \
1052 :<Key>-: Iconify() \n \
1053 :<Key>F1: ManProc() \n \
1054 :<Key>F2: FlipViewProc() \n \
1055 <KeyDown>.: BackwardProc() \n \
1056 <KeyUp>.: ForwardProc() \n \
1057 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1058 \"Send to chess program:\",,1) \n \
1059 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1060 \"Send to second chess program:\",,2) \n";
1062 char boardTranslations[] =
1063 "<Btn1Down>: HandleUserMove() \n \
1064 <Btn1Up>: HandleUserMove() \n \
1065 <Btn1Motion>: AnimateUserMove() \n \
1066 <Btn3Motion>: HandlePV() \n \
1067 <Btn3Up>: PieceMenuPopup(menuB) \n \
1068 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1069 PieceMenuPopup(menuB) \n \
1070 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1071 PieceMenuPopup(menuW) \n \
1072 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1073 PieceMenuPopup(menuW) \n \
1074 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1075 PieceMenuPopup(menuB) \n";
1077 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1078 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1080 char ICSInputTranslations[] =
1081 "<Key>Up: UpKeyProc() \n "
1082 "<Key>Down: DownKeyProc() \n "
1083 "<Key>Return: EnterKeyProc() \n";
1085 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1086 // as the widget is destroyed before the up-click can call extend-end
1087 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1089 String xboardResources[] = {
1090 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1091 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1092 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1097 /* Max possible square size */
1098 #define MAXSQSIZE 256
1100 static int xpm_avail[MAXSQSIZE];
1102 #ifdef HAVE_DIR_STRUCT
1104 /* Extract piece size from filename */
1106 xpm_getsize(name, len, ext)
1117 if ((p=strchr(name, '.')) == NULL ||
1118 StrCaseCmp(p+1, ext) != 0)
1124 while (*p && isdigit(*p))
1131 /* Setup xpm_avail */
1133 xpm_getavail(dirname, ext)
1141 for (i=0; i<MAXSQSIZE; ++i)
1144 if (appData.debugMode)
1145 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1147 dir = opendir(dirname);
1150 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1151 programName, dirname);
1155 while ((ent=readdir(dir)) != NULL) {
1156 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1157 if (i > 0 && i < MAXSQSIZE)
1167 xpm_print_avail(fp, ext)
1173 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1174 for (i=1; i<MAXSQSIZE; ++i) {
1180 /* Return XPM piecesize closest to size */
1182 xpm_closest_to(dirname, size, ext)
1188 int sm_diff = MAXSQSIZE;
1192 xpm_getavail(dirname, ext);
1194 if (appData.debugMode)
1195 xpm_print_avail(stderr, ext);
1197 for (i=1; i<MAXSQSIZE; ++i) {
1200 diff = (diff<0) ? -diff : diff;
1201 if (diff < sm_diff) {
1209 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1215 #else /* !HAVE_DIR_STRUCT */
1216 /* If we are on a system without a DIR struct, we can't
1217 read the directory, so we can't collect a list of
1218 filenames, etc., so we can't do any size-fitting. */
1220 xpm_closest_to(dirname, size, ext)
1225 fprintf(stderr, _("\
1226 Warning: No DIR structure found on this system --\n\
1227 Unable to autosize for XPM/XIM pieces.\n\
1228 Please report this error to frankm@hiwaay.net.\n\
1229 Include system type & operating system in message.\n"));
1232 #endif /* HAVE_DIR_STRUCT */
1234 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1235 "magenta", "cyan", "white" };
1239 TextColors textColors[(int)NColorClasses];
1241 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1243 parse_color(str, which)
1247 char *p, buf[100], *d;
1250 if (strlen(str) > 99) /* watch bounds on buf */
1255 for (i=0; i<which; ++i) {
1262 /* Could be looking at something like:
1264 .. in which case we want to stop on a comma also */
1265 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1269 return -1; /* Use default for empty field */
1272 if (which == 2 || isdigit(*p))
1275 while (*p && isalpha(*p))
1280 for (i=0; i<8; ++i) {
1281 if (!StrCaseCmp(buf, cnames[i]))
1282 return which? (i+40) : (i+30);
1284 if (!StrCaseCmp(buf, "default")) return -1;
1286 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1291 parse_cpair(cc, str)
1295 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1296 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1301 /* bg and attr are optional */
1302 textColors[(int)cc].bg = parse_color(str, 1);
1303 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1304 textColors[(int)cc].attr = 0;
1310 /* Arrange to catch delete-window events */
1311 Atom wm_delete_window;
1313 CatchDeleteWindow(Widget w, String procname)
1316 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1317 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1318 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1325 XtSetArg(args[0], XtNiconic, False);
1326 XtSetValues(shellWidget, args, 1);
1328 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1331 //---------------------------------------------------------------------------------------------------------
1332 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1335 #define CW_USEDEFAULT (1<<31)
1336 #define ICS_TEXT_MENU_SIZE 90
1337 #define DEBUG_FILE "xboard.debug"
1338 #define SetCurrentDirectory chdir
1339 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1343 // these two must some day move to frontend.h, when they are implemented
1344 Boolean GameListIsUp();
1346 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1349 // front-end part of option handling
1351 // [HGM] This platform-dependent table provides the location for storing the color info
1352 extern char *crWhite, * crBlack;
1356 &appData.whitePieceColor,
1357 &appData.blackPieceColor,
1358 &appData.lightSquareColor,
1359 &appData.darkSquareColor,
1360 &appData.highlightSquareColor,
1361 &appData.premoveHighlightColor,
1362 &appData.lowTimeWarningColor,
1373 // [HGM] font: keep a font for each square size, even non-stndard ones
1374 #define NUM_SIZES 18
1375 #define MAX_SIZE 130
1376 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1377 char *fontTable[NUM_FONTS][MAX_SIZE];
1380 ParseFont(char *name, int number)
1381 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1383 if(sscanf(name, "size%d:", &size)) {
1384 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1385 // defer processing it until we know if it matches our board size
1386 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1387 fontTable[number][size] = strdup(strchr(name, ':')+1);
1388 fontValid[number][size] = True;
1393 case 0: // CLOCK_FONT
1394 appData.clockFont = strdup(name);
1396 case 1: // MESSAGE_FONT
1397 appData.font = strdup(name);
1399 case 2: // COORD_FONT
1400 appData.coordFont = strdup(name);
1405 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1410 { // only 2 fonts currently
1411 appData.clockFont = CLOCK_FONT_NAME;
1412 appData.coordFont = COORD_FONT_NAME;
1413 appData.font = DEFAULT_FONT_NAME;
1418 { // no-op, until we identify the code for this already in XBoard and move it here
1422 ParseColor(int n, char *name)
1423 { // in XBoard, just copy the color-name string
1424 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1428 ParseTextAttribs(ColorClass cc, char *s)
1430 (&appData.colorShout)[cc] = strdup(s);
1434 ParseBoardSize(void *addr, char *name)
1436 appData.boardSize = strdup(name);
1441 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1445 SetCommPortDefaults()
1446 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1449 // [HGM] args: these three cases taken out to stay in front-end
1451 SaveFontArg(FILE *f, ArgDescriptor *ad)
1453 char *name, buf[MSG_SIZ];
1454 int i, n = (int)ad->argLoc;
1456 case 0: // CLOCK_FONT
1457 name = appData.clockFont;
1459 case 1: // MESSAGE_FONT
1460 name = appData.font;
1462 case 2: // COORD_FONT
1463 name = appData.coordFont;
1468 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1469 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1470 fontTable[n][squareSize] = strdup(name);
1471 fontValid[n][squareSize] = True;
1474 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1475 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1480 { // nothing to do, as the sounds are at all times represented by their text-string names already
1484 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1485 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1486 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1490 SaveColor(FILE *f, ArgDescriptor *ad)
1491 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1492 if(colorVariable[(int)ad->argLoc])
1493 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1497 SaveBoardSize(FILE *f, char *name, void *addr)
1498 { // wrapper to shield back-end from BoardSize & sizeInfo
1499 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1503 ParseCommPortSettings(char *s)
1504 { // no such option in XBoard (yet)
1507 extern Widget engineOutputShell;
1508 extern Widget tagsShell, editTagsShell;
1510 GetActualPlacement(Widget wg, WindowPlacement *wp)
1520 XtSetArg(args[i], XtNx, &x); i++;
1521 XtSetArg(args[i], XtNy, &y); i++;
1522 XtSetArg(args[i], XtNwidth, &w); i++;
1523 XtSetArg(args[i], XtNheight, &h); i++;
1524 XtGetValues(wg, args, i);
1533 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1534 // In XBoard this will have to wait until awareness of window parameters is implemented
1535 GetActualPlacement(shellWidget, &wpMain);
1536 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1537 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1538 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1539 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1540 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1541 else GetActualPlacement(editShell, &wpComment);
1542 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1543 else GetActualPlacement(editTagsShell, &wpTags);
1547 PrintCommPortSettings(FILE *f, char *name)
1548 { // This option does not exist in XBoard
1552 MySearchPath(char *installDir, char *name, char *fullname)
1553 { // just append installDir and name. Perhaps ExpandPath should be used here?
1554 name = ExpandPathName(name);
1555 if(name && name[0] == '/')
1556 safeStrCpy(fullname, name, MSG_SIZ );
1558 sprintf(fullname, "%s%c%s", installDir, '/', name);
1564 MyGetFullPathName(char *name, char *fullname)
1565 { // should use ExpandPath?
1566 name = ExpandPathName(name);
1567 safeStrCpy(fullname, name, MSG_SIZ );
1572 EnsureOnScreen(int *x, int *y, int minX, int minY)
1579 { // [HGM] args: allows testing if main window is realized from back-end
1580 return xBoardWindow != 0;
1584 PopUpStartupDialog()
1585 { // start menu not implemented in XBoard
1588 ConvertToLine(int argc, char **argv)
1590 static char line[128*1024], buf[1024];
1594 for(i=1; i<argc; i++) {
1595 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1596 && argv[i][0] != '{' )
1597 sprintf(buf, "{%s} ", argv[i]);
1598 else sprintf(buf, "%s ", argv[i]);
1601 line[strlen(line)-1] = NULLCHAR;
1605 //--------------------------------------------------------------------------------------------
1607 extern Boolean twoBoards, partnerUp;
1610 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1612 #define BoardSize int
1613 void InitDrawingSizes(BoardSize boardSize, int flags)
1614 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1615 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1617 XtGeometryResult gres;
1620 if(!formWidget) return;
1623 * Enable shell resizing.
1625 shellArgs[0].value = (XtArgVal) &w;
1626 shellArgs[1].value = (XtArgVal) &h;
1627 XtGetValues(shellWidget, shellArgs, 2);
1629 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1630 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1631 XtSetValues(shellWidget, &shellArgs[2], 4);
1633 XtSetArg(args[0], XtNdefaultDistance, &sep);
1634 XtGetValues(formWidget, args, 1);
1636 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1637 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1639 hOffset = boardWidth + 10;
1640 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1641 secondSegments[i] = gridSegments[i];
1642 secondSegments[i].x1 += hOffset;
1643 secondSegments[i].x2 += hOffset;
1646 XtSetArg(args[0], XtNwidth, boardWidth);
1647 XtSetArg(args[1], XtNheight, boardHeight);
1648 XtSetValues(boardWidget, args, 2);
1650 timerWidth = (boardWidth - sep) / 2;
1651 XtSetArg(args[0], XtNwidth, timerWidth);
1652 XtSetValues(whiteTimerWidget, args, 1);
1653 XtSetValues(blackTimerWidget, args, 1);
1655 XawFormDoLayout(formWidget, False);
1657 if (appData.titleInWindow) {
1659 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1660 XtSetArg(args[i], XtNheight, &h); i++;
1661 XtGetValues(titleWidget, args, i);
1663 w = boardWidth - 2*bor;
1665 XtSetArg(args[0], XtNwidth, &w);
1666 XtGetValues(menuBarWidget, args, 1);
1667 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1670 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1671 if (gres != XtGeometryYes && appData.debugMode) {
1673 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1674 programName, gres, w, h, wr, hr);
1678 XawFormDoLayout(formWidget, True);
1681 * Inhibit shell resizing.
1683 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1684 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1685 shellArgs[4].value = shellArgs[2].value = w;
1686 shellArgs[5].value = shellArgs[3].value = h;
1687 XtSetValues(shellWidget, &shellArgs[0], 6);
1689 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1692 for(i=0; i<4; i++) {
1694 for(p=0; p<=(int)WhiteKing; p++)
1695 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1696 if(gameInfo.variant == VariantShogi) {
1697 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1698 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1699 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1700 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1701 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1704 if(gameInfo.variant == VariantGothic) {
1705 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1709 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1710 for(p=0; p<=(int)WhiteKing; p++)
1711 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1712 if(gameInfo.variant == VariantShogi) {
1713 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1714 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1715 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1716 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1717 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1720 if(gameInfo.variant == VariantGothic) {
1721 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1727 for(i=0; i<2; i++) {
1729 for(p=0; p<=(int)WhiteKing; p++)
1730 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1731 if(gameInfo.variant == VariantShogi) {
1732 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1733 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1734 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1735 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1736 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1739 if(gameInfo.variant == VariantGothic) {
1740 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1756 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1757 XSetWindowAttributes window_attributes;
1759 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1760 XrmValue vFrom, vTo;
1761 XtGeometryResult gres;
1764 int forceMono = False;
1766 srandom(time(0)); // [HGM] book: make random truly random
1768 setbuf(stdout, NULL);
1769 setbuf(stderr, NULL);
1772 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1773 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1777 programName = strrchr(argv[0], '/');
1778 if (programName == NULL)
1779 programName = argv[0];
1784 XtSetLanguageProc(NULL, NULL, NULL);
1785 bindtextdomain(PACKAGE, LOCALEDIR);
1786 textdomain(PACKAGE);
1790 XtAppInitialize(&appContext, "XBoard", shellOptions,
1791 XtNumber(shellOptions),
1792 &argc, argv, xboardResources, NULL, 0);
1793 appData.boardSize = "";
1794 InitAppData(ConvertToLine(argc, argv));
1796 if (p == NULL) p = "/tmp";
1797 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1798 gameCopyFilename = (char*) malloc(i);
1799 gamePasteFilename = (char*) malloc(i);
1800 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1801 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1803 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1804 clientResources, XtNumber(clientResources),
1807 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1808 static char buf[MSG_SIZ];
1809 EscapeExpand(buf, appData.initString);
1810 appData.initString = strdup(buf);
1811 EscapeExpand(buf, appData.secondInitString);
1812 appData.secondInitString = strdup(buf);
1813 EscapeExpand(buf, appData.firstComputerString);
1814 appData.firstComputerString = strdup(buf);
1815 EscapeExpand(buf, appData.secondComputerString);
1816 appData.secondComputerString = strdup(buf);
1819 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1822 if (chdir(chessDir) != 0) {
1823 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1829 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1830 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1831 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1832 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1835 setbuf(debugFP, NULL);
1838 /* [HGM,HR] make sure board size is acceptable */
1839 if(appData.NrFiles > BOARD_FILES ||
1840 appData.NrRanks > BOARD_RANKS )
1841 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1844 /* This feature does not work; animation needs a rewrite */
1845 appData.highlightDragging = FALSE;
1849 xDisplay = XtDisplay(shellWidget);
1850 xScreen = DefaultScreen(xDisplay);
1851 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1853 gameInfo.variant = StringToVariant(appData.variant);
1854 InitPosition(FALSE);
1857 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1859 if (isdigit(appData.boardSize[0])) {
1860 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1861 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1862 &fontPxlSize, &smallLayout, &tinyLayout);
1864 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1865 programName, appData.boardSize);
1869 /* Find some defaults; use the nearest known size */
1870 SizeDefaults *szd, *nearest;
1871 int distance = 99999;
1872 nearest = szd = sizeDefaults;
1873 while (szd->name != NULL) {
1874 if (abs(szd->squareSize - squareSize) < distance) {
1876 distance = abs(szd->squareSize - squareSize);
1877 if (distance == 0) break;
1881 if (i < 2) lineGap = nearest->lineGap;
1882 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1883 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1884 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1885 if (i < 6) smallLayout = nearest->smallLayout;
1886 if (i < 7) tinyLayout = nearest->tinyLayout;
1889 SizeDefaults *szd = sizeDefaults;
1890 if (*appData.boardSize == NULLCHAR) {
1891 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1892 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1895 if (szd->name == NULL) szd--;
1896 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1898 while (szd->name != NULL &&
1899 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1900 if (szd->name == NULL) {
1901 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1902 programName, appData.boardSize);
1906 squareSize = szd->squareSize;
1907 lineGap = szd->lineGap;
1908 clockFontPxlSize = szd->clockFontPxlSize;
1909 coordFontPxlSize = szd->coordFontPxlSize;
1910 fontPxlSize = szd->fontPxlSize;
1911 smallLayout = szd->smallLayout;
1912 tinyLayout = szd->tinyLayout;
1913 // [HGM] font: use defaults from settings file if available and not overruled
1915 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1916 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1917 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1918 appData.font = fontTable[MESSAGE_FONT][squareSize];
1919 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1920 appData.coordFont = fontTable[COORD_FONT][squareSize];
1922 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1923 if (strlen(appData.pixmapDirectory) > 0) {
1924 p = ExpandPathName(appData.pixmapDirectory);
1926 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1927 appData.pixmapDirectory);
1930 if (appData.debugMode) {
1931 fprintf(stderr, _("\
1932 XBoard square size (hint): %d\n\
1933 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1935 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1936 if (appData.debugMode) {
1937 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1941 /* [HR] height treated separately (hacked) */
1942 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1943 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1944 if (appData.showJail == 1) {
1945 /* Jail on top and bottom */
1946 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1947 XtSetArg(boardArgs[2], XtNheight,
1948 boardHeight + 2*(lineGap + squareSize));
1949 } else if (appData.showJail == 2) {
1951 XtSetArg(boardArgs[1], XtNwidth,
1952 boardWidth + 2*(lineGap + squareSize));
1953 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1956 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1957 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1961 * Determine what fonts to use.
1963 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1964 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1965 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1966 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1967 coordFontID = XLoadFont(xDisplay, appData.coordFont);
1968 coordFontStruct = XQueryFont(xDisplay, coordFontID);
1969 appData.font = FindFont(appData.font, fontPxlSize);
1970 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
1971 countFontStruct = XQueryFont(xDisplay, countFontID);
1972 // appData.font = FindFont(appData.font, fontPxlSize);
1974 xdb = XtDatabase(xDisplay);
1975 XrmPutStringResource(&xdb, "*font", appData.font);
1978 * Detect if there are not enough colors available and adapt.
1980 if (DefaultDepth(xDisplay, xScreen) <= 2) {
1981 appData.monoMode = True;
1984 if (!appData.monoMode) {
1985 vFrom.addr = (caddr_t) appData.lightSquareColor;
1986 vFrom.size = strlen(appData.lightSquareColor);
1987 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1988 if (vTo.addr == NULL) {
1989 appData.monoMode = True;
1992 lightSquareColor = *(Pixel *) vTo.addr;
1995 if (!appData.monoMode) {
1996 vFrom.addr = (caddr_t) appData.darkSquareColor;
1997 vFrom.size = strlen(appData.darkSquareColor);
1998 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1999 if (vTo.addr == NULL) {
2000 appData.monoMode = True;
2003 darkSquareColor = *(Pixel *) vTo.addr;
2006 if (!appData.monoMode) {
2007 vFrom.addr = (caddr_t) appData.whitePieceColor;
2008 vFrom.size = strlen(appData.whitePieceColor);
2009 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2010 if (vTo.addr == NULL) {
2011 appData.monoMode = True;
2014 whitePieceColor = *(Pixel *) vTo.addr;
2017 if (!appData.monoMode) {
2018 vFrom.addr = (caddr_t) appData.blackPieceColor;
2019 vFrom.size = strlen(appData.blackPieceColor);
2020 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2021 if (vTo.addr == NULL) {
2022 appData.monoMode = True;
2025 blackPieceColor = *(Pixel *) vTo.addr;
2029 if (!appData.monoMode) {
2030 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2031 vFrom.size = strlen(appData.highlightSquareColor);
2032 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2033 if (vTo.addr == NULL) {
2034 appData.monoMode = True;
2037 highlightSquareColor = *(Pixel *) vTo.addr;
2041 if (!appData.monoMode) {
2042 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2043 vFrom.size = strlen(appData.premoveHighlightColor);
2044 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2045 if (vTo.addr == NULL) {
2046 appData.monoMode = True;
2049 premoveHighlightColor = *(Pixel *) vTo.addr;
2054 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2057 if (appData.bitmapDirectory == NULL ||
2058 appData.bitmapDirectory[0] == NULLCHAR)
2059 appData.bitmapDirectory = DEF_BITMAP_DIR;
2062 if (appData.lowTimeWarning && !appData.monoMode) {
2063 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2064 vFrom.size = strlen(appData.lowTimeWarningColor);
2065 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2066 if (vTo.addr == NULL)
2067 appData.monoMode = True;
2069 lowTimeWarningColor = *(Pixel *) vTo.addr;
2072 if (appData.monoMode && appData.debugMode) {
2073 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2074 (unsigned long) XWhitePixel(xDisplay, xScreen),
2075 (unsigned long) XBlackPixel(xDisplay, xScreen));
2078 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2079 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2080 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2081 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2082 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2083 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2084 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2085 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2086 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2087 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2089 if (appData.colorize) {
2091 _("%s: can't parse color names; disabling colorization\n"),
2094 appData.colorize = FALSE;
2096 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2097 textColors[ColorNone].attr = 0;
2099 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2105 layoutName = "tinyLayout";
2106 } else if (smallLayout) {
2107 layoutName = "smallLayout";
2109 layoutName = "normalLayout";
2111 /* Outer layoutWidget is there only to provide a name for use in
2112 resources that depend on the layout style */
2114 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2115 layoutArgs, XtNumber(layoutArgs));
2117 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2118 formArgs, XtNumber(formArgs));
2119 XtSetArg(args[0], XtNdefaultDistance, &sep);
2120 XtGetValues(formWidget, args, 1);
2123 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2124 XtSetArg(args[0], XtNtop, XtChainTop);
2125 XtSetArg(args[1], XtNbottom, XtChainTop);
2126 XtSetArg(args[2], XtNright, XtChainLeft);
2127 XtSetValues(menuBarWidget, args, 3);
2129 widgetList[j++] = whiteTimerWidget =
2130 XtCreateWidget("whiteTime", labelWidgetClass,
2131 formWidget, timerArgs, XtNumber(timerArgs));
2132 XtSetArg(args[0], XtNfont, clockFontStruct);
2133 XtSetArg(args[1], XtNtop, XtChainTop);
2134 XtSetArg(args[2], XtNbottom, XtChainTop);
2135 XtSetValues(whiteTimerWidget, args, 3);
2137 widgetList[j++] = blackTimerWidget =
2138 XtCreateWidget("blackTime", labelWidgetClass,
2139 formWidget, timerArgs, XtNumber(timerArgs));
2140 XtSetArg(args[0], XtNfont, clockFontStruct);
2141 XtSetArg(args[1], XtNtop, XtChainTop);
2142 XtSetArg(args[2], XtNbottom, XtChainTop);
2143 XtSetValues(blackTimerWidget, args, 3);
2145 if (appData.titleInWindow) {
2146 widgetList[j++] = titleWidget =
2147 XtCreateWidget("title", labelWidgetClass, formWidget,
2148 titleArgs, XtNumber(titleArgs));
2149 XtSetArg(args[0], XtNtop, XtChainTop);
2150 XtSetArg(args[1], XtNbottom, XtChainTop);
2151 XtSetValues(titleWidget, args, 2);
2154 if (appData.showButtonBar) {
2155 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2156 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2157 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2158 XtSetArg(args[2], XtNtop, XtChainTop);
2159 XtSetArg(args[3], XtNbottom, XtChainTop);
2160 XtSetValues(buttonBarWidget, args, 4);
2163 widgetList[j++] = messageWidget =
2164 XtCreateWidget("message", labelWidgetClass, formWidget,
2165 messageArgs, XtNumber(messageArgs));
2166 XtSetArg(args[0], XtNtop, XtChainTop);
2167 XtSetArg(args[1], XtNbottom, XtChainTop);
2168 XtSetValues(messageWidget, args, 2);
2170 widgetList[j++] = boardWidget =
2171 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2172 XtNumber(boardArgs));
2174 XtManageChildren(widgetList, j);
2176 timerWidth = (boardWidth - sep) / 2;
2177 XtSetArg(args[0], XtNwidth, timerWidth);
2178 XtSetValues(whiteTimerWidget, args, 1);
2179 XtSetValues(blackTimerWidget, args, 1);
2181 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2182 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2183 XtGetValues(whiteTimerWidget, args, 2);
2185 if (appData.showButtonBar) {
2186 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2187 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2188 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2192 * formWidget uses these constraints but they are stored
2196 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2197 XtSetValues(menuBarWidget, args, i);
2198 if (appData.titleInWindow) {
2201 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2202 XtSetValues(whiteTimerWidget, args, i);
2204 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2205 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2206 XtSetValues(blackTimerWidget, args, i);
2208 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2209 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2210 XtSetValues(titleWidget, args, i);
2212 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2213 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2214 XtSetValues(messageWidget, args, i);
2215 if (appData.showButtonBar) {
2217 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2218 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2219 XtSetValues(buttonBarWidget, args, i);
2223 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2224 XtSetValues(whiteTimerWidget, args, i);
2226 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2227 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2228 XtSetValues(blackTimerWidget, args, i);
2230 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2231 XtSetValues(titleWidget, args, i);
2233 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2234 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2235 XtSetValues(messageWidget, args, i);
2236 if (appData.showButtonBar) {
2238 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2239 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2240 XtSetValues(buttonBarWidget, args, i);
2245 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2246 XtSetValues(whiteTimerWidget, args, i);
2248 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2249 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2250 XtSetValues(blackTimerWidget, args, i);
2252 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2253 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2254 XtSetValues(messageWidget, args, i);
2255 if (appData.showButtonBar) {
2257 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2258 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2259 XtSetValues(buttonBarWidget, args, i);
2263 XtSetArg(args[0], XtNfromVert, messageWidget);
2264 XtSetArg(args[1], XtNtop, XtChainTop);
2265 XtSetArg(args[2], XtNbottom, XtChainBottom);
2266 XtSetArg(args[3], XtNleft, XtChainLeft);
2267 XtSetArg(args[4], XtNright, XtChainRight);
2268 XtSetValues(boardWidget, args, 5);
2270 XtRealizeWidget(shellWidget);
2273 XtSetArg(args[0], XtNx, wpMain.x);
2274 XtSetArg(args[1], XtNy, wpMain.y);
2275 XtSetValues(shellWidget, args, 2);
2279 * Correct the width of the message and title widgets.
2280 * It is not known why some systems need the extra fudge term.
2281 * The value "2" is probably larger than needed.
2283 XawFormDoLayout(formWidget, False);
2285 #define WIDTH_FUDGE 2
2287 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2288 XtSetArg(args[i], XtNheight, &h); i++;
2289 XtGetValues(messageWidget, args, i);
2290 if (appData.showButtonBar) {
2292 XtSetArg(args[i], XtNwidth, &w); i++;
2293 XtGetValues(buttonBarWidget, args, i);
2294 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2296 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2299 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2300 if (gres != XtGeometryYes && appData.debugMode) {
2301 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2302 programName, gres, w, h, wr, hr);
2305 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2306 /* The size used for the child widget in layout lags one resize behind
2307 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2309 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2310 if (gres != XtGeometryYes && appData.debugMode) {
2311 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2312 programName, gres, w, h, wr, hr);
2315 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2316 XtSetArg(args[1], XtNright, XtChainRight);
2317 XtSetValues(messageWidget, args, 2);
2319 if (appData.titleInWindow) {
2321 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2322 XtSetArg(args[i], XtNheight, &h); i++;
2323 XtGetValues(titleWidget, args, i);
2325 w = boardWidth - 2*bor;
2327 XtSetArg(args[0], XtNwidth, &w);
2328 XtGetValues(menuBarWidget, args, 1);
2329 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2332 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2333 if (gres != XtGeometryYes && appData.debugMode) {
2335 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2336 programName, gres, w, h, wr, hr);
2339 XawFormDoLayout(formWidget, True);
2341 xBoardWindow = XtWindow(boardWidget);
2343 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2344 // not need to go into InitDrawingSizes().
2348 * Create X checkmark bitmap and initialize option menu checks.
2350 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2351 checkmark_bits, checkmark_width, checkmark_height);
2352 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2353 if (appData.alwaysPromoteToQueen) {
2354 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2357 if (appData.animateDragging) {
2358 XtSetValues(XtNameToWidget(menuBarWidget,
2359 "menuOptions.Animate Dragging"),
2362 if (appData.animate) {
2363 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2366 if (appData.autoComment) {
2367 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2370 if (appData.autoCallFlag) {
2371 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2374 if (appData.autoFlipView) {
2375 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2378 if (appData.autoObserve) {
2379 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2382 if (appData.autoRaiseBoard) {
2383 XtSetValues(XtNameToWidget(menuBarWidget,
2384 "menuOptions.Auto Raise Board"), args, 1);
2386 if (appData.autoSaveGames) {
2387 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2390 if (appData.saveGameFile[0] != NULLCHAR) {
2391 /* Can't turn this off from menu */
2392 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2394 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2398 if (appData.blindfold) {
2399 XtSetValues(XtNameToWidget(menuBarWidget,
2400 "menuOptions.Blindfold"), args, 1);
2402 if (appData.flashCount > 0) {
2403 XtSetValues(XtNameToWidget(menuBarWidget,
2404 "menuOptions.Flash Moves"),
2407 if (appData.getMoveList) {
2408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2412 if (appData.highlightDragging) {
2413 XtSetValues(XtNameToWidget(menuBarWidget,
2414 "menuOptions.Highlight Dragging"),
2418 if (appData.highlightLastMove) {
2419 XtSetValues(XtNameToWidget(menuBarWidget,
2420 "menuOptions.Highlight Last Move"),
2423 if (appData.icsAlarm) {
2424 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2427 if (appData.ringBellAfterMoves) {
2428 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2431 if (appData.oldSaveStyle) {
2432 XtSetValues(XtNameToWidget(menuBarWidget,
2433 "menuOptions.Old Save Style"), args, 1);
2435 if (appData.periodicUpdates) {
2436 XtSetValues(XtNameToWidget(menuBarWidget,
2437 "menuOptions.Periodic Updates"), args, 1);
2439 if (appData.ponderNextMove) {
2440 XtSetValues(XtNameToWidget(menuBarWidget,
2441 "menuOptions.Ponder Next Move"), args, 1);
2443 if (appData.popupExitMessage) {
2444 XtSetValues(XtNameToWidget(menuBarWidget,
2445 "menuOptions.Popup Exit Message"), args, 1);
2447 if (appData.popupMoveErrors) {
2448 XtSetValues(XtNameToWidget(menuBarWidget,
2449 "menuOptions.Popup Move Errors"), args, 1);
2451 if (appData.premove) {
2452 XtSetValues(XtNameToWidget(menuBarWidget,
2453 "menuOptions.Premove"), args, 1);
2455 if (appData.quietPlay) {
2456 XtSetValues(XtNameToWidget(menuBarWidget,
2457 "menuOptions.Quiet Play"), args, 1);
2459 if (appData.showCoords) {
2460 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2463 if (appData.hideThinkingFromHuman) {
2464 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2467 if (appData.testLegality) {
2468 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2471 if (saveSettingsOnExit) {
2472 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2479 ReadBitmap(&wIconPixmap, "icon_white.bm",
2480 icon_white_bits, icon_white_width, icon_white_height);
2481 ReadBitmap(&bIconPixmap, "icon_black.bm",
2482 icon_black_bits, icon_black_width, icon_black_height);
2483 iconPixmap = wIconPixmap;
2485 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2486 XtSetValues(shellWidget, args, i);
2489 * Create a cursor for the board widget.
2491 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2492 XChangeWindowAttributes(xDisplay, xBoardWindow,
2493 CWCursor, &window_attributes);
2496 * Inhibit shell resizing.
2498 shellArgs[0].value = (XtArgVal) &w;
2499 shellArgs[1].value = (XtArgVal) &h;
2500 XtGetValues(shellWidget, shellArgs, 2);
2501 shellArgs[4].value = shellArgs[2].value = w;
2502 shellArgs[5].value = shellArgs[3].value = h;
2503 XtSetValues(shellWidget, &shellArgs[2], 4);
2504 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2505 marginH = h - boardHeight;
2507 CatchDeleteWindow(shellWidget, "QuitProc");
2512 if (appData.bitmapDirectory[0] != NULLCHAR) {
2519 /* Create regular pieces */
2520 if (!useImages) CreatePieces();
2525 if (appData.animate || appData.animateDragging)
2528 XtAugmentTranslations(formWidget,
2529 XtParseTranslationTable(globalTranslations));
2530 XtAugmentTranslations(boardWidget,
2531 XtParseTranslationTable(boardTranslations));
2532 XtAugmentTranslations(whiteTimerWidget,
2533 XtParseTranslationTable(whiteTranslations));
2534 XtAugmentTranslations(blackTimerWidget,
2535 XtParseTranslationTable(blackTranslations));
2537 /* Why is the following needed on some versions of X instead
2538 * of a translation? */
2539 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2540 (XtEventHandler) EventProc, NULL);
2543 /* [AS] Restore layout */
2544 if( wpMoveHistory.visible ) {
2548 if( wpEvalGraph.visible )
2553 if( wpEngineOutput.visible ) {
2554 EngineOutputPopUp();
2559 if (errorExitStatus == -1) {
2560 if (appData.icsActive) {
2561 /* We now wait until we see "login:" from the ICS before
2562 sending the logon script (problems with timestamp otherwise) */
2563 /*ICSInitScript();*/
2564 if (appData.icsInputBox) ICSInputBoxPopUp();
2568 signal(SIGWINCH, TermSizeSigHandler);
2570 signal(SIGINT, IntSigHandler);
2571 signal(SIGTERM, IntSigHandler);
2572 if (*appData.cmailGameName != NULLCHAR) {
2573 signal(SIGUSR1, CmailSigHandler);
2576 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2578 XtSetKeyboardFocus(shellWidget, formWidget);
2580 XtAppMainLoop(appContext);
2581 if (appData.debugMode) fclose(debugFP); // [DM] debug
2588 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2589 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2591 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2592 unlink(gameCopyFilename);
2593 unlink(gamePasteFilename);
2596 RETSIGTYPE TermSizeSigHandler(int sig)
2609 CmailSigHandler(sig)
2615 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2617 /* Activate call-back function CmailSigHandlerCallBack() */
2618 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2620 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2624 CmailSigHandlerCallBack(isr, closure, message, count, error)
2632 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2634 /**** end signal code ****/
2644 f = fopen(appData.icsLogon, "r");
2648 safeStrCpy(buf, p, sizeof(buf)/sizeof(buf[0]) );
2650 strcat(buf, appData.icsLogon);
2651 f = fopen(buf, "r");
2655 ProcessICSInitScript(f);
2662 EditCommentPopDown();
2677 if (!menuBarWidget) return;
2678 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2680 DisplayError("menuStep.Revert", 0);
2682 XtSetSensitive(w, !grey);
2684 w = XtNameToWidget(menuBarWidget, "menuStep.Annotate");
2686 DisplayError("menuStep.Annotate", 0);
2688 XtSetSensitive(w, !grey);
2693 SetMenuEnables(enab)
2697 if (!menuBarWidget) return;
2698 while (enab->name != NULL) {
2699 w = XtNameToWidget(menuBarWidget, enab->name);
2701 DisplayError(enab->name, 0);
2703 XtSetSensitive(w, enab->value);
2709 Enables icsEnables[] = {
2710 { "menuFile.Mail Move", False },
2711 { "menuFile.Reload CMail Message", False },
2712 { "menuMode.Machine Black", False },
2713 { "menuMode.Machine White", False },
2714 { "menuMode.Analysis Mode", False },
2715 { "menuMode.Analyze File", False },
2716 { "menuMode.Two Machines", False },
2718 { "menuHelp.Hint", False },
2719 { "menuHelp.Book", False },
2720 { "menuStep.Move Now", False },
2721 { "menuOptions.Periodic Updates", False },
2722 { "menuOptions.Hide Thinking", False },
2723 { "menuOptions.Ponder Next Move", False },
2725 { "menuStep.Annotate", False },
2729 Enables ncpEnables[] = {
2730 { "menuFile.Mail Move", False },
2731 { "menuFile.Reload CMail Message", False },
2732 { "menuMode.Machine White", False },
2733 { "menuMode.Machine Black", False },
2734 { "menuMode.Analysis Mode", False },
2735 { "menuMode.Analyze File", False },
2736 { "menuMode.Two Machines", False },
2737 { "menuMode.ICS Client", False },
2738 { "menuMode.ICS Input Box", False },
2739 { "Action", False },
2740 { "menuStep.Revert", False },
2741 { "menuStep.Annotate", False },
2742 { "menuStep.Move Now", False },
2743 { "menuStep.Retract Move", False },
2744 { "menuOptions.Auto Comment", False },
2745 { "menuOptions.Auto Flag", False },
2746 { "menuOptions.Auto Flip View", False },
2747 { "menuOptions.Auto Observe", False },
2748 { "menuOptions.Auto Raise Board", False },
2749 { "menuOptions.Get Move List", False },
2750 { "menuOptions.ICS Alarm", False },
2751 { "menuOptions.Move Sound", False },
2752 { "menuOptions.Quiet Play", False },
2753 { "menuOptions.Hide Thinking", False },
2754 { "menuOptions.Periodic Updates", False },
2755 { "menuOptions.Ponder Next Move", False },
2756 { "menuHelp.Hint", False },
2757 { "menuHelp.Book", False },
2761 Enables gnuEnables[] = {
2762 { "menuMode.ICS Client", False },
2763 { "menuMode.ICS Input Box", False },
2764 { "menuAction.Accept", False },
2765 { "menuAction.Decline", False },
2766 { "menuAction.Rematch", False },
2767 { "menuAction.Adjourn", False },
2768 { "menuAction.Stop Examining", False },
2769 { "menuAction.Stop Observing", False },
2770 { "menuAction.Upload to Examine", False },
2771 { "menuStep.Revert", False },
2772 { "menuStep.Annotate", False },
2773 { "menuOptions.Auto Comment", False },
2774 { "menuOptions.Auto Observe", False },
2775 { "menuOptions.Auto Raise Board", False },
2776 { "menuOptions.Get Move List", False },
2777 { "menuOptions.Premove", False },
2778 { "menuOptions.Quiet Play", False },
2780 /* The next two options rely on SetCmailMode being called *after* */
2781 /* SetGNUMode so that when GNU is being used to give hints these */
2782 /* menu options are still available */
2784 { "menuFile.Mail Move", False },
2785 { "menuFile.Reload CMail Message", False },
2789 Enables cmailEnables[] = {
2791 { "menuAction.Call Flag", False },
2792 { "menuAction.Draw", True },
2793 { "menuAction.Adjourn", False },
2794 { "menuAction.Abort", False },
2795 { "menuAction.Stop Observing", False },
2796 { "menuAction.Stop Examining", False },
2797 { "menuFile.Mail Move", True },
2798 { "menuFile.Reload CMail Message", True },
2802 Enables trainingOnEnables[] = {
2803 { "menuMode.Edit Comment", False },
2804 { "menuMode.Pause", False },
2805 { "menuStep.Forward", False },
2806 { "menuStep.Backward", False },
2807 { "menuStep.Forward to End", False },
2808 { "menuStep.Back to Start", False },
2809 { "menuStep.Move Now", False },
2810 { "menuStep.Truncate Game", False },
2814 Enables trainingOffEnables[] = {
2815 { "menuMode.Edit Comment", True },
2816 { "menuMode.Pause", True },
2817 { "menuStep.Forward", True },
2818 { "menuStep.Backward", True },
2819 { "menuStep.Forward to End", True },
2820 { "menuStep.Back to Start", True },
2821 { "menuStep.Move Now", True },
2822 { "menuStep.Truncate Game", True },
2826 Enables machineThinkingEnables[] = {
2827 { "menuFile.Load Game", False },
2828 { "menuFile.Load Next Game", False },
2829 { "menuFile.Load Previous Game", False },
2830 { "menuFile.Reload Same Game", False },
2831 { "menuFile.Paste Game", False },
2832 { "menuFile.Load Position", False },
2833 { "menuFile.Load Next Position", False },
2834 { "menuFile.Load Previous Position", False },
2835 { "menuFile.Reload Same Position", False },
2836 { "menuFile.Paste Position", False },
2837 { "menuMode.Machine White", False },
2838 { "menuMode.Machine Black", False },
2839 { "menuMode.Two Machines", False },
2840 { "menuStep.Retract Move", False },
2844 Enables userThinkingEnables[] = {
2845 { "menuFile.Load Game", True },
2846 { "menuFile.Load Next Game", True },
2847 { "menuFile.Load Previous Game", True },
2848 { "menuFile.Reload Same Game", True },
2849 { "menuFile.Paste Game", True },
2850 { "menuFile.Load Position", True },
2851 { "menuFile.Load Next Position", True },
2852 { "menuFile.Load Previous Position", True },
2853 { "menuFile.Reload Same Position", True },
2854 { "menuFile.Paste Position", True },
2855 { "menuMode.Machine White", True },
2856 { "menuMode.Machine Black", True },
2857 { "menuMode.Two Machines", True },
2858 { "menuStep.Retract Move", True },
2864 SetMenuEnables(icsEnables);
2867 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2868 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2875 SetMenuEnables(ncpEnables);
2881 SetMenuEnables(gnuEnables);
2887 SetMenuEnables(cmailEnables);
2893 SetMenuEnables(trainingOnEnables);
2894 if (appData.showButtonBar) {
2895 XtSetSensitive(buttonBarWidget, False);
2901 SetTrainingModeOff()
2903 SetMenuEnables(trainingOffEnables);
2904 if (appData.showButtonBar) {
2905 XtSetSensitive(buttonBarWidget, True);
2910 SetUserThinkingEnables()
2912 if (appData.noChessProgram) return;
2913 SetMenuEnables(userThinkingEnables);
2917 SetMachineThinkingEnables()
2919 if (appData.noChessProgram) return;
2920 SetMenuEnables(machineThinkingEnables);
2922 case MachinePlaysBlack:
2923 case MachinePlaysWhite:
2924 case TwoMachinesPlay:
2925 XtSetSensitive(XtNameToWidget(menuBarWidget,
2926 ModeToWidgetName(gameMode)), True);
2933 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2934 #define HISTORY_SIZE 64
\r
2935 static char *history[HISTORY_SIZE];
\r
2936 int histIn = 0, histP = 0;
\r
2939 SaveInHistory(char *cmd)
\r
2941 if (history[histIn] != NULL) {
\r
2942 free(history[histIn]);
\r
2943 history[histIn] = NULL;
\r
2945 if (*cmd == NULLCHAR) return;
\r
2946 history[histIn] = StrSave(cmd);
\r
2947 histIn = (histIn + 1) % HISTORY_SIZE;
\r
2948 if (history[histIn] != NULL) {
\r
2949 free(history[histIn]);
\r
2950 history[histIn] = NULL;
\r
2956 PrevInHistory(char *cmd)
\r
2959 if (histP == histIn) {
\r
2960 if (history[histIn] != NULL) free(history[histIn]);
\r
2961 history[histIn] = StrSave(cmd);
\r
2963 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
2964 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
2966 return history[histP];
\r
2972 if (histP == histIn) return NULL;
\r
2973 histP = (histP + 1) % HISTORY_SIZE;
\r
2974 return history[histP];
\r
2976 // end of borrowed code
\r
2978 #define Abs(n) ((n)<0 ? -(n) : (n))
2981 * Find a font that matches "pattern" that is as close as
2982 * possible to the targetPxlSize. Prefer fonts that are k
2983 * pixels smaller to fonts that are k pixels larger. The
2984 * pattern must be in the X Consortium standard format,
2985 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2986 * The return value should be freed with XtFree when no
2990 FindFont(pattern, targetPxlSize)
2994 char **fonts, *p, *best, *scalable, *scalableTail;
2995 int i, j, nfonts, minerr, err, pxlSize;
2998 char **missing_list;
3000 char *def_string, *base_fnt_lst, strInt[3];
3002 XFontStruct **fnt_list;
3004 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3005 sprintf(strInt, "%d", targetPxlSize);
3006 p = strstr(pattern, "--");
3007 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3008 strcat(base_fnt_lst, strInt);
3009 strcat(base_fnt_lst, strchr(p + 2, '-'));
3011 if ((fntSet = XCreateFontSet(xDisplay,
3015 &def_string)) == NULL) {
3017 fprintf(stderr, _("Unable to create font set.\n"));
3021 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3023 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3025 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3026 programName, pattern);
3034 for (i=0; i<nfonts; i++) {
3037 if (*p != '-') continue;
3039 if (*p == NULLCHAR) break;
3040 if (*p++ == '-') j++;
3042 if (j < 7) continue;
3045 scalable = fonts[i];
3048 err = pxlSize - targetPxlSize;
3049 if (Abs(err) < Abs(minerr) ||
3050 (minerr > 0 && err < 0 && -err == minerr)) {
3056 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3057 /* If the error is too big and there is a scalable font,
3058 use the scalable font. */
3059 int headlen = scalableTail - scalable;
3060 p = (char *) XtMalloc(strlen(scalable) + 10);
3061 while (isdigit(*scalableTail)) scalableTail++;
3062 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3064 p = (char *) XtMalloc(strlen(best) + 2);
3065 safeStrCpy(p, best, strlen(best)+1 );
3067 if (appData.debugMode) {
3068 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3069 pattern, targetPxlSize, p);
3072 if (missing_count > 0)
3073 XFreeStringList(missing_list);
3074 XFreeFontSet(xDisplay, fntSet);
3076 XFreeFontNames(fonts);
3083 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3084 | GCBackground | GCFunction | GCPlaneMask;
3085 XGCValues gc_values;
3088 gc_values.plane_mask = AllPlanes;
3089 gc_values.line_width = lineGap;
3090 gc_values.line_style = LineSolid;
3091 gc_values.function = GXcopy;
3093 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3094 gc_values.background = XBlackPixel(xDisplay, xScreen);
3095 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3097 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3098 gc_values.background = XWhitePixel(xDisplay, xScreen);
3099 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3100 XSetFont(xDisplay, coordGC, coordFontID);
3102 // [HGM] make font for holdings counts (white on black0
3103 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3104 gc_values.background = XBlackPixel(xDisplay, xScreen);
3105 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3106 XSetFont(xDisplay, countGC, countFontID);
3108 if (appData.monoMode) {
3109 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3110 gc_values.background = XWhitePixel(xDisplay, xScreen);
3111 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3113 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3114 gc_values.background = XBlackPixel(xDisplay, xScreen);
3115 lightSquareGC = wbPieceGC
3116 = XtGetGC(shellWidget, value_mask, &gc_values);
3118 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3119 gc_values.background = XWhitePixel(xDisplay, xScreen);
3120 darkSquareGC = bwPieceGC
3121 = XtGetGC(shellWidget, value_mask, &gc_values);
3123 if (DefaultDepth(xDisplay, xScreen) == 1) {
3124 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3125 gc_values.function = GXcopyInverted;
3126 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3127 gc_values.function = GXcopy;
3128 if (XBlackPixel(xDisplay, xScreen) == 1) {
3129 bwPieceGC = darkSquareGC;
3130 wbPieceGC = copyInvertedGC;
3132 bwPieceGC = copyInvertedGC;
3133 wbPieceGC = lightSquareGC;
3137 gc_values.foreground = highlightSquareColor;
3138 gc_values.background = highlightSquareColor;
3139 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3141 gc_values.foreground = premoveHighlightColor;
3142 gc_values.background = premoveHighlightColor;
3143 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3145 gc_values.foreground = lightSquareColor;
3146 gc_values.background = darkSquareColor;
3147 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3149 gc_values.foreground = darkSquareColor;
3150 gc_values.background = lightSquareColor;
3151 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3153 gc_values.foreground = jailSquareColor;
3154 gc_values.background = jailSquareColor;
3155 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3157 gc_values.foreground = whitePieceColor;
3158 gc_values.background = darkSquareColor;
3159 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3161 gc_values.foreground = whitePieceColor;
3162 gc_values.background = lightSquareColor;
3163 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3165 gc_values.foreground = whitePieceColor;
3166 gc_values.background = jailSquareColor;
3167 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3169 gc_values.foreground = blackPieceColor;
3170 gc_values.background = darkSquareColor;
3171 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3173 gc_values.foreground = blackPieceColor;
3174 gc_values.background = lightSquareColor;
3175 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3177 gc_values.foreground = blackPieceColor;
3178 gc_values.background = jailSquareColor;
3179 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3183 void loadXIM(xim, xmask, filename, dest, mask)
3196 fp = fopen(filename, "rb");
3198 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3205 for (y=0; y<h; ++y) {
3206 for (x=0; x<h; ++x) {
3211 XPutPixel(xim, x, y, blackPieceColor);
3213 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3216 XPutPixel(xim, x, y, darkSquareColor);
3218 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3221 XPutPixel(xim, x, y, whitePieceColor);
3223 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3226 XPutPixel(xim, x, y, lightSquareColor);
3228 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3234 /* create Pixmap of piece */
3235 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3237 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3240 /* create Pixmap of clipmask
3241 Note: We assume the white/black pieces have the same
3242 outline, so we make only 6 masks. This is okay
3243 since the XPM clipmask routines do the same. */
3245 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3247 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3250 /* now create the 1-bit version */
3251 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3254 values.foreground = 1;
3255 values.background = 0;
3257 /* Don't use XtGetGC, not read only */
3258 maskGC = XCreateGC(xDisplay, *mask,
3259 GCForeground | GCBackground, &values);
3260 XCopyPlane(xDisplay, temp, *mask, maskGC,
3261 0, 0, squareSize, squareSize, 0, 0, 1);
3262 XFreePixmap(xDisplay, temp);
3267 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3269 void CreateXIMPieces()
3274 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3279 /* The XSynchronize calls were copied from CreatePieces.
3280 Not sure if needed, but can't hurt */
3281 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3284 /* temp needed by loadXIM() */
3285 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3286 0, 0, ss, ss, AllPlanes, XYPixmap);
3288 if (strlen(appData.pixmapDirectory) == 0) {
3292 if (appData.monoMode) {
3293 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3297 fprintf(stderr, _("\nLoading XIMs...\n"));
3299 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3300 fprintf(stderr, "%d", piece+1);
3301 for (kind=0; kind<4; kind++) {
3302 fprintf(stderr, ".");
3303 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3304 ExpandPathName(appData.pixmapDirectory),
3305 piece <= (int) WhiteKing ? "" : "w",
3306 pieceBitmapNames[piece],
3308 ximPieceBitmap[kind][piece] =
3309 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3310 0, 0, ss, ss, AllPlanes, XYPixmap);
3311 if (appData.debugMode)
3312 fprintf(stderr, _("(File:%s:) "), buf);
3313 loadXIM(ximPieceBitmap[kind][piece],
3315 &(xpmPieceBitmap2[kind][piece]),
3316 &(ximMaskPm2[piece]));
3317 if(piece <= (int)WhiteKing)
3318 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3320 fprintf(stderr," ");
3322 /* Load light and dark squares */
3323 /* If the LSQ and DSQ pieces don't exist, we will
3324 draw them with solid squares. */
3325 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3326 if (access(buf, 0) != 0) {
3330 fprintf(stderr, _("light square "));
3332 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3333 0, 0, ss, ss, AllPlanes, XYPixmap);
3334 if (appData.debugMode)
3335 fprintf(stderr, _("(File:%s:) "), buf);
3337 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3338 fprintf(stderr, _("dark square "));
3339 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3340 ExpandPathName(appData.pixmapDirectory), ss);
3341 if (appData.debugMode)
3342 fprintf(stderr, _("(File:%s:) "), buf);
3344 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3345 0, 0, ss, ss, AllPlanes, XYPixmap);
3346 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3347 xpmJailSquare = xpmLightSquare;
3349 fprintf(stderr, _("Done.\n"));
3351 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3355 void CreateXPMPieces()
3359 u_int ss = squareSize;
3361 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3362 XpmColorSymbol symbols[4];
3364 /* The XSynchronize calls were copied from CreatePieces.
3365 Not sure if needed, but can't hurt */
3366 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3368 /* Setup translations so piece colors match square colors */
3369 symbols[0].name = "light_piece";
3370 symbols[0].value = appData.whitePieceColor;
3371 symbols[1].name = "dark_piece";
3372 symbols[1].value = appData.blackPieceColor;
3373 symbols[2].name = "light_square";
3374 symbols[2].value = appData.lightSquareColor;
3375 symbols[3].name = "dark_square";
3376 symbols[3].value = appData.darkSquareColor;
3378 attr.valuemask = XpmColorSymbols;
3379 attr.colorsymbols = symbols;
3380 attr.numsymbols = 4;
3382 if (appData.monoMode) {
3383 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3387 if (strlen(appData.pixmapDirectory) == 0) {
3388 XpmPieces* pieces = builtInXpms;
3391 while (pieces->size != squareSize && pieces->size) pieces++;
3392 if (!pieces->size) {
3393 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3396 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3397 for (kind=0; kind<4; kind++) {
3399 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3400 pieces->xpm[piece][kind],
3401 &(xpmPieceBitmap2[kind][piece]),
3402 NULL, &attr)) != 0) {
3403 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3407 if(piece <= (int) WhiteKing)
3408 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3412 xpmJailSquare = xpmLightSquare;
3416 fprintf(stderr, _("\nLoading XPMs...\n"));
3419 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3420 fprintf(stderr, "%d ", piece+1);
3421 for (kind=0; kind<4; kind++) {
3422 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3423 ExpandPathName(appData.pixmapDirectory),
3424 piece > (int) WhiteKing ? "w" : "",
3425 pieceBitmapNames[piece],
3427 if (appData.debugMode) {
3428 fprintf(stderr, _("(File:%s:) "), buf);
3430 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3431 &(xpmPieceBitmap2[kind][piece]),
3432 NULL, &attr)) != 0) {
3433 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3434 // [HGM] missing: read of unorthodox piece failed; substitute King.
3435 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3436 ExpandPathName(appData.pixmapDirectory),
3438 if (appData.debugMode) {
3439 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3441 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3442 &(xpmPieceBitmap2[kind][piece]),
3446 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3451 if(piece <= (int) WhiteKing)
3452 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3455 /* Load light and dark squares */
3456 /* If the LSQ and DSQ pieces don't exist, we will
3457 draw them with solid squares. */
3458 fprintf(stderr, _("light square "));
3459 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3460 if (access(buf, 0) != 0) {
3464 if (appData.debugMode)
3465 fprintf(stderr, _("(File:%s:) "), buf);
3467 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3468 &xpmLightSquare, NULL, &attr)) != 0) {
3469 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3472 fprintf(stderr, _("dark square "));
3473 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3474 ExpandPathName(appData.pixmapDirectory), ss);
3475 if (appData.debugMode) {
3476 fprintf(stderr, _("(File:%s:) "), buf);
3478 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3479 &xpmDarkSquare, NULL, &attr)) != 0) {
3480 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3484 xpmJailSquare = xpmLightSquare;
3485 fprintf(stderr, _("Done.\n"));
3487 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3490 #endif /* HAVE_LIBXPM */
3493 /* No built-in bitmaps */
3498 u_int ss = squareSize;
3500 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3503 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3504 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3505 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3506 pieceBitmapNames[piece],
3507 ss, kind == SOLID ? 's' : 'o');
3508 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3509 if(piece <= (int)WhiteKing)
3510 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3514 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3518 /* With built-in bitmaps */
3521 BuiltInBits* bib = builtInBits;
3524 u_int ss = squareSize;
3526 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3529 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3531 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3532 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3533 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3534 pieceBitmapNames[piece],
3535 ss, kind == SOLID ? 's' : 'o');
3536 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3537 bib->bits[kind][piece], ss, ss);
3538 if(piece <= (int)WhiteKing)
3539 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3543 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3548 void ReadBitmap(pm, name, bits, wreq, hreq)
3551 unsigned char bits[];
3557 char msg[MSG_SIZ], fullname[MSG_SIZ];
3559 if (*appData.bitmapDirectory != NULLCHAR) {
3560 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3561 strcat(fullname, "/");
3562 strcat(fullname, name);
3563 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3564 &w, &h, pm, &x_hot, &y_hot);
3565 fprintf(stderr, "load %s\n", name);
3566 if (errcode != BitmapSuccess) {
3568 case BitmapOpenFailed:
3569 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3571 case BitmapFileInvalid:
3572 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3574 case BitmapNoMemory:
3575 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3579 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3583 fprintf(stderr, _("%s: %s...using built-in\n"),
3585 } else if (w != wreq || h != hreq) {
3587 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3588 programName, fullname, w, h, wreq, hreq);
3594 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3603 if (lineGap == 0) return;
3605 /* [HR] Split this into 2 loops for non-square boards. */
3607 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3608 gridSegments[i].x1 = 0;
3609 gridSegments[i].x2 =
3610 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3611 gridSegments[i].y1 = gridSegments[i].y2
3612 = lineGap / 2 + (i * (squareSize + lineGap));
3615 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3616 gridSegments[j + i].y1 = 0;
3617 gridSegments[j + i].y2 =
3618 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3619 gridSegments[j + i].x1 = gridSegments[j + i].x2
3620 = lineGap / 2 + (j * (squareSize + lineGap));
3624 static void MenuBarSelect(w, addr, index)
3629 XtActionProc proc = (XtActionProc) addr;
3631 (proc)(NULL, NULL, NULL, NULL);
3634 void CreateMenuBarPopup(parent, name, mb)
3644 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3647 XtSetArg(args[j], XtNleftMargin, 20); j++;
3648 XtSetArg(args[j], XtNrightMargin, 20); j++;
3650 while (mi->string != NULL) {
3651 if (strcmp(mi->string, "----") == 0) {
3652 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3655 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3656 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3658 XtAddCallback(entry, XtNcallback,
3659 (XtCallbackProc) MenuBarSelect,
3660 (caddr_t) mi->proc);
3666 Widget CreateMenuBar(mb)
3670 Widget anchor, menuBar;
3672 char menuName[MSG_SIZ];
3675 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3676 XtSetArg(args[j], XtNvSpace, 0); j++;
3677 XtSetArg(args[j], XtNborderWidth, 0); j++;
3678 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3679 formWidget, args, j);
3681 while (mb->name != NULL) {
3682 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3683 strcat(menuName, mb->name);
3685 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3688 shortName[0] = _(mb->name)[0];
3689 shortName[1] = NULLCHAR;
3690 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3693 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3696 XtSetArg(args[j], XtNborderWidth, 0); j++;
3697 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3699 CreateMenuBarPopup(menuBar, menuName, mb);
3705 Widget CreateButtonBar(mi)
3709 Widget button, buttonBar;
3713 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3715 XtSetArg(args[j], XtNhSpace, 0); j++;
3717 XtSetArg(args[j], XtNborderWidth, 0); j++;
3718 XtSetArg(args[j], XtNvSpace, 0); j++;
3719 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3720 formWidget, args, j);
3722 while (mi->string != NULL) {
3725 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3726 XtSetArg(args[j], XtNborderWidth, 0); j++;
3728 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3729 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3730 buttonBar, args, j);
3731 XtAddCallback(button, XtNcallback,
3732 (XtCallbackProc) MenuBarSelect,
3733 (caddr_t) mi->proc);
3740 CreatePieceMenu(name, color)
3747 ChessSquare selection;
3749 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3750 boardWidget, args, 0);
3752 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3753 String item = pieceMenuStrings[color][i];
3755 if (strcmp(item, "----") == 0) {
3756 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3759 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3760 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3762 selection = pieceMenuTranslation[color][i];
3763 XtAddCallback(entry, XtNcallback,
3764 (XtCallbackProc) PieceMenuSelect,
3765 (caddr_t) selection);
3766 if (selection == WhitePawn || selection == BlackPawn) {
3767 XtSetArg(args[0], XtNpopupOnEntry, entry);
3768 XtSetValues(menu, args, 1);
3781 ChessSquare selection;
3783 whitePieceMenu = CreatePieceMenu("menuW", 0);
3784 blackPieceMenu = CreatePieceMenu("menuB", 1);
3786 XtRegisterGrabAction(PieceMenuPopup, True,
3787 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3788 GrabModeAsync, GrabModeAsync);
3790 XtSetArg(args[0], XtNlabel, _("Drop"));
3791 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3792 boardWidget, args, 1);
3793 for (i = 0; i < DROP_MENU_SIZE; i++) {
3794 String item = dropMenuStrings[i];
3796 if (strcmp(item, "----") == 0) {
3797 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3800 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3801 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3803 selection = dropMenuTranslation[i];
3804 XtAddCallback(entry, XtNcallback,
3805 (XtCallbackProc) DropMenuSelect,
3806 (caddr_t) selection);
3811 void SetupDropMenu()
3819 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3820 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3821 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3822 dmEnables[i].piece);
3823 XtSetSensitive(entry, p != NULL || !appData.testLegality
3824 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3825 && !appData.icsActive));
3827 while (p && *p++ == dmEnables[i].piece) count++;
3828 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3830 XtSetArg(args[j], XtNlabel, label); j++;
3831 XtSetValues(entry, args, j);
3835 void PieceMenuPopup(w, event, params, num_params)
3839 Cardinal *num_params;
3841 String whichMenu; int menuNr;
3842 if (event->type == ButtonRelease)
3843 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3844 else if (event->type == ButtonPress)
3845 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3847 case 0: whichMenu = params[0]; break;
3848 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3850 case -1: if (errorUp) ErrorPopDown();
3853 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3856 static void PieceMenuSelect(w, piece, junk)
3861 if (pmFromX < 0 || pmFromY < 0) return;
3862 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3865 static void DropMenuSelect(w, piece, junk)
3870 if (pmFromX < 0 || pmFromY < 0) return;
3871 DropMenuEvent(piece, pmFromX, pmFromY);
3874 void WhiteClock(w, event, prms, nprms)
3880 if (gameMode == EditPosition || gameMode == IcsExamining) {
3881 SetWhiteToPlayEvent();
3882 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3887 void BlackClock(w, event, prms, nprms)
3893 if (gameMode == EditPosition || gameMode == IcsExamining) {
3894 SetBlackToPlayEvent();
3895 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3902 * If the user selects on a border boundary, return -1; if off the board,
3903 * return -2. Otherwise map the event coordinate to the square.
3905 int EventToSquare(x, limit)
3913 if ((x % (squareSize + lineGap)) >= squareSize)
3915 x /= (squareSize + lineGap);
3921 static void do_flash_delay(msec)
3927 static void drawHighlight(file, rank, gc)
3933 if (lineGap == 0 || appData.blindfold) return;
3936 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3937 (squareSize + lineGap);
3938 y = lineGap/2 + rank * (squareSize + lineGap);
3940 x = lineGap/2 + file * (squareSize + lineGap);
3941 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3942 (squareSize + lineGap);
3945 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3946 squareSize+lineGap, squareSize+lineGap);
3949 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3950 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3953 SetHighlights(fromX, fromY, toX, toY)
3954 int fromX, fromY, toX, toY;
3956 if (hi1X != fromX || hi1Y != fromY) {
3957 if (hi1X >= 0 && hi1Y >= 0) {
3958 drawHighlight(hi1X, hi1Y, lineGC);
3960 } // [HGM] first erase both, then draw new!
3961 if (hi2X != toX || hi2Y != toY) {
3962 if (hi2X >= 0 && hi2Y >= 0) {
3963 drawHighlight(hi2X, hi2Y, lineGC);
3966 if (hi1X != fromX || hi1Y != fromY) {
3967 if (fromX >= 0 && fromY >= 0) {
3968 drawHighlight(fromX, fromY, highlineGC);
3971 if (hi2X != toX || hi2Y != toY) {
3972 if (toX >= 0 && toY >= 0) {
3973 drawHighlight(toX, toY, highlineGC);
3985 SetHighlights(-1, -1, -1, -1);
3990 SetPremoveHighlights(fromX, fromY, toX, toY)
3991 int fromX, fromY, toX, toY;
3993 if (pm1X != fromX || pm1Y != fromY) {
3994 if (pm1X >= 0 && pm1Y >= 0) {
3995 drawHighlight(pm1X, pm1Y, lineGC);
3997 if (fromX >= 0 && fromY >= 0) {
3998 drawHighlight(fromX, fromY, prelineGC);
4001 if (pm2X != toX || pm2Y != toY) {
4002 if (pm2X >= 0 && pm2Y >= 0) {
4003 drawHighlight(pm2X, pm2Y, lineGC);
4005 if (toX >= 0 && toY >= 0) {
4006 drawHighlight(toX, toY, prelineGC);
4016 ClearPremoveHighlights()
4018 SetPremoveHighlights(-1, -1, -1, -1);
4021 static void BlankSquare(x, y, color, piece, dest)
4026 if (useImages && useImageSqs) {
4030 pm = xpmLightSquare;
4035 case 2: /* neutral */
4040 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4041 squareSize, squareSize, x, y);
4051 case 2: /* neutral */
4056 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4061 I split out the routines to draw a piece so that I could
4062 make a generic flash routine.
4064 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4066 int square_color, x, y;
4069 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4070 switch (square_color) {
4072 case 2: /* neutral */
4074 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4075 ? *pieceToOutline(piece)
4076 : *pieceToSolid(piece),
4077 dest, bwPieceGC, 0, 0,
4078 squareSize, squareSize, x, y);
4081 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4082 ? *pieceToSolid(piece)
4083 : *pieceToOutline(piece),
4084 dest, wbPieceGC, 0, 0,
4085 squareSize, squareSize, x, y);
4090 static void monoDrawPiece(piece, square_color, x, y, dest)
4092 int square_color, x, y;
4095 switch (square_color) {
4097 case 2: /* neutral */
4099 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4100 ? *pieceToOutline(piece)
4101 : *pieceToSolid(piece),
4102 dest, bwPieceGC, 0, 0,
4103 squareSize, squareSize, x, y, 1);
4106 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4107 ? *pieceToSolid(piece)
4108 : *pieceToOutline(piece),
4109 dest, wbPieceGC, 0, 0,
4110 squareSize, squareSize, x, y, 1);
4115 static void colorDrawPiece(piece, square_color, x, y, dest)
4117 int square_color, x, y;
4120 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4121 switch (square_color) {
4123 XCopyPlane(xDisplay, *pieceToSolid(piece),
4124 dest, (int) piece < (int) BlackPawn
4125 ? wlPieceGC : blPieceGC, 0, 0,
4126 squareSize, squareSize, x, y, 1);
4129 XCopyPlane(xDisplay, *pieceToSolid(piece),
4130 dest, (int) piece < (int) BlackPawn
4131 ? wdPieceGC : bdPieceGC, 0, 0,
4132 squareSize, squareSize, x, y, 1);
4134 case 2: /* neutral */
4136 XCopyPlane(xDisplay, *pieceToSolid(piece),
4137 dest, (int) piece < (int) BlackPawn
4138 ? wjPieceGC : bjPieceGC, 0, 0,
4139 squareSize, squareSize, x, y, 1);
4144 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4146 int square_color, x, y;
4151 switch (square_color) {
4153 case 2: /* neutral */
4155 if ((int)piece < (int) BlackPawn) {
4163 if ((int)piece < (int) BlackPawn) {
4171 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4172 dest, wlPieceGC, 0, 0,
4173 squareSize, squareSize, x, y);
4176 typedef void (*DrawFunc)();
4178 DrawFunc ChooseDrawFunc()
4180 if (appData.monoMode) {
4181 if (DefaultDepth(xDisplay, xScreen) == 1) {
4182 return monoDrawPiece_1bit;
4184 return monoDrawPiece;
4188 return colorDrawPieceImage;
4190 return colorDrawPiece;
4194 /* [HR] determine square color depending on chess variant. */
4195 static int SquareColor(row, column)
4200 if (gameInfo.variant == VariantXiangqi) {
4201 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4203 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4205 } else if (row <= 4) {
4211 square_color = ((column + row) % 2) == 1;
4214 /* [hgm] holdings: next line makes all holdings squares light */
4215 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4217 return square_color;
4220 void DrawSquare(row, column, piece, do_flash)
4221 int row, column, do_flash;
4224 int square_color, x, y, direction, font_ascent, font_descent;
4227 XCharStruct overall;
4231 /* Calculate delay in milliseconds (2-delays per complete flash) */
4232 flash_delay = 500 / appData.flashRate;
4235 x = lineGap + ((BOARD_WIDTH-1)-column) *
4236 (squareSize + lineGap);
4237 y = lineGap + row * (squareSize + lineGap);
4239 x = lineGap + column * (squareSize + lineGap);
4240 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4241 (squareSize + lineGap);
4244 if(twoBoards && partnerUp) x += hOffset; // [HGM] dual: draw second board
4246 square_color = SquareColor(row, column);
4248 if ( // [HGM] holdings: blank out area between board and holdings
4249 column == BOARD_LEFT-1 || column == BOARD_RGHT
4250 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4251 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4252 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4254 // [HGM] print piece counts next to holdings
4255 string[1] = NULLCHAR;
4256 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4257 string[0] = '0' + piece;
4258 XTextExtents(countFontStruct, string, 1, &direction,
4259 &font_ascent, &font_descent, &overall);
4260 if (appData.monoMode) {
4261 XDrawImageString(xDisplay, xBoardWindow, countGC,
4262 x + squareSize - overall.width - 2,
4263 y + font_ascent + 1, string, 1);
4265 XDrawString(xDisplay, xBoardWindow, countGC,
4266 x + squareSize - overall.width - 2,