2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
65 # if HAVE_SYS_SOCKET_H
66 # include <sys/socket.h>
67 # include <netinet/in.h>
69 # else /* not HAVE_SYS_SOCKET_H */
70 # if HAVE_LAN_SOCKET_H
71 # include <lan/socket.h>
73 # include <lan/netdb.h>
74 # else /* not HAVE_LAN_SOCKET_H */
75 # define OMIT_SOCKETS 1
76 # endif /* not HAVE_LAN_SOCKET_H */
77 # endif /* not HAVE_SYS_SOCKET_H */
78 #endif /* !OMIT_SOCKETS */
83 #else /* not STDC_HEADERS */
84 extern char *getenv();
87 # else /* not HAVE_STRING_H */
89 # endif /* not HAVE_STRING_H */
90 #endif /* not STDC_HEADERS */
93 # include <sys/fcntl.h>
94 #else /* not HAVE_SYS_FCNTL_H */
97 # endif /* HAVE_FCNTL_H */
98 #endif /* not HAVE_SYS_FCNTL_H */
100 #if HAVE_SYS_SYSTEMINFO_H
101 # include <sys/systeminfo.h>
102 #endif /* HAVE_SYS_SYSTEMINFO_H */
104 #if TIME_WITH_SYS_TIME
105 # include <sys/time.h>
109 # include <sys/time.h>
120 # include <sys/wait.h>
125 # define NAMLEN(dirent) strlen((dirent)->d_name)
126 # define HAVE_DIR_STRUCT
128 # define dirent direct
129 # define NAMLEN(dirent) (dirent)->d_namlen
131 # include <sys/ndir.h>
132 # define HAVE_DIR_STRUCT
135 # include <sys/dir.h>
136 # define HAVE_DIR_STRUCT
140 # define HAVE_DIR_STRUCT
144 #include <X11/Intrinsic.h>
145 #include <X11/StringDefs.h>
146 #include <X11/Shell.h>
147 #include <X11/cursorfont.h>
148 #include <X11/Xatom.h>
149 #include <X11/Xmu/Atoms.h>
151 #include <X11/Xaw3d/Dialog.h>
152 #include <X11/Xaw3d/Form.h>
153 #include <X11/Xaw3d/List.h>
154 #include <X11/Xaw3d/Label.h>
155 #include <X11/Xaw3d/SimpleMenu.h>
156 #include <X11/Xaw3d/SmeBSB.h>
157 #include <X11/Xaw3d/SmeLine.h>
158 #include <X11/Xaw3d/Box.h>
159 #include <X11/Xaw3d/MenuButton.h>
160 #include <X11/Xaw3d/Text.h>
161 #include <X11/Xaw3d/AsciiText.h>
163 #include <X11/Xaw/Dialog.h>
164 #include <X11/Xaw/Form.h>
165 #include <X11/Xaw/List.h>
166 #include <X11/Xaw/Label.h>
167 #include <X11/Xaw/SimpleMenu.h>
168 #include <X11/Xaw/SmeBSB.h>
169 #include <X11/Xaw/SmeLine.h>
170 #include <X11/Xaw/Box.h>
171 #include <X11/Xaw/MenuButton.h>
172 #include <X11/Xaw/Text.h>
173 #include <X11/Xaw/AsciiText.h>
176 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
181 #include "pixmaps/pixmaps.h"
182 #define IMAGE_EXT "xpm"
184 #define IMAGE_EXT "xim"
185 #include "bitmaps/bitmaps.h"
188 #include "bitmaps/icon_white.bm"
189 #include "bitmaps/icon_black.bm"
190 #include "bitmaps/checkmark.bm"
192 #include "frontend.h"
194 #include "backendz.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
203 // must be moved to xengineoutput.h
205 void EngineOutputProc P((Widget w, XEvent *event,
206 String *prms, Cardinal *nprms));
207 void EvalGraphProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
215 #define usleep(t) _sleep2(((t)+500)/1000)
219 # define _(s) gettext (s)
220 # define N_(s) gettext_noop (s)
238 int main P((int argc, char **argv));
239 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
240 char *init_path, char *mode, int (*show_entry)(), char **name_return));
241 RETSIGTYPE CmailSigHandler P((int sig));
242 RETSIGTYPE IntSigHandler P((int sig));
243 RETSIGTYPE TermSizeSigHandler P((int sig));
244 void CreateGCs P((void));
245 void CreateXIMPieces P((void));
246 void CreateXPMPieces P((void));
247 void CreateXPMBoard P((char *s, int n));
248 void CreatePieces P((void));
249 void CreatePieceMenus P((void));
250 Widget CreateMenuBar P((Menu *mb));
251 Widget CreateButtonBar P ((MenuItem *mi));
252 char *FindFont P((char *pattern, int targetPxlSize));
253 void PieceMenuPopup P((Widget w, XEvent *event,
254 String *params, Cardinal *num_params));
255 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
256 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
257 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
258 u_int wreq, u_int hreq));
259 void CreateGrid P((void));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
263 void HandleUserMove P((Widget w, XEvent *event,
264 String *prms, Cardinal *nprms));
265 void AnimateUserMove P((Widget w, XEvent * event,
266 String * params, Cardinal * nParams));
267 void HandlePV P((Widget w, XEvent * event,
268 String * params, Cardinal * nParams));
269 void SelectPV P((Widget w, XEvent * event,
270 String * params, Cardinal * nParams));
271 void StopPV P((Widget w, XEvent * event,
272 String * params, Cardinal * nParams));
273 void WhiteClock P((Widget w, XEvent *event,
274 String *prms, Cardinal *nprms));
275 void BlackClock P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void DrawPositionProc P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
281 void CommentClick P((Widget w, XEvent * event,
282 String * params, Cardinal * nParams));
283 void CommentPopUp P((char *title, char *label));
284 void CommentPopDown P((void));
285 void CommentCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void ICSInputBoxPopUp P((void));
288 void ICSInputBoxPopDown P((void));
289 void FileNamePopUp P((char *label, char *def,
290 FileProc proc, char *openMode));
291 void FileNamePopDown P((void));
292 void FileNameCallback P((Widget w, XtPointer client_data,
293 XtPointer call_data));
294 void FileNameAction P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void AskQuestionReplyAction P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void AskQuestionProc P((Widget w, XEvent *event,
299 String *prms, Cardinal *nprms));
300 void AskQuestionPopDown P((void));
301 void PromotionPopDown P((void));
302 void PromotionCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void EditCommentPopDown P((void));
305 void EditCommentCallback P((Widget w, XtPointer client_data,
306 XtPointer call_data));
307 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
308 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
312 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
314 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
316 void LoadPositionProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
320 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
322 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
324 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
326 void PastePositionProc P((Widget w, XEvent *event, String *prms,
328 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void SavePositionProc P((Widget w, XEvent *event,
332 String *prms, Cardinal *nprms));
333 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
336 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
340 void MachineWhiteProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void AnalyzeModeProc P((Widget w, XEvent *event,
343 String *prms, Cardinal *nprms));
344 void AnalyzeFileProc P((Widget w, XEvent *event,
345 String *prms, Cardinal *nprms));
346 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
348 void IcsClientProc P((Widget w, XEvent *event, String *prms,
350 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void EditPositionProc P((Widget w, XEvent *event,
352 String *prms, Cardinal *nprms));
353 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void EditCommentProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void IcsInputBoxProc P((Widget w, XEvent *event,
357 String *prms, Cardinal *nprms));
358 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void StopObservingProc P((Widget w, XEvent *event, String *prms,
374 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
376 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
385 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
387 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
390 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
392 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
394 void AutocommProc P((Widget w, XEvent *event, String *prms,
396 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void AutobsProc P((Widget w, XEvent *event, String *prms,
400 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
405 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
408 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
410 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
412 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
416 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
418 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
420 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
422 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
424 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
428 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
430 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
432 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
434 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void DisplayMove P((int moveNumber));
446 void DisplayTitle P((char *title));
447 void ICSInitScript P((void));
448 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
449 void ErrorPopUp P((char *title, char *text, int modal));
450 void ErrorPopDown P((void));
451 static char *ExpandPathName P((char *path));
452 static void CreateAnimVars P((void));
453 static void DragPieceMove P((int x, int y));
454 static void DrawDragPiece P((void));
455 char *ModeToWidgetName P((GameMode mode));
456 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void GameListOptionsPopDown P(());
465 void ShufflePopDown P(());
466 void EnginePopDown P(());
467 void UciPopDown P(());
468 void TimeControlPopDown P(());
469 void NewVariantPopDown P(());
470 void SettingsPopDown P(());
471 void update_ics_width P(());
472 int get_term_width P(());
473 int CopyMemoProc P(());
475 * XBoard depends on Xt R4 or higher
477 int xtVersion = XtSpecificationRelease;
482 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
483 jailSquareColor, highlightSquareColor, premoveHighlightColor;
484 Pixel lowTimeWarningColor;
485 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
486 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
487 wjPieceGC, bjPieceGC, prelineGC, countGC;
488 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
489 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
490 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
491 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
492 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
493 ICSInputShell, fileNameShell, askQuestionShell;
494 Widget historyShell, evalGraphShell, gameListShell;
495 int hOffset; // [HGM] dual
496 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
497 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
498 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
499 Font clockFontID, coordFontID, countFontID;
500 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
501 XtAppContext appContext;
503 char *oldICSInteractionTitle;
507 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
509 Position commentX = -1, commentY = -1;
510 Dimension commentW, commentH;
511 typedef unsigned int BoardSize;
513 Boolean chessProgram;
515 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
516 int squareSize, smallLayout = 0, tinyLayout = 0,
517 marginW, marginH, // [HGM] for run-time resizing
518 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
519 ICSInputBoxUp = False, askQuestionUp = False,
520 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
521 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
522 Pixel timerForegroundPixel, timerBackgroundPixel;
523 Pixel buttonForegroundPixel, buttonBackgroundPixel;
524 char *chessDir, *programName, *programVersion,
525 *gameCopyFilename, *gamePasteFilename;
526 Boolean alwaysOnTop = False;
527 Boolean saveSettingsOnExit;
528 char *settingsFileName;
529 char *icsTextMenuString;
531 char *firstChessProgramNames;
532 char *secondChessProgramNames;
534 WindowPlacement wpMain;
535 WindowPlacement wpConsole;
536 WindowPlacement wpComment;
537 WindowPlacement wpMoveHistory;
538 WindowPlacement wpEvalGraph;
539 WindowPlacement wpEngineOutput;
540 WindowPlacement wpGameList;
541 WindowPlacement wpTags;
545 Pixmap pieceBitmap[2][(int)BlackPawn];
546 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
547 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
548 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
549 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
550 Pixmap xpmBoardBitmap[2];
551 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
552 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
553 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
554 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
555 XImage *ximLightSquare, *ximDarkSquare;
558 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
559 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
561 #define White(piece) ((int)(piece) < (int)BlackPawn)
563 /* Variables for doing smooth animation. This whole thing
564 would be much easier if the board was double-buffered,
565 but that would require a fairly major rewrite. */
570 GC blitGC, pieceGC, outlineGC;
571 XPoint startSquare, prevFrame, mouseDelta;
575 int startBoardX, startBoardY;
578 /* There can be two pieces being animated at once: a player
579 can begin dragging a piece before the remote opponent has moved. */
581 static AnimState game, player;
583 /* Bitmaps for use as masks when drawing XPM pieces.
584 Need one for each black and white piece. */
585 static Pixmap xpmMask[BlackKing + 1];
587 /* This magic number is the number of intermediate frames used
588 in each half of the animation. For short moves it's reduced
589 by 1. The total number of frames will be factor * 2 + 1. */
592 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
594 MenuItem fileMenu[] = {
595 {N_("New Game"), "New Game", ResetProc},
596 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
597 {N_("New Variant ..."), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
598 {"----", NULL, NothingProc},
599 {N_("Load Game"), "Load Game", LoadGameProc},
600 {N_("Load Position"), "Load Position", LoadPositionProc},
601 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
602 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
603 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
604 {"----", NULL, NothingProc},
605 // {N_("Load Next Position"), "Load Next Position", LoadNextPositionProc},
606 // {N_("Load Previous Position"), "Load Previous Position", LoadPrevPositionProc},
607 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
608 {N_("Save Game"), "Save Game", SaveGameProc},
609 {N_("Save Position"), "Save Position", SavePositionProc},
610 {"----", NULL, NothingProc},
611 {N_("Mail Move"), "Mail Move", MailMoveProc},
612 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
613 {"----", NULL, NothingProc},
614 {N_("Exit"), "Exit", QuitProc},
618 MenuItem editMenu[] = {
619 {N_("Copy Game"), "Copy Game", CopyGameProc},
620 {N_("Copy Position"), "Copy Position", CopyPositionProc},
621 {"----", NULL, NothingProc},
622 {N_("Paste Game"), "Paste Game", PasteGameProc},
623 {N_("Paste Position"), "Paste Position", PastePositionProc},
624 {"----", NULL, NothingProc},
625 {N_("Edit Game"), "Edit Game", EditGameProc},
626 {N_("Edit Position"), "Edit Position", EditPositionProc},
627 {"----", NULL, NothingProc},
628 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
629 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
630 {"----", NULL, NothingProc},
631 {N_("Revert"), "Revert", RevertProc},
632 {N_("Annotate"), "Annotate", AnnotateProc},
633 {N_("Truncate Game"), "Truncate Game", TruncateGameProc},
634 {"----", NULL, NothingProc},
635 {N_("Backward"), "Backward", BackwardProc},
636 {N_("Forward"), "Forward", ForwardProc},
637 {N_("Back to Start"), "Back to Start", ToStartProc},
638 {N_("Forward to End"), "Forward to End", ToEndProc},
642 MenuItem viewMenu[] = {
643 {N_("Flip View"), "Flip View", FlipViewProc},
644 {"----", NULL, NothingProc},
645 {N_("Engine Output"), "Show Engine Output", EngineOutputProc},
646 {N_("Evaluation Graph"), "Show Evaluation Graph", EvalGraphProc},
647 {N_("Game List"), "Show Game List", ShowGameListProc},
648 {N_("Move History"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
649 {"----", NULL, NothingProc},
650 {N_("Tags"), "Show Tags", EditTagsProc},
651 {N_("Comments"), "Show Comments", EditCommentProc},
652 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
656 MenuItem modeMenu[] = {
657 {N_("Machine White"), "Machine White", MachineWhiteProc},
658 {N_("Machine Black"), "Machine Black", MachineBlackProc},
659 {N_("Two Machines"), "Two Machines", TwoMachinesProc},
660 {N_("Analysis Mode"), "Analysis Mode", AnalyzeModeProc},
661 {N_("Analyze File"), "Analyze File", AnalyzeFileProc },
662 {N_("Edit Game"), "Edit Game", EditGameProc},
663 {N_("Edit Position"), "Edit Position", EditPositionProc},
664 {N_("Training"), "Training", TrainingProc},
665 {N_("ICS Client"), "ICS Client", IcsClientProc},
666 {"----", NULL, NothingProc},
667 {N_("Pause"), "Pause", PauseProc},
671 MenuItem actionMenu[] = {
672 {N_("Accept"), "Accept", AcceptProc},
673 {N_("Decline"), "Decline", DeclineProc},
674 {N_("Rematch"), "Rematch", RematchProc},
675 {"----", NULL, NothingProc},
676 {N_("Call Flag"), "Call Flag", CallFlagProc},
677 {N_("Draw"), "Draw", DrawProc},
678 {N_("Adjourn"), "Adjourn", AdjournProc},
679 {N_("Abort"), "Abort", AbortProc},
680 {N_("Resign"), "Resign", ResignProc},
681 {"----", NULL, NothingProc},
682 {N_("Stop Observing"), "Stop Observing", StopObservingProc},
683 {N_("Stop Examining"), "Stop Examining", StopExaminingProc},
684 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
685 {"----", NULL, NothingProc},
686 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
687 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
688 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
692 MenuItem engineMenu[] = {
693 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
694 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
695 {"----", NULL, NothingProc},
696 {N_("Move Now"), "Move Now", MoveNowProc},
697 {N_("Retract Move"), "Retract Move", RetractMoveProc},
701 MenuItem optionsMenu[] = {
702 {N_("Time Control ..."), "Time Control", TimeControlProc},
703 {N_("Common Engine ..."), "Common Engine", UciMenuProc},
704 {N_("Adjudications ..."), "Adjudications", EngineMenuProc},
705 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
706 {"----", NULL, NothingProc},
707 {N_("Always Queen"), "Always Queen", AlwaysQueenProc},
708 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
709 {N_("Animate Moving"), "Animate Moving", AnimateMovingProc},
710 {N_("Auto Comment"), "Auto Comment", AutocommProc},
711 {N_("Auto Flag"), "Auto Flag", AutoflagProc},
712 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
713 {N_("Auto Observe"), "Auto Observe", AutobsProc},
714 {N_("Auto Raise Board"), "Auto Raise Board", AutoraiseProc},
715 {N_("Auto Save"), "Auto Save", AutosaveProc},
716 {N_("Blindfold"), "Blindfold", BlindfoldProc},
717 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
718 {N_("Get Move List"), "Get Move List", GetMoveListProc},
720 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
722 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
723 {N_("Move Sound"), "Move Sound", MoveSoundProc},
724 {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
725 {N_("Old Save Style"), "Old Save Style", OldSaveStyleProc},
726 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
727 {N_("Ponder Next Move"), "Ponder Next Move", PonderNextMoveProc},
728 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
729 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
730 {N_("Premove"), "Premove", PremoveProc},
731 {N_("Quiet Play"), "Quiet Play", QuietPlayProc},
732 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
733 {N_("Hide Thinking"), "Hide Thinking", HideThinkingProc},
734 {N_("Test Legality"), "Test Legality", TestLegalityProc},
735 {"----", NULL, NothingProc},
736 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
737 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
741 MenuItem helpMenu[] = {
742 {N_("Info XBoard"), "Info XBoard", InfoProc},
743 {N_("Man XBoard"), "Man XBoard", ManProc},
744 {"----", NULL, NothingProc},
745 {N_("Hint"), "Hint", HintProc},
746 {N_("Book"), "Book", BookProc},
747 {"----", NULL, NothingProc},
748 {N_("About XBoard"), "About XBoard", AboutProc},
753 {N_("File"), "File", fileMenu},
754 {N_("Edit"), "Edit", editMenu},
755 {N_("View"), "View", viewMenu},
756 {N_("Mode"), "Mode", modeMenu},
757 {N_("Action"), "Action", actionMenu},
758 {N_("Engine"), "Engine", engineMenu},
759 {N_("Options"), "Options", optionsMenu},
760 {N_("Help"), "Help", helpMenu},
764 #define PAUSE_BUTTON "P"
765 MenuItem buttonBar[] = {
766 {"<<", "<<", ToStartProc},
767 {"<", "<", BackwardProc},
768 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
769 {">", ">", ForwardProc},
770 {">>", ">>", ToEndProc},
774 #define PIECE_MENU_SIZE 18
775 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
776 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
777 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
778 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
779 N_("Empty square"), N_("Clear board") },
780 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
781 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
782 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
783 N_("Empty square"), N_("Clear board") }
785 /* must be in same order as PieceMenuStrings! */
786 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
787 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
788 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
789 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
790 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
791 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
792 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
793 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
794 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
797 #define DROP_MENU_SIZE 6
798 String dropMenuStrings[DROP_MENU_SIZE] = {
799 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
801 /* must be in same order as PieceMenuStrings! */
802 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
803 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
804 WhiteRook, WhiteQueen
812 DropMenuEnables dmEnables[] = {
830 { XtNborderWidth, 0 },
831 { XtNdefaultDistance, 0 },
835 { XtNborderWidth, 0 },
836 { XtNresizable, (XtArgVal) True },
840 { XtNborderWidth, 0 },
846 { XtNjustify, (XtArgVal) XtJustifyRight },
847 { XtNlabel, (XtArgVal) "..." },
848 { XtNresizable, (XtArgVal) True },
849 { XtNresize, (XtArgVal) False }
852 Arg messageArgs[] = {
853 { XtNjustify, (XtArgVal) XtJustifyLeft },
854 { XtNlabel, (XtArgVal) "..." },
855 { XtNresizable, (XtArgVal) True },
856 { XtNresize, (XtArgVal) False }
860 { XtNborderWidth, 0 },
861 { XtNjustify, (XtArgVal) XtJustifyLeft }
864 XtResource clientResources[] = {
865 { "flashCount", "flashCount", XtRInt, sizeof(int),
866 XtOffset(AppDataPtr, flashCount), XtRImmediate,
867 (XtPointer) FLASH_COUNT },
870 XrmOptionDescRec shellOptions[] = {
871 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
872 { "-flash", "flashCount", XrmoptionNoArg, "3" },
873 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
876 XtActionsRec boardActions[] = {
877 { "DrawPosition", DrawPositionProc },
878 { "HandleUserMove", HandleUserMove },
879 { "AnimateUserMove", AnimateUserMove },
880 { "HandlePV", HandlePV },
881 { "SelectPV", SelectPV },
882 { "StopPV", StopPV },
883 { "FileNameAction", FileNameAction },
884 { "AskQuestionProc", AskQuestionProc },
885 { "AskQuestionReplyAction", AskQuestionReplyAction },
886 { "PieceMenuPopup", PieceMenuPopup },
887 { "WhiteClock", WhiteClock },
888 { "BlackClock", BlackClock },
889 { "Iconify", Iconify },
890 { "ResetProc", ResetProc },
891 { "NewVariantProc", NewVariantProc },
892 { "LoadGameProc", LoadGameProc },
893 { "LoadNextGameProc", LoadNextGameProc },
894 { "LoadPrevGameProc", LoadPrevGameProc },
895 { "LoadSelectedProc", LoadSelectedProc },
896 { "SetFilterProc", SetFilterProc },
897 { "ReloadGameProc", ReloadGameProc },
898 { "LoadPositionProc", LoadPositionProc },
899 { "LoadNextPositionProc", LoadNextPositionProc },
900 { "LoadPrevPositionProc", LoadPrevPositionProc },
901 { "ReloadPositionProc", ReloadPositionProc },
902 { "CopyPositionProc", CopyPositionProc },
903 { "PastePositionProc", PastePositionProc },
904 { "CopyGameProc", CopyGameProc },
905 { "PasteGameProc", PasteGameProc },
906 { "SaveGameProc", SaveGameProc },
907 { "SavePositionProc", SavePositionProc },
908 { "MailMoveProc", MailMoveProc },
909 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
910 { "QuitProc", QuitProc },
911 { "MachineWhiteProc", MachineWhiteProc },
912 { "MachineBlackProc", MachineBlackProc },
913 { "AnalysisModeProc", AnalyzeModeProc },
914 { "AnalyzeFileProc", AnalyzeFileProc },
915 { "TwoMachinesProc", TwoMachinesProc },
916 { "IcsClientProc", IcsClientProc },
917 { "EditGameProc", EditGameProc },
918 { "EditPositionProc", EditPositionProc },
919 { "TrainingProc", EditPositionProc },
920 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
921 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
922 { "ShowGameListProc", ShowGameListProc },
923 { "ShowMoveListProc", HistoryShowProc},
924 { "EditTagsProc", EditCommentProc },
925 { "EditCommentProc", EditCommentProc },
926 { "IcsAlarmProc", IcsAlarmProc },
927 { "IcsInputBoxProc", IcsInputBoxProc },
928 { "PauseProc", PauseProc },
929 { "AcceptProc", AcceptProc },
930 { "DeclineProc", DeclineProc },
931 { "RematchProc", RematchProc },
932 { "CallFlagProc", CallFlagProc },
933 { "DrawProc", DrawProc },
934 { "AdjournProc", AdjournProc },
935 { "AbortProc", AbortProc },
936 { "ResignProc", ResignProc },
937 { "AdjuWhiteProc", AdjuWhiteProc },
938 { "AdjuBlackProc", AdjuBlackProc },
939 { "AdjuDrawProc", AdjuDrawProc },
940 { "EnterKeyProc", EnterKeyProc },
941 { "UpKeyProc", UpKeyProc },
942 { "DownKeyProc", DownKeyProc },
943 { "StopObservingProc", StopObservingProc },
944 { "StopExaminingProc", StopExaminingProc },
945 { "UploadProc", UploadProc },
946 { "BackwardProc", BackwardProc },
947 { "ForwardProc", ForwardProc },
948 { "ToStartProc", ToStartProc },
949 { "ToEndProc", ToEndProc },
950 { "RevertProc", RevertProc },
951 { "AnnotateProc", AnnotateProc },
952 { "TruncateGameProc", TruncateGameProc },
953 { "MoveNowProc", MoveNowProc },
954 { "RetractMoveProc", RetractMoveProc },
955 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
956 { "UciMenuProc", (XtActionProc) UciMenuProc },
957 { "TimeControlProc", (XtActionProc) TimeControlProc },
958 { "AlwaysQueenProc", AlwaysQueenProc },
959 { "AnimateDraggingProc", AnimateDraggingProc },
960 { "AnimateMovingProc", AnimateMovingProc },
961 { "AutoflagProc", AutoflagProc },
962 { "AutoflipProc", AutoflipProc },
963 { "AutobsProc", AutobsProc },
964 { "AutoraiseProc", AutoraiseProc },
965 { "AutosaveProc", AutosaveProc },
966 { "BlindfoldProc", BlindfoldProc },
967 { "FlashMovesProc", FlashMovesProc },
968 { "FlipViewProc", FlipViewProc },
969 { "GetMoveListProc", GetMoveListProc },
971 { "HighlightDraggingProc", HighlightDraggingProc },
973 { "HighlightLastMoveProc", HighlightLastMoveProc },
974 { "IcsAlarmProc", IcsAlarmProc },
975 { "MoveSoundProc", MoveSoundProc },
976 { "OldSaveStyleProc", OldSaveStyleProc },
977 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
978 { "PonderNextMoveProc", PonderNextMoveProc },
979 { "PopupExitMessageProc", PopupExitMessageProc },
980 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
981 { "PremoveProc", PremoveProc },
982 { "QuietPlayProc", QuietPlayProc },
983 { "ShowCoordsProc", ShowCoordsProc },
984 { "ShowThinkingProc", ShowThinkingProc },
985 { "HideThinkingProc", HideThinkingProc },
986 { "TestLegalityProc", TestLegalityProc },
987 { "SaveSettingsProc", SaveSettingsProc },
988 { "SaveOnExitProc", SaveOnExitProc },
989 { "InfoProc", InfoProc },
990 { "ManProc", ManProc },
991 { "HintProc", HintProc },
992 { "BookProc", BookProc },
993 { "AboutGameProc", AboutGameProc },
994 { "AboutProc", AboutProc },
995 { "DebugProc", DebugProc },
996 { "NothingProc", NothingProc },
997 { "CommentClick", (XtActionProc) CommentClick },
998 { "CommentPopDown", (XtActionProc) CommentPopDown },
999 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1000 { "TagsPopDown", (XtActionProc) TagsPopDown },
1001 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1002 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1003 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1004 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1005 { "GameListPopDown", (XtActionProc) GameListPopDown },
1006 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1007 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1008 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1009 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1010 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1011 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1012 { "EnginePopDown", (XtActionProc) EnginePopDown },
1013 { "UciPopDown", (XtActionProc) UciPopDown },
1014 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1015 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1016 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1017 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1020 char globalTranslations[] =
1021 ":<Key>F9: ResignProc() \n \
1022 :Ctrl<Key>n: ResetProc() \n \
1023 :Meta<Key>V: NewVariantProc() \n \
1024 :Ctrl<Key>o: LoadGameProc() \n \
1025 :Meta<Key>Next: LoadNextGameProc() \n \
1026 :Meta<Key>Prior: LoadPrevGameProc() \n \
1027 :Ctrl<Key>s: SaveGameProc() \n \
1028 :Ctrl<Key>c: CopyGameProc() \n \
1029 :Ctrl<Key>v: PasteGameProc() \n \
1030 :Ctrl<Key>O: LoadPositionProc() \n \
1031 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1032 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1033 :Ctrl<Key>S: SavePositionProc() \n \
1034 :Ctrl<Key>C: CopyPositionProc() \n \
1035 :Ctrl<Key>V: PastePositionProc() \n \
1036 :Ctrl<Key>q: QuitProc() \n \
1037 :Ctrl<Key>w: MachineWhiteProc() \n \
1038 :Ctrl<Key>b: MachineBlackProc() \n \
1039 :Ctrl<Key>t: TwoMachinesProc() \n \
1040 :Ctrl<Key>a: AnalysisModeProc() \n \
1041 :Ctrl<Key>f: AnalyzeFileProc() \n \
1042 :Ctrl<Key>e: EditGameProc() \n \
1043 :Ctrl<Key>E: EditPositionProc() \n \
1044 :Meta<Key>O: EngineOutputProc() \n \
1045 :Meta<Key>E: EvalGraphProc() \n \
1046 :Meta<Key>G: ShowGameListProc() \n \
1047 :Meta<Key>H: ShowMoveListProc() \n \
1048 :<Key>Pause: PauseProc() \n \
1049 :<Key>F3: AcceptProc() \n \
1050 :<Key>F4: DeclineProc() \n \
1051 :<Key>F12: RematchProc() \n \
1052 :<Key>F5: CallFlagProc() \n \
1053 :<Key>F6: DrawProc() \n \
1054 :<Key>F7: AdjournProc() \n \
1055 :<Key>F8: AbortProc() \n \
1056 :<Key>F10: StopObservingProc() \n \
1057 :<Key>F11: StopExaminingProc() \n \
1058 :Meta Ctrl<Key>F12: DebugProc() \n \
1059 :Meta<Key>End: ToEndProc() \n \
1060 :Meta<Key>Right: ForwardProc() \n \
1061 :Meta<Key>Home: ToStartProc() \n \
1062 :Meta<Key>Left: BackwardProc() \n \
1063 :<Key>Home: RevertProc() \n \
1064 :<Key>End: TruncateGameProc() \n \
1065 :Ctrl<Key>m: MoveNowProc() \n \
1066 :Ctrl<Key>x: RetractMoveProc() \n \
1067 :Meta<Key>J: EngineMenuProc() \n \
1068 :Meta<Key>U: UciMenuProc() \n \
1069 :Meta<Key>T: TimeControlProc() \n \
1070 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1071 :Ctrl<Key>F: AutoflagProc() \n \
1072 :Ctrl<Key>A: AnimateMovingProc() \n \
1073 :Ctrl<Key>P: PonderNextMoveProc() \n \
1074 :Ctrl<Key>L: TestLegalityProc() \n \
1075 :Ctrl<Key>H: HideThinkingProc() \n \
1076 :<Key>-: Iconify() \n \
1077 :<Key>F1: ManProc() \n \
1078 :<Key>F2: FlipViewProc() \n \
1079 <KeyDown>.: BackwardProc() \n \
1080 <KeyUp>.: ForwardProc() \n \
1081 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1082 \"Send to chess program:\",,1) \n \
1083 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1084 \"Send to second chess program:\",,2) \n";
1086 char boardTranslations[] =
1087 "<Btn1Down>: HandleUserMove(0) \n \
1088 Shift<Btn1Up>: HandleUserMove(1) \n \
1089 <Btn1Up>: HandleUserMove(0) \n \
1090 <Btn1Motion>: AnimateUserMove() \n \
1091 <Btn3Motion>: HandlePV() \n \
1092 <Btn3Up>: PieceMenuPopup(menuB) \n \
1093 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1094 PieceMenuPopup(menuB) \n \
1095 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1096 PieceMenuPopup(menuW) \n \
1097 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1098 PieceMenuPopup(menuW) \n \
1099 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1100 PieceMenuPopup(menuB) \n";
1102 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1103 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1105 char ICSInputTranslations[] =
1106 "<Key>Up: UpKeyProc() \n "
1107 "<Key>Down: DownKeyProc() \n "
1108 "<Key>Return: EnterKeyProc() \n";
1110 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1111 // as the widget is destroyed before the up-click can call extend-end
1112 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1114 String xboardResources[] = {
1115 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1116 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1117 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1122 /* Max possible square size */
1123 #define MAXSQSIZE 256
1125 static int xpm_avail[MAXSQSIZE];
1127 #ifdef HAVE_DIR_STRUCT
1129 /* Extract piece size from filename */
1131 xpm_getsize(name, len, ext)
1142 if ((p=strchr(name, '.')) == NULL ||
1143 StrCaseCmp(p+1, ext) != 0)
1149 while (*p && isdigit(*p))
1156 /* Setup xpm_avail */
1158 xpm_getavail(dirname, ext)
1166 for (i=0; i<MAXSQSIZE; ++i)
1169 if (appData.debugMode)
1170 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1172 dir = opendir(dirname);
1175 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1176 programName, dirname);
1180 while ((ent=readdir(dir)) != NULL) {
1181 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1182 if (i > 0 && i < MAXSQSIZE)
1192 xpm_print_avail(fp, ext)
1198 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1199 for (i=1; i<MAXSQSIZE; ++i) {
1205 /* Return XPM piecesize closest to size */
1207 xpm_closest_to(dirname, size, ext)
1213 int sm_diff = MAXSQSIZE;
1217 xpm_getavail(dirname, ext);
1219 if (appData.debugMode)
1220 xpm_print_avail(stderr, ext);
1222 for (i=1; i<MAXSQSIZE; ++i) {
1225 diff = (diff<0) ? -diff : diff;
1226 if (diff < sm_diff) {
1234 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1240 #else /* !HAVE_DIR_STRUCT */
1241 /* If we are on a system without a DIR struct, we can't
1242 read the directory, so we can't collect a list of
1243 filenames, etc., so we can't do any size-fitting. */
1245 xpm_closest_to(dirname, size, ext)
1250 fprintf(stderr, _("\
1251 Warning: No DIR structure found on this system --\n\
1252 Unable to autosize for XPM/XIM pieces.\n\
1253 Please report this error to frankm@hiwaay.net.\n\
1254 Include system type & operating system in message.\n"));
1257 #endif /* HAVE_DIR_STRUCT */
1259 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1260 "magenta", "cyan", "white" };
1264 TextColors textColors[(int)NColorClasses];
1266 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1268 parse_color(str, which)
1272 char *p, buf[100], *d;
1275 if (strlen(str) > 99) /* watch bounds on buf */
1280 for (i=0; i<which; ++i) {
1287 /* Could be looking at something like:
1289 .. in which case we want to stop on a comma also */
1290 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1294 return -1; /* Use default for empty field */
1297 if (which == 2 || isdigit(*p))
1300 while (*p && isalpha(*p))
1305 for (i=0; i<8; ++i) {
1306 if (!StrCaseCmp(buf, cnames[i]))
1307 return which? (i+40) : (i+30);
1309 if (!StrCaseCmp(buf, "default")) return -1;
1311 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1316 parse_cpair(cc, str)
1320 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1321 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1326 /* bg and attr are optional */
1327 textColors[(int)cc].bg = parse_color(str, 1);
1328 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1329 textColors[(int)cc].attr = 0;
1335 /* Arrange to catch delete-window events */
1336 Atom wm_delete_window;
1338 CatchDeleteWindow(Widget w, String procname)
1341 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1342 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1343 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1350 XtSetArg(args[0], XtNiconic, False);
1351 XtSetValues(shellWidget, args, 1);
1353 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1356 //---------------------------------------------------------------------------------------------------------
1357 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1360 #define CW_USEDEFAULT (1<<31)
1361 #define ICS_TEXT_MENU_SIZE 90
1362 #define DEBUG_FILE "xboard.debug"
1363 #define SetCurrentDirectory chdir
1364 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1368 // these two must some day move to frontend.h, when they are implemented
1369 Boolean GameListIsUp();
1371 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1374 // front-end part of option handling
1376 // [HGM] This platform-dependent table provides the location for storing the color info
1377 extern char *crWhite, * crBlack;
1381 &appData.whitePieceColor,
1382 &appData.blackPieceColor,
1383 &appData.lightSquareColor,
1384 &appData.darkSquareColor,
1385 &appData.highlightSquareColor,
1386 &appData.premoveHighlightColor,
1387 &appData.lowTimeWarningColor,
1398 // [HGM] font: keep a font for each square size, even non-stndard ones
1399 #define NUM_SIZES 18
1400 #define MAX_SIZE 130
1401 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1402 char *fontTable[NUM_FONTS][MAX_SIZE];
1405 ParseFont(char *name, int number)
1406 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1408 if(sscanf(name, "size%d:", &size)) {
1409 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1410 // defer processing it until we know if it matches our board size
1411 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1412 fontTable[number][size] = strdup(strchr(name, ':')+1);
1413 fontValid[number][size] = True;
1418 case 0: // CLOCK_FONT
1419 appData.clockFont = strdup(name);
1421 case 1: // MESSAGE_FONT
1422 appData.font = strdup(name);
1424 case 2: // COORD_FONT
1425 appData.coordFont = strdup(name);
1430 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1435 { // only 2 fonts currently
1436 appData.clockFont = CLOCK_FONT_NAME;
1437 appData.coordFont = COORD_FONT_NAME;
1438 appData.font = DEFAULT_FONT_NAME;
1443 { // no-op, until we identify the code for this already in XBoard and move it here
1447 ParseColor(int n, char *name)
1448 { // in XBoard, just copy the color-name string
1449 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1453 ParseTextAttribs(ColorClass cc, char *s)
1455 (&appData.colorShout)[cc] = strdup(s);
1459 ParseBoardSize(void *addr, char *name)
1461 appData.boardSize = strdup(name);
1466 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1470 SetCommPortDefaults()
1471 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1474 // [HGM] args: these three cases taken out to stay in front-end
1476 SaveFontArg(FILE *f, ArgDescriptor *ad)
1479 int i, n = (int)ad->argLoc;
1481 case 0: // CLOCK_FONT
1482 name = appData.clockFont;
1484 case 1: // MESSAGE_FONT
1485 name = appData.font;
1487 case 2: // COORD_FONT
1488 name = appData.coordFont;
1493 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1494 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1495 fontTable[n][squareSize] = strdup(name);
1496 fontValid[n][squareSize] = True;
1499 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1500 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1505 { // nothing to do, as the sounds are at all times represented by their text-string names already
1509 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1510 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1511 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1515 SaveColor(FILE *f, ArgDescriptor *ad)
1516 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1517 if(colorVariable[(int)ad->argLoc])
1518 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1522 SaveBoardSize(FILE *f, char *name, void *addr)
1523 { // wrapper to shield back-end from BoardSize & sizeInfo
1524 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1528 ParseCommPortSettings(char *s)
1529 { // no such option in XBoard (yet)
1532 extern Widget engineOutputShell;
1533 extern Widget tagsShell, editTagsShell;
1535 GetActualPlacement(Widget wg, WindowPlacement *wp)
1545 XtSetArg(args[i], XtNx, &x); i++;
1546 XtSetArg(args[i], XtNy, &y); i++;
1547 XtSetArg(args[i], XtNwidth, &w); i++;
1548 XtSetArg(args[i], XtNheight, &h); i++;
1549 XtGetValues(wg, args, i);
1558 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1559 // In XBoard this will have to wait until awareness of window parameters is implemented
1560 GetActualPlacement(shellWidget, &wpMain);
1561 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1562 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1563 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1564 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1565 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1566 else GetActualPlacement(editShell, &wpComment);
1567 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1568 else GetActualPlacement(editTagsShell, &wpTags);
1572 PrintCommPortSettings(FILE *f, char *name)
1573 { // This option does not exist in XBoard
1577 MySearchPath(char *installDir, char *name, char *fullname)
1578 { // just append installDir and name. Perhaps ExpandPath should be used here?
1579 name = ExpandPathName(name);
1580 if(name && name[0] == '/')
1581 safeStrCpy(fullname, name, MSG_SIZ );
1583 sprintf(fullname, "%s%c%s", installDir, '/', name);
1589 MyGetFullPathName(char *name, char *fullname)
1590 { // should use ExpandPath?
1591 name = ExpandPathName(name);
1592 safeStrCpy(fullname, name, MSG_SIZ );
1597 EnsureOnScreen(int *x, int *y, int minX, int minY)
1604 { // [HGM] args: allows testing if main window is realized from back-end
1605 return xBoardWindow != 0;
1609 PopUpStartupDialog()
1610 { // start menu not implemented in XBoard
1614 ConvertToLine(int argc, char **argv)
1616 static char line[128*1024], buf[1024];
1620 for(i=1; i<argc; i++)
1622 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1623 && argv[i][0] != '{' )
1624 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1626 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1627 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1630 line[strlen(line)-1] = NULLCHAR;
1634 //--------------------------------------------------------------------------------------------
1636 extern Boolean twoBoards, partnerUp;
1639 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1641 #define BoardSize int
1642 void InitDrawingSizes(BoardSize boardSize, int flags)
1643 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1644 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1646 XtGeometryResult gres;
1649 if(!formWidget) return;
1652 * Enable shell resizing.
1654 shellArgs[0].value = (XtArgVal) &w;
1655 shellArgs[1].value = (XtArgVal) &h;
1656 XtGetValues(shellWidget, shellArgs, 2);
1658 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1659 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1660 XtSetValues(shellWidget, &shellArgs[2], 4);
1662 XtSetArg(args[0], XtNdefaultDistance, &sep);
1663 XtGetValues(formWidget, args, 1);
1665 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1666 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1668 hOffset = boardWidth + 10;
1669 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1670 secondSegments[i] = gridSegments[i];
1671 secondSegments[i].x1 += hOffset;
1672 secondSegments[i].x2 += hOffset;
1675 XtSetArg(args[0], XtNwidth, boardWidth);
1676 XtSetArg(args[1], XtNheight, boardHeight);
1677 XtSetValues(boardWidget, args, 2);
1679 timerWidth = (boardWidth - sep) / 2;
1680 XtSetArg(args[0], XtNwidth, timerWidth);
1681 XtSetValues(whiteTimerWidget, args, 1);
1682 XtSetValues(blackTimerWidget, args, 1);
1684 XawFormDoLayout(formWidget, False);
1686 if (appData.titleInWindow) {
1688 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1689 XtSetArg(args[i], XtNheight, &h); i++;
1690 XtGetValues(titleWidget, args, i);
1692 w = boardWidth - 2*bor;
1694 XtSetArg(args[0], XtNwidth, &w);
1695 XtGetValues(menuBarWidget, args, 1);
1696 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1699 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1700 if (gres != XtGeometryYes && appData.debugMode) {
1702 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1703 programName, gres, w, h, wr, hr);
1707 XawFormDoLayout(formWidget, True);
1710 * Inhibit shell resizing.
1712 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1713 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1714 shellArgs[4].value = shellArgs[2].value = w;
1715 shellArgs[5].value = shellArgs[3].value = h;
1716 XtSetValues(shellWidget, &shellArgs[0], 6);
1718 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1721 for(i=0; i<4; i++) {
1723 for(p=0; p<=(int)WhiteKing; p++)
1724 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1725 if(gameInfo.variant == VariantShogi) {
1726 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1727 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1728 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1729 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1730 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1733 if(gameInfo.variant == VariantGothic) {
1734 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1737 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1738 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1739 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1742 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1743 for(p=0; p<=(int)WhiteKing; p++)
1744 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1745 if(gameInfo.variant == VariantShogi) {
1746 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1747 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1748 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1749 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1750 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1753 if(gameInfo.variant == VariantGothic) {
1754 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1757 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1758 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1759 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1764 for(i=0; i<2; i++) {
1766 for(p=0; p<=(int)WhiteKing; p++)
1767 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1768 if(gameInfo.variant == VariantShogi) {
1769 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1770 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1771 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1772 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1773 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1776 if(gameInfo.variant == VariantGothic) {
1777 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1780 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1781 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1782 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1797 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1798 XSetWindowAttributes window_attributes;
1800 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1801 XrmValue vFrom, vTo;
1802 XtGeometryResult gres;
1805 int forceMono = False;
1807 srandom(time(0)); // [HGM] book: make random truly random
1809 setbuf(stdout, NULL);
1810 setbuf(stderr, NULL);
1813 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1814 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1818 programName = strrchr(argv[0], '/');
1819 if (programName == NULL)
1820 programName = argv[0];
1825 XtSetLanguageProc(NULL, NULL, NULL);
1826 bindtextdomain(PACKAGE, LOCALEDIR);
1827 textdomain(PACKAGE);
1831 XtAppInitialize(&appContext, "XBoard", shellOptions,
1832 XtNumber(shellOptions),
1833 &argc, argv, xboardResources, NULL, 0);
1834 appData.boardSize = "";
1835 InitAppData(ConvertToLine(argc, argv));
1837 if (p == NULL) p = "/tmp";
1838 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1839 gameCopyFilename = (char*) malloc(i);
1840 gamePasteFilename = (char*) malloc(i);
1841 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1842 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1844 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1845 clientResources, XtNumber(clientResources),
1848 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1849 static char buf[MSG_SIZ];
1850 EscapeExpand(buf, appData.initString);
1851 appData.initString = strdup(buf);
1852 EscapeExpand(buf, appData.secondInitString);
1853 appData.secondInitString = strdup(buf);
1854 EscapeExpand(buf, appData.firstComputerString);
1855 appData.firstComputerString = strdup(buf);
1856 EscapeExpand(buf, appData.secondComputerString);
1857 appData.secondComputerString = strdup(buf);
1860 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1863 if (chdir(chessDir) != 0) {
1864 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1870 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1871 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1872 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1873 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1876 setbuf(debugFP, NULL);
1879 /* [HGM,HR] make sure board size is acceptable */
1880 if(appData.NrFiles > BOARD_FILES ||
1881 appData.NrRanks > BOARD_RANKS )
1882 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1885 /* This feature does not work; animation needs a rewrite */
1886 appData.highlightDragging = FALSE;
1890 xDisplay = XtDisplay(shellWidget);
1891 xScreen = DefaultScreen(xDisplay);
1892 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1894 gameInfo.variant = StringToVariant(appData.variant);
1895 InitPosition(FALSE);
1898 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1900 if (isdigit(appData.boardSize[0])) {
1901 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1902 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1903 &fontPxlSize, &smallLayout, &tinyLayout);
1905 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1906 programName, appData.boardSize);
1910 /* Find some defaults; use the nearest known size */
1911 SizeDefaults *szd, *nearest;
1912 int distance = 99999;
1913 nearest = szd = sizeDefaults;
1914 while (szd->name != NULL) {
1915 if (abs(szd->squareSize - squareSize) < distance) {
1917 distance = abs(szd->squareSize - squareSize);
1918 if (distance == 0) break;
1922 if (i < 2) lineGap = nearest->lineGap;
1923 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1924 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1925 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1926 if (i < 6) smallLayout = nearest->smallLayout;
1927 if (i < 7) tinyLayout = nearest->tinyLayout;
1930 SizeDefaults *szd = sizeDefaults;
1931 if (*appData.boardSize == NULLCHAR) {
1932 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1933 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1936 if (szd->name == NULL) szd--;
1937 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1939 while (szd->name != NULL &&
1940 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1941 if (szd->name == NULL) {
1942 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1943 programName, appData.boardSize);
1947 squareSize = szd->squareSize;
1948 lineGap = szd->lineGap;
1949 clockFontPxlSize = szd->clockFontPxlSize;
1950 coordFontPxlSize = szd->coordFontPxlSize;
1951 fontPxlSize = szd->fontPxlSize;
1952 smallLayout = szd->smallLayout;
1953 tinyLayout = szd->tinyLayout;
1954 // [HGM] font: use defaults from settings file if available and not overruled
1956 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1957 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1958 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1959 appData.font = fontTable[MESSAGE_FONT][squareSize];
1960 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1961 appData.coordFont = fontTable[COORD_FONT][squareSize];
1963 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1964 if (strlen(appData.pixmapDirectory) > 0) {
1965 p = ExpandPathName(appData.pixmapDirectory);
1967 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1968 appData.pixmapDirectory);
1971 if (appData.debugMode) {
1972 fprintf(stderr, _("\
1973 XBoard square size (hint): %d\n\
1974 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1976 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1977 if (appData.debugMode) {
1978 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1981 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1983 /* [HR] height treated separately (hacked) */
1984 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1985 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1986 if (appData.showJail == 1) {
1987 /* Jail on top and bottom */
1988 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1989 XtSetArg(boardArgs[2], XtNheight,
1990 boardHeight + 2*(lineGap + squareSize));
1991 } else if (appData.showJail == 2) {
1993 XtSetArg(boardArgs[1], XtNwidth,
1994 boardWidth + 2*(lineGap + squareSize));
1995 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1998 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1999 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2003 * Determine what fonts to use.
2005 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2006 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2007 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2008 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2009 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2010 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2011 appData.font = FindFont(appData.font, fontPxlSize);
2012 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2013 countFontStruct = XQueryFont(xDisplay, countFontID);
2014 // appData.font = FindFont(appData.font, fontPxlSize);
2016 xdb = XtDatabase(xDisplay);
2017 XrmPutStringResource(&xdb, "*font", appData.font);
2020 * Detect if there are not enough colors available and adapt.
2022 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2023 appData.monoMode = True;
2026 if (!appData.monoMode) {
2027 vFrom.addr = (caddr_t) appData.lightSquareColor;
2028 vFrom.size = strlen(appData.lightSquareColor);
2029 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2030 if (vTo.addr == NULL) {
2031 appData.monoMode = True;
2034 lightSquareColor = *(Pixel *) vTo.addr;
2037 if (!appData.monoMode) {
2038 vFrom.addr = (caddr_t) appData.darkSquareColor;
2039 vFrom.size = strlen(appData.darkSquareColor);
2040 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2041 if (vTo.addr == NULL) {
2042 appData.monoMode = True;
2045 darkSquareColor = *(Pixel *) vTo.addr;
2048 if (!appData.monoMode) {
2049 vFrom.addr = (caddr_t) appData.whitePieceColor;
2050 vFrom.size = strlen(appData.whitePieceColor);
2051 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2052 if (vTo.addr == NULL) {
2053 appData.monoMode = True;
2056 whitePieceColor = *(Pixel *) vTo.addr;
2059 if (!appData.monoMode) {
2060 vFrom.addr = (caddr_t) appData.blackPieceColor;
2061 vFrom.size = strlen(appData.blackPieceColor);
2062 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2063 if (vTo.addr == NULL) {
2064 appData.monoMode = True;
2067 blackPieceColor = *(Pixel *) vTo.addr;
2071 if (!appData.monoMode) {
2072 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2073 vFrom.size = strlen(appData.highlightSquareColor);
2074 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2075 if (vTo.addr == NULL) {
2076 appData.monoMode = True;
2079 highlightSquareColor = *(Pixel *) vTo.addr;
2083 if (!appData.monoMode) {
2084 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2085 vFrom.size = strlen(appData.premoveHighlightColor);
2086 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2087 if (vTo.addr == NULL) {
2088 appData.monoMode = True;
2091 premoveHighlightColor = *(Pixel *) vTo.addr;
2096 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2099 if (appData.bitmapDirectory == NULL ||
2100 appData.bitmapDirectory[0] == NULLCHAR)
2101 appData.bitmapDirectory = DEF_BITMAP_DIR;
2104 if (appData.lowTimeWarning && !appData.monoMode) {
2105 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2106 vFrom.size = strlen(appData.lowTimeWarningColor);
2107 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2108 if (vTo.addr == NULL)
2109 appData.monoMode = True;
2111 lowTimeWarningColor = *(Pixel *) vTo.addr;
2114 if (appData.monoMode && appData.debugMode) {
2115 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2116 (unsigned long) XWhitePixel(xDisplay, xScreen),
2117 (unsigned long) XBlackPixel(xDisplay, xScreen));
2120 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2121 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2122 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2123 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2124 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2125 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2126 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2127 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2128 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2129 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2131 if (appData.colorize) {
2133 _("%s: can't parse color names; disabling colorization\n"),
2136 appData.colorize = FALSE;
2138 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2139 textColors[ColorNone].attr = 0;
2141 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2147 layoutName = "tinyLayout";
2148 } else if (smallLayout) {
2149 layoutName = "smallLayout";
2151 layoutName = "normalLayout";
2153 /* Outer layoutWidget is there only to provide a name for use in
2154 resources that depend on the layout style */
2156 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2157 layoutArgs, XtNumber(layoutArgs));
2159 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2160 formArgs, XtNumber(formArgs));
2161 XtSetArg(args[0], XtNdefaultDistance, &sep);
2162 XtGetValues(formWidget, args, 1);
2165 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2166 XtSetArg(args[0], XtNtop, XtChainTop);
2167 XtSetArg(args[1], XtNbottom, XtChainTop);
2168 XtSetArg(args[2], XtNright, XtChainLeft);
2169 XtSetValues(menuBarWidget, args, 3);
2171 widgetList[j++] = whiteTimerWidget =
2172 XtCreateWidget("whiteTime", labelWidgetClass,
2173 formWidget, timerArgs, XtNumber(timerArgs));
2174 XtSetArg(args[0], XtNfont, clockFontStruct);
2175 XtSetArg(args[1], XtNtop, XtChainTop);
2176 XtSetArg(args[2], XtNbottom, XtChainTop);
2177 XtSetValues(whiteTimerWidget, args, 3);
2179 widgetList[j++] = blackTimerWidget =
2180 XtCreateWidget("blackTime", labelWidgetClass,
2181 formWidget, timerArgs, XtNumber(timerArgs));
2182 XtSetArg(args[0], XtNfont, clockFontStruct);
2183 XtSetArg(args[1], XtNtop, XtChainTop);
2184 XtSetArg(args[2], XtNbottom, XtChainTop);
2185 XtSetValues(blackTimerWidget, args, 3);
2187 if (appData.titleInWindow) {
2188 widgetList[j++] = titleWidget =
2189 XtCreateWidget("title", labelWidgetClass, formWidget,
2190 titleArgs, XtNumber(titleArgs));
2191 XtSetArg(args[0], XtNtop, XtChainTop);
2192 XtSetArg(args[1], XtNbottom, XtChainTop);
2193 XtSetValues(titleWidget, args, 2);
2196 if (appData.showButtonBar) {
2197 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2198 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2199 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2200 XtSetArg(args[2], XtNtop, XtChainTop);
2201 XtSetArg(args[3], XtNbottom, XtChainTop);
2202 XtSetValues(buttonBarWidget, args, 4);
2205 widgetList[j++] = messageWidget =
2206 XtCreateWidget("message", labelWidgetClass, formWidget,
2207 messageArgs, XtNumber(messageArgs));
2208 XtSetArg(args[0], XtNtop, XtChainTop);
2209 XtSetArg(args[1], XtNbottom, XtChainTop);
2210 XtSetValues(messageWidget, args, 2);
2212 widgetList[j++] = boardWidget =
2213 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2214 XtNumber(boardArgs));
2216 XtManageChildren(widgetList, j);
2218 timerWidth = (boardWidth - sep) / 2;
2219 XtSetArg(args[0], XtNwidth, timerWidth);
2220 XtSetValues(whiteTimerWidget, args, 1);
2221 XtSetValues(blackTimerWidget, args, 1);
2223 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2224 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2225 XtGetValues(whiteTimerWidget, args, 2);
2227 if (appData.showButtonBar) {
2228 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2229 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2230 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2234 * formWidget uses these constraints but they are stored
2238 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2239 XtSetValues(menuBarWidget, args, i);
2240 if (appData.titleInWindow) {
2243 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2244 XtSetValues(whiteTimerWidget, args, i);
2246 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2247 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2248 XtSetValues(blackTimerWidget, args, i);
2250 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2251 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2252 XtSetValues(titleWidget, args, i);
2254 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2255 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2256 XtSetValues(messageWidget, args, i);
2257 if (appData.showButtonBar) {
2259 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2260 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2261 XtSetValues(buttonBarWidget, args, i);
2265 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2266 XtSetValues(whiteTimerWidget, args, i);
2268 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2269 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2270 XtSetValues(blackTimerWidget, args, i);
2272 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2273 XtSetValues(titleWidget, args, i);
2275 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2276 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2277 XtSetValues(messageWidget, args, i);
2278 if (appData.showButtonBar) {
2280 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2281 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2282 XtSetValues(buttonBarWidget, args, i);
2287 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2288 XtSetValues(whiteTimerWidget, args, i);
2290 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2291 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2292 XtSetValues(blackTimerWidget, args, i);
2294 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2295 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2296 XtSetValues(messageWidget, args, i);
2297 if (appData.showButtonBar) {
2299 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2300 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2301 XtSetValues(buttonBarWidget, args, i);
2305 XtSetArg(args[0], XtNfromVert, messageWidget);
2306 XtSetArg(args[1], XtNtop, XtChainTop);
2307 XtSetArg(args[2], XtNbottom, XtChainBottom);
2308 XtSetArg(args[3], XtNleft, XtChainLeft);
2309 XtSetArg(args[4], XtNright, XtChainRight);
2310 XtSetValues(boardWidget, args, 5);
2312 XtRealizeWidget(shellWidget);
2315 XtSetArg(args[0], XtNx, wpMain.x);
2316 XtSetArg(args[1], XtNy, wpMain.y);
2317 XtSetValues(shellWidget, args, 2);
2321 * Correct the width of the message and title widgets.
2322 * It is not known why some systems need the extra fudge term.
2323 * The value "2" is probably larger than needed.
2325 XawFormDoLayout(formWidget, False);
2327 #define WIDTH_FUDGE 2
2329 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2330 XtSetArg(args[i], XtNheight, &h); i++;
2331 XtGetValues(messageWidget, args, i);
2332 if (appData.showButtonBar) {
2334 XtSetArg(args[i], XtNwidth, &w); i++;
2335 XtGetValues(buttonBarWidget, args, i);
2336 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2338 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
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 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2348 /* The size used for the child widget in layout lags one resize behind
2349 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2351 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2352 if (gres != XtGeometryYes && appData.debugMode) {
2353 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2354 programName, gres, w, h, wr, hr);
2357 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2358 XtSetArg(args[1], XtNright, XtChainRight);
2359 XtSetValues(messageWidget, args, 2);
2361 if (appData.titleInWindow) {
2363 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2364 XtSetArg(args[i], XtNheight, &h); i++;
2365 XtGetValues(titleWidget, args, i);
2367 w = boardWidth - 2*bor;
2369 XtSetArg(args[0], XtNwidth, &w);
2370 XtGetValues(menuBarWidget, args, 1);
2371 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2374 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2375 if (gres != XtGeometryYes && appData.debugMode) {
2377 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2378 programName, gres, w, h, wr, hr);
2381 XawFormDoLayout(formWidget, True);
2383 xBoardWindow = XtWindow(boardWidget);
2385 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2386 // not need to go into InitDrawingSizes().
2390 * Create X checkmark bitmap and initialize option menu checks.
2392 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2393 checkmark_bits, checkmark_width, checkmark_height);
2394 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2395 if (appData.alwaysPromoteToQueen) {
2396 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2399 if (appData.animateDragging) {
2400 XtSetValues(XtNameToWidget(menuBarWidget,
2401 "menuOptions.Animate Dragging"),
2404 if (appData.animate) {
2405 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2408 if (appData.autoComment) {
2409 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2412 if (appData.autoCallFlag) {
2413 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2416 if (appData.autoFlipView) {
2417 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2420 if (appData.autoObserve) {
2421 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2424 if (appData.autoRaiseBoard) {
2425 XtSetValues(XtNameToWidget(menuBarWidget,
2426 "menuOptions.Auto Raise Board"), args, 1);
2428 if (appData.autoSaveGames) {
2429 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2432 if (appData.saveGameFile[0] != NULLCHAR) {
2433 /* Can't turn this off from menu */
2434 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2436 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2440 if (appData.blindfold) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Blindfold"), args, 1);
2444 if (appData.flashCount > 0) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Flash Moves"),
2449 if (appData.getMoveList) {
2450 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2454 if (appData.highlightDragging) {
2455 XtSetValues(XtNameToWidget(menuBarWidget,
2456 "menuOptions.Highlight Dragging"),
2460 if (appData.highlightLastMove) {
2461 XtSetValues(XtNameToWidget(menuBarWidget,
2462 "menuOptions.Highlight Last Move"),
2465 if (appData.icsAlarm) {
2466 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2469 if (appData.ringBellAfterMoves) {
2470 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2473 if (appData.oldSaveStyle) {
2474 XtSetValues(XtNameToWidget(menuBarWidget,
2475 "menuOptions.Old Save Style"), args, 1);
2477 if (appData.periodicUpdates) {
2478 XtSetValues(XtNameToWidget(menuBarWidget,
2479 "menuOptions.Periodic Updates"), args, 1);
2481 if (appData.ponderNextMove) {
2482 XtSetValues(XtNameToWidget(menuBarWidget,
2483 "menuOptions.Ponder Next Move"), args, 1);
2485 if (appData.popupExitMessage) {
2486 XtSetValues(XtNameToWidget(menuBarWidget,
2487 "menuOptions.Popup Exit Message"), args, 1);
2489 if (appData.popupMoveErrors) {
2490 XtSetValues(XtNameToWidget(menuBarWidget,
2491 "menuOptions.Popup Move Errors"), args, 1);
2493 if (appData.premove) {
2494 XtSetValues(XtNameToWidget(menuBarWidget,
2495 "menuOptions.Premove"), args, 1);
2497 if (appData.quietPlay) {
2498 XtSetValues(XtNameToWidget(menuBarWidget,
2499 "menuOptions.Quiet Play"), args, 1);
2501 if (appData.showCoords) {
2502 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2505 if (appData.hideThinkingFromHuman) {
2506 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2509 if (appData.testLegality) {
2510 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2513 if (saveSettingsOnExit) {
2514 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2521 ReadBitmap(&wIconPixmap, "icon_white.bm",
2522 icon_white_bits, icon_white_width, icon_white_height);
2523 ReadBitmap(&bIconPixmap, "icon_black.bm",
2524 icon_black_bits, icon_black_width, icon_black_height);
2525 iconPixmap = wIconPixmap;
2527 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2528 XtSetValues(shellWidget, args, i);
2531 * Create a cursor for the board widget.
2533 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2534 XChangeWindowAttributes(xDisplay, xBoardWindow,
2535 CWCursor, &window_attributes);
2538 * Inhibit shell resizing.
2540 shellArgs[0].value = (XtArgVal) &w;
2541 shellArgs[1].value = (XtArgVal) &h;
2542 XtGetValues(shellWidget, shellArgs, 2);
2543 shellArgs[4].value = shellArgs[2].value = w;
2544 shellArgs[5].value = shellArgs[3].value = h;
2545 XtSetValues(shellWidget, &shellArgs[2], 4);
2546 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2547 marginH = h - boardHeight;
2549 CatchDeleteWindow(shellWidget, "QuitProc");
2554 if (appData.bitmapDirectory[0] != NULLCHAR) {
2558 CreateXPMBoard(appData.liteBackTextureFile, 1);
2559 CreateXPMBoard(appData.darkBackTextureFile, 0);
2563 /* Create regular pieces */
2564 if (!useImages) CreatePieces();
2569 if (appData.animate || appData.animateDragging)
2572 XtAugmentTranslations(formWidget,
2573 XtParseTranslationTable(globalTranslations));
2574 XtAugmentTranslations(boardWidget,
2575 XtParseTranslationTable(boardTranslations));
2576 XtAugmentTranslations(whiteTimerWidget,
2577 XtParseTranslationTable(whiteTranslations));
2578 XtAugmentTranslations(blackTimerWidget,
2579 XtParseTranslationTable(blackTranslations));
2581 /* Why is the following needed on some versions of X instead
2582 * of a translation? */
2583 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2584 (XtEventHandler) EventProc, NULL);
2587 /* [AS] Restore layout */
2588 if( wpMoveHistory.visible ) {
2592 if( wpEvalGraph.visible )
2597 if( wpEngineOutput.visible ) {
2598 EngineOutputPopUp();
2603 if (errorExitStatus == -1) {
2604 if (appData.icsActive) {
2605 /* We now wait until we see "login:" from the ICS before
2606 sending the logon script (problems with timestamp otherwise) */
2607 /*ICSInitScript();*/
2608 if (appData.icsInputBox) ICSInputBoxPopUp();
2612 signal(SIGWINCH, TermSizeSigHandler);
2614 signal(SIGINT, IntSigHandler);
2615 signal(SIGTERM, IntSigHandler);
2616 if (*appData.cmailGameName != NULLCHAR) {
2617 signal(SIGUSR1, CmailSigHandler);
2620 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2622 XtSetKeyboardFocus(shellWidget, formWidget);
2624 XtAppMainLoop(appContext);
2625 if (appData.debugMode) fclose(debugFP); // [DM] debug
2632 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2633 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2635 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2636 unlink(gameCopyFilename);
2637 unlink(gamePasteFilename);
2640 RETSIGTYPE TermSizeSigHandler(int sig)
2653 CmailSigHandler(sig)
2659 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2661 /* Activate call-back function CmailSigHandlerCallBack() */
2662 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2664 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2668 CmailSigHandlerCallBack(isr, closure, message, count, error)
2676 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2678 /**** end signal code ****/
2684 /* try to open the icsLogon script, either in the location given
2685 * or in the users HOME directory
2692 f = fopen(appData.icsLogon, "r");
2695 homedir = getenv("HOME");
2696 if (homedir != NULL)
2698 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2699 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2700 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2701 f = fopen(buf, "r");
2706 ProcessICSInitScript(f);
2708 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2717 EditCommentPopDown();
2732 if (!menuBarWidget) return;
2733 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2735 DisplayError("menuEdit.Revert", 0);
2737 XtSetSensitive(w, !grey);
2739 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2741 DisplayError("menuEdit.Annotate", 0);
2743 XtSetSensitive(w, !grey);
2748 SetMenuEnables(enab)
2752 if (!menuBarWidget) return;
2753 while (enab->name != NULL) {
2754 w = XtNameToWidget(menuBarWidget, enab->name);
2756 DisplayError(enab->name, 0);
2758 XtSetSensitive(w, enab->value);
2764 Enables icsEnables[] = {
2765 { "menuFile.Mail Move", False },
2766 { "menuFile.Reload CMail Message", False },
2767 { "menuMode.Machine Black", False },
2768 { "menuMode.Machine White", False },
2769 { "menuMode.Analysis Mode", False },
2770 { "menuMode.Analyze File", False },
2771 { "menuMode.Two Machines", False },
2773 { "menuHelp.Hint", False },
2774 { "menuHelp.Book", False },
2775 { "menuEngine.Move Now", False },
2776 { "menuOptions.Periodic Updates", False },
2777 { "menuOptions.Hide Thinking", False },
2778 { "menuOptions.Ponder Next Move", False },
2779 { "menuEngine.Engine #1 Settings", False },
2781 { "menuEngine.Engine #2 Settings", False },
2782 { "menuEdit.Annotate", False },
2786 Enables ncpEnables[] = {
2787 { "menuFile.Mail Move", False },
2788 { "menuFile.Reload CMail Message", False },
2789 { "menuMode.Machine White", False },
2790 { "menuMode.Machine Black", False },
2791 { "menuMode.Analysis Mode", False },
2792 { "menuMode.Analyze File", False },
2793 { "menuMode.Two Machines", False },
2794 { "menuMode.ICS Client", False },
2795 { "menuView.ICS Input Box", False },
2796 { "Action", False },
2797 { "menuEdit.Revert", False },
2798 { "menuEdit.Annotate", False },
2799 { "menuEngine.Engine #1 Settings", False },
2800 { "menuEngine.Engine #2 Settings", False },
2801 { "menuEngine.Move Now", False },
2802 { "menuEngine.Retract Move", False },
2803 { "menuOptions.Auto Comment", False },
2804 { "menuOptions.Auto Flag", False },
2805 { "menuOptions.Auto Flip View", False },
2806 { "menuOptions.Auto Observe", False },
2807 { "menuOptions.Auto Raise Board", False },
2808 { "menuOptions.Get Move List", False },
2809 { "menuOptions.ICS Alarm", False },
2810 { "menuOptions.Move Sound", False },
2811 { "menuOptions.Quiet Play", False },
2812 { "menuOptions.Hide Thinking", False },
2813 { "menuOptions.Periodic Updates", False },
2814 { "menuOptions.Ponder Next Move", False },
2815 { "menuHelp.Hint", False },
2816 { "menuHelp.Book", False },
2820 Enables gnuEnables[] = {
2821 { "menuMode.ICS Client", False },
2822 { "menuView.ICS Input Box", False },
2823 { "menuAction.Accept", False },
2824 { "menuAction.Decline", False },
2825 { "menuAction.Rematch", False },
2826 { "menuAction.Adjourn", False },
2827 { "menuAction.Stop Examining", False },
2828 { "menuAction.Stop Observing", False },
2829 { "menuAction.Upload to Examine", False },
2830 { "menuEdit.Revert", False },
2831 { "menuEdit.Annotate", False },
2832 { "menuOptions.Auto Comment", False },
2833 { "menuOptions.Auto Observe", False },
2834 { "menuOptions.Auto Raise Board", False },
2835 { "menuOptions.Get Move List", False },
2836 { "menuOptions.Premove", False },
2837 { "menuOptions.Quiet Play", False },
2839 /* The next two options rely on SetCmailMode being called *after* */
2840 /* SetGNUMode so that when GNU is being used to give hints these */
2841 /* menu options are still available */
2843 { "menuFile.Mail Move", False },
2844 { "menuFile.Reload CMail Message", False },
2848 Enables cmailEnables[] = {
2850 { "menuAction.Call Flag", False },
2851 { "menuAction.Draw", True },
2852 { "menuAction.Adjourn", False },
2853 { "menuAction.Abort", False },
2854 { "menuAction.Stop Observing", False },
2855 { "menuAction.Stop Examining", False },
2856 { "menuFile.Mail Move", True },
2857 { "menuFile.Reload CMail Message", True },
2861 Enables trainingOnEnables[] = {
2862 { "menuMode.Edit Comment", False },
2863 { "menuMode.Pause", False },
2864 { "menuEdit.Forward", False },
2865 { "menuEdit.Backward", False },
2866 { "menuEdit.Forward to End", False },
2867 { "menuEdit.Back to Start", False },
2868 { "menuEngine.Move Now", False },
2869 { "menuEdit.Truncate Game", False },
2873 Enables trainingOffEnables[] = {
2874 { "menuMode.Edit Comment", True },
2875 { "menuMode.Pause", True },
2876 { "menuEdit.Forward", True },
2877 { "menuEdit.Backward", True },
2878 { "menuEdit.Forward to End", True },
2879 { "menuEdit.Back to Start", True },
2880 { "menuEngine.Move Now", True },
2881 { "menuEdit.Truncate Game", True },
2885 Enables machineThinkingEnables[] = {
2886 { "menuFile.Load Game", False },
2887 // { "menuFile.Load Next Game", False },
2888 // { "menuFile.Load Previous Game", False },
2889 // { "menuFile.Reload Same Game", False },
2890 { "menuEdit.Paste Game", False },
2891 { "menuFile.Load Position", False },
2892 // { "menuFile.Load Next Position", False },
2893 // { "menuFile.Load Previous Position", False },
2894 // { "menuFile.Reload Same Position", False },
2895 { "menuEdit.Paste Position", False },
2896 { "menuMode.Machine White", False },
2897 { "menuMode.Machine Black", False },
2898 { "menuMode.Two Machines", False },
2899 { "menuEngine.Retract Move", False },
2903 Enables userThinkingEnables[] = {
2904 { "menuFile.Load Game", True },
2905 // { "menuFile.Load Next Game", True },
2906 // { "menuFile.Load Previous Game", True },
2907 // { "menuFile.Reload Same Game", True },
2908 { "menuEdit.Paste Game", True },
2909 { "menuFile.Load Position", True },
2910 // { "menuFile.Load Next Position", True },
2911 // { "menuFile.Load Previous Position", True },
2912 // { "menuFile.Reload Same Position", True },
2913 { "menuEdit.Paste Position", True },
2914 { "menuMode.Machine White", True },
2915 { "menuMode.Machine Black", True },
2916 { "menuMode.Two Machines", True },
2917 { "menuEngine.Retract Move", True },
2923 SetMenuEnables(icsEnables);
2926 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2927 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2934 SetMenuEnables(ncpEnables);
2940 SetMenuEnables(gnuEnables);
2946 SetMenuEnables(cmailEnables);
2952 SetMenuEnables(trainingOnEnables);
2953 if (appData.showButtonBar) {
2954 XtSetSensitive(buttonBarWidget, False);
2960 SetTrainingModeOff()
2962 SetMenuEnables(trainingOffEnables);
2963 if (appData.showButtonBar) {
2964 XtSetSensitive(buttonBarWidget, True);
2969 SetUserThinkingEnables()
2971 if (appData.noChessProgram) return;
2972 SetMenuEnables(userThinkingEnables);
2976 SetMachineThinkingEnables()
2978 if (appData.noChessProgram) return;
2979 SetMenuEnables(machineThinkingEnables);
2981 case MachinePlaysBlack:
2982 case MachinePlaysWhite:
2983 case TwoMachinesPlay:
2984 XtSetSensitive(XtNameToWidget(menuBarWidget,
2985 ModeToWidgetName(gameMode)), True);
2992 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2993 #define HISTORY_SIZE 64
\r
2994 static char *history[HISTORY_SIZE];
\r
2995 int histIn = 0, histP = 0;
\r
2998 SaveInHistory(char *cmd)
\r
3000 if (history[histIn] != NULL) {
\r
3001 free(history[histIn]);
\r
3002 history[histIn] = NULL;
\r
3004 if (*cmd == NULLCHAR) return;
\r
3005 history[histIn] = StrSave(cmd);
\r
3006 histIn = (histIn + 1) % HISTORY_SIZE;
\r
3007 if (history[histIn] != NULL) {
\r
3008 free(history[histIn]);
\r
3009 history[histIn] = NULL;
\r
3015 PrevInHistory(char *cmd)
\r
3018 if (histP == histIn) {
\r
3019 if (history[histIn] != NULL) free(history[histIn]);
\r
3020 history[histIn] = StrSave(cmd);
\r
3022 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
3023 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
3025 return history[histP];
\r
3031 if (histP == histIn) return NULL;
\r
3032 histP = (histP + 1) % HISTORY_SIZE;
\r
3033 return history[histP];
\r
3035 // end of borrowed code
\r
3037 #define Abs(n) ((n)<0 ? -(n) : (n))
3040 * Find a font that matches "pattern" that is as close as
3041 * possible to the targetPxlSize. Prefer fonts that are k
3042 * pixels smaller to fonts that are k pixels larger. The
3043 * pattern must be in the X Consortium standard format,
3044 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3045 * The return value should be freed with XtFree when no
3049 FindFont(pattern, targetPxlSize)
3053 char **fonts, *p, *best, *scalable, *scalableTail;
3054 int i, j, nfonts, minerr, err, pxlSize;
3057 char **missing_list;
3059 char *def_string, *base_fnt_lst, strInt[3];
3061 XFontStruct **fnt_list;
3063 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3064 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3065 p = strstr(pattern, "--");
3066 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3067 strcat(base_fnt_lst, strInt);
3068 strcat(base_fnt_lst, strchr(p + 2, '-'));
3070 if ((fntSet = XCreateFontSet(xDisplay,
3074 &def_string)) == NULL) {
3076 fprintf(stderr, _("Unable to create font set.\n"));
3080 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3082 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3084 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3085 programName, pattern);
3093 for (i=0; i<nfonts; i++) {
3096 if (*p != '-') continue;
3098 if (*p == NULLCHAR) break;
3099 if (*p++ == '-') j++;
3101 if (j < 7) continue;
3104 scalable = fonts[i];
3107 err = pxlSize - targetPxlSize;
3108 if (Abs(err) < Abs(minerr) ||
3109 (minerr > 0 && err < 0 && -err == minerr)) {
3115 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3116 /* If the error is too big and there is a scalable font,
3117 use the scalable font. */
3118 int headlen = scalableTail - scalable;
3119 p = (char *) XtMalloc(strlen(scalable) + 10);
3120 while (isdigit(*scalableTail)) scalableTail++;
3121 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3123 p = (char *) XtMalloc(strlen(best) + 2);
3124 safeStrCpy(p, best, strlen(best)+1 );
3126 if (appData.debugMode) {
3127 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3128 pattern, targetPxlSize, p);
3131 if (missing_count > 0)
3132 XFreeStringList(missing_list);
3133 XFreeFontSet(xDisplay, fntSet);
3135 XFreeFontNames(fonts);
3142 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3143 | GCBackground | GCFunction | GCPlaneMask;
3144 XGCValues gc_values;
3147 gc_values.plane_mask = AllPlanes;
3148 gc_values.line_width = lineGap;
3149 gc_values.line_style = LineSolid;
3150 gc_values.function = GXcopy;
3152 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3153 gc_values.background = XBlackPixel(xDisplay, xScreen);
3154 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3156 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3157 gc_values.background = XWhitePixel(xDisplay, xScreen);
3158 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3159 XSetFont(xDisplay, coordGC, coordFontID);
3161 // [HGM] make font for holdings counts (white on black0
3162 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3163 gc_values.background = XBlackPixel(xDisplay, xScreen);
3164 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3165 XSetFont(xDisplay, countGC, countFontID);
3167 if (appData.monoMode) {
3168 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3169 gc_values.background = XWhitePixel(xDisplay, xScreen);
3170 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3172 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3173 gc_values.background = XBlackPixel(xDisplay, xScreen);
3174 lightSquareGC = wbPieceGC
3175 = XtGetGC(shellWidget, value_mask, &gc_values);
3177 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3178 gc_values.background = XWhitePixel(xDisplay, xScreen);
3179 darkSquareGC = bwPieceGC
3180 = XtGetGC(shellWidget, value_mask, &gc_values);
3182 if (DefaultDepth(xDisplay, xScreen) == 1) {
3183 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3184 gc_values.function = GXcopyInverted;
3185 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3186 gc_values.function = GXcopy;
3187 if (XBlackPixel(xDisplay, xScreen) == 1) {
3188 bwPieceGC = darkSquareGC;
3189 wbPieceGC = copyInvertedGC;
3191 bwPieceGC = copyInvertedGC;
3192 wbPieceGC = lightSquareGC;
3196 gc_values.foreground = highlightSquareColor;
3197 gc_values.background = highlightSquareColor;
3198 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3200 gc_values.foreground = premoveHighlightColor;
3201 gc_values.background = premoveHighlightColor;
3202 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3204 gc_values.foreground = lightSquareColor;
3205 gc_values.background = darkSquareColor;
3206 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3208 gc_values.foreground = darkSquareColor;
3209 gc_values.background = lightSquareColor;
3210 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3212 gc_values.foreground = jailSquareColor;
3213 gc_values.background = jailSquareColor;
3214 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3216 gc_values.foreground = whitePieceColor;
3217 gc_values.background = darkSquareColor;
3218 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3220 gc_values.foreground = whitePieceColor;
3221 gc_values.background = lightSquareColor;
3222 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3224 gc_values.foreground = whitePieceColor;
3225 gc_values.background = jailSquareColor;
3226 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3228 gc_values.foreground = blackPieceColor;
3229 gc_values.background = darkSquareColor;
3230 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3232 gc_values.foreground = blackPieceColor;
3233 gc_values.background = lightSquareColor;
3234 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3236 gc_values.foreground = blackPieceColor;
3237 gc_values.background = jailSquareColor;
3238 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3242 void loadXIM(xim, xmask, filename, dest, mask)
3255 fp = fopen(filename, "rb");
3257 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3264 for (y=0; y<h; ++y) {
3265 for (x=0; x<h; ++x) {
3270 XPutPixel(xim, x, y, blackPieceColor);
3272 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3275 XPutPixel(xim, x, y, darkSquareColor);
3277 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3280 XPutPixel(xim, x, y, whitePieceColor);
3282 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3285 XPutPixel(xim, x, y, lightSquareColor);
3287 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3293 /* create Pixmap of piece */
3294 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3296 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3299 /* create Pixmap of clipmask
3300 Note: We assume the white/black pieces have the same
3301 outline, so we make only 6 masks. This is okay
3302 since the XPM clipmask routines do the same. */
3304 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3306 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3309 /* now create the 1-bit version */
3310 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3313 values.foreground = 1;
3314 values.background = 0;
3316 /* Don't use XtGetGC, not read only */
3317 maskGC = XCreateGC(xDisplay, *mask,
3318 GCForeground | GCBackground, &values);
3319 XCopyPlane(xDisplay, temp, *mask, maskGC,
3320 0, 0, squareSize, squareSize, 0, 0, 1);
3321 XFreePixmap(xDisplay, temp);
3326 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3328 void CreateXIMPieces()
3333 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3338 /* The XSynchronize calls were copied from CreatePieces.
3339 Not sure if needed, but can't hurt */
3340 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3343 /* temp needed by loadXIM() */
3344 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3345 0, 0, ss, ss, AllPlanes, XYPixmap);
3347 if (strlen(appData.pixmapDirectory) == 0) {
3351 if (appData.monoMode) {
3352 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3356 fprintf(stderr, _("\nLoading XIMs...\n"));
3358 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3359 fprintf(stderr, "%d", piece+1);
3360 for (kind=0; kind<4; kind++) {
3361 fprintf(stderr, ".");
3362 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3363 ExpandPathName(appData.pixmapDirectory),
3364 piece <= (int) WhiteKing ? "" : "w",
3365 pieceBitmapNames[piece],
3367 ximPieceBitmap[kind][piece] =
3368 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3369 0, 0, ss, ss, AllPlanes, XYPixmap);
3370 if (appData.debugMode)
3371 fprintf(stderr, _("(File:%s:) "), buf);
3372 loadXIM(ximPieceBitmap[kind][piece],
3374 &(xpmPieceBitmap2[kind][piece]),
3375 &(ximMaskPm2[piece]));
3376 if(piece <= (int)WhiteKing)
3377 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3379 fprintf(stderr," ");
3381 /* Load light and dark squares */
3382 /* If the LSQ and DSQ pieces don't exist, we will
3383 draw them with solid squares. */
3384 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3385 if (access(buf, 0) != 0) {
3389 fprintf(stderr, _("light square "));
3391 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3392 0, 0, ss, ss, AllPlanes, XYPixmap);
3393 if (appData.debugMode)
3394 fprintf(stderr, _("(File:%s:) "), buf);
3396 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3397 fprintf(stderr, _("dark square "));
3398 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3399 ExpandPathName(appData.pixmapDirectory), ss);
3400 if (appData.debugMode)
3401 fprintf(stderr, _("(File:%s:) "), buf);
3403 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3404 0, 0, ss, ss, AllPlanes, XYPixmap);
3405 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3406 xpmJailSquare = xpmLightSquare;
3408 fprintf(stderr, _("Done.\n"));
3410 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3414 void CreateXPMBoard(char *s, int kind)
3418 if(s == NULL || *s == 0 || *s == '*') return;
3419 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3420 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3424 void CreateXPMPieces()
3428 u_int ss = squareSize;
3430 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3431 XpmColorSymbol symbols[4];
3433 /* The XSynchronize calls were copied from CreatePieces.
3434 Not sure if needed, but can't hurt */
3435 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3437 /* Setup translations so piece colors match square colors */
3438 symbols[0].name = "light_piece";
3439 symbols[0].value = appData.whitePieceColor;
3440 symbols[1].name = "dark_piece";
3441 symbols[1].value = appData.blackPieceColor;
3442 symbols[2].name = "light_square";
3443 symbols[2].value = appData.lightSquareColor;
3444 symbols[3].name = "dark_square";
3445 symbols[3].value = appData.darkSquareColor;
3447 attr.valuemask = XpmColorSymbols;
3448 attr.colorsymbols = symbols;
3449 attr.numsymbols = 4;
3451 if (appData.monoMode) {
3452 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3456 if (strlen(appData.pixmapDirectory) == 0) {
3457 XpmPieces* pieces = builtInXpms;
3460 while (pieces->size != squareSize && pieces->size) pieces++;
3461 if (!pieces->size) {
3462 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3465 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3466 for (kind=0; kind<4; kind++) {
3468 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3469 pieces->xpm[piece][kind],
3470 &(xpmPieceBitmap2[kind][piece]),
3471 NULL, &attr)) != 0) {
3472 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3476 if(piece <= (int) WhiteKing)
3477 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3481 xpmJailSquare = xpmLightSquare;
3485 fprintf(stderr, _("\nLoading XPMs...\n"));
3488 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3489 fprintf(stderr, "%d ", piece+1);
3490 for (kind=0; kind<4; kind++) {
3491 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3492 ExpandPathName(appData.pixmapDirectory),
3493 piece > (int) WhiteKing ? "w" : "",
3494 pieceBitmapNames[piece],
3496 if (appData.debugMode) {
3497 fprintf(stderr, _("(File:%s:) "), buf);
3499 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3500 &(xpmPieceBitmap2[kind][piece]),
3501 NULL, &attr)) != 0) {
3502 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3503 // [HGM] missing: read of unorthodox piece failed; substitute King.
3504 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3505 ExpandPathName(appData.pixmapDirectory),
3507 if (appData.debugMode) {
3508 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3510 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3511 &(xpmPieceBitmap2[kind][piece]),
3515 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3520 if(piece <= (int) WhiteKing)
3521 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3524 /* Load light and dark squares */
3525 /* If the LSQ and DSQ pieces don't exist, we will
3526 draw them with solid squares. */
3527 fprintf(stderr, _("light square "));
3528 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3529 if (access(buf, 0) != 0) {
3533 if (appData.debugMode)
3534 fprintf(stderr, _("(File:%s:) "), buf);
3536 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3537 &xpmLightSquare, NULL, &attr)) != 0) {
3538 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3541 fprintf(stderr, _("dark square "));
3542 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3543 ExpandPathName(appData.pixmapDirectory), ss);
3544 if (appData.debugMode) {
3545 fprintf(stderr, _("(File:%s:) "), buf);
3547 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3548 &xpmDarkSquare, NULL, &attr)) != 0) {
3549 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3553 xpmJailSquare = xpmLightSquare;
3554 fprintf(stderr, _("Done.\n"));
3556 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3559 #endif /* HAVE_LIBXPM */
3562 /* No built-in bitmaps */
3567 u_int ss = squareSize;
3569 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3572 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3573 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3574 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3575 pieceBitmapNames[piece],
3576 ss, kind == SOLID ? 's' : 'o');
3577 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3578 if(piece <= (int)WhiteKing)
3579 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3583 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3587 /* With built-in bitmaps */
3590 BuiltInBits* bib = builtInBits;
3593 u_int ss = squareSize;
3595 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3598 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3600 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3601 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3602 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3603 pieceBitmapNames[piece],
3604 ss, kind == SOLID ? 's' : 'o');
3605 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3606 bib->bits[kind][piece], ss, ss);
3607 if(piece <= (int)WhiteKing)
3608 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3612 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3617 void ReadBitmap(pm, name, bits, wreq, hreq)
3620 unsigned char bits[];
3626 char msg[MSG_SIZ], fullname[MSG_SIZ];
3628 if (*appData.bitmapDirectory != NULLCHAR) {
3629 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3630 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3631 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3632 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3633 &w, &h, pm, &x_hot, &y_hot);
3634 fprintf(stderr, "load %s\n", name);
3635 if (errcode != BitmapSuccess) {
3637 case BitmapOpenFailed:
3638 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3640 case BitmapFileInvalid:
3641 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3643 case BitmapNoMemory:
3644 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3648 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3652 fprintf(stderr, _("%s: %s...using built-in\n"),
3654 } else if (w != wreq || h != hreq) {
3656 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3657 programName, fullname, w, h, wreq, hreq);
3663 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3672 if (lineGap == 0) return;
3674 /* [HR] Split this into 2 loops for non-square boards. */
3676 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3677 gridSegments[i].x1 = 0;
3678 gridSegments[i].x2 =
3679 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3680 gridSegments[i].y1 = gridSegments[i].y2
3681 = lineGap / 2 + (i * (squareSize + lineGap));
3684 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3685 gridSegments[j + i].y1 = 0;
3686 gridSegments[j + i].y2 =
3687 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3688 gridSegments[j + i].x1 = gridSegments[j + i].x2
3689 = lineGap / 2 + (j * (squareSize + lineGap));
3693 static void MenuBarSelect(w, addr, index)
3698 XtActionProc proc = (XtActionProc) addr;
3700 (proc)(NULL, NULL, NULL, NULL);
3703 void CreateMenuBarPopup(parent, name, mb)
3713 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3716 XtSetArg(args[j], XtNleftMargin, 20); j++;
3717 XtSetArg(args[j], XtNrightMargin, 20); j++;
3719 while (mi->string != NULL) {
3720 if (strcmp(mi->string, "----") == 0) {
3721 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3724 XtSetArg(args[j], XtNlabel, XtNewString(mi->string));
3725 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3727 XtAddCallback(entry, XtNcallback,
3728 (XtCallbackProc) MenuBarSelect,
3729 (caddr_t) mi->proc);
3735 Widget CreateMenuBar(mb)
3739 Widget anchor, menuBar;
3741 char menuName[MSG_SIZ];
3744 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3745 XtSetArg(args[j], XtNvSpace, 0); j++;
3746 XtSetArg(args[j], XtNborderWidth, 0); j++;
3747 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3748 formWidget, args, j);
3750 while (mb->name != NULL) {
3751 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3752 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3754 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3757 shortName[0] = mb->name[0];
3758 shortName[1] = NULLCHAR;
3759 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3762 XtSetArg(args[j], XtNlabel, XtNewString(mb->name)); j++;
3765 XtSetArg(args[j], XtNborderWidth, 0); j++;
3766 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3768 CreateMenuBarPopup(menuBar, menuName, mb);
3774 Widget CreateButtonBar(mi)
3778 Widget button, buttonBar;
3782 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3784 XtSetArg(args[j], XtNhSpace, 0); j++;
3786 XtSetArg(args[j], XtNborderWidth, 0); j++;
3787 XtSetArg(args[j], XtNvSpace, 0); j++;
3788 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3789 formWidget, args, j);
3791 while (mi->string != NULL) {
3794 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3795 XtSetArg(args[j], XtNborderWidth, 0); j++;
3797 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3798 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3799 buttonBar, args, j);
3800 XtAddCallback(button, XtNcallback,
3801 (XtCallbackProc) MenuBarSelect,
3802 (caddr_t) mi->proc);
3809 CreatePieceMenu(name, color)
3816 ChessSquare selection;
3818 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3819 boardWidget, args, 0);
3821 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3822 String item = pieceMenuStrings[color][i];
3824 if (strcmp(item, "----") == 0) {
3825 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3828 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3829 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3831 selection = pieceMenuTranslation[color][i];
3832 XtAddCallback(entry, XtNcallback,
3833 (XtCallbackProc) PieceMenuSelect,
3834 (caddr_t) selection);
3835 if (selection == WhitePawn || selection == BlackPawn) {
3836 XtSetArg(args[0], XtNpopupOnEntry, entry);
3837 XtSetValues(menu, args, 1);
3850 ChessSquare selection;
3852 whitePieceMenu = CreatePieceMenu("menuW", 0);
3853 blackPieceMenu = CreatePieceMenu("menuB", 1);
3855 XtRegisterGrabAction(PieceMenuPopup, True,
3856 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3857 GrabModeAsync, GrabModeAsync);
3859 XtSetArg(args[0], XtNlabel, _("Drop"));
3860 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3861 boardWidget, args, 1);
3862 for (i = 0; i < DROP_MENU_SIZE; i++) {
3863 String item = dropMenuStrings[i];
3865 if (strcmp(item, "----") == 0) {
3866 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3869 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3870 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3872 selection = dropMenuTranslation[i];
3873 XtAddCallback(entry, XtNcallback,
3874 (XtCallbackProc) DropMenuSelect,
3875 (caddr_t) selection);
3880 void SetupDropMenu()
3888 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3889 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3890 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3891 dmEnables[i].piece);
3892 XtSetSensitive(entry, p != NULL || !appData.testLegality
3893 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3894 && !appData.icsActive));
3896 while (p && *p++ == dmEnables[i].piece) count++;
3897 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3899 XtSetArg(args[j], XtNlabel, label); j++;
3900 XtSetValues(entry, args, j);
3904 void PieceMenuPopup(w, event, params, num_params)
3908 Cardinal *num_params;
3910 String whichMenu; int menuNr;
3911 if (event->type == ButtonRelease)
3912 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3913 else if (event->type == ButtonPress)
3914 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3916 case 0: whichMenu = params[0]; break;
3917 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3919 case -1: if (errorUp) ErrorPopDown();
3922 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3925 static void PieceMenuSelect(w, piece, junk)
3930 if (pmFromX < 0 || pmFromY < 0) return;
3931 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3934 static void DropMenuSelect(w, piece, junk)
3939 if (pmFromX < 0 || pmFromY < 0) return;
3940 DropMenuEvent(piece, pmFromX, pmFromY);
3943 void WhiteClock(w, event, prms, nprms)
3949 if (gameMode == EditPosition || gameMode == IcsExamining) {
3950 SetWhiteToPlayEvent();
3951 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3956 void BlackClock(w, event, prms, nprms)
3962 if (gameMode == EditPosition || gameMode == IcsExamining) {
3963 SetBlackToPlayEvent();
3964 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3971 * If the user selects on a border boundary, return -1; if off the board,
3972 * return -2. Otherwise map the event coordinate to the square.
3974 int EventToSquare(x, limit)
3982 if ((x % (squareSize + lineGap)) >= squareSize)
3984 x /= (squareSize + lineGap);
3990 static void do_flash_delay(msec)
3996 static void drawHighlight(file, rank, gc)
4002 if (lineGap == 0 || appData.blindfold) return;
4005 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4006 (squareSize + lineGap);
4007 y = lineGap/2 + rank * (squareSize + lineGap);
4009 x = lineGap/2 + file * (squareSize + lineGap);
4010 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4011 (squareSize + lineGap);
4014 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4015 squareSize+lineGap, squareSize+lineGap);
4018 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4019 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4022 SetHighlights(fromX, fromY, toX, toY)
4023 int fromX, fromY, toX, toY;
4025 if (hi1X != fromX || hi1Y != fromY) {
4026 if (hi1X >= 0 && hi1Y >= 0) {
4027 drawHighlight(hi1X, hi1Y, lineGC);
4029 } // [HGM] first erase both, then draw new!
4030 if (hi2X != toX || hi2Y != toY) {
4031 if (hi2X >= 0 && hi2Y >= 0) {
4032 drawHighlight(hi2X, hi2Y, lineGC);
4035 if (hi1X != fromX || hi1Y != fromY) {
4036 if (fromX >= 0 && fromY >= 0) {
4037 drawHighlight(fromX, fromY, highlineGC);
4040 if (hi2X != toX || hi2Y != toY) {
4041 if (toX >= 0 && toY >= 0) {
4042 drawHighlight(toX, toY, highlineGC);
4054 SetHighlights(-1, -1, -1, -1);
4059 SetPremoveHighlights(fromX, fromY, toX, toY)
4060 int fromX, fromY, toX, toY;
4062 if (pm1X != fromX || pm1Y != fromY) {
4063 if (pm1X >= 0 && pm1Y >= 0) {
4064 drawHighlight(pm1X, pm1Y, lineGC);
4066 if (fromX >= 0 && fromY >= 0) {
4067 drawHighlight(fromX, fromY, prelineGC);
4070 if (pm2X != toX || pm2Y != toY) {
4071 if (pm2X >= 0 && pm2Y >= 0) {
4072 drawHighlight(pm2X, pm2Y, lineGC);
4074 if (toX >= 0 && toY >= 0) {
4075 drawHighlight(toX, toY, prelineGC);
4085 ClearPremoveHighlights()
4087 SetPremoveHighlights(-1, -1, -1, -1);
4090 static int CutOutSquare(x, y, x0, y0, kind)
4091 int x, y, *x0, *y0, kind;
4093 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4094 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4096 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4097 if(textureW[kind] < W*squareSize)
4098 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4100 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4101 if(textureH[kind] < H*squareSize)
4102 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4104 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4108 static void BlankSquare(x, y, color, piece, dest, fac)
4109 int x, y, color, fac;
4112 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4114 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4115 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4116 squareSize, squareSize, x*fac, y*fac);
4118 if (useImages && useImageSqs) {
4122 pm = xpmLightSquare;
4127 case 2: /* neutral */
4132 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4133 squareSize, squareSize, x*fac, y*fac);
4143 case 2: /* neutral */
4148 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4153 I split out the routines to draw a piece so that I could
4154 make a generic flash routine.
4156 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4158 int square_color, x, y;
4161 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4162 switch (square_color) {
4164 case 2: /* neutral */
4166 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4167 ? *pieceToOutline(piece)
4168 : *pieceToSolid(piece),
4169 dest, bwPieceGC, 0, 0,
4170 squareSize, squareSize, x, y);
4173 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4174 ? *pieceToSolid(piece)
4175 : *pieceToOutline(piece),
4176 dest, wbPieceGC, 0, 0,
4177 squareSize, squareSize, x, y);
4182 static void monoDrawPiece(piece, square_color, x, y, dest)
4184 int square_color, x, y;
4187 switch (square_color) {
4189 case 2: /* neutral */
4191 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4192 ? *pieceToOutline(piece)
4193 : *pieceToSolid(piece),
4194 dest, bwPieceGC, 0, 0,
4195 squareSize, squareSize, x, y, 1);
4198 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4199 ? *pieceToSolid(piece)
4200 : *pieceToOutline(piece),
4201 dest, wbPieceGC, 0, 0,
4202 squareSize, squareSize, x, y, 1);
4207 static void colorDrawPiece(piece, square_color, x, y, dest)
4209 int square_color, x, y;
4212 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4213 switch (square_color) {
4215 XCopyPlane(xDisplay, *pieceToSolid(piece),
4216 dest, (int) piece < (int) BlackPawn
4217 ? wlPieceGC : blPieceGC, 0, 0,
4218 squareSize, squareSize, x, y, 1);
4221 XCopyPlane(xDisplay, *pieceToSolid(piece),
4222 dest, (int) piece < (int) BlackPawn
4223 ? wdPieceGC : bdPieceGC, 0, 0,
4224 squareSize, squareSize, x, y, 1);
4226 case 2: /* neutral */
4228 XCopyPlane(xDisplay, *pieceToSolid(piece),
4229 dest, (int) piece < (int) BlackPawn
4230 ? wjPieceGC : bjPieceGC, 0, 0,
4231 squareSize, squareSize, x, y, 1);
4236 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4238 int square_color, x, y;
4241 int kind, p = piece;
4243 switch (square_color) {
4245 case 2: /* neutral */