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
145 # if HAVE_LIBREADLINE /* add gnu-readline support */
146 #include <readline/readline.h>
147 #include <readline/history.h>
150 #include <X11/Intrinsic.h>
151 #include <X11/StringDefs.h>
152 #include <X11/Shell.h>
153 #include <X11/cursorfont.h>
154 #include <X11/Xatom.h>
155 #include <X11/Xmu/Atoms.h>
157 #include <X11/Xaw3d/Dialog.h>
158 #include <X11/Xaw3d/Form.h>
159 #include <X11/Xaw3d/List.h>
160 #include <X11/Xaw3d/Label.h>
161 #include <X11/Xaw3d/SimpleMenu.h>
162 #include <X11/Xaw3d/SmeBSB.h>
163 #include <X11/Xaw3d/SmeLine.h>
164 #include <X11/Xaw3d/Box.h>
165 #include <X11/Xaw3d/MenuButton.h>
166 #include <X11/Xaw3d/Text.h>
167 #include <X11/Xaw3d/AsciiText.h>
169 #include <X11/Xaw/Dialog.h>
170 #include <X11/Xaw/Form.h>
171 #include <X11/Xaw/List.h>
172 #include <X11/Xaw/Label.h>
173 #include <X11/Xaw/SimpleMenu.h>
174 #include <X11/Xaw/SmeBSB.h>
175 #include <X11/Xaw/SmeLine.h>
176 #include <X11/Xaw/Box.h>
177 #include <X11/Xaw/MenuButton.h>
178 #include <X11/Xaw/Text.h>
179 #include <X11/Xaw/AsciiText.h>
182 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
187 #include "pixmaps/pixmaps.h"
188 #define IMAGE_EXT "xpm"
190 #define IMAGE_EXT "xim"
191 #include "bitmaps/bitmaps.h"
194 #include "bitmaps/icon_white.bm"
195 #include "bitmaps/icon_black.bm"
196 #include "bitmaps/checkmark.bm"
198 #include "frontend.h"
200 #include "backendz.h"
204 #include "xgamelist.h"
205 #include "xhistory.h"
206 #include "xedittags.h"
209 // must be moved to xengineoutput.h
211 void EngineOutputProc P((Widget w, XEvent *event,
212 String *prms, Cardinal *nprms));
213 void EvalGraphProc P((Widget w, XEvent *event,
214 String *prms, Cardinal *nprms));
221 #define usleep(t) _sleep2(((t)+500)/1000)
225 # define _(s) gettext (s)
226 # define N_(s) gettext_noop (s)
242 int main P((int argc, char **argv));
243 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
244 char *init_path, char *mode, int (*show_entry)(), char **name_return));
245 RETSIGTYPE CmailSigHandler P((int sig));
246 RETSIGTYPE IntSigHandler P((int sig));
247 RETSIGTYPE TermSizeSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreateXPMBoard P((char *s, int n));
252 void CreatePieces P((void));
253 void CreatePieceMenus P((void));
254 Widget CreateMenuBar P((Menu *mb));
255 Widget CreateButtonBar P ((MenuItem *mi));
256 char *FindFont P((char *pattern, int targetPxlSize));
257 void PieceMenuPopup P((Widget w, XEvent *event,
258 String *params, Cardinal *num_params));
259 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
261 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
262 u_int wreq, u_int hreq));
263 void CreateGrid P((void));
264 int EventToSquare P((int x, int limit));
265 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
266 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
267 void HandleUserMove P((Widget w, XEvent *event,
268 String *prms, Cardinal *nprms));
269 void AnimateUserMove P((Widget w, XEvent * event,
270 String * params, Cardinal * nParams));
271 void HandlePV P((Widget w, XEvent * event,
272 String * params, Cardinal * nParams));
273 void SelectPV P((Widget w, XEvent * event,
274 String * params, Cardinal * nParams));
275 void StopPV P((Widget w, XEvent * event,
276 String * params, Cardinal * nParams));
277 void WhiteClock P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void BlackClock P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void DrawPositionProc P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
285 void CommentClick P((Widget w, XEvent * event,
286 String * params, Cardinal * nParams));
287 void CommentPopUp P((char *title, char *label));
288 void CommentPopDown P((void));
289 void CommentCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void ICSInputBoxPopUp P((void));
292 void ICSInputBoxPopDown P((void));
293 void FileNamePopUp P((char *label, char *def,
294 FileProc proc, char *openMode));
295 void FileNamePopDown P((void));
296 void FileNameCallback P((Widget w, XtPointer client_data,
297 XtPointer call_data));
298 void FileNameAction P((Widget w, XEvent *event,
299 String *prms, Cardinal *nprms));
300 void AskQuestionReplyAction P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void AskQuestionProc P((Widget w, XEvent *event,
303 String *prms, Cardinal *nprms));
304 void AskQuestionPopDown P((void));
305 void PromotionPopDown P((void));
306 void PromotionCallback P((Widget w, XtPointer client_data,
307 XtPointer call_data));
308 void EditCommentPopDown P((void));
309 void EditCommentCallback P((Widget w, XtPointer client_data,
310 XtPointer call_data));
311 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
312 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
316 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
318 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
320 void LoadPositionProc P((Widget w, XEvent *event,
321 String *prms, Cardinal *nprms));
322 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
324 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
326 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
328 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
330 void PastePositionProc P((Widget w, XEvent *event, String *prms,
332 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void SavePositionProc P((Widget w, XEvent *event,
336 String *prms, Cardinal *nprms));
337 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
340 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
344 void MachineWhiteProc P((Widget w, XEvent *event,
345 String *prms, Cardinal *nprms));
346 void AnalyzeModeProc P((Widget w, XEvent *event,
347 String *prms, Cardinal *nprms));
348 void AnalyzeFileProc P((Widget w, XEvent *event,
349 String *prms, Cardinal *nprms));
350 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
352 void IcsClientProc P((Widget w, XEvent *event, String *prms,
354 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void EditPositionProc P((Widget w, XEvent *event,
356 String *prms, Cardinal *nprms));
357 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void EditCommentProc P((Widget w, XEvent *event,
359 String *prms, Cardinal *nprms));
360 void IcsInputBoxProc P((Widget w, XEvent *event,
361 String *prms, Cardinal *nprms));
362 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void StopObservingProc P((Widget w, XEvent *event, String *prms,
378 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
380 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
387 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
389 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
391 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
394 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
396 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
398 void AutocommProc P((Widget w, XEvent *event, String *prms,
400 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void AutobsProc P((Widget w, XEvent *event, String *prms,
404 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
409 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
412 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
414 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
416 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
420 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
422 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
424 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
426 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
428 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
432 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
434 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
436 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
438 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
449 void DisplayMove P((int moveNumber));
450 void DisplayTitle P((char *title));
451 void ICSInitScript P((void));
452 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
453 void ErrorPopUp P((char *title, char *text, int modal));
454 void ErrorPopDown P((void));
455 static char *ExpandPathName P((char *path));
456 static void CreateAnimVars P((void));
457 static void DragPieceMove P((int x, int y));
458 static void DrawDragPiece P((void));
459 char *ModeToWidgetName P((GameMode mode));
460 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
467 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
468 void GameListOptionsPopDown P(());
469 void ShufflePopDown P(());
470 void EnginePopDown P(());
471 void UciPopDown P(());
472 void TimeControlPopDown P(());
473 void NewVariantPopDown P(());
474 void SettingsPopDown P(());
475 void update_ics_width P(());
476 int get_term_width P(());
477 int CopyMemoProc P(());
479 # if HAVE_LIBREADLINE /* add gnu-readline support */
480 static void ReadlineCompleteHandler P((char *));
484 * XBoard depends on Xt R4 or higher
486 int xtVersion = XtSpecificationRelease;
491 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
492 jailSquareColor, highlightSquareColor, premoveHighlightColor;
493 Pixel lowTimeWarningColor;
494 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
495 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
496 wjPieceGC, bjPieceGC, prelineGC, countGC;
497 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
498 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
499 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
500 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
501 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
502 ICSInputShell, fileNameShell, askQuestionShell;
503 Widget historyShell, evalGraphShell, gameListShell;
504 int hOffset; // [HGM] dual
505 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
506 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
507 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
508 Font clockFontID, coordFontID, countFontID;
509 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
510 XtAppContext appContext;
512 char *oldICSInteractionTitle;
516 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
518 # if HAVE_LIBREADLINE /* gnu readline support */
519 static char* readline_buffer;
520 static int readline_complete=0;
521 extern int sending_ICS_login;
522 extern int sending_ICS_password;
525 Position commentX = -1, commentY = -1;
526 Dimension commentW, commentH;
527 typedef unsigned int BoardSize;
529 Boolean chessProgram;
531 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
532 int squareSize, smallLayout = 0, tinyLayout = 0,
533 marginW, marginH, // [HGM] for run-time resizing
534 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
535 ICSInputBoxUp = False, askQuestionUp = False,
536 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
537 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
538 Pixel timerForegroundPixel, timerBackgroundPixel;
539 Pixel buttonForegroundPixel, buttonBackgroundPixel;
540 char *chessDir, *programName, *programVersion,
541 *gameCopyFilename, *gamePasteFilename;
542 Boolean alwaysOnTop = False;
543 Boolean saveSettingsOnExit;
544 char *settingsFileName;
545 char *icsTextMenuString;
547 char *firstChessProgramNames;
548 char *secondChessProgramNames;
550 WindowPlacement wpMain;
551 WindowPlacement wpConsole;
552 WindowPlacement wpComment;
553 WindowPlacement wpMoveHistory;
554 WindowPlacement wpEvalGraph;
555 WindowPlacement wpEngineOutput;
556 WindowPlacement wpGameList;
557 WindowPlacement wpTags;
561 Pixmap pieceBitmap[2][(int)BlackPawn];
562 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
563 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
564 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
565 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
566 Pixmap xpmBoardBitmap[2];
567 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
568 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
569 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
570 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
571 XImage *ximLightSquare, *ximDarkSquare;
574 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
575 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
577 #define White(piece) ((int)(piece) < (int)BlackPawn)
579 /* Variables for doing smooth animation. This whole thing
580 would be much easier if the board was double-buffered,
581 but that would require a fairly major rewrite. */
586 GC blitGC, pieceGC, outlineGC;
587 XPoint startSquare, prevFrame, mouseDelta;
591 int startBoardX, startBoardY;
594 /* There can be two pieces being animated at once: a player
595 can begin dragging a piece before the remote opponent has moved. */
597 static AnimState game, player;
599 /* Bitmaps for use as masks when drawing XPM pieces.
600 Need one for each black and white piece. */
601 static Pixmap xpmMask[BlackKing + 1];
603 /* This magic number is the number of intermediate frames used
604 in each half of the animation. For short moves it's reduced
605 by 1. The total number of frames will be factor * 2 + 1. */
608 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
610 MenuItem fileMenu[] = {
611 {N_("New Game"), ResetProc},
612 {N_("New Shuffle Game ..."), ShuffleMenuProc},
613 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
614 {"----", NothingProc},
615 {N_("Load Game"), LoadGameProc},
616 {N_("Load Next Game"), LoadNextGameProc},
617 {N_("Load Previous Game"), LoadPrevGameProc},
618 {N_("Reload Same Game"), ReloadGameProc},
619 {N_("Save Game"), SaveGameProc},
620 {"----", NothingProc},
621 {N_("Copy Game"), CopyGameProc},
622 {N_("Paste Game"), PasteGameProc},
623 {"----", NothingProc},
624 {N_("Load Position"), LoadPositionProc},
625 {N_("Load Next Position"), LoadNextPositionProc},
626 {N_("Load Previous Position"), LoadPrevPositionProc},
627 {N_("Reload Same Position"), ReloadPositionProc},
628 {N_("Save Position"), SavePositionProc},
629 {"----", NothingProc},
630 {N_("Copy Position"), CopyPositionProc},
631 {N_("Paste Position"), PastePositionProc},
632 {"----", NothingProc},
633 {N_("Mail Move"), MailMoveProc},
634 {N_("Reload CMail Message"), ReloadCmailMsgProc},
635 {"----", NothingProc},
636 {N_("Exit"), QuitProc},
640 MenuItem modeMenu[] = {
641 {N_("Machine White"), MachineWhiteProc},
642 {N_("Machine Black"), MachineBlackProc},
643 {N_("Two Machines"), TwoMachinesProc},
644 {N_("Analysis Mode"), AnalyzeModeProc},
645 {N_("Analyze File"), AnalyzeFileProc },
646 {N_("ICS Client"), IcsClientProc},
647 {N_("Edit Game"), EditGameProc},
648 {N_("Edit Position"), EditPositionProc},
649 {N_("Training"), TrainingProc},
650 {"----", NothingProc},
651 {N_("Show Engine Output"), EngineOutputProc},
652 {N_("Show Evaluation Graph"), EvalGraphProc},
653 {N_("Show Game List"), ShowGameListProc},
654 {N_("Show Move History"), HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
655 {"----", NothingProc},
656 {N_("Edit Tags"), EditTagsProc},
657 {N_("Edit Comment"), EditCommentProc},
658 {N_("ICS Input Box"), IcsInputBoxProc},
659 {N_("Pause"), PauseProc},
663 MenuItem actionMenu[] = {
664 {N_("Accept"), AcceptProc},
665 {N_("Decline"), DeclineProc},
666 {N_("Rematch"), RematchProc},
667 {"----", NothingProc},
668 {N_("Call Flag"), CallFlagProc},
669 {N_("Draw"), DrawProc},
670 {N_("Adjourn"), AdjournProc},
671 {N_("Abort"), AbortProc},
672 {N_("Resign"), ResignProc},
673 {"----", NothingProc},
674 {N_("Stop Observing"), StopObservingProc},
675 {N_("Stop Examining"), StopExaminingProc},
676 {N_("Upload to Examine"), UploadProc},
677 {"----", NothingProc},
678 {N_("Adjudicate to White"), AdjuWhiteProc},
679 {N_("Adjudicate to Black"), AdjuBlackProc},
680 {N_("Adjudicate Draw"), AdjuDrawProc},
684 MenuItem stepMenu[] = {
685 {N_("Backward"), BackwardProc},
686 {N_("Forward"), ForwardProc},
687 {N_("Back to Start"), ToStartProc},
688 {N_("Forward to End"), ToEndProc},
689 {N_("Revert"), RevertProc},
690 {N_("Annotate"), AnnotateProc},
691 {N_("Truncate Game"), TruncateGameProc},
692 {"----", NothingProc},
693 {N_("Move Now"), MoveNowProc},
694 {N_("Retract Move"), RetractMoveProc},
698 MenuItem optionsMenu[] = {
699 {N_("Flip View"), FlipViewProc},
700 {"----", NothingProc},
701 {N_("Adjudications ..."), EngineMenuProc},
702 {N_("General Settings ..."), UciMenuProc},
703 {N_("Engine #1 Settings ..."), FirstSettingsProc},
704 {N_("Engine #2 Settings ..."), SecondSettingsProc},
705 {N_("Time Control ..."), TimeControlProc},
706 {N_("Game List ..."), GameListOptionsPopUp},
707 {"----", NothingProc},
708 {N_("Always Queen"), AlwaysQueenProc},
709 {N_("Animate Dragging"), AnimateDraggingProc},
710 {N_("Animate Moving"), AnimateMovingProc},
711 {N_("Auto Comment"), AutocommProc},
712 {N_("Auto Flag"), AutoflagProc},
713 {N_("Auto Flip View"), AutoflipProc},
714 {N_("Auto Observe"), AutobsProc},
715 {N_("Auto Raise Board"), AutoraiseProc},
716 {N_("Auto Save"), AutosaveProc},
717 {N_("Blindfold"), BlindfoldProc},
718 {N_("Flash Moves"), FlashMovesProc},
719 {N_("Get Move List"), GetMoveListProc},
721 {N_("Highlight Dragging"), HighlightDraggingProc},
723 {N_("Highlight Last Move"), HighlightLastMoveProc},
724 {N_("Move Sound"), MoveSoundProc},
725 {N_("ICS Alarm"), IcsAlarmProc},
726 {N_("Old Save Style"), OldSaveStyleProc},
727 {N_("Periodic Updates"), PeriodicUpdatesProc},
728 {N_("Ponder Next Move"), PonderNextMoveProc},
729 {N_("Popup Exit Message"), PopupExitMessageProc},
730 {N_("Popup Move Errors"), PopupMoveErrorsProc},
731 {N_("Premove"), PremoveProc},
732 {N_("Quiet Play"), QuietPlayProc},
733 {N_("Show Coords"), ShowCoordsProc},
734 {N_("Hide Thinking"), HideThinkingProc},
735 {N_("Test Legality"), TestLegalityProc},
736 {"----", NothingProc},
737 {N_("Save Settings Now"), SaveSettingsProc},
738 {N_("Save Settings on Exit"), SaveOnExitProc},
742 MenuItem helpMenu[] = {
743 {N_("Info XBoard"), InfoProc},
744 {N_("Man XBoard"), ManProc},
745 {"----", NothingProc},
746 {N_("Hint"), HintProc},
747 {N_("Book"), BookProc},
748 {"----", NothingProc},
749 {N_("About XBoard"), AboutProc},
754 {N_("File"), fileMenu},
755 {N_("Mode"), modeMenu},
756 {N_("Action"), actionMenu},
757 {N_("Step"), stepMenu},
758 {N_("Options"), optionsMenu},
759 {N_("Help"), helpMenu},
763 #define PAUSE_BUTTON N_("P")
764 MenuItem buttonBar[] = {
767 {PAUSE_BUTTON, PauseProc},
773 #define PIECE_MENU_SIZE 18
774 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
775 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
776 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
777 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
778 N_("Empty square"), N_("Clear board") },
779 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
780 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
781 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
782 N_("Empty square"), N_("Clear board") }
784 /* must be in same order as PieceMenuStrings! */
785 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
786 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
787 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
788 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
789 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
790 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
791 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
792 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
793 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
796 #define DROP_MENU_SIZE 6
797 String dropMenuStrings[DROP_MENU_SIZE] = {
798 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
800 /* must be in same order as PieceMenuStrings! */
801 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
802 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
803 WhiteRook, WhiteQueen
811 DropMenuEnables dmEnables[] = {
829 { XtNborderWidth, 0 },
830 { XtNdefaultDistance, 0 },
834 { XtNborderWidth, 0 },
835 { XtNresizable, (XtArgVal) True },
839 { XtNborderWidth, 0 },
845 { XtNjustify, (XtArgVal) XtJustifyRight },
846 { XtNlabel, (XtArgVal) "..." },
847 { XtNresizable, (XtArgVal) True },
848 { XtNresize, (XtArgVal) False }
851 Arg messageArgs[] = {
852 { XtNjustify, (XtArgVal) XtJustifyLeft },
853 { XtNlabel, (XtArgVal) "..." },
854 { XtNresizable, (XtArgVal) True },
855 { XtNresize, (XtArgVal) False }
859 { XtNborderWidth, 0 },
860 { XtNjustify, (XtArgVal) XtJustifyLeft }
863 XtResource clientResources[] = {
864 { "flashCount", "flashCount", XtRInt, sizeof(int),
865 XtOffset(AppDataPtr, flashCount), XtRImmediate,
866 (XtPointer) FLASH_COUNT },
869 XrmOptionDescRec shellOptions[] = {
870 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
871 { "-flash", "flashCount", XrmoptionNoArg, "3" },
872 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
875 XtActionsRec boardActions[] = {
876 { "DrawPosition", DrawPositionProc },
877 { "HandleUserMove", HandleUserMove },
878 { "AnimateUserMove", AnimateUserMove },
879 { "HandlePV", HandlePV },
880 { "SelectPV", SelectPV },
881 { "StopPV", StopPV },
882 { "FileNameAction", FileNameAction },
883 { "AskQuestionProc", AskQuestionProc },
884 { "AskQuestionReplyAction", AskQuestionReplyAction },
885 { "PieceMenuPopup", PieceMenuPopup },
886 { "WhiteClock", WhiteClock },
887 { "BlackClock", BlackClock },
888 { "Iconify", Iconify },
889 { "ResetProc", ResetProc },
890 { "NewVariantProc", NewVariantProc },
891 { "LoadGameProc", LoadGameProc },
892 { "LoadNextGameProc", LoadNextGameProc },
893 { "LoadPrevGameProc", LoadPrevGameProc },
894 { "LoadSelectedProc", LoadSelectedProc },
895 { "SetFilterProc", SetFilterProc },
896 { "ReloadGameProc", ReloadGameProc },
897 { "LoadPositionProc", LoadPositionProc },
898 { "LoadNextPositionProc", LoadNextPositionProc },
899 { "LoadPrevPositionProc", LoadPrevPositionProc },
900 { "ReloadPositionProc", ReloadPositionProc },
901 { "CopyPositionProc", CopyPositionProc },
902 { "PastePositionProc", PastePositionProc },
903 { "CopyGameProc", CopyGameProc },
904 { "PasteGameProc", PasteGameProc },
905 { "SaveGameProc", SaveGameProc },
906 { "SavePositionProc", SavePositionProc },
907 { "MailMoveProc", MailMoveProc },
908 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
909 { "QuitProc", QuitProc },
910 { "MachineWhiteProc", MachineWhiteProc },
911 { "MachineBlackProc", MachineBlackProc },
912 { "AnalysisModeProc", AnalyzeModeProc },
913 { "AnalyzeFileProc", AnalyzeFileProc },
914 { "TwoMachinesProc", TwoMachinesProc },
915 { "IcsClientProc", IcsClientProc },
916 { "EditGameProc", EditGameProc },
917 { "EditPositionProc", EditPositionProc },
918 { "TrainingProc", EditPositionProc },
919 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
920 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
921 { "ShowGameListProc", ShowGameListProc },
922 { "ShowMoveListProc", HistoryShowProc},
923 { "EditTagsProc", EditCommentProc },
924 { "EditCommentProc", EditCommentProc },
925 { "IcsAlarmProc", IcsAlarmProc },
926 { "IcsInputBoxProc", IcsInputBoxProc },
927 { "PauseProc", PauseProc },
928 { "AcceptProc", AcceptProc },
929 { "DeclineProc", DeclineProc },
930 { "RematchProc", RematchProc },
931 { "CallFlagProc", CallFlagProc },
932 { "DrawProc", DrawProc },
933 { "AdjournProc", AdjournProc },
934 { "AbortProc", AbortProc },
935 { "ResignProc", ResignProc },
936 { "AdjuWhiteProc", AdjuWhiteProc },
937 { "AdjuBlackProc", AdjuBlackProc },
938 { "AdjuDrawProc", AdjuDrawProc },
939 { "EnterKeyProc", EnterKeyProc },
940 { "UpKeyProc", UpKeyProc },
941 { "DownKeyProc", DownKeyProc },
942 { "StopObservingProc", StopObservingProc },
943 { "StopExaminingProc", StopExaminingProc },
944 { "UploadProc", UploadProc },
945 { "BackwardProc", BackwardProc },
946 { "ForwardProc", ForwardProc },
947 { "ToStartProc", ToStartProc },
948 { "ToEndProc", ToEndProc },
949 { "RevertProc", RevertProc },
950 { "AnnotateProc", AnnotateProc },
951 { "TruncateGameProc", TruncateGameProc },
952 { "MoveNowProc", MoveNowProc },
953 { "RetractMoveProc", RetractMoveProc },
954 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
955 { "UciMenuProc", (XtActionProc) UciMenuProc },
956 { "TimeControlProc", (XtActionProc) TimeControlProc },
957 { "AlwaysQueenProc", AlwaysQueenProc },
958 { "AnimateDraggingProc", AnimateDraggingProc },
959 { "AnimateMovingProc", AnimateMovingProc },
960 { "AutoflagProc", AutoflagProc },
961 { "AutoflipProc", AutoflipProc },
962 { "AutobsProc", AutobsProc },
963 { "AutoraiseProc", AutoraiseProc },
964 { "AutosaveProc", AutosaveProc },
965 { "BlindfoldProc", BlindfoldProc },
966 { "FlashMovesProc", FlashMovesProc },
967 { "FlipViewProc", FlipViewProc },
968 { "GetMoveListProc", GetMoveListProc },
970 { "HighlightDraggingProc", HighlightDraggingProc },
972 { "HighlightLastMoveProc", HighlightLastMoveProc },
973 { "IcsAlarmProc", IcsAlarmProc },
974 { "MoveSoundProc", MoveSoundProc },
975 { "OldSaveStyleProc", OldSaveStyleProc },
976 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
977 { "PonderNextMoveProc", PonderNextMoveProc },
978 { "PopupExitMessageProc", PopupExitMessageProc },
979 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
980 { "PremoveProc", PremoveProc },
981 { "QuietPlayProc", QuietPlayProc },
982 { "ShowCoordsProc", ShowCoordsProc },
983 { "ShowThinkingProc", ShowThinkingProc },
984 { "HideThinkingProc", HideThinkingProc },
985 { "TestLegalityProc", TestLegalityProc },
986 { "SaveSettingsProc", SaveSettingsProc },
987 { "SaveOnExitProc", SaveOnExitProc },
988 { "InfoProc", InfoProc },
989 { "ManProc", ManProc },
990 { "HintProc", HintProc },
991 { "BookProc", BookProc },
992 { "AboutGameProc", AboutGameProc },
993 { "AboutProc", AboutProc },
994 { "DebugProc", DebugProc },
995 { "NothingProc", NothingProc },
996 { "CommentClick", (XtActionProc) CommentClick },
997 { "CommentPopDown", (XtActionProc) CommentPopDown },
998 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
999 { "TagsPopDown", (XtActionProc) TagsPopDown },
1000 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1001 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1002 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1003 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1004 { "GameListPopDown", (XtActionProc) GameListPopDown },
1005 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1006 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1007 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1008 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1009 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1010 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1011 { "EnginePopDown", (XtActionProc) EnginePopDown },
1012 { "UciPopDown", (XtActionProc) UciPopDown },
1013 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1014 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1015 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1016 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1019 char globalTranslations[] =
1020 ":<Key>F9: ResignProc() \n \
1021 :Ctrl<Key>n: ResetProc() \n \
1022 :Meta<Key>V: NewVariantProc() \n \
1023 :Ctrl<Key>o: LoadGameProc() \n \
1024 :Meta<Key>Next: LoadNextGameProc() \n \
1025 :Meta<Key>Prior: LoadPrevGameProc() \n \
1026 :Ctrl<Key>s: SaveGameProc() \n \
1027 :Ctrl<Key>c: CopyGameProc() \n \
1028 :Ctrl<Key>v: PasteGameProc() \n \
1029 :Ctrl<Key>O: LoadPositionProc() \n \
1030 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1031 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1032 :Ctrl<Key>S: SavePositionProc() \n \
1033 :Ctrl<Key>C: CopyPositionProc() \n \
1034 :Ctrl<Key>V: PastePositionProc() \n \
1035 :Ctrl<Key>q: QuitProc() \n \
1036 :Ctrl<Key>w: MachineWhiteProc() \n \
1037 :Ctrl<Key>b: MachineBlackProc() \n \
1038 :Ctrl<Key>t: TwoMachinesProc() \n \
1039 :Ctrl<Key>a: AnalysisModeProc() \n \
1040 :Ctrl<Key>f: AnalyzeFileProc() \n \
1041 :Ctrl<Key>e: EditGameProc() \n \
1042 :Ctrl<Key>E: EditPositionProc() \n \
1043 :Meta<Key>O: EngineOutputProc() \n \
1044 :Meta<Key>E: EvalGraphProc() \n \
1045 :Meta<Key>G: ShowGameListProc() \n \
1046 :Meta<Key>H: ShowMoveListProc() \n \
1047 :<Key>Pause: PauseProc() \n \
1048 :<Key>F3: AcceptProc() \n \
1049 :<Key>F4: DeclineProc() \n \
1050 :<Key>F12: RematchProc() \n \
1051 :<Key>F5: CallFlagProc() \n \
1052 :<Key>F6: DrawProc() \n \
1053 :<Key>F7: AdjournProc() \n \
1054 :<Key>F8: AbortProc() \n \
1055 :<Key>F10: StopObservingProc() \n \
1056 :<Key>F11: StopExaminingProc() \n \
1057 :Meta Ctrl<Key>F12: DebugProc() \n \
1058 :Meta<Key>End: ToEndProc() \n \
1059 :Meta<Key>Right: ForwardProc() \n \
1060 :Meta<Key>Home: ToStartProc() \n \
1061 :Meta<Key>Left: BackwardProc() \n \
1062 :Ctrl<Key>m: MoveNowProc() \n \
1063 :Ctrl<Key>x: RetractMoveProc() \n \
1064 :Meta<Key>J: EngineMenuProc() \n \
1065 :Meta<Key>U: UciMenuProc() \n \
1066 :Meta<Key>T: TimeControlProc() \n \
1067 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1068 :Ctrl<Key>F: AutoflagProc() \n \
1069 :Ctrl<Key>A: AnimateMovingProc() \n \
1070 :Ctrl<Key>P: PonderNextMoveProc() \n \
1071 :Ctrl<Key>L: TestLegalityProc() \n \
1072 :Ctrl<Key>H: HideThinkingProc() \n \
1073 :<Key>-: Iconify() \n \
1074 :<Key>F1: ManProc() \n \
1075 :<Key>F2: FlipViewProc() \n \
1076 <KeyDown>.: BackwardProc() \n \
1077 <KeyUp>.: ForwardProc() \n \
1078 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1079 \"Send to chess program:\",,1) \n \
1080 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1081 \"Send to second chess program:\",,2) \n";
1083 char boardTranslations[] =
1084 "<Btn1Down>: HandleUserMove(0) \n \
1085 Shift<Btn1Up>: HandleUserMove(1) \n \
1086 <Btn1Up>: HandleUserMove(0) \n \
1087 <Btn1Motion>: AnimateUserMove() \n \
1088 <Btn3Motion>: HandlePV() \n \
1089 <Btn3Up>: PieceMenuPopup(menuB) \n \
1090 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1091 PieceMenuPopup(menuB) \n \
1092 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1093 PieceMenuPopup(menuW) \n \
1094 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1095 PieceMenuPopup(menuW) \n \
1096 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1097 PieceMenuPopup(menuB) \n";
1099 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1100 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1102 char ICSInputTranslations[] =
1103 "<Key>Up: UpKeyProc() \n "
1104 "<Key>Down: DownKeyProc() \n "
1105 "<Key>Return: EnterKeyProc() \n";
1107 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1108 // as the widget is destroyed before the up-click can call extend-end
1109 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1111 String xboardResources[] = {
1112 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1113 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1114 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1119 /* Max possible square size */
1120 #define MAXSQSIZE 256
1122 static int xpm_avail[MAXSQSIZE];
1124 #ifdef HAVE_DIR_STRUCT
1126 /* Extract piece size from filename */
1128 xpm_getsize(name, len, ext)
1139 if ((p=strchr(name, '.')) == NULL ||
1140 StrCaseCmp(p+1, ext) != 0)
1146 while (*p && isdigit(*p))
1153 /* Setup xpm_avail */
1155 xpm_getavail(dirname, ext)
1163 for (i=0; i<MAXSQSIZE; ++i)
1166 if (appData.debugMode)
1167 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1169 dir = opendir(dirname);
1172 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1173 programName, dirname);
1177 while ((ent=readdir(dir)) != NULL) {
1178 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1179 if (i > 0 && i < MAXSQSIZE)
1189 xpm_print_avail(fp, ext)
1195 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1196 for (i=1; i<MAXSQSIZE; ++i) {
1202 /* Return XPM piecesize closest to size */
1204 xpm_closest_to(dirname, size, ext)
1210 int sm_diff = MAXSQSIZE;
1214 xpm_getavail(dirname, ext);
1216 if (appData.debugMode)
1217 xpm_print_avail(stderr, ext);
1219 for (i=1; i<MAXSQSIZE; ++i) {
1222 diff = (diff<0) ? -diff : diff;
1223 if (diff < sm_diff) {
1231 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1237 #else /* !HAVE_DIR_STRUCT */
1238 /* If we are on a system without a DIR struct, we can't
1239 read the directory, so we can't collect a list of
1240 filenames, etc., so we can't do any size-fitting. */
1242 xpm_closest_to(dirname, size, ext)
1247 fprintf(stderr, _("\
1248 Warning: No DIR structure found on this system --\n\
1249 Unable to autosize for XPM/XIM pieces.\n\
1250 Please report this error to frankm@hiwaay.net.\n\
1251 Include system type & operating system in message.\n"));
1254 #endif /* HAVE_DIR_STRUCT */
1256 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1257 "magenta", "cyan", "white" };
1261 TextColors textColors[(int)NColorClasses];
1263 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1265 parse_color(str, which)
1269 char *p, buf[100], *d;
1272 if (strlen(str) > 99) /* watch bounds on buf */
1277 for (i=0; i<which; ++i) {
1284 /* Could be looking at something like:
1286 .. in which case we want to stop on a comma also */
1287 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1291 return -1; /* Use default for empty field */
1294 if (which == 2 || isdigit(*p))
1297 while (*p && isalpha(*p))
1302 for (i=0; i<8; ++i) {
1303 if (!StrCaseCmp(buf, cnames[i]))
1304 return which? (i+40) : (i+30);
1306 if (!StrCaseCmp(buf, "default")) return -1;
1308 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1313 parse_cpair(cc, str)
1317 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1318 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1323 /* bg and attr are optional */
1324 textColors[(int)cc].bg = parse_color(str, 1);
1325 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1326 textColors[(int)cc].attr = 0;
1332 /* Arrange to catch delete-window events */
1333 Atom wm_delete_window;
1335 CatchDeleteWindow(Widget w, String procname)
1338 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1339 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1340 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1347 XtSetArg(args[0], XtNiconic, False);
1348 XtSetValues(shellWidget, args, 1);
1350 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1353 //---------------------------------------------------------------------------------------------------------
1354 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1357 #define CW_USEDEFAULT (1<<31)
1358 #define ICS_TEXT_MENU_SIZE 90
1359 #define DEBUG_FILE "xboard.debug"
1360 #define SetCurrentDirectory chdir
1361 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1365 // these two must some day move to frontend.h, when they are implemented
1366 Boolean GameListIsUp();
1368 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1371 // front-end part of option handling
1373 // [HGM] This platform-dependent table provides the location for storing the color info
1374 extern char *crWhite, * crBlack;
1378 &appData.whitePieceColor,
1379 &appData.blackPieceColor,
1380 &appData.lightSquareColor,
1381 &appData.darkSquareColor,
1382 &appData.highlightSquareColor,
1383 &appData.premoveHighlightColor,
1384 &appData.lowTimeWarningColor,
1395 // [HGM] font: keep a font for each square size, even non-stndard ones
1396 #define NUM_SIZES 18
1397 #define MAX_SIZE 130
1398 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1399 char *fontTable[NUM_FONTS][MAX_SIZE];
1402 ParseFont(char *name, int number)
1403 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1405 if(sscanf(name, "size%d:", &size)) {
1406 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1407 // defer processing it until we know if it matches our board size
1408 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1409 fontTable[number][size] = strdup(strchr(name, ':')+1);
1410 fontValid[number][size] = True;
1415 case 0: // CLOCK_FONT
1416 appData.clockFont = strdup(name);
1418 case 1: // MESSAGE_FONT
1419 appData.font = strdup(name);
1421 case 2: // COORD_FONT
1422 appData.coordFont = strdup(name);
1427 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1432 { // only 2 fonts currently
1433 appData.clockFont = CLOCK_FONT_NAME;
1434 appData.coordFont = COORD_FONT_NAME;
1435 appData.font = DEFAULT_FONT_NAME;
1440 { // no-op, until we identify the code for this already in XBoard and move it here
1444 ParseColor(int n, char *name)
1445 { // in XBoard, just copy the color-name string
1446 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1450 ParseTextAttribs(ColorClass cc, char *s)
1452 (&appData.colorShout)[cc] = strdup(s);
1456 ParseBoardSize(void *addr, char *name)
1458 appData.boardSize = strdup(name);
1463 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1467 SetCommPortDefaults()
1468 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1471 // [HGM] args: these three cases taken out to stay in front-end
1473 SaveFontArg(FILE *f, ArgDescriptor *ad)
1476 int i, n = (int)ad->argLoc;
1478 case 0: // CLOCK_FONT
1479 name = appData.clockFont;
1481 case 1: // MESSAGE_FONT
1482 name = appData.font;
1484 case 2: // COORD_FONT
1485 name = appData.coordFont;
1490 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1491 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1492 fontTable[n][squareSize] = strdup(name);
1493 fontValid[n][squareSize] = True;
1496 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1497 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1502 { // nothing to do, as the sounds are at all times represented by their text-string names already
1506 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1507 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1508 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1512 SaveColor(FILE *f, ArgDescriptor *ad)
1513 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1514 if(colorVariable[(int)ad->argLoc])
1515 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1519 SaveBoardSize(FILE *f, char *name, void *addr)
1520 { // wrapper to shield back-end from BoardSize & sizeInfo
1521 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1525 ParseCommPortSettings(char *s)
1526 { // no such option in XBoard (yet)
1529 extern Widget engineOutputShell;
1530 extern Widget tagsShell, editTagsShell;
1532 GetActualPlacement(Widget wg, WindowPlacement *wp)
1542 XtSetArg(args[i], XtNx, &x); i++;
1543 XtSetArg(args[i], XtNy, &y); i++;
1544 XtSetArg(args[i], XtNwidth, &w); i++;
1545 XtSetArg(args[i], XtNheight, &h); i++;
1546 XtGetValues(wg, args, i);
1555 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1556 // In XBoard this will have to wait until awareness of window parameters is implemented
1557 GetActualPlacement(shellWidget, &wpMain);
1558 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1559 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1560 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1561 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1562 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1563 else GetActualPlacement(editShell, &wpComment);
1564 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1565 else GetActualPlacement(editTagsShell, &wpTags);
1569 PrintCommPortSettings(FILE *f, char *name)
1570 { // This option does not exist in XBoard
1574 MySearchPath(char *installDir, char *name, char *fullname)
1575 { // just append installDir and name. Perhaps ExpandPath should be used here?
1576 name = ExpandPathName(name);
1577 if(name && name[0] == '/')
1578 safeStrCpy(fullname, name, MSG_SIZ );
1580 sprintf(fullname, "%s%c%s", installDir, '/', name);
1586 MyGetFullPathName(char *name, char *fullname)
1587 { // should use ExpandPath?
1588 name = ExpandPathName(name);
1589 safeStrCpy(fullname, name, MSG_SIZ );
1594 EnsureOnScreen(int *x, int *y, int minX, int minY)
1601 { // [HGM] args: allows testing if main window is realized from back-end
1602 return xBoardWindow != 0;
1606 PopUpStartupDialog()
1607 { // start menu not implemented in XBoard
1611 ConvertToLine(int argc, char **argv)
1613 static char line[128*1024], buf[1024];
1617 for(i=1; i<argc; i++)
1619 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1620 && argv[i][0] != '{' )
1621 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1623 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1624 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1627 line[strlen(line)-1] = NULLCHAR;
1631 //--------------------------------------------------------------------------------------------
1633 extern Boolean twoBoards, partnerUp;
1636 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1638 #define BoardSize int
1639 void InitDrawingSizes(BoardSize boardSize, int flags)
1640 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1641 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1643 XtGeometryResult gres;
1646 if(!formWidget) return;
1649 * Enable shell resizing.
1651 shellArgs[0].value = (XtArgVal) &w;
1652 shellArgs[1].value = (XtArgVal) &h;
1653 XtGetValues(shellWidget, shellArgs, 2);
1655 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1656 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1657 XtSetValues(shellWidget, &shellArgs[2], 4);
1659 XtSetArg(args[0], XtNdefaultDistance, &sep);
1660 XtGetValues(formWidget, args, 1);
1662 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1663 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1665 hOffset = boardWidth + 10;
1666 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1667 secondSegments[i] = gridSegments[i];
1668 secondSegments[i].x1 += hOffset;
1669 secondSegments[i].x2 += hOffset;
1672 XtSetArg(args[0], XtNwidth, boardWidth);
1673 XtSetArg(args[1], XtNheight, boardHeight);
1674 XtSetValues(boardWidget, args, 2);
1676 timerWidth = (boardWidth - sep) / 2;
1677 XtSetArg(args[0], XtNwidth, timerWidth);
1678 XtSetValues(whiteTimerWidget, args, 1);
1679 XtSetValues(blackTimerWidget, args, 1);
1681 XawFormDoLayout(formWidget, False);
1683 if (appData.titleInWindow) {
1685 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1686 XtSetArg(args[i], XtNheight, &h); i++;
1687 XtGetValues(titleWidget, args, i);
1689 w = boardWidth - 2*bor;
1691 XtSetArg(args[0], XtNwidth, &w);
1692 XtGetValues(menuBarWidget, args, 1);
1693 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1696 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1697 if (gres != XtGeometryYes && appData.debugMode) {
1699 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1700 programName, gres, w, h, wr, hr);
1704 XawFormDoLayout(formWidget, True);
1707 * Inhibit shell resizing.
1709 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1710 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1711 shellArgs[4].value = shellArgs[2].value = w;
1712 shellArgs[5].value = shellArgs[3].value = h;
1713 XtSetValues(shellWidget, &shellArgs[0], 6);
1715 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1718 for(i=0; i<4; i++) {
1720 for(p=0; p<=(int)WhiteKing; p++)
1721 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1722 if(gameInfo.variant == VariantShogi) {
1723 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1724 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1725 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1726 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1727 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1730 if(gameInfo.variant == VariantGothic) {
1731 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1735 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1736 for(p=0; p<=(int)WhiteKing; p++)
1737 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1738 if(gameInfo.variant == VariantShogi) {
1739 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1740 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1741 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1742 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1743 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1746 if(gameInfo.variant == VariantGothic) {
1747 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1753 for(i=0; i<2; i++) {
1755 for(p=0; p<=(int)WhiteKing; p++)
1756 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1757 if(gameInfo.variant == VariantShogi) {
1758 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1759 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1760 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1761 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1762 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1765 if(gameInfo.variant == VariantGothic) {
1766 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1782 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1783 XSetWindowAttributes window_attributes;
1785 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1786 XrmValue vFrom, vTo;
1787 XtGeometryResult gres;
1790 int forceMono = False;
1792 srandom(time(0)); // [HGM] book: make random truly random
1794 setbuf(stdout, NULL);
1795 setbuf(stderr, NULL);
1798 # if HAVE_LIBREADLINE
1799 /* install gnu-readline handler */
1800 rl_callback_handler_install("> ", ReadlineCompleteHandler);
1801 rl_readline_name="XBoard";
1804 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1805 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1809 programName = strrchr(argv[0], '/');
1810 if (programName == NULL)
1811 programName = argv[0];
1816 XtSetLanguageProc(NULL, NULL, NULL);
1817 bindtextdomain(PACKAGE, LOCALEDIR);
1818 textdomain(PACKAGE);
1822 XtAppInitialize(&appContext, "XBoard", shellOptions,
1823 XtNumber(shellOptions),
1824 &argc, argv, xboardResources, NULL, 0);
1825 appData.boardSize = "";
1826 InitAppData(ConvertToLine(argc, argv));
1828 if (p == NULL) p = "/tmp";
1829 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1830 gameCopyFilename = (char*) malloc(i);
1831 gamePasteFilename = (char*) malloc(i);
1832 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1833 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1835 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1836 clientResources, XtNumber(clientResources),
1839 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1840 static char buf[MSG_SIZ];
1841 EscapeExpand(buf, appData.initString);
1842 appData.initString = strdup(buf);
1843 EscapeExpand(buf, appData.secondInitString);
1844 appData.secondInitString = strdup(buf);
1845 EscapeExpand(buf, appData.firstComputerString);
1846 appData.firstComputerString = strdup(buf);
1847 EscapeExpand(buf, appData.secondComputerString);
1848 appData.secondComputerString = strdup(buf);
1851 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1854 if (chdir(chessDir) != 0) {
1855 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1861 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1862 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1863 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1864 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1867 setbuf(debugFP, NULL);
1870 /* [HGM,HR] make sure board size is acceptable */
1871 if(appData.NrFiles > BOARD_FILES ||
1872 appData.NrRanks > BOARD_RANKS )
1873 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1876 /* This feature does not work; animation needs a rewrite */
1877 appData.highlightDragging = FALSE;
1881 xDisplay = XtDisplay(shellWidget);
1882 xScreen = DefaultScreen(xDisplay);
1883 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1885 gameInfo.variant = StringToVariant(appData.variant);
1886 InitPosition(FALSE);
1889 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1891 if (isdigit(appData.boardSize[0])) {
1892 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1893 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1894 &fontPxlSize, &smallLayout, &tinyLayout);
1896 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1897 programName, appData.boardSize);
1901 /* Find some defaults; use the nearest known size */
1902 SizeDefaults *szd, *nearest;
1903 int distance = 99999;
1904 nearest = szd = sizeDefaults;
1905 while (szd->name != NULL) {
1906 if (abs(szd->squareSize - squareSize) < distance) {
1908 distance = abs(szd->squareSize - squareSize);
1909 if (distance == 0) break;
1913 if (i < 2) lineGap = nearest->lineGap;
1914 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1915 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1916 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1917 if (i < 6) smallLayout = nearest->smallLayout;
1918 if (i < 7) tinyLayout = nearest->tinyLayout;
1921 SizeDefaults *szd = sizeDefaults;
1922 if (*appData.boardSize == NULLCHAR) {
1923 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1924 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1927 if (szd->name == NULL) szd--;
1928 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1930 while (szd->name != NULL &&
1931 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1932 if (szd->name == NULL) {
1933 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1934 programName, appData.boardSize);
1938 squareSize = szd->squareSize;
1939 lineGap = szd->lineGap;
1940 clockFontPxlSize = szd->clockFontPxlSize;
1941 coordFontPxlSize = szd->coordFontPxlSize;
1942 fontPxlSize = szd->fontPxlSize;
1943 smallLayout = szd->smallLayout;
1944 tinyLayout = szd->tinyLayout;
1945 // [HGM] font: use defaults from settings file if available and not overruled
1947 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1948 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1949 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1950 appData.font = fontTable[MESSAGE_FONT][squareSize];
1951 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1952 appData.coordFont = fontTable[COORD_FONT][squareSize];
1954 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1955 if (strlen(appData.pixmapDirectory) > 0) {
1956 p = ExpandPathName(appData.pixmapDirectory);
1958 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1959 appData.pixmapDirectory);
1962 if (appData.debugMode) {
1963 fprintf(stderr, _("\
1964 XBoard square size (hint): %d\n\
1965 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1967 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1968 if (appData.debugMode) {
1969 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1973 /* [HR] height treated separately (hacked) */
1974 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1975 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1976 if (appData.showJail == 1) {
1977 /* Jail on top and bottom */
1978 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1979 XtSetArg(boardArgs[2], XtNheight,
1980 boardHeight + 2*(lineGap + squareSize));
1981 } else if (appData.showJail == 2) {
1983 XtSetArg(boardArgs[1], XtNwidth,
1984 boardWidth + 2*(lineGap + squareSize));
1985 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1988 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1989 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1993 * Determine what fonts to use.
1995 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1996 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1997 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1998 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1999 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2000 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2001 appData.font = FindFont(appData.font, fontPxlSize);
2002 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2003 countFontStruct = XQueryFont(xDisplay, countFontID);
2004 // appData.font = FindFont(appData.font, fontPxlSize);
2006 xdb = XtDatabase(xDisplay);
2007 XrmPutStringResource(&xdb, "*font", appData.font);
2010 * Detect if there are not enough colors available and adapt.
2012 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2013 appData.monoMode = True;
2016 if (!appData.monoMode) {
2017 vFrom.addr = (caddr_t) appData.lightSquareColor;
2018 vFrom.size = strlen(appData.lightSquareColor);
2019 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2020 if (vTo.addr == NULL) {
2021 appData.monoMode = True;
2024 lightSquareColor = *(Pixel *) vTo.addr;
2027 if (!appData.monoMode) {
2028 vFrom.addr = (caddr_t) appData.darkSquareColor;
2029 vFrom.size = strlen(appData.darkSquareColor);
2030 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2031 if (vTo.addr == NULL) {
2032 appData.monoMode = True;
2035 darkSquareColor = *(Pixel *) vTo.addr;
2038 if (!appData.monoMode) {
2039 vFrom.addr = (caddr_t) appData.whitePieceColor;
2040 vFrom.size = strlen(appData.whitePieceColor);
2041 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2042 if (vTo.addr == NULL) {
2043 appData.monoMode = True;
2046 whitePieceColor = *(Pixel *) vTo.addr;
2049 if (!appData.monoMode) {
2050 vFrom.addr = (caddr_t) appData.blackPieceColor;
2051 vFrom.size = strlen(appData.blackPieceColor);
2052 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2053 if (vTo.addr == NULL) {
2054 appData.monoMode = True;
2057 blackPieceColor = *(Pixel *) vTo.addr;
2061 if (!appData.monoMode) {
2062 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2063 vFrom.size = strlen(appData.highlightSquareColor);
2064 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2065 if (vTo.addr == NULL) {
2066 appData.monoMode = True;
2069 highlightSquareColor = *(Pixel *) vTo.addr;
2073 if (!appData.monoMode) {
2074 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2075 vFrom.size = strlen(appData.premoveHighlightColor);
2076 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2077 if (vTo.addr == NULL) {
2078 appData.monoMode = True;
2081 premoveHighlightColor = *(Pixel *) vTo.addr;
2086 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2089 if (appData.bitmapDirectory == NULL ||
2090 appData.bitmapDirectory[0] == NULLCHAR)
2091 appData.bitmapDirectory = DEF_BITMAP_DIR;
2094 if (appData.lowTimeWarning && !appData.monoMode) {
2095 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2096 vFrom.size = strlen(appData.lowTimeWarningColor);
2097 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2098 if (vTo.addr == NULL)
2099 appData.monoMode = True;
2101 lowTimeWarningColor = *(Pixel *) vTo.addr;
2104 if (appData.monoMode && appData.debugMode) {
2105 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2106 (unsigned long) XWhitePixel(xDisplay, xScreen),
2107 (unsigned long) XBlackPixel(xDisplay, xScreen));
2110 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2111 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2112 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2113 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2114 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2115 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2116 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2117 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2118 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2119 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2121 if (appData.colorize) {
2123 _("%s: can't parse color names; disabling colorization\n"),
2126 appData.colorize = FALSE;
2128 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2129 textColors[ColorNone].attr = 0;
2131 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2137 layoutName = "tinyLayout";
2138 } else if (smallLayout) {
2139 layoutName = "smallLayout";
2141 layoutName = "normalLayout";
2143 /* Outer layoutWidget is there only to provide a name for use in
2144 resources that depend on the layout style */
2146 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2147 layoutArgs, XtNumber(layoutArgs));
2149 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2150 formArgs, XtNumber(formArgs));
2151 XtSetArg(args[0], XtNdefaultDistance, &sep);
2152 XtGetValues(formWidget, args, 1);
2155 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2156 XtSetArg(args[0], XtNtop, XtChainTop);
2157 XtSetArg(args[1], XtNbottom, XtChainTop);
2158 XtSetArg(args[2], XtNright, XtChainLeft);
2159 XtSetValues(menuBarWidget, args, 3);
2161 widgetList[j++] = whiteTimerWidget =
2162 XtCreateWidget("whiteTime", labelWidgetClass,
2163 formWidget, timerArgs, XtNumber(timerArgs));
2164 XtSetArg(args[0], XtNfont, clockFontStruct);
2165 XtSetArg(args[1], XtNtop, XtChainTop);
2166 XtSetArg(args[2], XtNbottom, XtChainTop);
2167 XtSetValues(whiteTimerWidget, args, 3);
2169 widgetList[j++] = blackTimerWidget =
2170 XtCreateWidget("blackTime", labelWidgetClass,
2171 formWidget, timerArgs, XtNumber(timerArgs));
2172 XtSetArg(args[0], XtNfont, clockFontStruct);
2173 XtSetArg(args[1], XtNtop, XtChainTop);
2174 XtSetArg(args[2], XtNbottom, XtChainTop);
2175 XtSetValues(blackTimerWidget, args, 3);
2177 if (appData.titleInWindow) {
2178 widgetList[j++] = titleWidget =
2179 XtCreateWidget("title", labelWidgetClass, formWidget,
2180 titleArgs, XtNumber(titleArgs));
2181 XtSetArg(args[0], XtNtop, XtChainTop);
2182 XtSetArg(args[1], XtNbottom, XtChainTop);
2183 XtSetValues(titleWidget, args, 2);
2186 if (appData.showButtonBar) {
2187 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2188 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2189 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2190 XtSetArg(args[2], XtNtop, XtChainTop);
2191 XtSetArg(args[3], XtNbottom, XtChainTop);
2192 XtSetValues(buttonBarWidget, args, 4);
2195 widgetList[j++] = messageWidget =
2196 XtCreateWidget("message", labelWidgetClass, formWidget,
2197 messageArgs, XtNumber(messageArgs));
2198 XtSetArg(args[0], XtNtop, XtChainTop);
2199 XtSetArg(args[1], XtNbottom, XtChainTop);
2200 XtSetValues(messageWidget, args, 2);
2202 widgetList[j++] = boardWidget =
2203 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2204 XtNumber(boardArgs));
2206 XtManageChildren(widgetList, j);
2208 timerWidth = (boardWidth - sep) / 2;
2209 XtSetArg(args[0], XtNwidth, timerWidth);
2210 XtSetValues(whiteTimerWidget, args, 1);
2211 XtSetValues(blackTimerWidget, args, 1);
2213 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2214 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2215 XtGetValues(whiteTimerWidget, args, 2);
2217 if (appData.showButtonBar) {
2218 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2219 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2220 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2224 * formWidget uses these constraints but they are stored
2228 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2229 XtSetValues(menuBarWidget, args, i);
2230 if (appData.titleInWindow) {
2233 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2234 XtSetValues(whiteTimerWidget, args, i);
2236 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2237 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2238 XtSetValues(blackTimerWidget, args, i);
2240 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2241 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2242 XtSetValues(titleWidget, args, i);
2244 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2245 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2246 XtSetValues(messageWidget, args, i);
2247 if (appData.showButtonBar) {
2249 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2250 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2251 XtSetValues(buttonBarWidget, args, i);
2255 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2256 XtSetValues(whiteTimerWidget, args, i);
2258 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2259 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2260 XtSetValues(blackTimerWidget, args, i);
2262 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2263 XtSetValues(titleWidget, args, i);
2265 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2266 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2267 XtSetValues(messageWidget, args, i);
2268 if (appData.showButtonBar) {
2270 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2271 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2272 XtSetValues(buttonBarWidget, args, i);
2277 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2278 XtSetValues(whiteTimerWidget, args, i);
2280 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2281 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2282 XtSetValues(blackTimerWidget, args, i);
2284 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2285 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2286 XtSetValues(messageWidget, args, i);
2287 if (appData.showButtonBar) {
2289 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2290 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2291 XtSetValues(buttonBarWidget, args, i);
2295 XtSetArg(args[0], XtNfromVert, messageWidget);
2296 XtSetArg(args[1], XtNtop, XtChainTop);
2297 XtSetArg(args[2], XtNbottom, XtChainBottom);
2298 XtSetArg(args[3], XtNleft, XtChainLeft);
2299 XtSetArg(args[4], XtNright, XtChainRight);
2300 XtSetValues(boardWidget, args, 5);
2302 XtRealizeWidget(shellWidget);
2305 XtSetArg(args[0], XtNx, wpMain.x);
2306 XtSetArg(args[1], XtNy, wpMain.y);
2307 XtSetValues(shellWidget, args, 2);
2311 * Correct the width of the message and title widgets.
2312 * It is not known why some systems need the extra fudge term.
2313 * The value "2" is probably larger than needed.
2315 XawFormDoLayout(formWidget, False);
2317 #define WIDTH_FUDGE 2
2319 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2320 XtSetArg(args[i], XtNheight, &h); i++;
2321 XtGetValues(messageWidget, args, i);
2322 if (appData.showButtonBar) {
2324 XtSetArg(args[i], XtNwidth, &w); i++;
2325 XtGetValues(buttonBarWidget, args, i);
2326 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2328 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2331 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2332 if (gres != XtGeometryYes && appData.debugMode) {
2333 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2334 programName, gres, w, h, wr, hr);
2337 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2338 /* The size used for the child widget in layout lags one resize behind
2339 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2341 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2342 if (gres != XtGeometryYes && appData.debugMode) {
2343 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2344 programName, gres, w, h, wr, hr);
2347 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2348 XtSetArg(args[1], XtNright, XtChainRight);
2349 XtSetValues(messageWidget, args, 2);
2351 if (appData.titleInWindow) {
2353 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2354 XtSetArg(args[i], XtNheight, &h); i++;
2355 XtGetValues(titleWidget, args, i);
2357 w = boardWidth - 2*bor;
2359 XtSetArg(args[0], XtNwidth, &w);
2360 XtGetValues(menuBarWidget, args, 1);
2361 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2364 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2365 if (gres != XtGeometryYes && appData.debugMode) {
2367 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2368 programName, gres, w, h, wr, hr);
2371 XawFormDoLayout(formWidget, True);
2373 xBoardWindow = XtWindow(boardWidget);
2375 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2376 // not need to go into InitDrawingSizes().
2380 * Create X checkmark bitmap and initialize option menu checks.
2382 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2383 checkmark_bits, checkmark_width, checkmark_height);
2384 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2385 if (appData.alwaysPromoteToQueen) {
2386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2389 if (appData.animateDragging) {
2390 XtSetValues(XtNameToWidget(menuBarWidget,
2391 "menuOptions.Animate Dragging"),
2394 if (appData.animate) {
2395 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2398 if (appData.autoComment) {
2399 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2402 if (appData.autoCallFlag) {
2403 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2406 if (appData.autoFlipView) {
2407 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2410 if (appData.autoObserve) {
2411 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2414 if (appData.autoRaiseBoard) {
2415 XtSetValues(XtNameToWidget(menuBarWidget,
2416 "menuOptions.Auto Raise Board"), args, 1);
2418 if (appData.autoSaveGames) {
2419 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2422 if (appData.saveGameFile[0] != NULLCHAR) {
2423 /* Can't turn this off from menu */
2424 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2426 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2430 if (appData.blindfold) {
2431 XtSetValues(XtNameToWidget(menuBarWidget,
2432 "menuOptions.Blindfold"), args, 1);
2434 if (appData.flashCount > 0) {
2435 XtSetValues(XtNameToWidget(menuBarWidget,
2436 "menuOptions.Flash Moves"),
2439 if (appData.getMoveList) {
2440 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2444 if (appData.highlightDragging) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Highlight Dragging"),
2450 if (appData.highlightLastMove) {
2451 XtSetValues(XtNameToWidget(menuBarWidget,
2452 "menuOptions.Highlight Last Move"),
2455 if (appData.icsAlarm) {
2456 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2459 if (appData.ringBellAfterMoves) {
2460 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2463 if (appData.oldSaveStyle) {
2464 XtSetValues(XtNameToWidget(menuBarWidget,
2465 "menuOptions.Old Save Style"), args, 1);
2467 if (appData.periodicUpdates) {
2468 XtSetValues(XtNameToWidget(menuBarWidget,
2469 "menuOptions.Periodic Updates"), args, 1);
2471 if (appData.ponderNextMove) {
2472 XtSetValues(XtNameToWidget(menuBarWidget,
2473 "menuOptions.Ponder Next Move"), args, 1);
2475 if (appData.popupExitMessage) {
2476 XtSetValues(XtNameToWidget(menuBarWidget,
2477 "menuOptions.Popup Exit Message"), args, 1);
2479 if (appData.popupMoveErrors) {
2480 XtSetValues(XtNameToWidget(menuBarWidget,
2481 "menuOptions.Popup Move Errors"), args, 1);
2483 if (appData.premove) {
2484 XtSetValues(XtNameToWidget(menuBarWidget,
2485 "menuOptions.Premove"), args, 1);
2487 if (appData.quietPlay) {
2488 XtSetValues(XtNameToWidget(menuBarWidget,
2489 "menuOptions.Quiet Play"), args, 1);
2491 if (appData.showCoords) {
2492 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2495 if (appData.hideThinkingFromHuman) {
2496 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2499 if (appData.testLegality) {
2500 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2503 if (saveSettingsOnExit) {
2504 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2511 ReadBitmap(&wIconPixmap, "icon_white.bm",
2512 icon_white_bits, icon_white_width, icon_white_height);
2513 ReadBitmap(&bIconPixmap, "icon_black.bm",
2514 icon_black_bits, icon_black_width, icon_black_height);
2515 iconPixmap = wIconPixmap;
2517 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2518 XtSetValues(shellWidget, args, i);
2521 * Create a cursor for the board widget.
2523 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2524 XChangeWindowAttributes(xDisplay, xBoardWindow,
2525 CWCursor, &window_attributes);
2528 * Inhibit shell resizing.
2530 shellArgs[0].value = (XtArgVal) &w;
2531 shellArgs[1].value = (XtArgVal) &h;
2532 XtGetValues(shellWidget, shellArgs, 2);
2533 shellArgs[4].value = shellArgs[2].value = w;
2534 shellArgs[5].value = shellArgs[3].value = h;
2535 XtSetValues(shellWidget, &shellArgs[2], 4);
2536 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2537 marginH = h - boardHeight;
2539 CatchDeleteWindow(shellWidget, "QuitProc");
2544 if (appData.bitmapDirectory[0] != NULLCHAR) {
2548 CreateXPMBoard(appData.liteBackTextureFile, 1);
2549 CreateXPMBoard(appData.darkBackTextureFile, 0);
2553 /* Create regular pieces */
2554 if (!useImages) CreatePieces();
2559 if (appData.animate || appData.animateDragging)
2562 XtAugmentTranslations(formWidget,
2563 XtParseTranslationTable(globalTranslations));
2564 XtAugmentTranslations(boardWidget,
2565 XtParseTranslationTable(boardTranslations));
2566 XtAugmentTranslations(whiteTimerWidget,
2567 XtParseTranslationTable(whiteTranslations));
2568 XtAugmentTranslations(blackTimerWidget,
2569 XtParseTranslationTable(blackTranslations));
2571 /* Why is the following needed on some versions of X instead
2572 * of a translation? */
2573 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2574 (XtEventHandler) EventProc, NULL);
2577 /* [AS] Restore layout */
2578 if( wpMoveHistory.visible ) {
2582 if( wpEvalGraph.visible )
2587 if( wpEngineOutput.visible ) {
2588 EngineOutputPopUp();
2593 if (errorExitStatus == -1) {
2594 if (appData.icsActive) {
2595 /* We now wait until we see "login:" from the ICS before
2596 sending the logon script (problems with timestamp otherwise) */
2597 /*ICSInitScript();*/
2598 if (appData.icsInputBox) ICSInputBoxPopUp();
2602 signal(SIGWINCH, TermSizeSigHandler);
2604 signal(SIGINT, IntSigHandler);
2605 signal(SIGTERM, IntSigHandler);
2606 if (*appData.cmailGameName != NULLCHAR) {
2607 signal(SIGUSR1, CmailSigHandler);
2610 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2612 XtSetKeyboardFocus(shellWidget, formWidget);
2614 XtAppMainLoop(appContext);
2615 if (appData.debugMode) fclose(debugFP); // [DM] debug
2622 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2623 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2625 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2626 unlink(gameCopyFilename);
2627 unlink(gamePasteFilename);
2629 # if HAVE_LIBREADLINE
2630 /* remove gnu-readline handler. */
2631 rl_callback_handler_remove();
2637 RETSIGTYPE TermSizeSigHandler(int sig)
2650 CmailSigHandler(sig)
2656 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2658 /* Activate call-back function CmailSigHandlerCallBack() */
2659 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2661 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2665 CmailSigHandlerCallBack(isr, closure, message, count, error)
2673 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2675 /**** end signal code ****/
2681 /* try to open the icsLogon script, either in the location given
2682 * or in the users HOME directory
2689 f = fopen(appData.icsLogon, "r");
2692 homedir = getenv("HOME");
2693 if (homedir != NULL)
2695 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2696 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2697 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2698 f = fopen(buf, "r");
2703 ProcessICSInitScript(f);
2705 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2714 EditCommentPopDown();
2729 if (!menuBarWidget) return;
2730 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2732 DisplayError("menuStep.Revert", 0);
2734 XtSetSensitive(w, !grey);
2736 w = XtNameToWidget(menuBarWidget, "menuStep.Annotate");
2738 DisplayError("menuStep.Annotate", 0);
2740 XtSetSensitive(w, !grey);
2745 SetMenuEnables(enab)
2749 if (!menuBarWidget) return;
2750 while (enab->name != NULL) {
2751 w = XtNameToWidget(menuBarWidget, enab->name);
2753 DisplayError(enab->name, 0);
2755 XtSetSensitive(w, enab->value);
2761 Enables icsEnables[] = {
2762 { "menuFile.Mail Move", False },
2763 { "menuFile.Reload CMail Message", False },
2764 { "menuMode.Machine Black", False },
2765 { "menuMode.Machine White", False },
2766 { "menuMode.Analysis Mode", False },
2767 { "menuMode.Analyze File", False },
2768 { "menuMode.Two Machines", False },
2770 { "menuHelp.Hint", False },
2771 { "menuHelp.Book", False },
2772 { "menuStep.Move Now", False },
2773 { "menuOptions.Periodic Updates", False },
2774 { "menuOptions.Hide Thinking", False },
2775 { "menuOptions.Ponder Next Move", False },
2777 { "menuStep.Annotate", False },
2781 Enables ncpEnables[] = {
2782 { "menuFile.Mail Move", False },
2783 { "menuFile.Reload CMail Message", False },
2784 { "menuMode.Machine White", False },
2785 { "menuMode.Machine Black", False },
2786 { "menuMode.Analysis Mode", False },
2787 { "menuMode.Analyze File", False },
2788 { "menuMode.Two Machines", False },
2789 { "menuMode.ICS Client", False },
2790 { "menuMode.ICS Input Box", False },
2791 { "Action", False },
2792 { "menuStep.Revert", False },
2793 { "menuStep.Annotate", False },
2794 { "menuStep.Move Now", False },
2795 { "menuStep.Retract Move", False },
2796 { "menuOptions.Auto Comment", False },
2797 { "menuOptions.Auto Flag", False },
2798 { "menuOptions.Auto Flip View", False },
2799 { "menuOptions.Auto Observe", False },
2800 { "menuOptions.Auto Raise Board", False },
2801 { "menuOptions.Get Move List", False },
2802 { "menuOptions.ICS Alarm", False },
2803 { "menuOptions.Move Sound", False },
2804 { "menuOptions.Quiet Play", False },
2805 { "menuOptions.Hide Thinking", False },
2806 { "menuOptions.Periodic Updates", False },
2807 { "menuOptions.Ponder Next Move", False },
2808 { "menuHelp.Hint", False },
2809 { "menuHelp.Book", False },
2813 Enables gnuEnables[] = {
2814 { "menuMode.ICS Client", False },
2815 { "menuMode.ICS Input Box", False },
2816 { "menuAction.Accept", False },
2817 { "menuAction.Decline", False },
2818 { "menuAction.Rematch", False },
2819 { "menuAction.Adjourn", False },
2820 { "menuAction.Stop Examining", False },
2821 { "menuAction.Stop Observing", False },
2822 { "menuAction.Upload to Examine", False },
2823 { "menuStep.Revert", False },
2824 { "menuStep.Annotate", False },
2825 { "menuOptions.Auto Comment", False },
2826 { "menuOptions.Auto Observe", False },
2827 { "menuOptions.Auto Raise Board", False },
2828 { "menuOptions.Get Move List", False },
2829 { "menuOptions.Premove", False },
2830 { "menuOptions.Quiet Play", False },
2832 /* The next two options rely on SetCmailMode being called *after* */
2833 /* SetGNUMode so that when GNU is being used to give hints these */
2834 /* menu options are still available */
2836 { "menuFile.Mail Move", False },
2837 { "menuFile.Reload CMail Message", False },
2841 Enables cmailEnables[] = {
2843 { "menuAction.Call Flag", False },
2844 { "menuAction.Draw", True },
2845 { "menuAction.Adjourn", False },
2846 { "menuAction.Abort", False },
2847 { "menuAction.Stop Observing", False },
2848 { "menuAction.Stop Examining", False },
2849 { "menuFile.Mail Move", True },
2850 { "menuFile.Reload CMail Message", True },
2854 Enables trainingOnEnables[] = {
2855 { "menuMode.Edit Comment", False },
2856 { "menuMode.Pause", False },
2857 { "menuStep.Forward", False },
2858 { "menuStep.Backward", False },
2859 { "menuStep.Forward to End", False },
2860 { "menuStep.Back to Start", False },
2861 { "menuStep.Move Now", False },
2862 { "menuStep.Truncate Game", False },
2866 Enables trainingOffEnables[] = {
2867 { "menuMode.Edit Comment", True },
2868 { "menuMode.Pause", True },
2869 { "menuStep.Forward", True },
2870 { "menuStep.Backward", True },
2871 { "menuStep.Forward to End", True },
2872 { "menuStep.Back to Start", True },
2873 { "menuStep.Move Now", True },
2874 { "menuStep.Truncate Game", True },
2878 Enables machineThinkingEnables[] = {
2879 { "menuFile.Load Game", False },
2880 { "menuFile.Load Next Game", False },
2881 { "menuFile.Load Previous Game", False },
2882 { "menuFile.Reload Same Game", False },
2883 { "menuFile.Paste Game", False },
2884 { "menuFile.Load Position", False },
2885 { "menuFile.Load Next Position", False },
2886 { "menuFile.Load Previous Position", False },
2887 { "menuFile.Reload Same Position", False },
2888 { "menuFile.Paste Position", False },
2889 { "menuMode.Machine White", False },
2890 { "menuMode.Machine Black", False },
2891 { "menuMode.Two Machines", False },
2892 { "menuStep.Retract Move", False },
2896 Enables userThinkingEnables[] = {
2897 { "menuFile.Load Game", True },
2898 { "menuFile.Load Next Game", True },
2899 { "menuFile.Load Previous Game", True },
2900 { "menuFile.Reload Same Game", True },
2901 { "menuFile.Paste Game", True },
2902 { "menuFile.Load Position", True },
2903 { "menuFile.Load Next Position", True },
2904 { "menuFile.Load Previous Position", True },
2905 { "menuFile.Reload Same Position", True },
2906 { "menuFile.Paste Position", True },
2907 { "menuMode.Machine White", True },
2908 { "menuMode.Machine Black", True },
2909 { "menuMode.Two Machines", True },
2910 { "menuStep.Retract Move", True },
2916 SetMenuEnables(icsEnables);
2919 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2920 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2927 SetMenuEnables(ncpEnables);
2933 SetMenuEnables(gnuEnables);
2939 SetMenuEnables(cmailEnables);
2945 SetMenuEnables(trainingOnEnables);
2946 if (appData.showButtonBar) {
2947 XtSetSensitive(buttonBarWidget, False);
2953 SetTrainingModeOff()
2955 SetMenuEnables(trainingOffEnables);
2956 if (appData.showButtonBar) {
2957 XtSetSensitive(buttonBarWidget, True);
2962 SetUserThinkingEnables()
2964 if (appData.noChessProgram) return;
2965 SetMenuEnables(userThinkingEnables);
2969 SetMachineThinkingEnables()
2971 if (appData.noChessProgram) return;
2972 SetMenuEnables(machineThinkingEnables);
2974 case MachinePlaysBlack:
2975 case MachinePlaysWhite:
2976 case TwoMachinesPlay:
2977 XtSetSensitive(XtNameToWidget(menuBarWidget,
2978 ModeToWidgetName(gameMode)), True);
2985 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2986 #define HISTORY_SIZE 64
\r
2987 static char *history[HISTORY_SIZE];
\r
2988 int histIn = 0, histP = 0;
\r
2991 SaveInHistory(char *cmd)
\r
2993 if (history[histIn] != NULL) {
\r
2994 free(history[histIn]);
\r
2995 history[histIn] = NULL;
\r
2997 if (*cmd == NULLCHAR) return;
\r
2998 history[histIn] = StrSave(cmd);
\r
2999 histIn = (histIn + 1) % HISTORY_SIZE;
\r
3000 if (history[histIn] != NULL) {
\r
3001 free(history[histIn]);
\r
3002 history[histIn] = NULL;
\r
3008 PrevInHistory(char *cmd)
\r
3011 if (histP == histIn) {
\r
3012 if (history[histIn] != NULL) free(history[histIn]);
\r
3013 history[histIn] = StrSave(cmd);
\r
3015 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
3016 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
3018 return history[histP];
\r
3024 if (histP == histIn) return NULL;
\r
3025 histP = (histP + 1) % HISTORY_SIZE;
\r
3026 return history[histP];
\r
3028 // end of borrowed code
\r
3030 #define Abs(n) ((n)<0 ? -(n) : (n))
3033 * Find a font that matches "pattern" that is as close as
3034 * possible to the targetPxlSize. Prefer fonts that are k
3035 * pixels smaller to fonts that are k pixels larger. The
3036 * pattern must be in the X Consortium standard format,
3037 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3038 * The return value should be freed with XtFree when no
3042 FindFont(pattern, targetPxlSize)
3046 char **fonts, *p, *best, *scalable, *scalableTail;
3047 int i, j, nfonts, minerr, err, pxlSize;
3050 char **missing_list;
3052 char *def_string, *base_fnt_lst, strInt[3];
3054 XFontStruct **fnt_list;
3056 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3057 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3058 p = strstr(pattern, "--");
3059 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3060 strcat(base_fnt_lst, strInt);
3061 strcat(base_fnt_lst, strchr(p + 2, '-'));
3063 if ((fntSet = XCreateFontSet(xDisplay,
3067 &def_string)) == NULL) {
3069 fprintf(stderr, _("Unable to create font set.\n"));
3073 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3075 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3077 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3078 programName, pattern);
3086 for (i=0; i<nfonts; i++) {
3089 if (*p != '-') continue;
3091 if (*p == NULLCHAR) break;
3092 if (*p++ == '-') j++;
3094 if (j < 7) continue;
3097 scalable = fonts[i];
3100 err = pxlSize - targetPxlSize;
3101 if (Abs(err) < Abs(minerr) ||
3102 (minerr > 0 && err < 0 && -err == minerr)) {
3108 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3109 /* If the error is too big and there is a scalable font,
3110 use the scalable font. */
3111 int headlen = scalableTail - scalable;
3112 p = (char *) XtMalloc(strlen(scalable) + 10);
3113 while (isdigit(*scalableTail)) scalableTail++;
3114 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3116 p = (char *) XtMalloc(strlen(best) + 2);
3117 safeStrCpy(p, best, strlen(best)+1 );
3119 if (appData.debugMode) {
3120 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3121 pattern, targetPxlSize, p);
3124 if (missing_count > 0)
3125 XFreeStringList(missing_list);
3126 XFreeFontSet(xDisplay, fntSet);
3128 XFreeFontNames(fonts);
3135 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3136 | GCBackground | GCFunction | GCPlaneMask;
3137 XGCValues gc_values;
3140 gc_values.plane_mask = AllPlanes;
3141 gc_values.line_width = lineGap;
3142 gc_values.line_style = LineSolid;
3143 gc_values.function = GXcopy;
3145 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3146 gc_values.background = XBlackPixel(xDisplay, xScreen);
3147 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3149 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3150 gc_values.background = XWhitePixel(xDisplay, xScreen);
3151 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3152 XSetFont(xDisplay, coordGC, coordFontID);
3154 // [HGM] make font for holdings counts (white on black0
3155 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3156 gc_values.background = XBlackPixel(xDisplay, xScreen);
3157 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3158 XSetFont(xDisplay, countGC, countFontID);
3160 if (appData.monoMode) {
3161 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3162 gc_values.background = XWhitePixel(xDisplay, xScreen);
3163 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3165 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3166 gc_values.background = XBlackPixel(xDisplay, xScreen);
3167 lightSquareGC = wbPieceGC
3168 = XtGetGC(shellWidget, value_mask, &gc_values);
3170 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3171 gc_values.background = XWhitePixel(xDisplay, xScreen);
3172 darkSquareGC = bwPieceGC
3173 = XtGetGC(shellWidget, value_mask, &gc_values);
3175 if (DefaultDepth(xDisplay, xScreen) == 1) {
3176 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3177 gc_values.function = GXcopyInverted;
3178 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3179 gc_values.function = GXcopy;
3180 if (XBlackPixel(xDisplay, xScreen) == 1) {
3181 bwPieceGC = darkSquareGC;
3182 wbPieceGC = copyInvertedGC;
3184 bwPieceGC = copyInvertedGC;
3185 wbPieceGC = lightSquareGC;
3189 gc_values.foreground = highlightSquareColor;
3190 gc_values.background = highlightSquareColor;
3191 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3193 gc_values.foreground = premoveHighlightColor;
3194 gc_values.background = premoveHighlightColor;
3195 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3197 gc_values.foreground = lightSquareColor;
3198 gc_values.background = darkSquareColor;
3199 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3201 gc_values.foreground = darkSquareColor;
3202 gc_values.background = lightSquareColor;
3203 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3205 gc_values.foreground = jailSquareColor;
3206 gc_values.background = jailSquareColor;
3207 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3209 gc_values.foreground = whitePieceColor;
3210 gc_values.background = darkSquareColor;
3211 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3213 gc_values.foreground = whitePieceColor;
3214 gc_values.background = lightSquareColor;
3215 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3217 gc_values.foreground = whitePieceColor;
3218 gc_values.background = jailSquareColor;
3219 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3221 gc_values.foreground = blackPieceColor;
3222 gc_values.background = darkSquareColor;
3223 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3225 gc_values.foreground = blackPieceColor;
3226 gc_values.background = lightSquareColor;
3227 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3229 gc_values.foreground = blackPieceColor;
3230 gc_values.background = jailSquareColor;
3231 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3235 void loadXIM(xim, xmask, filename, dest, mask)
3248 fp = fopen(filename, "rb");
3250 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3257 for (y=0; y<h; ++y) {
3258 for (x=0; x<h; ++x) {
3263 XPutPixel(xim, x, y, blackPieceColor);
3265 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3268 XPutPixel(xim, x, y, darkSquareColor);
3270 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3273 XPutPixel(xim, x, y, whitePieceColor);
3275 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3278 XPutPixel(xim, x, y, lightSquareColor);
3280 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3286 /* create Pixmap of piece */
3287 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3289 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3292 /* create Pixmap of clipmask
3293 Note: We assume the white/black pieces have the same
3294 outline, so we make only 6 masks. This is okay
3295 since the XPM clipmask routines do the same. */
3297 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3299 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3302 /* now create the 1-bit version */
3303 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3306 values.foreground = 1;
3307 values.background = 0;
3309 /* Don't use XtGetGC, not read only */
3310 maskGC = XCreateGC(xDisplay, *mask,
3311 GCForeground | GCBackground, &values);
3312 XCopyPlane(xDisplay, temp, *mask, maskGC,
3313 0, 0, squareSize, squareSize, 0, 0, 1);
3314 XFreePixmap(xDisplay, temp);
3319 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3321 void CreateXIMPieces()
3326 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3331 /* The XSynchronize calls were copied from CreatePieces.
3332 Not sure if needed, but can't hurt */
3333 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3336 /* temp needed by loadXIM() */
3337 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3338 0, 0, ss, ss, AllPlanes, XYPixmap);
3340 if (strlen(appData.pixmapDirectory) == 0) {
3344 if (appData.monoMode) {
3345 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3349 fprintf(stderr, _("\nLoading XIMs...\n"));
3351 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3352 fprintf(stderr, "%d", piece+1);
3353 for (kind=0; kind<4; kind++) {
3354 fprintf(stderr, ".");
3355 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3356 ExpandPathName(appData.pixmapDirectory),
3357 piece <= (int) WhiteKing ? "" : "w",
3358 pieceBitmapNames[piece],
3360 ximPieceBitmap[kind][piece] =
3361 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3362 0, 0, ss, ss, AllPlanes, XYPixmap);
3363 if (appData.debugMode)
3364 fprintf(stderr, _("(File:%s:) "), buf);
3365 loadXIM(ximPieceBitmap[kind][piece],
3367 &(xpmPieceBitmap2[kind][piece]),
3368 &(ximMaskPm2[piece]));
3369 if(piece <= (int)WhiteKing)
3370 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3372 fprintf(stderr," ");
3374 /* Load light and dark squares */
3375 /* If the LSQ and DSQ pieces don't exist, we will
3376 draw them with solid squares. */
3377 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3378 if (access(buf, 0) != 0) {
3382 fprintf(stderr, _("light square "));
3384 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3385 0, 0, ss, ss, AllPlanes, XYPixmap);
3386 if (appData.debugMode)
3387 fprintf(stderr, _("(File:%s:) "), buf);
3389 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3390 fprintf(stderr, _("dark square "));
3391 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3392 ExpandPathName(appData.pixmapDirectory), ss);
3393 if (appData.debugMode)
3394 fprintf(stderr, _("(File:%s:) "), buf);
3396 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3397 0, 0, ss, ss, AllPlanes, XYPixmap);
3398 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3399 xpmJailSquare = xpmLightSquare;
3401 fprintf(stderr, _("Done.\n"));
3403 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3407 void CreateXPMBoard(char *s, int kind)
3411 if(s == NULL || *s == 0 || *s == '*') return;
3412 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3413 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3417 void CreateXPMPieces()
3421 u_int ss = squareSize;
3423 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3424 XpmColorSymbol symbols[4];
3426 /* The XSynchronize calls were copied from CreatePieces.
3427 Not sure if needed, but can't hurt */
3428 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3430 /* Setup translations so piece colors match square colors */
3431 symbols[0].name = "light_piece";
3432 symbols[0].value = appData.whitePieceColor;
3433 symbols[1].name = "dark_piece";
3434 symbols[1].value = appData.blackPieceColor;
3435 symbols[2].name = "light_square";
3436 symbols[2].value = appData.lightSquareColor;
3437 symbols[3].name = "dark_square";
3438 symbols[3].value = appData.darkSquareColor;
3440 attr.valuemask = XpmColorSymbols;
3441 attr.colorsymbols = symbols;
3442 attr.numsymbols = 4;
3444 if (appData.monoMode) {
3445 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3449 if (strlen(appData.pixmapDirectory) == 0) {
3450 XpmPieces* pieces = builtInXpms;
3453 while (pieces->size != squareSize && pieces->size) pieces++;
3454 if (!pieces->size) {
3455 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3458 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3459 for (kind=0; kind<4; kind++) {
3461 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3462 pieces->xpm[piece][kind],
3463 &(xpmPieceBitmap2[kind][piece]),
3464 NULL, &attr)) != 0) {
3465 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3469 if(piece <= (int) WhiteKing)
3470 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3474 xpmJailSquare = xpmLightSquare;
3478 fprintf(stderr, _("\nLoading XPMs...\n"));
3481 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3482 fprintf(stderr, "%d ", piece+1);
3483 for (kind=0; kind<4; kind++) {
3484 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3485 ExpandPathName(appData.pixmapDirectory),
3486 piece > (int) WhiteKing ? "w" : "",
3487 pieceBitmapNames[piece],
3489 if (appData.debugMode) {
3490 fprintf(stderr, _("(File:%s:) "), buf);
3492 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3493 &(xpmPieceBitmap2[kind][piece]),
3494 NULL, &attr)) != 0) {
3495 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3496 // [HGM] missing: read of unorthodox piece failed; substitute King.
3497 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3498 ExpandPathName(appData.pixmapDirectory),
3500 if (appData.debugMode) {
3501 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3503 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3504 &(xpmPieceBitmap2[kind][piece]),
3508 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3513 if(piece <= (int) WhiteKing)
3514 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3517 /* Load light and dark squares */
3518 /* If the LSQ and DSQ pieces don't exist, we will
3519 draw them with solid squares. */
3520 fprintf(stderr, _("light square "));
3521 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3522 if (access(buf, 0) != 0) {
3526 if (appData.debugMode)
3527 fprintf(stderr, _("(File:%s:) "), buf);
3529 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3530 &xpmLightSquare, NULL, &attr)) != 0) {
3531 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3534 fprintf(stderr, _("dark square "));
3535 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3536 ExpandPathName(appData.pixmapDirectory), ss);
3537 if (appData.debugMode) {
3538 fprintf(stderr, _("(File:%s:) "), buf);
3540 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3541 &xpmDarkSquare, NULL, &attr)) != 0) {
3542 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3546 xpmJailSquare = xpmLightSquare;
3547 fprintf(stderr, _("Done.\n"));
3549 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3552 #endif /* HAVE_LIBXPM */
3555 /* No built-in bitmaps */
3560 u_int ss = squareSize;
3562 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3565 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3566 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3567 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3568 pieceBitmapNames[piece],
3569 ss, kind == SOLID ? 's' : 'o');
3570 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3571 if(piece <= (int)WhiteKing)
3572 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3576 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3580 /* With built-in bitmaps */
3583 BuiltInBits* bib = builtInBits;
3586 u_int ss = squareSize;
3588 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3591 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3593 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3594 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3595 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3596 pieceBitmapNames[piece],
3597 ss, kind == SOLID ? 's' : 'o');
3598 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3599 bib->bits[kind][piece], ss, ss);
3600 if(piece <= (int)WhiteKing)
3601 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3605 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3610 void ReadBitmap(pm, name, bits, wreq, hreq)
3613 unsigned char bits[];
3619 char msg[MSG_SIZ], fullname[MSG_SIZ];
3621 if (*appData.bitmapDirectory != NULLCHAR) {
3622 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3623 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3624 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3625 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3626 &w, &h, pm, &x_hot, &y_hot);
3627 fprintf(stderr, "load %s\n", name);
3628 if (errcode != BitmapSuccess) {
3630 case BitmapOpenFailed:
3631 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3633 case BitmapFileInvalid:
3634 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3636 case BitmapNoMemory:
3637 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3641 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3645 fprintf(stderr, _("%s: %s...using built-in\n"),
3647 } else if (w != wreq || h != hreq) {
3649 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3650 programName, fullname, w, h, wreq, hreq);
3656 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3665 if (lineGap == 0) return;
3667 /* [HR] Split this into 2 loops for non-square boards. */
3669 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3670 gridSegments[i].x1 = 0;
3671 gridSegments[i].x2 =
3672 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3673 gridSegments[i].y1 = gridSegments[i].y2
3674 = lineGap / 2 + (i * (squareSize + lineGap));
3677 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3678 gridSegments[j + i].y1 = 0;
3679 gridSegments[j + i].y2 =
3680 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3681 gridSegments[j + i].x1 = gridSegments[j + i].x2
3682 = lineGap / 2 + (j * (squareSize + lineGap));
3686 static void MenuBarSelect(w, addr, index)
3691 XtActionProc proc = (XtActionProc) addr;
3693 (proc)(NULL, NULL, NULL, NULL);
3696 void CreateMenuBarPopup(parent, name, mb)
3706 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3709 XtSetArg(args[j], XtNleftMargin, 20); j++;
3710 XtSetArg(args[j], XtNrightMargin, 20); j++;
3712 while (mi->string != NULL) {
3713 if (strcmp(mi->string, "----") == 0) {
3714 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3717 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3718 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3720 XtAddCallback(entry, XtNcallback,
3721 (XtCallbackProc) MenuBarSelect,
3722 (caddr_t) mi->proc);
3728 Widget CreateMenuBar(mb)
3732 Widget anchor, menuBar;
3734 char menuName[MSG_SIZ];
3737 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3738 XtSetArg(args[j], XtNvSpace, 0); j++;
3739 XtSetArg(args[j], XtNborderWidth, 0); j++;
3740 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3741 formWidget, args, j);
3743 while (mb->name != NULL) {
3744 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3745 strncat(menuName, mb->name, MSG_SIZ - strlen(menuName) - 1);
3747 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3750 shortName[0] = _(mb->name)[0];
3751 shortName[1] = NULLCHAR;
3752 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3755 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3758 XtSetArg(args[j], XtNborderWidth, 0); j++;
3759 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3761 CreateMenuBarPopup(menuBar, menuName, mb);
3767 Widget CreateButtonBar(mi)
3771 Widget button, buttonBar;
3775 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3777 XtSetArg(args[j], XtNhSpace, 0); j++;
3779 XtSetArg(args[j], XtNborderWidth, 0); j++;
3780 XtSetArg(args[j], XtNvSpace, 0); j++;
3781 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3782 formWidget, args, j);
3784 while (mi->string != NULL) {
3787 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3788 XtSetArg(args[j], XtNborderWidth, 0); j++;
3790 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3791 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3792 buttonBar, args, j);
3793 XtAddCallback(button, XtNcallback,
3794 (XtCallbackProc) MenuBarSelect,
3795 (caddr_t) mi->proc);
3802 CreatePieceMenu(name, color)
3809 ChessSquare selection;
3811 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3812 boardWidget, args, 0);
3814 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3815 String item = pieceMenuStrings[color][i];
3817 if (strcmp(item, "----") == 0) {
3818 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3821 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3822 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3824 selection = pieceMenuTranslation[color][i];
3825 XtAddCallback(entry, XtNcallback,
3826 (XtCallbackProc) PieceMenuSelect,
3827 (caddr_t) selection);
3828 if (selection == WhitePawn || selection == BlackPawn) {
3829 XtSetArg(args[0], XtNpopupOnEntry, entry);
3830 XtSetValues(menu, args, 1);
3843 ChessSquare selection;
3845 whitePieceMenu = CreatePieceMenu("menuW", 0);
3846 blackPieceMenu = CreatePieceMenu("menuB", 1);
3848 XtRegisterGrabAction(PieceMenuPopup, True,
3849 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3850 GrabModeAsync, GrabModeAsync);
3852 XtSetArg(args[0], XtNlabel, _("Drop"));
3853 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3854 boardWidget, args, 1);
3855 for (i = 0; i < DROP_MENU_SIZE; i++) {
3856 String item = dropMenuStrings[i];
3858 if (strcmp(item, "----") == 0) {
3859 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3862 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3863 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3865 selection = dropMenuTranslation[i];
3866 XtAddCallback(entry, XtNcallback,
3867 (XtCallbackProc) DropMenuSelect,
3868 (caddr_t) selection);
3873 void SetupDropMenu()
3881 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3882 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3883 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3884 dmEnables[i].piece);
3885 XtSetSensitive(entry, p != NULL || !appData.testLegality
3886 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3887 && !appData.icsActive));
3889 while (p && *p++ == dmEnables[i].piece) count++;
3890 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3892 XtSetArg(args[j], XtNlabel, label); j++;
3893 XtSetValues(entry, args, j);
3897 void PieceMenuPopup(w, event, params, num_params)
3901 Cardinal *num_params;
3903 String whichMenu; int menuNr;
3904 if (event->type == ButtonRelease)
3905 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3906 else if (event->type == ButtonPress)
3907 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3909 case 0: whichMenu = params[0]; break;
3910 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3912 case -1: if (errorUp) ErrorPopDown();
3915 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3918 static void PieceMenuSelect(w, piece, junk)
3923 if (pmFromX < 0 || pmFromY < 0) return;
3924 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3927 static void DropMenuSelect(w, piece, junk)
3932 if (pmFromX < 0 || pmFromY < 0) return;
3933 DropMenuEvent(piece, pmFromX, pmFromY);
3936 void WhiteClock(w, event, prms, nprms)
3942 if (gameMode == EditPosition || gameMode == IcsExamining) {
3943 SetWhiteToPlayEvent();
3944 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3949 void BlackClock(w, event, prms, nprms)
3955 if (gameMode == EditPosition || gameMode == IcsExamining) {
3956 SetBlackToPlayEvent();
3957 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3964 * If the user selects on a border boundary, return -1; if off the board,
3965 * return -2. Otherwise map the event coordinate to the square.
3967 int EventToSquare(x, limit)
3975 if ((x % (squareSize + lineGap)) >= squareSize)
3977 x /= (squareSize + lineGap);
3983 static void do_flash_delay(msec)
3989 static void drawHighlight(file, rank, gc)
3995 if (lineGap == 0 || appData.blindfold) return;
3998 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3999 (squareSize + lineGap);
4000 y = lineGap/2 + rank * (squareSize + lineGap);
4002 x = lineGap/2 + file * (squareSize + lineGap);
4003 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4004 (squareSize + lineGap);
4007 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4008 squareSize+lineGap, squareSize+lineGap);
4011 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4012 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4015 SetHighlights(fromX, fromY, toX, toY)
4016 int fromX, fromY, toX, toY;
4018 if (hi1X != fromX || hi1Y != fromY) {
4019 if (hi1X >= 0 && hi1Y >= 0) {
4020 drawHighlight(hi1X, hi1Y, lineGC);
4022 } // [HGM] first erase both, then draw new!
4023 if (hi2X != toX || hi2Y != toY) {
4024 if (hi2X >= 0 && hi2Y >= 0) {
4025 drawHighlight(hi2X, hi2Y, lineGC);
4028 if (hi1X != fromX || hi1Y != fromY) {
4029 if (fromX >= 0 && fromY >= 0) {
4030 drawHighlight(fromX, fromY, highlineGC);
4033 if (hi2X != toX || hi2Y != toY) {
4034 if (toX >= 0 && toY >= 0) {
4035 drawHighlight(toX, toY, highlineGC);
4047 SetHighlights(-1, -1, -1, -1);
4052 SetPremoveHighlights(fromX, fromY, toX, toY)
4053 int fromX, fromY, toX, toY;
4055 if (pm1X != fromX || pm1Y != fromY) {
4056 if (pm1X >= 0 && pm1Y >= 0) {
4057 drawHighlight(pm1X, pm1Y, lineGC);
4059 if (fromX >= 0 && fromY >= 0) {
4060 drawHighlight(fromX, fromY, prelineGC);
4063 if (pm2X != toX || pm2Y != toY) {
4064 if (pm2X >= 0 && pm2Y >= 0) {
4065 drawHighlight(pm2X, pm2Y, lineGC);
4067 if (toX >= 0 && toY >= 0) {
4068 drawHighlight(toX, toY, prelineGC);
4078 ClearPremoveHighlights()
4080 SetPremoveHighlights(-1, -1, -1, -1);
4083 static int CutOutSquare(x, y, x0, y0, kind)
4084 int x, y, *x0, *y0, kind;
4086 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4087 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4089 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4090 if(textureW[kind] < W*squareSize)
4091 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4093 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4094 if(textureH[kind] < H*squareSize)
4095 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4097 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4101 static void BlankSquare(x, y, color, piece, dest, fac)
4102 int x, y, color, fac;
4105 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4107 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4108 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4109 squareSize, squareSize, x*fac, y*fac);
4111 if (useImages && useImageSqs) {
4115 pm = xpmLightSquare;
4120 case 2: /* neutral */
4125 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4126 squareSize, squareSize, x*fac, y*fac);
4136 case 2: /* neutral */
4141 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4146 I split out the routines to draw a piece so that I could
4147 make a generic flash routine.
4149 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4151 int square_color, x, y;
4154 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4155 switch (square_color) {
4157 case 2: /* neutral */
4159 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4160 ? *pieceToOutline(piece)
4161 : *pieceToSolid(piece),
4162 dest, bwPieceGC, 0, 0,
4163 squareSize, squareSize, x, y);
4166 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4167 ? *pieceToSolid(piece)
4168 : *pieceToOutline(piece),
4169 dest, wbPieceGC, 0, 0,
4170 squareSize, squareSize, x, y);
4175 static void monoDrawPiece(piece, square_color, x, y, dest)
4177 int square_color, x, y;
4180 switch (square_color) {
4182 case 2: /* neutral */
4184 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4185 ? *pieceToOutline(piece)
4186 : *pieceToSolid(piece),
4187 dest, bwPieceGC, 0, 0,
4188 squareSize, squareSize, x, y, 1);
4191 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4192 ? *pieceToSolid(piece)
4193 : *pieceToOutline(piece),
4194 dest, wbPieceGC, 0, 0,
4195 squareSize, squareSize, x, y, 1);
4200 static void colorDrawPiece(piece, square_color, x, y, dest)
4202 int square_color, x, y;
4205 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4206 switch (square_color) {
4208 XCopyPlane(xDisplay, *pieceToSolid(piece),
4209 dest, (int) piece < (int) BlackPawn
4210 ? wlPieceGC : blPieceGC, 0, 0,
4211 squareSize, squareSize, x, y, 1);
4214 XCopyPlane(xDisplay, *pieceToSolid(piece),
4215 dest, (int) piece < (int) BlackPawn
4216 ? wdPieceGC : bdPieceGC, 0, 0,
4217 squareSize, squareSize, x, y, 1);
4219 case 2: /* neutral */
4221 XCopyPlane(xDisplay, *pieceToSolid(piece),
4222 dest, (int) piece < (int) BlackPawn
4223 ? wjPieceGC : bjPieceGC, 0, 0,
4224 squareSize, squareSize, x, y, 1);
4229 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4231 int square_color, x, y;
4234 int kind, p = piece;
4236 switch (square_color) {
4238 case 2: /* neutral */
4240 if ((int)piece < (int) BlackPawn) {
4248 if ((int)piece < (int) BlackPawn) {
4256 if(appData.upsideDown && flipView) kind ^= 2; // swap white and black pieces
4257 if(useTexture & square_color+1) {
4258 BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
4259 XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]);
4260 XSetClipOrigin(xDisplay, wlPieceGC, x, y);
4261 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y);
4262 XSetClipMask(xDisplay, wlPieceGC, None);
4263 XSetClipOrigin(xDisplay, wlPieceGC, 0, 0);
4265 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4266 dest, wlPieceGC, 0, 0,
4267 squareSize, squareSize, x, y);
4270 typedef void (*DrawFunc)();
4272 DrawFunc ChooseDrawFunc()
4274 if (appData.monoMode) {
4275 if (DefaultDepth(xDisplay, xScreen) == 1) {
4276 return monoDrawPiece_1bit;
4278 return monoDrawPiece;