2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
66 # if HAVE_SYS_SOCKET_H
67 # include <sys/socket.h>
68 # include <netinet/in.h>
70 # else /* not HAVE_SYS_SOCKET_H */
71 # if HAVE_LAN_SOCKET_H
72 # include <lan/socket.h>
74 # include <lan/netdb.h>
75 # else /* not HAVE_LAN_SOCKET_H */
76 # define OMIT_SOCKETS 1
77 # endif /* not HAVE_LAN_SOCKET_H */
78 # endif /* not HAVE_SYS_SOCKET_H */
79 #endif /* !OMIT_SOCKETS */
84 #else /* not STDC_HEADERS */
85 extern char *getenv();
88 # else /* not HAVE_STRING_H */
90 # endif /* not HAVE_STRING_H */
91 #endif /* not STDC_HEADERS */
94 # include <sys/fcntl.h>
95 #else /* not HAVE_SYS_FCNTL_H */
98 # endif /* HAVE_FCNTL_H */
99 #endif /* not HAVE_SYS_FCNTL_H */
101 #if HAVE_SYS_SYSTEMINFO_H
102 # include <sys/systeminfo.h>
103 #endif /* HAVE_SYS_SYSTEMINFO_H */
105 #if TIME_WITH_SYS_TIME
106 # include <sys/time.h>
110 # include <sys/time.h>
121 # include <sys/wait.h>
126 # define NAMLEN(dirent) strlen((dirent)->d_name)
127 # define HAVE_DIR_STRUCT
129 # define dirent direct
130 # define NAMLEN(dirent) (dirent)->d_namlen
132 # include <sys/ndir.h>
133 # define HAVE_DIR_STRUCT
136 # include <sys/dir.h>
137 # define HAVE_DIR_STRUCT
141 # define HAVE_DIR_STRUCT
145 #include <X11/Intrinsic.h>
146 #include <X11/StringDefs.h>
147 #include <X11/Shell.h>
148 #include <X11/cursorfont.h>
149 #include <X11/Xatom.h>
150 #include <X11/Xmu/Atoms.h>
152 #include <X11/Xaw3d/Dialog.h>
153 #include <X11/Xaw3d/Form.h>
154 #include <X11/Xaw3d/List.h>
155 #include <X11/Xaw3d/Label.h>
156 #include <X11/Xaw3d/SimpleMenu.h>
157 #include <X11/Xaw3d/SmeBSB.h>
158 #include <X11/Xaw3d/SmeLine.h>
159 #include <X11/Xaw3d/Box.h>
160 #include <X11/Xaw3d/MenuButton.h>
161 #include <X11/Xaw3d/Text.h>
162 #include <X11/Xaw3d/AsciiText.h>
164 #include <X11/Xaw/Dialog.h>
165 #include <X11/Xaw/Form.h>
166 #include <X11/Xaw/List.h>
167 #include <X11/Xaw/Label.h>
168 #include <X11/Xaw/SimpleMenu.h>
169 #include <X11/Xaw/SmeBSB.h>
170 #include <X11/Xaw/SmeLine.h>
171 #include <X11/Xaw/Box.h>
172 #include <X11/Xaw/MenuButton.h>
173 #include <X11/Xaw/Text.h>
174 #include <X11/Xaw/AsciiText.h>
177 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
182 #include "pixmaps/pixmaps.h"
183 #define IMAGE_EXT "xpm"
185 #define IMAGE_EXT "xim"
186 #include "bitmaps/bitmaps.h"
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
195 #include "backendz.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
204 // must be moved to xengineoutput.h
206 void EngineOutputProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
208 void EvalGraphProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
216 #define usleep(t) _sleep2(((t)+500)/1000)
220 # define _(s) gettext (s)
221 # define N_(s) gettext_noop (s)
239 int main P((int argc, char **argv));
240 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
241 char *init_path, char *mode, int (*show_entry)(), char **name_return));
242 RETSIGTYPE CmailSigHandler P((int sig));
243 RETSIGTYPE IntSigHandler P((int sig));
244 RETSIGTYPE TermSizeSigHandler P((int sig));
245 void CreateGCs P((int redo));
246 void CreateXIMPieces P((void));
247 void CreateXPMPieces P((void));
248 void CreateXPMBoard P((char *s, int n));
249 void CreatePieces P((void));
250 void CreatePieceMenus P((void));
251 Widget CreateMenuBar P((Menu *mb));
252 Widget CreateButtonBar P ((MenuItem *mi));
253 char *FindFont P((char *pattern, int targetPxlSize));
254 void PieceMenuPopup P((Widget w, XEvent *event,
255 String *params, Cardinal *num_params));
256 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
257 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
259 u_int wreq, u_int hreq));
260 void CreateGrid P((void));
261 int EventToSquare P((int x, int limit));
262 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
263 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
264 void HandleUserMove P((Widget w, XEvent *event,
265 String *prms, Cardinal *nprms));
266 void AnimateUserMove P((Widget w, XEvent * event,
267 String * params, Cardinal * nParams));
268 void HandlePV P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void SelectPV P((Widget w, XEvent * event,
271 String * params, Cardinal * nParams));
272 void StopPV P((Widget w, XEvent * event,
273 String * params, Cardinal * nParams));
274 void WhiteClock P((Widget w, XEvent *event,
275 String *prms, Cardinal *nprms));
276 void BlackClock P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void DrawPositionProc P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
282 void CommentClick P((Widget w, XEvent * event,
283 String * params, Cardinal * nParams));
284 void CommentPopUp P((char *title, char *label));
285 void CommentPopDown P((void));
286 void CommentCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void ICSInputBoxPopUp P((void));
289 void ICSInputBoxPopDown P((void));
290 void FileNamePopUp P((char *label, char *def,
291 FileProc proc, char *openMode));
292 void FileNamePopDown P((void));
293 void FileNameCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void FileNameAction P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void AskQuestionReplyAction P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void AskQuestionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void AskQuestionPopDown P((void));
302 void PromotionPopDown P((void));
303 void PromotionCallback P((Widget w, XtPointer client_data,
304 XtPointer call_data));
305 void EditCommentPopDown P((void));
306 void EditCommentCallback P((Widget w, XtPointer client_data,
307 XtPointer call_data));
308 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
309 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
313 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
315 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
317 void LoadPositionProc P((Widget w, XEvent *event,
318 String *prms, Cardinal *nprms));
319 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
321 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
323 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
325 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
327 void PastePositionProc P((Widget w, XEvent *event, String *prms,
329 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void SavePositionProc P((Widget w, XEvent *event,
333 String *prms, Cardinal *nprms));
334 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
337 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
341 void MachineWhiteProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void AnalyzeModeProc P((Widget w, XEvent *event,
344 String *prms, Cardinal *nprms));
345 void AnalyzeFileProc P((Widget w, XEvent *event,
346 String *prms, Cardinal *nprms));
347 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
349 void IcsClientProc P((Widget w, XEvent *event, String *prms,
351 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EditPositionProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void EditCommentProc P((Widget w, XEvent *event,
356 String *prms, Cardinal *nprms));
357 void IcsInputBoxProc P((Widget w, XEvent *event,
358 String *prms, Cardinal *nprms));
359 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void StopObservingProc P((Widget w, XEvent *event, String *prms,
375 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
377 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
386 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
388 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
391 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
393 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
395 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
400 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
403 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
405 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
407 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
412 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
414 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
416 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
418 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
421 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
423 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
425 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
427 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
428 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void DisplayMove P((int moveNumber));
439 void DisplayTitle P((char *title));
440 void ICSInitScript P((void));
441 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
442 void ErrorPopUp P((char *title, char *text, int modal));
443 void ErrorPopDown P((void));
444 static char *ExpandPathName P((char *path));
445 static void CreateAnimVars P((void));
446 static void DragPieceMove P((int x, int y));
447 static void DrawDragPiece P((void));
448 char *ModeToWidgetName P((GameMode mode));
449 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
450 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void GameListOptionsPopDown P(());
463 void ShufflePopDown P(());
464 void UciPopDown P(());
465 void TimeControlPopDown P(());
466 void NewVariantPopDown P(());
467 void SettingsPopDown 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 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
522 Pixel timerForegroundPixel, timerBackgroundPixel;
523 Pixel buttonForegroundPixel, buttonBackgroundPixel;
524 char *chessDir, *programName, *programVersion,
525 *gameCopyFilename, *gamePasteFilename;
526 Boolean alwaysOnTop = False;
527 Boolean saveSettingsOnExit;
528 char *settingsFileName;
529 char *icsTextMenuString;
531 char *firstChessProgramNames;
532 char *secondChessProgramNames;
534 WindowPlacement wpMain;
535 WindowPlacement wpConsole;
536 WindowPlacement wpComment;
537 WindowPlacement wpMoveHistory;
538 WindowPlacement wpEvalGraph;
539 WindowPlacement wpEngineOutput;
540 WindowPlacement wpGameList;
541 WindowPlacement wpTags;
545 Pixmap pieceBitmap[2][(int)BlackPawn];
546 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
547 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
548 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
549 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
550 Pixmap xpmBoardBitmap[2];
551 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
552 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
553 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
554 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
555 XImage *ximLightSquare, *ximDarkSquare;
558 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
559 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
561 #define White(piece) ((int)(piece) < (int)BlackPawn)
563 /* Variables for doing smooth animation. This whole thing
564 would be much easier if the board was double-buffered,
565 but that would require a fairly major rewrite. */
570 GC blitGC, pieceGC, outlineGC;
571 XPoint startSquare, prevFrame, mouseDelta;
575 int startBoardX, startBoardY;
578 /* There can be two pieces being animated at once: a player
579 can begin dragging a piece before the remote opponent has moved. */
581 static AnimState game, player;
583 /* Bitmaps for use as masks when drawing XPM pieces.
584 Need one for each black and white piece. */
585 static Pixmap xpmMask[BlackKing + 1];
587 /* This magic number is the number of intermediate frames used
588 in each half of the animation. For short moves it's reduced
589 by 1. The total number of frames will be factor * 2 + 1. */
592 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
594 MenuItem fileMenu[] = {
595 {N_("New Game Ctrl+N"), "New Game", ResetProc},
596 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
597 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
598 {"----", NULL, NothingProc},
599 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
600 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
601 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
602 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
603 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
604 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
605 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
606 {"----", NULL, NothingProc},
607 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
608 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
609 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
610 {"----", NULL, NothingProc},
611 {N_("Mail Move"), "Mail Move", MailMoveProc},
612 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
613 {"----", NULL, NothingProc},
614 {N_("Quit Ctr+Q"), "Exit", QuitProc},
618 MenuItem editMenu[] = {
619 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
620 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
621 {"----", NULL, NothingProc},
622 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
623 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
624 {"----", NULL, NothingProc},
625 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
626 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
627 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
628 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
629 {"----", NULL, NothingProc},
630 {N_("Revert Home"), "Revert", RevertProc},
631 {N_("Annotate"), "Annotate", AnnotateProc},
632 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
633 {"----", NULL, NothingProc},
634 {N_("Backward Alt+Left"), "Backward", BackwardProc},
635 {N_("Forward Alt+Right"), "Forward", ForwardProc},
636 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
637 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
641 MenuItem viewMenu[] = {
642 {N_("Flip View F2"), "Flip View", FlipViewProc},
643 {"----", NULL, NothingProc},
644 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
645 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
646 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
647 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
648 {"----", NULL, NothingProc},
649 {N_("Tags"), "Show Tags", EditTagsProc},
650 {N_("Comments"), "Show Comments", EditCommentProc},
651 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
652 {"----", NULL, NothingProc},
653 {N_("Board..."), "Board Options", BoardOptionsProc},
654 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
658 MenuItem modeMenu[] = {
659 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
660 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
661 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
662 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
663 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
664 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
665 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
666 {N_("Training"), "Training", TrainingProc},
667 {N_("ICS Client"), "ICS Client", IcsClientProc},
668 {"----", NULL, NothingProc},
669 {N_("Pause Pause"), "Pause", PauseProc},
673 MenuItem actionMenu[] = {
674 {N_("Accept F3"), "Accept", AcceptProc},
675 {N_("Decline F4"), "Decline", DeclineProc},
676 {N_("Rematch F12"), "Rematch", RematchProc},
677 {"----", NULL, NothingProc},
678 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
679 {N_("Draw F6"), "Draw", DrawProc},
680 {N_("Adjourn F7"), "Adjourn", AdjournProc},
681 {N_("Abort F8"),"Abort", AbortProc},
682 {N_("Resign F9"), "Resign", ResignProc},
683 {"----", NULL, NothingProc},
684 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
685 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
686 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
687 {"----", NULL, NothingProc},
688 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
689 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
690 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
694 MenuItem engineMenu[] = {
695 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
696 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
697 {"----", NULL, NothingProc},
698 {N_("Hint"), "Hint", HintProc},
699 {N_("Book"), "Book", BookProc},
700 {"----", NULL, NothingProc},
701 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
702 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
706 MenuItem optionsMenu[] = {
707 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
708 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
709 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
710 {N_("ICS ..."), "ICS", IcsOptionsProc},
711 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
712 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
713 // {N_(" ..."), "", OptionsProc},
714 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
715 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
716 {"----", NULL, NothingProc},
717 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
718 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
719 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
720 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
721 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
722 {N_("Blindfold"), "Blindfold", BlindfoldProc},
723 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
725 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
727 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
728 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
729 {N_("Move Sound"), "Move Sound", MoveSoundProc},
730 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
731 {N_("One-Click Moving"), "OneClick", OneClickProc},
732 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
733 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
734 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
735 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
736 // {N_("Premove"), "Premove", PremoveProc},
737 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
738 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
739 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
740 {"----", NULL, NothingProc},
741 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
742 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
746 MenuItem helpMenu[] = {
747 {N_("Info XBoard"), "Info XBoard", InfoProc},
748 {N_("Man XBoard F1"), "Man XBoard", ManProc},
749 {"----", NULL, NothingProc},
750 {N_("About XBoard"), "About XBoard", AboutProc},
755 {N_("File"), "File", fileMenu},
756 {N_("Edit"), "Edit", editMenu},
757 {N_("View"), "View", viewMenu},
758 {N_("Mode"), "Mode", modeMenu},
759 {N_("Action"), "Action", actionMenu},
760 {N_("Engine"), "Engine", engineMenu},
761 {N_("Options"), "Options", optionsMenu},
762 {N_("Help"), "Help", helpMenu},
766 #define PAUSE_BUTTON "P"
767 MenuItem buttonBar[] = {
768 {"<<", "<<", ToStartProc},
769 {"<", "<", BackwardProc},
770 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
771 {">", ">", ForwardProc},
772 {">>", ">>", ToEndProc},
776 #define PIECE_MENU_SIZE 18
777 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
778 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
779 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
780 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
781 N_("Empty square"), N_("Clear board") },
782 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
783 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
784 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
785 N_("Empty square"), N_("Clear board") }
787 /* must be in same order as PieceMenuStrings! */
788 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
789 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
790 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
791 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
792 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
793 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
794 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
795 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
796 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
799 #define DROP_MENU_SIZE 6
800 String dropMenuStrings[DROP_MENU_SIZE] = {
801 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
803 /* must be in same order as PieceMenuStrings! */
804 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
805 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
806 WhiteRook, WhiteQueen
814 DropMenuEnables dmEnables[] = {
832 { XtNborderWidth, 0 },
833 { XtNdefaultDistance, 0 },
837 { XtNborderWidth, 0 },
838 { XtNresizable, (XtArgVal) True },
842 { XtNborderWidth, 0 },
848 { XtNjustify, (XtArgVal) XtJustifyRight },
849 { XtNlabel, (XtArgVal) "..." },
850 { XtNresizable, (XtArgVal) True },
851 { XtNresize, (XtArgVal) False }
854 Arg messageArgs[] = {
855 { XtNjustify, (XtArgVal) XtJustifyLeft },
856 { XtNlabel, (XtArgVal) "..." },
857 { XtNresizable, (XtArgVal) True },
858 { XtNresize, (XtArgVal) False }
862 { XtNborderWidth, 0 },
863 { XtNjustify, (XtArgVal) XtJustifyLeft }
866 XtResource clientResources[] = {
867 { "flashCount", "flashCount", XtRInt, sizeof(int),
868 XtOffset(AppDataPtr, flashCount), XtRImmediate,
869 (XtPointer) FLASH_COUNT },
872 XrmOptionDescRec shellOptions[] = {
873 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
874 { "-flash", "flashCount", XrmoptionNoArg, "3" },
875 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
878 XtActionsRec boardActions[] = {
879 { "DrawPosition", DrawPositionProc },
880 { "HandleUserMove", HandleUserMove },
881 { "AnimateUserMove", AnimateUserMove },
882 { "HandlePV", HandlePV },
883 { "SelectPV", SelectPV },
884 { "StopPV", StopPV },
885 { "FileNameAction", FileNameAction },
886 { "AskQuestionProc", AskQuestionProc },
887 { "AskQuestionReplyAction", AskQuestionReplyAction },
888 { "PieceMenuPopup", PieceMenuPopup },
889 { "WhiteClock", WhiteClock },
890 { "BlackClock", BlackClock },
891 { "Iconify", Iconify },
892 { "ResetProc", ResetProc },
893 { "NewVariantProc", NewVariantProc },
894 { "LoadGameProc", LoadGameProc },
895 { "LoadNextGameProc", LoadNextGameProc },
896 { "LoadPrevGameProc", LoadPrevGameProc },
897 { "LoadSelectedProc", LoadSelectedProc },
898 { "SetFilterProc", SetFilterProc },
899 { "ReloadGameProc", ReloadGameProc },
900 { "LoadPositionProc", LoadPositionProc },
901 { "LoadNextPositionProc", LoadNextPositionProc },
902 { "LoadPrevPositionProc", LoadPrevPositionProc },
903 { "ReloadPositionProc", ReloadPositionProc },
904 { "CopyPositionProc", CopyPositionProc },
905 { "PastePositionProc", PastePositionProc },
906 { "CopyGameProc", CopyGameProc },
907 { "PasteGameProc", PasteGameProc },
908 { "SaveGameProc", SaveGameProc },
909 { "SavePositionProc", SavePositionProc },
910 { "MailMoveProc", MailMoveProc },
911 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
912 { "QuitProc", QuitProc },
913 { "MachineWhiteProc", MachineWhiteProc },
914 { "MachineBlackProc", MachineBlackProc },
915 { "AnalysisModeProc", AnalyzeModeProc },
916 { "AnalyzeFileProc", AnalyzeFileProc },
917 { "TwoMachinesProc", TwoMachinesProc },
918 { "IcsClientProc", IcsClientProc },
919 { "EditGameProc", EditGameProc },
920 { "EditPositionProc", EditPositionProc },
921 { "TrainingProc", EditPositionProc },
922 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
923 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
924 { "ShowGameListProc", ShowGameListProc },
925 { "ShowMoveListProc", HistoryShowProc},
926 { "EditTagsProc", EditCommentProc },
927 { "EditCommentProc", EditCommentProc },
928 { "IcsInputBoxProc", IcsInputBoxProc },
929 { "PauseProc", PauseProc },
930 { "AcceptProc", AcceptProc },
931 { "DeclineProc", DeclineProc },
932 { "RematchProc", RematchProc },
933 { "CallFlagProc", CallFlagProc },
934 { "DrawProc", DrawProc },
935 { "AdjournProc", AdjournProc },
936 { "AbortProc", AbortProc },
937 { "ResignProc", ResignProc },
938 { "AdjuWhiteProc", AdjuWhiteProc },
939 { "AdjuBlackProc", AdjuBlackProc },
940 { "AdjuDrawProc", AdjuDrawProc },
941 { "EnterKeyProc", EnterKeyProc },
942 { "UpKeyProc", UpKeyProc },
943 { "DownKeyProc", DownKeyProc },
944 { "StopObservingProc", StopObservingProc },
945 { "StopExaminingProc", StopExaminingProc },
946 { "UploadProc", UploadProc },
947 { "BackwardProc", BackwardProc },
948 { "ForwardProc", ForwardProc },
949 { "ToStartProc", ToStartProc },
950 { "ToEndProc", ToEndProc },
951 { "RevertProc", RevertProc },
952 { "AnnotateProc", AnnotateProc },
953 { "TruncateGameProc", TruncateGameProc },
954 { "MoveNowProc", MoveNowProc },
955 { "RetractMoveProc", RetractMoveProc },
956 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
957 { "UciMenuProc", (XtActionProc) UciMenuProc },
958 { "TimeControlProc", (XtActionProc) TimeControlProc },
959 { "AlwaysQueenProc", AlwaysQueenProc },
960 { "AnimateDraggingProc", AnimateDraggingProc },
961 { "AnimateMovingProc", AnimateMovingProc },
962 { "AutoflagProc", AutoflagProc },
963 { "AutoflipProc", AutoflipProc },
964 { "BlindfoldProc", BlindfoldProc },
965 { "FlashMovesProc", FlashMovesProc },
966 { "FlipViewProc", FlipViewProc },
968 { "HighlightDraggingProc", HighlightDraggingProc },
970 { "HighlightLastMoveProc", HighlightLastMoveProc },
971 // { "IcsAlarmProc", IcsAlarmProc },
972 { "MoveSoundProc", MoveSoundProc },
973 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
974 { "PonderNextMoveProc", PonderNextMoveProc },
975 { "PopupExitMessageProc", PopupExitMessageProc },
976 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
977 // { "PremoveProc", PremoveProc },
978 { "ShowCoordsProc", ShowCoordsProc },
979 { "ShowThinkingProc", ShowThinkingProc },
980 { "HideThinkingProc", HideThinkingProc },
981 { "TestLegalityProc", TestLegalityProc },
982 { "SaveSettingsProc", SaveSettingsProc },
983 { "SaveOnExitProc", SaveOnExitProc },
984 { "InfoProc", InfoProc },
985 { "ManProc", ManProc },
986 { "HintProc", HintProc },
987 { "BookProc", BookProc },
988 { "AboutGameProc", AboutGameProc },
989 { "AboutProc", AboutProc },
990 { "DebugProc", DebugProc },
991 { "NothingProc", NothingProc },
992 { "CommentClick", (XtActionProc) CommentClick },
993 { "CommentPopDown", (XtActionProc) CommentPopDown },
994 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
995 { "TagsPopDown", (XtActionProc) TagsPopDown },
996 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
997 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
998 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
999 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1000 { "GameListPopDown", (XtActionProc) GameListPopDown },
1001 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1002 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1003 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1004 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1005 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1006 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1007 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1008 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1009 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1010 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1013 char globalTranslations[] =
1014 ":<Key>F9: ResignProc() \n \
1015 :Ctrl<Key>n: ResetProc() \n \
1016 :Meta<Key>V: NewVariantProc() \n \
1017 :Ctrl<Key>o: LoadGameProc() \n \
1018 :Meta<Key>Next: LoadNextGameProc() \n \
1019 :Meta<Key>Prior: LoadPrevGameProc() \n \
1020 :Ctrl<Key>s: SaveGameProc() \n \
1021 :Ctrl<Key>c: CopyGameProc() \n \
1022 :Ctrl<Key>v: PasteGameProc() \n \
1023 :Ctrl<Key>O: LoadPositionProc() \n \
1024 :Shift<Key>Next: LoadNextPositionProc() \n \
1025 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1026 :Ctrl<Key>S: SavePositionProc() \n \
1027 :Ctrl<Key>C: CopyPositionProc() \n \
1028 :Ctrl<Key>V: PastePositionProc() \n \
1029 :Ctrl<Key>q: QuitProc() \n \
1030 :Ctrl<Key>w: MachineWhiteProc() \n \
1031 :Ctrl<Key>b: MachineBlackProc() \n \
1032 :Ctrl<Key>t: TwoMachinesProc() \n \
1033 :Ctrl<Key>a: AnalysisModeProc() \n \
1034 :Ctrl<Key>f: AnalyzeFileProc() \n \
1035 :Ctrl<Key>e: EditGameProc() \n \
1036 :Ctrl<Key>E: EditPositionProc() \n \
1037 :Meta<Key>O: EngineOutputProc() \n \
1038 :Meta<Key>E: EvalGraphProc() \n \
1039 :Meta<Key>G: ShowGameListProc() \n \
1040 :Meta<Key>H: ShowMoveListProc() \n \
1041 :<Key>Pause: PauseProc() \n \
1042 :<Key>F3: AcceptProc() \n \
1043 :<Key>F4: DeclineProc() \n \
1044 :<Key>F12: RematchProc() \n \
1045 :<Key>F5: CallFlagProc() \n \
1046 :<Key>F6: DrawProc() \n \
1047 :<Key>F7: AdjournProc() \n \
1048 :<Key>F8: AbortProc() \n \
1049 :<Key>F10: StopObservingProc() \n \
1050 :<Key>F11: StopExaminingProc() \n \
1051 :Meta Ctrl<Key>F12: DebugProc() \n \
1052 :Meta<Key>End: ToEndProc() \n \
1053 :Meta<Key>Right: ForwardProc() \n \
1054 :Meta<Key>Home: ToStartProc() \n \
1055 :Meta<Key>Left: BackwardProc() \n \
1056 :<Key>Home: RevertProc() \n \
1057 :<Key>End: TruncateGameProc() \n \
1058 :Ctrl<Key>m: MoveNowProc() \n \
1059 :Ctrl<Key>x: RetractMoveProc() \n \
1060 :Meta<Key>J: EngineMenuProc() \n \
1061 :Meta<Key>U: UciMenuProc() \n \
1062 :Meta<Key>T: TimeControlProc() \n \
1063 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1064 :Ctrl<Key>F: AutoflagProc() \n \
1065 :Ctrl<Key>A: AnimateMovingProc() \n \
1066 :Ctrl<Key>P: PonderNextMoveProc() \n \
1067 :Ctrl<Key>L: TestLegalityProc() \n \
1068 :Ctrl<Key>H: HideThinkingProc() \n \
1069 :<Key>-: Iconify() \n \
1070 :<Key>F1: ManProc() \n \
1071 :<Key>F2: FlipViewProc() \n \
1072 <KeyDown>.: BackwardProc() \n \
1073 <KeyUp>.: ForwardProc() \n \
1074 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1075 \"Send to chess program:\",,1) \n \
1076 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1077 \"Send to second chess program:\",,2) \n";
1079 char boardTranslations[] =
1080 "<Btn1Down>: HandleUserMove(0) \n \
1081 Shift<Btn1Up>: HandleUserMove(1) \n \
1082 <Btn1Up>: HandleUserMove(0) \n \
1083 <Btn1Motion>: AnimateUserMove() \n \
1084 <Btn3Motion>: HandlePV() \n \
1085 <Btn3Up>: PieceMenuPopup(menuB) \n \
1086 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1087 PieceMenuPopup(menuB) \n \
1088 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1089 PieceMenuPopup(menuW) \n \
1090 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1091 PieceMenuPopup(menuW) \n \
1092 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1093 PieceMenuPopup(menuB) \n";
1095 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1096 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1098 char ICSInputTranslations[] =
1099 "<Key>Up: UpKeyProc() \n "
1100 "<Key>Down: DownKeyProc() \n "
1101 "<Key>Return: EnterKeyProc() \n";
1103 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1104 // as the widget is destroyed before the up-click can call extend-end
1105 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1107 String xboardResources[] = {
1108 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1109 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1110 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1115 /* Max possible square size */
1116 #define MAXSQSIZE 256
1118 static int xpm_avail[MAXSQSIZE];
1120 #ifdef HAVE_DIR_STRUCT
1122 /* Extract piece size from filename */
1124 xpm_getsize(name, len, ext)
1135 if ((p=strchr(name, '.')) == NULL ||
1136 StrCaseCmp(p+1, ext) != 0)
1142 while (*p && isdigit(*p))
1149 /* Setup xpm_avail */
1151 xpm_getavail(dirname, ext)
1159 for (i=0; i<MAXSQSIZE; ++i)
1162 if (appData.debugMode)
1163 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1165 dir = opendir(dirname);
1168 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1169 programName, dirname);
1173 while ((ent=readdir(dir)) != NULL) {
1174 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1175 if (i > 0 && i < MAXSQSIZE)
1185 xpm_print_avail(fp, ext)
1191 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1192 for (i=1; i<MAXSQSIZE; ++i) {
1198 /* Return XPM piecesize closest to size */
1200 xpm_closest_to(dirname, size, ext)
1206 int sm_diff = MAXSQSIZE;
1210 xpm_getavail(dirname, ext);
1212 if (appData.debugMode)
1213 xpm_print_avail(stderr, ext);
1215 for (i=1; i<MAXSQSIZE; ++i) {
1218 diff = (diff<0) ? -diff : diff;
1219 if (diff < sm_diff) {
1227 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1233 #else /* !HAVE_DIR_STRUCT */
1234 /* If we are on a system without a DIR struct, we can't
1235 read the directory, so we can't collect a list of
1236 filenames, etc., so we can't do any size-fitting. */
1238 xpm_closest_to(dirname, size, ext)
1243 fprintf(stderr, _("\
1244 Warning: No DIR structure found on this system --\n\
1245 Unable to autosize for XPM/XIM pieces.\n\
1246 Please report this error to frankm@hiwaay.net.\n\
1247 Include system type & operating system in message.\n"));
1250 #endif /* HAVE_DIR_STRUCT */
1252 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1253 "magenta", "cyan", "white" };
1257 TextColors textColors[(int)NColorClasses];
1259 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1261 parse_color(str, which)
1265 char *p, buf[100], *d;
1268 if (strlen(str) > 99) /* watch bounds on buf */
1273 for (i=0; i<which; ++i) {
1280 /* Could be looking at something like:
1282 .. in which case we want to stop on a comma also */
1283 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1287 return -1; /* Use default for empty field */
1290 if (which == 2 || isdigit(*p))
1293 while (*p && isalpha(*p))
1298 for (i=0; i<8; ++i) {
1299 if (!StrCaseCmp(buf, cnames[i]))
1300 return which? (i+40) : (i+30);
1302 if (!StrCaseCmp(buf, "default")) return -1;
1304 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1309 parse_cpair(cc, str)
1313 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1314 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1319 /* bg and attr are optional */
1320 textColors[(int)cc].bg = parse_color(str, 1);
1321 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1322 textColors[(int)cc].attr = 0;
1328 /* Arrange to catch delete-window events */
1329 Atom wm_delete_window;
1331 CatchDeleteWindow(Widget w, String procname)
1334 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1335 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1336 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1343 XtSetArg(args[0], XtNiconic, False);
1344 XtSetValues(shellWidget, args, 1);
1346 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1349 //---------------------------------------------------------------------------------------------------------
1350 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1353 #define CW_USEDEFAULT (1<<31)
1354 #define ICS_TEXT_MENU_SIZE 90
1355 #define DEBUG_FILE "xboard.debug"
1356 #define SetCurrentDirectory chdir
1357 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1361 // these two must some day move to frontend.h, when they are implemented
1362 Boolean GameListIsUp();
1364 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1367 // front-end part of option handling
1369 // [HGM] This platform-dependent table provides the location for storing the color info
1370 extern char *crWhite, * crBlack;
1374 &appData.whitePieceColor,
1375 &appData.blackPieceColor,
1376 &appData.lightSquareColor,
1377 &appData.darkSquareColor,
1378 &appData.highlightSquareColor,
1379 &appData.premoveHighlightColor,
1380 &appData.lowTimeWarningColor,
1391 // [HGM] font: keep a font for each square size, even non-stndard ones
1392 #define NUM_SIZES 18
1393 #define MAX_SIZE 130
1394 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1395 char *fontTable[NUM_FONTS][MAX_SIZE];
1398 ParseFont(char *name, int number)
1399 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1401 if(sscanf(name, "size%d:", &size)) {
1402 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1403 // defer processing it until we know if it matches our board size
1404 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1405 fontTable[number][size] = strdup(strchr(name, ':')+1);
1406 fontValid[number][size] = True;
1411 case 0: // CLOCK_FONT
1412 appData.clockFont = strdup(name);
1414 case 1: // MESSAGE_FONT
1415 appData.font = strdup(name);
1417 case 2: // COORD_FONT
1418 appData.coordFont = strdup(name);
1423 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1428 { // only 2 fonts currently
1429 appData.clockFont = CLOCK_FONT_NAME;
1430 appData.coordFont = COORD_FONT_NAME;
1431 appData.font = DEFAULT_FONT_NAME;
1436 { // no-op, until we identify the code for this already in XBoard and move it here
1440 ParseColor(int n, char *name)
1441 { // in XBoard, just copy the color-name string
1442 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1446 ParseTextAttribs(ColorClass cc, char *s)
1448 (&appData.colorShout)[cc] = strdup(s);
1452 ParseBoardSize(void *addr, char *name)
1454 appData.boardSize = strdup(name);
1459 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1463 SetCommPortDefaults()
1464 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1467 // [HGM] args: these three cases taken out to stay in front-end
1469 SaveFontArg(FILE *f, ArgDescriptor *ad)
1472 int i, n = (int)(intptr_t)ad->argLoc;
1474 case 0: // CLOCK_FONT
1475 name = appData.clockFont;
1477 case 1: // MESSAGE_FONT
1478 name = appData.font;
1480 case 2: // COORD_FONT
1481 name = appData.coordFont;
1486 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1487 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1488 fontTable[n][squareSize] = strdup(name);
1489 fontValid[n][squareSize] = True;
1492 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1493 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1498 { // nothing to do, as the sounds are at all times represented by their text-string names already
1502 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1503 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1504 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1508 SaveColor(FILE *f, ArgDescriptor *ad)
1509 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1510 if(colorVariable[(int)(intptr_t)ad->argLoc])
1511 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1515 SaveBoardSize(FILE *f, char *name, void *addr)
1516 { // wrapper to shield back-end from BoardSize & sizeInfo
1517 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1521 ParseCommPortSettings(char *s)
1522 { // no such option in XBoard (yet)
1525 extern Widget engineOutputShell;
1526 extern Widget tagsShell, editTagsShell;
1528 GetActualPlacement(Widget wg, WindowPlacement *wp)
1538 XtSetArg(args[i], XtNx, &x); i++;
1539 XtSetArg(args[i], XtNy, &y); i++;
1540 XtSetArg(args[i], XtNwidth, &w); i++;
1541 XtSetArg(args[i], XtNheight, &h); i++;
1542 XtGetValues(wg, args, i);
1551 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1552 // In XBoard this will have to wait until awareness of window parameters is implemented
1553 GetActualPlacement(shellWidget, &wpMain);
1554 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1555 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1556 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1557 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1558 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1559 else GetActualPlacement(editShell, &wpComment);
1560 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1561 else GetActualPlacement(editTagsShell, &wpTags);
1565 PrintCommPortSettings(FILE *f, char *name)
1566 { // This option does not exist in XBoard
1570 MySearchPath(char *installDir, char *name, char *fullname)
1571 { // just append installDir and name. Perhaps ExpandPath should be used here?
1572 name = ExpandPathName(name);
1573 if(name && name[0] == '/')
1574 safeStrCpy(fullname, name, MSG_SIZ );
1576 sprintf(fullname, "%s%c%s", installDir, '/', name);
1582 MyGetFullPathName(char *name, char *fullname)
1583 { // should use ExpandPath?
1584 name = ExpandPathName(name);
1585 safeStrCpy(fullname, name, MSG_SIZ );
1590 EnsureOnScreen(int *x, int *y, int minX, int minY)
1597 { // [HGM] args: allows testing if main window is realized from back-end
1598 return xBoardWindow != 0;
1602 PopUpStartupDialog()
1603 { // start menu not implemented in XBoard
1607 ConvertToLine(int argc, char **argv)
1609 static char line[128*1024], buf[1024];
1613 for(i=1; i<argc; i++)
1615 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1616 && argv[i][0] != '{' )
1617 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1619 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1620 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1623 line[strlen(line)-1] = NULLCHAR;
1627 //--------------------------------------------------------------------------------------------
1629 extern Boolean twoBoards, partnerUp;
1632 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1634 #define BoardSize int
1635 void InitDrawingSizes(BoardSize boardSize, int flags)
1636 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1637 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1639 XtGeometryResult gres;
1642 if(!formWidget) return;
1645 * Enable shell resizing.
1647 shellArgs[0].value = (XtArgVal) &w;
1648 shellArgs[1].value = (XtArgVal) &h;
1649 XtGetValues(shellWidget, shellArgs, 2);
1651 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1652 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1653 XtSetValues(shellWidget, &shellArgs[2], 4);
1655 XtSetArg(args[0], XtNdefaultDistance, &sep);
1656 XtGetValues(formWidget, args, 1);
1658 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1659 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1660 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1662 hOffset = boardWidth + 10;
1663 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1664 secondSegments[i] = gridSegments[i];
1665 secondSegments[i].x1 += hOffset;
1666 secondSegments[i].x2 += hOffset;
1669 XtSetArg(args[0], XtNwidth, boardWidth);
1670 XtSetArg(args[1], XtNheight, boardHeight);
1671 XtSetValues(boardWidget, args, 2);
1673 timerWidth = (boardWidth - sep) / 2;
1674 XtSetArg(args[0], XtNwidth, timerWidth);
1675 XtSetValues(whiteTimerWidget, args, 1);
1676 XtSetValues(blackTimerWidget, args, 1);
1678 XawFormDoLayout(formWidget, False);
1680 if (appData.titleInWindow) {
1682 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1683 XtSetArg(args[i], XtNheight, &h); i++;
1684 XtGetValues(titleWidget, args, i);
1686 w = boardWidth - 2*bor;
1688 XtSetArg(args[0], XtNwidth, &w);
1689 XtGetValues(menuBarWidget, args, 1);
1690 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1693 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1694 if (gres != XtGeometryYes && appData.debugMode) {
1696 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1697 programName, gres, w, h, wr, hr);
1701 XawFormDoLayout(formWidget, True);
1704 * Inhibit shell resizing.
1706 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1707 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1708 shellArgs[4].value = shellArgs[2].value = w;
1709 shellArgs[5].value = shellArgs[3].value = h;
1710 XtSetValues(shellWidget, &shellArgs[0], 6);
1712 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1715 for(i=0; i<4; i++) {
1717 for(p=0; p<=(int)WhiteKing; p++)
1718 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1719 if(gameInfo.variant == VariantShogi) {
1720 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1721 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1722 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1723 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1724 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1727 if(gameInfo.variant == VariantGothic) {
1728 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1731 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1732 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1733 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1736 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1737 for(p=0; p<=(int)WhiteKing; p++)
1738 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1739 if(gameInfo.variant == VariantShogi) {
1740 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1741 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1742 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1743 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1744 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1747 if(gameInfo.variant == VariantGothic) {
1748 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1751 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1752 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1753 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1758 for(i=0; i<2; i++) {
1760 for(p=0; p<=(int)WhiteKing; p++)
1761 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1762 if(gameInfo.variant == VariantShogi) {
1763 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1764 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1765 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1766 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1767 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1770 if(gameInfo.variant == VariantGothic) {
1771 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1774 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1775 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1776 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1786 void ParseIcsTextColors()
1787 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1788 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1789 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1790 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1791 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1792 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1793 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1794 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1795 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1796 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1797 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1799 if (appData.colorize) {
1801 _("%s: can't parse color names; disabling colorization\n"),
1804 appData.colorize = FALSE;
1809 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1810 XrmValue vFrom, vTo;
1811 int forceMono = False;
1813 if (!appData.monoMode) {
1814 vFrom.addr = (caddr_t) appData.lightSquareColor;
1815 vFrom.size = strlen(appData.lightSquareColor);
1816 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1817 if (vTo.addr == NULL) {
1818 appData.monoMode = True;
1821 lightSquareColor = *(Pixel *) vTo.addr;
1824 if (!appData.monoMode) {
1825 vFrom.addr = (caddr_t) appData.darkSquareColor;
1826 vFrom.size = strlen(appData.darkSquareColor);
1827 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1828 if (vTo.addr == NULL) {
1829 appData.monoMode = True;
1832 darkSquareColor = *(Pixel *) vTo.addr;
1835 if (!appData.monoMode) {
1836 vFrom.addr = (caddr_t) appData.whitePieceColor;
1837 vFrom.size = strlen(appData.whitePieceColor);
1838 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1839 if (vTo.addr == NULL) {
1840 appData.monoMode = True;
1843 whitePieceColor = *(Pixel *) vTo.addr;
1846 if (!appData.monoMode) {
1847 vFrom.addr = (caddr_t) appData.blackPieceColor;
1848 vFrom.size = strlen(appData.blackPieceColor);
1849 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1850 if (vTo.addr == NULL) {
1851 appData.monoMode = True;
1854 blackPieceColor = *(Pixel *) vTo.addr;
1858 if (!appData.monoMode) {
1859 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1860 vFrom.size = strlen(appData.highlightSquareColor);
1861 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1862 if (vTo.addr == NULL) {
1863 appData.monoMode = True;
1866 highlightSquareColor = *(Pixel *) vTo.addr;
1870 if (!appData.monoMode) {
1871 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1872 vFrom.size = strlen(appData.premoveHighlightColor);
1873 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1874 if (vTo.addr == NULL) {
1875 appData.monoMode = True;
1878 premoveHighlightColor = *(Pixel *) vTo.addr;
1889 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1890 XSetWindowAttributes window_attributes;
1892 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1893 XrmValue vFrom, vTo;
1894 XtGeometryResult gres;
1897 int forceMono = False;
1899 srandom(time(0)); // [HGM] book: make random truly random
1901 setbuf(stdout, NULL);
1902 setbuf(stderr, NULL);
1905 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1906 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1910 programName = strrchr(argv[0], '/');
1911 if (programName == NULL)
1912 programName = argv[0];
1917 XtSetLanguageProc(NULL, NULL, NULL);
1918 bindtextdomain(PACKAGE, LOCALEDIR);
1919 textdomain(PACKAGE);
1923 XtAppInitialize(&appContext, "XBoard", shellOptions,
1924 XtNumber(shellOptions),
1925 &argc, argv, xboardResources, NULL, 0);
1926 appData.boardSize = "";
1927 InitAppData(ConvertToLine(argc, argv));
1929 if (p == NULL) p = "/tmp";
1930 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1931 gameCopyFilename = (char*) malloc(i);
1932 gamePasteFilename = (char*) malloc(i);
1933 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1934 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1936 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1937 clientResources, XtNumber(clientResources),
1940 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1941 static char buf[MSG_SIZ];
1942 EscapeExpand(buf, appData.initString);
1943 appData.initString = strdup(buf);
1944 EscapeExpand(buf, appData.secondInitString);
1945 appData.secondInitString = strdup(buf);
1946 EscapeExpand(buf, appData.firstComputerString);
1947 appData.firstComputerString = strdup(buf);
1948 EscapeExpand(buf, appData.secondComputerString);
1949 appData.secondComputerString = strdup(buf);
1952 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1955 if (chdir(chessDir) != 0) {
1956 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1962 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1963 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1964 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1965 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1968 setbuf(debugFP, NULL);
1971 /* [HGM,HR] make sure board size is acceptable */
1972 if(appData.NrFiles > BOARD_FILES ||
1973 appData.NrRanks > BOARD_RANKS )
1974 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1977 /* This feature does not work; animation needs a rewrite */
1978 appData.highlightDragging = FALSE;
1982 xDisplay = XtDisplay(shellWidget);
1983 xScreen = DefaultScreen(xDisplay);
1984 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1986 gameInfo.variant = StringToVariant(appData.variant);
1987 InitPosition(FALSE);
1990 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1992 if (isdigit(appData.boardSize[0])) {
1993 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1994 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1995 &fontPxlSize, &smallLayout, &tinyLayout);
1997 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1998 programName, appData.boardSize);
2002 /* Find some defaults; use the nearest known size */
2003 SizeDefaults *szd, *nearest;
2004 int distance = 99999;
2005 nearest = szd = sizeDefaults;
2006 while (szd->name != NULL) {
2007 if (abs(szd->squareSize - squareSize) < distance) {
2009 distance = abs(szd->squareSize - squareSize);
2010 if (distance == 0) break;
2014 if (i < 2) lineGap = nearest->lineGap;
2015 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2016 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2017 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2018 if (i < 6) smallLayout = nearest->smallLayout;
2019 if (i < 7) tinyLayout = nearest->tinyLayout;
2022 SizeDefaults *szd = sizeDefaults;
2023 if (*appData.boardSize == NULLCHAR) {
2024 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2025 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2028 if (szd->name == NULL) szd--;
2029 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2031 while (szd->name != NULL &&
2032 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2033 if (szd->name == NULL) {
2034 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2035 programName, appData.boardSize);
2039 squareSize = szd->squareSize;
2040 lineGap = szd->lineGap;
2041 clockFontPxlSize = szd->clockFontPxlSize;
2042 coordFontPxlSize = szd->coordFontPxlSize;
2043 fontPxlSize = szd->fontPxlSize;
2044 smallLayout = szd->smallLayout;
2045 tinyLayout = szd->tinyLayout;
2046 // [HGM] font: use defaults from settings file if available and not overruled
2048 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2049 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2050 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2051 appData.font = fontTable[MESSAGE_FONT][squareSize];
2052 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2053 appData.coordFont = fontTable[COORD_FONT][squareSize];
2055 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2056 if (strlen(appData.pixmapDirectory) > 0) {
2057 p = ExpandPathName(appData.pixmapDirectory);
2059 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2060 appData.pixmapDirectory);
2063 if (appData.debugMode) {
2064 fprintf(stderr, _("\
2065 XBoard square size (hint): %d\n\
2066 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2068 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2069 if (appData.debugMode) {
2070 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2073 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2075 /* [HR] height treated separately (hacked) */
2076 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2077 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2078 if (appData.showJail == 1) {
2079 /* Jail on top and bottom */
2080 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2081 XtSetArg(boardArgs[2], XtNheight,
2082 boardHeight + 2*(lineGap + squareSize));
2083 } else if (appData.showJail == 2) {
2085 XtSetArg(boardArgs[1], XtNwidth,
2086 boardWidth + 2*(lineGap + squareSize));
2087 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2090 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2091 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2095 * Determine what fonts to use.
2097 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2098 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2099 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2100 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2101 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2102 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2103 appData.font = FindFont(appData.font, fontPxlSize);
2104 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2105 countFontStruct = XQueryFont(xDisplay, countFontID);
2106 // appData.font = FindFont(appData.font, fontPxlSize);
2108 xdb = XtDatabase(xDisplay);
2109 XrmPutStringResource(&xdb, "*font", appData.font);
2112 * Detect if there are not enough colors available and adapt.
2114 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2115 appData.monoMode = True;
2118 forceMono = MakeColors();
2121 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2124 if (appData.bitmapDirectory == NULL ||
2125 appData.bitmapDirectory[0] == NULLCHAR)
2126 appData.bitmapDirectory = DEF_BITMAP_DIR;
2129 if (appData.lowTimeWarning && !appData.monoMode) {
2130 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2131 vFrom.size = strlen(appData.lowTimeWarningColor);
2132 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2133 if (vTo.addr == NULL)
2134 appData.monoMode = True;
2136 lowTimeWarningColor = *(Pixel *) vTo.addr;
2139 if (appData.monoMode && appData.debugMode) {
2140 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2141 (unsigned long) XWhitePixel(xDisplay, xScreen),
2142 (unsigned long) XBlackPixel(xDisplay, xScreen));
2145 ParseIcsTextColors();
2146 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2147 textColors[ColorNone].attr = 0;
2149 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2155 layoutName = "tinyLayout";
2156 } else if (smallLayout) {
2157 layoutName = "smallLayout";
2159 layoutName = "normalLayout";
2161 /* Outer layoutWidget is there only to provide a name for use in
2162 resources that depend on the layout style */
2164 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2165 layoutArgs, XtNumber(layoutArgs));
2167 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2168 formArgs, XtNumber(formArgs));
2169 XtSetArg(args[0], XtNdefaultDistance, &sep);
2170 XtGetValues(formWidget, args, 1);
2173 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2174 XtSetArg(args[0], XtNtop, XtChainTop);
2175 XtSetArg(args[1], XtNbottom, XtChainTop);
2176 XtSetArg(args[2], XtNright, XtChainLeft);
2177 XtSetValues(menuBarWidget, args, 3);
2179 widgetList[j++] = whiteTimerWidget =
2180 XtCreateWidget("whiteTime", labelWidgetClass,
2181 formWidget, timerArgs, XtNumber(timerArgs));
2182 XtSetArg(args[0], XtNfont, clockFontStruct);
2183 XtSetArg(args[1], XtNtop, XtChainTop);
2184 XtSetArg(args[2], XtNbottom, XtChainTop);
2185 XtSetValues(whiteTimerWidget, args, 3);
2187 widgetList[j++] = blackTimerWidget =
2188 XtCreateWidget("blackTime", labelWidgetClass,
2189 formWidget, timerArgs, XtNumber(timerArgs));
2190 XtSetArg(args[0], XtNfont, clockFontStruct);
2191 XtSetArg(args[1], XtNtop, XtChainTop);
2192 XtSetArg(args[2], XtNbottom, XtChainTop);
2193 XtSetValues(blackTimerWidget, args, 3);
2195 if (appData.titleInWindow) {
2196 widgetList[j++] = titleWidget =
2197 XtCreateWidget("title", labelWidgetClass, formWidget,
2198 titleArgs, XtNumber(titleArgs));
2199 XtSetArg(args[0], XtNtop, XtChainTop);
2200 XtSetArg(args[1], XtNbottom, XtChainTop);
2201 XtSetValues(titleWidget, args, 2);
2204 if (appData.showButtonBar) {
2205 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2206 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2207 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2208 XtSetArg(args[2], XtNtop, XtChainTop);
2209 XtSetArg(args[3], XtNbottom, XtChainTop);
2210 XtSetValues(buttonBarWidget, args, 4);
2213 widgetList[j++] = messageWidget =
2214 XtCreateWidget("message", labelWidgetClass, formWidget,
2215 messageArgs, XtNumber(messageArgs));
2216 XtSetArg(args[0], XtNtop, XtChainTop);
2217 XtSetArg(args[1], XtNbottom, XtChainTop);
2218 XtSetValues(messageWidget, args, 2);
2220 widgetList[j++] = boardWidget =
2221 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2222 XtNumber(boardArgs));
2224 XtManageChildren(widgetList, j);
2226 timerWidth = (boardWidth - sep) / 2;
2227 XtSetArg(args[0], XtNwidth, timerWidth);
2228 XtSetValues(whiteTimerWidget, args, 1);
2229 XtSetValues(blackTimerWidget, args, 1);
2231 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2232 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2233 XtGetValues(whiteTimerWidget, args, 2);
2235 if (appData.showButtonBar) {
2236 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2237 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2238 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2242 * formWidget uses these constraints but they are stored
2246 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2247 XtSetValues(menuBarWidget, args, i);
2248 if (appData.titleInWindow) {
2251 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2252 XtSetValues(whiteTimerWidget, args, i);
2254 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2255 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2256 XtSetValues(blackTimerWidget, args, i);
2258 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2259 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2260 XtSetValues(titleWidget, args, i);
2262 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2263 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2264 XtSetValues(messageWidget, args, i);
2265 if (appData.showButtonBar) {
2267 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2268 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2269 XtSetValues(buttonBarWidget, args, i);
2273 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2274 XtSetValues(whiteTimerWidget, args, i);
2276 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2277 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2278 XtSetValues(blackTimerWidget, args, i);
2280 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2281 XtSetValues(titleWidget, args, i);
2283 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2284 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2285 XtSetValues(messageWidget, args, i);
2286 if (appData.showButtonBar) {
2288 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2289 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2290 XtSetValues(buttonBarWidget, args, i);
2295 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2296 XtSetValues(whiteTimerWidget, args, i);
2298 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2299 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2300 XtSetValues(blackTimerWidget, args, i);
2302 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2303 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2304 XtSetValues(messageWidget, args, i);
2305 if (appData.showButtonBar) {
2307 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2308 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2309 XtSetValues(buttonBarWidget, args, i);
2313 XtSetArg(args[0], XtNfromVert, messageWidget);
2314 XtSetArg(args[1], XtNtop, XtChainTop);
2315 XtSetArg(args[2], XtNbottom, XtChainBottom);
2316 XtSetArg(args[3], XtNleft, XtChainLeft);
2317 XtSetArg(args[4], XtNright, XtChainRight);
2318 XtSetValues(boardWidget, args, 5);
2320 XtRealizeWidget(shellWidget);
2323 XtSetArg(args[0], XtNx, wpMain.x);
2324 XtSetArg(args[1], XtNy, wpMain.y);
2325 XtSetValues(shellWidget, args, 2);
2329 * Correct the width of the message and title widgets.
2330 * It is not known why some systems need the extra fudge term.
2331 * The value "2" is probably larger than needed.
2333 XawFormDoLayout(formWidget, False);
2335 #define WIDTH_FUDGE 2
2337 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2338 XtSetArg(args[i], XtNheight, &h); i++;
2339 XtGetValues(messageWidget, args, i);
2340 if (appData.showButtonBar) {
2342 XtSetArg(args[i], XtNwidth, &w); i++;
2343 XtGetValues(buttonBarWidget, args, i);
2344 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2346 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2349 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2350 if (gres != XtGeometryYes && appData.debugMode) {
2351 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2352 programName, gres, w, h, wr, hr);
2355 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2356 /* The size used for the child widget in layout lags one resize behind
2357 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2359 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2360 if (gres != XtGeometryYes && appData.debugMode) {
2361 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2362 programName, gres, w, h, wr, hr);
2365 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2366 XtSetArg(args[1], XtNright, XtChainRight);
2367 XtSetValues(messageWidget, args, 2);
2369 if (appData.titleInWindow) {
2371 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2372 XtSetArg(args[i], XtNheight, &h); i++;
2373 XtGetValues(titleWidget, args, i);
2375 w = boardWidth - 2*bor;
2377 XtSetArg(args[0], XtNwidth, &w);
2378 XtGetValues(menuBarWidget, args, 1);
2379 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2382 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2383 if (gres != XtGeometryYes && appData.debugMode) {
2385 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2386 programName, gres, w, h, wr, hr);
2389 XawFormDoLayout(formWidget, True);
2391 xBoardWindow = XtWindow(boardWidget);
2393 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2394 // not need to go into InitDrawingSizes().
2398 * Create X checkmark bitmap and initialize option menu checks.
2400 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2401 checkmark_bits, checkmark_width, checkmark_height);
2402 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2403 if (appData.alwaysPromoteToQueen) {
2404 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2407 if (appData.animateDragging) {
2408 XtSetValues(XtNameToWidget(menuBarWidget,
2409 "menuOptions.Animate Dragging"),
2412 if (appData.animate) {
2413 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2416 if (appData.autoCallFlag) {
2417 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2420 if (appData.autoFlipView) {
2421 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2424 if (appData.blindfold) {
2425 XtSetValues(XtNameToWidget(menuBarWidget,
2426 "menuOptions.Blindfold"), args, 1);
2428 if (appData.flashCount > 0) {
2429 XtSetValues(XtNameToWidget(menuBarWidget,
2430 "menuOptions.Flash Moves"),
2434 if (appData.highlightDragging) {
2435 XtSetValues(XtNameToWidget(menuBarWidget,
2436 "menuOptions.Highlight Dragging"),
2440 if (appData.highlightLastMove) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Highlight Last Move"),
2445 if (appData.highlightMoveWithArrow) {
2446 XtSetValues(XtNameToWidget(menuBarWidget,
2447 "menuOptions.Arrow"),
2450 // if (appData.icsAlarm) {
2451 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2454 if (appData.ringBellAfterMoves) {
2455 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2458 if (appData.oneClick) {
2459 XtSetValues(XtNameToWidget(menuBarWidget,
2460 "menuOptions.OneClick"), args, 1);
2462 if (appData.periodicUpdates) {
2463 XtSetValues(XtNameToWidget(menuBarWidget,
2464 "menuOptions.Periodic Updates"), args, 1);
2466 if (appData.ponderNextMove) {
2467 XtSetValues(XtNameToWidget(menuBarWidget,
2468 "menuOptions.Ponder Next Move"), args, 1);
2470 if (appData.popupExitMessage) {
2471 XtSetValues(XtNameToWidget(menuBarWidget,
2472 "menuOptions.Popup Exit Message"), args, 1);
2474 if (appData.popupMoveErrors) {
2475 XtSetValues(XtNameToWidget(menuBarWidget,
2476 "menuOptions.Popup Move Errors"), args, 1);
2478 // if (appData.premove) {
2479 // XtSetValues(XtNameToWidget(menuBarWidget,
2480 // "menuOptions.Premove"), args, 1);
2482 if (appData.showCoords) {
2483 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2486 if (appData.hideThinkingFromHuman) {
2487 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2490 if (appData.testLegality) {
2491 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2494 if (saveSettingsOnExit) {
2495 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2502 ReadBitmap(&wIconPixmap, "icon_white.bm",
2503 icon_white_bits, icon_white_width, icon_white_height);
2504 ReadBitmap(&bIconPixmap, "icon_black.bm",
2505 icon_black_bits, icon_black_width, icon_black_height);
2506 iconPixmap = wIconPixmap;
2508 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2509 XtSetValues(shellWidget, args, i);
2512 * Create a cursor for the board widget.
2514 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2515 XChangeWindowAttributes(xDisplay, xBoardWindow,
2516 CWCursor, &window_attributes);
2519 * Inhibit shell resizing.
2521 shellArgs[0].value = (XtArgVal) &w;
2522 shellArgs[1].value = (XtArgVal) &h;
2523 XtGetValues(shellWidget, shellArgs, 2);
2524 shellArgs[4].value = shellArgs[2].value = w;
2525 shellArgs[5].value = shellArgs[3].value = h;
2526 XtSetValues(shellWidget, &shellArgs[2], 4);
2527 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2528 marginH = h - boardHeight;
2530 CatchDeleteWindow(shellWidget, "QuitProc");
2535 if (appData.bitmapDirectory[0] != NULLCHAR) {
2539 CreateXPMBoard(appData.liteBackTextureFile, 1);
2540 CreateXPMBoard(appData.darkBackTextureFile, 0);
2544 /* Create regular pieces */
2545 if (!useImages) CreatePieces();
2550 if (appData.animate || appData.animateDragging)
2553 XtAugmentTranslations(formWidget,
2554 XtParseTranslationTable(globalTranslations));
2555 XtAugmentTranslations(boardWidget,
2556 XtParseTranslationTable(boardTranslations));
2557 XtAugmentTranslations(whiteTimerWidget,
2558 XtParseTranslationTable(whiteTranslations));
2559 XtAugmentTranslations(blackTimerWidget,
2560 XtParseTranslationTable(blackTranslations));
2562 /* Why is the following needed on some versions of X instead
2563 * of a translation? */
2564 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2565 (XtEventHandler) EventProc, NULL);
2568 /* [AS] Restore layout */
2569 if( wpMoveHistory.visible ) {
2573 if( wpEvalGraph.visible )
2578 if( wpEngineOutput.visible ) {
2579 EngineOutputPopUp();
2584 if (errorExitStatus == -1) {
2585 if (appData.icsActive) {
2586 /* We now wait until we see "login:" from the ICS before
2587 sending the logon script (problems with timestamp otherwise) */
2588 /*ICSInitScript();*/
2589 if (appData.icsInputBox) ICSInputBoxPopUp();
2593 signal(SIGWINCH, TermSizeSigHandler);
2595 signal(SIGINT, IntSigHandler);
2596 signal(SIGTERM, IntSigHandler);
2597 if (*appData.cmailGameName != NULLCHAR) {
2598 signal(SIGUSR1, CmailSigHandler);
2601 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2603 XtSetKeyboardFocus(shellWidget, formWidget);
2605 XtAppMainLoop(appContext);
2606 if (appData.debugMode) fclose(debugFP); // [DM] debug
2613 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2614 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2616 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2617 unlink(gameCopyFilename);
2618 unlink(gamePasteFilename);
2621 RETSIGTYPE TermSizeSigHandler(int sig)
2634 CmailSigHandler(sig)
2640 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2642 /* Activate call-back function CmailSigHandlerCallBack() */
2643 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2645 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2649 CmailSigHandlerCallBack(isr, closure, message, count, error)
2657 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2659 /**** end signal code ****/
2665 /* try to open the icsLogon script, either in the location given
2666 * or in the users HOME directory
2673 f = fopen(appData.icsLogon, "r");
2676 homedir = getenv("HOME");
2677 if (homedir != NULL)
2679 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2680 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2681 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2682 f = fopen(buf, "r");
2687 ProcessICSInitScript(f);
2689 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2698 EditCommentPopDown();
2713 if (!menuBarWidget) return;
2714 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2716 DisplayError("menuEdit.Revert", 0);
2718 XtSetSensitive(w, !grey);
2720 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2722 DisplayError("menuEdit.Annotate", 0);
2724 XtSetSensitive(w, !grey);
2729 SetMenuEnables(enab)
2733 if (!menuBarWidget) return;
2734 while (enab->name != NULL) {
2735 w = XtNameToWidget(menuBarWidget, enab->name);
2737 DisplayError(enab->name, 0);
2739 XtSetSensitive(w, enab->value);
2745 Enables icsEnables[] = {
2746 { "menuFile.Mail Move", False },
2747 { "menuFile.Reload CMail Message", False },
2748 { "menuMode.Machine Black", False },
2749 { "menuMode.Machine White", False },
2750 { "menuMode.Analysis Mode", False },
2751 { "menuMode.Analyze File", False },
2752 { "menuMode.Two Machines", False },
2754 { "menuEngine.Hint", False },
2755 { "menuEngine.Book", False },
2756 { "menuEngine.Move Now", False },
2757 { "menuOptions.Periodic Updates", False },
2758 { "menuOptions.Hide Thinking", False },
2759 { "menuOptions.Ponder Next Move", False },
2760 { "menuEngine.Engine #1 Settings", False },
2762 { "menuEngine.Engine #2 Settings", False },
2763 { "menuEdit.Annotate", False },
2767 Enables ncpEnables[] = {
2768 { "menuFile.Mail Move", False },
2769 { "menuFile.Reload CMail Message", False },
2770 { "menuMode.Machine White", False },
2771 { "menuMode.Machine Black", False },
2772 { "menuMode.Analysis Mode", False },
2773 { "menuMode.Analyze File", False },
2774 { "menuMode.Two Machines", False },
2775 { "menuMode.ICS Client", False },
2776 { "menuView.ICS Input Box", False },
2777 { "Action", False },
2778 { "menuEdit.Revert", False },
2779 { "menuEdit.Annotate", False },
2780 { "menuEngine.Engine #1 Settings", False },
2781 { "menuEngine.Engine #2 Settings", False },
2782 { "menuEngine.Move Now", False },
2783 { "menuEngine.Retract Move", False },
2784 { "menuOptions.Auto Flag", False },
2785 { "menuOptions.Auto Flip View", False },
2786 { "menuOptions.ICS", False },
2787 // { "menuOptions.ICS Alarm", False },
2788 { "menuOptions.Move Sound", False },
2789 { "menuOptions.Hide Thinking", False },
2790 { "menuOptions.Periodic Updates", False },
2791 { "menuOptions.Ponder Next Move", False },
2792 { "menuEngine.Hint", False },
2793 { "menuEngine.Book", False },
2797 Enables gnuEnables[] = {
2798 { "menuMode.ICS Client", False },
2799 { "menuView.ICS Input Box", False },
2800 { "menuAction.Accept", False },
2801 { "menuAction.Decline", False },
2802 { "menuAction.Rematch", False },
2803 { "menuAction.Adjourn", False },
2804 { "menuAction.Stop Examining", False },
2805 { "menuAction.Stop Observing", False },
2806 { "menuAction.Upload to Examine", False },
2807 { "menuEdit.Revert", False },
2808 { "menuEdit.Annotate", False },
2809 { "menuOptions.ICS", False },
2811 /* The next two options rely on SetCmailMode being called *after* */
2812 /* SetGNUMode so that when GNU is being used to give hints these */
2813 /* menu options are still available */
2815 { "menuFile.Mail Move", False },
2816 { "menuFile.Reload CMail Message", False },
2820 Enables cmailEnables[] = {
2822 { "menuAction.Call Flag", False },
2823 { "menuAction.Draw", True },
2824 { "menuAction.Adjourn", False },
2825 { "menuAction.Abort", False },
2826 { "menuAction.Stop Observing", False },
2827 { "menuAction.Stop Examining", False },
2828 { "menuFile.Mail Move", True },
2829 { "menuFile.Reload CMail Message", True },
2833 Enables trainingOnEnables[] = {
2834 { "menuMode.Edit Comment", False },
2835 { "menuMode.Pause", False },
2836 { "menuEdit.Forward", False },
2837 { "menuEdit.Backward", False },
2838 { "menuEdit.Forward to End", False },
2839 { "menuEdit.Back to Start", False },
2840 { "menuEngine.Move Now", False },
2841 { "menuEdit.Truncate Game", False },
2845 Enables trainingOffEnables[] = {
2846 { "menuMode.Edit Comment", True },
2847 { "menuMode.Pause", True },
2848 { "menuEdit.Forward", True },
2849 { "menuEdit.Backward", True },
2850 { "menuEdit.Forward to End", True },
2851 { "menuEdit.Back to Start", True },
2852 { "menuEngine.Move Now", True },
2853 { "menuEdit.Truncate Game", True },
2857 Enables machineThinkingEnables[] = {
2858 { "menuFile.Load Game", False },
2859 // { "menuFile.Load Next Game", False },
2860 // { "menuFile.Load Previous Game", False },
2861 // { "menuFile.Reload Same Game", False },
2862 { "menuEdit.Paste Game", False },
2863 { "menuFile.Load Position", False },
2864 // { "menuFile.Load Next Position", False },
2865 // { "menuFile.Load Previous Position", False },
2866 // { "menuFile.Reload Same Position", False },
2867 { "menuEdit.Paste Position", False },
2868 { "menuMode.Machine White", False },
2869 { "menuMode.Machine Black", False },
2870 { "menuMode.Two Machines", False },
2871 { "menuEngine.Retract Move", False },
2875 Enables userThinkingEnables[] = {
2876 { "menuFile.Load Game", True },
2877 // { "menuFile.Load Next Game", True },
2878 // { "menuFile.Load Previous Game", True },
2879 // { "menuFile.Reload Same Game", True },
2880 { "menuEdit.Paste Game", True },
2881 { "menuFile.Load Position", True },
2882 // { "menuFile.Load Next Position", True },
2883 // { "menuFile.Load Previous Position", True },
2884 // { "menuFile.Reload Same Position", True },
2885 { "menuEdit.Paste Position", True },
2886 { "menuMode.Machine White", True },
2887 { "menuMode.Machine Black", True },
2888 { "menuMode.Two Machines", True },
2889 { "menuEngine.Retract Move", True },
2895 SetMenuEnables(icsEnables);
2898 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2899 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2906 SetMenuEnables(ncpEnables);
2912 SetMenuEnables(gnuEnables);
2918 SetMenuEnables(cmailEnables);
2924 SetMenuEnables(trainingOnEnables);
2925 if (appData.showButtonBar) {
2926 XtSetSensitive(buttonBarWidget, False);
2932 SetTrainingModeOff()
2934 SetMenuEnables(trainingOffEnables);
2935 if (appData.showButtonBar) {
2936 XtSetSensitive(buttonBarWidget, True);
2941 SetUserThinkingEnables()
2943 if (appData.noChessProgram) return;
2944 SetMenuEnables(userThinkingEnables);
2948 SetMachineThinkingEnables()
2950 if (appData.noChessProgram) return;
2951 SetMenuEnables(machineThinkingEnables);
2953 case MachinePlaysBlack:
2954 case MachinePlaysWhite:
2955 case TwoMachinesPlay:
2956 XtSetSensitive(XtNameToWidget(menuBarWidget,
2957 ModeToWidgetName(gameMode)), True);
2964 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2965 #define HISTORY_SIZE 64
2966 static char *history[HISTORY_SIZE];
2967 int histIn = 0, histP = 0;
2970 SaveInHistory(char *cmd)
2972 if (history[histIn] != NULL) {
2973 free(history[histIn]);
2974 history[histIn] = NULL;
2976 if (*cmd == NULLCHAR) return;
2977 history[histIn] = StrSave(cmd);
2978 histIn = (histIn + 1) % HISTORY_SIZE;
2979 if (history[histIn] != NULL) {
2980 free(history[histIn]);
2981 history[histIn] = NULL;
2987 PrevInHistory(char *cmd)
2990 if (histP == histIn) {
2991 if (history[histIn] != NULL) free(history[histIn]);
2992 history[histIn] = StrSave(cmd);
2994 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
2995 if (newhp == histIn || history[newhp] == NULL) return NULL;
2997 return history[histP];
3003 if (histP == histIn) return NULL;
3004 histP = (histP + 1) % HISTORY_SIZE;
3005 return history[histP];
3007 // end of borrowed code
3009 #define Abs(n) ((n)<0 ? -(n) : (n))
3012 * Find a font that matches "pattern" that is as close as
3013 * possible to the targetPxlSize. Prefer fonts that are k
3014 * pixels smaller to fonts that are k pixels larger. The
3015 * pattern must be in the X Consortium standard format,
3016 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3017 * The return value should be freed with XtFree when no
3021 FindFont(pattern, targetPxlSize)
3025 char **fonts, *p, *best, *scalable, *scalableTail;
3026 int i, j, nfonts, minerr, err, pxlSize;
3029 char **missing_list;
3031 char *def_string, *base_fnt_lst, strInt[3];
3033 XFontStruct **fnt_list;
3035 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3036 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3037 p = strstr(pattern, "--");
3038 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3039 strcat(base_fnt_lst, strInt);
3040 strcat(base_fnt_lst, strchr(p + 2, '-'));
3042 if ((fntSet = XCreateFontSet(xDisplay,
3046 &def_string)) == NULL) {
3048 fprintf(stderr, _("Unable to create font set.\n"));
3052 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3054 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3056 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3057 programName, pattern);
3065 for (i=0; i<nfonts; i++) {
3068 if (*p != '-') continue;
3070 if (*p == NULLCHAR) break;
3071 if (*p++ == '-') j++;
3073 if (j < 7) continue;
3076 scalable = fonts[i];
3079 err = pxlSize - targetPxlSize;
3080 if (Abs(err) < Abs(minerr) ||
3081 (minerr > 0 && err < 0 && -err == minerr)) {
3087 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3088 /* If the error is too big and there is a scalable font,
3089 use the scalable font. */
3090 int headlen = scalableTail - scalable;
3091 p = (char *) XtMalloc(strlen(scalable) + 10);
3092 while (isdigit(*scalableTail)) scalableTail++;
3093 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3095 p = (char *) XtMalloc(strlen(best) + 2);
3096 safeStrCpy(p, best, strlen(best)+1 );
3098 if (appData.debugMode) {
3099 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3100 pattern, targetPxlSize, p);
3103 if (missing_count > 0)
3104 XFreeStringList(missing_list);
3105 XFreeFontSet(xDisplay, fntSet);
3107 XFreeFontNames(fonts);
3113 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3114 // must be called before all non-first callse to CreateGCs()
3115 XtReleaseGC(shellWidget, highlineGC);
3116 XtReleaseGC(shellWidget, lightSquareGC);
3117 XtReleaseGC(shellWidget, darkSquareGC);
3118 if (appData.monoMode) {
3119 if (DefaultDepth(xDisplay, xScreen) == 1) {
3120 XtReleaseGC(shellWidget, wbPieceGC);
3122 XtReleaseGC(shellWidget, bwPieceGC);
3125 XtReleaseGC(shellWidget, prelineGC);
3126 XtReleaseGC(shellWidget, jailSquareGC);
3127 XtReleaseGC(shellWidget, wdPieceGC);
3128 XtReleaseGC(shellWidget, wlPieceGC);
3129 XtReleaseGC(shellWidget, wjPieceGC);
3130 XtReleaseGC(shellWidget, bdPieceGC);
3131 XtReleaseGC(shellWidget, blPieceGC);
3132 XtReleaseGC(shellWidget, bjPieceGC);
3136 void CreateGCs(int redo)
3138 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3139 | GCBackground | GCFunction | GCPlaneMask;
3140 XGCValues gc_values;
3143 gc_values.plane_mask = AllPlanes;
3144 gc_values.line_width = lineGap;
3145 gc_values.line_style = LineSolid;
3146 gc_values.function = GXcopy;
3149 DeleteGCs(); // called a second time; clean up old GCs first
3150 } else { // [HGM] grid and font GCs created on first call only
3151 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3152 gc_values.background = XBlackPixel(xDisplay, xScreen);
3153 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3155 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3156 gc_values.background = XWhitePixel(xDisplay, xScreen);
3157 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3158 XSetFont(xDisplay, coordGC, coordFontID);
3160 // [HGM] make font for holdings counts (white on black)
3161 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3162 gc_values.background = XBlackPixel(xDisplay, xScreen);
3163 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3164 XSetFont(xDisplay, countGC, countFontID);
3166 if (appData.monoMode) {
3167 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3168 gc_values.background = XWhitePixel(xDisplay, xScreen);
3169 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3171 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3172 gc_values.background = XBlackPixel(xDisplay, xScreen);
3173 lightSquareGC = wbPieceGC
3174 = XtGetGC(shellWidget, value_mask, &gc_values);
3176 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3177 gc_values.background = XWhitePixel(xDisplay, xScreen);
3178 darkSquareGC = bwPieceGC
3179 = XtGetGC(shellWidget, value_mask, &gc_values);
3181 if (DefaultDepth(xDisplay, xScreen) == 1) {
3182 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3183 gc_values.function = GXcopyInverted;
3184 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3185 gc_values.function = GXcopy;
3186 if (XBlackPixel(xDisplay, xScreen) == 1) {
3187 bwPieceGC = darkSquareGC;
3188 wbPieceGC = copyInvertedGC;
3190 bwPieceGC = copyInvertedGC;
3191 wbPieceGC = lightSquareGC;
3195 gc_values.foreground = highlightSquareColor;
3196 gc_values.background = highlightSquareColor;
3197 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3199 gc_values.foreground = premoveHighlightColor;
3200 gc_values.background = premoveHighlightColor;
3201 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3203 gc_values.foreground = lightSquareColor;
3204 gc_values.background = darkSquareColor;
3205 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3207 gc_values.foreground = darkSquareColor;
3208 gc_values.background = lightSquareColor;
3209 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3211 gc_values.foreground = jailSquareColor;
3212 gc_values.background = jailSquareColor;
3213 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3215 gc_values.foreground = whitePieceColor;
3216 gc_values.background = darkSquareColor;
3217 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3219 gc_values.foreground = whitePieceColor;
3220 gc_values.background = lightSquareColor;
3221 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3223 gc_values.foreground = whitePieceColor;
3224 gc_values.background = jailSquareColor;
3225 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3227 gc_values.foreground = blackPieceColor;
3228 gc_values.background = darkSquareColor;
3229 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3231 gc_values.foreground = blackPieceColor;
3232 gc_values.background = lightSquareColor;
3233 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3235 gc_values.foreground = blackPieceColor;
3236 gc_values.background = jailSquareColor;
3237 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3241 void loadXIM(xim, xmask, filename, dest, mask)
3254 fp = fopen(filename, "rb");
3256 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3263 for (y=0; y<h; ++y) {
3264 for (x=0; x<h; ++x) {
3269 XPutPixel(xim, x, y, blackPieceColor);
3271 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3274 XPutPixel(xim, x, y, darkSquareColor);
3276 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3279 XPutPixel(xim, x, y, whitePieceColor);
3281 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3284 XPutPixel(xim, x, y, lightSquareColor);
3286 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3294 /* create Pixmap of piece */
3295 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3297 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3300 /* create Pixmap of clipmask
3301 Note: We assume the white/black pieces have the same
3302 outline, so we make only 6 masks. This is okay
3303 since the XPM clipmask routines do the same. */
3305 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3307 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3310 /* now create the 1-bit version */
3311 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3314 values.foreground = 1;
3315 values.background = 0;
3317 /* Don't use XtGetGC, not read only */
3318 maskGC = XCreateGC(xDisplay, *mask,
3319 GCForeground | GCBackground, &values);
3320 XCopyPlane(xDisplay, temp, *mask, maskGC,
3321 0, 0, squareSize, squareSize, 0, 0, 1);
3322 XFreePixmap(xDisplay, temp);
3327 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3329 void CreateXIMPieces()
3334 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3339 /* The XSynchronize calls were copied from CreatePieces.
3340 Not sure if needed, but can't hurt */
3341 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3344 /* temp needed by loadXIM() */
3345 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3346 0, 0, ss, ss, AllPlanes, XYPixmap);
3348 if (strlen(appData.pixmapDirectory) == 0) {
3352 if (appData.monoMode) {
3353 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3357 fprintf(stderr, _("\nLoading XIMs...\n"));
3359 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3360 fprintf(stderr, "%d", piece+1);
3361 for (kind=0; kind<4; kind++) {
3362 fprintf(stderr, ".");
3363 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3364 ExpandPathName(appData.pixmapDirectory),
3365 piece <= (int) WhiteKing ? "" : "w",
3366 pieceBitmapNames[piece],
3368 ximPieceBitmap[kind][piece] =
3369 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3370 0, 0, ss, ss, AllPlanes, XYPixmap);
3371 if (appData.debugMode)
3372 fprintf(stderr, _("(File:%s:) "), buf);
3373 loadXIM(ximPieceBitmap[kind][piece],
3375 &(xpmPieceBitmap2[kind][piece]),
3376 &(ximMaskPm2[piece]));
3377 if(piece <= (int)WhiteKing)
3378 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3380 fprintf(stderr," ");
3382 /* Load light and dark squares */
3383 /* If the LSQ and DSQ pieces don't exist, we will
3384 draw them with solid squares. */
3385 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3386 if (access(buf, 0) != 0) {
3390 fprintf(stderr, _("light square "));
3392 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3393 0, 0, ss, ss, AllPlanes, XYPixmap);
3394 if (appData.debugMode)
3395 fprintf(stderr, _("(File:%s:) "), buf);
3397 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3398 fprintf(stderr, _("dark square "));
3399 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3400 ExpandPathName(appData.pixmapDirectory), ss);
3401 if (appData.debugMode)
3402 fprintf(stderr, _("(File:%s:) "), buf);
3404 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3405 0, 0, ss, ss, AllPlanes, XYPixmap);
3406 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3407 xpmJailSquare = xpmLightSquare;
3409 fprintf(stderr, _("Done.\n"));
3411 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3415 void CreateXPMBoard(char *s, int kind)
3419 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3420 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3421 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3425 void FreeXPMPieces()
3426 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3427 // thisroutine has to be called t free the old piece pixmaps
3429 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3430 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3432 XFreePixmap(xDisplay, xpmLightSquare);
3433 XFreePixmap(xDisplay, xpmDarkSquare);
3437 void CreateXPMPieces()
3441 u_int ss = squareSize;
3443 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3444 XpmColorSymbol symbols[4];
3445 static int redo = False;
3447 if(redo) FreeXPMPieces(); else redo = 1;
3449 /* The XSynchronize calls were copied from CreatePieces.
3450 Not sure if needed, but can't hurt */
3451 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3453 /* Setup translations so piece colors match square colors */
3454 symbols[0].name = "light_piece";
3455 symbols[0].value = appData.whitePieceColor;
3456 symbols[1].name = "dark_piece";
3457 symbols[1].value = appData.blackPieceColor;
3458 symbols[2].name = "light_square";
3459 symbols[2].value = appData.lightSquareColor;
3460 symbols[3].name = "dark_square";
3461 symbols[3].value = appData.darkSquareColor;
3463 attr.valuemask = XpmColorSymbols;
3464 attr.colorsymbols = symbols;
3465 attr.numsymbols = 4;
3467 if (appData.monoMode) {
3468 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3472 if (strlen(appData.pixmapDirectory) == 0) {
3473 XpmPieces* pieces = builtInXpms;
3476 while (pieces->size != squareSize && pieces->size) pieces++;
3477 if (!pieces->size) {
3478 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3481 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3482 for (kind=0; kind<4; kind++) {
3484 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3485 pieces->xpm[piece][kind],
3486 &(xpmPieceBitmap2[kind][piece]),
3487 NULL, &attr)) != 0) {
3488 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3492 if(piece <= (int) WhiteKing)
3493 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3497 xpmJailSquare = xpmLightSquare;
3501 fprintf(stderr, _("\nLoading XPMs...\n"));
3504 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3505 fprintf(stderr, "%d ", piece+1);
3506 for (kind=0; kind<4; kind++) {
3507 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3508 ExpandPathName(appData.pixmapDirectory),
3509 piece > (int) WhiteKing ? "w" : "",
3510 pieceBitmapNames[piece],
3512 if (appData.debugMode) {
3513 fprintf(stderr, _("(File:%s:) "), buf);
3515 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3516 &(xpmPieceBitmap2[kind][piece]),
3517 NULL, &attr)) != 0) {
3518 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3519 // [HGM] missing: read of unorthodox piece failed; substitute King.
3520 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3521 ExpandPathName(appData.pixmapDirectory),
3523 if (appData.debugMode) {
3524 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3526 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3527 &(xpmPieceBitmap2[kind][piece]),
3531 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3536 if(piece <= (int) WhiteKing)
3537 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3540 /* Load light and dark squares */
3541 /* If the LSQ and DSQ pieces don't exist, we will
3542 draw them with solid squares. */
3543 fprintf(stderr, _("light square "));
3544 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3545 if (access(buf, 0) != 0) {
3549 if (appData.debugMode)
3550 fprintf(stderr, _("(File:%s:) "), buf);
3552 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3553 &xpmLightSquare, NULL, &attr)) != 0) {
3554 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3557 fprintf(stderr, _("dark square "));
3558 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3559 ExpandPathName(appData.pixmapDirectory), ss);
3560 if (appData.debugMode) {
3561 fprintf(stderr, _("(File:%s:) "), buf);
3563 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3564 &xpmDarkSquare, NULL, &attr)) != 0) {
3565 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3569 xpmJailSquare = xpmLightSquare;
3570 fprintf(stderr, _("Done.\n"));
3572 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3575 #endif /* HAVE_LIBXPM */
3578 /* No built-in bitmaps */
3583 u_int ss = squareSize;
3585 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3588 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3589 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3590 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3591 pieceBitmapNames[piece],
3592 ss, kind == SOLID ? 's' : 'o');
3593 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3594 if(piece <= (int)WhiteKing)
3595 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3599 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3603 /* With built-in bitmaps */
3606 BuiltInBits* bib = builtInBits;
3609 u_int ss = squareSize;
3611 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3614 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3616 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3617 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3618 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3619 pieceBitmapNames[piece],
3620 ss, kind == SOLID ? 's' : 'o');
3621 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3622 bib->bits[kind][piece], ss, ss);
3623 if(piece <= (int)WhiteKing)
3624 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3628 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3633 void ReadBitmap(pm, name, bits, wreq, hreq)
3636 unsigned char bits[];
3642 char msg[MSG_SIZ], fullname[MSG_SIZ];
3644 if (*appData.bitmapDirectory != NULLCHAR) {
3645 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3646 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3647 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3648 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3649 &w, &h, pm, &x_hot, &y_hot);
3650 fprintf(stderr, "load %s\n", name);
3651 if (errcode != BitmapSuccess) {
3653 case BitmapOpenFailed:
3654 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3656 case BitmapFileInvalid:
3657 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3659 case BitmapNoMemory:
3660 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3664 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3668 fprintf(stderr, _("%s: %s...using built-in\n"),
3670 } else if (w != wreq || h != hreq) {
3672 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3673 programName, fullname, w, h, wreq, hreq);
3679 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3688 if (lineGap == 0) return;
3690 /* [HR] Split this into 2 loops for non-square boards. */
3692 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3693 gridSegments[i].x1 = 0;
3694 gridSegments[i].x2 =
3695 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3696 gridSegments[i].y1 = gridSegments[i].y2
3697 = lineGap / 2 + (i * (squareSize + lineGap));
3700 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3701 gridSegments[j + i].y1 = 0;
3702 gridSegments[j + i].y2 =
3703 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3704 gridSegments[j + i].x1 = gridSegments[j + i].x2
3705 = lineGap / 2 + (j * (squareSize + lineGap));
3709 static void MenuBarSelect(w, addr, index)
3714 XtActionProc proc = (XtActionProc) addr;
3716 (proc)(NULL, NULL, NULL, NULL);
3719 void CreateMenuBarPopup(parent, name, mb)
3729 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3732 XtSetArg(args[j], XtNleftMargin, 20); j++;
3733 XtSetArg(args[j], XtNrightMargin, 20); j++;
3735 while (mi->string != NULL) {
3736 if (strcmp(mi->string, "----") == 0) {
3737 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3740 XtSetArg(args[j], XtNlabel, XtNewString(mi->string));
3741 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3743 XtAddCallback(entry, XtNcallback,
3744 (XtCallbackProc) MenuBarSelect,
3745 (caddr_t) mi->proc);
3751 Widget CreateMenuBar(mb)
3755 Widget anchor, menuBar;
3757 char menuName[MSG_SIZ];
3760 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3761 XtSetArg(args[j], XtNvSpace, 0); j++;
3762 XtSetArg(args[j], XtNborderWidth, 0); j++;
3763 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3764 formWidget, args, j);
3766 while (mb->name != NULL) {
3767 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3768 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3770 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3773 shortName[0] = mb->name[0];
3774 shortName[1] = NULLCHAR;
3775 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3778 XtSetArg(args[j], XtNlabel, XtNewString(mb->name)); j++;
3781 XtSetArg(args[j], XtNborderWidth, 0); j++;
3782 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3784 CreateMenuBarPopup(menuBar, menuName, mb);
3790 Widget CreateButtonBar(mi)
3794 Widget button, buttonBar;
3798 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3800 XtSetArg(args[j], XtNhSpace, 0); j++;
3802 XtSetArg(args[j], XtNborderWidth, 0); j++;
3803 XtSetArg(args[j], XtNvSpace, 0); j++;
3804 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3805 formWidget, args, j);
3807 while (mi->string != NULL) {
3810 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3811 XtSetArg(args[j], XtNborderWidth, 0); j++;
3813 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3814 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3815 buttonBar, args, j);
3816 XtAddCallback(button, XtNcallback,
3817 (XtCallbackProc) MenuBarSelect,
3818 (caddr_t) mi->proc);
3825 CreatePieceMenu(name, color)
3832 ChessSquare selection;
3834 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3835 boardWidget, args, 0);
3837 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3838 String item = pieceMenuStrings[color][i];
3840 if (strcmp(item, "----") == 0) {
3841 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3844 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3845 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3847 selection = pieceMenuTranslation[color][i];
3848 XtAddCallback(entry, XtNcallback,
3849 (XtCallbackProc) PieceMenuSelect,
3850 (caddr_t) selection);
3851 if (selection == WhitePawn || selection == BlackPawn) {
3852 XtSetArg(args[0], XtNpopupOnEntry, entry);
3853 XtSetValues(menu, args, 1);
3866 ChessSquare selection;
3868 whitePieceMenu = CreatePieceMenu("menuW", 0);
3869 blackPieceMenu = CreatePieceMenu("menuB", 1);
3871 XtRegisterGrabAction(PieceMenuPopup, True,
3872 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3873 GrabModeAsync, GrabModeAsync);
3875 XtSetArg(args[0], XtNlabel, _("Drop"));
3876 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3877 boardWidget, args, 1);
3878 for (i = 0; i < DROP_MENU_SIZE; i++) {
3879 String item = dropMenuStrings[i];
3881 if (strcmp(item, "----") == 0) {
3882 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3885 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3886 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3888 selection = dropMenuTranslation[i];
3889 XtAddCallback(entry, XtNcallback,
3890 (XtCallbackProc) DropMenuSelect,
3891 (caddr_t) selection);
3896 void SetupDropMenu()
3904 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3905 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3906 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3907 dmEnables[i].piece);
3908 XtSetSensitive(entry, p != NULL || !appData.testLegality
3909 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3910 && !appData.icsActive));
3912 while (p && *p++ == dmEnables[i].piece) count++;
3913 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3915 XtSetArg(args[j], XtNlabel, label); j++;
3916 XtSetValues(entry, args, j);
3920 void PieceMenuPopup(w, event, params, num_params)
3924 Cardinal *num_params;
3926 String whichMenu; int menuNr;
3927 if (event->type == ButtonRelease)
3928 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3929 else if (event->type == ButtonPress)
3930 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3932 case 0: whichMenu = params[0]; break;
3933 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3935 case -1: if (errorUp) ErrorPopDown();
3938 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3941 static void PieceMenuSelect(w, piece, junk)
3946 if (pmFromX < 0 || pmFromY < 0) return;
3947 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3950 static void DropMenuSelect(w, piece, junk)
3955 if (pmFromX < 0 || pmFromY < 0) return;
3956 DropMenuEvent(piece, pmFromX, pmFromY);
3959 void WhiteClock(w, event, prms, nprms)
3968 void BlackClock(w, event, prms, nprms)
3979 * If the user selects on a border boundary, return -1; if off the board,
3980 * return -2. Otherwise map the event coordinate to the square.
3982 int EventToSquare(x, limit)
3990 if ((x % (squareSize + lineGap)) >= squareSize)
3992 x /= (squareSize + lineGap);
3998 static void do_flash_delay(msec)
4004 static void drawHighlight(file, rank, gc)
4010 if (lineGap == 0) return;
4013 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4014 (squareSize + lineGap);
4015 y = lineGap/2 + rank * (squareSize + lineGap);
4017 x = lineGap/2 + file * (squareSize + lineGap);
4018 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4019 (squareSize + lineGap);
4022 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4023 squareSize+lineGap, squareSize+lineGap);
4026 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4027 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4030 SetHighlights(fromX, fromY, toX, toY)
4031 int fromX, fromY, toX, toY;
4033 if (hi1X != fromX || hi1Y != fromY) {
4034 if (hi1X >= 0 && hi1Y >= 0) {
4035 drawHighlight(hi1X, hi1Y, lineGC);
4037 } // [HGM] first erase both, then draw new!
4038 if (hi2X != toX || hi2Y != toY) {
4039 if (hi2X >= 0 && hi2Y >= 0) {
4040 drawHighlight(hi2X, hi2Y, lineGC);
4043 if (hi1X != fromX || hi1Y != fromY) {
4044 if (fromX >= 0 && fromY >= 0) {
4045 drawHighlight(fromX, fromY, highlineGC);
4048 if (hi2X != toX || hi2Y != toY) {
4049 if (toX >= 0 && toY >= 0) {
4050 drawHighlight(toX, toY, highlineGC);
4062 SetHighlights(-1, -1, -1, -1);
4067 SetPremoveHighlights(fromX, fromY, toX, toY)
4068 int fromX, fromY, toX, toY;
4070 if (pm1X != fromX || pm1Y != fromY) {
4071 if (pm1X >= 0 && pm1Y >= 0) {
4072 drawHighlight(pm1X, pm1Y, lineGC);
4074 if (fromX >= 0 && fromY >= 0) {
4075 drawHighlight(fromX, fromY, prelineGC);
4078 if (pm2X != toX || pm2Y != toY) {
4079 if (pm2X >= 0 && pm2Y >= 0) {
4080 drawHighlight(pm2X, pm2Y, lineGC);
4082 if (toX >= 0 && toY >= 0) {
4083 drawHighlight(toX, toY, prelineGC);
4093 ClearPremoveHighlights()
4095 SetPremoveHighlights(-1, -1, -1, -1);
4098 static int CutOutSquare(x, y, x0, y0, kind)
4099 int x, y, *x0, *y0, kind;
4101 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4102 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4104 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4105 if(textureW[kind] < W*squareSize)
4106 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4108 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4109 if(textureH[kind] < H*squareSize)
4110 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4112 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4116 static void BlankSquare(x, y, color, piece, dest, fac)
4117 int x, y, color, fac;
4120 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4122 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4123 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4124 squareSize, squareSize, x*fac, y*fac);
4126 if (useImages && useImageSqs) {
4130 pm = xpmLightSquare;
4135 case 2: /* neutral */
4140 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4141 squareSize, squareSize, x*fac, y*fac);
4151 case 2: /* neutral */
4156 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4161 I split out the routines to draw a piece so that I could
4162 make a generic flash routine.
4164 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4166 int square_color, x, y;
4169 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4170 switch (square_color) {
4172 case 2: /* neutral */
4174 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4175 ? *pieceToOutline(piece)
4176 : *pieceToSolid(piece),
4177 dest, bwPieceGC, 0, 0,
4178 squareSize, squareSize, x, y);
4181 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4182 ? *pieceToSolid(piece)
4183 : *pieceToOutline(piece),
4184 dest, wbPieceGC, 0, 0,
4185 squareSize, squareSize, x, y);
4190 static void monoDrawPiece(piece, square_color, x, y, dest)
4192 int square_color, x, y;
4195 switch (square_color) {
4197 case 2: /* neutral */
4199 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4200 ? *pieceToOutline(piece)
4201 : *pieceToSolid(piece),
4202 dest, bwPieceGC, 0, 0,
4203 squareSize, squareSize, x, y, 1);
4206 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4207 ? *pieceToSolid(piece)
4208 : *pieceToOutline(piece),
4209 dest, wbPieceGC, 0, 0,
4210 squareSize, squareSize, x, y, 1);
4215 static void colorDrawPiece(piece, square_color, x, y, dest)
4217 int square_color, x, y;
4220 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4221 switch (square_color) {
4223 XCopyPlane(xDisplay, *pieceToSolid(piece),
4224 dest, (int) piece < (int) BlackPawn
4225 ? wlPieceGC : blPieceGC, 0, 0,
4226 squareSize, squareSize, x, y, 1);
4229 XCopyPlane(xDisplay, *pieceToSolid(piece),
4230 dest, (int) piece < (int) BlackPawn
4231 ? wdPieceGC : bdPieceGC, 0, 0,
4232 squareSize, squareSize, x, y, 1);
4234 case 2: /* neutral */
4236 XCopyPlane(xDisplay, *pieceToSolid(piece),
4237 dest, (int) piece < (int) BlackPawn
4238 ? wjPieceGC : bjPieceGC, 0, 0,
4239 squareSize, squareSize, x, y, 1);
4244 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4246 int square_color, x, y;
<