2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
65 # if HAVE_SYS_SOCKET_H
66 # include <sys/socket.h>
67 # include <netinet/in.h>
69 # else /* not HAVE_SYS_SOCKET_H */
70 # if HAVE_LAN_SOCKET_H
71 # include <lan/socket.h>
73 # include <lan/netdb.h>
74 # else /* not HAVE_LAN_SOCKET_H */
75 # define OMIT_SOCKETS 1
76 # endif /* not HAVE_LAN_SOCKET_H */
77 # endif /* not HAVE_SYS_SOCKET_H */
78 #endif /* !OMIT_SOCKETS */
83 #else /* not STDC_HEADERS */
84 extern char *getenv();
87 # else /* not HAVE_STRING_H */
89 # endif /* not HAVE_STRING_H */
90 #endif /* not STDC_HEADERS */
93 # include <sys/fcntl.h>
94 #else /* not HAVE_SYS_FCNTL_H */
97 # endif /* HAVE_FCNTL_H */
98 #endif /* not HAVE_SYS_FCNTL_H */
100 #if HAVE_SYS_SYSTEMINFO_H
101 # include <sys/systeminfo.h>
102 #endif /* HAVE_SYS_SYSTEMINFO_H */
104 #if TIME_WITH_SYS_TIME
105 # include <sys/time.h>
109 # include <sys/time.h>
120 # include <sys/wait.h>
125 # define NAMLEN(dirent) strlen((dirent)->d_name)
126 # define HAVE_DIR_STRUCT
128 # define dirent direct
129 # define NAMLEN(dirent) (dirent)->d_namlen
131 # include <sys/ndir.h>
132 # define HAVE_DIR_STRUCT
135 # include <sys/dir.h>
136 # define HAVE_DIR_STRUCT
140 # define HAVE_DIR_STRUCT
144 #include <X11/Intrinsic.h>
145 #include <X11/StringDefs.h>
146 #include <X11/Shell.h>
147 #include <X11/cursorfont.h>
148 #include <X11/Xatom.h>
149 #include <X11/Xmu/Atoms.h>
151 #include <X11/Xaw3d/Dialog.h>
152 #include <X11/Xaw3d/Form.h>
153 #include <X11/Xaw3d/List.h>
154 #include <X11/Xaw3d/Label.h>
155 #include <X11/Xaw3d/SimpleMenu.h>
156 #include <X11/Xaw3d/SmeBSB.h>
157 #include <X11/Xaw3d/SmeLine.h>
158 #include <X11/Xaw3d/Box.h>
159 #include <X11/Xaw3d/MenuButton.h>
160 #include <X11/Xaw3d/Text.h>
161 #include <X11/Xaw3d/AsciiText.h>
163 #include <X11/Xaw/Dialog.h>
164 #include <X11/Xaw/Form.h>
165 #include <X11/Xaw/List.h>
166 #include <X11/Xaw/Label.h>
167 #include <X11/Xaw/SimpleMenu.h>
168 #include <X11/Xaw/SmeBSB.h>
169 #include <X11/Xaw/SmeLine.h>
170 #include <X11/Xaw/Box.h>
171 #include <X11/Xaw/MenuButton.h>
172 #include <X11/Xaw/Text.h>
173 #include <X11/Xaw/AsciiText.h>
176 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
181 #include "pixmaps/pixmaps.h"
182 #define IMAGE_EXT "xpm"
184 #define IMAGE_EXT "xim"
185 #include "bitmaps/bitmaps.h"
188 #include "bitmaps/icon_white.bm"
189 #include "bitmaps/icon_black.bm"
190 #include "bitmaps/checkmark.bm"
192 #include "frontend.h"
194 #include "backendz.h"
198 #include "xgamelist.h"
199 #include "xhistory.h"
200 #include "xedittags.h"
203 // must be moved to xengineoutput.h
205 void EngineOutputProc P((Widget w, XEvent *event,
206 String *prms, Cardinal *nprms));
207 void EvalGraphProc P((Widget w, XEvent *event,
208 String *prms, Cardinal *nprms));
215 #define usleep(t) _sleep2(((t)+500)/1000)
219 # define _(s) gettext (s)
220 # define N_(s) gettext_noop (s)
238 int main P((int argc, char **argv));
239 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
240 char *init_path, char *mode, int (*show_entry)(), char **name_return));
241 RETSIGTYPE CmailSigHandler P((int sig));
242 RETSIGTYPE IntSigHandler P((int sig));
243 RETSIGTYPE TermSizeSigHandler P((int sig));
244 void CreateGCs P((void));
245 void CreateXIMPieces P((void));
246 void CreateXPMPieces P((void));
247 void CreateXPMBoard P((char *s, int n));
248 void CreatePieces P((void));
249 void CreatePieceMenus P((void));
250 Widget CreateMenuBar P((Menu *mb));
251 Widget CreateButtonBar P ((MenuItem *mi));
252 char *FindFont P((char *pattern, int targetPxlSize));
253 void PieceMenuPopup P((Widget w, XEvent *event,
254 String *params, Cardinal *num_params));
255 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
256 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
257 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
258 u_int wreq, u_int hreq));
259 void CreateGrid P((void));
260 int EventToSquare P((int x, int limit));
261 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
262 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
263 void HandleUserMove P((Widget w, XEvent *event,
264 String *prms, Cardinal *nprms));
265 void AnimateUserMove P((Widget w, XEvent * event,
266 String * params, Cardinal * nParams));
267 void HandlePV P((Widget w, XEvent * event,
268 String * params, Cardinal * nParams));
269 void SelectPV P((Widget w, XEvent * event,
270 String * params, Cardinal * nParams));
271 void StopPV P((Widget w, XEvent * event,
272 String * params, Cardinal * nParams));
273 void WhiteClock P((Widget w, XEvent *event,
274 String *prms, Cardinal *nprms));
275 void BlackClock P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void DrawPositionProc P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
281 void CommentClick P((Widget w, XEvent * event,
282 String * params, Cardinal * nParams));
283 void CommentPopUp P((char *title, char *label));
284 void CommentPopDown P((void));
285 void CommentCallback P((Widget w, XtPointer client_data,
286 XtPointer call_data));
287 void ICSInputBoxPopUp P((void));
288 void ICSInputBoxPopDown P((void));
289 void FileNamePopUp P((char *label, char *def,
290 FileProc proc, char *openMode));
291 void FileNamePopDown P((void));
292 void FileNameCallback P((Widget w, XtPointer client_data,
293 XtPointer call_data));
294 void FileNameAction P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void AskQuestionReplyAction P((Widget w, XEvent *event,
297 String *prms, Cardinal *nprms));
298 void AskQuestionProc P((Widget w, XEvent *event,
299 String *prms, Cardinal *nprms));
300 void AskQuestionPopDown P((void));
301 void PromotionPopDown P((void));
302 void PromotionCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void EditCommentPopDown P((void));
305 void EditCommentCallback P((Widget w, XtPointer client_data,
306 XtPointer call_data));
307 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
308 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
312 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
314 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
316 void LoadPositionProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
320 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
322 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
324 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
326 void PastePositionProc P((Widget w, XEvent *event, String *prms,
328 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void SavePositionProc P((Widget w, XEvent *event,
332 String *prms, Cardinal *nprms));
333 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
336 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
340 void MachineWhiteProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void AnalyzeModeProc P((Widget w, XEvent *event,
343 String *prms, Cardinal *nprms));
344 void AnalyzeFileProc P((Widget w, XEvent *event,
345 String *prms, Cardinal *nprms));
346 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
348 void IcsClientProc P((Widget w, XEvent *event, String *prms,
350 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void EditPositionProc P((Widget w, XEvent *event,
352 String *prms, Cardinal *nprms));
353 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void EditCommentProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void IcsInputBoxProc P((Widget w, XEvent *event,
357 String *prms, Cardinal *nprms));
358 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void StopObservingProc P((Widget w, XEvent *event, String *prms,
374 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
376 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
385 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
387 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
390 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
392 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
394 void AutocommProc P((Widget w, XEvent *event, String *prms,
396 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void AutobsProc P((Widget w, XEvent *event, String *prms,
400 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
405 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
408 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
410 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
412 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
416 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
418 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
420 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
422 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
424 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
428 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
430 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
432 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
434 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void DisplayMove P((int moveNumber));
446 void DisplayTitle P((char *title));
447 void ICSInitScript P((void));
448 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
449 void ErrorPopUp P((char *title, char *text, int modal));
450 void ErrorPopDown P((void));
451 static char *ExpandPathName P((char *path));
452 static void CreateAnimVars P((void));
453 static void DragPieceMove P((int x, int y));
454 static void DrawDragPiece P((void));
455 char *ModeToWidgetName P((GameMode mode));
456 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void GameListOptionsPopDown P(());
465 void ShufflePopDown P(());
466 void EnginePopDown P(());
467 void UciPopDown P(());
468 void TimeControlPopDown P(());
469 void NewVariantPopDown P(());
470 void SettingsPopDown P(());
471 void update_ics_width P(());
472 int get_term_width P(());
473 int CopyMemoProc P(());
475 * XBoard depends on Xt R4 or higher
477 int xtVersion = XtSpecificationRelease;
482 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
483 jailSquareColor, highlightSquareColor, premoveHighlightColor;
484 Pixel lowTimeWarningColor;
485 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
486 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
487 wjPieceGC, bjPieceGC, prelineGC, countGC;
488 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
489 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
490 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
491 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
492 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
493 ICSInputShell, fileNameShell, askQuestionShell;
494 Widget historyShell, evalGraphShell, gameListShell;
495 int hOffset; // [HGM] dual
496 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
497 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
498 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
499 Font clockFontID, coordFontID, countFontID;
500 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
501 XtAppContext appContext;
503 char *oldICSInteractionTitle;
507 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
509 Position commentX = -1, commentY = -1;
510 Dimension commentW, commentH;
511 typedef unsigned int BoardSize;
513 Boolean chessProgram;
515 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
516 int squareSize, smallLayout = 0, tinyLayout = 0,
517 marginW, marginH, // [HGM] for run-time resizing
518 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
519 ICSInputBoxUp = False, askQuestionUp = False,
520 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
521 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
522 Pixel timerForegroundPixel, timerBackgroundPixel;
523 Pixel buttonForegroundPixel, buttonBackgroundPixel;
524 char *chessDir, *programName, *programVersion,
525 *gameCopyFilename, *gamePasteFilename;
526 Boolean alwaysOnTop = False;
527 Boolean saveSettingsOnExit;
528 char *settingsFileName;
529 char *icsTextMenuString;
531 char *firstChessProgramNames;
532 char *secondChessProgramNames;
534 WindowPlacement wpMain;
535 WindowPlacement wpConsole;
536 WindowPlacement wpComment;
537 WindowPlacement wpMoveHistory;
538 WindowPlacement wpEvalGraph;
539 WindowPlacement wpEngineOutput;
540 WindowPlacement wpGameList;
541 WindowPlacement wpTags;
545 Pixmap pieceBitmap[2][(int)BlackPawn];
546 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
547 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
548 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
549 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
550 Pixmap xpmBoardBitmap[2];
551 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
552 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
553 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
554 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
555 XImage *ximLightSquare, *ximDarkSquare;
558 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
559 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
561 #define White(piece) ((int)(piece) < (int)BlackPawn)
563 /* Variables for doing smooth animation. This whole thing
564 would be much easier if the board was double-buffered,
565 but that would require a fairly major rewrite. */
570 GC blitGC, pieceGC, outlineGC;
571 XPoint startSquare, prevFrame, mouseDelta;
575 int startBoardX, startBoardY;
578 /* There can be two pieces being animated at once: a player
579 can begin dragging a piece before the remote opponent has moved. */
581 static AnimState game, player;
583 /* Bitmaps for use as masks when drawing XPM pieces.
584 Need one for each black and white piece. */
585 static Pixmap xpmMask[BlackKing + 1];
587 /* This magic number is the number of intermediate frames used
588 in each half of the animation. For short moves it's reduced
589 by 1. The total number of frames will be factor * 2 + 1. */
592 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
594 MenuItem fileMenu[] = {
595 {N_("New Game 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 {"----", NULL, NothingProc},
605 // {N_("Load Next Position"), "Load Next Position", LoadNextPositionProc},
606 // {N_("Load Previous Position"), "Load Previous Position", LoadPrevPositionProc},
607 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
608 {N_("Save Game 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},
655 MenuItem modeMenu[] = {
656 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
657 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
658 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
659 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
660 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
661 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
662 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
663 {N_("Training"), "Training", TrainingProc},
664 {N_("ICS Client"), "ICS Client", IcsClientProc},
665 {"----", NULL, NothingProc},
666 {N_("Pause Pause"), "Pause", PauseProc},
670 MenuItem actionMenu[] = {
671 {N_("Accept F3"), "Accept", AcceptProc},
672 {N_("Decline F4"), "Decline", DeclineProc},
673 {N_("Rematch F12"), "Rematch", RematchProc},
674 {"----", NULL, NothingProc},
675 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
676 {N_("Draw F6"), "Draw", DrawProc},
677 {N_("Adjourn F7"), "Adjourn", AdjournProc},
678 {N_("Abort F8"),"Abort", AbortProc},
679 {N_("Resign F9"), "Resign", ResignProc},
680 {"----", NULL, NothingProc},
681 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
682 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
683 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
684 {"----", NULL, NothingProc},
685 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
686 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
687 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
691 MenuItem engineMenu[] = {
692 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
693 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
694 {"----", NULL, NothingProc},
695 {N_("Hint"), "Hint", HintProc},
696 {N_("Book"), "Book", BookProc},
697 {"----", NULL, NothingProc},
698 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
699 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
703 MenuItem optionsMenu[] = {
704 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
705 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
706 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
707 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
708 {"----", NULL, NothingProc},
709 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
710 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
711 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
712 {N_("Auto Comment"), "Auto Comment", AutocommProc},
713 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
714 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
715 {N_("Auto Observe"), "Auto Observe", AutobsProc},
716 {N_("Auto Raise Board"), "Auto Raise Board", AutoraiseProc},
717 {N_("Auto Save"), "Auto Save", AutosaveProc},
718 {N_("Blindfold"), "Blindfold", BlindfoldProc},
719 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
720 {N_("Get Move List"), "Get Move List", GetMoveListProc},
722 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
724 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
725 {N_("Move Sound"), "Move Sound", MoveSoundProc},
726 {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
727 {N_("Old Save Style"), "Old Save Style", OldSaveStyleProc},
728 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
729 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
730 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
731 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
732 {N_("Premove"), "Premove", PremoveProc},
733 {N_("Quiet Play"), "Quiet Play", QuietPlayProc},
734 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
735 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
736 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
737 {"----", NULL, NothingProc},
738 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
739 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
743 MenuItem helpMenu[] = {
744 {N_("Info XBoard"), "Info XBoard", InfoProc},
745 {N_("Man XBoard F1"), "Man XBoard", ManProc},
746 {"----", NULL, NothingProc},
747 {N_("About XBoard"), "About XBoard", AboutProc},
752 {N_("File"), "File", fileMenu},
753 {N_("Edit"), "Edit", editMenu},
754 {N_("View"), "View", viewMenu},
755 {N_("Mode"), "Mode", modeMenu},
756 {N_("Action"), "Action", actionMenu},
757 {N_("Engine"), "Engine", engineMenu},
758 {N_("Options"), "Options", optionsMenu},
759 {N_("Help"), "Help", helpMenu},
763 #define PAUSE_BUTTON "P"
764 MenuItem buttonBar[] = {
765 {"<<", "<<", ToStartProc},
766 {"<", "<", BackwardProc},
767 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
768 {">", ">", ForwardProc},
769 {">>", ">>", ToEndProc},
773 #define PIECE_MENU_SIZE 18
774 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
775 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
776 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
777 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
778 N_("Empty square"), N_("Clear board") },
779 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
780 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
781 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
782 N_("Empty square"), N_("Clear board") }
784 /* must be in same order as PieceMenuStrings! */
785 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
786 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
787 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
788 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
789 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
790 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
791 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
792 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
793 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
796 #define DROP_MENU_SIZE 6
797 String dropMenuStrings[DROP_MENU_SIZE] = {
798 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
800 /* must be in same order as PieceMenuStrings! */
801 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
802 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
803 WhiteRook, WhiteQueen
811 DropMenuEnables dmEnables[] = {
829 { XtNborderWidth, 0 },
830 { XtNdefaultDistance, 0 },
834 { XtNborderWidth, 0 },
835 { XtNresizable, (XtArgVal) True },
839 { XtNborderWidth, 0 },
845 { XtNjustify, (XtArgVal) XtJustifyRight },
846 { XtNlabel, (XtArgVal) "..." },
847 { XtNresizable, (XtArgVal) True },
848 { XtNresize, (XtArgVal) False }
851 Arg messageArgs[] = {
852 { XtNjustify, (XtArgVal) XtJustifyLeft },
853 { XtNlabel, (XtArgVal) "..." },
854 { XtNresizable, (XtArgVal) True },
855 { XtNresize, (XtArgVal) False }
859 { XtNborderWidth, 0 },
860 { XtNjustify, (XtArgVal) XtJustifyLeft }
863 XtResource clientResources[] = {
864 { "flashCount", "flashCount", XtRInt, sizeof(int),
865 XtOffset(AppDataPtr, flashCount), XtRImmediate,
866 (XtPointer) FLASH_COUNT },
869 XrmOptionDescRec shellOptions[] = {
870 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
871 { "-flash", "flashCount", XrmoptionNoArg, "3" },
872 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
875 XtActionsRec boardActions[] = {
876 { "DrawPosition", DrawPositionProc },
877 { "HandleUserMove", HandleUserMove },
878 { "AnimateUserMove", AnimateUserMove },
879 { "HandlePV", HandlePV },
880 { "SelectPV", SelectPV },
881 { "StopPV", StopPV },
882 { "FileNameAction", FileNameAction },
883 { "AskQuestionProc", AskQuestionProc },
884 { "AskQuestionReplyAction", AskQuestionReplyAction },
885 { "PieceMenuPopup", PieceMenuPopup },
886 { "WhiteClock", WhiteClock },
887 { "BlackClock", BlackClock },
888 { "Iconify", Iconify },
889 { "ResetProc", ResetProc },
890 { "NewVariantProc", NewVariantProc },
891 { "LoadGameProc", LoadGameProc },
892 { "LoadNextGameProc", LoadNextGameProc },
893 { "LoadPrevGameProc", LoadPrevGameProc },
894 { "LoadSelectedProc", LoadSelectedProc },
895 { "SetFilterProc", SetFilterProc },
896 { "ReloadGameProc", ReloadGameProc },
897 { "LoadPositionProc", LoadPositionProc },
898 { "LoadNextPositionProc", LoadNextPositionProc },
899 { "LoadPrevPositionProc", LoadPrevPositionProc },
900 { "ReloadPositionProc", ReloadPositionProc },
901 { "CopyPositionProc", CopyPositionProc },
902 { "PastePositionProc", PastePositionProc },
903 { "CopyGameProc", CopyGameProc },
904 { "PasteGameProc", PasteGameProc },
905 { "SaveGameProc", SaveGameProc },
906 { "SavePositionProc", SavePositionProc },
907 { "MailMoveProc", MailMoveProc },
908 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
909 { "QuitProc", QuitProc },
910 { "MachineWhiteProc", MachineWhiteProc },
911 { "MachineBlackProc", MachineBlackProc },
912 { "AnalysisModeProc", AnalyzeModeProc },
913 { "AnalyzeFileProc", AnalyzeFileProc },
914 { "TwoMachinesProc", TwoMachinesProc },
915 { "IcsClientProc", IcsClientProc },
916 { "EditGameProc", EditGameProc },
917 { "EditPositionProc", EditPositionProc },
918 { "TrainingProc", EditPositionProc },
919 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
920 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
921 { "ShowGameListProc", ShowGameListProc },
922 { "ShowMoveListProc", HistoryShowProc},
923 { "EditTagsProc", EditCommentProc },
924 { "EditCommentProc", EditCommentProc },
925 { "IcsAlarmProc", IcsAlarmProc },
926 { "IcsInputBoxProc", IcsInputBoxProc },
927 { "PauseProc", PauseProc },
928 { "AcceptProc", AcceptProc },
929 { "DeclineProc", DeclineProc },
930 { "RematchProc", RematchProc },
931 { "CallFlagProc", CallFlagProc },
932 { "DrawProc", DrawProc },
933 { "AdjournProc", AdjournProc },
934 { "AbortProc", AbortProc },
935 { "ResignProc", ResignProc },
936 { "AdjuWhiteProc", AdjuWhiteProc },
937 { "AdjuBlackProc", AdjuBlackProc },
938 { "AdjuDrawProc", AdjuDrawProc },
939 { "EnterKeyProc", EnterKeyProc },
940 { "UpKeyProc", UpKeyProc },
941 { "DownKeyProc", DownKeyProc },
942 { "StopObservingProc", StopObservingProc },
943 { "StopExaminingProc", StopExaminingProc },
944 { "UploadProc", UploadProc },
945 { "BackwardProc", BackwardProc },
946 { "ForwardProc", ForwardProc },
947 { "ToStartProc", ToStartProc },
948 { "ToEndProc", ToEndProc },
949 { "RevertProc", RevertProc },
950 { "AnnotateProc", AnnotateProc },
951 { "TruncateGameProc", TruncateGameProc },
952 { "MoveNowProc", MoveNowProc },
953 { "RetractMoveProc", RetractMoveProc },
954 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
955 { "UciMenuProc", (XtActionProc) UciMenuProc },
956 { "TimeControlProc", (XtActionProc) TimeControlProc },
957 { "AlwaysQueenProc", AlwaysQueenProc },
958 { "AnimateDraggingProc", AnimateDraggingProc },
959 { "AnimateMovingProc", AnimateMovingProc },
960 { "AutoflagProc", AutoflagProc },
961 { "AutoflipProc", AutoflipProc },
962 { "AutobsProc", AutobsProc },
963 { "AutoraiseProc", AutoraiseProc },
964 { "AutosaveProc", AutosaveProc },
965 { "BlindfoldProc", BlindfoldProc },
966 { "FlashMovesProc", FlashMovesProc },
967 { "FlipViewProc", FlipViewProc },
968 { "GetMoveListProc", GetMoveListProc },
970 { "HighlightDraggingProc", HighlightDraggingProc },
972 { "HighlightLastMoveProc", HighlightLastMoveProc },
973 { "IcsAlarmProc", IcsAlarmProc },
974 { "MoveSoundProc", MoveSoundProc },
975 { "OldSaveStyleProc", OldSaveStyleProc },
976 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
977 { "PonderNextMoveProc", PonderNextMoveProc },
978 { "PopupExitMessageProc", PopupExitMessageProc },
979 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
980 { "PremoveProc", PremoveProc },
981 { "QuietPlayProc", QuietPlayProc },
982 { "ShowCoordsProc", ShowCoordsProc },
983 { "ShowThinkingProc", ShowThinkingProc },
984 { "HideThinkingProc", HideThinkingProc },
985 { "TestLegalityProc", TestLegalityProc },
986 { "SaveSettingsProc", SaveSettingsProc },
987 { "SaveOnExitProc", SaveOnExitProc },
988 { "InfoProc", InfoProc },
989 { "ManProc", ManProc },
990 { "HintProc", HintProc },
991 { "BookProc", BookProc },
992 { "AboutGameProc", AboutGameProc },
993 { "AboutProc", AboutProc },
994 { "DebugProc", DebugProc },
995 { "NothingProc", NothingProc },
996 { "CommentClick", (XtActionProc) CommentClick },
997 { "CommentPopDown", (XtActionProc) CommentPopDown },
998 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
999 { "TagsPopDown", (XtActionProc) TagsPopDown },
1000 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1001 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1002 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1003 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1004 { "GameListPopDown", (XtActionProc) GameListPopDown },
1005 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1006 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1007 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1008 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1009 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1010 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1011 { "EnginePopDown", (XtActionProc) EnginePopDown },
1012 { "UciPopDown", (XtActionProc) UciPopDown },
1013 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1014 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1015 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1016 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1019 char globalTranslations[] =
1020 ":<Key>F9: ResignProc() \n \
1021 :Ctrl<Key>n: ResetProc() \n \
1022 :Meta<Key>V: NewVariantProc() \n \
1023 :Ctrl<Key>o: LoadGameProc() \n \
1024 :Meta<Key>Next: LoadNextGameProc() \n \
1025 :Meta<Key>Prior: LoadPrevGameProc() \n \
1026 :Ctrl<Key>s: SaveGameProc() \n \
1027 :Ctrl<Key>c: CopyGameProc() \n \
1028 :Ctrl<Key>v: PasteGameProc() \n \
1029 :Ctrl<Key>O: LoadPositionProc() \n \
1030 :Shift Meta<Key>Next: LoadNextPositionProc() \n \
1031 :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
1032 :Ctrl<Key>S: SavePositionProc() \n \
1033 :Ctrl<Key>C: CopyPositionProc() \n \
1034 :Ctrl<Key>V: PastePositionProc() \n \
1035 :Ctrl<Key>q: QuitProc() \n \
1036 :Ctrl<Key>w: MachineWhiteProc() \n \
1037 :Ctrl<Key>b: MachineBlackProc() \n \
1038 :Ctrl<Key>t: TwoMachinesProc() \n \
1039 :Ctrl<Key>a: AnalysisModeProc() \n \
1040 :Ctrl<Key>f: AnalyzeFileProc() \n \
1041 :Ctrl<Key>e: EditGameProc() \n \
1042 :Ctrl<Key>E: EditPositionProc() \n \
1043 :Meta<Key>O: EngineOutputProc() \n \
1044 :Meta<Key>E: EvalGraphProc() \n \
1045 :Meta<Key>G: ShowGameListProc() \n \
1046 :Meta<Key>H: ShowMoveListProc() \n \
1047 :<Key>Pause: PauseProc() \n \
1048 :<Key>F3: AcceptProc() \n \
1049 :<Key>F4: DeclineProc() \n \
1050 :<Key>F12: RematchProc() \n \
1051 :<Key>F5: CallFlagProc() \n \
1052 :<Key>F6: DrawProc() \n \
1053 :<Key>F7: AdjournProc() \n \
1054 :<Key>F8: AbortProc() \n \
1055 :<Key>F10: StopObservingProc() \n \
1056 :<Key>F11: StopExaminingProc() \n \
1057 :Meta Ctrl<Key>F12: DebugProc() \n \
1058 :Meta<Key>End: ToEndProc() \n \
1059 :Meta<Key>Right: ForwardProc() \n \
1060 :Meta<Key>Home: ToStartProc() \n \
1061 :Meta<Key>Left: BackwardProc() \n \
1062 :<Key>Home: RevertProc() \n \
1063 :<Key>End: TruncateGameProc() \n \
1064 :Ctrl<Key>m: MoveNowProc() \n \
1065 :Ctrl<Key>x: RetractMoveProc() \n \
1066 :Meta<Key>J: EngineMenuProc() \n \
1067 :Meta<Key>U: UciMenuProc() \n \
1068 :Meta<Key>T: TimeControlProc() \n \
1069 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1070 :Ctrl<Key>F: AutoflagProc() \n \
1071 :Ctrl<Key>A: AnimateMovingProc() \n \
1072 :Ctrl<Key>P: PonderNextMoveProc() \n \
1073 :Ctrl<Key>L: TestLegalityProc() \n \
1074 :Ctrl<Key>H: HideThinkingProc() \n \
1075 :<Key>-: Iconify() \n \
1076 :<Key>F1: ManProc() \n \
1077 :<Key>F2: FlipViewProc() \n \
1078 <KeyDown>.: BackwardProc() \n \
1079 <KeyUp>.: ForwardProc() \n \
1080 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1081 \"Send to chess program:\",,1) \n \
1082 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1083 \"Send to second chess program:\",,2) \n";
1085 char boardTranslations[] =
1086 "<Btn1Down>: HandleUserMove(0) \n \
1087 Shift<Btn1Up>: HandleUserMove(1) \n \
1088 <Btn1Up>: HandleUserMove(0) \n \
1089 <Btn1Motion>: AnimateUserMove() \n \
1090 <Btn3Motion>: HandlePV() \n \
1091 <Btn3Up>: PieceMenuPopup(menuB) \n \
1092 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1093 PieceMenuPopup(menuB) \n \
1094 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1095 PieceMenuPopup(menuW) \n \
1096 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1097 PieceMenuPopup(menuW) \n \
1098 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1099 PieceMenuPopup(menuB) \n";
1101 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1102 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1104 char ICSInputTranslations[] =
1105 "<Key>Up: UpKeyProc() \n "
1106 "<Key>Down: DownKeyProc() \n "
1107 "<Key>Return: EnterKeyProc() \n";
1109 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1110 // as the widget is destroyed before the up-click can call extend-end
1111 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1113 String xboardResources[] = {
1114 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1115 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1116 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1121 /* Max possible square size */
1122 #define MAXSQSIZE 256
1124 static int xpm_avail[MAXSQSIZE];
1126 #ifdef HAVE_DIR_STRUCT
1128 /* Extract piece size from filename */
1130 xpm_getsize(name, len, ext)
1141 if ((p=strchr(name, '.')) == NULL ||
1142 StrCaseCmp(p+1, ext) != 0)
1148 while (*p && isdigit(*p))
1155 /* Setup xpm_avail */
1157 xpm_getavail(dirname, ext)
1165 for (i=0; i<MAXSQSIZE; ++i)
1168 if (appData.debugMode)
1169 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1171 dir = opendir(dirname);
1174 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1175 programName, dirname);
1179 while ((ent=readdir(dir)) != NULL) {
1180 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1181 if (i > 0 && i < MAXSQSIZE)
1191 xpm_print_avail(fp, ext)
1197 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1198 for (i=1; i<MAXSQSIZE; ++i) {
1204 /* Return XPM piecesize closest to size */
1206 xpm_closest_to(dirname, size, ext)
1212 int sm_diff = MAXSQSIZE;
1216 xpm_getavail(dirname, ext);
1218 if (appData.debugMode)
1219 xpm_print_avail(stderr, ext);
1221 for (i=1; i<MAXSQSIZE; ++i) {
1224 diff = (diff<0) ? -diff : diff;
1225 if (diff < sm_diff) {
1233 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1239 #else /* !HAVE_DIR_STRUCT */
1240 /* If we are on a system without a DIR struct, we can't
1241 read the directory, so we can't collect a list of
1242 filenames, etc., so we can't do any size-fitting. */
1244 xpm_closest_to(dirname, size, ext)
1249 fprintf(stderr, _("\
1250 Warning: No DIR structure found on this system --\n\
1251 Unable to autosize for XPM/XIM pieces.\n\
1252 Please report this error to frankm@hiwaay.net.\n\
1253 Include system type & operating system in message.\n"));
1256 #endif /* HAVE_DIR_STRUCT */
1258 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1259 "magenta", "cyan", "white" };
1263 TextColors textColors[(int)NColorClasses];
1265 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1267 parse_color(str, which)
1271 char *p, buf[100], *d;
1274 if (strlen(str) > 99) /* watch bounds on buf */
1279 for (i=0; i<which; ++i) {
1286 /* Could be looking at something like:
1288 .. in which case we want to stop on a comma also */
1289 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1293 return -1; /* Use default for empty field */
1296 if (which == 2 || isdigit(*p))
1299 while (*p && isalpha(*p))
1304 for (i=0; i<8; ++i) {
1305 if (!StrCaseCmp(buf, cnames[i]))
1306 return which? (i+40) : (i+30);
1308 if (!StrCaseCmp(buf, "default")) return -1;
1310 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1315 parse_cpair(cc, str)
1319 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1320 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1325 /* bg and attr are optional */
1326 textColors[(int)cc].bg = parse_color(str, 1);
1327 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1328 textColors[(int)cc].attr = 0;
1334 /* Arrange to catch delete-window events */
1335 Atom wm_delete_window;
1337 CatchDeleteWindow(Widget w, String procname)
1340 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1341 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1342 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1349 XtSetArg(args[0], XtNiconic, False);
1350 XtSetValues(shellWidget, args, 1);
1352 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1355 //---------------------------------------------------------------------------------------------------------
1356 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1359 #define CW_USEDEFAULT (1<<31)
1360 #define ICS_TEXT_MENU_SIZE 90
1361 #define DEBUG_FILE "xboard.debug"
1362 #define SetCurrentDirectory chdir
1363 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1367 // these two must some day move to frontend.h, when they are implemented
1368 Boolean GameListIsUp();
1370 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1373 // front-end part of option handling
1375 // [HGM] This platform-dependent table provides the location for storing the color info
1376 extern char *crWhite, * crBlack;
1380 &appData.whitePieceColor,
1381 &appData.blackPieceColor,
1382 &appData.lightSquareColor,
1383 &appData.darkSquareColor,
1384 &appData.highlightSquareColor,
1385 &appData.premoveHighlightColor,
1386 &appData.lowTimeWarningColor,
1397 // [HGM] font: keep a font for each square size, even non-stndard ones
1398 #define NUM_SIZES 18
1399 #define MAX_SIZE 130
1400 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1401 char *fontTable[NUM_FONTS][MAX_SIZE];
1404 ParseFont(char *name, int number)
1405 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1407 if(sscanf(name, "size%d:", &size)) {
1408 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1409 // defer processing it until we know if it matches our board size
1410 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1411 fontTable[number][size] = strdup(strchr(name, ':')+1);
1412 fontValid[number][size] = True;
1417 case 0: // CLOCK_FONT
1418 appData.clockFont = strdup(name);
1420 case 1: // MESSAGE_FONT
1421 appData.font = strdup(name);
1423 case 2: // COORD_FONT
1424 appData.coordFont = strdup(name);
1429 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1434 { // only 2 fonts currently
1435 appData.clockFont = CLOCK_FONT_NAME;
1436 appData.coordFont = COORD_FONT_NAME;
1437 appData.font = DEFAULT_FONT_NAME;
1442 { // no-op, until we identify the code for this already in XBoard and move it here
1446 ParseColor(int n, char *name)
1447 { // in XBoard, just copy the color-name string
1448 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1452 ParseTextAttribs(ColorClass cc, char *s)
1454 (&appData.colorShout)[cc] = strdup(s);
1458 ParseBoardSize(void *addr, char *name)
1460 appData.boardSize = strdup(name);
1465 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1469 SetCommPortDefaults()
1470 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1473 // [HGM] args: these three cases taken out to stay in front-end
1475 SaveFontArg(FILE *f, ArgDescriptor *ad)
1478 int i, n = (int)ad->argLoc;
1480 case 0: // CLOCK_FONT
1481 name = appData.clockFont;
1483 case 1: // MESSAGE_FONT
1484 name = appData.font;
1486 case 2: // COORD_FONT
1487 name = appData.coordFont;
1492 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1493 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1494 fontTable[n][squareSize] = strdup(name);
1495 fontValid[n][squareSize] = True;
1498 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1499 fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]);
1504 { // nothing to do, as the sounds are at all times represented by their text-string names already
1508 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1509 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1510 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1514 SaveColor(FILE *f, ArgDescriptor *ad)
1515 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1516 if(colorVariable[(int)ad->argLoc])
1517 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1521 SaveBoardSize(FILE *f, char *name, void *addr)
1522 { // wrapper to shield back-end from BoardSize & sizeInfo
1523 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1527 ParseCommPortSettings(char *s)
1528 { // no such option in XBoard (yet)
1531 extern Widget engineOutputShell;
1532 extern Widget tagsShell, editTagsShell;
1534 GetActualPlacement(Widget wg, WindowPlacement *wp)
1544 XtSetArg(args[i], XtNx, &x); i++;
1545 XtSetArg(args[i], XtNy, &y); i++;
1546 XtSetArg(args[i], XtNwidth, &w); i++;
1547 XtSetArg(args[i], XtNheight, &h); i++;
1548 XtGetValues(wg, args, i);
1557 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1558 // In XBoard this will have to wait until awareness of window parameters is implemented
1559 GetActualPlacement(shellWidget, &wpMain);
1560 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1561 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1562 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1563 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1564 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1565 else GetActualPlacement(editShell, &wpComment);
1566 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1567 else GetActualPlacement(editTagsShell, &wpTags);
1571 PrintCommPortSettings(FILE *f, char *name)
1572 { // This option does not exist in XBoard
1576 MySearchPath(char *installDir, char *name, char *fullname)
1577 { // just append installDir and name. Perhaps ExpandPath should be used here?
1578 name = ExpandPathName(name);
1579 if(name && name[0] == '/')
1580 safeStrCpy(fullname, name, MSG_SIZ );
1582 sprintf(fullname, "%s%c%s", installDir, '/', name);
1588 MyGetFullPathName(char *name, char *fullname)
1589 { // should use ExpandPath?
1590 name = ExpandPathName(name);
1591 safeStrCpy(fullname, name, MSG_SIZ );
1596 EnsureOnScreen(int *x, int *y, int minX, int minY)
1603 { // [HGM] args: allows testing if main window is realized from back-end
1604 return xBoardWindow != 0;
1608 PopUpStartupDialog()
1609 { // start menu not implemented in XBoard
1613 ConvertToLine(int argc, char **argv)
1615 static char line[128*1024], buf[1024];
1619 for(i=1; i<argc; i++)
1621 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1622 && argv[i][0] != '{' )
1623 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1625 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1626 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1629 line[strlen(line)-1] = NULLCHAR;
1633 //--------------------------------------------------------------------------------------------
1635 extern Boolean twoBoards, partnerUp;
1638 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1640 #define BoardSize int
1641 void InitDrawingSizes(BoardSize boardSize, int flags)
1642 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1643 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1645 XtGeometryResult gres;
1648 if(!formWidget) return;
1651 * Enable shell resizing.
1653 shellArgs[0].value = (XtArgVal) &w;
1654 shellArgs[1].value = (XtArgVal) &h;
1655 XtGetValues(shellWidget, shellArgs, 2);
1657 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1658 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1659 XtSetValues(shellWidget, &shellArgs[2], 4);
1661 XtSetArg(args[0], XtNdefaultDistance, &sep);
1662 XtGetValues(formWidget, args, 1);
1664 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1665 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1667 hOffset = boardWidth + 10;
1668 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1669 secondSegments[i] = gridSegments[i];
1670 secondSegments[i].x1 += hOffset;
1671 secondSegments[i].x2 += hOffset;
1674 XtSetArg(args[0], XtNwidth, boardWidth);
1675 XtSetArg(args[1], XtNheight, boardHeight);
1676 XtSetValues(boardWidget, args, 2);
1678 timerWidth = (boardWidth - sep) / 2;
1679 XtSetArg(args[0], XtNwidth, timerWidth);
1680 XtSetValues(whiteTimerWidget, args, 1);
1681 XtSetValues(blackTimerWidget, args, 1);
1683 XawFormDoLayout(formWidget, False);
1685 if (appData.titleInWindow) {
1687 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1688 XtSetArg(args[i], XtNheight, &h); i++;
1689 XtGetValues(titleWidget, args, i);
1691 w = boardWidth - 2*bor;
1693 XtSetArg(args[0], XtNwidth, &w);
1694 XtGetValues(menuBarWidget, args, 1);
1695 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1698 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1699 if (gres != XtGeometryYes && appData.debugMode) {
1701 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1702 programName, gres, w, h, wr, hr);
1706 XawFormDoLayout(formWidget, True);
1709 * Inhibit shell resizing.
1711 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1712 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1713 shellArgs[4].value = shellArgs[2].value = w;
1714 shellArgs[5].value = shellArgs[3].value = h;
1715 XtSetValues(shellWidget, &shellArgs[0], 6);
1717 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1720 for(i=0; i<4; i++) {
1722 for(p=0; p<=(int)WhiteKing; p++)
1723 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1724 if(gameInfo.variant == VariantShogi) {
1725 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1726 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1727 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1728 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1729 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1732 if(gameInfo.variant == VariantGothic) {
1733 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1736 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1737 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1738 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1741 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1742 for(p=0; p<=(int)WhiteKing; p++)
1743 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1744 if(gameInfo.variant == VariantShogi) {
1745 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1746 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1747 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1748 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1749 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1752 if(gameInfo.variant == VariantGothic) {
1753 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1756 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1757 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1758 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1763 for(i=0; i<2; i++) {
1765 for(p=0; p<=(int)WhiteKing; p++)
1766 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1767 if(gameInfo.variant == VariantShogi) {
1768 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1769 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1770 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1771 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1772 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1775 if(gameInfo.variant == VariantGothic) {
1776 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1779 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1780 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1781 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1796 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1797 XSetWindowAttributes window_attributes;
1799 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1800 XrmValue vFrom, vTo;
1801 XtGeometryResult gres;
1804 int forceMono = False;
1806 srandom(time(0)); // [HGM] book: make random truly random
1808 setbuf(stdout, NULL);
1809 setbuf(stderr, NULL);
1812 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1813 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1817 programName = strrchr(argv[0], '/');
1818 if (programName == NULL)
1819 programName = argv[0];
1824 XtSetLanguageProc(NULL, NULL, NULL);
1825 bindtextdomain(PACKAGE, LOCALEDIR);
1826 textdomain(PACKAGE);
1830 XtAppInitialize(&appContext, "XBoard", shellOptions,
1831 XtNumber(shellOptions),
1832 &argc, argv, xboardResources, NULL, 0);
1833 appData.boardSize = "";
1834 InitAppData(ConvertToLine(argc, argv));
1836 if (p == NULL) p = "/tmp";
1837 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1838 gameCopyFilename = (char*) malloc(i);
1839 gamePasteFilename = (char*) malloc(i);
1840 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1841 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1843 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1844 clientResources, XtNumber(clientResources),
1847 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1848 static char buf[MSG_SIZ];
1849 EscapeExpand(buf, appData.initString);
1850 appData.initString = strdup(buf);
1851 EscapeExpand(buf, appData.secondInitString);
1852 appData.secondInitString = strdup(buf);
1853 EscapeExpand(buf, appData.firstComputerString);
1854 appData.firstComputerString = strdup(buf);
1855 EscapeExpand(buf, appData.secondComputerString);
1856 appData.secondComputerString = strdup(buf);
1859 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1862 if (chdir(chessDir) != 0) {
1863 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1869 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1870 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1871 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1872 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1875 setbuf(debugFP, NULL);
1878 /* [HGM,HR] make sure board size is acceptable */
1879 if(appData.NrFiles > BOARD_FILES ||
1880 appData.NrRanks > BOARD_RANKS )
1881 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1884 /* This feature does not work; animation needs a rewrite */
1885 appData.highlightDragging = FALSE;
1889 xDisplay = XtDisplay(shellWidget);
1890 xScreen = DefaultScreen(xDisplay);
1891 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1893 gameInfo.variant = StringToVariant(appData.variant);
1894 InitPosition(FALSE);
1897 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1899 if (isdigit(appData.boardSize[0])) {
1900 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1901 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1902 &fontPxlSize, &smallLayout, &tinyLayout);
1904 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1905 programName, appData.boardSize);
1909 /* Find some defaults; use the nearest known size */
1910 SizeDefaults *szd, *nearest;
1911 int distance = 99999;
1912 nearest = szd = sizeDefaults;
1913 while (szd->name != NULL) {
1914 if (abs(szd->squareSize - squareSize) < distance) {
1916 distance = abs(szd->squareSize - squareSize);
1917 if (distance == 0) break;
1921 if (i < 2) lineGap = nearest->lineGap;
1922 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1923 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1924 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1925 if (i < 6) smallLayout = nearest->smallLayout;
1926 if (i < 7) tinyLayout = nearest->tinyLayout;
1929 SizeDefaults *szd = sizeDefaults;
1930 if (*appData.boardSize == NULLCHAR) {
1931 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1932 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1935 if (szd->name == NULL) szd--;
1936 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1938 while (szd->name != NULL &&
1939 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1940 if (szd->name == NULL) {
1941 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1942 programName, appData.boardSize);
1946 squareSize = szd->squareSize;
1947 lineGap = szd->lineGap;
1948 clockFontPxlSize = szd->clockFontPxlSize;
1949 coordFontPxlSize = szd->coordFontPxlSize;
1950 fontPxlSize = szd->fontPxlSize;
1951 smallLayout = szd->smallLayout;
1952 tinyLayout = szd->tinyLayout;
1953 // [HGM] font: use defaults from settings file if available and not overruled
1955 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
1956 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
1957 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
1958 appData.font = fontTable[MESSAGE_FONT][squareSize];
1959 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
1960 appData.coordFont = fontTable[COORD_FONT][squareSize];
1962 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1963 if (strlen(appData.pixmapDirectory) > 0) {
1964 p = ExpandPathName(appData.pixmapDirectory);
1966 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1967 appData.pixmapDirectory);
1970 if (appData.debugMode) {
1971 fprintf(stderr, _("\
1972 XBoard square size (hint): %d\n\
1973 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1975 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1976 if (appData.debugMode) {
1977 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1980 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1982 /* [HR] height treated separately (hacked) */
1983 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1984 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1985 if (appData.showJail == 1) {
1986 /* Jail on top and bottom */
1987 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1988 XtSetArg(boardArgs[2], XtNheight,
1989 boardHeight + 2*(lineGap + squareSize));
1990 } else if (appData.showJail == 2) {
1992 XtSetArg(boardArgs[1], XtNwidth,
1993 boardWidth + 2*(lineGap + squareSize));
1994 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1997 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1998 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2002 * Determine what fonts to use.
2004 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2005 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2006 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2007 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2008 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2009 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2010 appData.font = FindFont(appData.font, fontPxlSize);
2011 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2012 countFontStruct = XQueryFont(xDisplay, countFontID);
2013 // appData.font = FindFont(appData.font, fontPxlSize);
2015 xdb = XtDatabase(xDisplay);
2016 XrmPutStringResource(&xdb, "*font", appData.font);
2019 * Detect if there are not enough colors available and adapt.
2021 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2022 appData.monoMode = True;
2025 if (!appData.monoMode) {
2026 vFrom.addr = (caddr_t) appData.lightSquareColor;
2027 vFrom.size = strlen(appData.lightSquareColor);
2028 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2029 if (vTo.addr == NULL) {
2030 appData.monoMode = True;
2033 lightSquareColor = *(Pixel *) vTo.addr;
2036 if (!appData.monoMode) {
2037 vFrom.addr = (caddr_t) appData.darkSquareColor;
2038 vFrom.size = strlen(appData.darkSquareColor);
2039 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2040 if (vTo.addr == NULL) {
2041 appData.monoMode = True;
2044 darkSquareColor = *(Pixel *) vTo.addr;
2047 if (!appData.monoMode) {
2048 vFrom.addr = (caddr_t) appData.whitePieceColor;
2049 vFrom.size = strlen(appData.whitePieceColor);
2050 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2051 if (vTo.addr == NULL) {
2052 appData.monoMode = True;
2055 whitePieceColor = *(Pixel *) vTo.addr;
2058 if (!appData.monoMode) {
2059 vFrom.addr = (caddr_t) appData.blackPieceColor;
2060 vFrom.size = strlen(appData.blackPieceColor);
2061 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2062 if (vTo.addr == NULL) {
2063 appData.monoMode = True;
2066 blackPieceColor = *(Pixel *) vTo.addr;
2070 if (!appData.monoMode) {
2071 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2072 vFrom.size = strlen(appData.highlightSquareColor);
2073 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2074 if (vTo.addr == NULL) {
2075 appData.monoMode = True;
2078 highlightSquareColor = *(Pixel *) vTo.addr;
2082 if (!appData.monoMode) {
2083 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2084 vFrom.size = strlen(appData.premoveHighlightColor);
2085 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2086 if (vTo.addr == NULL) {
2087 appData.monoMode = True;
2090 premoveHighlightColor = *(Pixel *) vTo.addr;
2095 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2098 if (appData.bitmapDirectory == NULL ||
2099 appData.bitmapDirectory[0] == NULLCHAR)
2100 appData.bitmapDirectory = DEF_BITMAP_DIR;
2103 if (appData.lowTimeWarning && !appData.monoMode) {
2104 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2105 vFrom.size = strlen(appData.lowTimeWarningColor);
2106 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2107 if (vTo.addr == NULL)
2108 appData.monoMode = True;
2110 lowTimeWarningColor = *(Pixel *) vTo.addr;
2113 if (appData.monoMode && appData.debugMode) {
2114 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2115 (unsigned long) XWhitePixel(xDisplay, xScreen),
2116 (unsigned long) XBlackPixel(xDisplay, xScreen));
2119 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2120 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2121 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2122 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2123 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2124 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2125 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2126 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2127 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2128 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2130 if (appData.colorize) {
2132 _("%s: can't parse color names; disabling colorization\n"),
2135 appData.colorize = FALSE;
2137 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2138 textColors[ColorNone].attr = 0;
2140 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2146 layoutName = "tinyLayout";
2147 } else if (smallLayout) {
2148 layoutName = "smallLayout";
2150 layoutName = "normalLayout";
2152 /* Outer layoutWidget is there only to provide a name for use in
2153 resources that depend on the layout style */
2155 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2156 layoutArgs, XtNumber(layoutArgs));
2158 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2159 formArgs, XtNumber(formArgs));
2160 XtSetArg(args[0], XtNdefaultDistance, &sep);
2161 XtGetValues(formWidget, args, 1);
2164 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2165 XtSetArg(args[0], XtNtop, XtChainTop);
2166 XtSetArg(args[1], XtNbottom, XtChainTop);
2167 XtSetArg(args[2], XtNright, XtChainLeft);
2168 XtSetValues(menuBarWidget, args, 3);
2170 widgetList[j++] = whiteTimerWidget =
2171 XtCreateWidget("whiteTime", labelWidgetClass,
2172 formWidget, timerArgs, XtNumber(timerArgs));
2173 XtSetArg(args[0], XtNfont, clockFontStruct);
2174 XtSetArg(args[1], XtNtop, XtChainTop);
2175 XtSetArg(args[2], XtNbottom, XtChainTop);
2176 XtSetValues(whiteTimerWidget, args, 3);
2178 widgetList[j++] = blackTimerWidget =
2179 XtCreateWidget("blackTime", labelWidgetClass,
2180 formWidget, timerArgs, XtNumber(timerArgs));
2181 XtSetArg(args[0], XtNfont, clockFontStruct);
2182 XtSetArg(args[1], XtNtop, XtChainTop);
2183 XtSetArg(args[2], XtNbottom, XtChainTop);
2184 XtSetValues(blackTimerWidget, args, 3);
2186 if (appData.titleInWindow) {
2187 widgetList[j++] = titleWidget =
2188 XtCreateWidget("title", labelWidgetClass, formWidget,
2189 titleArgs, XtNumber(titleArgs));
2190 XtSetArg(args[0], XtNtop, XtChainTop);
2191 XtSetArg(args[1], XtNbottom, XtChainTop);
2192 XtSetValues(titleWidget, args, 2);
2195 if (appData.showButtonBar) {
2196 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2197 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2198 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2199 XtSetArg(args[2], XtNtop, XtChainTop);
2200 XtSetArg(args[3], XtNbottom, XtChainTop);
2201 XtSetValues(buttonBarWidget, args, 4);
2204 widgetList[j++] = messageWidget =
2205 XtCreateWidget("message", labelWidgetClass, formWidget,
2206 messageArgs, XtNumber(messageArgs));
2207 XtSetArg(args[0], XtNtop, XtChainTop);
2208 XtSetArg(args[1], XtNbottom, XtChainTop);
2209 XtSetValues(messageWidget, args, 2);
2211 widgetList[j++] = boardWidget =
2212 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2213 XtNumber(boardArgs));
2215 XtManageChildren(widgetList, j);
2217 timerWidth = (boardWidth - sep) / 2;
2218 XtSetArg(args[0], XtNwidth, timerWidth);
2219 XtSetValues(whiteTimerWidget, args, 1);
2220 XtSetValues(blackTimerWidget, args, 1);
2222 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2223 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2224 XtGetValues(whiteTimerWidget, args, 2);
2226 if (appData.showButtonBar) {
2227 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2228 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2229 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2233 * formWidget uses these constraints but they are stored
2237 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2238 XtSetValues(menuBarWidget, args, i);
2239 if (appData.titleInWindow) {
2242 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2243 XtSetValues(whiteTimerWidget, args, i);
2245 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2246 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2247 XtSetValues(blackTimerWidget, args, i);
2249 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2250 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2251 XtSetValues(titleWidget, args, i);
2253 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2254 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2255 XtSetValues(messageWidget, args, i);
2256 if (appData.showButtonBar) {
2258 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2259 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2260 XtSetValues(buttonBarWidget, args, i);
2264 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2265 XtSetValues(whiteTimerWidget, args, i);
2267 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2268 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2269 XtSetValues(blackTimerWidget, args, i);
2271 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2272 XtSetValues(titleWidget, args, i);
2274 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2275 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2276 XtSetValues(messageWidget, args, i);
2277 if (appData.showButtonBar) {
2279 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2280 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2281 XtSetValues(buttonBarWidget, args, i);
2286 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2287 XtSetValues(whiteTimerWidget, args, i);
2289 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2290 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2291 XtSetValues(blackTimerWidget, args, i);
2293 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2294 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2295 XtSetValues(messageWidget, args, i);
2296 if (appData.showButtonBar) {
2298 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2299 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2300 XtSetValues(buttonBarWidget, args, i);
2304 XtSetArg(args[0], XtNfromVert, messageWidget);
2305 XtSetArg(args[1], XtNtop, XtChainTop);
2306 XtSetArg(args[2], XtNbottom, XtChainBottom);
2307 XtSetArg(args[3], XtNleft, XtChainLeft);
2308 XtSetArg(args[4], XtNright, XtChainRight);
2309 XtSetValues(boardWidget, args, 5);
2311 XtRealizeWidget(shellWidget);
2314 XtSetArg(args[0], XtNx, wpMain.x);
2315 XtSetArg(args[1], XtNy, wpMain.y);
2316 XtSetValues(shellWidget, args, 2);
2320 * Correct the width of the message and title widgets.
2321 * It is not known why some systems need the extra fudge term.
2322 * The value "2" is probably larger than needed.
2324 XawFormDoLayout(formWidget, False);
2326 #define WIDTH_FUDGE 2
2328 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2329 XtSetArg(args[i], XtNheight, &h); i++;
2330 XtGetValues(messageWidget, args, i);
2331 if (appData.showButtonBar) {
2333 XtSetArg(args[i], XtNwidth, &w); i++;
2334 XtGetValues(buttonBarWidget, args, i);
2335 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2337 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2340 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2341 if (gres != XtGeometryYes && appData.debugMode) {
2342 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2343 programName, gres, w, h, wr, hr);
2346 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2347 /* The size used for the child widget in layout lags one resize behind
2348 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2350 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2351 if (gres != XtGeometryYes && appData.debugMode) {
2352 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2353 programName, gres, w, h, wr, hr);
2356 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2357 XtSetArg(args[1], XtNright, XtChainRight);
2358 XtSetValues(messageWidget, args, 2);
2360 if (appData.titleInWindow) {
2362 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2363 XtSetArg(args[i], XtNheight, &h); i++;
2364 XtGetValues(titleWidget, args, i);
2366 w = boardWidth - 2*bor;
2368 XtSetArg(args[0], XtNwidth, &w);
2369 XtGetValues(menuBarWidget, args, 1);
2370 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2373 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2374 if (gres != XtGeometryYes && appData.debugMode) {
2376 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2377 programName, gres, w, h, wr, hr);
2380 XawFormDoLayout(formWidget, True);
2382 xBoardWindow = XtWindow(boardWidget);
2384 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2385 // not need to go into InitDrawingSizes().
2389 * Create X checkmark bitmap and initialize option menu checks.
2391 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2392 checkmark_bits, checkmark_width, checkmark_height);
2393 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2394 if (appData.alwaysPromoteToQueen) {
2395 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2398 if (appData.animateDragging) {
2399 XtSetValues(XtNameToWidget(menuBarWidget,
2400 "menuOptions.Animate Dragging"),
2403 if (appData.animate) {
2404 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2407 if (appData.autoComment) {
2408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2411 if (appData.autoCallFlag) {
2412 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2415 if (appData.autoFlipView) {
2416 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2419 if (appData.autoObserve) {
2420 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2423 if (appData.autoRaiseBoard) {
2424 XtSetValues(XtNameToWidget(menuBarWidget,
2425 "menuOptions.Auto Raise Board"), args, 1);
2427 if (appData.autoSaveGames) {
2428 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2431 if (appData.saveGameFile[0] != NULLCHAR) {
2432 /* Can't turn this off from menu */
2433 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2435 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2439 if (appData.blindfold) {
2440 XtSetValues(XtNameToWidget(menuBarWidget,
2441 "menuOptions.Blindfold"), args, 1);
2443 if (appData.flashCount > 0) {
2444 XtSetValues(XtNameToWidget(menuBarWidget,
2445 "menuOptions.Flash Moves"),
2448 if (appData.getMoveList) {
2449 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2453 if (appData.highlightDragging) {
2454 XtSetValues(XtNameToWidget(menuBarWidget,
2455 "menuOptions.Highlight Dragging"),
2459 if (appData.highlightLastMove) {
2460 XtSetValues(XtNameToWidget(menuBarWidget,
2461 "menuOptions.Highlight Last Move"),
2464 if (appData.icsAlarm) {
2465 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2468 if (appData.ringBellAfterMoves) {
2469 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2472 if (appData.oldSaveStyle) {
2473 XtSetValues(XtNameToWidget(menuBarWidget,
2474 "menuOptions.Old Save Style"), args, 1);
2476 if (appData.periodicUpdates) {
2477 XtSetValues(XtNameToWidget(menuBarWidget,
2478 "menuOptions.Periodic Updates"), args, 1);
2480 if (appData.ponderNextMove) {
2481 XtSetValues(XtNameToWidget(menuBarWidget,
2482 "menuOptions.Ponder Next Move"), args, 1);
2484 if (appData.popupExitMessage) {
2485 XtSetValues(XtNameToWidget(menuBarWidget,
2486 "menuOptions.Popup Exit Message"), args, 1);
2488 if (appData.popupMoveErrors) {
2489 XtSetValues(XtNameToWidget(menuBarWidget,
2490 "menuOptions.Popup Move Errors"), args, 1);
2492 if (appData.premove) {
2493 XtSetValues(XtNameToWidget(menuBarWidget,
2494 "menuOptions.Premove"), args, 1);
2496 if (appData.quietPlay) {
2497 XtSetValues(XtNameToWidget(menuBarWidget,
2498 "menuOptions.Quiet Play"), args, 1);
2500 if (appData.showCoords) {
2501 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2504 if (appData.hideThinkingFromHuman) {
2505 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2508 if (appData.testLegality) {
2509 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2512 if (saveSettingsOnExit) {
2513 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2520 ReadBitmap(&wIconPixmap, "icon_white.bm",
2521 icon_white_bits, icon_white_width, icon_white_height);
2522 ReadBitmap(&bIconPixmap, "icon_black.bm",
2523 icon_black_bits, icon_black_width, icon_black_height);
2524 iconPixmap = wIconPixmap;
2526 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2527 XtSetValues(shellWidget, args, i);
2530 * Create a cursor for the board widget.
2532 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2533 XChangeWindowAttributes(xDisplay, xBoardWindow,
2534 CWCursor, &window_attributes);
2537 * Inhibit shell resizing.
2539 shellArgs[0].value = (XtArgVal) &w;
2540 shellArgs[1].value = (XtArgVal) &h;
2541 XtGetValues(shellWidget, shellArgs, 2);
2542 shellArgs[4].value = shellArgs[2].value = w;
2543 shellArgs[5].value = shellArgs[3].value = h;
2544 XtSetValues(shellWidget, &shellArgs[2], 4);
2545 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2546 marginH = h - boardHeight;
2548 CatchDeleteWindow(shellWidget, "QuitProc");
2553 if (appData.bitmapDirectory[0] != NULLCHAR) {
2557 CreateXPMBoard(appData.liteBackTextureFile, 1);
2558 CreateXPMBoard(appData.darkBackTextureFile, 0);
2562 /* Create regular pieces */
2563 if (!useImages) CreatePieces();
2568 if (appData.animate || appData.animateDragging)
2571 XtAugmentTranslations(formWidget,
2572 XtParseTranslationTable(globalTranslations));
2573 XtAugmentTranslations(boardWidget,
2574 XtParseTranslationTable(boardTranslations));
2575 XtAugmentTranslations(whiteTimerWidget,
2576 XtParseTranslationTable(whiteTranslations));
2577 XtAugmentTranslations(blackTimerWidget,
2578 XtParseTranslationTable(blackTranslations));
2580 /* Why is the following needed on some versions of X instead
2581 * of a translation? */
2582 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2583 (XtEventHandler) EventProc, NULL);
2586 /* [AS] Restore layout */
2587 if( wpMoveHistory.visible ) {
2591 if( wpEvalGraph.visible )
2596 if( wpEngineOutput.visible ) {
2597 EngineOutputPopUp();
2602 if (errorExitStatus == -1) {
2603 if (appData.icsActive) {
2604 /* We now wait until we see "login:" from the ICS before
2605 sending the logon script (problems with timestamp otherwise) */
2606 /*ICSInitScript();*/
2607 if (appData.icsInputBox) ICSInputBoxPopUp();
2611 signal(SIGWINCH, TermSizeSigHandler);
2613 signal(SIGINT, IntSigHandler);
2614 signal(SIGTERM, IntSigHandler);
2615 if (*appData.cmailGameName != NULLCHAR) {
2616 signal(SIGUSR1, CmailSigHandler);
2619 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2621 XtSetKeyboardFocus(shellWidget, formWidget);
2623 XtAppMainLoop(appContext);
2624 if (appData.debugMode) fclose(debugFP); // [DM] debug
2631 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2632 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2634 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2635 unlink(gameCopyFilename);
2636 unlink(gamePasteFilename);
2639 RETSIGTYPE TermSizeSigHandler(int sig)
2652 CmailSigHandler(sig)
2658 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2660 /* Activate call-back function CmailSigHandlerCallBack() */
2661 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2663 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2667 CmailSigHandlerCallBack(isr, closure, message, count, error)
2675 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2677 /**** end signal code ****/
2683 /* try to open the icsLogon script, either in the location given
2684 * or in the users HOME directory
2691 f = fopen(appData.icsLogon, "r");
2694 homedir = getenv("HOME");
2695 if (homedir != NULL)
2697 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2698 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2699 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2700 f = fopen(buf, "r");
2705 ProcessICSInitScript(f);
2707 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2716 EditCommentPopDown();
2731 if (!menuBarWidget) return;
2732 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2734 DisplayError("menuEdit.Revert", 0);
2736 XtSetSensitive(w, !grey);
2738 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2740 DisplayError("menuEdit.Annotate", 0);
2742 XtSetSensitive(w, !grey);
2747 SetMenuEnables(enab)
2751 if (!menuBarWidget) return;
2752 while (enab->name != NULL) {
2753 w = XtNameToWidget(menuBarWidget, enab->name);
2755 DisplayError(enab->name, 0);
2757 XtSetSensitive(w, enab->value);
2763 Enables icsEnables[] = {
2764 { "menuFile.Mail Move", False },
2765 { "menuFile.Reload CMail Message", False },
2766 { "menuMode.Machine Black", False },
2767 { "menuMode.Machine White", False },
2768 { "menuMode.Analysis Mode", False },
2769 { "menuMode.Analyze File", False },
2770 { "menuMode.Two Machines", False },
2772 { "menuEngine.Hint", False },
2773 { "menuEngine.Book", False },
2774 { "menuEngine.Move Now", False },
2775 { "menuOptions.Periodic Updates", False },
2776 { "menuOptions.Hide Thinking", False },
2777 { "menuOptions.Ponder Next Move", False },
2778 { "menuEngine.Engine #1 Settings", False },
2780 { "menuEngine.Engine #2 Settings", False },
2781 { "menuEdit.Annotate", False },
2785 Enables ncpEnables[] = {
2786 { "menuFile.Mail Move", False },
2787 { "menuFile.Reload CMail Message", False },
2788 { "menuMode.Machine White", False },
2789 { "menuMode.Machine Black", False },
2790 { "menuMode.Analysis Mode", False },
2791 { "menuMode.Analyze File", False },
2792 { "menuMode.Two Machines", False },
2793 { "menuMode.ICS Client", False },
2794 { "menuView.ICS Input Box", False },
2795 { "Action", False },
2796 { "menuEdit.Revert", False },
2797 { "menuEdit.Annotate", False },
2798 { "menuEngine.Engine #1 Settings", False },
2799 { "menuEngine.Engine #2 Settings", False },
2800 { "menuEngine.Move Now", False },
2801 { "menuEngine.Retract Move", False },
2802 { "menuOptions.Auto Comment", False },
2803 { "menuOptions.Auto Flag", False },
2804 { "menuOptions.Auto Flip View", False },
2805 { "menuOptions.Auto Observe", False },
2806 { "menuOptions.Auto Raise Board", False },
2807 { "menuOptions.Get Move List", False },
2808 { "menuOptions.ICS Alarm", False },
2809 { "menuOptions.Move Sound", False },
2810 { "menuOptions.Quiet Play", False },
2811 { "menuOptions.Hide Thinking", False },
2812 { "menuOptions.Periodic Updates", False },
2813 { "menuOptions.Ponder Next Move", False },
2814 { "menuEngine.Hint", False },
2815 { "menuEngine.Book", False },
2819 Enables gnuEnables[] = {
2820 { "menuMode.ICS Client", False },
2821 { "menuView.ICS Input Box", False },
2822 { "menuAction.Accept", False },
2823 { "menuAction.Decline", False },
2824 { "menuAction.Rematch", False },
2825 { "menuAction.Adjourn", False },
2826 { "menuAction.Stop Examining", False },
2827 { "menuAction.Stop Observing", False },
2828 { "menuAction.Upload to Examine", False },
2829 { "menuEdit.Revert", False },
2830 { "menuEdit.Annotate", False },
2831 { "menuOptions.Auto Comment", False },
2832 { "menuOptions.Auto Observe", False },
2833 { "menuOptions.Auto Raise Board", False },
2834 { "menuOptions.Get Move List", False },
2835 { "menuOptions.Premove", False },
2836 { "menuOptions.Quiet Play", False },
2838 /* The next two options rely on SetCmailMode being called *after* */
2839 /* SetGNUMode so that when GNU is being used to give hints these */
2840 /* menu options are still available */
2842 { "menuFile.Mail Move", False },
2843 { "menuFile.Reload CMail Message", False },
2847 Enables cmailEnables[] = {
2849 { "menuAction.Call Flag", False },
2850 { "menuAction.Draw", True },
2851 { "menuAction.Adjourn", False },
2852 { "menuAction.Abort", False },
2853 { "menuAction.Stop Observing", False },
2854 { "menuAction.Stop Examining", False },
2855 { "menuFile.Mail Move", True },
2856 { "menuFile.Reload CMail Message", True },
2860 Enables trainingOnEnables[] = {
2861 { "menuMode.Edit Comment", False },
2862 { "menuMode.Pause", False },
2863 { "menuEdit.Forward", False },
2864 { "menuEdit.Backward", False },
2865 { "menuEdit.Forward to End", False },
2866 { "menuEdit.Back to Start", False },
2867 { "menuEngine.Move Now", False },
2868 { "menuEdit.Truncate Game", False },
2872 Enables trainingOffEnables[] = {
2873 { "menuMode.Edit Comment", True },
2874 { "menuMode.Pause", True },
2875 { "menuEdit.Forward", True },
2876 { "menuEdit.Backward", True },
2877 { "menuEdit.Forward to End", True },
2878 { "menuEdit.Back to Start", True },
2879 { "menuEngine.Move Now", True },
2880 { "menuEdit.Truncate Game", True },
2884 Enables machineThinkingEnables[] = {
2885 { "menuFile.Load Game", False },
2886 // { "menuFile.Load Next Game", False },
2887 // { "menuFile.Load Previous Game", False },
2888 // { "menuFile.Reload Same Game", False },
2889 { "menuEdit.Paste Game", False },
2890 { "menuFile.Load Position", False },
2891 // { "menuFile.Load Next Position", False },
2892 // { "menuFile.Load Previous Position", False },
2893 // { "menuFile.Reload Same Position", False },
2894 { "menuEdit.Paste Position", False },
2895 { "menuMode.Machine White", False },
2896 { "menuMode.Machine Black", False },
2897 { "menuMode.Two Machines", False },
2898 { "menuEngine.Retract Move", False },
2902 Enables userThinkingEnables[] = {
2903 { "menuFile.Load Game", True },
2904 // { "menuFile.Load Next Game", True },
2905 // { "menuFile.Load Previous Game", True },
2906 // { "menuFile.Reload Same Game", True },
2907 { "menuEdit.Paste Game", True },
2908 { "menuFile.Load Position", True },
2909 // { "menuFile.Load Next Position", True },
2910 // { "menuFile.Load Previous Position", True },
2911 // { "menuFile.Reload Same Position", True },
2912 { "menuEdit.Paste Position", True },
2913 { "menuMode.Machine White", True },
2914 { "menuMode.Machine Black", True },
2915 { "menuMode.Two Machines", True },
2916 { "menuEngine.Retract Move", True },
2922 SetMenuEnables(icsEnables);
2925 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2926 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2933 SetMenuEnables(ncpEnables);
2939 SetMenuEnables(gnuEnables);
2945 SetMenuEnables(cmailEnables);
2951 SetMenuEnables(trainingOnEnables);
2952 if (appData.showButtonBar) {
2953 XtSetSensitive(buttonBarWidget, False);
2959 SetTrainingModeOff()
2961 SetMenuEnables(trainingOffEnables);
2962 if (appData.showButtonBar) {
2963 XtSetSensitive(buttonBarWidget, True);
2968 SetUserThinkingEnables()
2970 if (appData.noChessProgram) return;
2971 SetMenuEnables(userThinkingEnables);
2975 SetMachineThinkingEnables()
2977 if (appData.noChessProgram) return;
2978 SetMenuEnables(machineThinkingEnables);
2980 case MachinePlaysBlack:
2981 case MachinePlaysWhite:
2982 case TwoMachinesPlay:
2983 XtSetSensitive(XtNameToWidget(menuBarWidget,
2984 ModeToWidgetName(gameMode)), True);
2991 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
2992 #define HISTORY_SIZE 64
\r
2993 static char *history[HISTORY_SIZE];
\r
2994 int histIn = 0, histP = 0;
\r
2997 SaveInHistory(char *cmd)
\r
2999 if (history[histIn] != NULL) {
\r
3000 free(history[histIn]);
\r
3001 history[histIn] = NULL;
\r
3003 if (*cmd == NULLCHAR) return;
\r
3004 history[histIn] = StrSave(cmd);
\r
3005 histIn = (histIn + 1) % HISTORY_SIZE;
\r
3006 if (history[histIn] != NULL) {
\r
3007 free(history[histIn]);
\r
3008 history[histIn] = NULL;
\r
3014 PrevInHistory(char *cmd)
\r
3017 if (histP == histIn) {
\r
3018 if (history[histIn] != NULL) free(history[histIn]);
\r
3019 history[histIn] = StrSave(cmd);
\r
3021 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
\r
3022 if (newhp == histIn || history[newhp] == NULL) return NULL;
\r
3024 return history[histP];
\r
3030 if (histP == histIn) return NULL;
\r
3031 histP = (histP + 1) % HISTORY_SIZE;
\r
3032 return history[histP];
\r
3034 // end of borrowed code
\r
3036 #define Abs(n) ((n)<0 ? -(n) : (n))
3039 * Find a font that matches "pattern" that is as close as
3040 * possible to the targetPxlSize. Prefer fonts that are k
3041 * pixels smaller to fonts that are k pixels larger. The
3042 * pattern must be in the X Consortium standard format,
3043 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3044 * The return value should be freed with XtFree when no
3048 FindFont(pattern, targetPxlSize)
3052 char **fonts, *p, *best, *scalable, *scalableTail;
3053 int i, j, nfonts, minerr, err, pxlSize;
3056 char **missing_list;
3058 char *def_string, *base_fnt_lst, strInt[3];
3060 XFontStruct **fnt_list;
3062 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3063 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3064 p = strstr(pattern, "--");
3065 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3066 strcat(base_fnt_lst, strInt);
3067 strcat(base_fnt_lst, strchr(p + 2, '-'));
3069 if ((fntSet = XCreateFontSet(xDisplay,
3073 &def_string)) == NULL) {
3075 fprintf(stderr, _("Unable to create font set.\n"));
3079 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3081 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3083 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3084 programName, pattern);
3092 for (i=0; i<nfonts; i++) {
3095 if (*p != '-') continue;
3097 if (*p == NULLCHAR) break;
3098 if (*p++ == '-') j++;
3100 if (j < 7) continue;
3103 scalable = fonts[i];
3106 err = pxlSize - targetPxlSize;
3107 if (Abs(err) < Abs(minerr) ||
3108 (minerr > 0 && err < 0 && -err == minerr)) {
3114 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3115 /* If the error is too big and there is a scalable font,
3116 use the scalable font. */
3117 int headlen = scalableTail - scalable;
3118 p = (char *) XtMalloc(strlen(scalable) + 10);
3119 while (isdigit(*scalableTail)) scalableTail++;
3120 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3122 p = (char *) XtMalloc(strlen(best) + 2);
3123 safeStrCpy(p, best, strlen(best)+1 );
3125 if (appData.debugMode) {
3126 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3127 pattern, targetPxlSize, p);
3130 if (missing_count > 0)
3131 XFreeStringList(missing_list);
3132 XFreeFontSet(xDisplay, fntSet);
3134 XFreeFontNames(fonts);
3141 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3142 | GCBackground | GCFunction | GCPlaneMask;
3143 XGCValues gc_values;
3146 gc_values.plane_mask = AllPlanes;
3147 gc_values.line_width = lineGap;
3148 gc_values.line_style = LineSolid;
3149 gc_values.function = GXcopy;
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 black0
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));
3292 /* create Pixmap of piece */
3293 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3295 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3298 /* create Pixmap of clipmask
3299 Note: We assume the white/black pieces have the same
3300 outline, so we make only 6 masks. This is okay
3301 since the XPM clipmask routines do the same. */
3303 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3305 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3308 /* now create the 1-bit version */
3309 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3312 values.foreground = 1;
3313 values.background = 0;
3315 /* Don't use XtGetGC, not read only */
3316 maskGC = XCreateGC(xDisplay, *mask,
3317 GCForeground | GCBackground, &values);
3318 XCopyPlane(xDisplay, temp, *mask, maskGC,
3319 0, 0, squareSize, squareSize, 0, 0, 1);
3320 XFreePixmap(xDisplay, temp);
3325 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3327 void CreateXIMPieces()
3332 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3337 /* The XSynchronize calls were copied from CreatePieces.
3338 Not sure if needed, but can't hurt */
3339 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3342 /* temp needed by loadXIM() */
3343 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3344 0, 0, ss, ss, AllPlanes, XYPixmap);
3346 if (strlen(appData.pixmapDirectory) == 0) {
3350 if (appData.monoMode) {
3351 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3355 fprintf(stderr, _("\nLoading XIMs...\n"));
3357 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3358 fprintf(stderr, "%d", piece+1);
3359 for (kind=0; kind<4; kind++) {
3360 fprintf(stderr, ".");
3361 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3362 ExpandPathName(appData.pixmapDirectory),
3363 piece <= (int) WhiteKing ? "" : "w",
3364 pieceBitmapNames[piece],
3366 ximPieceBitmap[kind][piece] =
3367 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3368 0, 0, ss, ss, AllPlanes, XYPixmap);
3369 if (appData.debugMode)
3370 fprintf(stderr, _("(File:%s:) "), buf);
3371 loadXIM(ximPieceBitmap[kind][piece],
3373 &(xpmPieceBitmap2[kind][piece]),
3374 &(ximMaskPm2[piece]));
3375 if(piece <= (int)WhiteKing)
3376 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3378 fprintf(stderr," ");
3380 /* Load light and dark squares */
3381 /* If the LSQ and DSQ pieces don't exist, we will
3382 draw them with solid squares. */
3383 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3384 if (access(buf, 0) != 0) {
3388 fprintf(stderr, _("light square "));
3390 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3391 0, 0, ss, ss, AllPlanes, XYPixmap);
3392 if (appData.debugMode)
3393 fprintf(stderr, _("(File:%s:) "), buf);
3395 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3396 fprintf(stderr, _("dark square "));
3397 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3398 ExpandPathName(appData.pixmapDirectory), ss);
3399 if (appData.debugMode)
3400 fprintf(stderr, _("(File:%s:) "), buf);
3402 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3403 0, 0, ss, ss, AllPlanes, XYPixmap);
3404 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3405 xpmJailSquare = xpmLightSquare;
3407 fprintf(stderr, _("Done.\n"));
3409 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3413 void CreateXPMBoard(char *s, int kind)
3417 if(s == NULL || *s == 0 || *s == '*') return;
3418 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3419 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3423 void CreateXPMPieces()
3427 u_int ss = squareSize;
3429 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3430 XpmColorSymbol symbols[4];
3432 /* The XSynchronize calls were copied from CreatePieces.
3433 Not sure if needed, but can't hurt */
3434 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3436 /* Setup translations so piece colors match square colors */
3437 symbols[0].name = "light_piece";
3438 symbols[0].value = appData.whitePieceColor;
3439 symbols[1].name = "dark_piece";
3440 symbols[1].value = appData.blackPieceColor;
3441 symbols[2].name = "light_square";
3442 symbols[2].value = appData.lightSquareColor;
3443 symbols[3].name = "dark_square";
3444 symbols[3].value = appData.darkSquareColor;
3446 attr.valuemask = XpmColorSymbols;
3447 attr.colorsymbols = symbols;
3448 attr.numsymbols = 4;
3450 if (appData.monoMode) {
3451 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3455 if (strlen(appData.pixmapDirectory) == 0) {
3456 XpmPieces* pieces = builtInXpms;
3459 while (pieces->size != squareSize && pieces->size) pieces++;
3460 if (!pieces->size) {
3461 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3464 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3465 for (kind=0; kind<4; kind++) {
3467 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3468 pieces->xpm[piece][kind],
3469 &(xpmPieceBitmap2[kind][piece]),
3470 NULL, &attr)) != 0) {
3471 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3475 if(piece <= (int) WhiteKing)
3476 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3480 xpmJailSquare = xpmLightSquare;
3484 fprintf(stderr, _("\nLoading XPMs...\n"));
3487 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3488 fprintf(stderr, "%d ", piece+1);
3489 for (kind=0; kind<4; kind++) {
3490 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3491 ExpandPathName(appData.pixmapDirectory),
3492 piece > (int) WhiteKing ? "w" : "",
3493 pieceBitmapNames[piece],
3495 if (appData.debugMode) {
3496 fprintf(stderr, _("(File:%s:) "), buf);
3498 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3499 &(xpmPieceBitmap2[kind][piece]),
3500 NULL, &attr)) != 0) {
3501 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3502 // [HGM] missing: read of unorthodox piece failed; substitute King.
3503 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3504 ExpandPathName(appData.pixmapDirectory),
3506 if (appData.debugMode) {
3507 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3509 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3510 &(xpmPieceBitmap2[kind][piece]),
3514 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3519 if(piece <= (int) WhiteKing)
3520 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3523 /* Load light and dark squares */
3524 /* If the LSQ and DSQ pieces don't exist, we will
3525 draw them with solid squares. */
3526 fprintf(stderr, _("light square "));
3527 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3528 if (access(buf, 0) != 0) {
3532 if (appData.debugMode)
3533 fprintf(stderr, _("(File:%s:) "), buf);
3535 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3536 &xpmLightSquare, NULL, &attr)) != 0) {
3537 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3540 fprintf(stderr, _("dark square "));
3541 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3542 ExpandPathName(appData.pixmapDirectory), ss);
3543 if (appData.debugMode) {
3544 fprintf(stderr, _("(File:%s:) "), buf);
3546 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3547 &xpmDarkSquare, NULL, &attr)) != 0) {
3548 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3552 xpmJailSquare = xpmLightSquare;
3553 fprintf(stderr, _("Done.\n"));
3555 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3558 #endif /* HAVE_LIBXPM */
3561 /* No built-in bitmaps */
3566 u_int ss = squareSize;
3568 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3571 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3572 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3573 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3574 pieceBitmapNames[piece],
3575 ss, kind == SOLID ? 's' : 'o');
3576 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3577 if(piece <= (int)WhiteKing)
3578 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3582 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3586 /* With built-in bitmaps */
3589 BuiltInBits* bib = builtInBits;
3592 u_int ss = squareSize;
3594 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3597 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3599 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3600 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3601 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3602 pieceBitmapNames[piece],
3603 ss, kind == SOLID ? 's' : 'o');
3604 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3605 bib->bits[kind][piece], ss, ss);
3606 if(piece <= (int)WhiteKing)
3607 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3611 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3616 void ReadBitmap(pm, name, bits, wreq, hreq)
3619 unsigned char bits[];
3625 char msg[MSG_SIZ], fullname[MSG_SIZ];
3627 if (*appData.bitmapDirectory != NULLCHAR) {
3628 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3629 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3630 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3631 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3632 &w, &h, pm, &x_hot, &y_hot);
3633 fprintf(stderr, "load %s\n", name);
3634 if (errcode != BitmapSuccess) {
3636 case BitmapOpenFailed:
3637 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3639 case BitmapFileInvalid:
3640 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3642 case BitmapNoMemory:
3643 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3647 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3651 fprintf(stderr, _("%s: %s...using built-in\n"),
3653 } else if (w != wreq || h != hreq) {
3655 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3656 programName, fullname, w, h, wreq, hreq);
3662 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3671 if (lineGap == 0) return;
3673 /* [HR] Split this into 2 loops for non-square boards. */
3675 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3676 gridSegments[i].x1 = 0;
3677 gridSegments[i].x2 =
3678 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3679 gridSegments[i].y1 = gridSegments[i].y2
3680 = lineGap / 2 + (i * (squareSize + lineGap));
3683 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3684 gridSegments[j + i].y1 = 0;
3685 gridSegments[j + i].y2 =
3686 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3687 gridSegments[j + i].x1 = gridSegments[j + i].x2
3688 = lineGap / 2 + (j * (squareSize + lineGap));
3692 static void MenuBarSelect(w, addr, index)
3697 XtActionProc proc = (XtActionProc) addr;
3699 (proc)(NULL, NULL, NULL, NULL);
3702 void CreateMenuBarPopup(parent, name, mb)
3712 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3715 XtSetArg(args[j], XtNleftMargin, 20); j++;
3716 XtSetArg(args[j], XtNrightMargin, 20); j++;
3718 while (mi->string != NULL) {
3719 if (strcmp(mi->string, "----") == 0) {
3720 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3723 XtSetArg(args[j], XtNlabel, XtNewString(mi->string));
3724 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3726 XtAddCallback(entry, XtNcallback,
3727 (XtCallbackProc) MenuBarSelect,
3728 (caddr_t) mi->proc);
3734 Widget CreateMenuBar(mb)
3738 Widget anchor, menuBar;
3740 char menuName[MSG_SIZ];
3743 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3744 XtSetArg(args[j], XtNvSpace, 0); j++;
3745 XtSetArg(args[j], XtNborderWidth, 0); j++;
3746 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3747 formWidget, args, j);
3749 while (mb->name != NULL) {
3750 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3751 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3753 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3756 shortName[0] = mb->name[0];
3757 shortName[1] = NULLCHAR;
3758 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3761 XtSetArg(args[j], XtNlabel, XtNewString(mb->name)); j++;
3764 XtSetArg(args[j], XtNborderWidth, 0); j++;
3765 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3767 CreateMenuBarPopup(menuBar, menuName, mb);
3773 Widget CreateButtonBar(mi)
3777 Widget button, buttonBar;
3781 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3783 XtSetArg(args[j], XtNhSpace, 0); j++;
3785 XtSetArg(args[j], XtNborderWidth, 0); j++;
3786 XtSetArg(args[j], XtNvSpace, 0); j++;
3787 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3788 formWidget, args, j);
3790 while (mi->string != NULL) {
3793 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3794 XtSetArg(args[j], XtNborderWidth, 0); j++;
3796 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3797 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3798 buttonBar, args, j);
3799 XtAddCallback(button, XtNcallback,
3800 (XtCallbackProc) MenuBarSelect,
3801 (caddr_t) mi->proc);
3808 CreatePieceMenu(name, color)
3815 ChessSquare selection;
3817 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3818 boardWidget, args, 0);
3820 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3821 String item = pieceMenuStrings[color][i];
3823 if (strcmp(item, "----") == 0) {
3824 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3827 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3828 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3830 selection = pieceMenuTranslation[color][i];
3831 XtAddCallback(entry, XtNcallback,
3832 (XtCallbackProc) PieceMenuSelect,
3833 (caddr_t) selection);
3834 if (selection == WhitePawn || selection == BlackPawn) {
3835 XtSetArg(args[0], XtNpopupOnEntry, entry);
3836 XtSetValues(menu, args, 1);
3849 ChessSquare selection;
3851 whitePieceMenu = CreatePieceMenu("menuW", 0);
3852 blackPieceMenu = CreatePieceMenu("menuB", 1);
3854 XtRegisterGrabAction(PieceMenuPopup, True,
3855 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3856 GrabModeAsync, GrabModeAsync);
3858 XtSetArg(args[0], XtNlabel, _("Drop"));
3859 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3860 boardWidget, args, 1);
3861 for (i = 0; i < DROP_MENU_SIZE; i++) {
3862 String item = dropMenuStrings[i];
3864 if (strcmp(item, "----") == 0) {
3865 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3868 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3869 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3871 selection = dropMenuTranslation[i];
3872 XtAddCallback(entry, XtNcallback,
3873 (XtCallbackProc) DropMenuSelect,
3874 (caddr_t) selection);
3879 void SetupDropMenu()
3887 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3888 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3889 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3890 dmEnables[i].piece);
3891 XtSetSensitive(entry, p != NULL || !appData.testLegality
3892 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3893 && !appData.icsActive));
3895 while (p && *p++ == dmEnables[i].piece) count++;
3896 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3898 XtSetArg(args[j], XtNlabel, label); j++;
3899 XtSetValues(entry, args, j);
3903 void PieceMenuPopup(w, event, params, num_params)
3907 Cardinal *num_params;
3909 String whichMenu; int menuNr;
3910 if (event->type == ButtonRelease)
3911 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3912 else if (event->type == ButtonPress)
3913 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3915 case 0: whichMenu = params[0]; break;
3916 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
3918 case -1: if (errorUp) ErrorPopDown();
3921 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3924 static void PieceMenuSelect(w, piece, junk)
3929 if (pmFromX < 0 || pmFromY < 0) return;
3930 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3933 static void DropMenuSelect(w, piece, junk)
3938 if (pmFromX < 0 || pmFromY < 0) return;
3939 DropMenuEvent(piece, pmFromX, pmFromY);
3942 void WhiteClock(w, event, prms, nprms)
3948 if (gameMode == EditPosition || gameMode == IcsExamining) {
3949 SetWhiteToPlayEvent();
3950 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3955 void BlackClock(w, event, prms, nprms)
3961 if (gameMode == EditPosition || gameMode == IcsExamining) {
3962 SetBlackToPlayEvent();
3963 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3970 * If the user selects on a border boundary, return -1; if off the board,
3971 * return -2. Otherwise map the event coordinate to the square.
3973 int EventToSquare(x, limit)
3981 if ((x % (squareSize + lineGap)) >= squareSize)
3983 x /= (squareSize + lineGap);
3989 static void do_flash_delay(msec)
3995 static void drawHighlight(file, rank, gc)
4001 if (lineGap == 0) return;
4004 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4005 (squareSize + lineGap);
4006 y = lineGap/2 + rank * (squareSize + lineGap);
4008 x = lineGap/2 + file * (squareSize + lineGap);
4009 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4010 (squareSize + lineGap);
4013 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4014 squareSize+lineGap, squareSize+lineGap);
4017 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4018 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4021 SetHighlights(fromX, fromY, toX, toY)
4022 int fromX, fromY, toX, toY;
4024 if (hi1X != fromX || hi1Y != fromY) {
4025 if (hi1X >= 0 && hi1Y >= 0) {
4026 drawHighlight(hi1X, hi1Y, lineGC);
4028 } // [HGM] first erase both, then draw new!
4029 if (hi2X != toX || hi2Y != toY) {
4030 if (hi2X >= 0 && hi2Y >= 0) {
4031 drawHighlight(hi2X, hi2Y, lineGC);
4034 if (hi1X != fromX || hi1Y != fromY) {
4035 if (fromX >= 0 && fromY >= 0) {
4036 drawHighlight(fromX, fromY, highlineGC);
4039 if (hi2X != toX || hi2Y != toY) {
4040 if (toX >= 0 && toY >= 0) {
4041 drawHighlight(toX, toY, highlineGC);
4053 SetHighlights(-1, -1, -1, -1);
4058 SetPremoveHighlights(fromX, fromY, toX, toY)
4059 int fromX, fromY, toX, toY;
4061 if (pm1X != fromX || pm1Y != fromY) {
4062 if (pm1X >= 0 && pm1Y >= 0) {
4063 drawHighlight(pm1X, pm1Y, lineGC);
4065 if (fromX >= 0 && fromY >= 0) {
4066 drawHighlight(fromX, fromY, prelineGC);
4069 if (pm2X != toX || pm2Y != toY) {
4070 if (pm2X >= 0 && pm2Y >= 0) {
4071 drawHighlight(pm2X, pm2Y, lineGC);
4073 if (toX >= 0 && toY >= 0) {
4074 drawHighlight(toX, toY, prelineGC);
4084 ClearPremoveHighlights()
4086 SetPremoveHighlights(-1, -1, -1, -1);
4089 static int CutOutSquare(x, y, x0, y0, kind)
4090 int x, y, *x0, *y0, kind;
4092 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4093 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4095 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4096 if(textureW[kind] < W*squareSize)
4097 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4099 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4100 if(textureH[kind] < H*squareSize)
4101 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4103 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4107 static void BlankSquare(x, y, color, piece, dest, fac)
4108 int x, y, color, fac;
4111 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4113 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4114 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4115 squareSize, squareSize, x*fac, y*fac);
4117 if (useImages && useImageSqs) {
4121 pm = xpmLightSquare;
4126 case 2: /* neutral */
4131 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4132 squareSize, squareSize, x*fac, y*fac);
4142 case 2: /* neutral */
4147 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4152 I split out the routines to draw a piece so that I could
4153 make a generic flash routine.
4155 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4157 int square_color, x, y;
4160 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4161 switch (square_color) {
4163 case 2: /* neutral */
4165 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4166 ? *pieceToOutline(piece)
4167 : *pieceToSolid(piece),
4168 dest, bwPieceGC, 0, 0,
4169 squareSize, squareSize, x, y);
4172 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4173 ? *pieceToSolid(piece)
4174 : *pieceToOutline(piece),
4175 dest, wbPieceGC, 0, 0,
4176 squareSize, squareSize, x, y);
4181 static void monoDrawPiece(piece, square_color, x, y, dest)
4183 int square_color, x, y;
4186 switch (square_color) {
4188 case 2: /* neutral */
4190 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4191 ? *pieceToOutline(piece)
4192 : *pieceToSolid(piece),
4193 dest, bwPieceGC, 0, 0,
4194 squareSize, squareSize, x, y, 1);
4197 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4198 ? *pieceToSolid(piece)
4199 : *pieceToOutline(piece),
4200 dest, wbPieceGC, 0, 0,
4201 squareSize, squareSize, x, y, 1);
4206 static void colorDrawPiece(piece, square_color, x, y, dest)
4208 int square_color, x, y;
4211 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4212 switch (square_color) {
4214 XCopyPlane(xDisplay, *pieceToSolid(piece),
4215 dest, (int) piece < (int) BlackPawn
4216 ? wlPieceGC : blPieceGC, 0, 0,
4217 squareSize, squareSize, x, y, 1);
4220 XCopyPlane(xDisplay, *pieceToSolid(piece),
4221 dest, (int) piece < (int) BlackPawn
4222 ? wdPieceGC : bdPieceGC, 0, 0,
4223 squareSize, squareSize, x, y, 1);
4225 case 2: /* neutral */
4227 XCopyPlane(xDisplay, *pieceToSolid(piece),
4228 dest, (int) piece < (int) BlackPawn
4229 ? wjPieceGC : bjPieceGC, 0, 0,
4230 squareSize, squareSize, x, y, 1);