2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
66 # if HAVE_SYS_SOCKET_H
67 # include <sys/socket.h>
68 # include <netinet/in.h>
70 # else /* not HAVE_SYS_SOCKET_H */
71 # if HAVE_LAN_SOCKET_H
72 # include <lan/socket.h>
74 # include <lan/netdb.h>
75 # else /* not HAVE_LAN_SOCKET_H */
76 # define OMIT_SOCKETS 1
77 # endif /* not HAVE_LAN_SOCKET_H */
78 # endif /* not HAVE_SYS_SOCKET_H */
79 #endif /* !OMIT_SOCKETS */
84 #else /* not STDC_HEADERS */
85 extern char *getenv();
88 # else /* not HAVE_STRING_H */
90 # endif /* not HAVE_STRING_H */
91 #endif /* not STDC_HEADERS */
94 # include <sys/fcntl.h>
95 #else /* not HAVE_SYS_FCNTL_H */
98 # endif /* HAVE_FCNTL_H */
99 #endif /* not HAVE_SYS_FCNTL_H */
101 #if HAVE_SYS_SYSTEMINFO_H
102 # include <sys/systeminfo.h>
103 #endif /* HAVE_SYS_SYSTEMINFO_H */
105 #if TIME_WITH_SYS_TIME
106 # include <sys/time.h>
110 # include <sys/time.h>
121 # include <sys/wait.h>
126 # define NAMLEN(dirent) strlen((dirent)->d_name)
127 # define HAVE_DIR_STRUCT
129 # define dirent direct
130 # define NAMLEN(dirent) (dirent)->d_namlen
132 # include <sys/ndir.h>
133 # define HAVE_DIR_STRUCT
136 # include <sys/dir.h>
137 # define HAVE_DIR_STRUCT
141 # define HAVE_DIR_STRUCT
145 #include <X11/Intrinsic.h>
146 #include <X11/StringDefs.h>
147 #include <X11/Shell.h>
148 #include <X11/cursorfont.h>
149 #include <X11/Xatom.h>
150 #include <X11/Xmu/Atoms.h>
152 #include <X11/Xaw3d/Dialog.h>
153 #include <X11/Xaw3d/Form.h>
154 #include <X11/Xaw3d/List.h>
155 #include <X11/Xaw3d/Label.h>
156 #include <X11/Xaw3d/SimpleMenu.h>
157 #include <X11/Xaw3d/SmeBSB.h>
158 #include <X11/Xaw3d/SmeLine.h>
159 #include <X11/Xaw3d/Box.h>
160 #include <X11/Xaw3d/MenuButton.h>
161 #include <X11/Xaw3d/Text.h>
162 #include <X11/Xaw3d/AsciiText.h>
164 #include <X11/Xaw/Dialog.h>
165 #include <X11/Xaw/Form.h>
166 #include <X11/Xaw/List.h>
167 #include <X11/Xaw/Label.h>
168 #include <X11/Xaw/SimpleMenu.h>
169 #include <X11/Xaw/SmeBSB.h>
170 #include <X11/Xaw/SmeLine.h>
171 #include <X11/Xaw/Box.h>
172 #include <X11/Xaw/MenuButton.h>
173 #include <X11/Xaw/Text.h>
174 #include <X11/Xaw/AsciiText.h>
177 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
182 #include "pixmaps/pixmaps.h"
183 #define IMAGE_EXT "xpm"
185 #define IMAGE_EXT "xim"
186 #include "bitmaps/bitmaps.h"
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
195 #include "backendz.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
204 // must be moved to xengineoutput.h
206 void EngineOutputProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
208 void EvalGraphProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
216 #define usleep(t) _sleep2(((t)+500)/1000)
220 # define _(s) gettext (s)
221 # define N_(s) gettext_noop (s)
239 int main P((int argc, char **argv));
240 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
241 char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
242 RETSIGTYPE CmailSigHandler P((int sig));
243 RETSIGTYPE IntSigHandler P((int sig));
244 RETSIGTYPE TermSizeSigHandler P((int sig));
245 void CreateGCs P((int redo));
246 void CreateAnyPieces P((void));
247 void CreateXIMPieces P((void));
248 void CreateXPMPieces P((void));
249 void CreateXPMBoard P((char *s, int n));
250 void CreatePieces P((void));
251 void CreatePieceMenus P((void));
252 Widget CreateMenuBar P((Menu *mb));
253 Widget CreateButtonBar P ((MenuItem *mi));
254 char *FindFont P((char *pattern, int targetPxlSize));
255 void PieceMenuPopup P((Widget w, XEvent *event,
256 String *params, Cardinal *num_params));
257 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
260 u_int wreq, u_int hreq));
261 void CreateGrid P((void));
262 int EventToSquare P((int x, int limit));
263 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
264 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
265 void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
266 void HandleUserMove P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void AnimateUserMove P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void HandlePV P((Widget w, XEvent * event,
271 String * params, Cardinal * nParams));
272 void SelectPV P((Widget w, XEvent * event,
273 String * params, Cardinal * nParams));
274 void StopPV P((Widget w, XEvent * event,
275 String * params, Cardinal * nParams));
276 void WhiteClock P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void BlackClock P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void DrawPositionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
284 void CommentClick P((Widget w, XEvent * event,
285 String * params, Cardinal * nParams));
286 void CommentPopUp P((char *title, char *label));
287 void CommentPopDown P((void));
288 void ICSInputBoxPopUp P((void));
289 void ICSInputBoxPopDown P((void));
290 void FileNamePopUp P((char *label, char *def, char *filter,
291 FileProc proc, char *openMode));
292 void FileNamePopDown P((void));
293 void FileNameCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void FileNameAction P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void AskQuestionReplyAction P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void AskQuestionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void AskQuestionPopDown P((void));
302 void PromotionPopDown P((void));
303 void PromotionCallback P((Widget w, XtPointer client_data,
304 XtPointer call_data));
305 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
306 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
308 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
310 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
312 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
314 void LoadPositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
318 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
320 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
322 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
324 void PastePositionProc P((Widget w, XEvent *event, String *prms,
326 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void SavePositionProc P((Widget w, XEvent *event,
331 String *prms, Cardinal *nprms));
332 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
335 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
339 void MachineWhiteProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AnalyzeModeProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void AnalyzeFileProc P((Widget w, XEvent *event,
344 String *prms, Cardinal *nprms));
345 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
347 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void IcsClientProc P((Widget w, XEvent *event, String *prms,
351 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EditPositionProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void EditCommentProc P((Widget w, XEvent *event,
356 String *prms, Cardinal *nprms));
357 void IcsInputBoxProc P((Widget w, XEvent *event,
358 String *prms, Cardinal *nprms));
359 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void StopObservingProc P((Widget w, XEvent *event, String *prms,
376 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
378 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
387 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
389 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
392 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
394 void AnimateMovingProc 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 BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
401 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
404 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
406 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
408 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
413 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
415 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
417 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
419 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
422 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
424 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
426 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
428 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void DisplayMove P((int moveNumber));
440 void DisplayTitle P((char *title));
441 void ICSInitScript P((void));
442 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
443 void ErrorPopUp P((char *title, char *text, int modal));
444 void ErrorPopDown P((void));
445 static char *ExpandPathName P((char *path));
446 static void CreateAnimVars P((void));
447 static void DragPieceMove P((int x, int y));
448 static void DrawDragPiece P((void));
449 char *ModeToWidgetName P((GameMode mode));
450 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void EditBookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
467 void GameListOptionsPopDown P(());
468 void ShufflePopDown P(());
469 void TimeControlPopDown P(());
470 void GenericPopDown P(());
471 void update_ics_width P(());
472 int get_term_width P(());
473 int CopyMemoProc P(());
474 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
475 Boolean IsDrawArrowEnabled P(());
478 * XBoard depends on Xt R4 or higher
480 int xtVersion = XtSpecificationRelease;
485 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
486 jailSquareColor, highlightSquareColor, premoveHighlightColor;
487 Pixel lowTimeWarningColor;
488 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
489 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
490 wjPieceGC, bjPieceGC, prelineGC, countGC;
491 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
492 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
493 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
494 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
495 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
496 ICSInputShell, fileNameShell, askQuestionShell;
497 Widget historyShell, evalGraphShell, gameListShell;
498 int hOffset; // [HGM] dual
499 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
500 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
501 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
502 Font clockFontID, coordFontID, countFontID;
503 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
504 XtAppContext appContext;
506 char *oldICSInteractionTitle;
510 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
512 Position commentX = -1, commentY = -1;
513 Dimension commentW, commentH;
514 typedef unsigned int BoardSize;
516 Boolean chessProgram;
518 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
519 int squareSize, smallLayout = 0, tinyLayout = 0,
520 marginW, marginH, // [HGM] for run-time resizing
521 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
522 ICSInputBoxUp = False, askQuestionUp = False,
523 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
524 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
525 Pixel timerForegroundPixel, timerBackgroundPixel;
526 Pixel buttonForegroundPixel, buttonBackgroundPixel;
527 char *chessDir, *programName, *programVersion,
528 *gameCopyFilename, *gamePasteFilename;
529 Boolean alwaysOnTop = False;
530 Boolean saveSettingsOnExit;
531 char *settingsFileName;
532 char *icsTextMenuString;
534 char *firstChessProgramNames;
535 char *secondChessProgramNames;
537 WindowPlacement wpMain;
538 WindowPlacement wpConsole;
539 WindowPlacement wpComment;
540 WindowPlacement wpMoveHistory;
541 WindowPlacement wpEvalGraph;
542 WindowPlacement wpEngineOutput;
543 WindowPlacement wpGameList;
544 WindowPlacement wpTags;
546 extern Widget shells[];
547 extern Boolean shellUp[];
551 Pixmap pieceBitmap[2][(int)BlackPawn];
552 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
553 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
554 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
555 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
556 Pixmap xpmBoardBitmap[2];
557 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
558 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
559 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
560 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
561 XImage *ximLightSquare, *ximDarkSquare;
564 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
565 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
567 #define White(piece) ((int)(piece) < (int)BlackPawn)
569 /* Variables for doing smooth animation. This whole thing
570 would be much easier if the board was double-buffered,
571 but that would require a fairly major rewrite. */
576 GC blitGC, pieceGC, outlineGC;
577 XPoint startSquare, prevFrame, mouseDelta;
581 int startBoardX, startBoardY;
584 /* There can be two pieces being animated at once: a player
585 can begin dragging a piece before the remote opponent has moved. */
587 static AnimState game, player;
589 /* Bitmaps for use as masks when drawing XPM pieces.
590 Need one for each black and white piece. */
591 static Pixmap xpmMask[BlackKing + 1];
593 /* This magic number is the number of intermediate frames used
594 in each half of the animation. For short moves it's reduced
595 by 1. The total number of frames will be factor * 2 + 1. */
598 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
600 MenuItem fileMenu[] = {
601 {N_("New Game Ctrl+N"), "New Game", ResetProc},
602 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
603 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
604 {"----", NULL, NothingProc},
605 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
606 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
607 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
608 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
609 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
610 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
611 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
612 {"----", NULL, NothingProc},
613 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
614 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
615 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
616 {"----", NULL, NothingProc},
617 {N_("Mail Move"), "Mail Move", MailMoveProc},
618 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
619 {"----", NULL, NothingProc},
620 {N_("Quit Ctr+Q"), "Exit", QuitProc},
624 MenuItem editMenu[] = {
625 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
626 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
627 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
628 {"----", NULL, NothingProc},
629 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
630 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
631 {"----", NULL, NothingProc},
632 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
633 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
634 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
635 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
636 {N_("Edit Book"), "Edit Book", EditBookProc},
637 {"----", NULL, NothingProc},
638 {N_("Revert Home"), "Revert", RevertProc},
639 {N_("Annotate"), "Annotate", AnnotateProc},
640 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
641 {"----", NULL, NothingProc},
642 {N_("Backward Alt+Left"), "Backward", BackwardProc},
643 {N_("Forward Alt+Right"), "Forward", ForwardProc},
644 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
645 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
649 MenuItem viewMenu[] = {
650 {N_("Flip View F2"), "Flip View", FlipViewProc},
651 {"----", NULL, NothingProc},
652 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
653 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
654 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
655 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
656 {N_("ICS text menu"), "ICStex", IcsTextProc},
657 {"----", NULL, NothingProc},
658 {N_("Tags"), "Show Tags", EditTagsProc},
659 {N_("Comments"), "Show Comments", EditCommentProc},
660 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
661 {"----", NULL, NothingProc},
662 {N_("Board..."), "Board Options", BoardOptionsProc},
663 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
667 MenuItem modeMenu[] = {
668 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
669 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
670 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
671 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
672 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
673 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
674 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
675 {N_("Training"), "Training", TrainingProc},
676 {N_("ICS Client"), "ICS Client", IcsClientProc},
677 {"----", NULL, NothingProc},
678 {N_("Machine Match"), "Machine Match", MatchProc},
679 {N_("Pause Pause"), "Pause", PauseProc},
683 MenuItem actionMenu[] = {
684 {N_("Accept F3"), "Accept", AcceptProc},
685 {N_("Decline F4"), "Decline", DeclineProc},
686 {N_("Rematch F12"), "Rematch", RematchProc},
687 {"----", NULL, NothingProc},
688 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
689 {N_("Draw F6"), "Draw", DrawProc},
690 {N_("Adjourn F7"), "Adjourn", AdjournProc},
691 {N_("Abort F8"),"Abort", AbortProc},
692 {N_("Resign F9"), "Resign", ResignProc},
693 {"----", NULL, NothingProc},
694 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
695 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
696 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
697 {"----", NULL, NothingProc},
698 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
699 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
700 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
704 MenuItem engineMenu[] = {
705 {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
706 {"----", NULL, NothingProc},
707 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
708 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
709 {"----", NULL, NothingProc},
710 {N_("Hint"), "Hint", HintProc},
711 {N_("Book"), "Book", BookProc},
712 {"----", NULL, NothingProc},
713 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
714 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
718 MenuItem optionsMenu[] = {
719 #define OPTIONSDIALOG
721 {N_("General ..."), "General", OptionsProc},
723 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
724 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
725 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
726 {N_("ICS ..."), "ICS", IcsOptionsProc},
727 {N_("Match ..."), "Match", MatchOptionsProc},
728 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
729 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
730 // {N_(" ..."), "", OptionsProc},
731 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
732 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
733 {"----", NULL, NothingProc},
734 #ifndef OPTIONSDIALOG
735 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
736 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
737 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
738 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
739 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
740 {N_("Blindfold"), "Blindfold", BlindfoldProc},
741 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
743 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
745 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
746 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
747 {N_("Move Sound"), "Move Sound", MoveSoundProc},
748 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
749 {N_("One-Click Moving"), "OneClick", OneClickProc},
750 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
751 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
752 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
753 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
754 // {N_("Premove"), "Premove", PremoveProc},
755 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
756 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
757 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
758 {"----", NULL, NothingProc},
760 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
761 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
765 MenuItem helpMenu[] = {
766 {N_("Info XBoard"), "Info XBoard", InfoProc},
767 {N_("Man XBoard F1"), "Man XBoard", ManProc},
768 {"----", NULL, NothingProc},
769 {N_("About XBoard"), "About XBoard", AboutProc},
774 {N_("File"), "File", fileMenu},
775 {N_("Edit"), "Edit", editMenu},
776 {N_("View"), "View", viewMenu},
777 {N_("Mode"), "Mode", modeMenu},
778 {N_("Action"), "Action", actionMenu},
779 {N_("Engine"), "Engine", engineMenu},
780 {N_("Options"), "Options", optionsMenu},
781 {N_("Help"), "Help", helpMenu},
785 #define PAUSE_BUTTON "P"
786 MenuItem buttonBar[] = {
787 {"<<", "<<", ToStartProc},
788 {"<", "<", BackwardProc},
789 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
790 {">", ">", ForwardProc},
791 {">>", ">>", ToEndProc},
795 #define PIECE_MENU_SIZE 18
796 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
797 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
798 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
799 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
800 N_("Empty square"), N_("Clear board") },
801 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
802 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
803 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
804 N_("Empty square"), N_("Clear board") }
806 /* must be in same order as PieceMenuStrings! */
807 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
808 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
809 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
810 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
811 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
812 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
813 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
814 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
815 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
818 #define DROP_MENU_SIZE 6
819 String dropMenuStrings[DROP_MENU_SIZE] = {
820 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
822 /* must be in same order as PieceMenuStrings! */
823 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
824 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
825 WhiteRook, WhiteQueen
833 DropMenuEnables dmEnables[] = {
851 { XtNborderWidth, 0 },
852 { XtNdefaultDistance, 0 },
856 { XtNborderWidth, 0 },
857 { XtNresizable, (XtArgVal) True },
861 { XtNborderWidth, 0 },
867 { XtNjustify, (XtArgVal) XtJustifyRight },
868 { XtNlabel, (XtArgVal) "..." },
869 { XtNresizable, (XtArgVal) True },
870 { XtNresize, (XtArgVal) False }
873 Arg messageArgs[] = {
874 { XtNjustify, (XtArgVal) XtJustifyLeft },
875 { XtNlabel, (XtArgVal) "..." },
876 { XtNresizable, (XtArgVal) True },
877 { XtNresize, (XtArgVal) False }
881 { XtNborderWidth, 0 },
882 { XtNjustify, (XtArgVal) XtJustifyLeft }
885 XtResource clientResources[] = {
886 { "flashCount", "flashCount", XtRInt, sizeof(int),
887 XtOffset(AppDataPtr, flashCount), XtRImmediate,
888 (XtPointer) FLASH_COUNT },
891 XrmOptionDescRec shellOptions[] = {
892 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
893 { "-flash", "flashCount", XrmoptionNoArg, "3" },
894 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
897 XtActionsRec boardActions[] = {
898 { "DrawPosition", DrawPositionProc },
899 { "HandleUserMove", HandleUserMove },
900 { "AnimateUserMove", AnimateUserMove },
901 { "HandlePV", HandlePV },
902 { "SelectPV", SelectPV },
903 { "StopPV", StopPV },
904 { "FileNameAction", FileNameAction },
905 { "AskQuestionProc", AskQuestionProc },
906 { "AskQuestionReplyAction", AskQuestionReplyAction },
907 { "PieceMenuPopup", PieceMenuPopup },
908 { "WhiteClock", WhiteClock },
909 { "BlackClock", BlackClock },
910 { "Iconify", Iconify },
911 { "ResetProc", ResetProc },
912 { "NewVariantProc", NewVariantProc },
913 { "LoadGameProc", LoadGameProc },
914 { "LoadNextGameProc", LoadNextGameProc },
915 { "LoadPrevGameProc", LoadPrevGameProc },
916 { "LoadSelectedProc", LoadSelectedProc },
917 { "SetFilterProc", SetFilterProc },
918 { "ReloadGameProc", ReloadGameProc },
919 { "LoadPositionProc", LoadPositionProc },
920 { "LoadNextPositionProc", LoadNextPositionProc },
921 { "LoadPrevPositionProc", LoadPrevPositionProc },
922 { "ReloadPositionProc", ReloadPositionProc },
923 { "CopyPositionProc", CopyPositionProc },
924 { "PastePositionProc", PastePositionProc },
925 { "CopyGameProc", CopyGameProc },
926 { "CopyGameListProc", CopyGameListProc },
927 { "PasteGameProc", PasteGameProc },
928 { "SaveGameProc", SaveGameProc },
929 { "SavePositionProc", SavePositionProc },
930 { "MailMoveProc", MailMoveProc },
931 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
932 { "QuitProc", QuitProc },
933 { "MachineWhiteProc", MachineWhiteProc },
934 { "MachineBlackProc", MachineBlackProc },
935 { "AnalysisModeProc", AnalyzeModeProc },
936 { "AnalyzeFileProc", AnalyzeFileProc },
937 { "TwoMachinesProc", TwoMachinesProc },
938 { "IcsClientProc", IcsClientProc },
939 { "EditGameProc", EditGameProc },
940 { "EditPositionProc", EditPositionProc },
941 { "TrainingProc", EditPositionProc },
942 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
943 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
944 { "ShowGameListProc", ShowGameListProc },
945 { "ShowMoveListProc", HistoryShowProc},
946 { "EditTagsProc", EditCommentProc },
947 { "EditBookProc", EditBookProc },
948 { "EditCommentProc", EditCommentProc },
949 { "IcsInputBoxProc", IcsInputBoxProc },
950 { "PauseProc", PauseProc },
951 { "AcceptProc", AcceptProc },
952 { "DeclineProc", DeclineProc },
953 { "RematchProc", RematchProc },
954 { "CallFlagProc", CallFlagProc },
955 { "DrawProc", DrawProc },
956 { "AdjournProc", AdjournProc },
957 { "AbortProc", AbortProc },
958 { "ResignProc", ResignProc },
959 { "AdjuWhiteProc", AdjuWhiteProc },
960 { "AdjuBlackProc", AdjuBlackProc },
961 { "AdjuDrawProc", AdjuDrawProc },
962 { "TypeInProc", TypeInProc },
963 { "EnterKeyProc", EnterKeyProc },
964 { "UpKeyProc", UpKeyProc },
965 { "DownKeyProc", DownKeyProc },
966 { "StopObservingProc", StopObservingProc },
967 { "StopExaminingProc", StopExaminingProc },
968 { "UploadProc", UploadProc },
969 { "BackwardProc", BackwardProc },
970 { "ForwardProc", ForwardProc },
971 { "ToStartProc", ToStartProc },
972 { "ToEndProc", ToEndProc },
973 { "RevertProc", RevertProc },
974 { "AnnotateProc", AnnotateProc },
975 { "TruncateGameProc", TruncateGameProc },
976 { "MoveNowProc", MoveNowProc },
977 { "RetractMoveProc", RetractMoveProc },
978 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
979 { "UciMenuProc", (XtActionProc) UciMenuProc },
980 { "TimeControlProc", (XtActionProc) TimeControlProc },
981 { "FlipViewProc", FlipViewProc },
982 { "PonderNextMoveProc", PonderNextMoveProc },
983 #ifndef OPTIONSDIALOG
984 { "AlwaysQueenProc", AlwaysQueenProc },
985 { "AnimateDraggingProc", AnimateDraggingProc },
986 { "AnimateMovingProc", AnimateMovingProc },
987 { "AutoflagProc", AutoflagProc },
988 { "AutoflipProc", AutoflipProc },
989 { "BlindfoldProc", BlindfoldProc },
990 { "FlashMovesProc", FlashMovesProc },
992 { "HighlightDraggingProc", HighlightDraggingProc },
994 { "HighlightLastMoveProc", HighlightLastMoveProc },
995 // { "IcsAlarmProc", IcsAlarmProc },
996 { "MoveSoundProc", MoveSoundProc },
997 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
998 { "PopupExitMessageProc", PopupExitMessageProc },
999 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1000 // { "PremoveProc", PremoveProc },
1001 { "ShowCoordsProc", ShowCoordsProc },
1002 { "ShowThinkingProc", ShowThinkingProc },
1003 { "HideThinkingProc", HideThinkingProc },
1004 { "TestLegalityProc", TestLegalityProc },
1006 { "SaveSettingsProc", SaveSettingsProc },
1007 { "SaveOnExitProc", SaveOnExitProc },
1008 { "InfoProc", InfoProc },
1009 { "ManProc", ManProc },
1010 { "HintProc", HintProc },
1011 { "BookProc", BookProc },
1012 { "AboutGameProc", AboutGameProc },
1013 { "AboutProc", AboutProc },
1014 { "DebugProc", DebugProc },
1015 { "NothingProc", NothingProc },
1016 { "CommentClick", (XtActionProc) CommentClick },
1017 { "CommentPopDown", (XtActionProc) CommentPopDown },
1018 { "TagsPopDown", (XtActionProc) TagsPopDown },
1019 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1020 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1021 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1022 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1023 { "GameListPopDown", (XtActionProc) GameListPopDown },
1024 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1025 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1026 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1027 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1028 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1029 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1030 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1031 { "GenericPopDown", (XtActionProc) GenericPopDown },
1032 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1035 char globalTranslations[] =
1036 ":<Key>F9: ResignProc() \n \
1037 :Ctrl<Key>n: ResetProc() \n \
1038 :Meta<Key>V: NewVariantProc() \n \
1039 :Ctrl<Key>o: LoadGameProc() \n \
1040 :Meta<Key>Next: LoadNextGameProc() \n \
1041 :Meta<Key>Prior: LoadPrevGameProc() \n \
1042 :Ctrl<Key>s: SaveGameProc() \n \
1043 :Ctrl<Key>c: CopyGameProc() \n \
1044 :Ctrl<Key>v: PasteGameProc() \n \
1045 :Ctrl<Key>O: LoadPositionProc() \n \
1046 :Shift<Key>Next: LoadNextPositionProc() \n \
1047 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1048 :Ctrl<Key>S: SavePositionProc() \n \
1049 :Ctrl<Key>C: CopyPositionProc() \n \
1050 :Ctrl<Key>V: PastePositionProc() \n \
1051 :Ctrl<Key>q: QuitProc() \n \
1052 :Ctrl<Key>w: MachineWhiteProc() \n \
1053 :Ctrl<Key>b: MachineBlackProc() \n \
1054 :Ctrl<Key>t: TwoMachinesProc() \n \
1055 :Ctrl<Key>a: AnalysisModeProc() \n \
1056 :Ctrl<Key>f: AnalyzeFileProc() \n \
1057 :Ctrl<Key>e: EditGameProc() \n \
1058 :Ctrl<Key>E: EditPositionProc() \n \
1059 :Meta<Key>O: EngineOutputProc() \n \
1060 :Meta<Key>E: EvalGraphProc() \n \
1061 :Meta<Key>G: ShowGameListProc() \n \
1062 :Meta<Key>H: ShowMoveListProc() \n \
1063 :<Key>Pause: PauseProc() \n \
1064 :<Key>F3: AcceptProc() \n \
1065 :<Key>F4: DeclineProc() \n \
1066 :<Key>F12: RematchProc() \n \
1067 :<Key>F5: CallFlagProc() \n \
1068 :<Key>F6: DrawProc() \n \
1069 :<Key>F7: AdjournProc() \n \
1070 :<Key>F8: AbortProc() \n \
1071 :<Key>F10: StopObservingProc() \n \
1072 :<Key>F11: StopExaminingProc() \n \
1073 :Meta Ctrl<Key>F12: DebugProc() \n \
1074 :Meta<Key>End: ToEndProc() \n \
1075 :Meta<Key>Right: ForwardProc() \n \
1076 :Meta<Key>Home: ToStartProc() \n \
1077 :Meta<Key>Left: BackwardProc() \n \
1078 :<Key>Home: RevertProc() \n \
1079 :<Key>End: TruncateGameProc() \n \
1080 :Ctrl<Key>m: MoveNowProc() \n \
1081 :Ctrl<Key>x: RetractMoveProc() \n \
1082 :Meta<Key>J: EngineMenuProc() \n \
1083 :Meta<Key>U: UciMenuProc() \n \
1084 :Meta<Key>T: TimeControlProc() \n \
1085 :Ctrl<Key>P: PonderNextMoveProc() \n "
1086 #ifndef OPTIONSDIALOG
1088 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1089 :Ctrl<Key>F: AutoflagProc() \n \
1090 :Ctrl<Key>A: AnimateMovingProc() \n \
1091 :Ctrl<Key>L: TestLegalityProc() \n \
1092 :Ctrl<Key>H: HideThinkingProc() \n "
1095 :<Key>-: Iconify() \n \
1096 :<Key>F1: ManProc() \n \
1097 :<Key>F2: FlipViewProc() \n \
1098 <KeyDown>.: BackwardProc() \n \
1099 <KeyUp>.: ForwardProc() \n \
1100 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1101 \"Send to chess program:\",,1) \n \
1102 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1103 \"Send to second chess program:\",,2) \n";
1105 char boardTranslations[] =
1106 "<Btn1Down>: HandleUserMove(0) \n \
1107 Shift<Btn1Up>: HandleUserMove(1) \n \
1108 <Btn1Up>: HandleUserMove(0) \n \
1109 <Btn1Motion>: AnimateUserMove() \n \
1110 <Btn3Motion>: HandlePV() \n \
1111 <Btn3Up>: PieceMenuPopup(menuB) \n \
1112 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1113 PieceMenuPopup(menuB) \n \
1114 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1115 PieceMenuPopup(menuW) \n \
1116 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1117 PieceMenuPopup(menuW) \n \
1118 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1119 PieceMenuPopup(menuB) \n";
1121 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1122 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1124 char ICSInputTranslations[] =
1125 "<Key>Up: UpKeyProc() \n "
1126 "<Key>Down: DownKeyProc() \n "
1127 "<Key>Return: EnterKeyProc() \n";
1129 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1130 // as the widget is destroyed before the up-click can call extend-end
1131 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1133 String xboardResources[] = {
1134 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1135 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1136 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1141 /* Max possible square size */
1142 #define MAXSQSIZE 256
1144 static int xpm_avail[MAXSQSIZE];
1146 #ifdef HAVE_DIR_STRUCT
1148 /* Extract piece size from filename */
1150 xpm_getsize(name, len, ext)
1161 if ((p=strchr(name, '.')) == NULL ||
1162 StrCaseCmp(p+1, ext) != 0)
1168 while (*p && isdigit(*p))
1175 /* Setup xpm_avail */
1177 xpm_getavail(dirname, ext)
1185 for (i=0; i<MAXSQSIZE; ++i)
1188 if (appData.debugMode)
1189 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1191 dir = opendir(dirname);
1194 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1195 programName, dirname);
1199 while ((ent=readdir(dir)) != NULL) {
1200 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1201 if (i > 0 && i < MAXSQSIZE)
1211 xpm_print_avail(fp, ext)
1217 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1218 for (i=1; i<MAXSQSIZE; ++i) {
1224 /* Return XPM piecesize closest to size */
1226 xpm_closest_to(dirname, size, ext)
1232 int sm_diff = MAXSQSIZE;
1236 xpm_getavail(dirname, ext);
1238 if (appData.debugMode)
1239 xpm_print_avail(stderr, ext);
1241 for (i=1; i<MAXSQSIZE; ++i) {
1244 diff = (diff<0) ? -diff : diff;
1245 if (diff < sm_diff) {
1253 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1259 #else /* !HAVE_DIR_STRUCT */
1260 /* If we are on a system without a DIR struct, we can't
1261 read the directory, so we can't collect a list of
1262 filenames, etc., so we can't do any size-fitting. */
1264 xpm_closest_to(dirname, size, ext)
1269 fprintf(stderr, _("\
1270 Warning: No DIR structure found on this system --\n\
1271 Unable to autosize for XPM/XIM pieces.\n\
1272 Please report this error to %s.\n\
1273 Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
1276 #endif /* HAVE_DIR_STRUCT */
1278 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1279 "magenta", "cyan", "white" };
1283 TextColors textColors[(int)NColorClasses];
1285 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1287 parse_color(str, which)
1291 char *p, buf[100], *d;
1294 if (strlen(str) > 99) /* watch bounds on buf */
1299 for (i=0; i<which; ++i) {
1306 /* Could be looking at something like:
1308 .. in which case we want to stop on a comma also */
1309 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1313 return -1; /* Use default for empty field */
1316 if (which == 2 || isdigit(*p))
1319 while (*p && isalpha(*p))
1324 for (i=0; i<8; ++i) {
1325 if (!StrCaseCmp(buf, cnames[i]))
1326 return which? (i+40) : (i+30);
1328 if (!StrCaseCmp(buf, "default")) return -1;
1330 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1335 parse_cpair(cc, str)
1339 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1340 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1345 /* bg and attr are optional */
1346 textColors[(int)cc].bg = parse_color(str, 1);
1347 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1348 textColors[(int)cc].attr = 0;
1354 /* Arrange to catch delete-window events */
1355 Atom wm_delete_window;
1357 CatchDeleteWindow(Widget w, String procname)
1360 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1361 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1362 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1369 XtSetArg(args[0], XtNiconic, False);
1370 XtSetValues(shellWidget, args, 1);
1372 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1375 //---------------------------------------------------------------------------------------------------------
1376 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1379 #define CW_USEDEFAULT (1<<31)
1380 #define ICS_TEXT_MENU_SIZE 90
1381 #define DEBUG_FILE "xboard.debug"
1382 #define SetCurrentDirectory chdir
1383 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1387 // these two must some day move to frontend.h, when they are implemented
1388 Boolean GameListIsUp();
1390 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1393 // front-end part of option handling
1395 // [HGM] This platform-dependent table provides the location for storing the color info
1396 extern char *crWhite, * crBlack;
1400 &appData.whitePieceColor,
1401 &appData.blackPieceColor,
1402 &appData.lightSquareColor,
1403 &appData.darkSquareColor,
1404 &appData.highlightSquareColor,
1405 &appData.premoveHighlightColor,
1406 &appData.lowTimeWarningColor,
1417 // [HGM] font: keep a font for each square size, even non-stndard ones
1418 #define NUM_SIZES 18
1419 #define MAX_SIZE 130
1420 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1421 char *fontTable[NUM_FONTS][MAX_SIZE];
1424 ParseFont(char *name, int number)
1425 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1427 if(sscanf(name, "size%d:", &size)) {
1428 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1429 // defer processing it until we know if it matches our board size
1430 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1431 fontTable[number][size] = strdup(strchr(name, ':')+1);
1432 fontValid[number][size] = True;
1437 case 0: // CLOCK_FONT
1438 appData.clockFont = strdup(name);
1440 case 1: // MESSAGE_FONT
1441 appData.font = strdup(name);
1443 case 2: // COORD_FONT
1444 appData.coordFont = strdup(name);
1449 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1454 { // only 2 fonts currently
1455 appData.clockFont = CLOCK_FONT_NAME;
1456 appData.coordFont = COORD_FONT_NAME;
1457 appData.font = DEFAULT_FONT_NAME;
1462 { // no-op, until we identify the code for this already in XBoard and move it here
1466 ParseColor(int n, char *name)
1467 { // in XBoard, just copy the color-name string
1468 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1472 ParseTextAttribs(ColorClass cc, char *s)
1474 (&appData.colorShout)[cc] = strdup(s);
1478 ParseBoardSize(void *addr, char *name)
1480 appData.boardSize = strdup(name);
1485 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1489 SetCommPortDefaults()
1490 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1493 // [HGM] args: these three cases taken out to stay in front-end
1495 SaveFontArg(FILE *f, ArgDescriptor *ad)
1498 int i, n = (int)(intptr_t)ad->argLoc;
1500 case 0: // CLOCK_FONT
1501 name = appData.clockFont;
1503 case 1: // MESSAGE_FONT
1504 name = appData.font;
1506 case 2: // COORD_FONT
1507 name = appData.coordFont;
1512 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1513 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1514 fontTable[n][squareSize] = strdup(name);
1515 fontValid[n][squareSize] = True;
1518 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1519 fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
1524 { // nothing to do, as the sounds are at all times represented by their text-string names already
1528 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1529 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1530 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1534 SaveColor(FILE *f, ArgDescriptor *ad)
1535 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1536 if(colorVariable[(int)(intptr_t)ad->argLoc])
1537 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1541 SaveBoardSize(FILE *f, char *name, void *addr)
1542 { // wrapper to shield back-end from BoardSize & sizeInfo
1543 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1547 ParseCommPortSettings(char *s)
1548 { // no such option in XBoard (yet)
1551 extern Widget engineOutputShell;
1554 GetActualPlacement(Widget wg, WindowPlacement *wp)
1564 XtSetArg(args[i], XtNx, &x); i++;
1565 XtSetArg(args[i], XtNy, &y); i++;
1566 XtSetArg(args[i], XtNwidth, &w); i++;
1567 XtSetArg(args[i], XtNheight, &h); i++;
1568 XtGetValues(wg, args, i);
1577 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1578 // In XBoard this will have to wait until awareness of window parameters is implemented
1579 GetActualPlacement(shellWidget, &wpMain);
1580 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1581 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1582 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1583 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1584 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1585 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1589 PrintCommPortSettings(FILE *f, char *name)
1590 { // This option does not exist in XBoard
1594 MySearchPath(char *installDir, char *name, char *fullname)
1595 { // just append installDir and name. Perhaps ExpandPath should be used here?
1596 name = ExpandPathName(name);
1597 if(name && name[0] == '/')
1598 safeStrCpy(fullname, name, MSG_SIZ );
1600 sprintf(fullname, "%s%c%s", installDir, '/', name);
1606 MyGetFullPathName(char *name, char *fullname)
1607 { // should use ExpandPath?
1608 name = ExpandPathName(name);
1609 safeStrCpy(fullname, name, MSG_SIZ );
1614 EnsureOnScreen(int *x, int *y, int minX, int minY)
1621 { // [HGM] args: allows testing if main window is realized from back-end
1622 return xBoardWindow != 0;
1626 PopUpStartupDialog()
1627 { // start menu not implemented in XBoard
1631 ConvertToLine(int argc, char **argv)
1633 static char line[128*1024], buf[1024];
1637 for(i=1; i<argc; i++)
1639 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1640 && argv[i][0] != '{' )
1641 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1643 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1644 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1647 line[strlen(line)-1] = NULLCHAR;
1651 //--------------------------------------------------------------------------------------------
1653 extern Boolean twoBoards, partnerUp;
1656 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1658 #define BoardSize int
1659 void InitDrawingSizes(BoardSize boardSize, int flags)
1660 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1661 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1663 XtGeometryResult gres;
1666 if(!formWidget) return;
1669 * Enable shell resizing.
1671 shellArgs[0].value = (XtArgVal) &w;
1672 shellArgs[1].value = (XtArgVal) &h;
1673 XtGetValues(shellWidget, shellArgs, 2);
1675 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1676 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1677 XtSetValues(shellWidget, &shellArgs[2], 4);
1679 XtSetArg(args[0], XtNdefaultDistance, &sep);
1680 XtGetValues(formWidget, args, 1);
1682 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1683 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1684 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1686 hOffset = boardWidth + 10;
1687 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1688 secondSegments[i] = gridSegments[i];
1689 secondSegments[i].x1 += hOffset;
1690 secondSegments[i].x2 += hOffset;
1693 XtSetArg(args[0], XtNwidth, boardWidth);
1694 XtSetArg(args[1], XtNheight, boardHeight);
1695 XtSetValues(boardWidget, args, 2);
1697 timerWidth = (boardWidth - sep) / 2;
1698 XtSetArg(args[0], XtNwidth, timerWidth);
1699 XtSetValues(whiteTimerWidget, args, 1);
1700 XtSetValues(blackTimerWidget, args, 1);
1702 XawFormDoLayout(formWidget, False);
1704 if (appData.titleInWindow) {
1706 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1707 XtSetArg(args[i], XtNheight, &h); i++;
1708 XtGetValues(titleWidget, args, i);
1710 w = boardWidth - 2*bor;
1712 XtSetArg(args[0], XtNwidth, &w);
1713 XtGetValues(menuBarWidget, args, 1);
1714 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1717 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1718 if (gres != XtGeometryYes && appData.debugMode) {
1720 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1721 programName, gres, w, h, wr, hr);
1725 XawFormDoLayout(formWidget, True);
1728 * Inhibit shell resizing.
1730 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1731 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1732 shellArgs[4].value = shellArgs[2].value = w;
1733 shellArgs[5].value = shellArgs[3].value = h;
1734 XtSetValues(shellWidget, &shellArgs[0], 6);
1736 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1739 for(i=0; i<4; i++) {
1741 for(p=0; p<=(int)WhiteKing; p++)
1742 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1743 if(gameInfo.variant == VariantShogi) {
1744 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1745 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1746 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1747 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1748 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1751 if(gameInfo.variant == VariantGothic) {
1752 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1755 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1756 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1757 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1760 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1761 for(p=0; p<=(int)WhiteKing; p++)
1762 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1763 if(gameInfo.variant == VariantShogi) {
1764 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1765 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1766 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1767 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1768 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1771 if(gameInfo.variant == VariantGothic) {
1772 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1775 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1776 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1777 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1782 for(i=0; i<2; i++) {
1784 for(p=0; p<=(int)WhiteKing; p++)
1785 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1786 if(gameInfo.variant == VariantShogi) {
1787 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1788 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1789 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1790 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1791 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1794 if(gameInfo.variant == VariantGothic) {
1795 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1798 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1799 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1800 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1810 void ParseIcsTextColors()
1811 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1812 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1813 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1814 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1815 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1816 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1817 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1818 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1819 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1820 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1821 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1823 if (appData.colorize) {
1825 _("%s: can't parse color names; disabling colorization\n"),
1828 appData.colorize = FALSE;
1833 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1834 XrmValue vFrom, vTo;
1835 int forceMono = False;
1837 if (!appData.monoMode) {
1838 vFrom.addr = (caddr_t) appData.lightSquareColor;
1839 vFrom.size = strlen(appData.lightSquareColor);
1840 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1841 if (vTo.addr == NULL) {
1842 appData.monoMode = True;
1845 lightSquareColor = *(Pixel *) vTo.addr;
1848 if (!appData.monoMode) {
1849 vFrom.addr = (caddr_t) appData.darkSquareColor;
1850 vFrom.size = strlen(appData.darkSquareColor);
1851 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1852 if (vTo.addr == NULL) {
1853 appData.monoMode = True;
1856 darkSquareColor = *(Pixel *) vTo.addr;
1859 if (!appData.monoMode) {
1860 vFrom.addr = (caddr_t) appData.whitePieceColor;
1861 vFrom.size = strlen(appData.whitePieceColor);
1862 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1863 if (vTo.addr == NULL) {
1864 appData.monoMode = True;
1867 whitePieceColor = *(Pixel *) vTo.addr;
1870 if (!appData.monoMode) {
1871 vFrom.addr = (caddr_t) appData.blackPieceColor;
1872 vFrom.size = strlen(appData.blackPieceColor);
1873 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1874 if (vTo.addr == NULL) {
1875 appData.monoMode = True;
1878 blackPieceColor = *(Pixel *) vTo.addr;
1882 if (!appData.monoMode) {
1883 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1884 vFrom.size = strlen(appData.highlightSquareColor);
1885 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1886 if (vTo.addr == NULL) {
1887 appData.monoMode = True;
1890 highlightSquareColor = *(Pixel *) vTo.addr;
1894 if (!appData.monoMode) {
1895 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1896 vFrom.size = strlen(appData.premoveHighlightColor);
1897 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1898 if (vTo.addr == NULL) {
1899 appData.monoMode = True;
1902 premoveHighlightColor = *(Pixel *) vTo.addr;
1910 { // [HGM] taken out of main
1912 if (appData.monoMode && // [HGM] no sense to go on to certain doom
1913 (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
1914 appData.bitmapDirectory = DEF_BITMAP_DIR;
1916 if (appData.bitmapDirectory[0] != NULLCHAR) {
1920 CreateXPMBoard(appData.liteBackTextureFile, 1);
1921 CreateXPMBoard(appData.darkBackTextureFile, 0);
1925 /* Create regular pieces */
1926 if (!useImages) CreatePieces();
1935 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1936 XSetWindowAttributes window_attributes;
1938 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1939 XrmValue vFrom, vTo;
1940 XtGeometryResult gres;
1943 int forceMono = False;
1945 srandom(time(0)); // [HGM] book: make random truly random
1947 setbuf(stdout, NULL);
1948 setbuf(stderr, NULL);
1951 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1952 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1956 programName = strrchr(argv[0], '/');
1957 if (programName == NULL)
1958 programName = argv[0];
1963 XtSetLanguageProc(NULL, NULL, NULL);
1964 bindtextdomain(PACKAGE, LOCALEDIR);
1965 textdomain(PACKAGE);
1969 XtAppInitialize(&appContext, "XBoard", shellOptions,
1970 XtNumber(shellOptions),
1971 &argc, argv, xboardResources, NULL, 0);
1972 appData.boardSize = "";
1973 InitAppData(ConvertToLine(argc, argv));
1975 if (p == NULL) p = "/tmp";
1976 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1977 gameCopyFilename = (char*) malloc(i);
1978 gamePasteFilename = (char*) malloc(i);
1979 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1980 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1982 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1983 clientResources, XtNumber(clientResources),
1986 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1987 static char buf[MSG_SIZ];
1988 EscapeExpand(buf, appData.firstInitString);
1989 appData.firstInitString = strdup(buf);
1990 EscapeExpand(buf, appData.secondInitString);
1991 appData.secondInitString = strdup(buf);
1992 EscapeExpand(buf, appData.firstComputerString);
1993 appData.firstComputerString = strdup(buf);
1994 EscapeExpand(buf, appData.secondComputerString);
1995 appData.secondComputerString = strdup(buf);
1998 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2001 if (chdir(chessDir) != 0) {
2002 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2008 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2009 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2010 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2011 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2014 setbuf(debugFP, NULL);
2017 /* [HGM,HR] make sure board size is acceptable */
2018 if(appData.NrFiles > BOARD_FILES ||
2019 appData.NrRanks > BOARD_RANKS )
2020 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2023 /* This feature does not work; animation needs a rewrite */
2024 appData.highlightDragging = FALSE;
2028 xDisplay = XtDisplay(shellWidget);
2029 xScreen = DefaultScreen(xDisplay);
2030 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2032 gameInfo.variant = StringToVariant(appData.variant);
2033 InitPosition(FALSE);
2036 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2038 if (isdigit(appData.boardSize[0])) {
2039 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2040 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2041 &fontPxlSize, &smallLayout, &tinyLayout);
2043 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2044 programName, appData.boardSize);
2048 /* Find some defaults; use the nearest known size */
2049 SizeDefaults *szd, *nearest;
2050 int distance = 99999;
2051 nearest = szd = sizeDefaults;
2052 while (szd->name != NULL) {
2053 if (abs(szd->squareSize - squareSize) < distance) {
2055 distance = abs(szd->squareSize - squareSize);
2056 if (distance == 0) break;
2060 if (i < 2) lineGap = nearest->lineGap;
2061 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2062 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2063 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2064 if (i < 6) smallLayout = nearest->smallLayout;
2065 if (i < 7) tinyLayout = nearest->tinyLayout;
2068 SizeDefaults *szd = sizeDefaults;
2069 if (*appData.boardSize == NULLCHAR) {
2070 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2071 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2074 if (szd->name == NULL) szd--;
2075 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2077 while (szd->name != NULL &&
2078 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2079 if (szd->name == NULL) {
2080 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2081 programName, appData.boardSize);
2085 squareSize = szd->squareSize;
2086 lineGap = szd->lineGap;
2087 clockFontPxlSize = szd->clockFontPxlSize;
2088 coordFontPxlSize = szd->coordFontPxlSize;
2089 fontPxlSize = szd->fontPxlSize;
2090 smallLayout = szd->smallLayout;
2091 tinyLayout = szd->tinyLayout;
2092 // [HGM] font: use defaults from settings file if available and not overruled
2094 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2095 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2096 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2097 appData.font = fontTable[MESSAGE_FONT][squareSize];
2098 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2099 appData.coordFont = fontTable[COORD_FONT][squareSize];
2101 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2102 if (strlen(appData.pixmapDirectory) > 0) {
2103 p = ExpandPathName(appData.pixmapDirectory);
2105 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2106 appData.pixmapDirectory);
2109 if (appData.debugMode) {
2110 fprintf(stderr, _("\
2111 XBoard square size (hint): %d\n\
2112 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2114 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2115 if (appData.debugMode) {
2116 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2119 defaultLineGap = lineGap;
2120 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2122 /* [HR] height treated separately (hacked) */
2123 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2124 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2125 if (appData.showJail == 1) {
2126 /* Jail on top and bottom */
2127 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2128 XtSetArg(boardArgs[2], XtNheight,
2129 boardHeight + 2*(lineGap + squareSize));
2130 } else if (appData.showJail == 2) {
2132 XtSetArg(boardArgs[1], XtNwidth,
2133 boardWidth + 2*(lineGap + squareSize));
2134 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2137 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2138 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2142 * Determine what fonts to use.
2144 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2145 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2146 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2147 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2148 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2149 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2150 appData.font = FindFont(appData.font, fontPxlSize);
2151 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2152 countFontStruct = XQueryFont(xDisplay, countFontID);
2153 // appData.font = FindFont(appData.font, fontPxlSize);
2155 xdb = XtDatabase(xDisplay);
2156 XrmPutStringResource(&xdb, "*font", appData.font);
2159 * Detect if there are not enough colors available and adapt.
2161 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2162 appData.monoMode = True;
2165 forceMono = MakeColors();
2168 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2170 appData.monoMode = True;
2173 if (appData.lowTimeWarning && !appData.monoMode) {
2174 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2175 vFrom.size = strlen(appData.lowTimeWarningColor);
2176 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2177 if (vTo.addr == NULL)
2178 appData.monoMode = True;
2180 lowTimeWarningColor = *(Pixel *) vTo.addr;
2183 if (appData.monoMode && appData.debugMode) {
2184 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2185 (unsigned long) XWhitePixel(xDisplay, xScreen),
2186 (unsigned long) XBlackPixel(xDisplay, xScreen));
2189 ParseIcsTextColors();
2190 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2191 textColors[ColorNone].attr = 0;
2193 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2199 layoutName = "tinyLayout";
2200 } else if (smallLayout) {
2201 layoutName = "smallLayout";
2203 layoutName = "normalLayout";
2205 /* Outer layoutWidget is there only to provide a name for use in
2206 resources that depend on the layout style */
2208 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2209 layoutArgs, XtNumber(layoutArgs));
2211 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2212 formArgs, XtNumber(formArgs));
2213 XtSetArg(args[0], XtNdefaultDistance, &sep);
2214 XtGetValues(formWidget, args, 1);
2217 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2218 XtSetArg(args[0], XtNtop, XtChainTop);
2219 XtSetArg(args[1], XtNbottom, XtChainTop);
2220 XtSetArg(args[2], XtNright, XtChainLeft);
2221 XtSetValues(menuBarWidget, args, 3);
2223 widgetList[j++] = whiteTimerWidget =
2224 XtCreateWidget("whiteTime", labelWidgetClass,
2225 formWidget, timerArgs, XtNumber(timerArgs));
2226 XtSetArg(args[0], XtNfont, clockFontStruct);
2227 XtSetArg(args[1], XtNtop, XtChainTop);
2228 XtSetArg(args[2], XtNbottom, XtChainTop);
2229 XtSetValues(whiteTimerWidget, args, 3);
2231 widgetList[j++] = blackTimerWidget =
2232 XtCreateWidget("blackTime", labelWidgetClass,
2233 formWidget, timerArgs, XtNumber(timerArgs));
2234 XtSetArg(args[0], XtNfont, clockFontStruct);
2235 XtSetArg(args[1], XtNtop, XtChainTop);
2236 XtSetArg(args[2], XtNbottom, XtChainTop);
2237 XtSetValues(blackTimerWidget, args, 3);
2239 if (appData.titleInWindow) {
2240 widgetList[j++] = titleWidget =
2241 XtCreateWidget("title", labelWidgetClass, formWidget,
2242 titleArgs, XtNumber(titleArgs));
2243 XtSetArg(args[0], XtNtop, XtChainTop);
2244 XtSetArg(args[1], XtNbottom, XtChainTop);
2245 XtSetValues(titleWidget, args, 2);
2248 if (appData.showButtonBar) {
2249 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2250 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2251 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2252 XtSetArg(args[2], XtNtop, XtChainTop);
2253 XtSetArg(args[3], XtNbottom, XtChainTop);
2254 XtSetValues(buttonBarWidget, args, 4);
2257 widgetList[j++] = messageWidget =
2258 XtCreateWidget("message", labelWidgetClass, formWidget,
2259 messageArgs, XtNumber(messageArgs));
2260 XtSetArg(args[0], XtNtop, XtChainTop);
2261 XtSetArg(args[1], XtNbottom, XtChainTop);
2262 XtSetValues(messageWidget, args, 2);
2264 widgetList[j++] = boardWidget =
2265 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2266 XtNumber(boardArgs));
2268 XtManageChildren(widgetList, j);
2270 timerWidth = (boardWidth - sep) / 2;
2271 XtSetArg(args[0], XtNwidth, timerWidth);
2272 XtSetValues(whiteTimerWidget, args, 1);
2273 XtSetValues(blackTimerWidget, args, 1);
2275 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2276 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2277 XtGetValues(whiteTimerWidget, args, 2);
2279 if (appData.showButtonBar) {
2280 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2281 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2282 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2286 * formWidget uses these constraints but they are stored
2290 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2291 XtSetValues(menuBarWidget, args, i);
2292 if (appData.titleInWindow) {
2295 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2296 XtSetValues(whiteTimerWidget, args, i);
2298 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2299 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2300 XtSetValues(blackTimerWidget, args, i);
2302 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2303 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2304 XtSetValues(titleWidget, args, i);
2306 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2307 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2308 XtSetValues(messageWidget, args, i);
2309 if (appData.showButtonBar) {
2311 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2312 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2313 XtSetValues(buttonBarWidget, args, i);
2317 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2318 XtSetValues(whiteTimerWidget, args, i);
2320 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2321 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2322 XtSetValues(blackTimerWidget, args, i);
2324 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2325 XtSetValues(titleWidget, args, i);
2327 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2328 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2329 XtSetValues(messageWidget, args, i);
2330 if (appData.showButtonBar) {
2332 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2333 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2334 XtSetValues(buttonBarWidget, args, i);
2339 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2340 XtSetValues(whiteTimerWidget, args, i);
2342 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2343 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2344 XtSetValues(blackTimerWidget, args, i);
2346 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2347 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2348 XtSetValues(messageWidget, args, i);
2349 if (appData.showButtonBar) {
2351 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2352 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2353 XtSetValues(buttonBarWidget, args, i);
2357 XtSetArg(args[0], XtNfromVert, messageWidget);
2358 XtSetArg(args[1], XtNtop, XtChainTop);
2359 XtSetArg(args[2], XtNbottom, XtChainBottom);
2360 XtSetArg(args[3], XtNleft, XtChainLeft);
2361 XtSetArg(args[4], XtNright, XtChainRight);
2362 XtSetValues(boardWidget, args, 5);
2364 XtRealizeWidget(shellWidget);
2367 XtSetArg(args[0], XtNx, wpMain.x);
2368 XtSetArg(args[1], XtNy, wpMain.y);
2369 XtSetValues(shellWidget, args, 2);
2373 * Correct the width of the message and title widgets.
2374 * It is not known why some systems need the extra fudge term.
2375 * The value "2" is probably larger than needed.
2377 XawFormDoLayout(formWidget, False);
2379 #define WIDTH_FUDGE 2
2381 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2382 XtSetArg(args[i], XtNheight, &h); i++;
2383 XtGetValues(messageWidget, args, i);
2384 if (appData.showButtonBar) {
2386 XtSetArg(args[i], XtNwidth, &w); i++;
2387 XtGetValues(buttonBarWidget, args, i);
2388 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2390 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2393 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2394 if (gres != XtGeometryYes && appData.debugMode) {
2395 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2396 programName, gres, w, h, wr, hr);
2399 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2400 /* The size used for the child widget in layout lags one resize behind
2401 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2403 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2404 if (gres != XtGeometryYes && appData.debugMode) {
2405 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2406 programName, gres, w, h, wr, hr);
2409 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2410 XtSetArg(args[1], XtNright, XtChainRight);
2411 XtSetValues(messageWidget, args, 2);
2413 if (appData.titleInWindow) {
2415 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2416 XtSetArg(args[i], XtNheight, &h); i++;
2417 XtGetValues(titleWidget, args, i);
2419 w = boardWidth - 2*bor;
2421 XtSetArg(args[0], XtNwidth, &w);
2422 XtGetValues(menuBarWidget, args, 1);
2423 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2426 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2427 if (gres != XtGeometryYes && appData.debugMode) {
2429 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2430 programName, gres, w, h, wr, hr);
2433 XawFormDoLayout(formWidget, True);
2435 xBoardWindow = XtWindow(boardWidget);
2437 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2438 // not need to go into InitDrawingSizes().
2442 * Create X checkmark bitmap and initialize option menu checks.
2444 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2445 checkmark_bits, checkmark_width, checkmark_height);
2446 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2447 #ifndef OPTIONSDIALOG
2448 if (appData.alwaysPromoteToQueen) {
2449 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2452 if (appData.animateDragging) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,
2454 "menuOptions.Animate Dragging"),
2457 if (appData.animate) {
2458 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2461 if (appData.autoCallFlag) {
2462 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2465 if (appData.autoFlipView) {
2466 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2469 if (appData.blindfold) {
2470 XtSetValues(XtNameToWidget(menuBarWidget,
2471 "menuOptions.Blindfold"), args, 1);
2473 if (appData.flashCount > 0) {
2474 XtSetValues(XtNameToWidget(menuBarWidget,
2475 "menuOptions.Flash Moves"),
2479 if (appData.highlightDragging) {
2480 XtSetValues(XtNameToWidget(menuBarWidget,
2481 "menuOptions.Highlight Dragging"),
2485 if (appData.highlightLastMove) {
2486 XtSetValues(XtNameToWidget(menuBarWidget,
2487 "menuOptions.Highlight Last Move"),
2490 if (appData.highlightMoveWithArrow) {
2491 XtSetValues(XtNameToWidget(menuBarWidget,
2492 "menuOptions.Arrow"),
2495 // if (appData.icsAlarm) {
2496 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2499 if (appData.ringBellAfterMoves) {
2500 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2503 if (appData.oneClick) {
2504 XtSetValues(XtNameToWidget(menuBarWidget,
2505 "menuOptions.OneClick"), args, 1);
2507 if (appData.periodicUpdates) {
2508 XtSetValues(XtNameToWidget(menuBarWidget,
2509 "menuOptions.Periodic Updates"), args, 1);
2511 if (appData.ponderNextMove) {
2512 XtSetValues(XtNameToWidget(menuBarWidget,
2513 "menuOptions.Ponder Next Move"), args, 1);
2515 if (appData.popupExitMessage) {
2516 XtSetValues(XtNameToWidget(menuBarWidget,
2517 "menuOptions.Popup Exit Message"), args, 1);
2519 if (appData.popupMoveErrors) {
2520 XtSetValues(XtNameToWidget(menuBarWidget,
2521 "menuOptions.Popup Move Errors"), args, 1);
2523 // if (appData.premove) {
2524 // XtSetValues(XtNameToWidget(menuBarWidget,
2525 // "menuOptions.Premove"), args, 1);
2527 if (appData.showCoords) {
2528 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2531 if (appData.hideThinkingFromHuman) {
2532 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2535 if (appData.testLegality) {
2536 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2540 if (saveSettingsOnExit) {
2541 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2548 ReadBitmap(&wIconPixmap, "icon_white.bm",
2549 icon_white_bits, icon_white_width, icon_white_height);
2550 ReadBitmap(&bIconPixmap, "icon_black.bm",
2551 icon_black_bits, icon_black_width, icon_black_height);
2552 iconPixmap = wIconPixmap;
2554 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2555 XtSetValues(shellWidget, args, i);
2558 * Create a cursor for the board widget.
2560 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2561 XChangeWindowAttributes(xDisplay, xBoardWindow,
2562 CWCursor, &window_attributes);
2565 * Inhibit shell resizing.
2567 shellArgs[0].value = (XtArgVal) &w;
2568 shellArgs[1].value = (XtArgVal) &h;
2569 XtGetValues(shellWidget, shellArgs, 2);
2570 shellArgs[4].value = shellArgs[2].value = w;
2571 shellArgs[5].value = shellArgs[3].value = h;
2572 XtSetValues(shellWidget, &shellArgs[2], 4);
2573 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2574 marginH = h - boardHeight;
2576 CatchDeleteWindow(shellWidget, "QuitProc");
2584 if (appData.animate || appData.animateDragging)
2587 XtAugmentTranslations(formWidget,
2588 XtParseTranslationTable(globalTranslations));
2589 XtAugmentTranslations(boardWidget,
2590 XtParseTranslationTable(boardTranslations));
2591 XtAugmentTranslations(whiteTimerWidget,
2592 XtParseTranslationTable(whiteTranslations));
2593 XtAugmentTranslations(blackTimerWidget,
2594 XtParseTranslationTable(blackTranslations));
2596 /* Why is the following needed on some versions of X instead
2597 * of a translation? */
2598 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2599 (XtEventHandler) EventProc, NULL);
2601 XtAddEventHandler(formWidget, KeyPressMask, False,
2602 (XtEventHandler) MoveTypeInProc, NULL);
2604 /* [AS] Restore layout */
2605 if( wpMoveHistory.visible ) {
2609 if( wpEvalGraph.visible )
2614 if( wpEngineOutput.visible ) {
2615 EngineOutputPopUp();
2620 if (errorExitStatus == -1) {
2621 if (appData.icsActive) {
2622 /* We now wait until we see "login:" from the ICS before
2623 sending the logon script (problems with timestamp otherwise) */
2624 /*ICSInitScript();*/
2625 if (appData.icsInputBox) ICSInputBoxPopUp();
2629 signal(SIGWINCH, TermSizeSigHandler);
2631 signal(SIGINT, IntSigHandler);
2632 signal(SIGTERM, IntSigHandler);
2633 if (*appData.cmailGameName != NULLCHAR) {
2634 signal(SIGUSR1, CmailSigHandler);
2637 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2639 // XtSetKeyboardFocus(shellWidget, formWidget);
2640 XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
2642 XtAppMainLoop(appContext);
2643 if (appData.debugMode) fclose(debugFP); // [DM] debug
2650 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2651 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2653 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2654 unlink(gameCopyFilename);
2655 unlink(gamePasteFilename);
2658 RETSIGTYPE TermSizeSigHandler(int sig)
2671 CmailSigHandler(sig)
2677 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2679 /* Activate call-back function CmailSigHandlerCallBack() */
2680 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2682 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2686 CmailSigHandlerCallBack(isr, closure, message, count, error)
2694 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2696 /**** end signal code ****/
2702 /* try to open the icsLogon script, either in the location given
2703 * or in the users HOME directory
2710 f = fopen(appData.icsLogon, "r");
2713 homedir = getenv("HOME");
2714 if (homedir != NULL)
2716 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2717 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2718 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2719 f = fopen(buf, "r");
2724 ProcessICSInitScript(f);
2726 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2749 if (!menuBarWidget) return;
2750 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2752 DisplayError("menuEdit.Revert", 0);
2754 XtSetSensitive(w, !grey);
2756 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2758 DisplayError("menuEdit.Annotate", 0);
2760 XtSetSensitive(w, !grey);
2765 SetMenuEnables(enab)
2769 if (!menuBarWidget) return;
2770 while (enab->name != NULL) {
2771 w = XtNameToWidget(menuBarWidget, enab->name);
2773 DisplayError(enab->name, 0);
2775 XtSetSensitive(w, enab->value);
2781 Enables icsEnables[] = {
2782 { "menuFile.Mail Move", False },
2783 { "menuFile.Reload CMail Message", False },
2784 { "menuMode.Machine Black", False },
2785 { "menuMode.Machine White", False },
2786 { "menuMode.Analysis Mode", False },
2787 { "menuMode.Analyze File", False },
2788 { "menuMode.Two Machines", False },
2789 { "menuMode.Machine Match", False },
2791 { "menuEngine.Hint", False },
2792 { "menuEngine.Book", False },
2793 { "menuEngine.Move Now", False },
2794 #ifndef OPTIONSDIALOG
2795 { "menuOptions.Periodic Updates", False },
2796 { "menuOptions.Hide Thinking", False },
2797 { "menuOptions.Ponder Next Move", False },
2800 { "menuEngine.Engine #1 Settings", False },
2801 { "menuEngine.Engine #2 Settings", False },
2802 { "menuEngine.Load Engine", False },
2803 { "menuEdit.Annotate", False },
2804 { "menuOptions.Match", False },
2808 Enables ncpEnables[] = {
2809 { "menuFile.Mail Move", False },
2810 { "menuFile.Reload CMail Message", False },
2811 { "menuMode.Machine White", False },
2812 { "menuMode.Machine Black", False },
2813 { "menuMode.Analysis Mode", False },
2814 { "menuMode.Analyze File", False },
2815 { "menuMode.Two Machines", False },
2816 { "menuMode.Machine Match", False },
2817 { "menuMode.ICS Client", False },
2818 { "menuView.ICStex", False },
2819 { "menuView.ICS Input Box", False },
2820 { "Action", False },
2821 { "menuEdit.Revert", False },
2822 { "menuEdit.Annotate", False },
2823 { "menuEngine.Engine #1 Settings", False },
2824 { "menuEngine.Engine #2 Settings", False },
2825 { "menuEngine.Move Now", False },
2826 { "menuEngine.Retract Move", False },
2827 { "menuOptions.ICS", False },
2828 #ifndef OPTIONSDIALOG
2829 { "menuOptions.Auto Flag", False },
2830 { "menuOptions.Auto Flip View", False },
2831 // { "menuOptions.ICS Alarm", False },
2832 { "menuOptions.Move Sound", False },
2833 { "menuOptions.Hide Thinking", False },
2834 { "menuOptions.Periodic Updates", False },
2835 { "menuOptions.Ponder Next Move", False },
2837 { "menuEngine.Hint", False },
2838 { "menuEngine.Book", False },
2842 Enables gnuEnables[] = {
2843 { "menuMode.ICS Client", False },
2844 { "menuView.ICStex", False },
2845 { "menuView.ICS Input Box", False },
2846 { "menuAction.Accept", False },
2847 { "menuAction.Decline", False },
2848 { "menuAction.Rematch", False },
2849 { "menuAction.Adjourn", False },
2850 { "menuAction.Stop Examining", False },
2851 { "menuAction.Stop Observing", False },
2852 { "menuAction.Upload to Examine", False },
2853 { "menuEdit.Revert", False },
2854 { "menuEdit.Annotate", False },
2855 { "menuOptions.ICS", False },
2857 /* The next two options rely on SetCmailMode being called *after* */
2858 /* SetGNUMode so that when GNU is being used to give hints these */
2859 /* menu options are still available */
2861 { "menuFile.Mail Move", False },
2862 { "menuFile.Reload CMail Message", False },
2863 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
2864 { "menuMode.Machine White", True },
2865 { "menuMode.Machine Black", True },
2866 { "menuMode.Analysis Mode", True },
2867 { "menuMode.Analyze File", True },
2868 { "menuMode.Two Machines", True },
2869 { "menuMode.Machine Match", True },
2870 { "menuEngine.Engine #1 Settings", True },
2871 { "menuEngine.Engine #2 Settings", True },
2872 { "menuEngine.Hint", True },
2873 { "menuEngine.Book", True },
2874 { "menuEngine.Move Now", True },
2875 { "menuEngine.Retract Move", True },
2880 Enables cmailEnables[] = {
2882 { "menuAction.Call Flag", False },
2883 { "menuAction.Draw", True },
2884 { "menuAction.Adjourn", False },
2885 { "menuAction.Abort", False },
2886 { "menuAction.Stop Observing", False },
2887 { "menuAction.Stop Examining", False },
2888 { "menuFile.Mail Move", True },
2889 { "menuFile.Reload CMail Message", True },
2893 Enables trainingOnEnables[] = {
2894 { "menuMode.Edit Comment", False },
2895 { "menuMode.Pause", False },
2896 { "menuEdit.Forward", False },
2897 { "menuEdit.Backward", False },
2898 { "menuEdit.Forward to End", False },
2899 { "menuEdit.Back to Start", False },
2900 { "menuEngine.Move Now", False },
2901 { "menuEdit.Truncate Game", False },
2905 Enables trainingOffEnables[] = {
2906 { "menuMode.Edit Comment", True },
2907 { "menuMode.Pause", True },
2908 { "menuEdit.Forward", True },
2909 { "menuEdit.Backward", True },
2910 { "menuEdit.Forward to End", True },
2911 { "menuEdit.Back to Start", True },
2912 { "menuEngine.Move Now", True },
2913 { "menuEdit.Truncate Game", True },
2917 Enables machineThinkingEnables[] = {
2918 { "menuFile.Load Game", False },
2919 // { "menuFile.Load Next Game", False },
2920 // { "menuFile.Load Previous Game", False },
2921 // { "menuFile.Reload Same Game", False },
2922 { "menuEdit.Paste Game", False },
2923 { "menuFile.Load Position", False },
2924 // { "menuFile.Load Next Position", False },
2925 // { "menuFile.Load Previous Position", False },
2926 // { "menuFile.Reload Same Position", False },
2927 { "menuEdit.Paste Position", False },
2928 { "menuMode.Machine White", False },
2929 { "menuMode.Machine Black", False },
2930 { "menuMode.Two Machines", False },
2931 // { "menuMode.Machine Match", False },
2932 { "menuEngine.Retract Move", False },
2936 Enables userThinkingEnables[] = {
2937 { "menuFile.Load Game", True },
2938 // { "menuFile.Load Next Game", True },
2939 // { "menuFile.Load Previous Game", True },
2940 // { "menuFile.Reload Same Game", True },
2941 { "menuEdit.Paste Game", True },
2942 { "menuFile.Load Position", True },
2943 // { "menuFile.Load Next Position", True },
2944 // { "menuFile.Load Previous Position", True },
2945 // { "menuFile.Reload Same Position", True },
2946 { "menuEdit.Paste Position", True },
2947 { "menuMode.Machine White", True },
2948 { "menuMode.Machine Black", True },
2949 { "menuMode.Two Machines", True },
2950 // { "menuMode.Machine Match", True },
2951 { "menuEngine.Retract Move", True },
2957 SetMenuEnables(icsEnables);
2960 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
2961 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2962 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
2970 SetMenuEnables(ncpEnables);
2976 SetMenuEnables(gnuEnables);
2982 SetMenuEnables(cmailEnables);
2988 SetMenuEnables(trainingOnEnables);
2989 if (appData.showButtonBar) {
2990 XtSetSensitive(buttonBarWidget, False);
2996 SetTrainingModeOff()
2998 SetMenuEnables(trainingOffEnables);
2999 if (appData.showButtonBar) {
3000 XtSetSensitive(buttonBarWidget, True);
3005 SetUserThinkingEnables()
3007 if (appData.noChessProgram) return;
3008 SetMenuEnables(userThinkingEnables);
3012 SetMachineThinkingEnables()
3014 if (appData.noChessProgram) return;
3015 SetMenuEnables(machineThinkingEnables);
3017 case MachinePlaysBlack:
3018 case MachinePlaysWhite:
3019 case TwoMachinesPlay:
3020 XtSetSensitive(XtNameToWidget(menuBarWidget,
3021 ModeToWidgetName(gameMode)), True);
3028 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
3029 #define HISTORY_SIZE 64
3030 static char *history[HISTORY_SIZE];
3031 int histIn = 0, histP = 0;
3034 SaveInHistory(char *cmd)
3036 if (history[histIn] != NULL) {
3037 free(history[histIn]);
3038 history[histIn] = NULL;
3040 if (*cmd == NULLCHAR) return;
3041 history[histIn] = StrSave(cmd);
3042 histIn = (histIn + 1) % HISTORY_SIZE;
3043 if (history[histIn] != NULL) {
3044 free(history[histIn]);
3045 history[histIn] = NULL;
3051 PrevInHistory(char *cmd)
3054 if (histP == histIn) {
3055 if (history[histIn] != NULL) free(history[histIn]);
3056 history[histIn] = StrSave(cmd);
3058 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3059 if (newhp == histIn || history[newhp] == NULL) return NULL;
3061 return history[histP];
3067 if (histP == histIn) return NULL;
3068 histP = (histP + 1) % HISTORY_SIZE;
3069 return history[histP];
3071 // end of borrowed code
3073 #define Abs(n) ((n)<0 ? -(n) : (n))
3076 * Find a font that matches "pattern" that is as close as
3077 * possible to the targetPxlSize. Prefer fonts that are k
3078 * pixels smaller to fonts that are k pixels larger. The
3079 * pattern must be in the X Consortium standard format,
3080 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3081 * The return value should be freed with XtFree when no
3085 FindFont(pattern, targetPxlSize)
3089 char **fonts, *p, *best, *scalable, *scalableTail;
3090 int i, j, nfonts, minerr, err, pxlSize;
3093 char **missing_list;
3095 char *def_string, *base_fnt_lst, strInt[3];
3097 XFontStruct **fnt_list;
3098 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3099 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3100 p = strstr(pattern, "--");
3101 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3102 strcat(base_fnt_lst, strInt);
3103 strcat(base_fnt_lst, strchr(p + 2, '-'));
3105 if ((fntSet = XCreateFontSet(xDisplay,
3109 &def_string)) == NULL) {
3111 fprintf(stderr, _("Unable to create font set.\n"));
3115 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3117 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3119 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3120 programName, pattern);
3128 for (i=0; i<nfonts; i++) {
3131 if (*p != '-') continue;
3133 if (*p == NULLCHAR) break;
3134 if (*p++ == '-') j++;
3136 if (j < 7) continue;
3139 scalable = fonts[i];
3142 err = pxlSize - targetPxlSize;
3143 if (Abs(err) < Abs(minerr) ||
3144 (minerr > 0 && err < 0 && -err == minerr)) {
3150 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3151 /* If the error is too big and there is a scalable font,
3152 use the scalable font. */
3153 int headlen = scalableTail - scalable;
3154 p = (char *) XtMalloc(strlen(scalable) + 10);
3155 while (isdigit(*scalableTail)) scalableTail++;
3156 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3158 p = (char *) XtMalloc(strlen(best) + 2);
3159 safeStrCpy(p, best, strlen(best)+1 );
3161 if (appData.debugMode) {
3162 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3163 pattern, targetPxlSize, p);
3166 if (missing_count > 0)
3167 XFreeStringList(missing_list);
3168 XFreeFontSet(xDisplay, fntSet);
3170 XFreeFontNames(fonts);
3176 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3177 // must be called before all non-first callse to CreateGCs()
3178 XtReleaseGC(shellWidget, highlineGC);
3179 XtReleaseGC(shellWidget, lightSquareGC);
3180 XtReleaseGC(shellWidget, darkSquareGC);
3181 XtReleaseGC(shellWidget, lineGC);
3182 if (appData.monoMode) {
3183 if (DefaultDepth(xDisplay, xScreen) == 1) {
3184 XtReleaseGC(shellWidget, wbPieceGC);
3186 XtReleaseGC(shellWidget, bwPieceGC);
3189 XtReleaseGC(shellWidget, prelineGC);
3190 XtReleaseGC(shellWidget, jailSquareGC);
3191 XtReleaseGC(shellWidget, wdPieceGC);
3192 XtReleaseGC(shellWidget, wlPieceGC);
3193 XtReleaseGC(shellWidget, wjPieceGC);
3194 XtReleaseGC(shellWidget, bdPieceGC);
3195 XtReleaseGC(shellWidget, blPieceGC);
3196 XtReleaseGC(shellWidget, bjPieceGC);
3200 void CreateGCs(int redo)
3202 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3203 | GCBackground | GCFunction | GCPlaneMask;
3204 XGCValues gc_values;
3207 gc_values.plane_mask = AllPlanes;
3208 gc_values.line_width = lineGap;
3209 gc_values.line_style = LineSolid;
3210 gc_values.function = GXcopy;
3213 DeleteGCs(); // called a second time; clean up old GCs first
3214 } else { // [HGM] grid and font GCs created on first call only
3215 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3216 gc_values.background = XWhitePixel(xDisplay, xScreen);
3217 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3218 XSetFont(xDisplay, coordGC, coordFontID);
3220 // [HGM] make font for holdings counts (white on black)
3221 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3222 gc_values.background = XBlackPixel(xDisplay, xScreen);
3223 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3224 XSetFont(xDisplay, countGC, countFontID);
3226 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3227 gc_values.background = XBlackPixel(xDisplay, xScreen);
3228 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3230 if (appData.monoMode) {
3231 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3232 gc_values.background = XWhitePixel(xDisplay, xScreen);
3233 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3235 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3236 gc_values.background = XBlackPixel(xDisplay, xScreen);
3237 lightSquareGC = wbPieceGC
3238 = XtGetGC(shellWidget, value_mask, &gc_values);
3240 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3241 gc_values.background = XWhitePixel(xDisplay, xScreen);
3242 darkSquareGC = bwPieceGC
3243 = XtGetGC(shellWidget, value_mask, &gc_values);
3245 if (DefaultDepth(xDisplay, xScreen) == 1) {
3246 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3247 gc_values.function = GXcopyInverted;
3248 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3249 gc_values.function = GXcopy;
3250 if (XBlackPixel(xDisplay, xScreen) == 1) {
3251 bwPieceGC = darkSquareGC;
3252 wbPieceGC = copyInvertedGC;
3254 bwPieceGC = copyInvertedGC;
3255 wbPieceGC = lightSquareGC;
3259 gc_values.foreground = highlightSquareColor;
3260 gc_values.background = highlightSquareColor;
3261 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3263 gc_values.foreground = premoveHighlightColor;
3264 gc_values.background = premoveHighlightColor;
3265 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3267 gc_values.foreground = lightSquareColor;
3268 gc_values.background = darkSquareColor;
3269 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3271 gc_values.foreground = darkSquareColor;
3272 gc_values.background = lightSquareColor;
3273 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3275 gc_values.foreground = jailSquareColor;
3276 gc_values.background = jailSquareColor;
3277 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3279 gc_values.foreground = whitePieceColor;
3280 gc_values.background = darkSquareColor;
3281 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3283 gc_values.foreground = whitePieceColor;
3284 gc_values.background = lightSquareColor;
3285 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3287 gc_values.foreground = whitePieceColor;
3288 gc_values.background = jailSquareColor;
3289 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3291 gc_values.foreground = blackPieceColor;
3292 gc_values.background = darkSquareColor;
3293 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3295 gc_values.foreground = blackPieceColor;
3296 gc_values.background = lightSquareColor;
3297 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3299 gc_values.foreground = blackPieceColor;
3300 gc_values.background = jailSquareColor;
3301 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3305 void loadXIM(xim, xmask, filename, dest, mask)
3318 fp = fopen(filename, "rb");
3320 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3327 for (y=0; y<h; ++y) {
3328 for (x=0; x<h; ++x) {
3333 XPutPixel(xim, x, y, blackPieceColor);
3335 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3338 XPutPixel(xim, x, y, darkSquareColor);
3340 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3343 XPutPixel(xim, x, y, whitePieceColor);
3345 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3348 XPutPixel(xim, x, y, lightSquareColor);
3350 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3358 /* create Pixmap of piece */
3359 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3361 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3364 /* create Pixmap of clipmask
3365 Note: We assume the white/black pieces have the same
3366 outline, so we make only 6 masks. This is okay
3367 since the XPM clipmask routines do the same. */
3369 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3371 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3374 /* now create the 1-bit version */
3375 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3378 values.foreground = 1;
3379 values.background = 0;
3381 /* Don't use XtGetGC, not read only */
3382 maskGC = XCreateGC(xDisplay, *mask,
3383 GCForeground | GCBackground, &values);
3384 XCopyPlane(xDisplay, temp, *mask, maskGC,
3385 0, 0, squareSize, squareSize, 0, 0, 1);
3386 XFreePixmap(xDisplay, temp);
3391 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3393 void CreateXIMPieces()
3398 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3403 /* The XSynchronize calls were copied from CreatePieces.
3404 Not sure if needed, but can't hurt */
3405 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3408 /* temp needed by loadXIM() */
3409 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3410 0, 0, ss, ss, AllPlanes, XYPixmap);
3412 if (strlen(appData.pixmapDirectory) == 0) {
3416 if (appData.monoMode) {
3417 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3421 fprintf(stderr, _("\nLoading XIMs...\n"));
3423 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3424 fprintf(stderr, "%d", piece+1);
3425 for (kind=0; kind<4; kind++) {
3426 fprintf(stderr, ".");
3427 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3428 ExpandPathName(appData.pixmapDirectory),
3429 piece <= (int) WhiteKing ? "" : "w",
3430 pieceBitmapNames[piece],
3432 ximPieceBitmap[kind][piece] =
3433 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3434 0, 0, ss, ss, AllPlanes, XYPixmap);
3435 if (appData.debugMode)
3436 fprintf(stderr, _("(File:%s:) "), buf);
3437 loadXIM(ximPieceBitmap[kind][piece],
3439 &(xpmPieceBitmap2[kind][piece]),
3440 &(ximMaskPm2[piece]));
3441 if(piece <= (int)WhiteKing)
3442 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3444 fprintf(stderr," ");
3446 /* Load light and dark squares */
3447 /* If the LSQ and DSQ pieces don't exist, we will
3448 draw them with solid squares. */
3449 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3450 if (access(buf, 0) != 0) {
3454 fprintf(stderr, _("light square "));
3456 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3457 0, 0, ss, ss, AllPlanes, XYPixmap);
3458 if (appData.debugMode)
3459 fprintf(stderr, _("(File:%s:) "), buf);
3461 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3462 fprintf(stderr, _("dark square "));
3463 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3464 ExpandPathName(appData.pixmapDirectory), ss);
3465 if (appData.debugMode)
3466 fprintf(stderr, _("(File:%s:) "), buf);
3468 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3469 0, 0, ss, ss, AllPlanes, XYPixmap);
3470 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3471 xpmJailSquare = xpmLightSquare;
3473 fprintf(stderr, _("Done.\n"));
3475 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3478 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3481 void CreateXPMBoard(char *s, int kind)
3485 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3486 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3487 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3491 void FreeXPMPieces()
3492 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3493 // thisroutine has to be called t free the old piece pixmaps
3495 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3496 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3498 XFreePixmap(xDisplay, xpmLightSquare);
3499 XFreePixmap(xDisplay, xpmDarkSquare);
3503 void CreateXPMPieces()
3507 u_int ss = squareSize;
3509 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3510 XpmColorSymbol symbols[4];
3511 static int redo = False;
3513 if(redo) FreeXPMPieces(); else redo = 1;
3515 /* The XSynchronize calls were copied from CreatePieces.
3516 Not sure if needed, but can't hurt */
3517 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3519 /* Setup translations so piece colors match square colors */
3520 symbols[0].name = "light_piece";
3521 symbols[0].value = appData.whitePieceColor;
3522 symbols[1].name = "dark_piece";
3523 symbols[1].value = appData.blackPieceColor;
3524 symbols[2].name = "light_square";
3525 symbols[2].value = appData.lightSquareColor;
3526 symbols[3].name = "dark_square";
3527 symbols[3].value = appData.darkSquareColor;
3529 attr.valuemask = XpmColorSymbols;
3530 attr.colorsymbols = symbols;
3531 attr.numsymbols = 4;
3533 if (appData.monoMode) {
3534 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3538 if (strlen(appData.pixmapDirectory) == 0) {
3539 XpmPieces* pieces = builtInXpms;
3542 while (pieces->size != squareSize && pieces->size) pieces++;
3543 if (!pieces->size) {
3544 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3547 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3548 for (kind=0; kind<4; kind++) {
3550 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3551 pieces->xpm[piece][kind],
3552 &(xpmPieceBitmap2[kind][piece]),
3553 NULL, &attr)) != 0) {
3554 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3558 if(piece <= (int) WhiteKing)
3559 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3563 xpmJailSquare = xpmLightSquare;
3567 fprintf(stderr, _("\nLoading XPMs...\n"));
3570 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3571 fprintf(stderr, "%d ", piece+1);
3572 for (kind=0; kind<4; kind++) {
3573 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3574 ExpandPathName(appData.pixmapDirectory),
3575 piece > (int) WhiteKing ? "w" : "",
3576 pieceBitmapNames[piece],
3578 if (appData.debugMode) {
3579 fprintf(stderr, _("(File:%s:) "), buf);
3581 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3582 &(xpmPieceBitmap2[kind][piece]),
3583 NULL, &attr)) != 0) {
3584 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3585 // [HGM] missing: read of unorthodox piece failed; substitute King.
3586 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3587 ExpandPathName(appData.pixmapDirectory),
3589 if (appData.debugMode) {
3590 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3592 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3593 &(xpmPieceBitmap2[kind][piece]),
3597 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3602 if(piece <= (int) WhiteKing)
3603 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3606 /* Load light and dark squares */
3607 /* If the LSQ and DSQ pieces don't exist, we will
3608 draw them with solid squares. */
3609 fprintf(stderr, _("light square "));
3610 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3611 if (access(buf, 0) != 0) {
3615 if (appData.debugMode)
3616 fprintf(stderr, _("(File:%s:) "), buf);
3618 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3619 &xpmLightSquare, NULL, &attr)) != 0) {
3620 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3623 fprintf(stderr, _("dark square "));
3624 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",