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 MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void IcsClientProc P((Widget w, XEvent *event, String *prms,
353 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void EditPositionProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void EditCommentProc P((Widget w, XEvent *event,
358 String *prms, Cardinal *nprms));
359 void IcsInputBoxProc P((Widget w, XEvent *event,
360 String *prms, Cardinal *nprms));
361 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void StopObservingProc P((Widget w, XEvent *event, String *prms,
377 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
379 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
388 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
390 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
393 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
395 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
397 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
402 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
405 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
407 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
409 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
412 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
414 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
416 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
418 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
420 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
423 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
425 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
427 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
429 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void DisplayMove P((int moveNumber));
441 void DisplayTitle P((char *title));
442 void ICSInitScript P((void));
443 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
444 void ErrorPopUp P((char *title, char *text, int modal));
445 void ErrorPopDown P((void));
446 static char *ExpandPathName P((char *path));
447 static void CreateAnimVars P((void));
448 static void DragPieceMove P((int x, int y));
449 static void DrawDragPiece P((void));
450 char *ModeToWidgetName P((GameMode mode));
451 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void GameListOptionsPopDown P(());
466 void ShufflePopDown P(());
467 void TimeControlPopDown P(());
468 void GenericPopDown P(());
469 void update_ics_width P(());
470 int get_term_width P(());
471 int CopyMemoProc P(());
472 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
473 Boolean IsDrawArrowEnabled P(());
476 * XBoard depends on Xt R4 or higher
478 int xtVersion = XtSpecificationRelease;
483 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
484 jailSquareColor, highlightSquareColor, premoveHighlightColor;
485 Pixel lowTimeWarningColor;
486 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
487 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
488 wjPieceGC, bjPieceGC, prelineGC, countGC;
489 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
490 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
491 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
492 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
493 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
494 ICSInputShell, fileNameShell, askQuestionShell;
495 Widget historyShell, evalGraphShell, gameListShell;
496 int hOffset; // [HGM] dual
497 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
498 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
499 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
500 Font clockFontID, coordFontID, countFontID;
501 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
502 XtAppContext appContext;
504 char *oldICSInteractionTitle;
508 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
510 Position commentX = -1, commentY = -1;
511 Dimension commentW, commentH;
512 typedef unsigned int BoardSize;
514 Boolean chessProgram;
516 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
517 int squareSize, smallLayout = 0, tinyLayout = 0,
518 marginW, marginH, // [HGM] for run-time resizing
519 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
520 ICSInputBoxUp = False, askQuestionUp = False,
521 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
522 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
523 Pixel timerForegroundPixel, timerBackgroundPixel;
524 Pixel buttonForegroundPixel, buttonBackgroundPixel;
525 char *chessDir, *programName, *programVersion,
526 *gameCopyFilename, *gamePasteFilename;
527 Boolean alwaysOnTop = False;
528 Boolean saveSettingsOnExit;
529 char *settingsFileName;
530 char *icsTextMenuString;
532 char *firstChessProgramNames;
533 char *secondChessProgramNames;
535 WindowPlacement wpMain;
536 WindowPlacement wpConsole;
537 WindowPlacement wpComment;
538 WindowPlacement wpMoveHistory;
539 WindowPlacement wpEvalGraph;
540 WindowPlacement wpEngineOutput;
541 WindowPlacement wpGameList;
542 WindowPlacement wpTags;
546 Pixmap pieceBitmap[2][(int)BlackPawn];
547 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
548 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
549 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
550 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
551 Pixmap xpmBoardBitmap[2];
552 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
553 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
554 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
555 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
556 XImage *ximLightSquare, *ximDarkSquare;
559 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
560 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
562 #define White(piece) ((int)(piece) < (int)BlackPawn)
564 /* Variables for doing smooth animation. This whole thing
565 would be much easier if the board was double-buffered,
566 but that would require a fairly major rewrite. */
571 GC blitGC, pieceGC, outlineGC;
572 XPoint startSquare, prevFrame, mouseDelta;
576 int startBoardX, startBoardY;
579 /* There can be two pieces being animated at once: a player
580 can begin dragging a piece before the remote opponent has moved. */
582 static AnimState game, player;
584 /* Bitmaps for use as masks when drawing XPM pieces.
585 Need one for each black and white piece. */
586 static Pixmap xpmMask[BlackKing + 1];
588 /* This magic number is the number of intermediate frames used
589 in each half of the animation. For short moves it's reduced
590 by 1. The total number of frames will be factor * 2 + 1. */
593 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
595 MenuItem fileMenu[] = {
596 {N_("New Game Ctrl+N"), "New Game", ResetProc},
597 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
598 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
599 {"----", NULL, NothingProc},
600 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
601 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
602 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
603 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
604 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
605 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
606 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
607 {"----", NULL, NothingProc},
608 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
609 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
610 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
611 {"----", NULL, NothingProc},
612 {N_("Mail Move"), "Mail Move", MailMoveProc},
613 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
614 {"----", NULL, NothingProc},
615 {N_("Quit Ctr+Q"), "Exit", QuitProc},
619 MenuItem editMenu[] = {
620 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
621 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
622 {"----", NULL, NothingProc},
623 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
624 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
625 {"----", NULL, NothingProc},
626 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
627 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
628 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
629 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
630 {"----", NULL, NothingProc},
631 {N_("Revert Home"), "Revert", RevertProc},
632 {N_("Annotate"), "Annotate", AnnotateProc},
633 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
634 {"----", NULL, NothingProc},
635 {N_("Backward Alt+Left"), "Backward", BackwardProc},
636 {N_("Forward Alt+Right"), "Forward", ForwardProc},
637 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
638 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
642 MenuItem viewMenu[] = {
643 {N_("Flip View F2"), "Flip View", FlipViewProc},
644 {"----", NULL, NothingProc},
645 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
646 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
647 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
648 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
649 {"----", NULL, NothingProc},
650 {N_("Tags"), "Show Tags", EditTagsProc},
651 {N_("Comments"), "Show Comments", EditCommentProc},
652 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
653 {"----", NULL, NothingProc},
654 {N_("Board..."), "Board Options", BoardOptionsProc},
655 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
659 MenuItem modeMenu[] = {
660 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
661 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
662 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
663 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
664 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
665 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
666 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
667 {N_("Training"), "Training", TrainingProc},
668 {N_("ICS Client"), "ICS Client", IcsClientProc},
669 {"----", NULL, NothingProc},
670 {N_("Machine Match"), "Machine Match", MatchProc},
671 {N_("Pause Pause"), "Pause", PauseProc},
675 MenuItem actionMenu[] = {
676 {N_("Accept F3"), "Accept", AcceptProc},
677 {N_("Decline F4"), "Decline", DeclineProc},
678 {N_("Rematch F12"), "Rematch", RematchProc},
679 {"----", NULL, NothingProc},
680 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
681 {N_("Draw F6"), "Draw", DrawProc},
682 {N_("Adjourn F7"), "Adjourn", AdjournProc},
683 {N_("Abort F8"),"Abort", AbortProc},
684 {N_("Resign F9"), "Resign", ResignProc},
685 {"----", NULL, NothingProc},
686 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
687 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
688 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
689 {"----", NULL, NothingProc},
690 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
691 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
692 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
696 MenuItem engineMenu[] = {
697 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
698 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
699 {"----", NULL, NothingProc},
700 {N_("Hint"), "Hint", HintProc},
701 {N_("Book"), "Book", BookProc},
702 {"----", NULL, NothingProc},
703 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
704 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
708 MenuItem optionsMenu[] = {
709 #define OPTIONSDIALOG
711 {N_("General ..."), "General", OptionsProc},
713 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
714 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
715 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
716 {N_("ICS ..."), "ICS", IcsOptionsProc},
717 {N_("Match ..."), "Match", MatchOptionsProc},
718 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
719 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
720 // {N_(" ..."), "", OptionsProc},
721 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
722 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
723 {"----", NULL, NothingProc},
724 #ifndef OPTIONSDIALOG
725 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
726 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
727 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
728 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
729 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
730 {N_("Blindfold"), "Blindfold", BlindfoldProc},
731 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
733 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
735 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
736 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
737 {N_("Move Sound"), "Move Sound", MoveSoundProc},
738 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
739 {N_("One-Click Moving"), "OneClick", OneClickProc},
740 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
741 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
742 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
743 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
744 // {N_("Premove"), "Premove", PremoveProc},
745 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
746 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
747 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
748 {"----", NULL, NothingProc},
750 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
751 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
755 MenuItem helpMenu[] = {
756 {N_("Info XBoard"), "Info XBoard", InfoProc},
757 {N_("Man XBoard F1"), "Man XBoard", ManProc},
758 {"----", NULL, NothingProc},
759 {N_("About XBoard"), "About XBoard", AboutProc},
764 {N_("File"), "File", fileMenu},
765 {N_("Edit"), "Edit", editMenu},
766 {N_("View"), "View", viewMenu},
767 {N_("Mode"), "Mode", modeMenu},
768 {N_("Action"), "Action", actionMenu},
769 {N_("Engine"), "Engine", engineMenu},
770 {N_("Options"), "Options", optionsMenu},
771 {N_("Help"), "Help", helpMenu},
775 #define PAUSE_BUTTON "P"
776 MenuItem buttonBar[] = {
777 {"<<", "<<", ToStartProc},
778 {"<", "<", BackwardProc},
779 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
780 {">", ">", ForwardProc},
781 {">>", ">>", ToEndProc},
785 #define PIECE_MENU_SIZE 18
786 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
787 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
788 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
789 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
790 N_("Empty square"), N_("Clear board") },
791 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
792 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
793 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
794 N_("Empty square"), N_("Clear board") }
796 /* must be in same order as PieceMenuStrings! */
797 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
798 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
799 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
800 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
801 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
802 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
803 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
804 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
805 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
808 #define DROP_MENU_SIZE 6
809 String dropMenuStrings[DROP_MENU_SIZE] = {
810 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
812 /* must be in same order as PieceMenuStrings! */
813 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
814 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
815 WhiteRook, WhiteQueen
823 DropMenuEnables dmEnables[] = {
841 { XtNborderWidth, 0 },
842 { XtNdefaultDistance, 0 },
846 { XtNborderWidth, 0 },
847 { XtNresizable, (XtArgVal) True },
851 { XtNborderWidth, 0 },
857 { XtNjustify, (XtArgVal) XtJustifyRight },
858 { XtNlabel, (XtArgVal) "..." },
859 { XtNresizable, (XtArgVal) True },
860 { XtNresize, (XtArgVal) False }
863 Arg messageArgs[] = {
864 { XtNjustify, (XtArgVal) XtJustifyLeft },
865 { XtNlabel, (XtArgVal) "..." },
866 { XtNresizable, (XtArgVal) True },
867 { XtNresize, (XtArgVal) False }
871 { XtNborderWidth, 0 },
872 { XtNjustify, (XtArgVal) XtJustifyLeft }
875 XtResource clientResources[] = {
876 { "flashCount", "flashCount", XtRInt, sizeof(int),
877 XtOffset(AppDataPtr, flashCount), XtRImmediate,
878 (XtPointer) FLASH_COUNT },
881 XrmOptionDescRec shellOptions[] = {
882 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
883 { "-flash", "flashCount", XrmoptionNoArg, "3" },
884 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
887 XtActionsRec boardActions[] = {
888 { "DrawPosition", DrawPositionProc },
889 { "HandleUserMove", HandleUserMove },
890 { "AnimateUserMove", AnimateUserMove },
891 { "HandlePV", HandlePV },
892 { "SelectPV", SelectPV },
893 { "StopPV", StopPV },
894 { "FileNameAction", FileNameAction },
895 { "AskQuestionProc", AskQuestionProc },
896 { "AskQuestionReplyAction", AskQuestionReplyAction },
897 { "PieceMenuPopup", PieceMenuPopup },
898 { "WhiteClock", WhiteClock },
899 { "BlackClock", BlackClock },
900 { "Iconify", Iconify },
901 { "ResetProc", ResetProc },
902 { "NewVariantProc", NewVariantProc },
903 { "LoadGameProc", LoadGameProc },
904 { "LoadNextGameProc", LoadNextGameProc },
905 { "LoadPrevGameProc", LoadPrevGameProc },
906 { "LoadSelectedProc", LoadSelectedProc },
907 { "SetFilterProc", SetFilterProc },
908 { "ReloadGameProc", ReloadGameProc },
909 { "LoadPositionProc", LoadPositionProc },
910 { "LoadNextPositionProc", LoadNextPositionProc },
911 { "LoadPrevPositionProc", LoadPrevPositionProc },
912 { "ReloadPositionProc", ReloadPositionProc },
913 { "CopyPositionProc", CopyPositionProc },
914 { "PastePositionProc", PastePositionProc },
915 { "CopyGameProc", CopyGameProc },
916 { "PasteGameProc", PasteGameProc },
917 { "SaveGameProc", SaveGameProc },
918 { "SavePositionProc", SavePositionProc },
919 { "MailMoveProc", MailMoveProc },
920 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
921 { "QuitProc", QuitProc },
922 { "MachineWhiteProc", MachineWhiteProc },
923 { "MachineBlackProc", MachineBlackProc },
924 { "AnalysisModeProc", AnalyzeModeProc },
925 { "AnalyzeFileProc", AnalyzeFileProc },
926 { "TwoMachinesProc", TwoMachinesProc },
927 { "IcsClientProc", IcsClientProc },
928 { "EditGameProc", EditGameProc },
929 { "EditPositionProc", EditPositionProc },
930 { "TrainingProc", EditPositionProc },
931 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
932 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
933 { "ShowGameListProc", ShowGameListProc },
934 { "ShowMoveListProc", HistoryShowProc},
935 { "EditTagsProc", EditCommentProc },
936 { "EditCommentProc", EditCommentProc },
937 { "IcsInputBoxProc", IcsInputBoxProc },
938 { "PauseProc", PauseProc },
939 { "AcceptProc", AcceptProc },
940 { "DeclineProc", DeclineProc },
941 { "RematchProc", RematchProc },
942 { "CallFlagProc", CallFlagProc },
943 { "DrawProc", DrawProc },
944 { "AdjournProc", AdjournProc },
945 { "AbortProc", AbortProc },
946 { "ResignProc", ResignProc },
947 { "AdjuWhiteProc", AdjuWhiteProc },
948 { "AdjuBlackProc", AdjuBlackProc },
949 { "AdjuDrawProc", AdjuDrawProc },
950 { "EnterKeyProc", EnterKeyProc },
951 { "UpKeyProc", UpKeyProc },
952 { "DownKeyProc", DownKeyProc },
953 { "StopObservingProc", StopObservingProc },
954 { "StopExaminingProc", StopExaminingProc },
955 { "UploadProc", UploadProc },
956 { "BackwardProc", BackwardProc },
957 { "ForwardProc", ForwardProc },
958 { "ToStartProc", ToStartProc },
959 { "ToEndProc", ToEndProc },
960 { "RevertProc", RevertProc },
961 { "AnnotateProc", AnnotateProc },
962 { "TruncateGameProc", TruncateGameProc },
963 { "MoveNowProc", MoveNowProc },
964 { "RetractMoveProc", RetractMoveProc },
965 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
966 { "UciMenuProc", (XtActionProc) UciMenuProc },
967 { "TimeControlProc", (XtActionProc) TimeControlProc },
968 { "FlipViewProc", FlipViewProc },
969 { "PonderNextMoveProc", PonderNextMoveProc },
970 #ifndef OPTIONSDIALOG
971 { "AlwaysQueenProc", AlwaysQueenProc },
972 { "AnimateDraggingProc", AnimateDraggingProc },
973 { "AnimateMovingProc", AnimateMovingProc },
974 { "AutoflagProc", AutoflagProc },
975 { "AutoflipProc", AutoflipProc },
976 { "BlindfoldProc", BlindfoldProc },
977 { "FlashMovesProc", FlashMovesProc },
979 { "HighlightDraggingProc", HighlightDraggingProc },
981 { "HighlightLastMoveProc", HighlightLastMoveProc },
982 // { "IcsAlarmProc", IcsAlarmProc },
983 { "MoveSoundProc", MoveSoundProc },
984 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
985 { "PopupExitMessageProc", PopupExitMessageProc },
986 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
987 // { "PremoveProc", PremoveProc },
988 { "ShowCoordsProc", ShowCoordsProc },
989 { "ShowThinkingProc", ShowThinkingProc },
990 { "HideThinkingProc", HideThinkingProc },
991 { "TestLegalityProc", TestLegalityProc },
993 { "SaveSettingsProc", SaveSettingsProc },
994 { "SaveOnExitProc", SaveOnExitProc },
995 { "InfoProc", InfoProc },
996 { "ManProc", ManProc },
997 { "HintProc", HintProc },
998 { "BookProc", BookProc },
999 { "AboutGameProc", AboutGameProc },
1000 { "AboutProc", AboutProc },
1001 { "DebugProc", DebugProc },
1002 { "NothingProc", NothingProc },
1003 { "CommentClick", (XtActionProc) CommentClick },
1004 { "CommentPopDown", (XtActionProc) CommentPopDown },
1005 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1006 { "TagsPopDown", (XtActionProc) TagsPopDown },
1007 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1008 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1009 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1010 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1011 { "GameListPopDown", (XtActionProc) GameListPopDown },
1012 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1013 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1014 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1015 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1016 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1017 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1018 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1019 { "GenericPopDown", (XtActionProc) GenericPopDown },
1020 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1023 char globalTranslations[] =
1024 ":<Key>F9: ResignProc() \n \
1025 :Ctrl<Key>n: ResetProc() \n \
1026 :Meta<Key>V: NewVariantProc() \n \
1027 :Ctrl<Key>o: LoadGameProc() \n \
1028 :Meta<Key>Next: LoadNextGameProc() \n \
1029 :Meta<Key>Prior: LoadPrevGameProc() \n \
1030 :Ctrl<Key>s: SaveGameProc() \n \
1031 :Ctrl<Key>c: CopyGameProc() \n \
1032 :Ctrl<Key>v: PasteGameProc() \n \
1033 :Ctrl<Key>O: LoadPositionProc() \n \
1034 :Shift<Key>Next: LoadNextPositionProc() \n \
1035 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1036 :Ctrl<Key>S: SavePositionProc() \n \
1037 :Ctrl<Key>C: CopyPositionProc() \n \
1038 :Ctrl<Key>V: PastePositionProc() \n \
1039 :Ctrl<Key>q: QuitProc() \n \
1040 :Ctrl<Key>w: MachineWhiteProc() \n \
1041 :Ctrl<Key>b: MachineBlackProc() \n \
1042 :Ctrl<Key>t: TwoMachinesProc() \n \
1043 :Ctrl<Key>a: AnalysisModeProc() \n \
1044 :Ctrl<Key>f: AnalyzeFileProc() \n \
1045 :Ctrl<Key>e: EditGameProc() \n \
1046 :Ctrl<Key>E: EditPositionProc() \n \
1047 :Meta<Key>O: EngineOutputProc() \n \
1048 :Meta<Key>E: EvalGraphProc() \n \
1049 :Meta<Key>G: ShowGameListProc() \n \
1050 :Meta<Key>H: ShowMoveListProc() \n \
1051 :<Key>Pause: PauseProc() \n \
1052 :<Key>F3: AcceptProc() \n \
1053 :<Key>F4: DeclineProc() \n \
1054 :<Key>F12: RematchProc() \n \
1055 :<Key>F5: CallFlagProc() \n \
1056 :<Key>F6: DrawProc() \n \
1057 :<Key>F7: AdjournProc() \n \
1058 :<Key>F8: AbortProc() \n \
1059 :<Key>F10: StopObservingProc() \n \
1060 :<Key>F11: StopExaminingProc() \n \
1061 :Meta Ctrl<Key>F12: DebugProc() \n \
1062 :Meta<Key>End: ToEndProc() \n \
1063 :Meta<Key>Right: ForwardProc() \n \
1064 :Meta<Key>Home: ToStartProc() \n \
1065 :Meta<Key>Left: BackwardProc() \n \
1066 :<Key>Home: RevertProc() \n \
1067 :<Key>End: TruncateGameProc() \n \
1068 :Ctrl<Key>m: MoveNowProc() \n \
1069 :Ctrl<Key>x: RetractMoveProc() \n \
1070 :Meta<Key>J: EngineMenuProc() \n \
1071 :Meta<Key>U: UciMenuProc() \n \
1072 :Meta<Key>T: TimeControlProc() \n \
1073 :Ctrl<Key>P: PonderNextMoveProc() \n "
1074 #ifndef OPTIONSDIALOG
1076 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1077 :Ctrl<Key>F: AutoflagProc() \n \
1078 :Ctrl<Key>A: AnimateMovingProc() \n \
1079 :Ctrl<Key>L: TestLegalityProc() \n \
1080 :Ctrl<Key>H: HideThinkingProc() \n "
1083 :<Key>-: Iconify() \n \
1084 :<Key>F1: ManProc() \n \
1085 :<Key>F2: FlipViewProc() \n \
1086 <KeyDown>.: BackwardProc() \n \
1087 <KeyUp>.: ForwardProc() \n \
1088 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1089 \"Send to chess program:\",,1) \n \
1090 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1091 \"Send to second chess program:\",,2) \n";
1093 char boardTranslations[] =
1094 "<Btn1Down>: HandleUserMove(0) \n \
1095 Shift<Btn1Up>: HandleUserMove(1) \n \
1096 <Btn1Up>: HandleUserMove(0) \n \
1097 <Btn1Motion>: AnimateUserMove() \n \
1098 <Btn3Motion>: HandlePV() \n \
1099 <Btn3Up>: PieceMenuPopup(menuB) \n \
1100 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1101 PieceMenuPopup(menuB) \n \
1102 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1103 PieceMenuPopup(menuW) \n \
1104 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1105 PieceMenuPopup(menuW) \n \
1106 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1107 PieceMenuPopup(menuB) \n";
1109 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1110 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1112 char ICSInputTranslations[] =
1113 "<Key>Up: UpKeyProc() \n "
1114 "<Key>Down: DownKeyProc() \n "
1115 "<Key>Return: EnterKeyProc() \n";
1117 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1118 // as the widget is destroyed before the up-click can call extend-end
1119 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1121 String xboardResources[] = {
1122 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1123 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1124 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1129 /* Max possible square size */
1130 #define MAXSQSIZE 256
1132 static int xpm_avail[MAXSQSIZE];
1134 #ifdef HAVE_DIR_STRUCT
1136 /* Extract piece size from filename */
1138 xpm_getsize(name, len, ext)
1149 if ((p=strchr(name, '.')) == NULL ||
1150 StrCaseCmp(p+1, ext) != 0)
1156 while (*p && isdigit(*p))
1163 /* Setup xpm_avail */
1165 xpm_getavail(dirname, ext)
1173 for (i=0; i<MAXSQSIZE; ++i)
1176 if (appData.debugMode)
1177 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1179 dir = opendir(dirname);
1182 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1183 programName, dirname);
1187 while ((ent=readdir(dir)) != NULL) {
1188 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1189 if (i > 0 && i < MAXSQSIZE)
1199 xpm_print_avail(fp, ext)
1205 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1206 for (i=1; i<MAXSQSIZE; ++i) {
1212 /* Return XPM piecesize closest to size */
1214 xpm_closest_to(dirname, size, ext)
1220 int sm_diff = MAXSQSIZE;
1224 xpm_getavail(dirname, ext);
1226 if (appData.debugMode)
1227 xpm_print_avail(stderr, ext);
1229 for (i=1; i<MAXSQSIZE; ++i) {
1232 diff = (diff<0) ? -diff : diff;
1233 if (diff < sm_diff) {
1241 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1247 #else /* !HAVE_DIR_STRUCT */
1248 /* If we are on a system without a DIR struct, we can't
1249 read the directory, so we can't collect a list of
1250 filenames, etc., so we can't do any size-fitting. */
1252 xpm_closest_to(dirname, size, ext)
1257 fprintf(stderr, _("\
1258 Warning: No DIR structure found on this system --\n\
1259 Unable to autosize for XPM/XIM pieces.\n\
1260 Please report this error to frankm@hiwaay.net.\n\
1261 Include system type & operating system in message.\n"));
1264 #endif /* HAVE_DIR_STRUCT */
1266 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1267 "magenta", "cyan", "white" };
1271 TextColors textColors[(int)NColorClasses];
1273 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1275 parse_color(str, which)
1279 char *p, buf[100], *d;
1282 if (strlen(str) > 99) /* watch bounds on buf */
1287 for (i=0; i<which; ++i) {
1294 /* Could be looking at something like:
1296 .. in which case we want to stop on a comma also */
1297 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1301 return -1; /* Use default for empty field */
1304 if (which == 2 || isdigit(*p))
1307 while (*p && isalpha(*p))
1312 for (i=0; i<8; ++i) {
1313 if (!StrCaseCmp(buf, cnames[i]))
1314 return which? (i+40) : (i+30);
1316 if (!StrCaseCmp(buf, "default")) return -1;
1318 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1323 parse_cpair(cc, str)
1327 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1328 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1333 /* bg and attr are optional */
1334 textColors[(int)cc].bg = parse_color(str, 1);
1335 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1336 textColors[(int)cc].attr = 0;
1342 /* Arrange to catch delete-window events */
1343 Atom wm_delete_window;
1345 CatchDeleteWindow(Widget w, String procname)
1348 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1349 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1350 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1357 XtSetArg(args[0], XtNiconic, False);
1358 XtSetValues(shellWidget, args, 1);
1360 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1363 //---------------------------------------------------------------------------------------------------------
1364 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1367 #define CW_USEDEFAULT (1<<31)
1368 #define ICS_TEXT_MENU_SIZE 90
1369 #define DEBUG_FILE "xboard.debug"
1370 #define SetCurrentDirectory chdir
1371 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1375 // these two must some day move to frontend.h, when they are implemented
1376 Boolean GameListIsUp();
1378 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1381 // front-end part of option handling
1383 // [HGM] This platform-dependent table provides the location for storing the color info
1384 extern char *crWhite, * crBlack;
1388 &appData.whitePieceColor,
1389 &appData.blackPieceColor,
1390 &appData.lightSquareColor,
1391 &appData.darkSquareColor,
1392 &appData.highlightSquareColor,
1393 &appData.premoveHighlightColor,
1394 &appData.lowTimeWarningColor,
1405 // [HGM] font: keep a font for each square size, even non-stndard ones
1406 #define NUM_SIZES 18
1407 #define MAX_SIZE 130
1408 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1409 char *fontTable[NUM_FONTS][MAX_SIZE];
1412 ParseFont(char *name, int number)
1413 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1415 if(sscanf(name, "size%d:", &size)) {
1416 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1417 // defer processing it until we know if it matches our board size
1418 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1419 fontTable[number][size] = strdup(strchr(name, ':')+1);
1420 fontValid[number][size] = True;
1425 case 0: // CLOCK_FONT
1426 appData.clockFont = strdup(name);
1428 case 1: // MESSAGE_FONT
1429 appData.font = strdup(name);
1431 case 2: // COORD_FONT
1432 appData.coordFont = strdup(name);
1437 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1442 { // only 2 fonts currently
1443 appData.clockFont = CLOCK_FONT_NAME;
1444 appData.coordFont = COORD_FONT_NAME;
1445 appData.font = DEFAULT_FONT_NAME;
1450 { // no-op, until we identify the code for this already in XBoard and move it here
1454 ParseColor(int n, char *name)
1455 { // in XBoard, just copy the color-name string
1456 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1460 ParseTextAttribs(ColorClass cc, char *s)
1462 (&appData.colorShout)[cc] = strdup(s);
1466 ParseBoardSize(void *addr, char *name)
1468 appData.boardSize = strdup(name);
1473 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1477 SetCommPortDefaults()
1478 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1481 // [HGM] args: these three cases taken out to stay in front-end
1483 SaveFontArg(FILE *f, ArgDescriptor *ad)
1486 int i, n = (int)(intptr_t)ad->argLoc;
1488 case 0: // CLOCK_FONT
1489 name = appData.clockFont;
1491 case 1: // MESSAGE_FONT
1492 name = appData.font;
1494 case 2: // COORD_FONT
1495 name = appData.coordFont;
1500 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1501 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1502 fontTable[n][squareSize] = strdup(name);
1503 fontValid[n][squareSize] = True;
1506 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1507 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1512 { // nothing to do, as the sounds are at all times represented by their text-string names already
1516 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1517 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1518 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1522 SaveColor(FILE *f, ArgDescriptor *ad)
1523 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1524 if(colorVariable[(int)(intptr_t)ad->argLoc])
1525 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1529 SaveBoardSize(FILE *f, char *name, void *addr)
1530 { // wrapper to shield back-end from BoardSize & sizeInfo
1531 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1535 ParseCommPortSettings(char *s)
1536 { // no such option in XBoard (yet)
1539 extern Widget engineOutputShell;
1540 extern Widget tagsShell, editTagsShell;
1542 GetActualPlacement(Widget wg, WindowPlacement *wp)
1552 XtSetArg(args[i], XtNx, &x); i++;
1553 XtSetArg(args[i], XtNy, &y); i++;
1554 XtSetArg(args[i], XtNwidth, &w); i++;
1555 XtSetArg(args[i], XtNheight, &h); i++;
1556 XtGetValues(wg, args, i);
1565 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1566 // In XBoard this will have to wait until awareness of window parameters is implemented
1567 GetActualPlacement(shellWidget, &wpMain);
1568 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1569 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1570 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1571 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1572 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1573 else GetActualPlacement(editShell, &wpComment);
1574 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1575 else GetActualPlacement(editTagsShell, &wpTags);
1579 PrintCommPortSettings(FILE *f, char *name)
1580 { // This option does not exist in XBoard
1584 MySearchPath(char *installDir, char *name, char *fullname)
1585 { // just append installDir and name. Perhaps ExpandPath should be used here?
1586 name = ExpandPathName(name);
1587 if(name && name[0] == '/')
1588 safeStrCpy(fullname, name, MSG_SIZ );
1590 sprintf(fullname, "%s%c%s", installDir, '/', name);
1596 MyGetFullPathName(char *name, char *fullname)
1597 { // should use ExpandPath?
1598 name = ExpandPathName(name);
1599 safeStrCpy(fullname, name, MSG_SIZ );
1604 EnsureOnScreen(int *x, int *y, int minX, int minY)
1611 { // [HGM] args: allows testing if main window is realized from back-end
1612 return xBoardWindow != 0;
1616 PopUpStartupDialog()
1617 { // start menu not implemented in XBoard
1621 ConvertToLine(int argc, char **argv)
1623 static char line[128*1024], buf[1024];
1627 for(i=1; i<argc; i++)
1629 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1630 && argv[i][0] != '{' )
1631 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1633 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1634 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1637 line[strlen(line)-1] = NULLCHAR;
1641 //--------------------------------------------------------------------------------------------
1643 extern Boolean twoBoards, partnerUp;
1646 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1648 #define BoardSize int
1649 void InitDrawingSizes(BoardSize boardSize, int flags)
1650 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1651 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1653 XtGeometryResult gres;
1656 if(!formWidget) return;
1659 * Enable shell resizing.
1661 shellArgs[0].value = (XtArgVal) &w;
1662 shellArgs[1].value = (XtArgVal) &h;
1663 XtGetValues(shellWidget, shellArgs, 2);
1665 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1666 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1667 XtSetValues(shellWidget, &shellArgs[2], 4);
1669 XtSetArg(args[0], XtNdefaultDistance, &sep);
1670 XtGetValues(formWidget, args, 1);
1672 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1673 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1674 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1676 hOffset = boardWidth + 10;
1677 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1678 secondSegments[i] = gridSegments[i];
1679 secondSegments[i].x1 += hOffset;
1680 secondSegments[i].x2 += hOffset;
1683 XtSetArg(args[0], XtNwidth, boardWidth);
1684 XtSetArg(args[1], XtNheight, boardHeight);
1685 XtSetValues(boardWidget, args, 2);
1687 timerWidth = (boardWidth - sep) / 2;
1688 XtSetArg(args[0], XtNwidth, timerWidth);
1689 XtSetValues(whiteTimerWidget, args, 1);
1690 XtSetValues(blackTimerWidget, args, 1);
1692 XawFormDoLayout(formWidget, False);
1694 if (appData.titleInWindow) {
1696 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1697 XtSetArg(args[i], XtNheight, &h); i++;
1698 XtGetValues(titleWidget, args, i);
1700 w = boardWidth - 2*bor;
1702 XtSetArg(args[0], XtNwidth, &w);
1703 XtGetValues(menuBarWidget, args, 1);
1704 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1707 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1708 if (gres != XtGeometryYes && appData.debugMode) {
1710 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1711 programName, gres, w, h, wr, hr);
1715 XawFormDoLayout(formWidget, True);
1718 * Inhibit shell resizing.
1720 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1721 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1722 shellArgs[4].value = shellArgs[2].value = w;
1723 shellArgs[5].value = shellArgs[3].value = h;
1724 XtSetValues(shellWidget, &shellArgs[0], 6);
1726 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1729 for(i=0; i<4; i++) {
1731 for(p=0; p<=(int)WhiteKing; p++)
1732 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1733 if(gameInfo.variant == VariantShogi) {
1734 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1735 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1736 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1737 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1738 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1741 if(gameInfo.variant == VariantGothic) {
1742 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1745 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1746 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1747 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1750 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1751 for(p=0; p<=(int)WhiteKing; p++)
1752 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1753 if(gameInfo.variant == VariantShogi) {
1754 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1755 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1756 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1757 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1758 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1761 if(gameInfo.variant == VariantGothic) {
1762 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1765 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1766 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1767 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1772 for(i=0; i<2; i++) {
1774 for(p=0; p<=(int)WhiteKing; p++)
1775 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1776 if(gameInfo.variant == VariantShogi) {
1777 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1778 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1779 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1780 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1781 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1784 if(gameInfo.variant == VariantGothic) {
1785 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1788 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1789 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1790 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1800 void ParseIcsTextColors()
1801 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1802 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1803 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1804 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1805 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1806 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1807 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1808 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1809 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1810 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1811 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1813 if (appData.colorize) {
1815 _("%s: can't parse color names; disabling colorization\n"),
1818 appData.colorize = FALSE;
1823 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1824 XrmValue vFrom, vTo;
1825 int forceMono = False;
1827 if (!appData.monoMode) {
1828 vFrom.addr = (caddr_t) appData.lightSquareColor;
1829 vFrom.size = strlen(appData.lightSquareColor);
1830 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1831 if (vTo.addr == NULL) {
1832 appData.monoMode = True;
1835 lightSquareColor = *(Pixel *) vTo.addr;
1838 if (!appData.monoMode) {
1839 vFrom.addr = (caddr_t) appData.darkSquareColor;
1840 vFrom.size = strlen(appData.darkSquareColor);
1841 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1842 if (vTo.addr == NULL) {
1843 appData.monoMode = True;
1846 darkSquareColor = *(Pixel *) vTo.addr;
1849 if (!appData.monoMode) {
1850 vFrom.addr = (caddr_t) appData.whitePieceColor;
1851 vFrom.size = strlen(appData.whitePieceColor);
1852 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1853 if (vTo.addr == NULL) {
1854 appData.monoMode = True;
1857 whitePieceColor = *(Pixel *) vTo.addr;
1860 if (!appData.monoMode) {
1861 vFrom.addr = (caddr_t) appData.blackPieceColor;
1862 vFrom.size = strlen(appData.blackPieceColor);
1863 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1864 if (vTo.addr == NULL) {
1865 appData.monoMode = True;
1868 blackPieceColor = *(Pixel *) vTo.addr;
1872 if (!appData.monoMode) {
1873 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1874 vFrom.size = strlen(appData.highlightSquareColor);
1875 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1876 if (vTo.addr == NULL) {
1877 appData.monoMode = True;
1880 highlightSquareColor = *(Pixel *) vTo.addr;
1884 if (!appData.monoMode) {
1885 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1886 vFrom.size = strlen(appData.premoveHighlightColor);
1887 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1888 if (vTo.addr == NULL) {
1889 appData.monoMode = True;
1892 premoveHighlightColor = *(Pixel *) vTo.addr;
1903 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1904 XSetWindowAttributes window_attributes;
1906 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1907 XrmValue vFrom, vTo;
1908 XtGeometryResult gres;
1911 int forceMono = False;
1913 srandom(time(0)); // [HGM] book: make random truly random
1915 setbuf(stdout, NULL);
1916 setbuf(stderr, NULL);
1919 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1920 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1924 programName = strrchr(argv[0], '/');
1925 if (programName == NULL)
1926 programName = argv[0];
1931 XtSetLanguageProc(NULL, NULL, NULL);
1932 bindtextdomain(PACKAGE, LOCALEDIR);
1933 textdomain(PACKAGE);
1937 XtAppInitialize(&appContext, "XBoard", shellOptions,
1938 XtNumber(shellOptions),
1939 &argc, argv, xboardResources, NULL, 0);
1940 appData.boardSize = "";
1941 InitAppData(ConvertToLine(argc, argv));
1943 if (p == NULL) p = "/tmp";
1944 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1945 gameCopyFilename = (char*) malloc(i);
1946 gamePasteFilename = (char*) malloc(i);
1947 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1948 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1950 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1951 clientResources, XtNumber(clientResources),
1954 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1955 static char buf[MSG_SIZ];
1956 EscapeExpand(buf, appData.initString);
1957 appData.initString = strdup(buf);
1958 EscapeExpand(buf, appData.secondInitString);
1959 appData.secondInitString = strdup(buf);
1960 EscapeExpand(buf, appData.firstComputerString);
1961 appData.firstComputerString = strdup(buf);
1962 EscapeExpand(buf, appData.secondComputerString);
1963 appData.secondComputerString = strdup(buf);
1966 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1969 if (chdir(chessDir) != 0) {
1970 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1976 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1977 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1978 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1979 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1982 setbuf(debugFP, NULL);
1985 /* [HGM,HR] make sure board size is acceptable */
1986 if(appData.NrFiles > BOARD_FILES ||
1987 appData.NrRanks > BOARD_RANKS )
1988 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1991 /* This feature does not work; animation needs a rewrite */
1992 appData.highlightDragging = FALSE;
1996 xDisplay = XtDisplay(shellWidget);
1997 xScreen = DefaultScreen(xDisplay);
1998 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2000 gameInfo.variant = StringToVariant(appData.variant);
2001 InitPosition(FALSE);
2004 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2006 if (isdigit(appData.boardSize[0])) {
2007 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2008 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2009 &fontPxlSize, &smallLayout, &tinyLayout);
2011 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2012 programName, appData.boardSize);
2016 /* Find some defaults; use the nearest known size */
2017 SizeDefaults *szd, *nearest;
2018 int distance = 99999;
2019 nearest = szd = sizeDefaults;
2020 while (szd->name != NULL) {
2021 if (abs(szd->squareSize - squareSize) < distance) {
2023 distance = abs(szd->squareSize - squareSize);
2024 if (distance == 0) break;
2028 if (i < 2) lineGap = nearest->lineGap;
2029 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2030 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2031 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2032 if (i < 6) smallLayout = nearest->smallLayout;
2033 if (i < 7) tinyLayout = nearest->tinyLayout;
2036 SizeDefaults *szd = sizeDefaults;
2037 if (*appData.boardSize == NULLCHAR) {
2038 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2039 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2042 if (szd->name == NULL) szd--;
2043 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2045 while (szd->name != NULL &&
2046 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2047 if (szd->name == NULL) {
2048 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2049 programName, appData.boardSize);
2053 squareSize = szd->squareSize;
2054 lineGap = szd->lineGap;
2055 clockFontPxlSize = szd->clockFontPxlSize;
2056 coordFontPxlSize = szd->coordFontPxlSize;
2057 fontPxlSize = szd->fontPxlSize;
2058 smallLayout = szd->smallLayout;
2059 tinyLayout = szd->tinyLayout;
2060 // [HGM] font: use defaults from settings file if available and not overruled
2062 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2063 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2064 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2065 appData.font = fontTable[MESSAGE_FONT][squareSize];
2066 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2067 appData.coordFont = fontTable[COORD_FONT][squareSize];
2069 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2070 if (strlen(appData.pixmapDirectory) > 0) {
2071 p = ExpandPathName(appData.pixmapDirectory);
2073 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2074 appData.pixmapDirectory);
2077 if (appData.debugMode) {
2078 fprintf(stderr, _("\
2079 XBoard square size (hint): %d\n\
2080 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2082 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2083 if (appData.debugMode) {
2084 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2087 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2089 /* [HR] height treated separately (hacked) */
2090 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2091 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2092 if (appData.showJail == 1) {
2093 /* Jail on top and bottom */
2094 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2095 XtSetArg(boardArgs[2], XtNheight,
2096 boardHeight + 2*(lineGap + squareSize));
2097 } else if (appData.showJail == 2) {
2099 XtSetArg(boardArgs[1], XtNwidth,
2100 boardWidth + 2*(lineGap + squareSize));
2101 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2104 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2105 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2109 * Determine what fonts to use.
2111 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2112 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2113 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2114 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2115 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2116 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2117 appData.font = FindFont(appData.font, fontPxlSize);
2118 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2119 countFontStruct = XQueryFont(xDisplay, countFontID);
2120 // appData.font = FindFont(appData.font, fontPxlSize);
2122 xdb = XtDatabase(xDisplay);
2123 XrmPutStringResource(&xdb, "*font", appData.font);
2126 * Detect if there are not enough colors available and adapt.
2128 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2129 appData.monoMode = True;
2132 forceMono = MakeColors();
2135 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2138 if (appData.bitmapDirectory == NULL ||
2139 appData.bitmapDirectory[0] == NULLCHAR)
2140 appData.bitmapDirectory = DEF_BITMAP_DIR;
2143 if (appData.lowTimeWarning && !appData.monoMode) {
2144 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2145 vFrom.size = strlen(appData.lowTimeWarningColor);
2146 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2147 if (vTo.addr == NULL)
2148 appData.monoMode = True;
2150 lowTimeWarningColor = *(Pixel *) vTo.addr;
2153 if (appData.monoMode && appData.debugMode) {
2154 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2155 (unsigned long) XWhitePixel(xDisplay, xScreen),
2156 (unsigned long) XBlackPixel(xDisplay, xScreen));
2159 ParseIcsTextColors();
2160 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2161 textColors[ColorNone].attr = 0;
2163 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2169 layoutName = "tinyLayout";
2170 } else if (smallLayout) {
2171 layoutName = "smallLayout";
2173 layoutName = "normalLayout";
2175 /* Outer layoutWidget is there only to provide a name for use in
2176 resources that depend on the layout style */
2178 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2179 layoutArgs, XtNumber(layoutArgs));
2181 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2182 formArgs, XtNumber(formArgs));
2183 XtSetArg(args[0], XtNdefaultDistance, &sep);
2184 XtGetValues(formWidget, args, 1);
2187 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2188 XtSetArg(args[0], XtNtop, XtChainTop);
2189 XtSetArg(args[1], XtNbottom, XtChainTop);
2190 XtSetArg(args[2], XtNright, XtChainLeft);
2191 XtSetValues(menuBarWidget, args, 3);
2193 widgetList[j++] = whiteTimerWidget =
2194 XtCreateWidget("whiteTime", labelWidgetClass,
2195 formWidget, timerArgs, XtNumber(timerArgs));
2196 XtSetArg(args[0], XtNfont, clockFontStruct);
2197 XtSetArg(args[1], XtNtop, XtChainTop);
2198 XtSetArg(args[2], XtNbottom, XtChainTop);
2199 XtSetValues(whiteTimerWidget, args, 3);
2201 widgetList[j++] = blackTimerWidget =
2202 XtCreateWidget("blackTime", labelWidgetClass,
2203 formWidget, timerArgs, XtNumber(timerArgs));
2204 XtSetArg(args[0], XtNfont, clockFontStruct);
2205 XtSetArg(args[1], XtNtop, XtChainTop);
2206 XtSetArg(args[2], XtNbottom, XtChainTop);
2207 XtSetValues(blackTimerWidget, args, 3);
2209 if (appData.titleInWindow) {
2210 widgetList[j++] = titleWidget =
2211 XtCreateWidget("title", labelWidgetClass, formWidget,
2212 titleArgs, XtNumber(titleArgs));
2213 XtSetArg(args[0], XtNtop, XtChainTop);
2214 XtSetArg(args[1], XtNbottom, XtChainTop);
2215 XtSetValues(titleWidget, args, 2);
2218 if (appData.showButtonBar) {
2219 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2220 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2221 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2222 XtSetArg(args[2], XtNtop, XtChainTop);
2223 XtSetArg(args[3], XtNbottom, XtChainTop);
2224 XtSetValues(buttonBarWidget, args, 4);
2227 widgetList[j++] = messageWidget =
2228 XtCreateWidget("message", labelWidgetClass, formWidget,
2229 messageArgs, XtNumber(messageArgs));
2230 XtSetArg(args[0], XtNtop, XtChainTop);
2231 XtSetArg(args[1], XtNbottom, XtChainTop);
2232 XtSetValues(messageWidget, args, 2);
2234 widgetList[j++] = boardWidget =
2235 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2236 XtNumber(boardArgs));
2238 XtManageChildren(widgetList, j);
2240 timerWidth = (boardWidth - sep) / 2;
2241 XtSetArg(args[0], XtNwidth, timerWidth);
2242 XtSetValues(whiteTimerWidget, args, 1);
2243 XtSetValues(blackTimerWidget, args, 1);
2245 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2246 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2247 XtGetValues(whiteTimerWidget, args, 2);
2249 if (appData.showButtonBar) {
2250 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2251 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2252 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2256 * formWidget uses these constraints but they are stored
2260 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2261 XtSetValues(menuBarWidget, args, i);
2262 if (appData.titleInWindow) {
2265 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2266 XtSetValues(whiteTimerWidget, args, i);
2268 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2269 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2270 XtSetValues(blackTimerWidget, args, i);
2272 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2273 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2274 XtSetValues(titleWidget, args, i);
2276 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2277 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2278 XtSetValues(messageWidget, args, i);
2279 if (appData.showButtonBar) {
2281 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2282 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2283 XtSetValues(buttonBarWidget, args, i);
2287 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2288 XtSetValues(whiteTimerWidget, args, i);
2290 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2291 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2292 XtSetValues(blackTimerWidget, args, i);
2294 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2295 XtSetValues(titleWidget, args, i);
2297 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2298 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2299 XtSetValues(messageWidget, args, i);
2300 if (appData.showButtonBar) {
2302 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2303 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2304 XtSetValues(buttonBarWidget, args, i);
2309 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2310 XtSetValues(whiteTimerWidget, args, i);
2312 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2313 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2314 XtSetValues(blackTimerWidget, args, i);
2316 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2317 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2318 XtSetValues(messageWidget, args, i);
2319 if (appData.showButtonBar) {
2321 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2322 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2323 XtSetValues(buttonBarWidget, args, i);
2327 XtSetArg(args[0], XtNfromVert, messageWidget);
2328 XtSetArg(args[1], XtNtop, XtChainTop);
2329 XtSetArg(args[2], XtNbottom, XtChainBottom);
2330 XtSetArg(args[3], XtNleft, XtChainLeft);
2331 XtSetArg(args[4], XtNright, XtChainRight);
2332 XtSetValues(boardWidget, args, 5);
2334 XtRealizeWidget(shellWidget);
2337 XtSetArg(args[0], XtNx, wpMain.x);
2338 XtSetArg(args[1], XtNy, wpMain.y);
2339 XtSetValues(shellWidget, args, 2);
2343 * Correct the width of the message and title widgets.
2344 * It is not known why some systems need the extra fudge term.
2345 * The value "2" is probably larger than needed.
2347 XawFormDoLayout(formWidget, False);
2349 #define WIDTH_FUDGE 2
2351 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2352 XtSetArg(args[i], XtNheight, &h); i++;
2353 XtGetValues(messageWidget, args, i);
2354 if (appData.showButtonBar) {
2356 XtSetArg(args[i], XtNwidth, &w); i++;
2357 XtGetValues(buttonBarWidget, args, i);
2358 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2360 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2363 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2364 if (gres != XtGeometryYes && appData.debugMode) {
2365 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2366 programName, gres, w, h, wr, hr);
2369 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2370 /* The size used for the child widget in layout lags one resize behind
2371 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2373 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2374 if (gres != XtGeometryYes && appData.debugMode) {
2375 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2376 programName, gres, w, h, wr, hr);
2379 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2380 XtSetArg(args[1], XtNright, XtChainRight);
2381 XtSetValues(messageWidget, args, 2);
2383 if (appData.titleInWindow) {
2385 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2386 XtSetArg(args[i], XtNheight, &h); i++;
2387 XtGetValues(titleWidget, args, i);
2389 w = boardWidth - 2*bor;
2391 XtSetArg(args[0], XtNwidth, &w);
2392 XtGetValues(menuBarWidget, args, 1);
2393 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2396 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2397 if (gres != XtGeometryYes && appData.debugMode) {
2399 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2400 programName, gres, w, h, wr, hr);
2403 XawFormDoLayout(formWidget, True);
2405 xBoardWindow = XtWindow(boardWidget);
2407 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2408 // not need to go into InitDrawingSizes().
2412 * Create X checkmark bitmap and initialize option menu checks.
2414 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2415 checkmark_bits, checkmark_width, checkmark_height);
2416 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2417 #ifndef OPTIONSDIALOG
2418 if (appData.alwaysPromoteToQueen) {
2419 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2422 if (appData.animateDragging) {
2423 XtSetValues(XtNameToWidget(menuBarWidget,
2424 "menuOptions.Animate Dragging"),
2427 if (appData.animate) {
2428 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2431 if (appData.autoCallFlag) {
2432 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2435 if (appData.autoFlipView) {
2436 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2439 if (appData.blindfold) {
2440 XtSetValues(XtNameToWidget(menuBarWidget,
2441 "menuOptions.Blindfold"), args, 1);
2443 if (appData.flashCount > 0) {
2444 XtSetValues(XtNameToWidget(menuBarWidget,
2445 "menuOptions.Flash Moves"),
2449 if (appData.highlightDragging) {
2450 XtSetValues(XtNameToWidget(menuBarWidget,
2451 "menuOptions.Highlight Dragging"),
2455 if (appData.highlightLastMove) {
2456 XtSetValues(XtNameToWidget(menuBarWidget,
2457 "menuOptions.Highlight Last Move"),
2460 if (appData.highlightMoveWithArrow) {
2461 XtSetValues(XtNameToWidget(menuBarWidget,
2462 "menuOptions.Arrow"),
2465 // if (appData.icsAlarm) {
2466 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2469 if (appData.ringBellAfterMoves) {
2470 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2473 if (appData.oneClick) {
2474 XtSetValues(XtNameToWidget(menuBarWidget,
2475 "menuOptions.OneClick"), args, 1);
2477 if (appData.periodicUpdates) {
2478 XtSetValues(XtNameToWidget(menuBarWidget,
2479 "menuOptions.Periodic Updates"), args, 1);
2481 if (appData.ponderNextMove) {
2482 XtSetValues(XtNameToWidget(menuBarWidget,
2483 "menuOptions.Ponder Next Move"), args, 1);
2485 if (appData.popupExitMessage) {
2486 XtSetValues(XtNameToWidget(menuBarWidget,
2487 "menuOptions.Popup Exit Message"), args, 1);
2489 if (appData.popupMoveErrors) {
2490 XtSetValues(XtNameToWidget(menuBarWidget,
2491 "menuOptions.Popup Move Errors"), args, 1);
2493 // if (appData.premove) {
2494 // XtSetValues(XtNameToWidget(menuBarWidget,
2495 // "menuOptions.Premove"), args, 1);
2497 if (appData.showCoords) {
2498 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2501 if (appData.hideThinkingFromHuman) {
2502 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2505 if (appData.testLegality) {
2506 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2510 if (saveSettingsOnExit) {
2511 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2518 ReadBitmap(&wIconPixmap, "icon_white.bm",
2519 icon_white_bits, icon_white_width, icon_white_height);
2520 ReadBitmap(&bIconPixmap, "icon_black.bm",
2521 icon_black_bits, icon_black_width, icon_black_height);
2522 iconPixmap = wIconPixmap;
2524 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2525 XtSetValues(shellWidget, args, i);
2528 * Create a cursor for the board widget.
2530 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2531 XChangeWindowAttributes(xDisplay, xBoardWindow,
2532 CWCursor, &window_attributes);
2535 * Inhibit shell resizing.
2537 shellArgs[0].value = (XtArgVal) &w;
2538 shellArgs[1].value = (XtArgVal) &h;
2539 XtGetValues(shellWidget, shellArgs, 2);
2540 shellArgs[4].value = shellArgs[2].value = w;
2541 shellArgs[5].value = shellArgs[3].value = h;
2542 XtSetValues(shellWidget, &shellArgs[2], 4);
2543 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2544 marginH = h - boardHeight;
2546 CatchDeleteWindow(shellWidget, "QuitProc");
2551 if (appData.bitmapDirectory[0] != NULLCHAR) {
2555 CreateXPMBoard(appData.liteBackTextureFile, 1);
2556 CreateXPMBoard(appData.darkBackTextureFile, 0);
2560 /* Create regular pieces */
2561 if (!useImages) CreatePieces();
2566 if (appData.animate || appData.animateDragging)
2569 XtAugmentTranslations(formWidget,
2570 XtParseTranslationTable(globalTranslations));
2571 XtAugmentTranslations(boardWidget,
2572 XtParseTranslationTable(boardTranslations));
2573 XtAugmentTranslations(whiteTimerWidget,
2574 XtParseTranslationTable(whiteTranslations));
2575 XtAugmentTranslations(blackTimerWidget,
2576 XtParseTranslationTable(blackTranslations));
2578 /* Why is the following needed on some versions of X instead
2579 * of a translation? */
2580 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2581 (XtEventHandler) EventProc, NULL);
2584 /* [AS] Restore layout */
2585 if( wpMoveHistory.visible ) {
2589 if( wpEvalGraph.visible )
2594 if( wpEngineOutput.visible ) {
2595 EngineOutputPopUp();
2600 if (errorExitStatus == -1) {
2601 if (appData.icsActive) {
2602 /* We now wait until we see "login:" from the ICS before
2603 sending the logon script (problems with timestamp otherwise) */
2604 /*ICSInitScript();*/
2605 if (appData.icsInputBox) ICSInputBoxPopUp();
2609 signal(SIGWINCH, TermSizeSigHandler);
2611 signal(SIGINT, IntSigHandler);
2612 signal(SIGTERM, IntSigHandler);
2613 if (*appData.cmailGameName != NULLCHAR) {
2614 signal(SIGUSR1, CmailSigHandler);
2617 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2619 XtSetKeyboardFocus(shellWidget, formWidget);
2621 XtAppMainLoop(appContext);
2622 if (appData.debugMode) fclose(debugFP); // [DM] debug
2629 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2630 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2632 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2633 unlink(gameCopyFilename);
2634 unlink(gamePasteFilename);
2637 RETSIGTYPE TermSizeSigHandler(int sig)
2650 CmailSigHandler(sig)
2656 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2658 /* Activate call-back function CmailSigHandlerCallBack() */
2659 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2661 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2665 CmailSigHandlerCallBack(isr, closure, message, count, error)
2673 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2675 /**** end signal code ****/
2681 /* try to open the icsLogon script, either in the location given
2682 * or in the users HOME directory
2689 f = fopen(appData.icsLogon, "r");
2692 homedir = getenv("HOME");
2693 if (homedir != NULL)
2695 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2696 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2697 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2698 f = fopen(buf, "r");
2703 ProcessICSInitScript(f);
2705 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2714 EditCommentPopDown();
2729 if (!menuBarWidget) return;
2730 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2732 DisplayError("menuEdit.Revert", 0);
2734 XtSetSensitive(w, !grey);
2736 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2738 DisplayError("menuEdit.Annotate", 0);
2740 XtSetSensitive(w, !grey);
2745 SetMenuEnables(enab)
2749 if (!menuBarWidget) return;
2750 while (enab->name != NULL) {
2751 w = XtNameToWidget(menuBarWidget, enab->name);
2753 DisplayError(enab->name, 0);
2755 XtSetSensitive(w, enab->value);
2761 Enables icsEnables[] = {
2762 { "menuFile.Mail Move", False },
2763 { "menuFile.Reload CMail Message", False },
2764 { "menuMode.Machine Black", False },
2765 { "menuMode.Machine White", False },
2766 { "menuMode.Analysis Mode", False },
2767 { "menuMode.Analyze File", False },
2768 { "menuMode.Two Machines", False },
2769 { "menuMode.Machine Match", False },
2771 { "menuEngine.Hint", False },
2772 { "menuEngine.Book", False },
2773 { "menuEngine.Move Now", False },
2774 #ifndef OPTIONSDIALOG
2775 { "menuOptions.Periodic Updates", False },
2776 { "menuOptions.Hide Thinking", False },
2777 { "menuOptions.Ponder Next Move", False },
2779 { "menuEngine.Engine #1 Settings", False },
2781 { "menuEngine.Engine #2 Settings", False },
2782 { "menuEdit.Annotate", False },
2786 Enables ncpEnables[] = {
2787 { "menuFile.Mail Move", False },
2788 { "menuFile.Reload CMail Message", False },
2789 { "menuMode.Machine White", False },
2790 { "menuMode.Machine Black", False },
2791 { "menuMode.Analysis Mode", False },
2792 { "menuMode.Analyze File", False },
2793 { "menuMode.Two Machines", False },
2794 { "menuMode.Machine Match", False },
2795 { "menuMode.ICS Client", False },
2796 { "menuView.ICS Input Box", False },
2797 { "Action", False },
2798 { "menuEdit.Revert", False },
2799 { "menuEdit.Annotate", False },
2800 { "menuEngine.Engine #1 Settings", False },
2801 { "menuEngine.Engine #2 Settings", False },
2802 { "menuEngine.Move Now", False },
2803 { "menuEngine.Retract Move", False },
2804 #ifndef OPTIONSDIALOG
2805 { "menuOptions.Auto Flag", False },
2806 { "menuOptions.Auto Flip View", False },
2807 { "menuOptions.ICS", False },
2808 // { "menuOptions.ICS Alarm", False },
2809 { "menuOptions.Move Sound", False },
2810 { "menuOptions.Hide Thinking", False },
2811 { "menuOptions.Periodic Updates", False },
2812 { "menuOptions.Ponder Next Move", False },
2814 { "menuEngine.Hint", False },
2815 { "menuEngine.Book", False },
2819 Enables gnuEnables[] = {
2820 { "menuMode.ICS Client", False },
2821 { "menuView.ICS Input Box", False },
2822 { "menuAction.Accept", False },
2823 { "menuAction.Decline", False },
2824 { "menuAction.Rematch", False },
2825 { "menuAction.Adjourn", False },
2826 { "menuAction.Stop Examining", False },
2827 { "menuAction.Stop Observing", False },
2828 { "menuAction.Upload to Examine", False },
2829 { "menuEdit.Revert", False },
2830 { "menuEdit.Annotate", False },
2831 { "menuOptions.ICS", False },
2833 /* The next two options rely on SetCmailMode being called *after* */
2834 /* SetGNUMode so that when GNU is being used to give hints these */
2835 /* menu options are still available */
2837 { "menuFile.Mail Move", False },
2838 { "menuFile.Reload CMail Message", False },
2842 Enables cmailEnables[] = {
2844 { "menuAction.Call Flag", False },
2845 { "menuAction.Draw", True },
2846 { "menuAction.Adjourn", False },
2847 { "menuAction.Abort", False },
2848 { "menuAction.Stop Observing", False },
2849 { "menuAction.Stop Examining", False },
2850 { "menuFile.Mail Move", True },
2851 { "menuFile.Reload CMail Message", True },
2855 Enables trainingOnEnables[] = {
2856 { "menuMode.Edit Comment", False },
2857 { "menuMode.Pause", False },
2858 { "menuEdit.Forward", False },
2859 { "menuEdit.Backward", False },
2860 { "menuEdit.Forward to End", False },
2861 { "menuEdit.Back to Start", False },
2862 { "menuEngine.Move Now", False },
2863 { "menuEdit.Truncate Game", False },
2867 Enables trainingOffEnables[] = {
2868 { "menuMode.Edit Comment", True },
2869 { "menuMode.Pause", True },
2870 { "menuEdit.Forward", True },
2871 { "menuEdit.Backward", True },
2872 { "menuEdit.Forward to End", True },
2873 { "menuEdit.Back to Start", True },
2874 { "menuEngine.Move Now", True },
2875 { "menuEdit.Truncate Game", True },
2879 Enables machineThinkingEnables[] = {
2880 { "menuFile.Load Game", False },
2881 // { "menuFile.Load Next Game", False },
2882 // { "menuFile.Load Previous Game", False },
2883 // { "menuFile.Reload Same Game", False },
2884 { "menuEdit.Paste Game", False },
2885 { "menuFile.Load Position", False },
2886 // { "menuFile.Load Next Position", False },
2887 // { "menuFile.Load Previous Position", False },
2888 // { "menuFile.Reload Same Position", False },
2889 { "menuEdit.Paste Position", False },
2890 { "menuMode.Machine White", False },
2891 { "menuMode.Machine Black", False },
2892 { "menuMode.Two Machines", False },
2893 { "menuMode.Machine Match", False },
2894 { "menuEngine.Retract Move", False },
2898 Enables userThinkingEnables[] = {
2899 { "menuFile.Load Game", True },
2900 // { "menuFile.Load Next Game", True },
2901 // { "menuFile.Load Previous Game", True },
2902 // { "menuFile.Reload Same Game", True },
2903 { "menuEdit.Paste Game", True },
2904 { "menuFile.Load Position", True },
2905 // { "menuFile.Load Next Position", True },
2906 // { "menuFile.Load Previous Position", True },
2907 // { "menuFile.Reload Same Position", True },
2908 { "menuEdit.Paste Position", True },
2909 { "menuMode.Machine White", True },
2910 { "menuMode.Machine Black", True },
2911 { "menuMode.Two Machines", True },
2912 { "menuMode.Machine Match", True },
2913 { "menuEngine.Retract Move", True },
2919 SetMenuEnables(icsEnables);
2922 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2923 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2930 SetMenuEnables(ncpEnables);
2936 SetMenuEnables(gnuEnables);
2942 SetMenuEnables(cmailEnables);
2948 SetMenuEnables(trainingOnEnables);
2949 if (appData.showButtonBar) {
2950 XtSetSensitive(buttonBarWidget, False);
2956 SetTrainingModeOff()
2958 SetMenuEnables(trainingOffEnables);
2959 if (appData.showButtonBar) {
2960 XtSetSensitive(buttonBarWidget, True);
2965 SetUserThinkingEnables()
2967 if (appData.noChessProgram) return;
2968 SetMenuEnables(userThinkingEnables);
2972 SetMachineThinkingEnables()
2974 if (appData.noChessProgram) return;
2975 SetMenuEnables(machineThinkingEnables);
2977 case MachinePlaysBlack:
2978 case MachinePlaysWhite:
2979 case TwoMachinesPlay:
2980 XtSetSensitive(XtNameToWidget(menuBarWidget,
2981 ModeToWidgetName(gameMode)), True);
2988 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2989 #define HISTORY_SIZE 64
2990 static char *history[HISTORY_SIZE];
2991 int histIn = 0, histP = 0;
2994 SaveInHistory(char *cmd)
2996 if (history[histIn] != NULL) {
2997 free(history[histIn]);
2998 history[histIn] = NULL;
3000 if (*cmd == NULLCHAR) return;
3001 history[histIn] = StrSave(cmd);
3002 histIn = (histIn + 1) % HISTORY_SIZE;
3003 if (history[histIn] != NULL) {
3004 free(history[histIn]);
3005 history[histIn] = NULL;
3011 PrevInHistory(char *cmd)
3014 if (histP == histIn) {
3015 if (history[histIn] != NULL) free(history[histIn]);
3016 history[histIn] = StrSave(cmd);
3018 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3019 if (newhp == histIn || history[newhp] == NULL) return NULL;
3021 return history[histP];
3027 if (histP == histIn) return NULL;
3028 histP = (histP + 1) % HISTORY_SIZE;
3029 return history[histP];
3031 // end of borrowed code
3033 #define Abs(n) ((n)<0 ? -(n) : (n))
3036 * Find a font that matches "pattern" that is as close as
3037 * possible to the targetPxlSize. Prefer fonts that are k
3038 * pixels smaller to fonts that are k pixels larger. The
3039 * pattern must be in the X Consortium standard format,
3040 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3041 * The return value should be freed with XtFree when no
3045 FindFont(pattern, targetPxlSize)
3049 char **fonts, *p, *best, *scalable, *scalableTail;
3050 int i, j, nfonts, minerr, err, pxlSize;
3053 char **missing_list;
3055 char *def_string, *base_fnt_lst, strInt[3];
3057 XFontStruct **fnt_list;
3059 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3060 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3061 p = strstr(pattern, "--");
3062 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3063 strcat(base_fnt_lst, strInt);
3064 strcat(base_fnt_lst, strchr(p + 2, '-'));
3066 if ((fntSet = XCreateFontSet(xDisplay,
3070 &def_string)) == NULL) {
3072 fprintf(stderr, _("Unable to create font set.\n"));
3076 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3078 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3080 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3081 programName, pattern);
3089 for (i=0; i<nfonts; i++) {
3092 if (*p != '-') continue;
3094 if (*p == NULLCHAR) break;
3095 if (*p++ == '-') j++;
3097 if (j < 7) continue;
3100 scalable = fonts[i];
3103 err = pxlSize - targetPxlSize;
3104 if (Abs(err) < Abs(minerr) ||
3105 (minerr > 0 && err < 0 && -err == minerr)) {
3111 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3112 /* If the error is too big and there is a scalable font,
3113 use the scalable font. */
3114 int headlen = scalableTail - scalable;
3115 p = (char *) XtMalloc(strlen(scalable) + 10);
3116 while (isdigit(*scalableTail)) scalableTail++;
3117 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3119 p = (char *) XtMalloc(strlen(best) + 2);
3120 safeStrCpy(p, best, strlen(best)+1 );
3122 if (appData.debugMode) {
3123 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3124 pattern, targetPxlSize, p);
3127 if (missing_count > 0)
3128 XFreeStringList(missing_list);
3129 XFreeFontSet(xDisplay, fntSet);
3131 XFreeFontNames(fonts);
3137 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3138 // must be called before all non-first callse to CreateGCs()
3139 XtReleaseGC(shellWidget, highlineGC);
3140 XtReleaseGC(shellWidget, lightSquareGC);
3141 XtReleaseGC(shellWidget, darkSquareGC);
3142 if (appData.monoMode) {
3143 if (DefaultDepth(xDisplay, xScreen) == 1) {
3144 XtReleaseGC(shellWidget, wbPieceGC);
3146 XtReleaseGC(shellWidget, bwPieceGC);
3149 XtReleaseGC(shellWidget, prelineGC);
3150 XtReleaseGC(shellWidget, jailSquareGC);
3151 XtReleaseGC(shellWidget, wdPieceGC);
3152 XtReleaseGC(shellWidget, wlPieceGC);
3153 XtReleaseGC(shellWidget, wjPieceGC);
3154 XtReleaseGC(shellWidget, bdPieceGC);
3155 XtReleaseGC(shellWidget, blPieceGC);
3156 XtReleaseGC(shellWidget, bjPieceGC);
3160 void CreateGCs(int redo)
3162 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3163 | GCBackground | GCFunction | GCPlaneMask;
3164 XGCValues gc_values;
3167 gc_values.plane_mask = AllPlanes;
3168 gc_values.line_width = lineGap;
3169 gc_values.line_style = LineSolid;
3170 gc_values.function = GXcopy;
3173 DeleteGCs(); // called a second time; clean up old GCs first
3174 } else { // [HGM] grid and font GCs created on first call only
3175 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3176 gc_values.background = XBlackPixel(xDisplay, xScreen);
3177 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3179 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3180 gc_values.background = XWhitePixel(xDisplay, xScreen);
3181 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3182 XSetFont(xDisplay, coordGC, coordFontID);
3184 // [HGM] make font for holdings counts (white on black)
3185 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3186 gc_values.background = XBlackPixel(xDisplay, xScreen);
3187 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3188 XSetFont(xDisplay, countGC, countFontID);
3190 if (appData.monoMode) {
3191 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3192 gc_values.background = XWhitePixel(xDisplay, xScreen);
3193 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3195 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3196 gc_values.background = XBlackPixel(xDisplay, xScreen);
3197 lightSquareGC = wbPieceGC
3198 = XtGetGC(shellWidget, value_mask, &gc_values);
3200 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3201 gc_values.background = XWhitePixel(xDisplay, xScreen);
3202 darkSquareGC = bwPieceGC
3203 = XtGetGC(shellWidget, value_mask, &gc_values);
3205 if (DefaultDepth(xDisplay, xScreen) == 1) {
3206 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3207 gc_values.function = GXcopyInverted;
3208 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3209 gc_values.function = GXcopy;
3210 if (XBlackPixel(xDisplay, xScreen) == 1) {
3211 bwPieceGC = darkSquareGC;
3212 wbPieceGC = copyInvertedGC;
3214 bwPieceGC = copyInvertedGC;
3215 wbPieceGC = lightSquareGC;
3219 gc_values.foreground = highlightSquareColor;
3220 gc_values.background = highlightSquareColor;
3221 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3223 gc_values.foreground = premoveHighlightColor;
3224 gc_values.background = premoveHighlightColor;
3225 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3227 gc_values.foreground = lightSquareColor;
3228 gc_values.background = darkSquareColor;
3229 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3231 gc_values.foreground = darkSquareColor;
3232 gc_values.background = lightSquareColor;
3233 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3235 gc_values.foreground = jailSquareColor;
3236 gc_values.background = jailSquareColor;
3237 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3239 gc_values.foreground = whitePieceColor;
3240 gc_values.background = darkSquareColor;
3241 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3243 gc_values.foreground = whitePieceColor;
3244 gc_values.background = lightSquareColor;
3245 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3247 gc_values.foreground = whitePieceColor;
3248 gc_values.background = jailSquareColor;
3249 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3251 gc_values.foreground = blackPieceColor;
3252 gc_values.background = darkSquareColor;
3253 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3255 gc_values.foreground = blackPieceColor;
3256 gc_values.background = lightSquareColor;
3257 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3259 gc_values.foreground = blackPieceColor;
3260 gc_values.background = jailSquareColor;
3261 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3265 void loadXIM(xim, xmask, filename, dest, mask)
3278 fp = fopen(filename, "rb");
3280 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3287 for (y=0; y<h; ++y) {
3288 for (x=0; x<h; ++x) {
3293 XPutPixel(xim, x, y, blackPieceColor);
3295 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3298 XPutPixel(xim, x, y, darkSquareColor);
3300 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3303 XPutPixel(xim, x, y, whitePieceColor);
3305 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3308 XPutPixel(xim, x, y, lightSquareColor);
3310 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3318 /* create Pixmap of piece */
3319 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3321 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3324 /* create Pixmap of clipmask
3325 Note: We assume the white/black pieces have the same
3326 outline, so we make only 6 masks. This is okay
3327 since the XPM clipmask routines do the same. */
3329 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3331 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3334 /* now create the 1-bit version */
3335 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3338 values.foreground = 1;
3339 values.background = 0;
3341 /* Don't use XtGetGC, not read only */
3342 maskGC = XCreateGC(xDisplay, *mask,
3343 GCForeground | GCBackground, &values);
3344 XCopyPlane(xDisplay, temp, *mask, maskGC,
3345 0, 0, squareSize, squareSize, 0, 0, 1);
3346 XFreePixmap(xDisplay, temp);
3351 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3353 void CreateXIMPieces()
3358 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3363 /* The XSynchronize calls were copied from CreatePieces.
3364 Not sure if needed, but can't hurt */
3365 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3368 /* temp needed by loadXIM() */
3369 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3370 0, 0, ss, ss, AllPlanes, XYPixmap);
3372 if (strlen(appData.pixmapDirectory) == 0) {
3376 if (appData.monoMode) {
3377 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3381 fprintf(stderr, _("\nLoading XIMs...\n"));
3383 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3384 fprintf(stderr, "%d", piece+1);
3385 for (kind=0; kind<4; kind++) {
3386 fprintf(stderr, ".");
3387 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3388 ExpandPathName(appData.pixmapDirectory),
3389 piece <= (int) WhiteKing ? "" : "w",
3390 pieceBitmapNames[piece],
3392 ximPieceBitmap[kind][piece] =
3393 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3394 0, 0, ss, ss, AllPlanes, XYPixmap);
3395 if (appData.debugMode)
3396 fprintf(stderr, _("(File:%s:) "), buf);
3397 loadXIM(ximPieceBitmap[kind][piece],
3399 &(xpmPieceBitmap2[kind][piece]),
3400 &(ximMaskPm2[piece]));
3401 if(piece <= (int)WhiteKing)
3402 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3404 fprintf(stderr," ");
3406 /* Load light and dark squares */
3407 /* If the LSQ and DSQ pieces don't exist, we will
3408 draw them with solid squares. */
3409 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3410 if (access(buf, 0) != 0) {
3414 fprintf(stderr, _("light square "));
3416 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3417 0, 0, ss, ss, AllPlanes, XYPixmap);
3418 if (appData.debugMode)
3419 fprintf(stderr, _("(File:%s:) "), buf);
3421 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3422 fprintf(stderr, _("dark square "));
3423 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3424 ExpandPathName(appData.pixmapDirectory), ss);
3425 if (appData.debugMode)
3426 fprintf(stderr, _("(File:%s:) "), buf);
3428 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3429 0, 0, ss, ss, AllPlanes, XYPixmap);
3430 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3431 xpmJailSquare = xpmLightSquare;
3433 fprintf(stderr, _("Done.\n"));
3435 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3439 void CreateXPMBoard(char *s, int kind)
3443 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3444 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3445 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3449 void FreeXPMPieces()
3450 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3451 // thisroutine has to be called t free the old piece pixmaps
3453 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3454 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3456 XFreePixmap(xDisplay, xpmLightSquare);
3457 XFreePixmap(xDisplay, xpmDarkSquare);
3461 void CreateXPMPieces()
3465 u_int ss = squareSize;
3467 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3468 XpmColorSymbol symbols[4];
3469 static int redo = False;
3471 if(redo) FreeXPMPieces(); else redo = 1;
3473 /* The XSynchronize calls were copied from CreatePieces.
3474 Not sure if needed, but can't hurt */
3475 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3477 /* Setup translations so piece colors match square colors */
3478 symbols[0].name = "light_piece";
3479 symbols[0].value = appData.whitePieceColor;
3480 symbols[1].name = "dark_piece";
3481 symbols[1].value = appData.blackPieceColor;
3482 symbols[2].name = "light_square";
3483 symbols[2].value = appData.lightSquareColor;
3484 symbols[3].name = "dark_square";
3485 symbols[3].value = appData.darkSquareColor;
3487 attr.valuemask = XpmColorSymbols;
3488 attr.colorsymbols = symbols;
3489 attr.numsymbols = 4;
3491 if (appData.monoMode) {
3492 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3496 if (strlen(appData.pixmapDirectory) == 0) {
3497 XpmPieces* pieces = builtInXpms;
3500 while (pieces->size != squareSize && pieces->size) pieces++;
3501 if (!pieces->size) {
3502 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3505 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3506 for (kind=0; kind<4; kind++) {
3508 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3509 pieces->xpm[piece][kind],
3510 &(xpmPieceBitmap2[kind][piece]),
3511 NULL, &attr)) != 0) {
3512 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3516 if(piece <= (int) WhiteKing)
3517 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3521 xpmJailSquare = xpmLightSquare;
3525 fprintf(stderr, _("\nLoading XPMs...\n"));
3528 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3529 fprintf(stderr, "%d ", piece+1);
3530 for (kind=0; kind<4; kind++) {
3531 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3532 ExpandPathName(appData.pixmapDirectory),
3533 piece > (int) WhiteKing ? "w" : "",
3534 pieceBitmapNames[piece],
3536 if (appData.debugMode) {
3537 fprintf(stderr, _("(File:%s:) "), buf);
3539 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3540 &(xpmPieceBitmap2[kind][piece]),
3541 NULL, &attr)) != 0) {
3542 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3543 // [HGM] missing: read of unorthodox piece failed; substitute King.
3544 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3545 ExpandPathName(appData.pixmapDirectory),
3547 if (appData.debugMode) {
3548 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3550 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3551 &(xpmPieceBitmap2[kind][piece]),
3555 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3560 if(piece <= (int) WhiteKing)
3561 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3564 /* Load light and dark squares */
3565 /* If the LSQ and DSQ pieces don't exist, we will
3566 draw them with solid squares. */
3567 fprintf(stderr, _("light square "));
3568 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3569 if (access(buf, 0) != 0) {
3573 if (appData.debugMode)
3574 fprintf(stderr, _("(File:%s:) "), buf);
3576 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3577 &xpmLightSquare, NULL, &attr)) != 0) {
3578 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3581 fprintf(stderr, _("dark square "));
3582 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3583 ExpandPathName(appData.pixmapDirectory), ss);
3584 if (appData.debugMode) {
3585 fprintf(stderr, _("(File:%s:) "), buf);
3587 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3588 &xpmDarkSquare, NULL, &attr)) != 0) {
3589 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3593 xpmJailSquare = xpmLightSquare;
3594 fprintf(stderr, _("Done.\n"));
3596 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3599 #endif /* HAVE_LIBXPM */
3602 /* No built-in bitmaps */
3607 u_int ss = squareSize;
3609 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3612 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3613 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3614 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3615 pieceBitmapNames[piece],
3616 ss, kind == SOLID ? 's' : 'o');
3617 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3618 if(piece <= (int)WhiteKing)
3619 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3623 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3627 /* With built-in bitmaps */
3630 BuiltInBits* bib = builtInBits;
3633 u_int ss = squareSize;
3635 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3638 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3640 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3641 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3642 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3643 pieceBitmapNames[piece],
3644 ss, kind == SOLID ? 's' : 'o');
3645 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3646 bib->bits[kind][piece], ss, ss);
3647 if(piece <= (int)WhiteKing)
3648 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3652 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3657 void ReadBitmap(pm, name, bits, wreq, hreq)
3660 unsigned char bits[];
3666 char msg[MSG_SIZ], fullname[MSG_SIZ];
3668 if (*appData.bitmapDirectory != NULLCHAR) {
3669 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3670 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3671 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3672 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3673 &w, &h, pm, &x_hot, &y_hot);
3674 fprintf(stderr, "load %s\n", name);
3675 if (errcode != BitmapSuccess) {
3677 case BitmapOpenFailed:
3678 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3680 case BitmapFileInvalid:
3681 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3683 case BitmapNoMemory:
3684 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3688 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3692 fprintf(stderr, _("%s: %s...using built-in\n"),
3694 } else if (w != wreq || h != hreq) {
3696 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3697 programName, fullname, w, h, wreq, hreq);
3703 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3712 if (lineGap == 0) return;
3714 /* [HR] Split this into 2 loops for non-square boards. */
3716 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3717 gridSegments[i].x1 = 0;
3718 gridSegments[i].x2 =
3719 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3720 gridSegments[i].y1 = gridSegments[i].y2
3721 = lineGap / 2 + (i * (squareSize + lineGap));
3724 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3725 gridSegments[j + i].y1 = 0;
3726 gridSegments[j + i].y2 =
3727 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3728 gridSegments[j + i].x1 = gridSegments[j + i].x2
3729 = lineGap / 2 + (j * (squareSize + lineGap));
3733 static void MenuBarSelect(w, addr, index)
3738 XtActionProc proc = (XtActionProc) addr;
3740 (proc)(NULL, NULL, NULL, NULL);
3743 void CreateMenuBarPopup(parent, name, mb)
3753 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3756 XtSetArg(args[j], XtNleftMargin, 20); j++;
3757 XtSetArg(args[j], XtNrightMargin, 20); j++;
3759 while (mi->string != NULL) {
3760 if (strcmp(mi->string, "----") == 0) {
3761 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3764 XtSetArg(args[j], XtNlabel, XtNewString(mi->string));
3765 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3767 XtAddCallback(entry, XtNcallback,
3768 (XtCallbackProc) MenuBarSelect,
3769 (caddr_t) mi->proc);
3775 Widget CreateMenuBar(mb)
3779 Widget anchor, menuBar;
3781 char menuName[MSG_SIZ];
3784 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3785 XtSetArg(args[j], XtNvSpace, 0); j++;
3786 XtSetArg(args[j], XtNborderWidth, 0); j++;
3787 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3788 formWidget, args, j);
3790 while (mb->name != NULL) {
3791 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3792 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3794 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3797 shortName[0] = mb->name[0];
3798 shortName[1] = NULLCHAR;
3799 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3802 XtSetArg(args[j], XtNlabel, XtNewString(mb->name)); j++;
3805 XtSetArg(args[j], XtNborderWidth, 0); j++;
3806 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3808 CreateMenuBarPopup(menuBar, menuName, mb);
3814 Widget CreateButtonBar(mi)
3818 Widget button, buttonBar;
3822 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3824 XtSetArg(args[j], XtNhSpace, 0); j++;
3826 XtSetArg(args[j], XtNborderWidth, 0); j++;
3827 XtSetArg(args[j], XtNvSpace, 0); j++;
3828 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3829 formWidget, args, j);
3831 while (mi->string != NULL) {
3834 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3835 XtSetArg(args[j], XtNborderWidth, 0); j++;
3837 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3838 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3839 buttonBar, args, j);
3840 XtAddCallback(button, XtNcallback,
3841 (XtCallbackProc) MenuBarSelect,
3842 (caddr_t) mi->proc);
3849 CreatePieceMenu(name, color)
3856 ChessSquare selection;
3858 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3859 boardWidget, args, 0);
3861 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3862 String item = pieceMenuStrings[color][i];
3864 if (strcmp(item, "----") == 0) {
3865 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3868 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3869 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3871 selection = pieceMenuTranslation[color][i];
3872 XtAddCallback(entry, XtNcallback,
3873 (XtCallbackProc) PieceMenuSelect,
3874 (caddr_t) selection);
3875 if (selection == WhitePawn || selection == BlackPawn) {
3876 XtSetArg(args[0], XtNpopupOnEntry, entry);
3877 XtSetValues(menu, args, 1);
3890 ChessSquare selection;
3892 whitePieceMenu = CreatePieceMenu("menuW", 0);
3893 blackPieceMenu = CreatePieceMenu("menuB", 1);
3895 XtRegisterGrabAction(PieceMenuPopup, True,
3896 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3897 GrabModeAsync, GrabModeAsync);
3899 XtSetArg(args[0], XtNlabel, _("Drop"));
3900 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3901 boardWidget, args, 1);
3902 for (i = 0; i < DROP_MENU_SIZE; i++) {
3903 String item = dropMenuStrings[i];
3905 if (strcmp(item, "----") == 0) {
3906 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3909 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3910 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3912 selection = dropMenuTranslation[i];
3913 XtAddCallback(entry, XtNcallback,
3914 (XtCallbackProc) DropMenuSelect,
3915 (caddr_t) selection);
3920 void SetupDropMenu()
3928 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3929 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3930 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3931 dmEnables[i].piece);
3932 XtSetSensitive(entry, p != NULL || !appData.testLegality
3933 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3934 && !appData.icsActive));
3936 while (p && *p++ == dmEnables[i].piece) count++;
3937 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3939 XtSetArg(args[j], XtNlabel, label); j++;
3940 XtSetValues(entry, args, j);
3944 void PieceMenuPopup(w, event, params, num_params)
3948 Cardinal *num_params;
3950 String whichMenu; int menuNr;
3951 if (event->type == ButtonRelease)
3952 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3953 else if (event->type == ButtonPress)
3954 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3956 case 0: whichMenu = params[0]; break;
3957 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3959 case -1: if (errorUp) ErrorPopDown();
3962 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3965 static void PieceMenuSelect(w, piece, junk)
3970 if (pmFromX < 0 || pmFromY < 0) return;
3971 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3974 static void DropMenuSelect(w, piece, junk)
3979 if (pmFromX < 0 || pmFromY < 0) return;
3980 DropMenuEvent(piece, pmFromX, pmFromY);
3983 void WhiteClock(w, event, prms, nprms)
3992 void BlackClock(w, event, prms, nprms)
4003 * If the user selects on a border boundary, return -1; if off the board,
4004 * return -2. Otherwise map the event coordinate to the square.
4006 int EventToSquare(x, limit)
4014 if ((x % (squareSize + lineGap)) >= squareSize)
4016 x /= (squareSize + lineGap);
4022 static void do_flash_delay(msec)
4028 static void drawHighlight(file, rank, gc)
4034 if (lineGap == 0) return;
4037 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4038 (squareSize + lineGap);
4039 y = lineGap/2 + rank * (squareSize + lineGap);
4041 x = lineGap/2 + file * (squareSize + lineGap);
4042 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4043 (squareSize + lineGap);
4046 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4047 squareSize+lineGap, squareSize+lineGap);
4050 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4051 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4054 SetHighlights(fromX, fromY, toX, toY)
4055 int fromX, fromY, toX, toY;
4057 if (hi1X != fromX || hi1Y != fromY) {
4058 if (hi1X >= 0 && hi1Y >= 0) {
4059 drawHighlight(hi1X, hi1Y, lineGC);
4061 } // [HGM] first erase both, then draw new!
4062 if (hi2X != toX || hi2Y != toY) {
4063 if (hi2X >= 0 && hi2Y >= 0) {
4064 drawHighlight(hi2X, hi2Y, lineGC);
4067 if (hi1X != fromX || hi1Y != fromY) {
4068 if (fromX >= 0 && fromY >= 0) {
4069 drawHighlight(fromX, fromY, highlineGC);
4072 if (hi2X != toX || hi2Y != toY) {
4073 if (toX >= 0 && toY >= 0) {
4074 drawHighlight(toX, toY, highlineGC);
4086 SetHighlights(-1, -1, -1, -1);
4091 SetPremoveHighlights(fromX, fromY, toX, toY)
4092 int fromX, fromY, toX, toY;
4094 if (pm1X != fromX || pm1Y != fromY) {
4095 if (pm1X >= 0 && pm1Y >= 0) {
4096 drawHighlight(pm1X, pm1Y, lineGC);
4098 if (fromX >= 0 && fromY >= 0) {
4099 drawHighlight(fromX, fromY, prelineGC);
4102 if (pm2X != toX || pm2Y != toY) {
4103 if (pm2X >= 0 && pm2Y >= 0) {
4104 drawHighlight(pm2X, pm2Y, lineGC);
4106 if (toX >= 0 && toY >= 0) {
4107 drawHighlight(toX, toY, prelineGC);
4117 ClearPremoveHighlights()
4119 SetPremoveHighlights(-1, -1, -1, -1);
4122 static int CutOutSquare(x, y, x0, y0, kind)
4123 int x, y, *x0, *y0, kind;
4125 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4126 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4128 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4129 if(textureW[kind] < W*squareSize)
4130 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4132 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4133 if(textureH[kind] < H*squareSize)
4134 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4136 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4140 static void BlankSquare(x, y, color, piece, dest, fac)
4141 int x, y, color, fac;
4144 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4146 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4147 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4148 squareSize, squareSize, x*fac, y*fac);
4150 if (useImages && useImageSqs) {
4154 pm = xpmLightSquare;
4159 case 2: /* neutral */
4164 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4165 squareSize, squareSize, x*fac, y*fac);
4175 case 2: /* neutral */
4180 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4185 I split out the routines to draw a piece so that I could
4186 make a generic flash routine.
4188 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4190 int square_color, x, y;
4193 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4194 switch (square_color) {
4196 case 2: /* neutral */
4198 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4199 ? *pieceToOutline(piece)
4200 : *pieceToSolid(piece),
4201 dest, bwPieceGC, 0, 0,
4202 squareSize, squareSize, x, y);
4205 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4206 ? *pieceToSolid(piece)
4207 : *pieceToOutline(piece),
4208 dest, wbPieceGC, 0, 0,
4209 squareSize, squareSize, x, y);
4214 static void monoDrawPiece(piece, square_color, x, y, dest)
4216 int square_color, x, y;
4219 switch (square_color) {
4221 case 2: /* neutral */
4223 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4224 ? *pieceToOutline(piece)
4225 : *pieceToSolid(piece),
4226 dest, bwPieceGC, 0, 0,
4227 squareSize, squareSize, x, y, 1);
4230 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4231 ? *pieceToSolid(piece)
4232 : *pieceToOutline(piece),
4233 dest, wbPieceGC, 0, 0,
4234 squareSize, squareSize, x, y, 1);
4239 static void colorDrawPiece(piece, square_color, x, y, dest)
4241 int square_color, x, y;
4244 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4245 switch (square_color) {
4247 XCopyPlane(xDisplay, *pieceToSolid(piece),
4248 dest, (int) piece < (int) BlackPawn
4249 ? wlPieceGC : blPieceGC, 0, 0,