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 *filter, 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 MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
265 void HandleUserMove P((Widget w, XEvent *event,
266 String *prms, Cardinal *nprms));
267 void AnimateUserMove P((Widget w, XEvent * event,
268 String * params, Cardinal * nParams));
269 void HandlePV P((Widget w, XEvent * event,
270 String * params, Cardinal * nParams));
271 void SelectPV P((Widget w, XEvent * event,
272 String * params, Cardinal * nParams));
273 void StopPV P((Widget w, XEvent * event,
274 String * params, Cardinal * nParams));
275 void WhiteClock P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void BlackClock P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void DrawPositionProc P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
283 void CommentClick P((Widget w, XEvent * event,
284 String * params, Cardinal * nParams));
285 void CommentPopUp P((char *title, char *label));
286 void CommentPopDown P((void));
287 void ICSInputBoxPopUp P((void));
288 void ICSInputBoxPopDown P((void));
289 void FileNamePopUp P((char *label, char *def, char *filter,
290 FileProc proc, char *openMode));
291 void FileNamePopDown P((void));
292 void FileNameCallback P((Widget w, XtPointer client_data,
293 XtPointer call_data));
294 void FileNameAction P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void AskQuestionReplyAction P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void AskQuestionProc P((Widget w, XEvent *event,
299 String *prms, Cardinal *nprms));
300 void AskQuestionPopDown P((void));
301 void PromotionPopDown P((void));
302 void PromotionCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
305 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
309 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
311 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
313 void LoadPositionProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
317 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
319 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
321 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
323 void PastePositionProc P((Widget w, XEvent *event, String *prms,
325 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void SavePositionProc P((Widget w, XEvent *event,
330 String *prms, Cardinal *nprms));
331 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
334 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
338 void MachineWhiteProc P((Widget w, XEvent *event,
339 String *prms, Cardinal *nprms));
340 void AnalyzeModeProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void AnalyzeFileProc P((Widget w, XEvent *event,
343 String *prms, Cardinal *nprms));
344 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
346 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void IcsClientProc P((Widget w, XEvent *event, String *prms,
350 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void EditPositionProc P((Widget w, XEvent *event,
352 String *prms, Cardinal *nprms));
353 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void EditCommentProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void IcsInputBoxProc P((Widget w, XEvent *event,
357 String *prms, Cardinal *nprms));
358 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void StopObservingProc P((Widget w, XEvent *event, String *prms,
375 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
377 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
386 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
388 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
391 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
393 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
395 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
400 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
403 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
405 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
407 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
412 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
414 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
416 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
418 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
421 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
423 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
425 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
427 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void DisplayMove P((int moveNumber));
439 void DisplayTitle P((char *title));
440 void ICSInitScript P((void));
441 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
442 void ErrorPopUp P((char *title, char *text, int modal));
443 void ErrorPopDown P((void));
444 static char *ExpandPathName P((char *path));
445 static void CreateAnimVars P((void));
446 static void DragPieceMove P((int x, int y));
447 static void DrawDragPiece P((void));
448 char *ModeToWidgetName P((GameMode mode));
449 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
450 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void GameListOptionsPopDown P(());
465 void ShufflePopDown P(());
466 void TimeControlPopDown P(());
467 void GenericPopDown P(());
468 void update_ics_width P(());
469 int get_term_width P(());
470 int CopyMemoProc P(());
471 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
472 Boolean IsDrawArrowEnabled P(());
475 * XBoard depends on Xt R4 or higher
477 int xtVersion = XtSpecificationRelease;
482 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
483 jailSquareColor, highlightSquareColor, premoveHighlightColor;
484 Pixel lowTimeWarningColor;
485 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
486 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
487 wjPieceGC, bjPieceGC, prelineGC, countGC;
488 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
489 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
490 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
491 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
492 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
493 ICSInputShell, fileNameShell, askQuestionShell;
494 Widget historyShell, evalGraphShell, gameListShell;
495 int hOffset; // [HGM] dual
496 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
497 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
498 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
499 Font clockFontID, coordFontID, countFontID;
500 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
501 XtAppContext appContext;
503 char *oldICSInteractionTitle;
507 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
509 Position commentX = -1, commentY = -1;
510 Dimension commentW, commentH;
511 typedef unsigned int BoardSize;
513 Boolean chessProgram;
515 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
516 int squareSize, smallLayout = 0, tinyLayout = 0,
517 marginW, marginH, // [HGM] for run-time resizing
518 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
519 ICSInputBoxUp = False, askQuestionUp = False,
520 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
521 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
522 Pixel timerForegroundPixel, timerBackgroundPixel;
523 Pixel buttonForegroundPixel, buttonBackgroundPixel;
524 char *chessDir, *programName, *programVersion,
525 *gameCopyFilename, *gamePasteFilename;
526 Boolean alwaysOnTop = False;
527 Boolean saveSettingsOnExit;
528 char *settingsFileName;
529 char *icsTextMenuString;
531 char *firstChessProgramNames;
532 char *secondChessProgramNames;
534 WindowPlacement wpMain;
535 WindowPlacement wpConsole;
536 WindowPlacement wpComment;
537 WindowPlacement wpMoveHistory;
538 WindowPlacement wpEvalGraph;
539 WindowPlacement wpEngineOutput;
540 WindowPlacement wpGameList;
541 WindowPlacement wpTags;
543 extern Widget shells[];
544 extern Boolean shellUp[];
548 Pixmap pieceBitmap[2][(int)BlackPawn];
549 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
550 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
551 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
552 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
553 Pixmap xpmBoardBitmap[2];
554 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
555 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
556 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
557 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
558 XImage *ximLightSquare, *ximDarkSquare;
561 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
562 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
564 #define White(piece) ((int)(piece) < (int)BlackPawn)
566 /* Variables for doing smooth animation. This whole thing
567 would be much easier if the board was double-buffered,
568 but that would require a fairly major rewrite. */
573 GC blitGC, pieceGC, outlineGC;
574 XPoint startSquare, prevFrame, mouseDelta;
578 int startBoardX, startBoardY;
581 /* There can be two pieces being animated at once: a player
582 can begin dragging a piece before the remote opponent has moved. */
584 static AnimState game, player;
586 /* Bitmaps for use as masks when drawing XPM pieces.
587 Need one for each black and white piece. */
588 static Pixmap xpmMask[BlackKing + 1];
590 /* This magic number is the number of intermediate frames used
591 in each half of the animation. For short moves it's reduced
592 by 1. The total number of frames will be factor * 2 + 1. */
595 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
597 MenuItem fileMenu[] = {
598 {N_("New Game Ctrl+N"), "New Game", ResetProc},
599 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
600 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
601 {"----", NULL, NothingProc},
602 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
603 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
604 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
605 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
606 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
607 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
608 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
609 {"----", NULL, NothingProc},
610 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
611 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
612 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
613 {"----", NULL, NothingProc},
614 {N_("Mail Move"), "Mail Move", MailMoveProc},
615 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
616 {"----", NULL, NothingProc},
617 {N_("Quit Ctr+Q"), "Exit", QuitProc},
621 MenuItem editMenu[] = {
622 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
623 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
624 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
625 {"----", NULL, NothingProc},
626 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
627 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
628 {"----", NULL, NothingProc},
629 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
630 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
631 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
632 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
633 {"----", NULL, NothingProc},
634 {N_("Revert Home"), "Revert", RevertProc},
635 {N_("Annotate"), "Annotate", AnnotateProc},
636 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
637 {"----", NULL, NothingProc},
638 {N_("Backward Alt+Left"), "Backward", BackwardProc},
639 {N_("Forward Alt+Right"), "Forward", ForwardProc},
640 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
641 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
645 MenuItem viewMenu[] = {
646 {N_("Flip View F2"), "Flip View", FlipViewProc},
647 {"----", NULL, NothingProc},
648 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
649 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
650 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
651 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
652 {N_("ICS text menu"), "ICStex", IcsTextProc},
653 {"----", NULL, NothingProc},
654 {N_("Tags"), "Show Tags", EditTagsProc},
655 {N_("Comments"), "Show Comments", EditCommentProc},
656 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
657 {"----", NULL, NothingProc},
658 {N_("Board..."), "Board Options", BoardOptionsProc},
659 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
663 MenuItem modeMenu[] = {
664 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
665 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
666 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
667 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
668 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
669 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
670 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
671 {N_("Training"), "Training", TrainingProc},
672 {N_("ICS Client"), "ICS Client", IcsClientProc},
673 {"----", NULL, NothingProc},
674 {N_("Machine Match"), "Machine Match", MatchProc},
675 {N_("Pause Pause"), "Pause", PauseProc},
679 MenuItem actionMenu[] = {
680 {N_("Accept F3"), "Accept", AcceptProc},
681 {N_("Decline F4"), "Decline", DeclineProc},
682 {N_("Rematch F12"), "Rematch", RematchProc},
683 {"----", NULL, NothingProc},
684 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
685 {N_("Draw F6"), "Draw", DrawProc},
686 {N_("Adjourn F7"), "Adjourn", AdjournProc},
687 {N_("Abort F8"),"Abort", AbortProc},
688 {N_("Resign F9"), "Resign", ResignProc},
689 {"----", NULL, NothingProc},
690 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
691 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
692 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
693 {"----", NULL, NothingProc},
694 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
695 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
696 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
700 MenuItem engineMenu[] = {
701 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
702 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
703 {"----", NULL, NothingProc},
704 {N_("Hint"), "Hint", HintProc},
705 {N_("Book"), "Book", BookProc},
706 {"----", NULL, NothingProc},
707 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
708 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
712 MenuItem optionsMenu[] = {
713 #define OPTIONSDIALOG
715 {N_("General ..."), "General", OptionsProc},
717 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
718 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
719 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
720 {N_("ICS ..."), "ICS", IcsOptionsProc},
721 {N_("Match ..."), "Match", MatchOptionsProc},
722 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
723 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
724 // {N_(" ..."), "", OptionsProc},
725 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
726 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
727 {"----", NULL, NothingProc},
728 #ifndef OPTIONSDIALOG
729 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
730 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
731 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
732 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
733 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
734 {N_("Blindfold"), "Blindfold", BlindfoldProc},
735 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
737 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
739 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
740 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
741 {N_("Move Sound"), "Move Sound", MoveSoundProc},
742 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
743 {N_("One-Click Moving"), "OneClick", OneClickProc},
744 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
745 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
746 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
747 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
748 // {N_("Premove"), "Premove", PremoveProc},
749 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
750 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
751 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
752 {"----", NULL, NothingProc},
754 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
755 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
759 MenuItem helpMenu[] = {
760 {N_("Info XBoard"), "Info XBoard", InfoProc},
761 {N_("Man XBoard F1"), "Man XBoard", ManProc},
762 {"----", NULL, NothingProc},
763 {N_("About XBoard"), "About XBoard", AboutProc},
768 {N_("File"), "File", fileMenu},
769 {N_("Edit"), "Edit", editMenu},
770 {N_("View"), "View", viewMenu},
771 {N_("Mode"), "Mode", modeMenu},
772 {N_("Action"), "Action", actionMenu},
773 {N_("Engine"), "Engine", engineMenu},
774 {N_("Options"), "Options", optionsMenu},
775 {N_("Help"), "Help", helpMenu},
779 #define PAUSE_BUTTON "P"
780 MenuItem buttonBar[] = {
781 {"<<", "<<", ToStartProc},
782 {"<", "<", BackwardProc},
783 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
784 {">", ">", ForwardProc},
785 {">>", ">>", ToEndProc},
789 #define PIECE_MENU_SIZE 18
790 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
791 { N_("White"), "----", 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") },
795 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
796 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
797 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
798 N_("Empty square"), N_("Clear board") }
800 /* must be in same order as PieceMenuStrings! */
801 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
802 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
803 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
804 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
805 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
806 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
807 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
808 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
809 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
812 #define DROP_MENU_SIZE 6
813 String dropMenuStrings[DROP_MENU_SIZE] = {
814 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
816 /* must be in same order as PieceMenuStrings! */
817 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
818 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
819 WhiteRook, WhiteQueen
827 DropMenuEnables dmEnables[] = {
845 { XtNborderWidth, 0 },
846 { XtNdefaultDistance, 0 },
850 { XtNborderWidth, 0 },
851 { XtNresizable, (XtArgVal) True },
855 { XtNborderWidth, 0 },
861 { XtNjustify, (XtArgVal) XtJustifyRight },
862 { XtNlabel, (XtArgVal) "..." },
863 { XtNresizable, (XtArgVal) True },
864 { XtNresize, (XtArgVal) False }
867 Arg messageArgs[] = {
868 { XtNjustify, (XtArgVal) XtJustifyLeft },
869 { XtNlabel, (XtArgVal) "..." },
870 { XtNresizable, (XtArgVal) True },
871 { XtNresize, (XtArgVal) False }
875 { XtNborderWidth, 0 },
876 { XtNjustify, (XtArgVal) XtJustifyLeft }
879 XtResource clientResources[] = {
880 { "flashCount", "flashCount", XtRInt, sizeof(int),
881 XtOffset(AppDataPtr, flashCount), XtRImmediate,
882 (XtPointer) FLASH_COUNT },
885 XrmOptionDescRec shellOptions[] = {
886 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
887 { "-flash", "flashCount", XrmoptionNoArg, "3" },
888 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
891 XtActionsRec boardActions[] = {
892 { "DrawPosition", DrawPositionProc },
893 { "HandleUserMove", HandleUserMove },
894 { "AnimateUserMove", AnimateUserMove },
895 { "HandlePV", HandlePV },
896 { "SelectPV", SelectPV },
897 { "StopPV", StopPV },
898 { "FileNameAction", FileNameAction },
899 { "AskQuestionProc", AskQuestionProc },
900 { "AskQuestionReplyAction", AskQuestionReplyAction },
901 { "PieceMenuPopup", PieceMenuPopup },
902 { "WhiteClock", WhiteClock },
903 { "BlackClock", BlackClock },
904 { "Iconify", Iconify },
905 { "ResetProc", ResetProc },
906 { "NewVariantProc", NewVariantProc },
907 { "LoadGameProc", LoadGameProc },
908 { "LoadNextGameProc", LoadNextGameProc },
909 { "LoadPrevGameProc", LoadPrevGameProc },
910 { "LoadSelectedProc", LoadSelectedProc },
911 { "SetFilterProc", SetFilterProc },
912 { "ReloadGameProc", ReloadGameProc },
913 { "LoadPositionProc", LoadPositionProc },
914 { "LoadNextPositionProc", LoadNextPositionProc },
915 { "LoadPrevPositionProc", LoadPrevPositionProc },
916 { "ReloadPositionProc", ReloadPositionProc },
917 { "CopyPositionProc", CopyPositionProc },
918 { "PastePositionProc", PastePositionProc },
919 { "CopyGameProc", CopyGameProc },
920 { "CopyGameListProc", CopyGameListProc },
921 { "PasteGameProc", PasteGameProc },
922 { "SaveGameProc", SaveGameProc },
923 { "SavePositionProc", SavePositionProc },
924 { "MailMoveProc", MailMoveProc },
925 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
926 { "QuitProc", QuitProc },
927 { "MachineWhiteProc", MachineWhiteProc },
928 { "MachineBlackProc", MachineBlackProc },
929 { "AnalysisModeProc", AnalyzeModeProc },
930 { "AnalyzeFileProc", AnalyzeFileProc },
931 { "TwoMachinesProc", TwoMachinesProc },
932 { "IcsClientProc", IcsClientProc },
933 { "EditGameProc", EditGameProc },
934 { "EditPositionProc", EditPositionProc },
935 { "TrainingProc", EditPositionProc },
936 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
937 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
938 { "ShowGameListProc", ShowGameListProc },
939 { "ShowMoveListProc", HistoryShowProc},
940 { "EditTagsProc", EditCommentProc },
941 { "EditCommentProc", EditCommentProc },
942 { "IcsInputBoxProc", IcsInputBoxProc },
943 { "PauseProc", PauseProc },
944 { "AcceptProc", AcceptProc },
945 { "DeclineProc", DeclineProc },
946 { "RematchProc", RematchProc },
947 { "CallFlagProc", CallFlagProc },
948 { "DrawProc", DrawProc },
949 { "AdjournProc", AdjournProc },
950 { "AbortProc", AbortProc },
951 { "ResignProc", ResignProc },
952 { "AdjuWhiteProc", AdjuWhiteProc },
953 { "AdjuBlackProc", AdjuBlackProc },
954 { "AdjuDrawProc", AdjuDrawProc },
955 { "TypeInProc", TypeInProc },
956 { "EnterKeyProc", EnterKeyProc },
957 { "UpKeyProc", UpKeyProc },
958 { "DownKeyProc", DownKeyProc },
959 { "StopObservingProc", StopObservingProc },
960 { "StopExaminingProc", StopExaminingProc },
961 { "UploadProc", UploadProc },
962 { "BackwardProc", BackwardProc },
963 { "ForwardProc", ForwardProc },
964 { "ToStartProc", ToStartProc },
965 { "ToEndProc", ToEndProc },
966 { "RevertProc", RevertProc },
967 { "AnnotateProc", AnnotateProc },
968 { "TruncateGameProc", TruncateGameProc },
969 { "MoveNowProc", MoveNowProc },
970 { "RetractMoveProc", RetractMoveProc },
971 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
972 { "UciMenuProc", (XtActionProc) UciMenuProc },
973 { "TimeControlProc", (XtActionProc) TimeControlProc },
974 { "FlipViewProc", FlipViewProc },
975 { "PonderNextMoveProc", PonderNextMoveProc },
976 #ifndef OPTIONSDIALOG
977 { "AlwaysQueenProc", AlwaysQueenProc },
978 { "AnimateDraggingProc", AnimateDraggingProc },
979 { "AnimateMovingProc", AnimateMovingProc },
980 { "AutoflagProc", AutoflagProc },
981 { "AutoflipProc", AutoflipProc },
982 { "BlindfoldProc", BlindfoldProc },
983 { "FlashMovesProc", FlashMovesProc },
985 { "HighlightDraggingProc", HighlightDraggingProc },
987 { "HighlightLastMoveProc", HighlightLastMoveProc },
988 // { "IcsAlarmProc", IcsAlarmProc },
989 { "MoveSoundProc", MoveSoundProc },
990 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
991 { "PopupExitMessageProc", PopupExitMessageProc },
992 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
993 // { "PremoveProc", PremoveProc },
994 { "ShowCoordsProc", ShowCoordsProc },
995 { "ShowThinkingProc", ShowThinkingProc },
996 { "HideThinkingProc", HideThinkingProc },
997 { "TestLegalityProc", TestLegalityProc },
999 { "SaveSettingsProc", SaveSettingsProc },
1000 { "SaveOnExitProc", SaveOnExitProc },
1001 { "InfoProc", InfoProc },
1002 { "ManProc", ManProc },
1003 { "HintProc", HintProc },
1004 { "BookProc", BookProc },
1005 { "AboutGameProc", AboutGameProc },
1006 { "AboutProc", AboutProc },
1007 { "DebugProc", DebugProc },
1008 { "NothingProc", NothingProc },
1009 { "CommentClick", (XtActionProc) CommentClick },
1010 { "CommentPopDown", (XtActionProc) CommentPopDown },
1011 { "TagsPopDown", (XtActionProc) TagsPopDown },
1012 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1013 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1014 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1015 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1016 { "GameListPopDown", (XtActionProc) GameListPopDown },
1017 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1018 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1019 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1020 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1021 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1022 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1023 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1024 { "GenericPopDown", (XtActionProc) GenericPopDown },
1025 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1028 char globalTranslations[] =
1029 ":<Key>F9: ResignProc() \n \
1030 :Ctrl<Key>n: ResetProc() \n \
1031 :Meta<Key>V: NewVariantProc() \n \
1032 :Ctrl<Key>o: LoadGameProc() \n \
1033 :Meta<Key>Next: LoadNextGameProc() \n \
1034 :Meta<Key>Prior: LoadPrevGameProc() \n \
1035 :Ctrl<Key>s: SaveGameProc() \n \
1036 :Ctrl<Key>c: CopyGameProc() \n \
1037 :Ctrl<Key>v: PasteGameProc() \n \
1038 :Ctrl<Key>O: LoadPositionProc() \n \
1039 :Shift<Key>Next: LoadNextPositionProc() \n \
1040 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1041 :Ctrl<Key>S: SavePositionProc() \n \
1042 :Ctrl<Key>C: CopyPositionProc() \n \
1043 :Ctrl<Key>V: PastePositionProc() \n \
1044 :Ctrl<Key>q: QuitProc() \n \
1045 :Ctrl<Key>w: MachineWhiteProc() \n \
1046 :Ctrl<Key>b: MachineBlackProc() \n \
1047 :Ctrl<Key>t: TwoMachinesProc() \n \
1048 :Ctrl<Key>a: AnalysisModeProc() \n \
1049 :Ctrl<Key>f: AnalyzeFileProc() \n \
1050 :Ctrl<Key>e: EditGameProc() \n \
1051 :Ctrl<Key>E: EditPositionProc() \n \
1052 :Meta<Key>O: EngineOutputProc() \n \
1053 :Meta<Key>E: EvalGraphProc() \n \
1054 :Meta<Key>G: ShowGameListProc() \n \
1055 :Meta<Key>H: ShowMoveListProc() \n \
1056 :<Key>Pause: PauseProc() \n \
1057 :<Key>F3: AcceptProc() \n \
1058 :<Key>F4: DeclineProc() \n \
1059 :<Key>F12: RematchProc() \n \
1060 :<Key>F5: CallFlagProc() \n \
1061 :<Key>F6: DrawProc() \n \
1062 :<Key>F7: AdjournProc() \n \
1063 :<Key>F8: AbortProc() \n \
1064 :<Key>F10: StopObservingProc() \n \
1065 :<Key>F11: StopExaminingProc() \n \
1066 :Meta Ctrl<Key>F12: DebugProc() \n \
1067 :Meta<Key>End: ToEndProc() \n \
1068 :Meta<Key>Right: ForwardProc() \n \
1069 :Meta<Key>Home: ToStartProc() \n \
1070 :Meta<Key>Left: BackwardProc() \n \
1071 :<Key>Home: RevertProc() \n \
1072 :<Key>End: TruncateGameProc() \n \
1073 :Ctrl<Key>m: MoveNowProc() \n \
1074 :Ctrl<Key>x: RetractMoveProc() \n \
1075 :Meta<Key>J: EngineMenuProc() \n \
1076 :Meta<Key>U: UciMenuProc() \n \
1077 :Meta<Key>T: TimeControlProc() \n \
1078 :Ctrl<Key>P: PonderNextMoveProc() \n "
1079 #ifndef OPTIONSDIALOG
1081 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1082 :Ctrl<Key>F: AutoflagProc() \n \
1083 :Ctrl<Key>A: AnimateMovingProc() \n \
1084 :Ctrl<Key>L: TestLegalityProc() \n \
1085 :Ctrl<Key>H: HideThinkingProc() \n "
1088 :<Key>-: Iconify() \n \
1089 :<Key>F1: ManProc() \n \
1090 :<Key>F2: FlipViewProc() \n \
1091 <KeyDown>.: BackwardProc() \n \
1092 <KeyUp>.: ForwardProc() \n \
1093 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1094 \"Send to chess program:\",,1) \n \
1095 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1096 \"Send to second chess program:\",,2) \n";
1098 char boardTranslations[] =
1099 "<Btn1Down>: HandleUserMove(0) \n \
1100 Shift<Btn1Up>: HandleUserMove(1) \n \
1101 <Btn1Up>: HandleUserMove(0) \n \
1102 <Btn1Motion>: AnimateUserMove() \n \
1103 <Btn3Motion>: HandlePV() \n \
1104 <Btn3Up>: PieceMenuPopup(menuB) \n \
1105 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1106 PieceMenuPopup(menuB) \n \
1107 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1108 PieceMenuPopup(menuW) \n \
1109 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1110 PieceMenuPopup(menuW) \n \
1111 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1112 PieceMenuPopup(menuB) \n";
1114 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1115 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1117 char ICSInputTranslations[] =
1118 "<Key>Up: UpKeyProc() \n "
1119 "<Key>Down: DownKeyProc() \n "
1120 "<Key>Return: EnterKeyProc() \n";
1122 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1123 // as the widget is destroyed before the up-click can call extend-end
1124 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1126 String xboardResources[] = {
1127 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1128 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1129 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1134 /* Max possible square size */
1135 #define MAXSQSIZE 256
1137 static int xpm_avail[MAXSQSIZE];
1139 #ifdef HAVE_DIR_STRUCT
1141 /* Extract piece size from filename */
1143 xpm_getsize(name, len, ext)
1154 if ((p=strchr(name, '.')) == NULL ||
1155 StrCaseCmp(p+1, ext) != 0)
1161 while (*p && isdigit(*p))
1168 /* Setup xpm_avail */
1170 xpm_getavail(dirname, ext)
1178 for (i=0; i<MAXSQSIZE; ++i)
1181 if (appData.debugMode)
1182 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1184 dir = opendir(dirname);
1187 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1188 programName, dirname);
1192 while ((ent=readdir(dir)) != NULL) {
1193 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1194 if (i > 0 && i < MAXSQSIZE)
1204 xpm_print_avail(fp, ext)
1210 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1211 for (i=1; i<MAXSQSIZE; ++i) {
1217 /* Return XPM piecesize closest to size */
1219 xpm_closest_to(dirname, size, ext)
1225 int sm_diff = MAXSQSIZE;
1229 xpm_getavail(dirname, ext);
1231 if (appData.debugMode)
1232 xpm_print_avail(stderr, ext);
1234 for (i=1; i<MAXSQSIZE; ++i) {
1237 diff = (diff<0) ? -diff : diff;
1238 if (diff < sm_diff) {
1246 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1252 #else /* !HAVE_DIR_STRUCT */
1253 /* If we are on a system without a DIR struct, we can't
1254 read the directory, so we can't collect a list of
1255 filenames, etc., so we can't do any size-fitting. */
1257 xpm_closest_to(dirname, size, ext)
1262 fprintf(stderr, _("\
1263 Warning: No DIR structure found on this system --\n\
1264 Unable to autosize for XPM/XIM pieces.\n\
1265 Please report this error to frankm@hiwaay.net.\n\
1266 Include system type & operating system in message.\n"));
1269 #endif /* HAVE_DIR_STRUCT */
1271 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1272 "magenta", "cyan", "white" };
1276 TextColors textColors[(int)NColorClasses];
1278 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1280 parse_color(str, which)
1284 char *p, buf[100], *d;
1287 if (strlen(str) > 99) /* watch bounds on buf */
1292 for (i=0; i<which; ++i) {
1299 /* Could be looking at something like:
1301 .. in which case we want to stop on a comma also */
1302 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1306 return -1; /* Use default for empty field */
1309 if (which == 2 || isdigit(*p))
1312 while (*p && isalpha(*p))
1317 for (i=0; i<8; ++i) {
1318 if (!StrCaseCmp(buf, cnames[i]))
1319 return which? (i+40) : (i+30);
1321 if (!StrCaseCmp(buf, "default")) return -1;
1323 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1328 parse_cpair(cc, str)
1332 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1333 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1338 /* bg and attr are optional */
1339 textColors[(int)cc].bg = parse_color(str, 1);
1340 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1341 textColors[(int)cc].attr = 0;
1347 /* Arrange to catch delete-window events */
1348 Atom wm_delete_window;
1350 CatchDeleteWindow(Widget w, String procname)
1353 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1354 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1355 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1362 XtSetArg(args[0], XtNiconic, False);
1363 XtSetValues(shellWidget, args, 1);
1365 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1368 //---------------------------------------------------------------------------------------------------------
1369 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1372 #define CW_USEDEFAULT (1<<31)
1373 #define ICS_TEXT_MENU_SIZE 90
1374 #define DEBUG_FILE "xboard.debug"
1375 #define SetCurrentDirectory chdir
1376 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1380 // these two must some day move to frontend.h, when they are implemented
1381 Boolean GameListIsUp();
1383 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1386 // front-end part of option handling
1388 // [HGM] This platform-dependent table provides the location for storing the color info
1389 extern char *crWhite, * crBlack;
1393 &appData.whitePieceColor,
1394 &appData.blackPieceColor,
1395 &appData.lightSquareColor,
1396 &appData.darkSquareColor,
1397 &appData.highlightSquareColor,
1398 &appData.premoveHighlightColor,
1399 &appData.lowTimeWarningColor,
1410 // [HGM] font: keep a font for each square size, even non-stndard ones
1411 #define NUM_SIZES 18
1412 #define MAX_SIZE 130
1413 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1414 char *fontTable[NUM_FONTS][MAX_SIZE];
1417 ParseFont(char *name, int number)
1418 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1420 if(sscanf(name, "size%d:", &size)) {
1421 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1422 // defer processing it until we know if it matches our board size
1423 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1424 fontTable[number][size] = strdup(strchr(name, ':')+1);
1425 fontValid[number][size] = True;
1430 case 0: // CLOCK_FONT
1431 appData.clockFont = strdup(name);
1433 case 1: // MESSAGE_FONT
1434 appData.font = strdup(name);
1436 case 2: // COORD_FONT
1437 appData.coordFont = strdup(name);
1442 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1447 { // only 2 fonts currently
1448 appData.clockFont = CLOCK_FONT_NAME;
1449 appData.coordFont = COORD_FONT_NAME;
1450 appData.font = DEFAULT_FONT_NAME;
1455 { // no-op, until we identify the code for this already in XBoard and move it here
1459 ParseColor(int n, char *name)
1460 { // in XBoard, just copy the color-name string
1461 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1465 ParseTextAttribs(ColorClass cc, char *s)
1467 (&appData.colorShout)[cc] = strdup(s);
1471 ParseBoardSize(void *addr, char *name)
1473 appData.boardSize = strdup(name);
1478 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1482 SetCommPortDefaults()
1483 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1486 // [HGM] args: these three cases taken out to stay in front-end
1488 SaveFontArg(FILE *f, ArgDescriptor *ad)
1491 int i, n = (int)(intptr_t)ad->argLoc;
1493 case 0: // CLOCK_FONT
1494 name = appData.clockFont;
1496 case 1: // MESSAGE_FONT
1497 name = appData.font;
1499 case 2: // COORD_FONT
1500 name = appData.coordFont;
1505 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1506 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1507 fontTable[n][squareSize] = strdup(name);
1508 fontValid[n][squareSize] = True;
1511 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1512 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1517 { // nothing to do, as the sounds are at all times represented by their text-string names already
1521 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1522 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1523 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1527 SaveColor(FILE *f, ArgDescriptor *ad)
1528 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1529 if(colorVariable[(int)(intptr_t)ad->argLoc])
1530 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1534 SaveBoardSize(FILE *f, char *name, void *addr)
1535 { // wrapper to shield back-end from BoardSize & sizeInfo
1536 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1540 ParseCommPortSettings(char *s)
1541 { // no such option in XBoard (yet)
1544 extern Widget engineOutputShell;
1547 GetActualPlacement(Widget wg, WindowPlacement *wp)
1557 XtSetArg(args[i], XtNx, &x); i++;
1558 XtSetArg(args[i], XtNy, &y); i++;
1559 XtSetArg(args[i], XtNwidth, &w); i++;
1560 XtSetArg(args[i], XtNheight, &h); i++;
1561 XtGetValues(wg, args, i);
1570 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1571 // In XBoard this will have to wait until awareness of window parameters is implemented
1572 GetActualPlacement(shellWidget, &wpMain);
1573 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1574 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1575 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1576 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1577 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1578 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1582 PrintCommPortSettings(FILE *f, char *name)
1583 { // This option does not exist in XBoard
1587 MySearchPath(char *installDir, char *name, char *fullname)
1588 { // just append installDir and name. Perhaps ExpandPath should be used here?
1589 name = ExpandPathName(name);
1590 if(name && name[0] == '/')
1591 safeStrCpy(fullname, name, MSG_SIZ );
1593 sprintf(fullname, "%s%c%s", installDir, '/', name);
1599 MyGetFullPathName(char *name, char *fullname)
1600 { // should use ExpandPath?
1601 name = ExpandPathName(name);
1602 safeStrCpy(fullname, name, MSG_SIZ );
1607 EnsureOnScreen(int *x, int *y, int minX, int minY)
1614 { // [HGM] args: allows testing if main window is realized from back-end
1615 return xBoardWindow != 0;
1619 PopUpStartupDialog()
1620 { // start menu not implemented in XBoard
1624 ConvertToLine(int argc, char **argv)
1626 static char line[128*1024], buf[1024];
1630 for(i=1; i<argc; i++)
1632 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1633 && argv[i][0] != '{' )
1634 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1636 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1637 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1640 line[strlen(line)-1] = NULLCHAR;
1644 //--------------------------------------------------------------------------------------------
1646 extern Boolean twoBoards, partnerUp;
1649 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1651 #define BoardSize int
1652 void InitDrawingSizes(BoardSize boardSize, int flags)
1653 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1654 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1656 XtGeometryResult gres;
1659 if(!formWidget) return;
1662 * Enable shell resizing.
1664 shellArgs[0].value = (XtArgVal) &w;
1665 shellArgs[1].value = (XtArgVal) &h;
1666 XtGetValues(shellWidget, shellArgs, 2);
1668 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1669 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1670 XtSetValues(shellWidget, &shellArgs[2], 4);
1672 XtSetArg(args[0], XtNdefaultDistance, &sep);
1673 XtGetValues(formWidget, args, 1);
1675 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1676 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1677 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1679 hOffset = boardWidth + 10;
1680 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1681 secondSegments[i] = gridSegments[i];
1682 secondSegments[i].x1 += hOffset;
1683 secondSegments[i].x2 += hOffset;
1686 XtSetArg(args[0], XtNwidth, boardWidth);
1687 XtSetArg(args[1], XtNheight, boardHeight);
1688 XtSetValues(boardWidget, args, 2);
1690 timerWidth = (boardWidth - sep) / 2;
1691 XtSetArg(args[0], XtNwidth, timerWidth);
1692 XtSetValues(whiteTimerWidget, args, 1);
1693 XtSetValues(blackTimerWidget, args, 1);
1695 XawFormDoLayout(formWidget, False);
1697 if (appData.titleInWindow) {
1699 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1700 XtSetArg(args[i], XtNheight, &h); i++;
1701 XtGetValues(titleWidget, args, i);
1703 w = boardWidth - 2*bor;
1705 XtSetArg(args[0], XtNwidth, &w);
1706 XtGetValues(menuBarWidget, args, 1);
1707 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1710 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1711 if (gres != XtGeometryYes && appData.debugMode) {
1713 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1714 programName, gres, w, h, wr, hr);
1718 XawFormDoLayout(formWidget, True);
1721 * Inhibit shell resizing.
1723 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1724 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1725 shellArgs[4].value = shellArgs[2].value = w;
1726 shellArgs[5].value = shellArgs[3].value = h;
1727 XtSetValues(shellWidget, &shellArgs[0], 6);
1729 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1732 for(i=0; i<4; i++) {
1734 for(p=0; p<=(int)WhiteKing; p++)
1735 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1736 if(gameInfo.variant == VariantShogi) {
1737 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1738 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1739 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1740 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1741 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1744 if(gameInfo.variant == VariantGothic) {
1745 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1748 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1749 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1750 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1753 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1754 for(p=0; p<=(int)WhiteKing; p++)
1755 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1756 if(gameInfo.variant == VariantShogi) {
1757 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1758 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1759 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1760 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1761 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1764 if(gameInfo.variant == VariantGothic) {
1765 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1768 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1769 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1770 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1775 for(i=0; i<2; i++) {
1777 for(p=0; p<=(int)WhiteKing; p++)
1778 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1779 if(gameInfo.variant == VariantShogi) {
1780 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1781 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1782 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1783 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1784 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1787 if(gameInfo.variant == VariantGothic) {
1788 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1791 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1792 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1793 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1803 void ParseIcsTextColors()
1804 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1805 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1806 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1807 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1808 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1809 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1810 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1811 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1812 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1813 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1814 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1816 if (appData.colorize) {
1818 _("%s: can't parse color names; disabling colorization\n"),
1821 appData.colorize = FALSE;
1826 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1827 XrmValue vFrom, vTo;
1828 int forceMono = False;
1830 if (!appData.monoMode) {
1831 vFrom.addr = (caddr_t) appData.lightSquareColor;
1832 vFrom.size = strlen(appData.lightSquareColor);
1833 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1834 if (vTo.addr == NULL) {
1835 appData.monoMode = True;
1838 lightSquareColor = *(Pixel *) vTo.addr;
1841 if (!appData.monoMode) {
1842 vFrom.addr = (caddr_t) appData.darkSquareColor;
1843 vFrom.size = strlen(appData.darkSquareColor);
1844 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1845 if (vTo.addr == NULL) {
1846 appData.monoMode = True;
1849 darkSquareColor = *(Pixel *) vTo.addr;
1852 if (!appData.monoMode) {
1853 vFrom.addr = (caddr_t) appData.whitePieceColor;
1854 vFrom.size = strlen(appData.whitePieceColor);
1855 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1856 if (vTo.addr == NULL) {
1857 appData.monoMode = True;
1860 whitePieceColor = *(Pixel *) vTo.addr;
1863 if (!appData.monoMode) {
1864 vFrom.addr = (caddr_t) appData.blackPieceColor;
1865 vFrom.size = strlen(appData.blackPieceColor);
1866 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1867 if (vTo.addr == NULL) {
1868 appData.monoMode = True;
1871 blackPieceColor = *(Pixel *) vTo.addr;
1875 if (!appData.monoMode) {
1876 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1877 vFrom.size = strlen(appData.highlightSquareColor);
1878 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1879 if (vTo.addr == NULL) {
1880 appData.monoMode = True;
1883 highlightSquareColor = *(Pixel *) vTo.addr;
1887 if (!appData.monoMode) {
1888 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1889 vFrom.size = strlen(appData.premoveHighlightColor);
1890 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1891 if (vTo.addr == NULL) {
1892 appData.monoMode = True;
1895 premoveHighlightColor = *(Pixel *) vTo.addr;
1906 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1907 XSetWindowAttributes window_attributes;
1909 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1910 XrmValue vFrom, vTo;
1911 XtGeometryResult gres;
1914 int forceMono = False;
1916 srandom(time(0)); // [HGM] book: make random truly random
1918 setbuf(stdout, NULL);
1919 setbuf(stderr, NULL);
1922 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1923 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1927 programName = strrchr(argv[0], '/');
1928 if (programName == NULL)
1929 programName = argv[0];
1934 XtSetLanguageProc(NULL, NULL, NULL);
1935 bindtextdomain(PACKAGE, LOCALEDIR);
1936 textdomain(PACKAGE);
1940 XtAppInitialize(&appContext, "XBoard", shellOptions,
1941 XtNumber(shellOptions),
1942 &argc, argv, xboardResources, NULL, 0);
1943 appData.boardSize = "";
1944 InitAppData(ConvertToLine(argc, argv));
1946 if (p == NULL) p = "/tmp";
1947 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1948 gameCopyFilename = (char*) malloc(i);
1949 gamePasteFilename = (char*) malloc(i);
1950 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1951 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1953 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1954 clientResources, XtNumber(clientResources),
1957 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1958 static char buf[MSG_SIZ];
1959 EscapeExpand(buf, appData.initString);
1960 appData.initString = strdup(buf);
1961 EscapeExpand(buf, appData.secondInitString);
1962 appData.secondInitString = strdup(buf);
1963 EscapeExpand(buf, appData.firstComputerString);
1964 appData.firstComputerString = strdup(buf);
1965 EscapeExpand(buf, appData.secondComputerString);
1966 appData.secondComputerString = strdup(buf);
1969 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1972 if (chdir(chessDir) != 0) {
1973 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1979 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1980 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1981 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1982 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1985 setbuf(debugFP, NULL);
1988 /* [HGM,HR] make sure board size is acceptable */
1989 if(appData.NrFiles > BOARD_FILES ||
1990 appData.NrRanks > BOARD_RANKS )
1991 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1994 /* This feature does not work; animation needs a rewrite */
1995 appData.highlightDragging = FALSE;
1999 xDisplay = XtDisplay(shellWidget);
2000 xScreen = DefaultScreen(xDisplay);
2001 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2003 gameInfo.variant = StringToVariant(appData.variant);
2004 InitPosition(FALSE);
2007 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2009 if (isdigit(appData.boardSize[0])) {
2010 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2011 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2012 &fontPxlSize, &smallLayout, &tinyLayout);
2014 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2015 programName, appData.boardSize);
2019 /* Find some defaults; use the nearest known size */
2020 SizeDefaults *szd, *nearest;
2021 int distance = 99999;
2022 nearest = szd = sizeDefaults;
2023 while (szd->name != NULL) {
2024 if (abs(szd->squareSize - squareSize) < distance) {
2026 distance = abs(szd->squareSize - squareSize);
2027 if (distance == 0) break;
2031 if (i < 2) lineGap = nearest->lineGap;
2032 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2033 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2034 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2035 if (i < 6) smallLayout = nearest->smallLayout;
2036 if (i < 7) tinyLayout = nearest->tinyLayout;
2039 SizeDefaults *szd = sizeDefaults;
2040 if (*appData.boardSize == NULLCHAR) {
2041 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2042 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2045 if (szd->name == NULL) szd--;
2046 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2048 while (szd->name != NULL &&
2049 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2050 if (szd->name == NULL) {
2051 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2052 programName, appData.boardSize);
2056 squareSize = szd->squareSize;
2057 lineGap = szd->lineGap;
2058 clockFontPxlSize = szd->clockFontPxlSize;
2059 coordFontPxlSize = szd->coordFontPxlSize;
2060 fontPxlSize = szd->fontPxlSize;
2061 smallLayout = szd->smallLayout;
2062 tinyLayout = szd->tinyLayout;
2063 // [HGM] font: use defaults from settings file if available and not overruled
2065 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2066 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2067 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2068 appData.font = fontTable[MESSAGE_FONT][squareSize];
2069 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2070 appData.coordFont = fontTable[COORD_FONT][squareSize];
2072 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2073 if (strlen(appData.pixmapDirectory) > 0) {
2074 p = ExpandPathName(appData.pixmapDirectory);
2076 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2077 appData.pixmapDirectory);
2080 if (appData.debugMode) {
2081 fprintf(stderr, _("\
2082 XBoard square size (hint): %d\n\
2083 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2085 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2086 if (appData.debugMode) {
2087 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2090 defaultLineGap = lineGap;
2091 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2093 /* [HR] height treated separately (hacked) */
2094 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2095 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2096 if (appData.showJail == 1) {
2097 /* Jail on top and bottom */
2098 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2099 XtSetArg(boardArgs[2], XtNheight,
2100 boardHeight + 2*(lineGap + squareSize));
2101 } else if (appData.showJail == 2) {
2103 XtSetArg(boardArgs[1], XtNwidth,
2104 boardWidth + 2*(lineGap + squareSize));
2105 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2108 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2109 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2113 * Determine what fonts to use.
2115 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2116 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2117 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2118 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2119 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2120 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2121 appData.font = FindFont(appData.font, fontPxlSize);
2122 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2123 countFontStruct = XQueryFont(xDisplay, countFontID);
2124 // appData.font = FindFont(appData.font, fontPxlSize);
2126 xdb = XtDatabase(xDisplay);
2127 XrmPutStringResource(&xdb, "*font", appData.font);
2130 * Detect if there are not enough colors available and adapt.
2132 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2133 appData.monoMode = True;
2136 forceMono = MakeColors();
2139 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2142 if (appData.bitmapDirectory == NULL ||
2143 appData.bitmapDirectory[0] == NULLCHAR)
2144 appData.bitmapDirectory = DEF_BITMAP_DIR;
2147 if (appData.lowTimeWarning && !appData.monoMode) {
2148 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2149 vFrom.size = strlen(appData.lowTimeWarningColor);
2150 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2151 if (vTo.addr == NULL)
2152 appData.monoMode = True;
2154 lowTimeWarningColor = *(Pixel *) vTo.addr;
2157 if (appData.monoMode && appData.debugMode) {
2158 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2159 (unsigned long) XWhitePixel(xDisplay, xScreen),
2160 (unsigned long) XBlackPixel(xDisplay, xScreen));
2163 ParseIcsTextColors();
2164 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2165 textColors[ColorNone].attr = 0;
2167 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2173 layoutName = "tinyLayout";
2174 } else if (smallLayout) {
2175 layoutName = "smallLayout";
2177 layoutName = "normalLayout";
2179 /* Outer layoutWidget is there only to provide a name for use in
2180 resources that depend on the layout style */
2182 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2183 layoutArgs, XtNumber(layoutArgs));
2185 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2186 formArgs, XtNumber(formArgs));
2187 XtSetArg(args[0], XtNdefaultDistance, &sep);
2188 XtGetValues(formWidget, args, 1);
2191 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2192 XtSetArg(args[0], XtNtop, XtChainTop);
2193 XtSetArg(args[1], XtNbottom, XtChainTop);
2194 XtSetArg(args[2], XtNright, XtChainLeft);
2195 XtSetValues(menuBarWidget, args, 3);
2197 widgetList[j++] = whiteTimerWidget =
2198 XtCreateWidget("whiteTime", labelWidgetClass,
2199 formWidget, timerArgs, XtNumber(timerArgs));
2200 XtSetArg(args[0], XtNfont, clockFontStruct);
2201 XtSetArg(args[1], XtNtop, XtChainTop);
2202 XtSetArg(args[2], XtNbottom, XtChainTop);
2203 XtSetValues(whiteTimerWidget, args, 3);
2205 widgetList[j++] = blackTimerWidget =
2206 XtCreateWidget("blackTime", labelWidgetClass,
2207 formWidget, timerArgs, XtNumber(timerArgs));
2208 XtSetArg(args[0], XtNfont, clockFontStruct);
2209 XtSetArg(args[1], XtNtop, XtChainTop);
2210 XtSetArg(args[2], XtNbottom, XtChainTop);
2211 XtSetValues(blackTimerWidget, args, 3);
2213 if (appData.titleInWindow) {
2214 widgetList[j++] = titleWidget =
2215 XtCreateWidget("title", labelWidgetClass, formWidget,
2216 titleArgs, XtNumber(titleArgs));
2217 XtSetArg(args[0], XtNtop, XtChainTop);
2218 XtSetArg(args[1], XtNbottom, XtChainTop);
2219 XtSetValues(titleWidget, args, 2);
2222 if (appData.showButtonBar) {
2223 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2224 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2225 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2226 XtSetArg(args[2], XtNtop, XtChainTop);
2227 XtSetArg(args[3], XtNbottom, XtChainTop);
2228 XtSetValues(buttonBarWidget, args, 4);
2231 widgetList[j++] = messageWidget =
2232 XtCreateWidget("message", labelWidgetClass, formWidget,
2233 messageArgs, XtNumber(messageArgs));
2234 XtSetArg(args[0], XtNtop, XtChainTop);
2235 XtSetArg(args[1], XtNbottom, XtChainTop);
2236 XtSetValues(messageWidget, args, 2);
2238 widgetList[j++] = boardWidget =
2239 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2240 XtNumber(boardArgs));
2242 XtManageChildren(widgetList, j);
2244 timerWidth = (boardWidth - sep) / 2;
2245 XtSetArg(args[0], XtNwidth, timerWidth);
2246 XtSetValues(whiteTimerWidget, args, 1);
2247 XtSetValues(blackTimerWidget, args, 1);
2249 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2250 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2251 XtGetValues(whiteTimerWidget, args, 2);
2253 if (appData.showButtonBar) {
2254 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2255 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2256 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2260 * formWidget uses these constraints but they are stored
2264 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2265 XtSetValues(menuBarWidget, args, i);
2266 if (appData.titleInWindow) {
2269 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2270 XtSetValues(whiteTimerWidget, args, i);
2272 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2273 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2274 XtSetValues(blackTimerWidget, args, i);
2276 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2277 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2278 XtSetValues(titleWidget, args, i);
2280 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2281 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2282 XtSetValues(messageWidget, args, i);
2283 if (appData.showButtonBar) {
2285 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2286 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2287 XtSetValues(buttonBarWidget, args, i);
2291 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2292 XtSetValues(whiteTimerWidget, args, i);
2294 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2295 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2296 XtSetValues(blackTimerWidget, args, i);
2298 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2299 XtSetValues(titleWidget, args, i);
2301 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2302 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2303 XtSetValues(messageWidget, args, i);
2304 if (appData.showButtonBar) {
2306 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2307 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2308 XtSetValues(buttonBarWidget, args, i);
2313 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2314 XtSetValues(whiteTimerWidget, args, i);
2316 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2317 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2318 XtSetValues(blackTimerWidget, args, i);
2320 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2321 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2322 XtSetValues(messageWidget, args, i);
2323 if (appData.showButtonBar) {
2325 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2326 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2327 XtSetValues(buttonBarWidget, args, i);
2331 XtSetArg(args[0], XtNfromVert, messageWidget);
2332 XtSetArg(args[1], XtNtop, XtChainTop);
2333 XtSetArg(args[2], XtNbottom, XtChainBottom);
2334 XtSetArg(args[3], XtNleft, XtChainLeft);
2335 XtSetArg(args[4], XtNright, XtChainRight);
2336 XtSetValues(boardWidget, args, 5);
2338 XtRealizeWidget(shellWidget);
2341 XtSetArg(args[0], XtNx, wpMain.x);
2342 XtSetArg(args[1], XtNy, wpMain.y);
2343 XtSetValues(shellWidget, args, 2);
2347 * Correct the width of the message and title widgets.
2348 * It is not known why some systems need the extra fudge term.
2349 * The value "2" is probably larger than needed.
2351 XawFormDoLayout(formWidget, False);
2353 #define WIDTH_FUDGE 2
2355 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2356 XtSetArg(args[i], XtNheight, &h); i++;
2357 XtGetValues(messageWidget, args, i);
2358 if (appData.showButtonBar) {
2360 XtSetArg(args[i], XtNwidth, &w); i++;
2361 XtGetValues(buttonBarWidget, args, i);
2362 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2364 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2367 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2368 if (gres != XtGeometryYes && appData.debugMode) {
2369 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2370 programName, gres, w, h, wr, hr);
2373 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2374 /* The size used for the child widget in layout lags one resize behind
2375 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2377 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2378 if (gres != XtGeometryYes && appData.debugMode) {
2379 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2380 programName, gres, w, h, wr, hr);
2383 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2384 XtSetArg(args[1], XtNright, XtChainRight);
2385 XtSetValues(messageWidget, args, 2);
2387 if (appData.titleInWindow) {
2389 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2390 XtSetArg(args[i], XtNheight, &h); i++;
2391 XtGetValues(titleWidget, args, i);
2393 w = boardWidth - 2*bor;
2395 XtSetArg(args[0], XtNwidth, &w);
2396 XtGetValues(menuBarWidget, args, 1);
2397 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2400 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2401 if (gres != XtGeometryYes && appData.debugMode) {
2403 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2404 programName, gres, w, h, wr, hr);
2407 XawFormDoLayout(formWidget, True);
2409 xBoardWindow = XtWindow(boardWidget);
2411 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2412 // not need to go into InitDrawingSizes().
2416 * Create X checkmark bitmap and initialize option menu checks.
2418 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2419 checkmark_bits, checkmark_width, checkmark_height);
2420 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2421 #ifndef OPTIONSDIALOG
2422 if (appData.alwaysPromoteToQueen) {
2423 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2426 if (appData.animateDragging) {
2427 XtSetValues(XtNameToWidget(menuBarWidget,
2428 "menuOptions.Animate Dragging"),
2431 if (appData.animate) {
2432 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2435 if (appData.autoCallFlag) {
2436 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2439 if (appData.autoFlipView) {
2440 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2443 if (appData.blindfold) {
2444 XtSetValues(XtNameToWidget(menuBarWidget,
2445 "menuOptions.Blindfold"), args, 1);
2447 if (appData.flashCount > 0) {
2448 XtSetValues(XtNameToWidget(menuBarWidget,
2449 "menuOptions.Flash Moves"),
2453 if (appData.highlightDragging) {
2454 XtSetValues(XtNameToWidget(menuBarWidget,
2455 "menuOptions.Highlight Dragging"),
2459 if (appData.highlightLastMove) {
2460 XtSetValues(XtNameToWidget(menuBarWidget,
2461 "menuOptions.Highlight Last Move"),
2464 if (appData.highlightMoveWithArrow) {
2465 XtSetValues(XtNameToWidget(menuBarWidget,
2466 "menuOptions.Arrow"),
2469 // if (appData.icsAlarm) {
2470 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2473 if (appData.ringBellAfterMoves) {
2474 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2477 if (appData.oneClick) {
2478 XtSetValues(XtNameToWidget(menuBarWidget,
2479 "menuOptions.OneClick"), args, 1);
2481 if (appData.periodicUpdates) {
2482 XtSetValues(XtNameToWidget(menuBarWidget,
2483 "menuOptions.Periodic Updates"), args, 1);
2485 if (appData.ponderNextMove) {
2486 XtSetValues(XtNameToWidget(menuBarWidget,
2487 "menuOptions.Ponder Next Move"), args, 1);
2489 if (appData.popupExitMessage) {
2490 XtSetValues(XtNameToWidget(menuBarWidget,
2491 "menuOptions.Popup Exit Message"), args, 1);
2493 if (appData.popupMoveErrors) {
2494 XtSetValues(XtNameToWidget(menuBarWidget,
2495 "menuOptions.Popup Move Errors"), args, 1);
2497 // if (appData.premove) {
2498 // XtSetValues(XtNameToWidget(menuBarWidget,
2499 // "menuOptions.Premove"), args, 1);
2501 if (appData.showCoords) {
2502 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2505 if (appData.hideThinkingFromHuman) {
2506 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2509 if (appData.testLegality) {
2510 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2514 if (saveSettingsOnExit) {
2515 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2522 ReadBitmap(&wIconPixmap, "icon_white.bm",
2523 icon_white_bits, icon_white_width, icon_white_height);
2524 ReadBitmap(&bIconPixmap, "icon_black.bm",
2525 icon_black_bits, icon_black_width, icon_black_height);
2526 iconPixmap = wIconPixmap;
2528 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2529 XtSetValues(shellWidget, args, i);
2532 * Create a cursor for the board widget.
2534 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2535 XChangeWindowAttributes(xDisplay, xBoardWindow,
2536 CWCursor, &window_attributes);
2539 * Inhibit shell resizing.
2541 shellArgs[0].value = (XtArgVal) &w;
2542 shellArgs[1].value = (XtArgVal) &h;
2543 XtGetValues(shellWidget, shellArgs, 2);
2544 shellArgs[4].value = shellArgs[2].value = w;
2545 shellArgs[5].value = shellArgs[3].value = h;
2546 XtSetValues(shellWidget, &shellArgs[2], 4);
2547 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2548 marginH = h - boardHeight;
2550 CatchDeleteWindow(shellWidget, "QuitProc");
2555 if (appData.bitmapDirectory[0] != NULLCHAR) {
2559 CreateXPMBoard(appData.liteBackTextureFile, 1);
2560 CreateXPMBoard(appData.darkBackTextureFile, 0);
2564 /* Create regular pieces */
2565 if (!useImages) CreatePieces();
2570 if (appData.animate || appData.animateDragging)
2573 XtAugmentTranslations(formWidget,
2574 XtParseTranslationTable(globalTranslations));
2575 XtAugmentTranslations(boardWidget,
2576 XtParseTranslationTable(boardTranslations));
2577 XtAugmentTranslations(whiteTimerWidget,
2578 XtParseTranslationTable(whiteTranslations));
2579 XtAugmentTranslations(blackTimerWidget,
2580 XtParseTranslationTable(blackTranslations));
2582 /* Why is the following needed on some versions of X instead
2583 * of a translation? */
2584 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2585 (XtEventHandler) EventProc, NULL);
2587 XtAddEventHandler(formWidget, KeyPressMask, False,
2588 (XtEventHandler) MoveTypeInProc, NULL);
2590 /* [AS] Restore layout */
2591 if( wpMoveHistory.visible ) {
2595 if( wpEvalGraph.visible )
2600 if( wpEngineOutput.visible ) {
2601 EngineOutputPopUp();
2606 if (errorExitStatus == -1) {
2607 if (appData.icsActive) {
2608 /* We now wait until we see "login:" from the ICS before
2609 sending the logon script (problems with timestamp otherwise) */
2610 /*ICSInitScript();*/
2611 if (appData.icsInputBox) ICSInputBoxPopUp();
2615 signal(SIGWINCH, TermSizeSigHandler);
2617 signal(SIGINT, IntSigHandler);
2618 signal(SIGTERM, IntSigHandler);
2619 if (*appData.cmailGameName != NULLCHAR) {
2620 signal(SIGUSR1, CmailSigHandler);
2623 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2625 XtSetKeyboardFocus(shellWidget, formWidget);
2627 XtAppMainLoop(appContext);
2628 if (appData.debugMode) fclose(debugFP); // [DM] debug
2635 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2636 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2638 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2639 unlink(gameCopyFilename);
2640 unlink(gamePasteFilename);
2643 RETSIGTYPE TermSizeSigHandler(int sig)
2656 CmailSigHandler(sig)
2662 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2664 /* Activate call-back function CmailSigHandlerCallBack() */
2665 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2667 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2671 CmailSigHandlerCallBack(isr, closure, message, count, error)
2679 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2681 /**** end signal code ****/
2687 /* try to open the icsLogon script, either in the location given
2688 * or in the users HOME directory
2695 f = fopen(appData.icsLogon, "r");
2698 homedir = getenv("HOME");
2699 if (homedir != NULL)
2701 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2702 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2703 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2704 f = fopen(buf, "r");
2709 ProcessICSInitScript(f);
2711 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2734 if (!menuBarWidget) return;
2735 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2737 DisplayError("menuEdit.Revert", 0);
2739 XtSetSensitive(w, !grey);
2741 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2743 DisplayError("menuEdit.Annotate", 0);
2745 XtSetSensitive(w, !grey);
2750 SetMenuEnables(enab)
2754 if (!menuBarWidget) return;
2755 while (enab->name != NULL) {
2756 w = XtNameToWidget(menuBarWidget, enab->name);
2758 DisplayError(enab->name, 0);
2760 XtSetSensitive(w, enab->value);
2766 Enables icsEnables[] = {
2767 { "menuFile.Mail Move", False },
2768 { "menuFile.Reload CMail Message", False },
2769 { "menuMode.Machine Black", False },
2770 { "menuMode.Machine White", False },
2771 { "menuMode.Analysis Mode", False },
2772 { "menuMode.Analyze File", False },
2773 { "menuMode.Two Machines", False },
2774 { "menuMode.Machine Match", False },
2776 { "menuEngine.Hint", False },
2777 { "menuEngine.Book", False },
2778 { "menuEngine.Move Now", False },
2779 #ifndef OPTIONSDIALOG
2780 { "menuOptions.Periodic Updates", False },
2781 { "menuOptions.Hide Thinking", False },
2782 { "menuOptions.Ponder Next Move", False },
2784 { "menuEngine.Engine #1 Settings", False },
2786 { "menuEngine.Engine #2 Settings", False },
2787 { "menuEdit.Annotate", False },
2791 Enables ncpEnables[] = {
2792 { "menuFile.Mail Move", False },
2793 { "menuFile.Reload CMail Message", False },
2794 { "menuMode.Machine White", False },
2795 { "menuMode.Machine Black", False },
2796 { "menuMode.Analysis Mode", False },
2797 { "menuMode.Analyze File", False },
2798 { "menuMode.Two Machines", False },
2799 { "menuMode.Machine Match", False },
2800 { "menuMode.ICS Client", False },
2801 { "menuView.ICStex", False },
2802 { "menuView.ICS Input Box", False },
2803 { "Action", False },
2804 { "menuEdit.Revert", False },
2805 { "menuEdit.Annotate", False },
2806 { "menuEngine.Engine #1 Settings", False },
2807 { "menuEngine.Engine #2 Settings", False },
2808 { "menuEngine.Move Now", False },
2809 { "menuEngine.Retract Move", False },
2810 { "menuOptions.ICS", False },
2811 #ifndef OPTIONSDIALOG
2812 { "menuOptions.Auto Flag", False },
2813 { "menuOptions.Auto Flip View", False },
2814 // { "menuOptions.ICS Alarm", False },
2815 { "menuOptions.Move Sound", False },
2816 { "menuOptions.Hide Thinking", False },
2817 { "menuOptions.Periodic Updates", False },
2818 { "menuOptions.Ponder Next Move", False },
2820 { "menuEngine.Hint", False },
2821 { "menuEngine.Book", False },
2825 Enables gnuEnables[] = {
2826 { "menuMode.ICS Client", False },
2827 { "menuView.ICStex", False },
2828 { "menuView.ICS Input Box", False },
2829 { "menuAction.Accept", False },
2830 { "menuAction.Decline", False },
2831 { "menuAction.Rematch", False },
2832 { "menuAction.Adjourn", False },
2833 { "menuAction.Stop Examining", False },
2834 { "menuAction.Stop Observing", False },
2835 { "menuAction.Upload to Examine", False },
2836 { "menuEdit.Revert", False },
2837 { "menuEdit.Annotate", False },
2838 { "menuOptions.ICS", False },
2840 /* The next two options rely on SetCmailMode being called *after* */
2841 /* SetGNUMode so that when GNU is being used to give hints these */
2842 /* menu options are still available */
2844 { "menuFile.Mail Move", False },
2845 { "menuFile.Reload CMail Message", False },
2849 Enables cmailEnables[] = {
2851 { "menuAction.Call Flag", False },
2852 { "menuAction.Draw", True },
2853 { "menuAction.Adjourn", False },
2854 { "menuAction.Abort", False },
2855 { "menuAction.Stop Observing", False },
2856 { "menuAction.Stop Examining", False },
2857 { "menuFile.Mail Move", True },
2858 { "menuFile.Reload CMail Message", True },
2862 Enables trainingOnEnables[] = {
2863 { "menuMode.Edit Comment", False },
2864 { "menuMode.Pause", False },
2865 { "menuEdit.Forward", False },
2866 { "menuEdit.Backward", False },
2867 { "menuEdit.Forward to End", False },
2868 { "menuEdit.Back to Start", False },
2869 { "menuEngine.Move Now", False },
2870 { "menuEdit.Truncate Game", False },
2874 Enables trainingOffEnables[] = {
2875 { "menuMode.Edit Comment", True },
2876 { "menuMode.Pause", True },
2877 { "menuEdit.Forward", True },
2878 { "menuEdit.Backward", True },
2879 { "menuEdit.Forward to End", True },
2880 { "menuEdit.Back to Start", True },
2881 { "menuEngine.Move Now", True },
2882 { "menuEdit.Truncate Game", True },
2886 Enables machineThinkingEnables[] = {
2887 { "menuFile.Load Game", False },
2888 // { "menuFile.Load Next Game", False },
2889 // { "menuFile.Load Previous Game", False },
2890 // { "menuFile.Reload Same Game", False },
2891 { "menuEdit.Paste Game", False },
2892 { "menuFile.Load Position", False },
2893 // { "menuFile.Load Next Position", False },
2894 // { "menuFile.Load Previous Position", False },
2895 // { "menuFile.Reload Same Position", False },
2896 { "menuEdit.Paste Position", False },
2897 { "menuMode.Machine White", False },
2898 { "menuMode.Machine Black", False },
2899 { "menuMode.Two Machines", False },
2900 { "menuMode.Machine Match", False },
2901 { "menuEngine.Retract Move", False },
2905 Enables userThinkingEnables[] = {
2906 { "menuFile.Load Game", True },
2907 // { "menuFile.Load Next Game", True },
2908 // { "menuFile.Load Previous Game", True },
2909 // { "menuFile.Reload Same Game", True },
2910 { "menuEdit.Paste Game", True },
2911 { "menuFile.Load Position", True },
2912 // { "menuFile.Load Next Position", True },
2913 // { "menuFile.Load Previous Position", True },
2914 // { "menuFile.Reload Same Position", True },
2915 { "menuEdit.Paste Position", True },
2916 { "menuMode.Machine White", True },
2917 { "menuMode.Machine Black", True },
2918 { "menuMode.Two Machines", True },
2919 { "menuMode.Machine Match", True },
2920 { "menuEngine.Retract Move", True },
2926 SetMenuEnables(icsEnables);
2929 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2930 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2937 SetMenuEnables(ncpEnables);
2943 SetMenuEnables(gnuEnables);
2949 SetMenuEnables(cmailEnables);
2955 SetMenuEnables(trainingOnEnables);
2956 if (appData.showButtonBar) {
2957 XtSetSensitive(buttonBarWidget, False);
2963 SetTrainingModeOff()
2965 SetMenuEnables(trainingOffEnables);
2966 if (appData.showButtonBar) {
2967 XtSetSensitive(buttonBarWidget, True);
2972 SetUserThinkingEnables()
2974 if (appData.noChessProgram) return;
2975 SetMenuEnables(userThinkingEnables);
2979 SetMachineThinkingEnables()
2981 if (appData.noChessProgram) return;
2982 SetMenuEnables(machineThinkingEnables);
2984 case MachinePlaysBlack:
2985 case MachinePlaysWhite:
2986 case TwoMachinesPlay:
2987 XtSetSensitive(XtNameToWidget(menuBarWidget,
2988 ModeToWidgetName(gameMode)), True);
2995 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2996 #define HISTORY_SIZE 64
2997 static char *history[HISTORY_SIZE];
2998 int histIn = 0, histP = 0;
3001 SaveInHistory(char *cmd)
3003 if (history[histIn] != NULL) {
3004 free(history[histIn]);
3005 history[histIn] = NULL;
3007 if (*cmd == NULLCHAR) return;
3008 history[histIn] = StrSave(cmd);
3009 histIn = (histIn + 1) % HISTORY_SIZE;
3010 if (history[histIn] != NULL) {
3011 free(history[histIn]);
3012 history[histIn] = NULL;
3018 PrevInHistory(char *cmd)
3021 if (histP == histIn) {
3022 if (history[histIn] != NULL) free(history[histIn]);
3023 history[histIn] = StrSave(cmd);
3025 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3026 if (newhp == histIn || history[newhp] == NULL) return NULL;
3028 return history[histP];
3034 if (histP == histIn) return NULL;
3035 histP = (histP + 1) % HISTORY_SIZE;
3036 return history[histP];
3038 // end of borrowed code
3040 #define Abs(n) ((n)<0 ? -(n) : (n))
3043 * Find a font that matches "pattern" that is as close as
3044 * possible to the targetPxlSize. Prefer fonts that are k
3045 * pixels smaller to fonts that are k pixels larger. The
3046 * pattern must be in the X Consortium standard format,
3047 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3048 * The return value should be freed with XtFree when no
3052 FindFont(pattern, targetPxlSize)
3056 char **fonts, *p, *best, *scalable, *scalableTail;
3057 int i, j, nfonts, minerr, err, pxlSize;
3060 char **missing_list;
3062 char *def_string, *base_fnt_lst, strInt[3];
3064 XFontStruct **fnt_list;
3066 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3067 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3068 p = strstr(pattern, "--");
3069 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3070 strcat(base_fnt_lst, strInt);
3071 strcat(base_fnt_lst, strchr(p + 2, '-'));
3073 if ((fntSet = XCreateFontSet(xDisplay,
3077 &def_string)) == NULL) {
3079 fprintf(stderr, _("Unable to create font set.\n"));
3083 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3085 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3087 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3088 programName, pattern);
3096 for (i=0; i<nfonts; i++) {
3099 if (*p != '-') continue;
3101 if (*p == NULLCHAR) break;
3102 if (*p++ == '-') j++;
3104 if (j < 7) continue;
3107 scalable = fonts[i];
3110 err = pxlSize - targetPxlSize;
3111 if (Abs(err) < Abs(minerr) ||
3112 (minerr > 0 && err < 0 && -err == minerr)) {
3118 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3119 /* If the error is too big and there is a scalable font,
3120 use the scalable font. */
3121 int headlen = scalableTail - scalable;
3122 p = (char *) XtMalloc(strlen(scalable) + 10);
3123 while (isdigit(*scalableTail)) scalableTail++;
3124 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3126 p = (char *) XtMalloc(strlen(best) + 2);
3127 safeStrCpy(p, best, strlen(best)+1 );
3129 if (appData.debugMode) {
3130 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3131 pattern, targetPxlSize, p);
3134 if (missing_count > 0)
3135 XFreeStringList(missing_list);
3136 XFreeFontSet(xDisplay, fntSet);
3138 XFreeFontNames(fonts);
3144 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3145 // must be called before all non-first callse to CreateGCs()
3146 XtReleaseGC(shellWidget, highlineGC);
3147 XtReleaseGC(shellWidget, lightSquareGC);
3148 XtReleaseGC(shellWidget, darkSquareGC);
3149 XtReleaseGC(shellWidget, lineGC);
3150 if (appData.monoMode) {
3151 if (DefaultDepth(xDisplay, xScreen) == 1) {
3152 XtReleaseGC(shellWidget, wbPieceGC);
3154 XtReleaseGC(shellWidget, bwPieceGC);
3157 XtReleaseGC(shellWidget, prelineGC);
3158 XtReleaseGC(shellWidget, jailSquareGC);
3159 XtReleaseGC(shellWidget, wdPieceGC);
3160 XtReleaseGC(shellWidget, wlPieceGC);
3161 XtReleaseGC(shellWidget, wjPieceGC);
3162 XtReleaseGC(shellWidget, bdPieceGC);
3163 XtReleaseGC(shellWidget, blPieceGC);
3164 XtReleaseGC(shellWidget, bjPieceGC);
3168 void CreateGCs(int redo)
3170 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3171 | GCBackground | GCFunction | GCPlaneMask;
3172 XGCValues gc_values;
3175 gc_values.plane_mask = AllPlanes;
3176 gc_values.line_width = lineGap;
3177 gc_values.line_style = LineSolid;
3178 gc_values.function = GXcopy;
3181 DeleteGCs(); // called a second time; clean up old GCs first
3182 } else { // [HGM] grid and font GCs created on first call only
3183 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3184 gc_values.background = XWhitePixel(xDisplay, xScreen);
3185 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3186 XSetFont(xDisplay, coordGC, coordFontID);
3188 // [HGM] make font for holdings counts (white on black)
3189 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3190 gc_values.background = XBlackPixel(xDisplay, xScreen);
3191 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3192 XSetFont(xDisplay, countGC, countFontID);
3194 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3195 gc_values.background = XBlackPixel(xDisplay, xScreen);
3196 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3198 if (appData.monoMode) {
3199 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3200 gc_values.background = XWhitePixel(xDisplay, xScreen);
3201 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3203 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3204 gc_values.background = XBlackPixel(xDisplay, xScreen);
3205 lightSquareGC = wbPieceGC
3206 = XtGetGC(shellWidget, value_mask, &gc_values);
3208 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3209 gc_values.background = XWhitePixel(xDisplay, xScreen);
3210 darkSquareGC = bwPieceGC
3211 = XtGetGC(shellWidget, value_mask, &gc_values);
3213 if (DefaultDepth(xDisplay, xScreen) == 1) {
3214 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3215 gc_values.function = GXcopyInverted;
3216 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3217 gc_values.function = GXcopy;
3218 if (XBlackPixel(xDisplay, xScreen) == 1) {
3219 bwPieceGC = darkSquareGC;
3220 wbPieceGC = copyInvertedGC;
3222 bwPieceGC = copyInvertedGC;
3223 wbPieceGC = lightSquareGC;
3227 gc_values.foreground = highlightSquareColor;
3228 gc_values.background = highlightSquareColor;
3229 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3231 gc_values.foreground = premoveHighlightColor;
3232 gc_values.background = premoveHighlightColor;
3233 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3235 gc_values.foreground = lightSquareColor;
3236 gc_values.background = darkSquareColor;
3237 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3239 gc_values.foreground = darkSquareColor;
3240 gc_values.background = lightSquareColor;
3241 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3243 gc_values.foreground = jailSquareColor;
3244 gc_values.background = jailSquareColor;
3245 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3247 gc_values.foreground = whitePieceColor;
3248 gc_values.background = darkSquareColor;
3249 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3251 gc_values.foreground = whitePieceColor;
3252 gc_values.background = lightSquareColor;
3253 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3255 gc_values.foreground = whitePieceColor;
3256 gc_values.background = jailSquareColor;
3257 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3259 gc_values.foreground = blackPieceColor;
3260 gc_values.background = darkSquareColor;
3261 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3263 gc_values.foreground = blackPieceColor;
3264 gc_values.background = lightSquareColor;
3265 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3267 gc_values.foreground = blackPieceColor;
3268 gc_values.background = jailSquareColor;
3269 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3273 void loadXIM(xim, xmask, filename, dest, mask)
3286 fp = fopen(filename, "rb");
3288 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3295 for (y=0; y<h; ++y) {
3296 for (x=0; x<h; ++x) {
3301 XPutPixel(xim, x, y, blackPieceColor);
3303 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3306 XPutPixel(xim, x, y, darkSquareColor);
3308 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3311 XPutPixel(xim, x, y, whitePieceColor);
3313 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3316 XPutPixel(xim, x, y, lightSquareColor);
3318 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3326 /* create Pixmap of piece */
3327 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3329 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3332 /* create Pixmap of clipmask
3333 Note: We assume the white/black pieces have the same
3334 outline, so we make only 6 masks. This is okay
3335 since the XPM clipmask routines do the same. */
3337 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3339 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3342 /* now create the 1-bit version */
3343 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3346 values.foreground = 1;
3347 values.background = 0;
3349 /* Don't use XtGetGC, not read only */
3350 maskGC = XCreateGC(xDisplay, *mask,
3351 GCForeground | GCBackground, &values);
3352 XCopyPlane(xDisplay, temp, *mask, maskGC,
3353 0, 0, squareSize, squareSize, 0, 0, 1);
3354 XFreePixmap(xDisplay, temp);
3359 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3361 void CreateXIMPieces()
3366 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3371 /* The XSynchronize calls were copied from CreatePieces.
3372 Not sure if needed, but can't hurt */
3373 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3376 /* temp needed by loadXIM() */
3377 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3378 0, 0, ss, ss, AllPlanes, XYPixmap);
3380 if (strlen(appData.pixmapDirectory) == 0) {
3384 if (appData.monoMode) {
3385 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3389 fprintf(stderr, _("\nLoading XIMs...\n"));
3391 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3392 fprintf(stderr, "%d", piece+1);
3393 for (kind=0; kind<4; kind++) {
3394 fprintf(stderr, ".");
3395 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3396 ExpandPathName(appData.pixmapDirectory),
3397 piece <= (int) WhiteKing ? "" : "w",
3398 pieceBitmapNames[piece],
3400 ximPieceBitmap[kind][piece] =
3401 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3402 0, 0, ss, ss, AllPlanes, XYPixmap);
3403 if (appData.debugMode)
3404 fprintf(stderr, _("(File:%s:) "), buf);
3405 loadXIM(ximPieceBitmap[kind][piece],
3407 &(xpmPieceBitmap2[kind][piece]),
3408 &(ximMaskPm2[piece]));
3409 if(piece <= (int)WhiteKing)
3410 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3412 fprintf(stderr," ");
3414 /* Load light and dark squares */
3415 /* If the LSQ and DSQ pieces don't exist, we will
3416 draw them with solid squares. */
3417 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3418 if (access(buf, 0) != 0) {
3422 fprintf(stderr, _("light square "));
3424 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3425 0, 0, ss, ss, AllPlanes, XYPixmap);
3426 if (appData.debugMode)
3427 fprintf(stderr, _("(File:%s:) "), buf);
3429 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3430 fprintf(stderr, _("dark square "));
3431 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3432 ExpandPathName(appData.pixmapDirectory), ss);
3433 if (appData.debugMode)
3434 fprintf(stderr, _("(File:%s:) "), buf);
3436 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3437 0, 0, ss, ss, AllPlanes, XYPixmap);
3438 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3439 xpmJailSquare = xpmLightSquare;
3441 fprintf(stderr, _("Done.\n"));
3443 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3446 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3449 void CreateXPMBoard(char *s, int kind)
3453 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3454 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3455 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3459 void FreeXPMPieces()
3460 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3461 // thisroutine has to be called t free the old piece pixmaps
3463 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3464 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3466 XFreePixmap(xDisplay, xpmLightSquare);
3467 XFreePixmap(xDisplay, xpmDarkSquare);
3471 void CreateXPMPieces()
3475 u_int ss = squareSize;
3477 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3478 XpmColorSymbol symbols[4];
3479 static int redo = False;
3481 if(redo) FreeXPMPieces(); else redo = 1;
3483 /* The XSynchronize calls were copied from CreatePieces.
3484 Not sure if needed, but can't hurt */
3485 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3487 /* Setup translations so piece colors match square colors */
3488 symbols[0].name = "light_piece";
3489 symbols[0].value = appData.whitePieceColor;
3490 symbols[1].name = "dark_piece";
3491 symbols[1].value = appData.blackPieceColor;
3492 symbols[2].name = "light_square";
3493 symbols[2].value = appData.lightSquareColor;
3494 symbols[3].name = "dark_square";
3495 symbols[3].value = appData.darkSquareColor;
3497 attr.valuemask = XpmColorSymbols;
3498 attr.colorsymbols = symbols;
3499 attr.numsymbols = 4;
3501 if (appData.monoMode) {
3502 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3506 if (strlen(appData.pixmapDirectory) == 0) {
3507 XpmPieces* pieces = builtInXpms;
3510 while (pieces->size != squareSize && pieces->size) pieces++;
3511 if (!pieces->size) {
3512 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3515 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3516 for (kind=0; kind<4; kind++) {
3518 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3519 pieces->xpm[piece][kind],
3520 &(xpmPieceBitmap2[kind][piece]),
3521 NULL, &attr)) != 0) {
3522 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3526 if(piece <= (int) WhiteKing)
3527 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3531 xpmJailSquare = xpmLightSquare;
3535 fprintf(stderr, _("\nLoading XPMs...\n"));
3538 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3539 fprintf(stderr, "%d ", piece+1);
3540 for (kind=0; kind<4; kind++) {
3541 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3542 ExpandPathName(appData.pixmapDirectory),
3543 piece > (int) WhiteKing ? "w" : "",
3544 pieceBitmapNames[piece],
3546 if (appData.debugMode) {
3547 fprintf(stderr, _("(File:%s:) "), buf);
3549 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3550 &(xpmPieceBitmap2[kind][piece]),
3551 NULL, &attr)) != 0) {
3552 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3553 // [HGM] missing: read of unorthodox piece failed; substitute King.
3554 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3555 ExpandPathName(appData.pixmapDirectory),
3557 if (appData.debugMode) {
3558 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3560 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3561 &(xpmPieceBitmap2[kind][piece]),
3565 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3570 if(piece <= (int) WhiteKing)
3571 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3574 /* Load light and dark squares */
3575 /* If the LSQ and DSQ pieces don't exist, we will
3576 draw them with solid squares. */
3577 fprintf(stderr, _("light square "));
3578 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3579 if (access(buf, 0) != 0) {
3583 if (appData.debugMode)
3584 fprintf(stderr, _("(File:%s:) "), buf);
3586 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3587 &xpmLightSquare, NULL, &attr)) != 0) {
3588 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3591 fprintf(stderr, _("dark square "));
3592 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3593 ExpandPathName(appData.pixmapDirectory), ss);
3594 if (appData.debugMode) {
3595 fprintf(stderr, _("(File:%s:) "), buf);
3597 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3598 &xpmDarkSquare, NULL, &attr)) != 0) {
3599 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3603 xpmJailSquare = xpmLightSquare;
3604 fprintf(stderr, _("Done.\n"));
3606 oldVariant = -1; // kludge to force re-makig of animation masks
3607 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3610 #endif /* HAVE_LIBXPM */
3613 /* No built-in bitmaps */
3618 u_int ss = squareSize;
3620 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3623 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3624 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3625 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3626 pieceBitmapNames[piece],
3627 ss, kind == SOLID ? 's' : 'o');
3628 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3629 if(piece <= (int)WhiteKing)
3630 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3634 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3638 /* With built-in bitmaps */
3641 BuiltInBits* bib = builtInBits;
3644 u_int ss = squareSize;
3646 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3649 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3651 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3652 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3653 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3654 pieceBitmapNames[piece],
3655 ss, kind == SOLID ? 's' : 'o');
3656 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3657 bib->bits[kind][piece], ss, ss);
3658 if(piece <= (int)WhiteKing)
3659 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3663 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3668 void ReadBitmap(pm, name, bits, wreq, hreq)
3671 unsigned char bits[];
3677 char msg[MSG_SIZ], fullname[MSG_SIZ];
3679 if (*appData.bitmapDirectory != NULLCHAR) {
3680 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3681 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3682 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3683 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3684 &w, &h, pm, &x_hot, &y_hot);
3685 fprintf(stderr, "load %s\n", name);
3686 if (errcode != BitmapSuccess) {
3688 case BitmapOpenFailed:
3689 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3691 case BitmapFileInvalid:
3692 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3694 case BitmapNoMemory:
3695 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3699 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3703 fprintf(stderr, _("%s: %s...using built-in\n"),
3705 } else if (w != wreq || h != hreq) {
3707 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3708 programName, fullname, w, h, wreq, hreq);
3714 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3723 if (lineGap == 0) return;
3725 /* [HR] Split this into 2 loops for non-square boards. */
3727 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3728 gridSegments[i].x1 = 0;
3729 gridSegments[i].x2 =
3730 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3731 gridSegments[i].y1 = gridSegments[i].y2
3732 = lineGap / 2 + (i * (squareSize + lineGap));
3735 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3736 gridSegments[j + i].y1 = 0;
3737 gridSegments[j + i].y2 =
3738 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3739 gridSegments[j + i].x1 = gridSegments[j + i].x2
3740 = lineGap / 2 + (j * (squareSize + lineGap));
3744 static void MenuBarSelect(w, addr, index)
3749 XtActionProc proc = (XtActionProc) addr;
3751 (proc)(NULL, NULL, NULL, NULL);
3754 void CreateMenuBarPopup(parent, name, mb)
3764 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3767 XtSetArg(args[j], XtNleftMargin, 20); j++;
3768 XtSetArg(args[j], XtNrightMargin, 20); j++;
3770 while (mi->string != NULL) {
3771 if (strcmp(mi->string, "----") == 0) {
3772 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3775 XtSetArg(args[j], XtNlabel, XtNewString(mi->string));
3776 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3778 XtAddCallback(entry, XtNcallback,
3779 (XtCallbackProc) MenuBarSelect,
3780 (caddr_t) mi->proc);
3786 Widget CreateMenuBar(mb)
3790 Widget anchor, menuBar;
3792 char menuName[MSG_SIZ];
3795 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3796 XtSetArg(args[j], XtNvSpace, 0); j++;
3797 XtSetArg(args[j], XtNborderWidth, 0); j++;
3798 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3799 formWidget, args, j);
3801 while (mb->name != NULL) {
3802 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3803 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3805 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3808 shortName[0] = mb->name[0];
3809 shortName[1] = NULLCHAR;
3810 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3813 XtSetArg(args[j], XtNlabel, XtNewString(mb->name)); j++;
3816 XtSetArg(args[j], XtNborderWidth, 0); j++;
3817 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3819 CreateMenuBarPopup(menuBar, menuName, mb);
3825 Widget CreateButtonBar(mi)
3829 Widget button, buttonBar;
3833 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3835 XtSetArg(args[j], XtNhSpace, 0); j++;
3837 XtSetArg(args[j], XtNborderWidth, 0); j++;
3838 XtSetArg(args[j], XtNvSpace, 0); j++;
3839 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3840 formWidget, args, j);
3842 while (mi->string != NULL) {
3845 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3846 XtSetArg(args[j], XtNborderWidth, 0); j++;
3848 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3849 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3850 buttonBar, args, j);
3851 XtAddCallback(button, XtNcallback,
3852 (XtCallbackProc) MenuBarSelect,
3853 (caddr_t) mi->proc);
3860 CreatePieceMenu(name, color)
3867 ChessSquare selection;
3869 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3870 boardWidget, args, 0);
3872 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3873 String item = pieceMenuStrings[color][i];
3875 if (strcmp(item, "----") == 0) {
3876 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3879 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3880 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3882 selection = pieceMenuTranslation[color][i];
3883 XtAddCallback(entry, XtNcallback,
3884 (XtCallbackProc) PieceMenuSelect,
3885 (caddr_t) selection);
3886 if (selection == WhitePawn || selection == BlackPawn) {
3887 XtSetArg(args[0], XtNpopupOnEntry, entry);
3888 XtSetValues(menu, args, 1);
3901 ChessSquare selection;
3903 whitePieceMenu = CreatePieceMenu("menuW", 0);
3904 blackPieceMenu = CreatePieceMenu("menuB", 1);
3906 XtRegisterGrabAction(PieceMenuPopup, True,
3907 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3908 GrabModeAsync, GrabModeAsync);
3910 XtSetArg(args[0], XtNlabel, _("Drop"));
3911 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3912 boardWidget, args, 1);
3913 for (i = 0; i < DROP_MENU_SIZE; i++) {
3914 String item = dropMenuStrings[i];
3916 if (strcmp(item, "----") == 0) {
3917 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3920 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3921 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3923 selection = dropMenuTranslation[i];
3924 XtAddCallback(entry, XtNcallback,
3925 (XtCallbackProc) DropMenuSelect,
3926 (caddr_t) selection);
3931 void SetupDropMenu()
3939 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3940 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3941 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3942 dmEnables[i].piece);
3943 XtSetSensitive(entry, p != NULL || !appData.testLegality
3944 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3945 && !appData.icsActive));
3947 while (p && *p++ == dmEnables[i].piece) count++;
3948 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3950 XtSetArg(args[j], XtNlabel, label); j++;
3951 XtSetValues(entry, args, j);
3955 void PieceMenuPopup(w, event, params, num_params)
3959 Cardinal *num_params;
3961 String whichMenu; int menuNr;
3962 shiftKey = strcmp(params[0], "menuW"); // used to indicate black
3963 if (event->type == ButtonRelease)
3964 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3965 else if (event->type == ButtonPress)
3966 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3968 case 0: whichMenu = params[0]; break;
3969 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3971 case -1: if (errorUp) ErrorPopDown();
3974 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3977 static void PieceMenuSelect(w, piece, junk)
3982 if (pmFromX < 0 || pmFromY < 0) return;
3983 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3986 static void DropMenuSelect(w, piece, junk)
3991 if (pmFromX < 0 || pmFromY < 0) return;
3992 DropMenuEvent(piece, pmFromX, pmFromY);
3995 void WhiteClock(w, event, prms, nprms)
4004 void BlackClock(w, event, prms, nprms)
4015 * If the user selects on a border boundary, return -1; if off the board,
4016 * return -2. Otherwise map the event coordinate to the square.
4018 int EventToSquare(x, limit)
4026 if ((x % (squareSize + lineGap)) >= squareSize)
4028 x /= (squareSize + lineGap);
4034 static void do_flash_delay(msec)
4040 static void drawHighlight(file, rank, gc)
4046 if (lineGap == 0) return;
4049 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4050 (squareSize + lineGap);
4051 y = lineGap/2 + rank * (squareSize + lineGap);
4053 x = lineGap/2 + file * (squareSize + lineGap);
4054 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4055 (squareSize + lineGap);
4058 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4059 squareSize+lineGap, squareSize+lineGap);
4062 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4063 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4066 SetHighlights(fromX, fromY, toX, toY)
4067 int fromX, fromY, toX, toY;
4069 if (hi1X != fromX || hi1Y != fromY) {
4070 if (hi1X >= 0 && hi1Y >= 0) {
4071 drawHighlight(hi1X, hi1Y, lineGC);
4073 } // [HGM] first erase both, then draw new!
4074 if (hi2X != toX || hi2Y != toY) {
4075 if (hi2X >= 0 && hi2Y >= 0) {
4076 drawHighlight(hi2X, hi2Y, lineGC);
4079 if (hi1X != fromX || hi1Y != fromY) {
4080 if (fromX >= 0 && fromY >= 0) {
4081 drawHighlight(fromX, fromY, highlineGC);
4084 if (hi2X != toX || hi2Y != toY) {
4085 if (toX >= 0 && toY >= 0) {
4086 drawHighlight(toX, toY, highlineGC);
4098 SetHighlights(-1, -1, -1, -1);
4103 SetPremoveHighlights(fromX, fromY, toX, toY)
4104 int fromX, fromY, toX, toY;
4106 if (pm1X != fromX || pm1Y != fromY) {
4107 if (pm1X >= 0 && pm1Y >= 0) {
4108 drawHighlight(pm1X, pm1Y, lineGC);
4110 if (fromX >= 0 && fromY >= 0) {
4111 drawHighlight(fromX, fromY, prelineGC);
4114 if (pm2X != toX || pm2Y != toY) {
4115 if (pm2X >= 0 && pm2Y >= 0) {
4116 drawHighlight(pm2X, pm2Y, lineGC);
4118 if (toX >= 0 && toY >= 0) {
4119 drawHighlight(toX, toY, prelineGC);
4129 ClearPremoveHighlights()
4131 SetPremoveHighlights(-1, -1, -1, -1);
4134 static int CutOutSquare(x, y, x0, y0, kind)
4135 int x, y, *x0, *y0, kind;
4137 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4138 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4140 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4141 if(textureW[kind] < W*squareSize)
4142 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4144 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4145 if(textureH[kind] < H*squareSize)
4146 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4148 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4152 static void BlankSquare(x, y, color, piece, dest, fac)
4153 int x, y, color, fac;
4156 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4158 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4159 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4160 squareSize, squareSize, x*fac, y*fac);
4162 if (useImages && useImageSqs) {
4166 pm = xpmLightSquare;
4171 case 2: /* neutral */
4176 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4177 squareSize, squareSize, x*fac, y*fac);
4187 case 2: /* neutral */
4192 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4197 I split out the routines to draw a piece so that I could
4198 make a generic flash routine.
4200 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4202 int square_color, x, y;
4205 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4206 switch (square_color) {
4208 case 2: /* neutral */
4210 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4211 ? *pieceToOutline(piece)
4212 : *pieceToSolid(piece),
4213 dest, bwPieceGC, 0, 0,
4214 squareSize, squareSize, x, y);
4217 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4218 ? *pieceToSolid(piece)
4219 : *pieceToOutline(piece),
4220 dest, wbPieceGC, 0, 0,
4221 squareSize, squareSize, x, y);
4226 static void monoDrawPiece(piece, square_color, x, y, dest)
4228 int square_color, x, y;
4231 switch (square_color) {
4233 case 2: /* neutral */
4235 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4236 ? *pieceToOutline(piece)
4237 : *pieceToSolid(piece),
4238 dest, bwPieceGC, 0, 0,
4239 squareSize, squareSize, x, y, 1);
4242 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4243 ? *pieceToSolid(piece)
4244 : *pieceToOutline(piece),
4245 dest, wbPieceGC, 0, 0,
4246 squareSize, squareSize, x, y, 1);