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, 2011 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>
66 # if HAVE_SYS_SOCKET_H
67 # include <sys/socket.h>
68 # include <netinet/in.h>
70 # else /* not HAVE_SYS_SOCKET_H */
71 # if HAVE_LAN_SOCKET_H
72 # include <lan/socket.h>
74 # include <lan/netdb.h>
75 # else /* not HAVE_LAN_SOCKET_H */
76 # define OMIT_SOCKETS 1
77 # endif /* not HAVE_LAN_SOCKET_H */
78 # endif /* not HAVE_SYS_SOCKET_H */
79 #endif /* !OMIT_SOCKETS */
84 #else /* not STDC_HEADERS */
85 extern char *getenv();
88 # else /* not HAVE_STRING_H */
90 # endif /* not HAVE_STRING_H */
91 #endif /* not STDC_HEADERS */
94 # include <sys/fcntl.h>
95 #else /* not HAVE_SYS_FCNTL_H */
98 # endif /* HAVE_FCNTL_H */
99 #endif /* not HAVE_SYS_FCNTL_H */
101 #if HAVE_SYS_SYSTEMINFO_H
102 # include <sys/systeminfo.h>
103 #endif /* HAVE_SYS_SYSTEMINFO_H */
105 #if TIME_WITH_SYS_TIME
106 # include <sys/time.h>
110 # include <sys/time.h>
121 # include <sys/wait.h>
126 # define NAMLEN(dirent) strlen((dirent)->d_name)
127 # define HAVE_DIR_STRUCT
129 # define dirent direct
130 # define NAMLEN(dirent) (dirent)->d_namlen
132 # include <sys/ndir.h>
133 # define HAVE_DIR_STRUCT
136 # include <sys/dir.h>
137 # define HAVE_DIR_STRUCT
141 # define HAVE_DIR_STRUCT
145 #include <X11/Intrinsic.h>
146 #include <X11/StringDefs.h>
147 #include <X11/Shell.h>
148 #include <X11/cursorfont.h>
149 #include <X11/Xatom.h>
150 #include <X11/Xmu/Atoms.h>
152 #include <X11/Xaw3d/Dialog.h>
153 #include <X11/Xaw3d/Form.h>
154 #include <X11/Xaw3d/List.h>
155 #include <X11/Xaw3d/Label.h>
156 #include <X11/Xaw3d/SimpleMenu.h>
157 #include <X11/Xaw3d/SmeBSB.h>
158 #include <X11/Xaw3d/SmeLine.h>
159 #include <X11/Xaw3d/Box.h>
160 #include <X11/Xaw3d/MenuButton.h>
161 #include <X11/Xaw3d/Text.h>
162 #include <X11/Xaw3d/AsciiText.h>
164 #include <X11/Xaw/Dialog.h>
165 #include <X11/Xaw/Form.h>
166 #include <X11/Xaw/List.h>
167 #include <X11/Xaw/Label.h>
168 #include <X11/Xaw/SimpleMenu.h>
169 #include <X11/Xaw/SmeBSB.h>
170 #include <X11/Xaw/SmeLine.h>
171 #include <X11/Xaw/Box.h>
172 #include <X11/Xaw/MenuButton.h>
173 #include <X11/Xaw/Text.h>
174 #include <X11/Xaw/AsciiText.h>
177 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
182 #include "pixmaps/pixmaps.h"
183 #define IMAGE_EXT "xpm"
185 #define IMAGE_EXT "xim"
186 #include "bitmaps/bitmaps.h"
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
195 #include "backendz.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
204 // must be moved to xengineoutput.h
206 void EngineOutputProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
208 void EvalGraphProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
216 #define usleep(t) _sleep2(((t)+500)/1000)
220 # define _(s) gettext (s)
221 # define N_(s) gettext_noop (s)
239 int main P((int argc, char **argv));
240 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
241 char *init_path, char *mode, int (*show_entry)(), char **name_return));
242 RETSIGTYPE CmailSigHandler P((int sig));
243 RETSIGTYPE IntSigHandler P((int sig));
244 RETSIGTYPE TermSizeSigHandler P((int sig));
245 void CreateGCs P((int redo));
246 void CreateXIMPieces P((void));
247 void CreateXPMPieces P((void));
248 void CreateXPMBoard P((char *s, int n));
249 void CreatePieces P((void));
250 void CreatePieceMenus P((void));
251 Widget CreateMenuBar P((Menu *mb));
252 Widget CreateButtonBar P ((MenuItem *mi));
253 char *FindFont P((char *pattern, int targetPxlSize));
254 void PieceMenuPopup P((Widget w, XEvent *event,
255 String *params, Cardinal *num_params));
256 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
257 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
259 u_int wreq, u_int hreq));
260 void CreateGrid P((void));
261 int EventToSquare P((int x, int limit));
262 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
263 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
264 void HandleUserMove P((Widget w, XEvent *event,
265 String *prms, Cardinal *nprms));
266 void AnimateUserMove P((Widget w, XEvent * event,
267 String * params, Cardinal * nParams));
268 void HandlePV P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void SelectPV P((Widget w, XEvent * event,
271 String * params, Cardinal * nParams));
272 void StopPV P((Widget w, XEvent * event,
273 String * params, Cardinal * nParams));
274 void WhiteClock P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void BlackClock P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void DrawPositionProc P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
282 void CommentClick P((Widget w, XEvent * event,
283 String * params, Cardinal * nParams));
284 void CommentPopUp P((char *title, char *label));
285 void CommentPopDown P((void));
286 void CommentCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void ICSInputBoxPopUp P((void));
289 void ICSInputBoxPopDown P((void));
290 void FileNamePopUp P((char *label, char *def,
291 FileProc proc, char *openMode));
292 void FileNamePopDown P((void));
293 void FileNameCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void FileNameAction P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void AskQuestionReplyAction P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void AskQuestionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void AskQuestionPopDown P((void));
302 void PromotionPopDown P((void));
303 void PromotionCallback P((Widget w, XtPointer client_data,
304 XtPointer call_data));
305 void EditCommentPopDown P((void));
306 void EditCommentCallback P((Widget w, XtPointer client_data,
307 XtPointer call_data));
308 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
309 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
313 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
315 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
317 void LoadPositionProc P((Widget w, XEvent *event,
318 String *prms, Cardinal *nprms));
319 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
321 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
323 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
325 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
327 void PastePositionProc P((Widget w, XEvent *event, String *prms,
329 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void SavePositionProc P((Widget w, XEvent *event,
333 String *prms, Cardinal *nprms));
334 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
337 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
341 void MachineWhiteProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void AnalyzeModeProc P((Widget w, XEvent *event,
344 String *prms, Cardinal *nprms));
345 void AnalyzeFileProc P((Widget w, XEvent *event,
346 String *prms, Cardinal *nprms));
347 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
349 void IcsClientProc P((Widget w, XEvent *event, String *prms,
351 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EditPositionProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void EditCommentProc P((Widget w, XEvent *event,
356 String *prms, Cardinal *nprms));
357 void IcsInputBoxProc P((Widget w, XEvent *event,
358 String *prms, Cardinal *nprms));
359 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void StopObservingProc P((Widget w, XEvent *event, String *prms,
375 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
377 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
386 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
388 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
391 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
393 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
395 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
400 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
403 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
405 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
407 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
412 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
414 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
416 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
418 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
421 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
423 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
425 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
427 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void DisplayMove P((int moveNumber));
439 void DisplayTitle P((char *title));
440 void ICSInitScript P((void));
441 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
442 void ErrorPopUp P((char *title, char *text, int modal));
443 void ErrorPopDown P((void));
444 static char *ExpandPathName P((char *path));
445 static void CreateAnimVars P((void));
446 static void DragPieceMove P((int x, int y));
447 static void DrawDragPiece P((void));
448 char *ModeToWidgetName P((GameMode mode));
449 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
450 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void GameListOptionsPopDown P(());
461 void ShufflePopDown P(());
462 void EnginePopDown P(());
463 void UciPopDown P(());
464 void TimeControlPopDown P(());
465 void NewVariantPopDown P(());
466 void SettingsPopDown P(());
467 void update_ics_width P(());
468 int get_term_width P(());
469 int CopyMemoProc P(());
470 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
471 Boolean IsDrawArrowEnabled P(());
474 * XBoard depends on Xt R4 or higher
476 int xtVersion = XtSpecificationRelease;
481 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
482 jailSquareColor, highlightSquareColor, premoveHighlightColor;
483 Pixel lowTimeWarningColor;
484 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
485 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
486 wjPieceGC, bjPieceGC, prelineGC, countGC;
487 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
488 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
489 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
490 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
491 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
492 ICSInputShell, fileNameShell, askQuestionShell;
493 Widget historyShell, evalGraphShell, gameListShell;
494 int hOffset; // [HGM] dual
495 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
496 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
497 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
498 Font clockFontID, coordFontID, countFontID;
499 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
500 XtAppContext appContext;
502 char *oldICSInteractionTitle;
506 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
508 Position commentX = -1, commentY = -1;
509 Dimension commentW, commentH;
510 typedef unsigned int BoardSize;
512 Boolean chessProgram;
514 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
515 int squareSize, smallLayout = 0, tinyLayout = 0,
516 marginW, marginH, // [HGM] for run-time resizing
517 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
518 ICSInputBoxUp = False, askQuestionUp = False,
519 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
520 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
521 Pixel timerForegroundPixel, timerBackgroundPixel;
522 Pixel buttonForegroundPixel, buttonBackgroundPixel;
523 char *chessDir, *programName, *programVersion,
524 *gameCopyFilename, *gamePasteFilename;
525 Boolean alwaysOnTop = False;
526 Boolean saveSettingsOnExit;
527 char *settingsFileName;
528 char *icsTextMenuString;
530 char *firstChessProgramNames;
531 char *secondChessProgramNames;
533 WindowPlacement wpMain;
534 WindowPlacement wpConsole;
535 WindowPlacement wpComment;
536 WindowPlacement wpMoveHistory;
537 WindowPlacement wpEvalGraph;
538 WindowPlacement wpEngineOutput;
539 WindowPlacement wpGameList;
540 WindowPlacement wpTags;
544 Pixmap pieceBitmap[2][(int)BlackPawn];
545 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
546 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
547 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
548 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
549 Pixmap xpmBoardBitmap[2];
550 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
551 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
552 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
553 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
554 XImage *ximLightSquare, *ximDarkSquare;
557 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
558 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
560 #define White(piece) ((int)(piece) < (int)BlackPawn)
562 /* Variables for doing smooth animation. This whole thing
563 would be much easier if the board was double-buffered,
564 but that would require a fairly major rewrite. */
569 GC blitGC, pieceGC, outlineGC;
570 XPoint startSquare, prevFrame, mouseDelta;
574 int startBoardX, startBoardY;
577 /* There can be two pieces being animated at once: a player
578 can begin dragging a piece before the remote opponent has moved. */
580 static AnimState game, player;
582 /* Bitmaps for use as masks when drawing XPM pieces.
583 Need one for each black and white piece. */
584 static Pixmap xpmMask[BlackKing + 1];
586 /* This magic number is the number of intermediate frames used
587 in each half of the animation. For short moves it's reduced
588 by 1. The total number of frames will be factor * 2 + 1. */
591 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
593 MenuItem fileMenu[] = {
594 {N_("New Game Ctrl+N"), "New Game", ResetProc},
595 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
596 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
597 {"----", NULL, NothingProc},
598 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
599 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
600 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
601 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
602 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
603 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
604 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
605 {"----", NULL, NothingProc},
606 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
607 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
608 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
609 {"----", NULL, NothingProc},
610 {N_("Mail Move"), "Mail Move", MailMoveProc},
611 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
612 {"----", NULL, NothingProc},
613 {N_("Quit Ctr+Q"), "Exit", QuitProc},
617 MenuItem editMenu[] = {
618 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
619 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
620 {"----", NULL, NothingProc},
621 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
622 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
623 {"----", NULL, NothingProc},
624 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
625 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
626 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
627 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
628 {"----", NULL, NothingProc},
629 {N_("Revert Home"), "Revert", RevertProc},
630 {N_("Annotate"), "Annotate", AnnotateProc},
631 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
632 {"----", NULL, NothingProc},
633 {N_("Backward Alt+Left"), "Backward", BackwardProc},
634 {N_("Forward Alt+Right"), "Forward", ForwardProc},
635 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
636 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
640 MenuItem viewMenu[] = {
641 {N_("Flip View F2"), "Flip View", FlipViewProc},
642 {"----", NULL, NothingProc},
643 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
644 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
645 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
646 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
647 {"----", NULL, NothingProc},
648 {N_("Tags"), "Show Tags", EditTagsProc},
649 {N_("Comments"), "Show Comments", EditCommentProc},
650 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
651 {"----", NULL, NothingProc},
652 {N_("Board..."), "Board Options", BoardOptionsProc},
653 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
657 MenuItem modeMenu[] = {
658 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
659 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
660 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
661 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
662 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
663 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
664 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
665 {N_("Training"), "Training", TrainingProc},
666 {N_("ICS Client"), "ICS Client", IcsClientProc},
667 {"----", NULL, NothingProc},
668 {N_("Pause Pause"), "Pause", PauseProc},
672 MenuItem actionMenu[] = {
673 {N_("Accept F3"), "Accept", AcceptProc},
674 {N_("Decline F4"), "Decline", DeclineProc},
675 {N_("Rematch F12"), "Rematch", RematchProc},
676 {"----", NULL, NothingProc},
677 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
678 {N_("Draw F6"), "Draw", DrawProc},
679 {N_("Adjourn F7"), "Adjourn", AdjournProc},
680 {N_("Abort F8"),"Abort", AbortProc},
681 {N_("Resign F9"), "Resign", ResignProc},
682 {"----", NULL, NothingProc},
683 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
684 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
685 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
686 {"----", NULL, NothingProc},
687 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
688 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
689 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
693 MenuItem engineMenu[] = {
694 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
695 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
696 {"----", NULL, NothingProc},
697 {N_("Hint"), "Hint", HintProc},
698 {N_("Book"), "Book", BookProc},
699 {"----", NULL, NothingProc},
700 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
701 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
705 MenuItem optionsMenu[] = {
706 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
707 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
708 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
709 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
710 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
711 // {N_(" ..."), "", OptionsProc},
712 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
713 {"----", NULL, NothingProc},
714 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
715 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
716 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
717 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
718 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
719 {N_("Blindfold"), "Blindfold", BlindfoldProc},
720 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
722 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
724 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
725 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
726 {N_("Move Sound"), "Move Sound", MoveSoundProc},
727 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
728 {N_("One-Click Moving"), "OneClick", OneClickProc},
729 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
730 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
731 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
732 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
733 // {N_("Premove"), "Premove", PremoveProc},
734 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
735 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
736 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
737 {"----", NULL, NothingProc},
738 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
739 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
743 MenuItem helpMenu[] = {
744 {N_("Info XBoard"), "Info XBoard", InfoProc},
745 {N_("Man XBoard F1"), "Man XBoard", ManProc},
746 {"----", NULL, NothingProc},
747 {N_("About XBoard"), "About XBoard", AboutProc},
752 {N_("File"), "File", fileMenu},
753 {N_("Edit"), "Edit", editMenu},
754 {N_("View"), "View", viewMenu},
755 {N_("Mode"), "Mode", modeMenu},
756 {N_("Action"), "Action", actionMenu},
757 {N_("Engine"), "Engine", engineMenu},
758 {N_("Options"), "Options", optionsMenu},
759 {N_("Help"), "Help", helpMenu},
763 #define PAUSE_BUTTON "P"
764 MenuItem buttonBar[] = {
765 {"<<", "<<", ToStartProc},
766 {"<", "<", BackwardProc},
767 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
768 {">", ">", ForwardProc},
769 {">>", ">>", ToEndProc},
773 #define PIECE_MENU_SIZE 18
774 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
775 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
776 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
777 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
778 N_("Empty square"), N_("Clear board") },
779 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
780 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
781 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
782 N_("Empty square"), N_("Clear board") }
784 /* must be in same order as PieceMenuStrings! */
785 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
786 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
787 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
788 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
789 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
790 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
791 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
792 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
793 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
796 #define DROP_MENU_SIZE 6
797 String dropMenuStrings[DROP_MENU_SIZE] = {
798 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
800 /* must be in same order as PieceMenuStrings! */
801 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
802 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
803 WhiteRook, WhiteQueen
811 DropMenuEnables dmEnables[] = {
829 { XtNborderWidth, 0 },
830 { XtNdefaultDistance, 0 },
834 { XtNborderWidth, 0 },
835 { XtNresizable, (XtArgVal) True },
839 { XtNborderWidth, 0 },
845 { XtNjustify, (XtArgVal) XtJustifyRight },
846 { XtNlabel, (XtArgVal) "..." },
847 { XtNresizable, (XtArgVal) True },
848 { XtNresize, (XtArgVal) False }
851 Arg messageArgs[] = {
852 { XtNjustify, (XtArgVal) XtJustifyLeft },
853 { XtNlabel, (XtArgVal) "..." },
854 { XtNresizable, (XtArgVal) True },
855 { XtNresize, (XtArgVal) False }
859 { XtNborderWidth, 0 },
860 { XtNjustify, (XtArgVal) XtJustifyLeft }
863 XtResource clientResources[] = {
864 { "flashCount", "flashCount", XtRInt, sizeof(int),
865 XtOffset(AppDataPtr, flashCount), XtRImmediate,
866 (XtPointer) FLASH_COUNT },
869 XrmOptionDescRec shellOptions[] = {
870 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
871 { "-flash", "flashCount", XrmoptionNoArg, "3" },
872 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
875 XtActionsRec boardActions[] = {
876 { "DrawPosition", DrawPositionProc },
877 { "HandleUserMove", HandleUserMove },
878 { "AnimateUserMove", AnimateUserMove },
879 { "HandlePV", HandlePV },
880 { "SelectPV", SelectPV },
881 { "StopPV", StopPV },
882 { "FileNameAction", FileNameAction },
883 { "AskQuestionProc", AskQuestionProc },
884 { "AskQuestionReplyAction", AskQuestionReplyAction },
885 { "PieceMenuPopup", PieceMenuPopup },
886 { "WhiteClock", WhiteClock },
887 { "BlackClock", BlackClock },
888 { "Iconify", Iconify },
889 { "ResetProc", ResetProc },
890 { "NewVariantProc", NewVariantProc },
891 { "LoadGameProc", LoadGameProc },
892 { "LoadNextGameProc", LoadNextGameProc },
893 { "LoadPrevGameProc", LoadPrevGameProc },
894 { "LoadSelectedProc", LoadSelectedProc },
895 { "SetFilterProc", SetFilterProc },
896 { "ReloadGameProc", ReloadGameProc },
897 { "LoadPositionProc", LoadPositionProc },
898 { "LoadNextPositionProc", LoadNextPositionProc },
899 { "LoadPrevPositionProc", LoadPrevPositionProc },
900 { "ReloadPositionProc", ReloadPositionProc },
901 { "CopyPositionProc", CopyPositionProc },
902 { "PastePositionProc", PastePositionProc },
903 { "CopyGameProc", CopyGameProc },
904 { "PasteGameProc", PasteGameProc },
905 { "SaveGameProc", SaveGameProc },
906 { "SavePositionProc", SavePositionProc },
907 { "MailMoveProc", MailMoveProc },
908 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
909 { "QuitProc", QuitProc },
910 { "MachineWhiteProc", MachineWhiteProc },
911 { "MachineBlackProc", MachineBlackProc },
912 { "AnalysisModeProc", AnalyzeModeProc },
913 { "AnalyzeFileProc", AnalyzeFileProc },
914 { "TwoMachinesProc", TwoMachinesProc },
915 { "IcsClientProc", IcsClientProc },
916 { "EditGameProc", EditGameProc },
917 { "EditPositionProc", EditPositionProc },
918 { "TrainingProc", EditPositionProc },
919 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
920 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
921 { "ShowGameListProc", ShowGameListProc },
922 { "ShowMoveListProc", HistoryShowProc},
923 { "EditTagsProc", EditCommentProc },
924 { "EditCommentProc", EditCommentProc },
925 { "IcsInputBoxProc", IcsInputBoxProc },
926 { "PauseProc", PauseProc },
927 { "AcceptProc", AcceptProc },
928 { "DeclineProc", DeclineProc },
929 { "RematchProc", RematchProc },
930 { "CallFlagProc", CallFlagProc },
931 { "DrawProc", DrawProc },
932 { "AdjournProc", AdjournProc },
933 { "AbortProc", AbortProc },
934 { "ResignProc", ResignProc },
935 { "AdjuWhiteProc", AdjuWhiteProc },
936 { "AdjuBlackProc", AdjuBlackProc },
937 { "AdjuDrawProc", AdjuDrawProc },
938 { "EnterKeyProc", EnterKeyProc },
939 { "UpKeyProc", UpKeyProc },
940 { "DownKeyProc", DownKeyProc },
941 { "StopObservingProc", StopObservingProc },
942 { "StopExaminingProc", StopExaminingProc },
943 { "UploadProc", UploadProc },
944 { "BackwardProc", BackwardProc },
945 { "ForwardProc", ForwardProc },
946 { "ToStartProc", ToStartProc },
947 { "ToEndProc", ToEndProc },
948 { "RevertProc", RevertProc },
949 { "AnnotateProc", AnnotateProc },
950 { "TruncateGameProc", TruncateGameProc },
951 { "MoveNowProc", MoveNowProc },
952 { "RetractMoveProc", RetractMoveProc },
953 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
954 { "UciMenuProc", (XtActionProc) UciMenuProc },
955 { "TimeControlProc", (XtActionProc) TimeControlProc },
956 { "AlwaysQueenProc", AlwaysQueenProc },
957 { "AnimateDraggingProc", AnimateDraggingProc },
958 { "AnimateMovingProc", AnimateMovingProc },
959 { "AutoflagProc", AutoflagProc },
960 { "AutoflipProc", AutoflipProc },
961 { "BlindfoldProc", BlindfoldProc },
962 { "FlashMovesProc", FlashMovesProc },
963 { "FlipViewProc", FlipViewProc },
965 { "HighlightDraggingProc", HighlightDraggingProc },
967 { "HighlightLastMoveProc", HighlightLastMoveProc },
968 // { "IcsAlarmProc", IcsAlarmProc },
969 { "MoveSoundProc", MoveSoundProc },
970 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
971 { "PonderNextMoveProc", PonderNextMoveProc },
972 { "PopupExitMessageProc", PopupExitMessageProc },
973 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
974 // { "PremoveProc", PremoveProc },
975 { "ShowCoordsProc", ShowCoordsProc },
976 { "ShowThinkingProc", ShowThinkingProc },
977 { "HideThinkingProc", HideThinkingProc },
978 { "TestLegalityProc", TestLegalityProc },
979 { "SaveSettingsProc", SaveSettingsProc },
980 { "SaveOnExitProc", SaveOnExitProc },
981 { "InfoProc", InfoProc },
982 { "ManProc", ManProc },
983 { "HintProc", HintProc },
984 { "BookProc", BookProc },
985 { "AboutGameProc", AboutGameProc },
986 { "AboutProc", AboutProc },
987 { "DebugProc", DebugProc },
988 { "NothingProc", NothingProc },
989 { "CommentClick", (XtActionProc) CommentClick },
990 { "CommentPopDown", (XtActionProc) CommentPopDown },
991 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
992 { "TagsPopDown", (XtActionProc) TagsPopDown },
993 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
994 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
995 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
996 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
997 { "GameListPopDown", (XtActionProc) GameListPopDown },
998 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
999 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1000 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1001 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1002 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1003 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1004 { "EnginePopDown", (XtActionProc) EnginePopDown },
1005 { "UciPopDown", (XtActionProc) UciPopDown },
1006 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1007 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1008 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1009 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1012 char globalTranslations[] =
1013 ":<Key>F9: ResignProc() \n \
1014 :Ctrl<Key>n: ResetProc() \n \
1015 :Meta<Key>V: NewVariantProc() \n \
1016 :Ctrl<Key>o: LoadGameProc() \n \
1017 :Meta<Key>Next: LoadNextGameProc() \n \
1018 :Meta<Key>Prior: LoadPrevGameProc() \n \
1019 :Ctrl<Key>s: SaveGameProc() \n \
1020 :Ctrl<Key>c: CopyGameProc() \n \
1021 :Ctrl<Key>v: PasteGameProc() \n \
1022 :Ctrl<Key>O: LoadPositionProc() \n \
1023 :Shift<Key>Next: LoadNextPositionProc() \n \
1024 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1025 :Ctrl<Key>S: SavePositionProc() \n \
1026 :Ctrl<Key>C: CopyPositionProc() \n \
1027 :Ctrl<Key>V: PastePositionProc() \n \
1028 :Ctrl<Key>q: QuitProc() \n \
1029 :Ctrl<Key>w: MachineWhiteProc() \n \
1030 :Ctrl<Key>b: MachineBlackProc() \n \
1031 :Ctrl<Key>t: TwoMachinesProc() \n \
1032 :Ctrl<Key>a: AnalysisModeProc() \n \
1033 :Ctrl<Key>f: AnalyzeFileProc() \n \
1034 :Ctrl<Key>e: EditGameProc() \n \
1035 :Ctrl<Key>E: EditPositionProc() \n \
1036 :Meta<Key>O: EngineOutputProc() \n \
1037 :Meta<Key>E: EvalGraphProc() \n \
1038 :Meta<Key>G: ShowGameListProc() \n \
1039 :Meta<Key>H: ShowMoveListProc() \n \
1040 :<Key>Pause: PauseProc() \n \
1041 :<Key>F3: AcceptProc() \n \
1042 :<Key>F4: DeclineProc() \n \
1043 :<Key>F12: RematchProc() \n \
1044 :<Key>F5: CallFlagProc() \n \
1045 :<Key>F6: DrawProc() \n \
1046 :<Key>F7: AdjournProc() \n \
1047 :<Key>F8: AbortProc() \n \
1048 :<Key>F10: StopObservingProc() \n \
1049 :<Key>F11: StopExaminingProc() \n \
1050 :Meta Ctrl<Key>F12: DebugProc() \n \
1051 :Meta<Key>End: ToEndProc() \n \
1052 :Meta<Key>Right: ForwardProc() \n \
1053 :Meta<Key>Home: ToStartProc() \n \
1054 :Meta<Key>Left: BackwardProc() \n \
1055 :<Key>Home: RevertProc() \n \
1056 :<Key>End: TruncateGameProc() \n \
1057 :Ctrl<Key>m: MoveNowProc() \n \
1058 :Ctrl<Key>x: RetractMoveProc() \n \
1059 :Meta<Key>J: EngineMenuProc() \n \
1060 :Meta<Key>U: UciMenuProc() \n \
1061 :Meta<Key>T: TimeControlProc() \n \
1062 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1063 :Ctrl<Key>F: AutoflagProc() \n \
1064 :Ctrl<Key>A: AnimateMovingProc() \n \
1065 :Ctrl<Key>P: PonderNextMoveProc() \n \
1066 :Ctrl<Key>L: TestLegalityProc() \n \
1067 :Ctrl<Key>H: HideThinkingProc() \n \
1068 :<Key>-: Iconify() \n \
1069 :<Key>F1: ManProc() \n \
1070 :<Key>F2: FlipViewProc() \n \
1071 <KeyDown>.: BackwardProc() \n \
1072 <KeyUp>.: ForwardProc() \n \
1073 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1074 \"Send to chess program:\",,1) \n \
1075 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1076 \"Send to second chess program:\",,2) \n";
1078 char boardTranslations[] =
1079 "<Btn1Down>: HandleUserMove(0) \n \
1080 Shift<Btn1Up>: HandleUserMove(1) \n \
1081 <Btn1Up>: HandleUserMove(0) \n \
1082 <Btn1Motion>: AnimateUserMove() \n \
1083 <Btn3Motion>: HandlePV() \n \
1084 <Btn3Up>: PieceMenuPopup(menuB) \n \
1085 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1086 PieceMenuPopup(menuB) \n \
1087 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1088 PieceMenuPopup(menuW) \n \
1089 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1090 PieceMenuPopup(menuW) \n \
1091 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1092 PieceMenuPopup(menuB) \n";
1094 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1095 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1097 char ICSInputTranslations[] =
1098 "<Key>Up: UpKeyProc() \n "
1099 "<Key>Down: DownKeyProc() \n "
1100 "<Key>Return: EnterKeyProc() \n";
1102 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1103 // as the widget is destroyed before the up-click can call extend-end
1104 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1106 String xboardResources[] = {
1107 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1108 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1109 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1114 /* Max possible square size */
1115 #define MAXSQSIZE 256
1117 static int xpm_avail[MAXSQSIZE];
1119 #ifdef HAVE_DIR_STRUCT
1121 /* Extract piece size from filename */
1123 xpm_getsize(name, len, ext)
1134 if ((p=strchr(name, '.')) == NULL ||
1135 StrCaseCmp(p+1, ext) != 0)
1141 while (*p && isdigit(*p))
1148 /* Setup xpm_avail */
1150 xpm_getavail(dirname, ext)
1158 for (i=0; i<MAXSQSIZE; ++i)
1161 if (appData.debugMode)
1162 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1164 dir = opendir(dirname);
1167 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1168 programName, dirname);
1172 while ((ent=readdir(dir)) != NULL) {
1173 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1174 if (i > 0 && i < MAXSQSIZE)
1184 xpm_print_avail(fp, ext)
1190 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1191 for (i=1; i<MAXSQSIZE; ++i) {
1197 /* Return XPM piecesize closest to size */
1199 xpm_closest_to(dirname, size, ext)
1205 int sm_diff = MAXSQSIZE;
1209 xpm_getavail(dirname, ext);
1211 if (appData.debugMode)
1212 xpm_print_avail(stderr, ext);
1214 for (i=1; i<MAXSQSIZE; ++i) {
1217 diff = (diff<0) ? -diff : diff;
1218 if (diff < sm_diff) {
1226 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1232 #else /* !HAVE_DIR_STRUCT */
1233 /* If we are on a system without a DIR struct, we can't
1234 read the directory, so we can't collect a list of
1235 filenames, etc., so we can't do any size-fitting. */
1237 xpm_closest_to(dirname, size, ext)
1242 fprintf(stderr, _("\
1243 Warning: No DIR structure found on this system --\n\
1244 Unable to autosize for XPM/XIM pieces.\n\
1245 Please report this error to frankm@hiwaay.net.\n\
1246 Include system type & operating system in message.\n"));
1249 #endif /* HAVE_DIR_STRUCT */
1251 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1252 "magenta", "cyan", "white" };
1256 TextColors textColors[(int)NColorClasses];
1258 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1260 parse_color(str, which)
1264 char *p, buf[100], *d;
1267 if (strlen(str) > 99) /* watch bounds on buf */
1272 for (i=0; i<which; ++i) {
1279 /* Could be looking at something like:
1281 .. in which case we want to stop on a comma also */
1282 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1286 return -1; /* Use default for empty field */
1289 if (which == 2 || isdigit(*p))
1292 while (*p && isalpha(*p))
1297 for (i=0; i<8; ++i) {
1298 if (!StrCaseCmp(buf, cnames[i]))
1299 return which? (i+40) : (i+30);
1301 if (!StrCaseCmp(buf, "default")) return -1;
1303 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1308 parse_cpair(cc, str)
1312 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1313 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1318 /* bg and attr are optional */
1319 textColors[(int)cc].bg = parse_color(str, 1);
1320 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1321 textColors[(int)cc].attr = 0;
1327 /* Arrange to catch delete-window events */
1328 Atom wm_delete_window;
1330 CatchDeleteWindow(Widget w, String procname)
1333 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1334 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1335 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1342 XtSetArg(args[0], XtNiconic, False);
1343 XtSetValues(shellWidget, args, 1);
1345 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1348 //---------------------------------------------------------------------------------------------------------
1349 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1352 #define CW_USEDEFAULT (1<<31)
1353 #define ICS_TEXT_MENU_SIZE 90
1354 #define DEBUG_FILE "xboard.debug"
1355 #define SetCurrentDirectory chdir
1356 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1360 // these two must some day move to frontend.h, when they are implemented
1361 Boolean GameListIsUp();
1363 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1366 // front-end part of option handling
1368 // [HGM] This platform-dependent table provides the location for storing the color info
1369 extern char *crWhite, * crBlack;
1373 &appData.whitePieceColor,
1374 &appData.blackPieceColor,
1375 &appData.lightSquareColor,
1376 &appData.darkSquareColor,
1377 &appData.highlightSquareColor,
1378 &appData.premoveHighlightColor,
1379 &appData.lowTimeWarningColor,
1390 // [HGM] font: keep a font for each square size, even non-stndard ones
1391 #define NUM_SIZES 18
1392 #define MAX_SIZE 130
1393 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1394 char *fontTable[NUM_FONTS][MAX_SIZE];
1397 ParseFont(char *name, int number)
1398 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1400 if(sscanf(name, "size%d:", &size)) {
1401 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1402 // defer processing it until we know if it matches our board size
1403 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1404 fontTable[number][size] = strdup(strchr(name, ':')+1);
1405 fontValid[number][size] = True;
1410 case 0: // CLOCK_FONT
1411 appData.clockFont = strdup(name);
1413 case 1: // MESSAGE_FONT
1414 appData.font = strdup(name);
1416 case 2: // COORD_FONT
1417 appData.coordFont = strdup(name);
1422 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1427 { // only 2 fonts currently
1428 appData.clockFont = CLOCK_FONT_NAME;
1429 appData.coordFont = COORD_FONT_NAME;
1430 appData.font = DEFAULT_FONT_NAME;
1435 { // no-op, until we identify the code for this already in XBoard and move it here
1439 ParseColor(int n, char *name)
1440 { // in XBoard, just copy the color-name string
1441 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1445 ParseTextAttribs(ColorClass cc, char *s)
1447 (&appData.colorShout)[cc] = strdup(s);
1451 ParseBoardSize(void *addr, char *name)
1453 appData.boardSize = strdup(name);
1458 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1462 SetCommPortDefaults()
1463 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1466 // [HGM] args: these three cases taken out to stay in front-end
1468 SaveFontArg(FILE *f, ArgDescriptor *ad)
1471 int i, n = (int)(intptr_t)ad->argLoc;
1473 case 0: // CLOCK_FONT
1474 name = appData.clockFont;
1476 case 1: // MESSAGE_FONT
1477 name = appData.font;
1479 case 2: // COORD_FONT
1480 name = appData.coordFont;
1485 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1486 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1487 fontTable[n][squareSize] = strdup(name);
1488 fontValid[n][squareSize] = True;
1491 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1492 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1497 { // nothing to do, as the sounds are at all times represented by their text-string names already
1501 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1502 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1503 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1507 SaveColor(FILE *f, ArgDescriptor *ad)
1508 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1509 if(colorVariable[(int)(intptr_t)ad->argLoc])
1510 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1514 SaveBoardSize(FILE *f, char *name, void *addr)
1515 { // wrapper to shield back-end from BoardSize & sizeInfo
1516 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1520 ParseCommPortSettings(char *s)
1521 { // no such option in XBoard (yet)
1524 extern Widget engineOutputShell;
1525 extern Widget tagsShell, editTagsShell;
1527 GetActualPlacement(Widget wg, WindowPlacement *wp)
1537 XtSetArg(args[i], XtNx, &x); i++;
1538 XtSetArg(args[i], XtNy, &y); i++;
1539 XtSetArg(args[i], XtNwidth, &w); i++;
1540 XtSetArg(args[i], XtNheight, &h); i++;
1541 XtGetValues(wg, args, i);
1550 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1551 // In XBoard this will have to wait until awareness of window parameters is implemented
1552 GetActualPlacement(shellWidget, &wpMain);
1553 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1554 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1555 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1556 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1557 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1558 else GetActualPlacement(editShell, &wpComment);
1559 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1560 else GetActualPlacement(editTagsShell, &wpTags);
1564 PrintCommPortSettings(FILE *f, char *name)
1565 { // This option does not exist in XBoard
1569 MySearchPath(char *installDir, char *name, char *fullname)
1570 { // just append installDir and name. Perhaps ExpandPath should be used here?
1571 name = ExpandPathName(name);
1572 if(name && name[0] == '/')
1573 safeStrCpy(fullname, name, MSG_SIZ );
1575 sprintf(fullname, "%s%c%s", installDir, '/', name);
1581 MyGetFullPathName(char *name, char *fullname)
1582 { // should use ExpandPath?
1583 name = ExpandPathName(name);
1584 safeStrCpy(fullname, name, MSG_SIZ );
1589 EnsureOnScreen(int *x, int *y, int minX, int minY)
1596 { // [HGM] args: allows testing if main window is realized from back-end
1597 return xBoardWindow != 0;
1601 PopUpStartupDialog()
1602 { // start menu not implemented in XBoard
1606 ConvertToLine(int argc, char **argv)
1608 static char line[128*1024], buf[1024];
1612 for(i=1; i<argc; i++)
1614 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1615 && argv[i][0] != '{' )
1616 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1618 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1619 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1622 line[strlen(line)-1] = NULLCHAR;
1626 //--------------------------------------------------------------------------------------------
1628 extern Boolean twoBoards, partnerUp;
1631 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1633 #define BoardSize int
1634 void InitDrawingSizes(BoardSize boardSize, int flags)
1635 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1636 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1638 XtGeometryResult gres;
1641 if(!formWidget) return;
1644 * Enable shell resizing.
1646 shellArgs[0].value = (XtArgVal) &w;
1647 shellArgs[1].value = (XtArgVal) &h;
1648 XtGetValues(shellWidget, shellArgs, 2);
1650 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1651 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1652 XtSetValues(shellWidget, &shellArgs[2], 4);
1654 XtSetArg(args[0], XtNdefaultDistance, &sep);
1655 XtGetValues(formWidget, args, 1);
1657 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1658 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1659 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1661 hOffset = boardWidth + 10;
1662 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1663 secondSegments[i] = gridSegments[i];
1664 secondSegments[i].x1 += hOffset;
1665 secondSegments[i].x2 += hOffset;
1668 XtSetArg(args[0], XtNwidth, boardWidth);
1669 XtSetArg(args[1], XtNheight, boardHeight);
1670 XtSetValues(boardWidget, args, 2);
1672 timerWidth = (boardWidth - sep) / 2;
1673 XtSetArg(args[0], XtNwidth, timerWidth);
1674 XtSetValues(whiteTimerWidget, args, 1);
1675 XtSetValues(blackTimerWidget, args, 1);
1677 XawFormDoLayout(formWidget, False);
1679 if (appData.titleInWindow) {
1681 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1682 XtSetArg(args[i], XtNheight, &h); i++;
1683 XtGetValues(titleWidget, args, i);
1685 w = boardWidth - 2*bor;
1687 XtSetArg(args[0], XtNwidth, &w);
1688 XtGetValues(menuBarWidget, args, 1);
1689 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1692 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1693 if (gres != XtGeometryYes && appData.debugMode) {
1695 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1696 programName, gres, w, h, wr, hr);
1700 XawFormDoLayout(formWidget, True);
1703 * Inhibit shell resizing.
1705 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1706 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1707 shellArgs[4].value = shellArgs[2].value = w;
1708 shellArgs[5].value = shellArgs[3].value = h;
1709 XtSetValues(shellWidget, &shellArgs[0], 6);
1711 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1714 for(i=0; i<4; i++) {
1716 for(p=0; p<=(int)WhiteKing; p++)
1717 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1718 if(gameInfo.variant == VariantShogi) {
1719 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1720 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1721 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1722 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1723 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1726 if(gameInfo.variant == VariantGothic) {
1727 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1730 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1731 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1732 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1735 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1736 for(p=0; p<=(int)WhiteKing; p++)
1737 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1738 if(gameInfo.variant == VariantShogi) {
1739 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1740 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1741 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1742 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1743 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1746 if(gameInfo.variant == VariantGothic) {
1747 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1750 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1751 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1752 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1757 for(i=0; i<2; i++) {
1759 for(p=0; p<=(int)WhiteKing; p++)
1760 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1761 if(gameInfo.variant == VariantShogi) {
1762 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1763 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1764 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1765 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1766 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1769 if(gameInfo.variant == VariantGothic) {
1770 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1773 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1774 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1775 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1785 void ParseIcsTextColors()
1786 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1787 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1788 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1789 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1790 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1791 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1792 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1793 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1794 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1795 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1796 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1798 if (appData.colorize) {
1800 _("%s: can't parse color names; disabling colorization\n"),
1803 appData.colorize = FALSE;
1808 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1809 XrmValue vFrom, vTo;
1810 int forceMono = False;
1812 if (!appData.monoMode) {
1813 vFrom.addr = (caddr_t) appData.lightSquareColor;
1814 vFrom.size = strlen(appData.lightSquareColor);
1815 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1816 if (vTo.addr == NULL) {
1817 appData.monoMode = True;
1820 lightSquareColor = *(Pixel *) vTo.addr;
1823 if (!appData.monoMode) {
1824 vFrom.addr = (caddr_t) appData.darkSquareColor;
1825 vFrom.size = strlen(appData.darkSquareColor);
1826 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1827 if (vTo.addr == NULL) {
1828 appData.monoMode = True;
1831 darkSquareColor = *(Pixel *) vTo.addr;
1834 if (!appData.monoMode) {
1835 vFrom.addr = (caddr_t) appData.whitePieceColor;
1836 vFrom.size = strlen(appData.whitePieceColor);
1837 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1838 if (vTo.addr == NULL) {
1839 appData.monoMode = True;
1842 whitePieceColor = *(Pixel *) vTo.addr;
1845 if (!appData.monoMode) {
1846 vFrom.addr = (caddr_t) appData.blackPieceColor;
1847 vFrom.size = strlen(appData.blackPieceColor);
1848 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1849 if (vTo.addr == NULL) {
1850 appData.monoMode = True;
1853 blackPieceColor = *(Pixel *) vTo.addr;
1857 if (!appData.monoMode) {
1858 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1859 vFrom.size = strlen(appData.highlightSquareColor);
1860 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1861 if (vTo.addr == NULL) {
1862 appData.monoMode = True;
1865 highlightSquareColor = *(Pixel *) vTo.addr;
1869 if (!appData.monoMode) {
1870 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1871 vFrom.size = strlen(appData.premoveHighlightColor);
1872 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1873 if (vTo.addr == NULL) {
1874 appData.monoMode = True;
1877 premoveHighlightColor = *(Pixel *) vTo.addr;
1888 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1889 XSetWindowAttributes window_attributes;
1891 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1892 XrmValue vFrom, vTo;
1893 XtGeometryResult gres;
1896 int forceMono = False;
1898 srandom(time(0)); // [HGM] book: make random truly random
1900 setbuf(stdout, NULL);
1901 setbuf(stderr, NULL);
1904 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1905 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1909 programName = strrchr(argv[0], '/');
1910 if (programName == NULL)
1911 programName = argv[0];
1916 XtSetLanguageProc(NULL, NULL, NULL);
1917 bindtextdomain(PACKAGE, LOCALEDIR);
1918 textdomain(PACKAGE);
1922 XtAppInitialize(&appContext, "XBoard", shellOptions,
1923 XtNumber(shellOptions),
1924 &argc, argv, xboardResources, NULL, 0);
1925 appData.boardSize = "";
1926 InitAppData(ConvertToLine(argc, argv));
1928 if (p == NULL) p = "/tmp";
1929 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1930 gameCopyFilename = (char*) malloc(i);
1931 gamePasteFilename = (char*) malloc(i);
1932 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1933 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1935 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1936 clientResources, XtNumber(clientResources),
1939 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1940 static char buf[MSG_SIZ];
1941 EscapeExpand(buf, appData.initString);
1942 appData.initString = strdup(buf);
1943 EscapeExpand(buf, appData.secondInitString);
1944 appData.secondInitString = strdup(buf);
1945 EscapeExpand(buf, appData.firstComputerString);
1946 appData.firstComputerString = strdup(buf);
1947 EscapeExpand(buf, appData.secondComputerString);
1948 appData.secondComputerString = strdup(buf);
1951 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1954 if (chdir(chessDir) != 0) {
1955 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1961 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1962 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1963 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1964 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1967 setbuf(debugFP, NULL);
1970 /* [HGM,HR] make sure board size is acceptable */
1971 if(appData.NrFiles > BOARD_FILES ||
1972 appData.NrRanks > BOARD_RANKS )
1973 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1976 /* This feature does not work; animation needs a rewrite */
1977 appData.highlightDragging = FALSE;
1981 xDisplay = XtDisplay(shellWidget);
1982 xScreen = DefaultScreen(xDisplay);
1983 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1985 gameInfo.variant = StringToVariant(appData.variant);
1986 InitPosition(FALSE);
1989 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1991 if (isdigit(appData.boardSize[0])) {
1992 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1993 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1994 &fontPxlSize, &smallLayout, &tinyLayout);
1996 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1997 programName, appData.boardSize);
2001 /* Find some defaults; use the nearest known size */
2002 SizeDefaults *szd, *nearest;
2003 int distance = 99999;
2004 nearest = szd = sizeDefaults;
2005 while (szd->name != NULL) {
2006 if (abs(szd->squareSize - squareSize) < distance) {
2008 distance = abs(szd->squareSize - squareSize);
2009 if (distance == 0) break;
2013 if (i < 2) lineGap = nearest->lineGap;
2014 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2015 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2016 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2017 if (i < 6) smallLayout = nearest->smallLayout;
2018 if (i < 7) tinyLayout = nearest->tinyLayout;
2021 SizeDefaults *szd = sizeDefaults;
2022 if (*appData.boardSize == NULLCHAR) {
2023 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2024 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2027 if (szd->name == NULL) szd--;
2028 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2030 while (szd->name != NULL &&
2031 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2032 if (szd->name == NULL) {
2033 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2034 programName, appData.boardSize);
2038 squareSize = szd->squareSize;
2039 lineGap = szd->lineGap;
2040 clockFontPxlSize = szd->clockFontPxlSize;
2041 coordFontPxlSize = szd->coordFontPxlSize;
2042 fontPxlSize = szd->fontPxlSize;
2043 smallLayout = szd->smallLayout;
2044 tinyLayout = szd->tinyLayout;
2045 // [HGM] font: use defaults from settings file if available and not overruled
2047 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2048 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2049 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2050 appData.font = fontTable[MESSAGE_FONT][squareSize];
2051 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2052 appData.coordFont = fontTable[COORD_FONT][squareSize];
2054 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2055 if (strlen(appData.pixmapDirectory) > 0) {
2056 p = ExpandPathName(appData.pixmapDirectory);
2058 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2059 appData.pixmapDirectory);
2062 if (appData.debugMode) {
2063 fprintf(stderr, _("\
2064 XBoard square size (hint): %d\n\
2065 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2067 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2068 if (appData.debugMode) {
2069 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2072 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2074 /* [HR] height treated separately (hacked) */
2075 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2076 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2077 if (appData.showJail == 1) {
2078 /* Jail on top and bottom */
2079 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2080 XtSetArg(boardArgs[2], XtNheight,
2081 boardHeight + 2*(lineGap + squareSize));
2082 } else if (appData.showJail == 2) {
2084 XtSetArg(boardArgs[1], XtNwidth,
2085 boardWidth + 2*(lineGap + squareSize));
2086 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2089 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2090 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2094 * Determine what fonts to use.
2096 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2097 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2098 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2099 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2100 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2101 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2102 appData.font = FindFont(appData.font, fontPxlSize);
2103 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2104 countFontStruct = XQueryFont(xDisplay, countFontID);
2105 // appData.font = FindFont(appData.font, fontPxlSize);
2107 xdb = XtDatabase(xDisplay);
2108 XrmPutStringResource(&xdb, "*font", appData.font);
2111 * Detect if there are not enough colors available and adapt.
2113 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2114 appData.monoMode = True;
2117 forceMono = MakeColors();
2120 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2123 if (appData.bitmapDirectory == NULL ||
2124 appData.bitmapDirectory[0] == NULLCHAR)
2125 appData.bitmapDirectory = DEF_BITMAP_DIR;
2128 if (appData.lowTimeWarning && !appData.monoMode) {
2129 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2130 vFrom.size = strlen(appData.lowTimeWarningColor);
2131 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2132 if (vTo.addr == NULL)
2133 appData.monoMode = True;
2135 lowTimeWarningColor = *(Pixel *) vTo.addr;
2138 if (appData.monoMode && appData.debugMode) {
2139 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2140 (unsigned long) XWhitePixel(xDisplay, xScreen),
2141 (unsigned long) XBlackPixel(xDisplay, xScreen));
2144 ParseIcsTextColors();
2145 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2146 textColors[ColorNone].attr = 0;
2148 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2154 layoutName = "tinyLayout";
2155 } else if (smallLayout) {
2156 layoutName = "smallLayout";
2158 layoutName = "normalLayout";
2160 /* Outer layoutWidget is there only to provide a name for use in
2161 resources that depend on the layout style */
2163 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2164 layoutArgs, XtNumber(layoutArgs));
2166 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2167 formArgs, XtNumber(formArgs));
2168 XtSetArg(args[0], XtNdefaultDistance, &sep);
2169 XtGetValues(formWidget, args, 1);
2172 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2173 XtSetArg(args[0], XtNtop, XtChainTop);
2174 XtSetArg(args[1], XtNbottom, XtChainTop);
2175 XtSetArg(args[2], XtNright, XtChainLeft);
2176 XtSetValues(menuBarWidget, args, 3);
2178 widgetList[j++] = whiteTimerWidget =
2179 XtCreateWidget("whiteTime", labelWidgetClass,
2180 formWidget, timerArgs, XtNumber(timerArgs));
2181 XtSetArg(args[0], XtNfont, clockFontStruct);
2182 XtSetArg(args[1], XtNtop, XtChainTop);
2183 XtSetArg(args[2], XtNbottom, XtChainTop);
2184 XtSetValues(whiteTimerWidget, args, 3);
2186 widgetList[j++] = blackTimerWidget =
2187 XtCreateWidget("blackTime", labelWidgetClass,
2188 formWidget, timerArgs, XtNumber(timerArgs));
2189 XtSetArg(args[0], XtNfont, clockFontStruct);
2190 XtSetArg(args[1], XtNtop, XtChainTop);
2191 XtSetArg(args[2], XtNbottom, XtChainTop);
2192 XtSetValues(blackTimerWidget, args, 3);
2194 if (appData.titleInWindow) {
2195 widgetList[j++] = titleWidget =
2196 XtCreateWidget("title", labelWidgetClass, formWidget,
2197 titleArgs, XtNumber(titleArgs));
2198 XtSetArg(args[0], XtNtop, XtChainTop);
2199 XtSetArg(args[1], XtNbottom, XtChainTop);
2200 XtSetValues(titleWidget, args, 2);
2203 if (appData.showButtonBar) {
2204 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2205 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2206 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2207 XtSetArg(args[2], XtNtop, XtChainTop);
2208 XtSetArg(args[3], XtNbottom, XtChainTop);
2209 XtSetValues(buttonBarWidget, args, 4);
2212 widgetList[j++] = messageWidget =
2213 XtCreateWidget("message", labelWidgetClass, formWidget,
2214 messageArgs, XtNumber(messageArgs));
2215 XtSetArg(args[0], XtNtop, XtChainTop);
2216 XtSetArg(args[1], XtNbottom, XtChainTop);
2217 XtSetValues(messageWidget, args, 2);
2219 widgetList[j++] = boardWidget =
2220 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2221 XtNumber(boardArgs));
2223 XtManageChildren(widgetList, j);
2225 timerWidth = (boardWidth - sep) / 2;
2226 XtSetArg(args[0], XtNwidth, timerWidth);
2227 XtSetValues(whiteTimerWidget, args, 1);
2228 XtSetValues(blackTimerWidget, args, 1);
2230 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2231 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2232 XtGetValues(whiteTimerWidget, args, 2);
2234 if (appData.showButtonBar) {
2235 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2236 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2237 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2241 * formWidget uses these constraints but they are stored
2245 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2246 XtSetValues(menuBarWidget, args, i);
2247 if (appData.titleInWindow) {
2250 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2251 XtSetValues(whiteTimerWidget, args, i);
2253 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2254 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2255 XtSetValues(blackTimerWidget, args, i);
2257 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2258 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2259 XtSetValues(titleWidget, args, i);
2261 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2262 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2263 XtSetValues(messageWidget, args, i);
2264 if (appData.showButtonBar) {
2266 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2267 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2268 XtSetValues(buttonBarWidget, args, i);
2272 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2273 XtSetValues(whiteTimerWidget, args, i);
2275 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2276 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2277 XtSetValues(blackTimerWidget, args, i);
2279 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2280 XtSetValues(titleWidget, args, i);
2282 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2283 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2284 XtSetValues(messageWidget, args, i);
2285 if (appData.showButtonBar) {
2287 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2288 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2289 XtSetValues(buttonBarWidget, args, i);
2294 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2295 XtSetValues(whiteTimerWidget, args, i);
2297 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2298 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2299 XtSetValues(blackTimerWidget, args, i);
2301 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2302 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2303 XtSetValues(messageWidget, args, i);
2304 if (appData.showButtonBar) {
2306 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2307 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2308 XtSetValues(buttonBarWidget, args, i);
2312 XtSetArg(args[0], XtNfromVert, messageWidget);
2313 XtSetArg(args[1], XtNtop, XtChainTop);
2314 XtSetArg(args[2], XtNbottom, XtChainBottom);
2315 XtSetArg(args[3], XtNleft, XtChainLeft);
2316 XtSetArg(args[4], XtNright, XtChainRight);
2317 XtSetValues(boardWidget, args, 5);
2319 XtRealizeWidget(shellWidget);
2322 XtSetArg(args[0], XtNx, wpMain.x);
2323 XtSetArg(args[1], XtNy, wpMain.y);
2324 XtSetValues(shellWidget, args, 2);
2328 * Correct the width of the message and title widgets.
2329 * It is not known why some systems need the extra fudge term.
2330 * The value "2" is probably larger than needed.
2332 XawFormDoLayout(formWidget, False);
2334 #define WIDTH_FUDGE 2
2336 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2337 XtSetArg(args[i], XtNheight, &h); i++;
2338 XtGetValues(messageWidget, args, i);
2339 if (appData.showButtonBar) {
2341 XtSetArg(args[i], XtNwidth, &w); i++;
2342 XtGetValues(buttonBarWidget, args, i);
2343 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2345 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2348 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2349 if (gres != XtGeometryYes && appData.debugMode) {
2350 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2351 programName, gres, w, h, wr, hr);
2354 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2355 /* The size used for the child widget in layout lags one resize behind
2356 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2358 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2359 if (gres != XtGeometryYes && appData.debugMode) {
2360 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2361 programName, gres, w, h, wr, hr);
2364 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2365 XtSetArg(args[1], XtNright, XtChainRight);
2366 XtSetValues(messageWidget, args, 2);
2368 if (appData.titleInWindow) {
2370 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2371 XtSetArg(args[i], XtNheight, &h); i++;
2372 XtGetValues(titleWidget, args, i);
2374 w = boardWidth - 2*bor;
2376 XtSetArg(args[0], XtNwidth, &w);
2377 XtGetValues(menuBarWidget, args, 1);
2378 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2381 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2382 if (gres != XtGeometryYes && appData.debugMode) {
2384 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2385 programName, gres, w, h, wr, hr);
2388 XawFormDoLayout(formWidget, True);
2390 xBoardWindow = XtWindow(boardWidget);
2392 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2393 // not need to go into InitDrawingSizes().
2397 * Create X checkmark bitmap and initialize option menu checks.
2399 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2400 checkmark_bits, checkmark_width, checkmark_height);
2401 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2402 if (appData.alwaysPromoteToQueen) {
2403 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2406 if (appData.animateDragging) {
2407 XtSetValues(XtNameToWidget(menuBarWidget,
2408 "menuOptions.Animate Dragging"),
2411 if (appData.animate) {
2412 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2415 if (appData.autoCallFlag) {
2416 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2419 if (appData.autoFlipView) {
2420 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2423 if (appData.blindfold) {
2424 XtSetValues(XtNameToWidget(menuBarWidget,
2425 "menuOptions.Blindfold"), args, 1);
2427 if (appData.flashCount > 0) {
2428 XtSetValues(XtNameToWidget(menuBarWidget,
2429 "menuOptions.Flash Moves"),
2433 if (appData.highlightDragging) {
2434 XtSetValues(XtNameToWidget(menuBarWidget,
2435 "menuOptions.Highlight Dragging"),
2439 if (appData.highlightLastMove) {
2440 XtSetValues(XtNameToWidget(menuBarWidget,
2441 "menuOptions.Highlight Last Move"),
2444 if (appData.highlightMoveWithArrow) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Arrow"),
2449 // if (appData.icsAlarm) {
2450 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2453 if (appData.ringBellAfterMoves) {
2454 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2457 if (appData.oneClick) {
2458 XtSetValues(XtNameToWidget(menuBarWidget,
2459 "menuOptions.OneClick"), args, 1);
2461 if (appData.periodicUpdates) {
2462 XtSetValues(XtNameToWidget(menuBarWidget,
2463 "menuOptions.Periodic Updates"), args, 1);
2465 if (appData.ponderNextMove) {
2466 XtSetValues(XtNameToWidget(menuBarWidget,
2467 "menuOptions.Ponder Next Move"), args, 1);
2469 if (appData.popupExitMessage) {
2470 XtSetValues(XtNameToWidget(menuBarWidget,
2471 "menuOptions.Popup Exit Message"), args, 1);
2473 if (appData.popupMoveErrors) {
2474 XtSetValues(XtNameToWidget(menuBarWidget,
2475 "menuOptions.Popup Move Errors"), args, 1);
2477 // if (appData.premove) {
2478 // XtSetValues(XtNameToWidget(menuBarWidget,
2479 // "menuOptions.Premove"), args, 1);
2481 if (appData.showCoords) {
2482 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2485 if (appData.hideThinkingFromHuman) {
2486 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2489 if (appData.testLegality) {
2490 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2493 if (saveSettingsOnExit) {
2494 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2501 ReadBitmap(&wIconPixmap, "icon_white.bm",
2502 icon_white_bits, icon_white_width, icon_white_height);
2503 ReadBitmap(&bIconPixmap, "icon_black.bm",
2504 icon_black_bits, icon_black_width, icon_black_height);
2505 iconPixmap = wIconPixmap;
2507 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2508 XtSetValues(shellWidget, args, i);
2511 * Create a cursor for the board widget.
2513 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2514 XChangeWindowAttributes(xDisplay, xBoardWindow,
2515 CWCursor, &window_attributes);
2518 * Inhibit shell resizing.
2520 shellArgs[0].value = (XtArgVal) &w;
2521 shellArgs[1].value = (XtArgVal) &h;
2522 XtGetValues(shellWidget, shellArgs, 2);
2523 shellArgs[4].value = shellArgs[2].value = w;
2524 shellArgs[5].value = shellArgs[3].value = h;
2525 XtSetValues(shellWidget, &shellArgs[2], 4);
2526 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2527 marginH = h - boardHeight;
2529 CatchDeleteWindow(shellWidget, "QuitProc");
2534 if (appData.bitmapDirectory[0] != NULLCHAR) {
2538 CreateXPMBoard(appData.liteBackTextureFile, 1);
2539 CreateXPMBoard(appData.darkBackTextureFile, 0);
2543 /* Create regular pieces */
2544 if (!useImages) CreatePieces();
2549 if (appData.animate || appData.animateDragging)
2552 XtAugmentTranslations(formWidget,
2553 XtParseTranslationTable(globalTranslations));
2554 XtAugmentTranslations(boardWidget,
2555 XtParseTranslationTable(boardTranslations));
2556 XtAugmentTranslations(whiteTimerWidget,
2557 XtParseTranslationTable(whiteTranslations));
2558 XtAugmentTranslations(blackTimerWidget,
2559 XtParseTranslationTable(blackTranslations));
2561 /* Why is the following needed on some versions of X instead
2562 * of a translation? */
2563 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2564 (XtEventHandler) EventProc, NULL);
2567 /* [AS] Restore layout */
2568 if( wpMoveHistory.visible ) {
2572 if( wpEvalGraph.visible )
2577 if( wpEngineOutput.visible ) {
2578 EngineOutputPopUp();
2583 if (errorExitStatus == -1) {
2584 if (appData.icsActive) {
2585 /* We now wait until we see "login:" from the ICS before
2586 sending the logon script (problems with timestamp otherwise) */
2587 /*ICSInitScript();*/
2588 if (appData.icsInputBox) ICSInputBoxPopUp();
2592 signal(SIGWINCH, TermSizeSigHandler);
2594 signal(SIGINT, IntSigHandler);
2595 signal(SIGTERM, IntSigHandler);
2596 if (*appData.cmailGameName != NULLCHAR) {
2597 signal(SIGUSR1, CmailSigHandler);
2600 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2602 XtSetKeyboardFocus(shellWidget, formWidget);
2604 XtAppMainLoop(appContext);
2605 if (appData.debugMode) fclose(debugFP); // [DM] debug
2612 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2613 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2615 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2616 unlink(gameCopyFilename);
2617 unlink(gamePasteFilename);
2620 RETSIGTYPE TermSizeSigHandler(int sig)
2633 CmailSigHandler(sig)
2639 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2641 /* Activate call-back function CmailSigHandlerCallBack() */
2642 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2644 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2648 CmailSigHandlerCallBack(isr, closure, message, count, error)
2656 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2658 /**** end signal code ****/
2664 /* try to open the icsLogon script, either in the location given
2665 * or in the users HOME directory
2672 f = fopen(appData.icsLogon, "r");
2675 homedir = getenv("HOME");
2676 if (homedir != NULL)
2678 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2679 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2680 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2681 f = fopen(buf, "r");
2686 ProcessICSInitScript(f);
2688 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2697 EditCommentPopDown();
2712 if (!menuBarWidget) return;
2713 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2715 DisplayError("menuEdit.Revert", 0);
2717 XtSetSensitive(w, !grey);
2719 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2721 DisplayError("menuEdit.Annotate", 0);
2723 XtSetSensitive(w, !grey);
2728 SetMenuEnables(enab)
2732 if (!menuBarWidget) return;
2733 while (enab->name != NULL) {
2734 w = XtNameToWidget(menuBarWidget, enab->name);
2736 DisplayError(enab->name, 0);
2738 XtSetSensitive(w, enab->value);
2744 Enables icsEnables[] = {
2745 { "menuFile.Mail Move", False },
2746 { "menuFile.Reload CMail Message", False },
2747 { "menuMode.Machine Black", False },
2748 { "menuMode.Machine White", False },
2749 { "menuMode.Analysis Mode", False },
2750 { "menuMode.Analyze File", False },
2751 { "menuMode.Two Machines", False },
2753 { "menuEngine.Hint", False },
2754 { "menuEngine.Book", False },
2755 { "menuEngine.Move Now", False },
2756 { "menuOptions.Periodic Updates", False },
2757 { "menuOptions.Hide Thinking", False },
2758 { "menuOptions.Ponder Next Move", False },
2759 { "menuEngine.Engine #1 Settings", False },
2761 { "menuEngine.Engine #2 Settings", False },
2762 { "menuEdit.Annotate", False },
2766 Enables ncpEnables[] = {
2767 { "menuFile.Mail Move", False },
2768 { "menuFile.Reload CMail Message", False },
2769 { "menuMode.Machine White", False },
2770 { "menuMode.Machine Black", False },
2771 { "menuMode.Analysis Mode", False },
2772 { "menuMode.Analyze File", False },
2773 { "menuMode.Two Machines", False },
2774 { "menuMode.ICS Client", False },
2775 { "menuView.ICS Input Box", False },
2776 { "Action", False },
2777 { "menuEdit.Revert", False },
2778 { "menuEdit.Annotate", False },
2779 { "menuEngine.Engine #1 Settings", False },
2780 { "menuEngine.Engine #2 Settings", False },
2781 { "menuEngine.Move Now", False },
2782 { "menuEngine.Retract Move", False },
2783 { "menuOptions.Auto Flag", False },
2784 { "menuOptions.Auto Flip View", False },
2785 // { "menuOptions.ICS Alarm", False },
2786 { "menuOptions.Move Sound", False },
2787 { "menuOptions.Hide Thinking", False },
2788 { "menuOptions.Periodic Updates", False },
2789 { "menuOptions.Ponder Next Move", False },
2790 { "menuEngine.Hint", False },
2791 { "menuEngine.Book", False },
2795 Enables gnuEnables[] = {
2796 { "menuMode.ICS Client", False },
2797 { "menuView.ICS Input Box", False },
2798 { "menuAction.Accept", False },
2799 { "menuAction.Decline", False },
2800 { "menuAction.Rematch", False },
2801 { "menuAction.Adjourn", False },
2802 { "menuAction.Stop Examining", False },
2803 { "menuAction.Stop Observing", False },
2804 { "menuAction.Upload to Examine", False },
2805 { "menuEdit.Revert", False },
2806 { "menuEdit.Annotate", False },
2808 /* The next two options rely on SetCmailMode being called *after* */
2809 /* SetGNUMode so that when GNU is being used to give hints these */
2810 /* menu options are still available */
2812 { "menuFile.Mail Move", False },
2813 { "menuFile.Reload CMail Message", False },
2817 Enables cmailEnables[] = {
2819 { "menuAction.Call Flag", False },
2820 { "menuAction.Draw", True },
2821 { "menuAction.Adjourn", False },
2822 { "menuAction.Abort", False },
2823 { "menuAction.Stop Observing", False },
2824 { "menuAction.Stop Examining", False },
2825 { "menuFile.Mail Move", True },
2826 { "menuFile.Reload CMail Message", True },
2830 Enables trainingOnEnables[] = {
2831 { "menuMode.Edit Comment", False },
2832 { "menuMode.Pause", False },
2833 { "menuEdit.Forward", False },
2834 { "menuEdit.Backward", False },
2835 { "menuEdit.Forward to End", False },
2836 { "menuEdit.Back to Start", False },
2837 { "menuEngine.Move Now", False },
2838 { "menuEdit.Truncate Game", False },
2842 Enables trainingOffEnables[] = {
2843 { "menuMode.Edit Comment", True },
2844 { "menuMode.Pause", True },
2845 { "menuEdit.Forward", True },
2846 { "menuEdit.Backward", True },
2847 { "menuEdit.Forward to End", True },
2848 { "menuEdit.Back to Start", True },
2849 { "menuEngine.Move Now", True },
2850 { "menuEdit.Truncate Game", True },
2854 Enables machineThinkingEnables[] = {
2855 { "menuFile.Load Game", False },
2856 // { "menuFile.Load Next Game", False },
2857 // { "menuFile.Load Previous Game", False },
2858 // { "menuFile.Reload Same Game", False },
2859 { "menuEdit.Paste Game", False },
2860 { "menuFile.Load Position", False },
2861 // { "menuFile.Load Next Position", False },
2862 // { "menuFile.Load Previous Position", False },
2863 // { "menuFile.Reload Same Position", False },
2864 { "menuEdit.Paste Position", False },
2865 { "menuMode.Machine White", False },
2866 { "menuMode.Machine Black", False },
2867 { "menuMode.Two Machines", False },
2868 { "menuEngine.Retract Move", False },
2872 Enables userThinkingEnables[] = {
2873 { "menuFile.Load Game", True },
2874 // { "menuFile.Load Next Game", True },
2875 // { "menuFile.Load Previous Game", True },
2876 // { "menuFile.Reload Same Game", True },
2877 { "menuEdit.Paste Game", True },
2878 { "menuFile.Load Position", True },
2879 // { "menuFile.Load Next Position", True },
2880 // { "menuFile.Load Previous Position", True },
2881 // { "menuFile.Reload Same Position", True },
2882 { "menuEdit.Paste Position", True },
2883 { "menuMode.Machine White", True },
2884 { "menuMode.Machine Black", True },
2885 { "menuMode.Two Machines", True },
2886 { "menuEngine.Retract Move", True },
2892 SetMenuEnables(icsEnables);
2895 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2896 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2903 SetMenuEnables(ncpEnables);
2909 SetMenuEnables(gnuEnables);
2915 SetMenuEnables(cmailEnables);
2921 SetMenuEnables(trainingOnEnables);
2922 if (appData.showButtonBar) {
2923 XtSetSensitive(buttonBarWidget, False);
2929 SetTrainingModeOff()
2931 SetMenuEnables(trainingOffEnables);
2932 if (appData.showButtonBar) {
2933 XtSetSensitive(buttonBarWidget, True);
2938 SetUserThinkingEnables()
2940 if (appData.noChessProgram) return;
2941 SetMenuEnables(userThinkingEnables);
2945 SetMachineThinkingEnables()
2947 if (appData.noChessProgram) return;
2948 SetMenuEnables(machineThinkingEnables);
2950 case MachinePlaysBlack:
2951 case MachinePlaysWhite:
2952 case TwoMachinesPlay:
2953 XtSetSensitive(XtNameToWidget(menuBarWidget,
2954 ModeToWidgetName(gameMode)), True);
2961 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2962 #define HISTORY_SIZE 64
2963 static char *history[HISTORY_SIZE];
2964 int histIn = 0, histP = 0;
2967 SaveInHistory(char *cmd)
2969 if (history[histIn] != NULL) {
2970 free(history[histIn]);
2971 history[histIn] = NULL;
2973 if (*cmd == NULLCHAR) return;
2974 history[histIn] = StrSave(cmd);
2975 histIn = (histIn + 1) % HISTORY_SIZE;
2976 if (history[histIn] != NULL) {
2977 free(history[histIn]);
2978 history[histIn] = NULL;
2984 PrevInHistory(char *cmd)
2987 if (histP == histIn) {
2988 if (history[histIn] != NULL) free(history[histIn]);
2989 history[histIn] = StrSave(cmd);
2991 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
2992 if (newhp == histIn || history[newhp] == NULL) return NULL;
2994 return history[histP];
3000 if (histP == histIn) return NULL;
3001 histP = (histP + 1) % HISTORY_SIZE;
3002 return history[histP];
3004 // end of borrowed code
3006 #define Abs(n) ((n)<0 ? -(n) : (n))
3009 * Find a font that matches "pattern" that is as close as
3010 * possible to the targetPxlSize. Prefer fonts that are k
3011 * pixels smaller to fonts that are k pixels larger. The
3012 * pattern must be in the X Consortium standard format,
3013 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3014 * The return value should be freed with XtFree when no
3018 FindFont(pattern, targetPxlSize)
3022 char **fonts, *p, *best, *scalable, *scalableTail;
3023 int i, j, nfonts, minerr, err, pxlSize;
3026 char **missing_list;
3028 char *def_string, *base_fnt_lst, strInt[3];
3030 XFontStruct **fnt_list;
3032 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3033 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3034 p = strstr(pattern, "--");
3035 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3036 strcat(base_fnt_lst, strInt);
3037 strcat(base_fnt_lst, strchr(p + 2, '-'));
3039 if ((fntSet = XCreateFontSet(xDisplay,
3043 &def_string)) == NULL) {
3045 fprintf(stderr, _("Unable to create font set.\n"));
3049 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3051 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3053 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3054 programName, pattern);
3062 for (i=0; i<nfonts; i++) {
3065 if (*p != '-') continue;
3067 if (*p == NULLCHAR) break;
3068 if (*p++ == '-') j++;
3070 if (j < 7) continue;
3073 scalable = fonts[i];
3076 err = pxlSize - targetPxlSize;
3077 if (Abs(err) < Abs(minerr) ||
3078 (minerr > 0 && err < 0 && -err == minerr)) {
3084 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3085 /* If the error is too big and there is a scalable font,
3086 use the scalable font. */
3087 int headlen = scalableTail - scalable;
3088 p = (char *) XtMalloc(strlen(scalable) + 10);
3089 while (isdigit(*scalableTail)) scalableTail++;
3090 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3092 p = (char *) XtMalloc(strlen(best) + 2);
3093 safeStrCpy(p, best, strlen(best)+1 );
3095 if (appData.debugMode) {
3096 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3097 pattern, targetPxlSize, p);
3100 if (missing_count > 0)
3101 XFreeStringList(missing_list);
3102 XFreeFontSet(xDisplay, fntSet);
3104 XFreeFontNames(fonts);
3110 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3111 // must be called before all non-first callse to CreateGCs()
3112 XtReleaseGC(shellWidget, highlineGC);
3113 XtReleaseGC(shellWidget, lightSquareGC);
3114 XtReleaseGC(shellWidget, darkSquareGC);
3115 if (appData.monoMode) {
3116 if (DefaultDepth(xDisplay, xScreen) == 1) {
3117 XtReleaseGC(shellWidget, wbPieceGC);
3119 XtReleaseGC(shellWidget, bwPieceGC);
3122 XtReleaseGC(shellWidget, prelineGC);
3123 XtReleaseGC(shellWidget, jailSquareGC);
3124 XtReleaseGC(shellWidget, wdPieceGC);
3125 XtReleaseGC(shellWidget, wlPieceGC);
3126 XtReleaseGC(shellWidget, wjPieceGC);
3127 XtReleaseGC(shellWidget, bdPieceGC);
3128 XtReleaseGC(shellWidget, blPieceGC);
3129 XtReleaseGC(shellWidget, bjPieceGC);
3133 void CreateGCs(int redo)
3135 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3136 | GCBackground | GCFunction | GCPlaneMask;
3137 XGCValues gc_values;
3140 gc_values.plane_mask = AllPlanes;
3141 gc_values.line_width = lineGap;
3142 gc_values.line_style = LineSolid;
3143 gc_values.function = GXcopy;
3146 DeleteGCs(); // called a second time; clean up old GCs first
3147 } else { // [HGM] grid and font GCs created on first call only
3148 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3149 gc_values.background = XBlackPixel(xDisplay, xScreen);
3150 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3152 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3153 gc_values.background = XWhitePixel(xDisplay, xScreen);
3154 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3155 XSetFont(xDisplay, coordGC, coordFontID);
3157 // [HGM] make font for holdings counts (white on black)
3158 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3159 gc_values.background = XBlackPixel(xDisplay, xScreen);
3160 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3161 XSetFont(xDisplay, countGC, countFontID);
3163 if (appData.monoMode) {
3164 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3165 gc_values.background = XWhitePixel(xDisplay, xScreen);
3166 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3168 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3169 gc_values.background = XBlackPixel(xDisplay, xScreen);
3170 lightSquareGC = wbPieceGC
3171 = XtGetGC(shellWidget, value_mask, &gc_values);
3173 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3174 gc_values.background = XWhitePixel(xDisplay, xScreen);
3175 darkSquareGC = bwPieceGC
3176 = XtGetGC(shellWidget, value_mask, &gc_values);
3178 if (DefaultDepth(xDisplay, xScreen) == 1) {
3179 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3180 gc_values.function = GXcopyInverted;
3181 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3182 gc_values.function = GXcopy;
3183 if (XBlackPixel(xDisplay, xScreen) == 1) {
3184 bwPieceGC = darkSquareGC;
3185 wbPieceGC = copyInvertedGC;
3187 bwPieceGC = copyInvertedGC;
3188 wbPieceGC = lightSquareGC;
3192 gc_values.foreground = highlightSquareColor;
3193 gc_values.background = highlightSquareColor;
3194 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3196 gc_values.foreground = premoveHighlightColor;
3197 gc_values.background = premoveHighlightColor;
3198 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3200 gc_values.foreground = lightSquareColor;
3201 gc_values.background = darkSquareColor;
3202 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3204 gc_values.foreground = darkSquareColor;
3205 gc_values.background = lightSquareColor;
3206 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3208 gc_values.foreground = jailSquareColor;
3209 gc_values.background = jailSquareColor;
3210 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3212 gc_values.foreground = whitePieceColor;
3213 gc_values.background = darkSquareColor;
3214 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3216 gc_values.foreground = whitePieceColor;
3217 gc_values.background = lightSquareColor;
3218 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3220 gc_values.foreground = whitePieceColor;
3221 gc_values.background = jailSquareColor;
3222 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3224 gc_values.foreground = blackPieceColor;
3225 gc_values.background = darkSquareColor;
3226 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3228 gc_values.foreground = blackPieceColor;
3229 gc_values.background = lightSquareColor;
3230 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3232 gc_values.foreground = blackPieceColor;
3233 gc_values.background = jailSquareColor;
3234 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3238 void loadXIM(xim, xmask, filename, dest, mask)
3251 fp = fopen(filename, "rb");
3253 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3260 for (y=0; y<h; ++y) {
3261 for (x=0; x<h; ++x) {
3266 XPutPixel(xim, x, y, blackPieceColor);
3268 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3271 XPutPixel(xim, x, y, darkSquareColor);
3273 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3276 XPutPixel(xim, x, y, whitePieceColor);
3278 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3281 XPutPixel(xim, x, y, lightSquareColor);
3283 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3291 /* create Pixmap of piece */
3292 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3294 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3297 /* create Pixmap of clipmask
3298 Note: We assume the white/black pieces have the same
3299 outline, so we make only 6 masks. This is okay
3300 since the XPM clipmask routines do the same. */
3302 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3304 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3307 /* now create the 1-bit version */
3308 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3311 values.foreground = 1;
3312 values.background = 0;
3314 /* Don't use XtGetGC, not read only */
3315 maskGC = XCreateGC(xDisplay, *mask,
3316 GCForeground | GCBackground, &values);
3317 XCopyPlane(xDisplay, temp, *mask, maskGC,
3318 0, 0, squareSize, squareSize, 0, 0, 1);
3319 XFreePixmap(xDisplay, temp);
3324 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3326 void CreateXIMPieces()
3331 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3336 /* The XSynchronize calls were copied from CreatePieces.
3337 Not sure if needed, but can't hurt */
3338 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3341 /* temp needed by loadXIM() */
3342 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3343 0, 0, ss, ss, AllPlanes, XYPixmap);
3345 if (strlen(appData.pixmapDirectory) == 0) {
3349 if (appData.monoMode) {
3350 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3354 fprintf(stderr, _("\nLoading XIMs...\n"));
3356 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3357 fprintf(stderr, "%d", piece+1);
3358 for (kind=0; kind<4; kind++) {
3359 fprintf(stderr, ".");
3360 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3361 ExpandPathName(appData.pixmapDirectory),
3362 piece <= (int) WhiteKing ? "" : "w",
3363 pieceBitmapNames[piece],
3365 ximPieceBitmap[kind][piece] =
3366 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3367 0, 0, ss, ss, AllPlanes, XYPixmap);
3368 if (appData.debugMode)
3369 fprintf(stderr, _("(File:%s:) "), buf);
3370 loadXIM(ximPieceBitmap[kind][piece],
3372 &(xpmPieceBitmap2[kind][piece]),
3373 &(ximMaskPm2[piece]));
3374 if(piece <= (int)WhiteKing)
3375 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3377 fprintf(stderr," ");
3379 /* Load light and dark squares */
3380 /* If the LSQ and DSQ pieces don't exist, we will
3381 draw them with solid squares. */
3382 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3383 if (access(buf, 0) != 0) {
3387 fprintf(stderr, _("light square "));
3389 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3390 0, 0, ss, ss, AllPlanes, XYPixmap);
3391 if (appData.debugMode)
3392 fprintf(stderr, _("(File:%s:) "), buf);
3394 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3395 fprintf(stderr, _("dark square "));
3396 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3397 ExpandPathName(appData.pixmapDirectory), ss);
3398 if (appData.debugMode)
3399 fprintf(stderr, _("(File:%s:) "), buf);
3401 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3402 0, 0, ss, ss, AllPlanes, XYPixmap);
3403 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3404 xpmJailSquare = xpmLightSquare;
3406 fprintf(stderr, _("Done.\n"));
3408 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3412 void CreateXPMBoard(char *s, int kind)
3416 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3417 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3418 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3422 void FreeXPMPieces()
3423 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3424 // thisroutine has to be called t free the old piece pixmaps
3426 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3427 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3429 XFreePixmap(xDisplay, xpmLightSquare);
3430 XFreePixmap(xDisplay, xpmDarkSquare);
3434 void CreateXPMPieces()
3438 u_int ss = squareSize;
3440 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3441 XpmColorSymbol symbols[4];
3442 static int redo = False;
3444 if(redo) FreeXPMPieces(); else redo = 1;
3446 /* The XSynchronize calls were copied from CreatePieces.
3447 Not sure if needed, but can't hurt */
3448 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3450 /* Setup translations so piece colors match square colors */
3451 symbols[0].name = "light_piece";
3452 symbols[0].value = appData.whitePieceColor;
3453 symbols[1].name = "dark_piece";
3454 symbols[1].value = appData.blackPieceColor;
3455 symbols[2].name = "light_square";
3456 symbols[2].value = appData.lightSquareColor;
3457 symbols[3].name = "dark_square";
3458 symbols[3].value = appData.darkSquareColor;
3460 attr.valuemask = XpmColorSymbols;
3461 attr.colorsymbols = symbols;
3462 attr.numsymbols = 4;
3464 if (appData.monoMode) {
3465 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3469 if (strlen(appData.pixmapDirectory) == 0) {
3470 XpmPieces* pieces = builtInXpms;
3473 while (pieces->size != squareSize && pieces->size) pieces++;
3474 if (!pieces->size) {
3475 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3478 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3479 for (kind=0; kind<4; kind++) {
3481 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3482 pieces->xpm[piece][kind],
3483 &(xpmPieceBitmap2[kind][piece]),
3484 NULL, &attr)) != 0) {
3485 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3489 if(piece <= (int) WhiteKing)
3490 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3494 xpmJailSquare = xpmLightSquare;
3498 fprintf(stderr, _("\nLoading XPMs...\n"));
3501 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3502 fprintf(stderr, "%d ", piece+1);
3503 for (kind=0; kind<4; kind++) {
3504 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3505 ExpandPathName(appData.pixmapDirectory),
3506 piece > (int) WhiteKing ? "w" : "",
3507 pieceBitmapNames[piece],
3509 if (appData.debugMode) {
3510 fprintf(stderr, _("(File:%s:) "), buf);
3512 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3513 &(xpmPieceBitmap2[kind][piece]),
3514 NULL, &attr)) != 0) {
3515 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3516 // [HGM] missing: read of unorthodox piece failed; substitute King.
3517 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3518 ExpandPathName(appData.pixmapDirectory),
3520 if (appData.debugMode) {
3521 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3523 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3524 &(xpmPieceBitmap2[kind][piece]),
3528 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3533 if(piece <= (int) WhiteKing)
3534 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3537 /* Load light and dark squares */
3538 /* If the LSQ and DSQ pieces don't exist, we will
3539 draw them with solid squares. */
3540 fprintf(stderr, _("light square "));
3541 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3542 if (access(buf, 0) != 0) {
3546 if (appData.debugMode)
3547 fprintf(stderr, _("(File:%s:) "), buf);
3549 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3550 &xpmLightSquare, NULL, &attr)) != 0) {
3551 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3554 fprintf(stderr, _("dark square "));
3555 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3556 ExpandPathName(appData.pixmapDirectory), ss);
3557 if (appData.debugMode) {
3558 fprintf(stderr, _("(File:%s:) "), buf);
3560 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3561 &xpmDarkSquare, NULL, &attr)) != 0) {
3562 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3566 xpmJailSquare = xpmLightSquare;
3567 fprintf(stderr, _("Done.\n"));
3569 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3572 #endif /* HAVE_LIBXPM */
3575 /* No built-in bitmaps */
3580 u_int ss = squareSize;
3582 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3585 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3586 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3587 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3588 pieceBitmapNames[piece],
3589 ss, kind == SOLID ? 's' : 'o');
3590 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3591 if(piece <= (int)WhiteKing)
3592 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3596 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3600 /* With built-in bitmaps */
3603 BuiltInBits* bib = builtInBits;
3606 u_int ss = squareSize;
3608 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3611 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3613 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3614 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3615 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3616 pieceBitmapNames[piece],
3617 ss, kind == SOLID ? 's' : 'o');
3618 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3619 bib->bits[kind][piece], ss, ss);
3620 if(piece <= (int)WhiteKing)
3621 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3625 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3630 void ReadBitmap(pm, name, bits, wreq, hreq)
3633 unsigned char bits[];
3639 char msg[MSG_SIZ], fullname[MSG_SIZ];
3641 if (*appData.bitmapDirectory != NULLCHAR) {
3642 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3643 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3644 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3645 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3646 &w, &h, pm, &x_hot, &y_hot);
3647 fprintf(stderr, "load %s\n", name);
3648 if (errcode != BitmapSuccess) {
3650 case BitmapOpenFailed:
3651 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3653 case BitmapFileInvalid:
3654 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3656 case BitmapNoMemory:
3657 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3661 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3665 fprintf(stderr, _("%s: %s...using built-in\n"),
3667 } else if (w != wreq || h != hreq) {
3669 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3670 programName, fullname, w, h, wreq, hreq);
3676 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3685 if (lineGap == 0) return;
3687 /* [HR] Split this into 2 loops for non-square boards. */
3689 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3690 gridSegments[i].x1 = 0;
3691 gridSegments[i].x2 =
3692 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3693 gridSegments[i].y1 = gridSegments[i].y2
3694 = lineGap / 2 + (i * (squareSize + lineGap));
3697 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3698 gridSegments[j + i].y1 = 0;
3699 gridSegments[j + i].y2 =
3700 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3701 gridSegments[j + i].x1 = gridSegments[j + i].x2
3702 = lineGap / 2 + (j * (squareSize + lineGap));
3706 static void MenuBarSelect(w, addr, index)
3711 XtActionProc proc = (XtActionProc) addr;
3713 (proc)(NULL, NULL, NULL, NULL);
3716 void CreateMenuBarPopup(parent, name, mb)
3726 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3729 XtSetArg(args[j], XtNleftMargin, 20); j++;
3730 XtSetArg(args[j], XtNrightMargin, 20); j++;
3732 while (mi->string != NULL) {
3733 if (strcmp(mi->string, "----") == 0) {
3734 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3737 XtSetArg(args[j], XtNlabel, XtNewString(mi->string));
3738 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3740 XtAddCallback(entry, XtNcallback,
3741 (XtCallbackProc) MenuBarSelect,
3742 (caddr_t) mi->proc);
3748 Widget CreateMenuBar(mb)
3752 Widget anchor, menuBar;
3754 char menuName[MSG_SIZ];
3757 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3758 XtSetArg(args[j], XtNvSpace, 0); j++;
3759 XtSetArg(args[j], XtNborderWidth, 0); j++;
3760 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3761 formWidget, args, j);
3763 while (mb->name != NULL) {
3764 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3765 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3767 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3770 shortName[0] = mb->name[0];
3771 shortName[1] = NULLCHAR;
3772 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3775 XtSetArg(args[j], XtNlabel, XtNewString(mb->name)); j++;
3778 XtSetArg(args[j], XtNborderWidth, 0); j++;
3779 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3781 CreateMenuBarPopup(menuBar, menuName, mb);
3787 Widget CreateButtonBar(mi)
3791 Widget button, buttonBar;
3795 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3797 XtSetArg(args[j], XtNhSpace, 0); j++;
3799 XtSetArg(args[j], XtNborderWidth, 0); j++;
3800 XtSetArg(args[j], XtNvSpace, 0); j++;
3801 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3802 formWidget, args, j);
3804 while (mi->string != NULL) {
3807 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3808 XtSetArg(args[j], XtNborderWidth, 0); j++;
3810 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3811 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3812 buttonBar, args, j);
3813 XtAddCallback(button, XtNcallback,
3814 (XtCallbackProc) MenuBarSelect,
3815 (caddr_t) mi->proc);
3822 CreatePieceMenu(name, color)
3829 ChessSquare selection;
3831 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3832 boardWidget, args, 0);
3834 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3835 String item = pieceMenuStrings[color][i];
3837 if (strcmp(item, "----") == 0) {
3838 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3841 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3842 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3844 selection = pieceMenuTranslation[color][i];
3845 XtAddCallback(entry, XtNcallback,
3846 (XtCallbackProc) PieceMenuSelect,
3847 (caddr_t) selection);
3848 if (selection == WhitePawn || selection == BlackPawn) {
3849 XtSetArg(args[0], XtNpopupOnEntry, entry);
3850 XtSetValues(menu, args, 1);
3863 ChessSquare selection;
3865 whitePieceMenu = CreatePieceMenu("menuW", 0);
3866 blackPieceMenu = CreatePieceMenu("menuB", 1);
3868 XtRegisterGrabAction(PieceMenuPopup, True,
3869 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3870 GrabModeAsync, GrabModeAsync);
3872 XtSetArg(args[0], XtNlabel, _("Drop"));
3873 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3874 boardWidget, args, 1);
3875 for (i = 0; i < DROP_MENU_SIZE; i++) {
3876 String item = dropMenuStrings[i];
3878 if (strcmp(item, "----") == 0) {
3879 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3882 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3883 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3885 selection = dropMenuTranslation[i];
3886 XtAddCallback(entry, XtNcallback,
3887 (XtCallbackProc) DropMenuSelect,
3888 (caddr_t) selection);
3893 void SetupDropMenu()
3901 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3902 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3903 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3904 dmEnables[i].piece);
3905 XtSetSensitive(entry, p != NULL || !appData.testLegality
3906 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3907 && !appData.icsActive));
3909 while (p && *p++ == dmEnables[i].piece) count++;
3910 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3912 XtSetArg(args[j], XtNlabel, label); j++;
3913 XtSetValues(entry, args, j);
3917 void PieceMenuPopup(w, event, params, num_params)
3921 Cardinal *num_params;
3923 String whichMenu; int menuNr;
3924 if (event->type == ButtonRelease)
3925 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3926 else if (event->type == ButtonPress)
3927 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3929 case 0: whichMenu = params[0]; break;
3930 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3932 case -1: if (errorUp) ErrorPopDown();
3935 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3938 static void PieceMenuSelect(w, piece, junk)
3943 if (pmFromX < 0 || pmFromY < 0) return;
3944 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3947 static void DropMenuSelect(w, piece, junk)
3952 if (pmFromX < 0 || pmFromY < 0) return;
3953 DropMenuEvent(piece, pmFromX, pmFromY);
3956 void WhiteClock(w, event, prms, nprms)
3965 void BlackClock(w, event, prms, nprms)
3976 * If the user selects on a border boundary, return -1; if off the board,
3977 * return -2. Otherwise map the event coordinate to the square.
3979 int EventToSquare(x, limit)
3987 if ((x % (squareSize + lineGap)) >= squareSize)
3989 x /= (squareSize + lineGap);
3995 static void do_flash_delay(msec)
4001 static void drawHighlight(file, rank, gc)
4007 if (lineGap == 0) return;
4010 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4011 (squareSize + lineGap);
4012 y = lineGap/2 + rank * (squareSize + lineGap);
4014 x = lineGap/2 + file * (squareSize + lineGap);
4015 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4016 (squareSize + lineGap);
4019 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4020 squareSize+lineGap, squareSize+lineGap);
4023 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4024 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4027 SetHighlights(fromX, fromY, toX, toY)
4028 int fromX, fromY, toX, toY;
4030 if (hi1X != fromX || hi1Y != fromY) {
4031 if (hi1X >= 0 && hi1Y >= 0) {
4032 drawHighlight(hi1X, hi1Y, lineGC);
4034 } // [HGM] first erase both, then draw new!
4035 if (hi2X != toX || hi2Y != toY) {
4036 if (hi2X >= 0 && hi2Y >= 0) {
4037 drawHighlight(hi2X, hi2Y, lineGC);
4040 if (hi1X != fromX || hi1Y != fromY) {
4041 if (fromX >= 0 && fromY >= 0) {
4042 drawHighlight(fromX, fromY, highlineGC);
4045 if (hi2X != toX || hi2Y != toY) {
4046 if (toX >= 0 && toY >= 0) {
4047 drawHighlight(toX, toY, highlineGC);
4059 SetHighlights(-1, -1, -1, -1);
4064 SetPremoveHighlights(fromX, fromY, toX, toY)
4065 int fromX, fromY, toX, toY;
4067 if (pm1X != fromX || pm1Y != fromY) {
4068 if (pm1X >= 0 && pm1Y >= 0) {
4069 drawHighlight(pm1X, pm1Y, lineGC);
4071 if (fromX >= 0 && fromY >= 0) {
4072 drawHighlight(fromX, fromY, prelineGC);
4075 if (pm2X != toX || pm2Y != toY) {
4076 if (pm2X >= 0 && pm2Y >= 0) {
4077 drawHighlight(pm2X, pm2Y, lineGC);
4079 if (toX >= 0 && toY >= 0) {
4080 drawHighlight(toX, toY, prelineGC);
4090 ClearPremoveHighlights()
4092 SetPremoveHighlights(-1, -1, -1, -1);
4095 static int CutOutSquare(x, y, x0, y0, kind)
4096 int x, y, *x0, *y0, kind;
4098 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4099 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4101 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4102 if(textureW[kind] < W*squareSize)
4103 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4105 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4106 if(textureH[kind] < H*squareSize)
4107 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4109 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4113 static void BlankSquare(x, y, color, piece, dest, fac)
4114 int x, y, color, fac;
4117 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4119 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4120 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4121 squareSize, squareSize, x*fac, y*fac);
4123 if (useImages && useImageSqs) {
4127 pm = xpmLightSquare;
4132 case 2: /* neutral */
4137 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4138 squareSize, squareSize, x*fac, y*fac);
4148 case 2: /* neutral */
4153 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4158 I split out the routines to draw a piece so that I could
4159 make a generic flash routine.
4161 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4163 int square_color, x, y;
4166 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4167 switch (square_color) {
4169 case 2: /* neutral */
4171 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4172 ? *pieceToOutline(piece)
4173 : *pieceToSolid(piece),
4174 dest, bwPieceGC, 0, 0,
4175 squareSize, squareSize, x, y);
4178 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4179 ? *pieceToSolid(piece)
4180 : *pieceToOutline(piece),
4181 dest, wbPieceGC, 0, 0,
4182 squareSize, squareSize, x, y);
4187 static void monoDrawPiece(piece, square_color, x, y, dest)
4189 int square_color, x, y;
4192 switch (square_color) {
4194 case 2: /* neutral */
4196 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4197 ? *pieceToOutline(piece)
4198 : *pieceToSolid(piece),
4199 dest, bwPieceGC, 0, 0,
4200 squareSize, squareSize, x, y, 1);
4203 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4204 ? *pieceToSolid(piece)
4205 : *pieceToOutline(piece),
4206 dest, wbPieceGC, 0, 0,
4207 squareSize, squareSize, x, y, 1);
4212 static void colorDrawPiece(piece, square_color, x, y, dest)
4214 int square_color, x, y;
4217 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4218 switch (square_color) {
4220 XCopyPlane(xDisplay, *pieceToSolid(piece),
4221 dest, (int) piece < (int) BlackPawn
4222 ? wlPieceGC : blPieceGC, 0, 0,
4223 squareSize, squareSize, x, y, 1);
4226 XCopyPlane(xDisplay, *pieceToSolid(piece),
4227 dest, (int) piece < (int) BlackPawn
4228 ? wdPieceGC : bdPieceGC, 0, 0,
4229 squareSize, squareSize, x, y, 1);
4231 case 2: /* neutral */
4233 XCopyPlane(xDisplay, *pieceToSolid(piece),
4234 dest, (int) piece < (int) BlackPawn
4235 ? wjPieceGC : bjPieceGC, 0, 0,
4236 squareSize, squareSize, x, y, 1);
4241 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4243 int square_color, x, y;
4246 int kind, p = piece;