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
149 #include <X11/Intrinsic.h>
150 #include <X11/StringDefs.h>
151 #include <X11/Shell.h>
152 #include <X11/cursorfont.h>
153 #include <X11/Xatom.h>
154 #include <X11/Xmu/Atoms.h>
156 #include <X11/Xaw3d/Dialog.h>
157 #include <X11/Xaw3d/Form.h>
158 #include <X11/Xaw3d/List.h>
159 #include <X11/Xaw3d/Label.h>
160 #include <X11/Xaw3d/SimpleMenu.h>
161 #include <X11/Xaw3d/SmeBSB.h>
162 #include <X11/Xaw3d/SmeLine.h>
163 #include <X11/Xaw3d/Box.h>
164 #include <X11/Xaw3d/MenuButton.h>
165 #include <X11/Xaw3d/Text.h>
166 #include <X11/Xaw3d/AsciiText.h>
168 #include <X11/Xaw/Dialog.h>
169 #include <X11/Xaw/Form.h>
170 #include <X11/Xaw/List.h>
171 #include <X11/Xaw/Label.h>
172 #include <X11/Xaw/SimpleMenu.h>
173 #include <X11/Xaw/SmeBSB.h>
174 #include <X11/Xaw/SmeLine.h>
175 #include <X11/Xaw/Box.h>
176 #include <X11/Xaw/MenuButton.h>
177 #include <X11/Xaw/Text.h>
178 #include <X11/Xaw/AsciiText.h>
181 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
186 #include "pixmaps/pixmaps.h"
187 #define IMAGE_EXT "xpm"
189 #define IMAGE_EXT "xim"
190 #include "bitmaps/bitmaps.h"
193 #include "bitmaps/icon_white.bm"
194 #include "bitmaps/icon_black.bm"
195 #include "bitmaps/checkmark.bm"
197 #include "frontend.h"
199 #include "backendz.h"
203 #include "xgamelist.h"
204 #include "xhistory.h"
205 #include "xedittags.h"
208 // must be moved to xengineoutput.h
210 void EngineOutputProc P((Widget w, XEvent *event,
211 String *prms, Cardinal *nprms));
212 void EvalGraphProc P((Widget w, XEvent *event,
213 String *prms, Cardinal *nprms));
220 #define usleep(t) _sleep2(((t)+500)/1000)
224 # define _(s) gettext (s)
225 # define N_(s) gettext_noop (s)
243 int main P((int argc, char **argv));
244 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
245 char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 RETSIGTYPE TermSizeSigHandler P((int sig));
249 void CreateGCs P((int redo));
250 void CreateAnyPieces P((void));
251 void CreateXIMPieces P((void));
252 void CreateXPMPieces P((void));
253 void CreateXPMBoard P((char *s, int n));
254 void CreatePieces P((void));
255 void CreatePieceMenus P((void));
256 Widget CreateMenuBar P((Menu *mb));
257 Widget CreateButtonBar P ((MenuItem *mi));
259 char *InsertPxlSize P((char *pattern, int targetPxlSize));
260 XFontSet CreateFontSet P((char *base_fnt_lst));
262 char *FindFont P((char *pattern, int targetPxlSize));
264 void PieceMenuPopup P((Widget w, XEvent *event,
265 String *params, Cardinal *num_params));
266 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
267 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
268 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
269 u_int wreq, u_int hreq));
270 void CreateGrid P((void));
271 int EventToSquare P((int x, int limit));
272 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
273 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
274 void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
275 void HandleUserMove P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void AnimateUserMove P((Widget w, XEvent * event,
278 String * params, Cardinal * nParams));
279 void HandlePV P((Widget w, XEvent * event,
280 String * params, Cardinal * nParams));
281 void SelectPV P((Widget w, XEvent * event,
282 String * params, Cardinal * nParams));
283 void StopPV P((Widget w, XEvent * event,
284 String * params, Cardinal * nParams));
285 void WhiteClock P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void BlackClock P((Widget w, XEvent *event,
288 String *prms, Cardinal *nprms));
289 void DrawPositionProc P((Widget w, XEvent *event,
290 String *prms, Cardinal *nprms));
291 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
293 void CommentClick P((Widget w, XEvent * event,
294 String * params, Cardinal * nParams));
295 void CommentPopUp P((char *title, char *label));
296 void CommentPopDown P((void));
297 void ICSInputBoxPopUp P((void));
298 void ICSInputBoxPopDown P((void));
299 void FileNamePopUp P((char *label, char *def, char *filter,
300 FileProc proc, char *openMode));
301 void FileNamePopDown P((void));
302 void FileNameCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void FileNameAction P((Widget w, XEvent *event,
305 String *prms, Cardinal *nprms));
306 void AskQuestionReplyAction P((Widget w, XEvent *event,
307 String *prms, Cardinal *nprms));
308 void AskQuestionProc P((Widget w, XEvent *event,
309 String *prms, Cardinal *nprms));
310 void AskQuestionPopDown P((void));
311 void PromotionPopDown P((void));
312 void PromotionCallback P((Widget w, XtPointer client_data,
313 XtPointer call_data));
314 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
315 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
319 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
321 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
323 void LoadPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
327 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
329 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
331 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
333 void PastePositionProc P((Widget w, XEvent *event, String *prms,
335 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void SavePositionProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
344 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
348 void MachineWhiteProc P((Widget w, XEvent *event,
349 String *prms, Cardinal *nprms));
350 void AnalyzeModeProc P((Widget w, XEvent *event,
351 String *prms, Cardinal *nprms));
352 void AnalyzeFileProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
356 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void IcsClientProc P((Widget w, XEvent *event, String *prms,
360 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void EditPositionProc P((Widget w, XEvent *event,
362 String *prms, Cardinal *nprms));
363 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void EditCommentProc P((Widget w, XEvent *event,
365 String *prms, Cardinal *nprms));
366 void IcsInputBoxProc P((Widget w, XEvent *event,
367 String *prms, Cardinal *nprms));
368 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void StopObservingProc P((Widget w, XEvent *event, String *prms,
385 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
387 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
396 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
398 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
401 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
403 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
405 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
410 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
413 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
415 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
417 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
422 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
424 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
426 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
428 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
431 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
433 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
435 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
437 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void DisplayMove P((int moveNumber));
449 void DisplayTitle P((char *title));
450 void ICSInitScript P((void));
451 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
452 void ErrorPopUp P((char *title, char *text, int modal));
453 void ErrorPopDown P((void));
454 static char *ExpandPathName P((char *path));
455 static void CreateAnimVars P((void));
456 static void DragPieceMove P((int x, int y));
457 static void DrawDragPiece P((void));
458 char *ModeToWidgetName P((GameMode mode));
459 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
467 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
468 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
469 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
470 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
471 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
472 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
473 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
474 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
475 void EditBookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
476 void GameListOptionsPopDown P(());
477 void TimeControlPopDown P(());
478 void GenericPopDown P(());
479 void update_ics_width P(());
480 int get_term_width P(());
481 int CopyMemoProc P(());
482 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
483 Boolean IsDrawArrowEnabled P(());
486 * XBoard depends on Xt R4 or higher
488 int xtVersion = XtSpecificationRelease;
493 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
494 jailSquareColor, highlightSquareColor, premoveHighlightColor;
495 Pixel lowTimeWarningColor;
496 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
497 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
498 wjPieceGC, bjPieceGC, prelineGC, countGC;
499 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
500 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
501 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
502 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
503 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
504 ICSInputShell, fileNameShell, askQuestionShell;
505 Widget historyShell, evalGraphShell, gameListShell;
506 int hOffset; // [HGM] dual
507 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
508 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
509 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
511 XFontSet fontSet, clockFontSet;
514 XFontStruct *clockFontStruct;
516 Font coordFontID, countFontID;
517 XFontStruct *coordFontStruct, *countFontStruct;
518 XtAppContext appContext;
520 char *oldICSInteractionTitle;
524 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
526 Position commentX = -1, commentY = -1;
527 Dimension commentW, commentH;
528 typedef unsigned int BoardSize;
530 Boolean chessProgram;
532 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
533 int squareSize, smallLayout = 0, tinyLayout = 0,
534 marginW, marginH, // [HGM] for run-time resizing
535 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
536 ICSInputBoxUp = False, askQuestionUp = False,
537 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
538 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
539 Pixel timerForegroundPixel, timerBackgroundPixel;
540 Pixel buttonForegroundPixel, buttonBackgroundPixel;
541 char *chessDir, *programName, *programVersion,
542 *gameCopyFilename, *gamePasteFilename;
543 Boolean alwaysOnTop = False;
544 Boolean saveSettingsOnExit;
545 char *settingsFileName;
546 char *icsTextMenuString;
548 char *firstChessProgramNames;
549 char *secondChessProgramNames;
551 WindowPlacement wpMain;
552 WindowPlacement wpConsole;
553 WindowPlacement wpComment;
554 WindowPlacement wpMoveHistory;
555 WindowPlacement wpEvalGraph;
556 WindowPlacement wpEngineOutput;
557 WindowPlacement wpGameList;
558 WindowPlacement wpTags;
560 extern Widget shells[];
561 extern Boolean shellUp[];
565 Pixmap pieceBitmap[2][(int)BlackPawn];
566 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
567 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
568 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
569 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
570 Pixmap xpmBoardBitmap[2];
571 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
572 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
573 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
574 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
575 XImage *ximLightSquare, *ximDarkSquare;
578 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
579 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
581 #define White(piece) ((int)(piece) < (int)BlackPawn)
583 /* Variables for doing smooth animation. This whole thing
584 would be much easier if the board was double-buffered,
585 but that would require a fairly major rewrite. */
590 GC blitGC, pieceGC, outlineGC;
591 XPoint startSquare, prevFrame, mouseDelta;
595 int startBoardX, startBoardY;
598 /* There can be two pieces being animated at once: a player
599 can begin dragging a piece before the remote opponent has moved. */
601 static AnimState game, player;
603 /* Bitmaps for use as masks when drawing XPM pieces.
604 Need one for each black and white piece. */
605 static Pixmap xpmMask[BlackKing + 1];
607 /* This magic number is the number of intermediate frames used
608 in each half of the animation. For short moves it's reduced
609 by 1. The total number of frames will be factor * 2 + 1. */
612 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
614 MenuItem fileMenu[] = {
615 {N_("New Game Ctrl+N"), "New Game", ResetProc},
616 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
617 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
618 {"----", NULL, NothingProc},
619 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
620 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
621 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
622 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
623 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
624 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
625 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
626 {"----", NULL, NothingProc},
627 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
628 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
629 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
630 {"----", NULL, NothingProc},
631 {N_("Mail Move"), "Mail Move", MailMoveProc},
632 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
633 {"----", NULL, NothingProc},
634 {N_("Quit Ctr+Q"), "Exit", QuitProc},
638 MenuItem editMenu[] = {
639 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
640 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
641 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
642 {"----", NULL, NothingProc},
643 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
644 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
645 {"----", NULL, NothingProc},
646 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
647 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
648 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
649 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
650 {N_("Edit Book"), "Edit Book", EditBookProc},
651 {"----", NULL, NothingProc},
652 {N_("Revert Home"), "Revert", RevertProc},
653 {N_("Annotate"), "Annotate", AnnotateProc},
654 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
655 {"----", NULL, NothingProc},
656 {N_("Backward Alt+Left"), "Backward", BackwardProc},
657 {N_("Forward Alt+Right"), "Forward", ForwardProc},
658 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
659 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
663 MenuItem viewMenu[] = {
664 {N_("Flip View F2"), "Flip View", FlipViewProc},
665 {"----", NULL, NothingProc},
666 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
667 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
668 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
669 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
670 {N_("ICS text menu"), "ICStex", IcsTextProc},
671 {"----", NULL, NothingProc},
672 {N_("Tags"), "Show Tags", EditTagsProc},
673 {N_("Comments"), "Show Comments", EditCommentProc},
674 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
675 {"----", NULL, NothingProc},
676 {N_("Board..."), "Board Options", BoardOptionsProc},
677 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
681 MenuItem modeMenu[] = {
682 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
683 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
684 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
685 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
686 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
687 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
688 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
689 {N_("Training"), "Training", TrainingProc},
690 {N_("ICS Client"), "ICS Client", IcsClientProc},
691 {"----", NULL, NothingProc},
692 {N_("Machine Match"), "Machine Match", MatchProc},
693 {N_("Pause Pause"), "Pause", PauseProc},
697 MenuItem actionMenu[] = {
698 {N_("Accept F3"), "Accept", AcceptProc},
699 {N_("Decline F4"), "Decline", DeclineProc},
700 {N_("Rematch F12"), "Rematch", RematchProc},
701 {"----", NULL, NothingProc},
702 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
703 {N_("Draw F6"), "Draw", DrawProc},
704 {N_("Adjourn F7"), "Adjourn", AdjournProc},
705 {N_("Abort F8"),"Abort", AbortProc},
706 {N_("Resign F9"), "Resign", ResignProc},
707 {"----", NULL, NothingProc},
708 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
709 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
710 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
711 {"----", NULL, NothingProc},
712 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
713 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
714 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
718 MenuItem engineMenu[] = {
719 {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
720 {"----", NULL, NothingProc},
721 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
722 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
723 {"----", NULL, NothingProc},
724 {N_("Hint"), "Hint", HintProc},
725 {N_("Book"), "Book", BookProc},
726 {"----", NULL, NothingProc},
727 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
728 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
732 MenuItem optionsMenu[] = {
733 #define OPTIONSDIALOG
735 {N_("General ..."), "General", OptionsProc},
737 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
738 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
739 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
740 {N_("ICS ..."), "ICS", IcsOptionsProc},
741 {N_("Match ..."), "Match", MatchOptionsProc},
742 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
743 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
744 // {N_(" ..."), "", OptionsProc},
745 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
746 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
747 {"----", NULL, NothingProc},
748 #ifndef OPTIONSDIALOG
749 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
750 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
751 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
752 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
753 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
754 {N_("Blindfold"), "Blindfold", BlindfoldProc},
755 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
757 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
759 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
760 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
761 {N_("Move Sound"), "Move Sound", MoveSoundProc},
762 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
763 {N_("One-Click Moving"), "OneClick", OneClickProc},
764 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
765 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
766 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
767 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
768 // {N_("Premove"), "Premove", PremoveProc},
769 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
770 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
771 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
772 {"----", NULL, NothingProc},
774 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
775 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
779 MenuItem helpMenu[] = {
780 {N_("Info XBoard"), "Info XBoard", InfoProc},
781 {N_("Man XBoard F1"), "Man XBoard", ManProc},
782 {"----", NULL, NothingProc},
783 {N_("About XBoard"), "About XBoard", AboutProc},
788 {N_("File"), "File", fileMenu},
789 {N_("Edit"), "Edit", editMenu},
790 {N_("View"), "View", viewMenu},
791 {N_("Mode"), "Mode", modeMenu},
792 {N_("Action"), "Action", actionMenu},
793 {N_("Engine"), "Engine", engineMenu},
794 {N_("Options"), "Options", optionsMenu},
795 {N_("Help"), "Help", helpMenu},
799 #define PAUSE_BUTTON "P"
800 MenuItem buttonBar[] = {
801 {"<<", "<<", ToStartProc},
802 {"<", "<", BackwardProc},
803 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
804 {">", ">", ForwardProc},
805 {">>", ">>", ToEndProc},
809 #define PIECE_MENU_SIZE 18
810 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
811 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
812 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
813 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
814 N_("Empty square"), N_("Clear board") },
815 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
816 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
817 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
818 N_("Empty square"), N_("Clear board") }
820 /* must be in same order as pieceMenuStrings! */
821 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
822 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
823 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
824 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
825 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
826 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
827 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
828 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
829 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
832 #define DROP_MENU_SIZE 6
833 String dropMenuStrings[DROP_MENU_SIZE] = {
834 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
836 /* must be in same order as dropMenuStrings! */
837 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
838 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
839 WhiteRook, WhiteQueen
847 DropMenuEnables dmEnables[] = {
865 { XtNborderWidth, 0 },
866 { XtNdefaultDistance, 0 },
870 { XtNborderWidth, 0 },
871 { XtNresizable, (XtArgVal) True },
875 { XtNborderWidth, 0 },
881 { XtNjustify, (XtArgVal) XtJustifyRight },
882 { XtNlabel, (XtArgVal) "..." },
883 { XtNresizable, (XtArgVal) True },
884 { XtNresize, (XtArgVal) False }
887 Arg messageArgs[] = {
888 { XtNjustify, (XtArgVal) XtJustifyLeft },
889 { XtNlabel, (XtArgVal) "..." },
890 { XtNresizable, (XtArgVal) True },
891 { XtNresize, (XtArgVal) False }
895 { XtNborderWidth, 0 },
896 { XtNjustify, (XtArgVal) XtJustifyLeft }
899 XtResource clientResources[] = {
900 { "flashCount", "flashCount", XtRInt, sizeof(int),
901 XtOffset(AppDataPtr, flashCount), XtRImmediate,
902 (XtPointer) FLASH_COUNT },
905 XrmOptionDescRec shellOptions[] = {
906 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
907 { "-flash", "flashCount", XrmoptionNoArg, "3" },
908 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
911 XtActionsRec boardActions[] = {
912 { "DrawPosition", DrawPositionProc },
913 { "HandleUserMove", HandleUserMove },
914 { "AnimateUserMove", AnimateUserMove },
915 { "HandlePV", HandlePV },
916 { "SelectPV", SelectPV },
917 { "StopPV", StopPV },
918 { "FileNameAction", FileNameAction },
919 { "AskQuestionProc", AskQuestionProc },
920 { "AskQuestionReplyAction", AskQuestionReplyAction },
921 { "PieceMenuPopup", PieceMenuPopup },
922 { "WhiteClock", WhiteClock },
923 { "BlackClock", BlackClock },
924 { "Iconify", Iconify },
925 { "ResetProc", ResetProc },
926 { "NewVariantProc", NewVariantProc },
927 { "LoadGameProc", LoadGameProc },
928 { "LoadNextGameProc", LoadNextGameProc },
929 { "LoadPrevGameProc", LoadPrevGameProc },
930 { "LoadSelectedProc", LoadSelectedProc },
931 { "SetFilterProc", SetFilterProc },
932 { "ReloadGameProc", ReloadGameProc },
933 { "LoadPositionProc", LoadPositionProc },
934 { "LoadNextPositionProc", LoadNextPositionProc },
935 { "LoadPrevPositionProc", LoadPrevPositionProc },
936 { "ReloadPositionProc", ReloadPositionProc },
937 { "CopyPositionProc", CopyPositionProc },
938 { "PastePositionProc", PastePositionProc },
939 { "CopyGameProc", CopyGameProc },
940 { "CopyGameListProc", CopyGameListProc },
941 { "PasteGameProc", PasteGameProc },
942 { "SaveGameProc", SaveGameProc },
943 { "SavePositionProc", SavePositionProc },
944 { "MailMoveProc", MailMoveProc },
945 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
946 { "QuitProc", QuitProc },
947 { "MachineWhiteProc", MachineWhiteProc },
948 { "MachineBlackProc", MachineBlackProc },
949 { "AnalysisModeProc", AnalyzeModeProc },
950 { "AnalyzeFileProc", AnalyzeFileProc },
951 { "TwoMachinesProc", TwoMachinesProc },
952 { "IcsClientProc", IcsClientProc },
953 { "EditGameProc", EditGameProc },
954 { "EditPositionProc", EditPositionProc },
955 { "TrainingProc", EditPositionProc },
956 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
957 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
958 { "ShowGameListProc", ShowGameListProc },
959 { "ShowMoveListProc", HistoryShowProc},
960 { "EditTagsProc", EditCommentProc },
961 { "EditBookProc", EditBookProc },
962 { "EditCommentProc", EditCommentProc },
963 { "IcsInputBoxProc", IcsInputBoxProc },
964 { "PauseProc", PauseProc },
965 { "AcceptProc", AcceptProc },
966 { "DeclineProc", DeclineProc },
967 { "RematchProc", RematchProc },
968 { "CallFlagProc", CallFlagProc },
969 { "DrawProc", DrawProc },
970 { "AdjournProc", AdjournProc },
971 { "AbortProc", AbortProc },
972 { "ResignProc", ResignProc },
973 { "AdjuWhiteProc", AdjuWhiteProc },
974 { "AdjuBlackProc", AdjuBlackProc },
975 { "AdjuDrawProc", AdjuDrawProc },
976 { "TypeInProc", TypeInProc },
977 { "EnterKeyProc", EnterKeyProc },
978 { "UpKeyProc", UpKeyProc },
979 { "DownKeyProc", DownKeyProc },
980 { "StopObservingProc", StopObservingProc },
981 { "StopExaminingProc", StopExaminingProc },
982 { "UploadProc", UploadProc },
983 { "BackwardProc", BackwardProc },
984 { "ForwardProc", ForwardProc },
985 { "ToStartProc", ToStartProc },
986 { "ToEndProc", ToEndProc },
987 { "RevertProc", RevertProc },
988 { "AnnotateProc", AnnotateProc },
989 { "TruncateGameProc", TruncateGameProc },
990 { "MoveNowProc", MoveNowProc },
991 { "RetractMoveProc", RetractMoveProc },
992 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
993 { "UciMenuProc", (XtActionProc) UciMenuProc },
994 { "TimeControlProc", (XtActionProc) TimeControlProc },
995 { "FlipViewProc", FlipViewProc },
996 { "PonderNextMoveProc", PonderNextMoveProc },
997 #ifndef OPTIONSDIALOG
998 { "AlwaysQueenProc", AlwaysQueenProc },
999 { "AnimateDraggingProc", AnimateDraggingProc },
1000 { "AnimateMovingProc", AnimateMovingProc },
1001 { "AutoflagProc", AutoflagProc },
1002 { "AutoflipProc", AutoflipProc },
1003 { "BlindfoldProc", BlindfoldProc },
1004 { "FlashMovesProc", FlashMovesProc },
1006 { "HighlightDraggingProc", HighlightDraggingProc },
1008 { "HighlightLastMoveProc", HighlightLastMoveProc },
1009 // { "IcsAlarmProc", IcsAlarmProc },
1010 { "MoveSoundProc", MoveSoundProc },
1011 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1012 { "PopupExitMessageProc", PopupExitMessageProc },
1013 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1014 // { "PremoveProc", PremoveProc },
1015 { "ShowCoordsProc", ShowCoordsProc },
1016 { "ShowThinkingProc", ShowThinkingProc },
1017 { "HideThinkingProc", HideThinkingProc },
1018 { "TestLegalityProc", TestLegalityProc },
1020 { "SaveSettingsProc", SaveSettingsProc },
1021 { "SaveOnExitProc", SaveOnExitProc },
1022 { "InfoProc", InfoProc },
1023 { "ManProc", ManProc },
1024 { "HintProc", HintProc },
1025 { "BookProc", BookProc },
1026 { "AboutGameProc", AboutGameProc },
1027 { "AboutProc", AboutProc },
1028 { "DebugProc", DebugProc },
1029 { "NothingProc", NothingProc },
1030 { "CommentClick", (XtActionProc) CommentClick },
1031 { "CommentPopDown", (XtActionProc) CommentPopDown },
1032 { "TagsPopDown", (XtActionProc) TagsPopDown },
1033 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1034 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1035 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1036 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1037 { "GameListPopDown", (XtActionProc) GameListPopDown },
1038 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1039 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1040 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1041 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1042 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1043 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1044 { "GenericPopDown", (XtActionProc) GenericPopDown },
1045 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1048 char globalTranslations[] =
1049 ":<Key>F9: ResignProc() \n \
1050 :Ctrl<Key>n: ResetProc() \n \
1051 :Meta<Key>V: NewVariantProc() \n \
1052 :Ctrl<Key>o: LoadGameProc() \n \
1053 :Meta<Key>Next: LoadNextGameProc() \n \
1054 :Meta<Key>Prior: LoadPrevGameProc() \n \
1055 :Ctrl<Key>s: SaveGameProc() \n \
1056 :Ctrl<Key>c: CopyGameProc() \n \
1057 :Ctrl<Key>v: PasteGameProc() \n \
1058 :Ctrl<Key>O: LoadPositionProc() \n \
1059 :Shift<Key>Next: LoadNextPositionProc() \n \
1060 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1061 :Ctrl<Key>S: SavePositionProc() \n \
1062 :Ctrl<Key>C: CopyPositionProc() \n \
1063 :Ctrl<Key>V: PastePositionProc() \n \
1064 :Ctrl<Key>q: QuitProc() \n \
1065 :Ctrl<Key>w: MachineWhiteProc() \n \
1066 :Ctrl<Key>b: MachineBlackProc() \n \
1067 :Ctrl<Key>t: TwoMachinesProc() \n \
1068 :Ctrl<Key>a: AnalysisModeProc() \n \
1069 :Ctrl<Key>f: AnalyzeFileProc() \n \
1070 :Ctrl<Key>e: EditGameProc() \n \
1071 :Ctrl<Key>E: EditPositionProc() \n \
1072 :Meta<Key>O: EngineOutputProc() \n \
1073 :Meta<Key>E: EvalGraphProc() \n \
1074 :Meta<Key>G: ShowGameListProc() \n \
1075 :Meta<Key>H: ShowMoveListProc() \n \
1076 :<Key>Pause: PauseProc() \n \
1077 :<Key>F3: AcceptProc() \n \
1078 :<Key>F4: DeclineProc() \n \
1079 :<Key>F12: RematchProc() \n \
1080 :<Key>F5: CallFlagProc() \n \
1081 :<Key>F6: DrawProc() \n \
1082 :<Key>F7: AdjournProc() \n \
1083 :<Key>F8: AbortProc() \n \
1084 :<Key>F10: StopObservingProc() \n \
1085 :<Key>F11: StopExaminingProc() \n \
1086 :Meta Ctrl<Key>F12: DebugProc() \n \
1087 :Meta<Key>End: ToEndProc() \n \
1088 :Meta<Key>Right: ForwardProc() \n \
1089 :Meta<Key>Home: ToStartProc() \n \
1090 :Meta<Key>Left: BackwardProc() \n \
1091 :<Key>Home: RevertProc() \n \
1092 :<Key>End: TruncateGameProc() \n \
1093 :Ctrl<Key>m: MoveNowProc() \n \
1094 :Ctrl<Key>x: RetractMoveProc() \n \
1095 :Meta<Key>J: EngineMenuProc() \n \
1096 :Meta<Key>U: UciMenuProc() \n \
1097 :Meta<Key>T: TimeControlProc() \n \
1098 :Ctrl<Key>P: PonderNextMoveProc() \n "
1099 #ifndef OPTIONSDIALOG
1101 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1102 :Ctrl<Key>F: AutoflagProc() \n \
1103 :Ctrl<Key>A: AnimateMovingProc() \n \
1104 :Ctrl<Key>L: TestLegalityProc() \n \
1105 :Ctrl<Key>H: HideThinkingProc() \n "
1108 :<Key>-: Iconify() \n \
1109 :<Key>F1: ManProc() \n \
1110 :<Key>F2: FlipViewProc() \n \
1111 <KeyDown>.: BackwardProc() \n \
1112 <KeyUp>.: ForwardProc() \n \
1113 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1114 \"Send to chess program:\",,1) \n \
1115 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1116 \"Send to second chess program:\",,2) \n";
1118 char boardTranslations[] =
1119 "<Btn1Down>: HandleUserMove(0) \n \
1120 Shift<Btn1Up>: HandleUserMove(1) \n \
1121 <Btn1Up>: HandleUserMove(0) \n \
1122 <Btn1Motion>: AnimateUserMove() \n \
1123 <Btn3Motion>: HandlePV() \n \
1124 <Btn3Up>: PieceMenuPopup(menuB) \n \
1125 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1126 PieceMenuPopup(menuB) \n \
1127 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1128 PieceMenuPopup(menuW) \n \
1129 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1130 PieceMenuPopup(menuW) \n \
1131 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1132 PieceMenuPopup(menuB) \n";
1134 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1135 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1137 char ICSInputTranslations[] =
1138 "<Key>Up: UpKeyProc() \n "
1139 "<Key>Down: DownKeyProc() \n "
1140 "<Key>Return: EnterKeyProc() \n";
1142 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1143 // as the widget is destroyed before the up-click can call extend-end
1144 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1146 String xboardResources[] = {
1147 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1148 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1149 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1154 /* Max possible square size */
1155 #define MAXSQSIZE 256
1157 static int xpm_avail[MAXSQSIZE];
1159 #ifdef HAVE_DIR_STRUCT
1161 /* Extract piece size from filename */
1163 xpm_getsize(name, len, ext)
1174 if ((p=strchr(name, '.')) == NULL ||
1175 StrCaseCmp(p+1, ext) != 0)
1181 while (*p && isdigit(*p))
1188 /* Setup xpm_avail */
1190 xpm_getavail(dirname, ext)
1198 for (i=0; i<MAXSQSIZE; ++i)
1201 if (appData.debugMode)
1202 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1204 dir = opendir(dirname);
1207 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1208 programName, dirname);
1212 while ((ent=readdir(dir)) != NULL) {
1213 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1214 if (i > 0 && i < MAXSQSIZE)
1224 xpm_print_avail(fp, ext)
1230 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1231 for (i=1; i<MAXSQSIZE; ++i) {
1237 /* Return XPM piecesize closest to size */
1239 xpm_closest_to(dirname, size, ext)
1245 int sm_diff = MAXSQSIZE;
1249 xpm_getavail(dirname, ext);
1251 if (appData.debugMode)
1252 xpm_print_avail(stderr, ext);
1254 for (i=1; i<MAXSQSIZE; ++i) {
1257 diff = (diff<0) ? -diff : diff;
1258 if (diff < sm_diff) {
1266 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1272 #else /* !HAVE_DIR_STRUCT */
1273 /* If we are on a system without a DIR struct, we can't
1274 read the directory, so we can't collect a list of
1275 filenames, etc., so we can't do any size-fitting. */
1277 xpm_closest_to(dirname, size, ext)
1282 fprintf(stderr, _("\
1283 Warning: No DIR structure found on this system --\n\
1284 Unable to autosize for XPM/XIM pieces.\n\
1285 Please report this error to %s.\n\
1286 Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
1289 #endif /* HAVE_DIR_STRUCT */
1291 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1292 "magenta", "cyan", "white" };
1296 TextColors textColors[(int)NColorClasses];
1298 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1300 parse_color(str, which)
1304 char *p, buf[100], *d;
1307 if (strlen(str) > 99) /* watch bounds on buf */
1312 for (i=0; i<which; ++i) {
1319 /* Could be looking at something like:
1321 .. in which case we want to stop on a comma also */
1322 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1326 return -1; /* Use default for empty field */
1329 if (which == 2 || isdigit(*p))
1332 while (*p && isalpha(*p))
1337 for (i=0; i<8; ++i) {
1338 if (!StrCaseCmp(buf, cnames[i]))
1339 return which? (i+40) : (i+30);
1341 if (!StrCaseCmp(buf, "default")) return -1;
1343 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1348 parse_cpair(cc, str)
1352 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1353 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1358 /* bg and attr are optional */
1359 textColors[(int)cc].bg = parse_color(str, 1);
1360 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1361 textColors[(int)cc].attr = 0;
1367 /* Arrange to catch delete-window events */
1368 Atom wm_delete_window;
1370 CatchDeleteWindow(Widget w, String procname)
1373 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1374 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1375 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1382 XtSetArg(args[0], XtNiconic, False);
1383 XtSetValues(shellWidget, args, 1);
1385 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1388 //---------------------------------------------------------------------------------------------------------
1389 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1392 #define CW_USEDEFAULT (1<<31)
1393 #define ICS_TEXT_MENU_SIZE 90
1394 #define DEBUG_FILE "xboard.debug"
1395 #define SetCurrentDirectory chdir
1396 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1400 // these two must some day move to frontend.h, when they are implemented
1401 Boolean GameListIsUp();
1403 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1406 // front-end part of option handling
1408 // [HGM] This platform-dependent table provides the location for storing the color info
1409 extern char *crWhite, * crBlack;
1413 &appData.whitePieceColor,
1414 &appData.blackPieceColor,
1415 &appData.lightSquareColor,
1416 &appData.darkSquareColor,
1417 &appData.highlightSquareColor,
1418 &appData.premoveHighlightColor,
1419 &appData.lowTimeWarningColor,
1430 // [HGM] font: keep a font for each square size, even non-stndard ones
1431 #define NUM_SIZES 18
1432 #define MAX_SIZE 130
1433 Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1434 char *fontTable[NUM_FONTS][MAX_SIZE];
1437 ParseFont(char *name, int number)
1438 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1440 if(sscanf(name, "size%d:", &size)) {
1441 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1442 // defer processing it until we know if it matches our board size
1443 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1444 fontTable[number][size] = strdup(strchr(name, ':')+1);
1445 fontValid[number][size] = True;
1450 case 0: // CLOCK_FONT
1451 appData.clockFont = strdup(name);
1453 case 1: // MESSAGE_FONT
1454 appData.font = strdup(name);
1456 case 2: // COORD_FONT
1457 appData.coordFont = strdup(name);
1462 fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1467 { // only 2 fonts currently
1468 appData.clockFont = CLOCK_FONT_NAME;
1469 appData.coordFont = COORD_FONT_NAME;
1470 appData.font = DEFAULT_FONT_NAME;
1475 { // no-op, until we identify the code for this already in XBoard and move it here
1479 ParseColor(int n, char *name)
1480 { // in XBoard, just copy the color-name string
1481 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1485 ParseTextAttribs(ColorClass cc, char *s)
1487 (&appData.colorShout)[cc] = strdup(s);
1491 ParseBoardSize(void *addr, char *name)
1493 appData.boardSize = strdup(name);
1498 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1502 SetCommPortDefaults()
1503 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1506 // [HGM] args: these three cases taken out to stay in front-end
1508 SaveFontArg(FILE *f, ArgDescriptor *ad)
1511 int i, n = (int)(intptr_t)ad->argLoc;
1513 case 0: // CLOCK_FONT
1514 name = appData.clockFont;
1516 case 1: // MESSAGE_FONT
1517 name = appData.font;
1519 case 2: // COORD_FONT
1520 name = appData.coordFont;
1525 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1526 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1527 fontTable[n][squareSize] = strdup(name);
1528 fontValid[n][squareSize] = True;
1531 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1532 fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
1537 { // nothing to do, as the sounds are at all times represented by their text-string names already
1541 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1542 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1543 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1547 SaveColor(FILE *f, ArgDescriptor *ad)
1548 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1549 if(colorVariable[(int)(intptr_t)ad->argLoc])
1550 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1554 SaveBoardSize(FILE *f, char *name, void *addr)
1555 { // wrapper to shield back-end from BoardSize & sizeInfo
1556 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1560 ParseCommPortSettings(char *s)
1561 { // no such option in XBoard (yet)
1564 extern Widget engineOutputShell;
1567 GetActualPlacement(Widget wg, WindowPlacement *wp)
1577 XtSetArg(args[i], XtNx, &x); i++;
1578 XtSetArg(args[i], XtNy, &y); i++;
1579 XtSetArg(args[i], XtNwidth, &w); i++;
1580 XtSetArg(args[i], XtNheight, &h); i++;
1581 XtGetValues(wg, args, i);
1590 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1591 // In XBoard this will have to wait until awareness of window parameters is implemented
1592 GetActualPlacement(shellWidget, &wpMain);
1593 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1594 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1595 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1596 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1597 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1598 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1602 PrintCommPortSettings(FILE *f, char *name)
1603 { // This option does not exist in XBoard
1607 MySearchPath(char *installDir, char *name, char *fullname)
1608 { // just append installDir and name. Perhaps ExpandPath should be used here?
1609 name = ExpandPathName(name);
1610 if(name && name[0] == '/')
1611 safeStrCpy(fullname, name, MSG_SIZ );
1613 sprintf(fullname, "%s%c%s", installDir, '/', name);
1619 MyGetFullPathName(char *name, char *fullname)
1620 { // should use ExpandPath?
1621 name = ExpandPathName(name);
1622 safeStrCpy(fullname, name, MSG_SIZ );
1627 EnsureOnScreen(int *x, int *y, int minX, int minY)
1634 { // [HGM] args: allows testing if main window is realized from back-end
1635 return xBoardWindow != 0;
1639 PopUpStartupDialog()
1640 { // start menu not implemented in XBoard
1644 ConvertToLine(int argc, char **argv)
1646 static char line[128*1024], buf[1024];
1650 for(i=1; i<argc; i++)
1652 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1653 && argv[i][0] != '{' )
1654 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1656 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1657 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1660 line[strlen(line)-1] = NULLCHAR;
1664 //--------------------------------------------------------------------------------------------
1666 extern Boolean twoBoards, partnerUp;
1669 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1671 #define BoardSize int
1672 void InitDrawingSizes(BoardSize boardSize, int flags)
1673 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1674 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1676 XtGeometryResult gres;
1679 if(!formWidget) return;
1682 * Enable shell resizing.
1684 shellArgs[0].value = (XtArgVal) &w;
1685 shellArgs[1].value = (XtArgVal) &h;
1686 XtGetValues(shellWidget, shellArgs, 2);
1688 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1689 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1690 XtSetValues(shellWidget, &shellArgs[2], 4);
1692 XtSetArg(args[0], XtNdefaultDistance, &sep);
1693 XtGetValues(formWidget, args, 1);
1695 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1696 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1697 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1699 hOffset = boardWidth + 10;
1700 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1701 secondSegments[i] = gridSegments[i];
1702 secondSegments[i].x1 += hOffset;
1703 secondSegments[i].x2 += hOffset;
1706 XtSetArg(args[0], XtNwidth, boardWidth);
1707 XtSetArg(args[1], XtNheight, boardHeight);
1708 XtSetValues(boardWidget, args, 2);
1710 timerWidth = (boardWidth - sep) / 2;
1711 XtSetArg(args[0], XtNwidth, timerWidth);
1712 XtSetValues(whiteTimerWidget, args, 1);
1713 XtSetValues(blackTimerWidget, args, 1);
1715 XawFormDoLayout(formWidget, False);
1717 if (appData.titleInWindow) {
1719 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1720 XtSetArg(args[i], XtNheight, &h); i++;
1721 XtGetValues(titleWidget, args, i);
1723 w = boardWidth - 2*bor;
1725 XtSetArg(args[0], XtNwidth, &w);
1726 XtGetValues(menuBarWidget, args, 1);
1727 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1730 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1731 if (gres != XtGeometryYes && appData.debugMode) {
1733 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1734 programName, gres, w, h, wr, hr);
1738 XawFormDoLayout(formWidget, True);
1741 * Inhibit shell resizing.
1743 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1744 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1745 shellArgs[4].value = shellArgs[2].value = w;
1746 shellArgs[5].value = shellArgs[3].value = h;
1747 XtSetValues(shellWidget, &shellArgs[0], 6);
1749 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1752 for(i=0; i<4; i++) {
1754 for(p=0; p<=(int)WhiteKing; p++)
1755 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1756 if(gameInfo.variant == VariantShogi) {
1757 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1758 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1759 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1760 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1761 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1764 if(gameInfo.variant == VariantGothic) {
1765 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1768 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1769 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1770 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1773 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1774 for(p=0; p<=(int)WhiteKing; p++)
1775 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1776 if(gameInfo.variant == VariantShogi) {
1777 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1778 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1779 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1780 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1781 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1784 if(gameInfo.variant == VariantGothic) {
1785 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1788 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1789 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1790 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1795 for(i=0; i<2; i++) {
1797 for(p=0; p<=(int)WhiteKing; p++)
1798 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1799 if(gameInfo.variant == VariantShogi) {
1800 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1801 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1802 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1803 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1804 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1807 if(gameInfo.variant == VariantGothic) {
1808 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1811 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1812 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1813 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1823 void ParseIcsTextColors()
1824 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1825 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1826 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1827 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1828 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1829 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1830 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1831 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1832 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1833 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1834 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1836 if (appData.colorize) {
1838 _("%s: can't parse color names; disabling colorization\n"),
1841 appData.colorize = FALSE;
1846 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1847 XrmValue vFrom, vTo;
1848 int forceMono = False;
1850 if (!appData.monoMode) {
1851 vFrom.addr = (caddr_t) appData.lightSquareColor;
1852 vFrom.size = strlen(appData.lightSquareColor);
1853 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1854 if (vTo.addr == NULL) {
1855 appData.monoMode = True;
1858 lightSquareColor = *(Pixel *) vTo.addr;
1861 if (!appData.monoMode) {
1862 vFrom.addr = (caddr_t) appData.darkSquareColor;
1863 vFrom.size = strlen(appData.darkSquareColor);
1864 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1865 if (vTo.addr == NULL) {
1866 appData.monoMode = True;
1869 darkSquareColor = *(Pixel *) vTo.addr;
1872 if (!appData.monoMode) {
1873 vFrom.addr = (caddr_t) appData.whitePieceColor;
1874 vFrom.size = strlen(appData.whitePieceColor);
1875 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1876 if (vTo.addr == NULL) {
1877 appData.monoMode = True;
1880 whitePieceColor = *(Pixel *) vTo.addr;
1883 if (!appData.monoMode) {
1884 vFrom.addr = (caddr_t) appData.blackPieceColor;
1885 vFrom.size = strlen(appData.blackPieceColor);
1886 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1887 if (vTo.addr == NULL) {
1888 appData.monoMode = True;
1891 blackPieceColor = *(Pixel *) vTo.addr;
1895 if (!appData.monoMode) {
1896 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1897 vFrom.size = strlen(appData.highlightSquareColor);
1898 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1899 if (vTo.addr == NULL) {
1900 appData.monoMode = True;
1903 highlightSquareColor = *(Pixel *) vTo.addr;
1907 if (!appData.monoMode) {
1908 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1909 vFrom.size = strlen(appData.premoveHighlightColor);
1910 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1911 if (vTo.addr == NULL) {
1912 appData.monoMode = True;
1915 premoveHighlightColor = *(Pixel *) vTo.addr;
1923 { // [HGM] taken out of main
1925 if (appData.monoMode && // [HGM] no sense to go on to certain doom
1926 (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
1927 appData.bitmapDirectory = DEF_BITMAP_DIR;
1929 if (appData.bitmapDirectory[0] != NULLCHAR) {
1933 CreateXPMBoard(appData.liteBackTextureFile, 1);
1934 CreateXPMBoard(appData.darkBackTextureFile, 0);
1938 /* Create regular pieces */
1939 if (!useImages) CreatePieces();
1948 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1949 XSetWindowAttributes window_attributes;
1951 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1952 XrmValue vFrom, vTo;
1953 XtGeometryResult gres;
1956 int forceMono = False;
1958 srandom(time(0)); // [HGM] book: make random truly random
1960 setbuf(stdout, NULL);
1961 setbuf(stderr, NULL);
1964 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1965 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1969 programName = strrchr(argv[0], '/');
1970 if (programName == NULL)
1971 programName = argv[0];
1976 XtSetLanguageProc(NULL, NULL, NULL);
1977 bindtextdomain(PACKAGE, LOCALEDIR);
1978 textdomain(PACKAGE);
1982 XtAppInitialize(&appContext, "XBoard", shellOptions,
1983 XtNumber(shellOptions),
1984 &argc, argv, xboardResources, NULL, 0);
1985 appData.boardSize = "";
1986 InitAppData(ConvertToLine(argc, argv));
1988 if (p == NULL) p = "/tmp";
1989 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1990 gameCopyFilename = (char*) malloc(i);
1991 gamePasteFilename = (char*) malloc(i);
1992 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1993 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1995 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1996 clientResources, XtNumber(clientResources),
1999 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2000 static char buf[MSG_SIZ];
2001 EscapeExpand(buf, appData.firstInitString);
2002 appData.firstInitString = strdup(buf);
2003 EscapeExpand(buf, appData.secondInitString);
2004 appData.secondInitString = strdup(buf);
2005 EscapeExpand(buf, appData.firstComputerString);
2006 appData.firstComputerString = strdup(buf);
2007 EscapeExpand(buf, appData.secondComputerString);
2008 appData.secondComputerString = strdup(buf);
2011 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2014 if (chdir(chessDir) != 0) {
2015 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2021 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2022 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2023 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2024 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2027 setbuf(debugFP, NULL);
2031 if (appData.debugMode) {
2032 fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
2036 /* [HGM,HR] make sure board size is acceptable */
2037 if(appData.NrFiles > BOARD_FILES ||
2038 appData.NrRanks > BOARD_RANKS )
2039 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2042 /* This feature does not work; animation needs a rewrite */
2043 appData.highlightDragging = FALSE;
2047 xDisplay = XtDisplay(shellWidget);
2048 xScreen = DefaultScreen(xDisplay);
2049 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2051 gameInfo.variant = StringToVariant(appData.variant);
2052 InitPosition(FALSE);
2055 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2057 if (isdigit(appData.boardSize[0])) {
2058 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2059 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2060 &fontPxlSize, &smallLayout, &tinyLayout);
2062 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2063 programName, appData.boardSize);
2067 /* Find some defaults; use the nearest known size */
2068 SizeDefaults *szd, *nearest;
2069 int distance = 99999;
2070 nearest = szd = sizeDefaults;
2071 while (szd->name != NULL) {
2072 if (abs(szd->squareSize - squareSize) < distance) {
2074 distance = abs(szd->squareSize - squareSize);
2075 if (distance == 0) break;
2079 if (i < 2) lineGap = nearest->lineGap;
2080 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2081 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2082 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2083 if (i < 6) smallLayout = nearest->smallLayout;
2084 if (i < 7) tinyLayout = nearest->tinyLayout;
2087 SizeDefaults *szd = sizeDefaults;
2088 if (*appData.boardSize == NULLCHAR) {
2089 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2090 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2093 if (szd->name == NULL) szd--;
2094 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2096 while (szd->name != NULL &&
2097 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2098 if (szd->name == NULL) {
2099 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2100 programName, appData.boardSize);
2104 squareSize = szd->squareSize;
2105 lineGap = szd->lineGap;
2106 clockFontPxlSize = szd->clockFontPxlSize;
2107 coordFontPxlSize = szd->coordFontPxlSize;
2108 fontPxlSize = szd->fontPxlSize;
2109 smallLayout = szd->smallLayout;
2110 tinyLayout = szd->tinyLayout;
2111 // [HGM] font: use defaults from settings file if available and not overruled
2113 if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2114 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2115 if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2116 appData.font = fontTable[MESSAGE_FONT][squareSize];
2117 if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2118 appData.coordFont = fontTable[COORD_FONT][squareSize];
2120 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2121 if (strlen(appData.pixmapDirectory) > 0) {
2122 p = ExpandPathName(appData.pixmapDirectory);
2124 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2125 appData.pixmapDirectory);
2128 if (appData.debugMode) {
2129 fprintf(stderr, _("\
2130 XBoard square size (hint): %d\n\
2131 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2133 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2134 if (appData.debugMode) {
2135 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2138 defaultLineGap = lineGap;
2139 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2141 /* [HR] height treated separately (hacked) */
2142 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2143 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2144 if (appData.showJail == 1) {
2145 /* Jail on top and bottom */
2146 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2147 XtSetArg(boardArgs[2], XtNheight,
2148 boardHeight + 2*(lineGap + squareSize));
2149 } else if (appData.showJail == 2) {
2151 XtSetArg(boardArgs[1], XtNwidth,
2152 boardWidth + 2*(lineGap + squareSize));
2153 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2156 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2157 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2161 * Determine what fonts to use.
2164 appData.font = InsertPxlSize(appData.font, fontPxlSize);
2165 appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
2166 appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
2167 fontSet = CreateFontSet(appData.font);
2168 clockFontSet = CreateFontSet(appData.clockFont);
2170 /* For the coordFont, use the 0th font of the fontset. */
2171 XFontSet coordFontSet = CreateFontSet(appData.coordFont);
2172 XFontStruct **font_struct_list;
2173 char **font_name_list;
2174 XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
2175 coordFontID = XLoadFont(xDisplay, font_name_list[0]);
2176 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2179 appData.font = FindFont(appData.font, fontPxlSize);
2180 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2181 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2182 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2183 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2184 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2185 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2187 countFontID = coordFontID; // [HGM] holdings
2188 countFontStruct = coordFontStruct;
2190 xdb = XtDatabase(xDisplay);
2192 XrmPutLineResource(&xdb, "*international: True");
2193 vTo.size = sizeof(XFontSet);
2194 vTo.addr = (XtPointer) &fontSet;
2195 XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
2197 XrmPutStringResource(&xdb, "*font", appData.font);
2201 * Detect if there are not enough colors available and adapt.
2203 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2204 appData.monoMode = True;
2207 forceMono = MakeColors();
2210 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2212 appData.monoMode = True;
2215 if (appData.lowTimeWarning && !appData.monoMode) {
2216 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2217 vFrom.size = strlen(appData.lowTimeWarningColor);
2218 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2219 if (vTo.addr == NULL)
2220 appData.monoMode = True;
2222 lowTimeWarningColor = *(Pixel *) vTo.addr;
2225 if (appData.monoMode && appData.debugMode) {
2226 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2227 (unsigned long) XWhitePixel(xDisplay, xScreen),
2228 (unsigned long) XBlackPixel(xDisplay, xScreen));
2231 ParseIcsTextColors();
2232 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2233 textColors[ColorNone].attr = 0;
2235 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2241 layoutName = "tinyLayout";
2242 } else if (smallLayout) {
2243 layoutName = "smallLayout";
2245 layoutName = "normalLayout";
2247 /* Outer layoutWidget is there only to provide a name for use in
2248 resources that depend on the layout style */
2250 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2251 layoutArgs, XtNumber(layoutArgs));
2253 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2254 formArgs, XtNumber(formArgs));
2255 XtSetArg(args[0], XtNdefaultDistance, &sep);
2256 XtGetValues(formWidget, args, 1);
2259 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2260 XtSetArg(args[0], XtNtop, XtChainTop);
2261 XtSetArg(args[1], XtNbottom, XtChainTop);
2262 XtSetArg(args[2], XtNright, XtChainLeft);
2263 XtSetValues(menuBarWidget, args, 3);
2265 widgetList[j++] = whiteTimerWidget =
2266 XtCreateWidget("whiteTime", labelWidgetClass,
2267 formWidget, timerArgs, XtNumber(timerArgs));
2269 XtSetArg(args[0], XtNfontSet, clockFontSet);
2271 XtSetArg(args[0], XtNfont, clockFontStruct);
2273 XtSetArg(args[1], XtNtop, XtChainTop);
2274 XtSetArg(args[2], XtNbottom, XtChainTop);
2275 XtSetValues(whiteTimerWidget, args, 3);
2277 widgetList[j++] = blackTimerWidget =
2278 XtCreateWidget("blackTime", labelWidgetClass,
2279 formWidget, timerArgs, XtNumber(timerArgs));
2281 XtSetArg(args[0], XtNfontSet, clockFontSet);
2283 XtSetArg(args[0], XtNfont, clockFontStruct);
2285 XtSetArg(args[1], XtNtop, XtChainTop);
2286 XtSetArg(args[2], XtNbottom, XtChainTop);
2287 XtSetValues(blackTimerWidget, args, 3);
2289 if (appData.titleInWindow) {
2290 widgetList[j++] = titleWidget =
2291 XtCreateWidget("title", labelWidgetClass, formWidget,
2292 titleArgs, XtNumber(titleArgs));
2293 XtSetArg(args[0], XtNtop, XtChainTop);
2294 XtSetArg(args[1], XtNbottom, XtChainTop);
2295 XtSetValues(titleWidget, args, 2);
2298 if (appData.showButtonBar) {
2299 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2300 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2301 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2302 XtSetArg(args[2], XtNtop, XtChainTop);
2303 XtSetArg(args[3], XtNbottom, XtChainTop);
2304 XtSetValues(buttonBarWidget, args, 4);
2307 widgetList[j++] = messageWidget =
2308 XtCreateWidget("message", labelWidgetClass, formWidget,
2309 messageArgs, XtNumber(messageArgs));
2310 XtSetArg(args[0], XtNtop, XtChainTop);
2311 XtSetArg(args[1], XtNbottom, XtChainTop);
2312 XtSetValues(messageWidget, args, 2);
2314 widgetList[j++] = boardWidget =
2315 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2316 XtNumber(boardArgs));
2318 XtManageChildren(widgetList, j);
2320 timerWidth = (boardWidth - sep) / 2;
2321 XtSetArg(args[0], XtNwidth, timerWidth);
2322 XtSetValues(whiteTimerWidget, args, 1);
2323 XtSetValues(blackTimerWidget, args, 1);
2325 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2326 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2327 XtGetValues(whiteTimerWidget, args, 2);
2329 if (appData.showButtonBar) {
2330 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2331 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2332 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2336 * formWidget uses these constraints but they are stored
2340 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2341 XtSetValues(menuBarWidget, args, i);
2342 if (appData.titleInWindow) {
2345 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2346 XtSetValues(whiteTimerWidget, args, i);
2348 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2349 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2350 XtSetValues(blackTimerWidget, args, i);
2352 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2353 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2354 XtSetValues(titleWidget, args, i);
2356 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2357 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2358 XtSetValues(messageWidget, args, i);
2359 if (appData.showButtonBar) {
2361 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2362 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2363 XtSetValues(buttonBarWidget, args, i);
2367 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2368 XtSetValues(whiteTimerWidget, args, i);
2370 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2371 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2372 XtSetValues(blackTimerWidget, args, i);
2374 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2375 XtSetValues(titleWidget, args, i);
2377 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2378 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2379 XtSetValues(messageWidget, args, i);
2380 if (appData.showButtonBar) {
2382 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2383 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2384 XtSetValues(buttonBarWidget, args, i);
2389 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2390 XtSetValues(whiteTimerWidget, args, i);
2392 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2393 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2394 XtSetValues(blackTimerWidget, args, i);
2396 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2397 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2398 XtSetValues(messageWidget, args, i);
2399 if (appData.showButtonBar) {
2401 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2402 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2403 XtSetValues(buttonBarWidget, args, i);
2407 XtSetArg(args[0], XtNfromVert, messageWidget);
2408 XtSetArg(args[1], XtNtop, XtChainTop);
2409 XtSetArg(args[2], XtNbottom, XtChainBottom);
2410 XtSetArg(args[3], XtNleft, XtChainLeft);
2411 XtSetArg(args[4], XtNright, XtChainRight);
2412 XtSetValues(boardWidget, args, 5);
2414 XtRealizeWidget(shellWidget);
2417 XtSetArg(args[0], XtNx, wpMain.x);
2418 XtSetArg(args[1], XtNy, wpMain.y);
2419 XtSetValues(shellWidget, args, 2);
2423 * Correct the width of the message and title widgets.
2424 * It is not known why some systems need the extra fudge term.
2425 * The value "2" is probably larger than needed.
2427 XawFormDoLayout(formWidget, False);
2429 #define WIDTH_FUDGE 2
2431 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2432 XtSetArg(args[i], XtNheight, &h); i++;
2433 XtGetValues(messageWidget, args, i);
2434 if (appData.showButtonBar) {
2436 XtSetArg(args[i], XtNwidth, &w); i++;
2437 XtGetValues(buttonBarWidget, args, i);
2438 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2440 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2443 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2444 if (gres != XtGeometryYes && appData.debugMode) {
2445 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2446 programName, gres, w, h, wr, hr);
2449 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2450 /* The size used for the child widget in layout lags one resize behind
2451 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2453 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2454 if (gres != XtGeometryYes && appData.debugMode) {
2455 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2456 programName, gres, w, h, wr, hr);
2459 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2460 XtSetArg(args[1], XtNright, XtChainRight);
2461 XtSetValues(messageWidget, args, 2);
2463 if (appData.titleInWindow) {
2465 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2466 XtSetArg(args[i], XtNheight, &h); i++;
2467 XtGetValues(titleWidget, args, i);
2469 w = boardWidth - 2*bor;
2471 XtSetArg(args[0], XtNwidth, &w);
2472 XtGetValues(menuBarWidget, args, 1);
2473 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2476 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2477 if (gres != XtGeometryYes && appData.debugMode) {
2479 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2480 programName, gres, w, h, wr, hr);
2483 XawFormDoLayout(formWidget, True);
2485 xBoardWindow = XtWindow(boardWidget);
2487 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2488 // not need to go into InitDrawingSizes().
2492 * Create X checkmark bitmap and initialize option menu checks.
2494 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2495 checkmark_bits, checkmark_width, checkmark_height);
2496 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2497 #ifndef OPTIONSDIALOG
2498 if (appData.alwaysPromoteToQueen) {
2499 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2502 if (appData.animateDragging) {
2503 XtSetValues(XtNameToWidget(menuBarWidget,
2504 "menuOptions.Animate Dragging"),
2507 if (appData.animate) {
2508 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2511 if (appData.autoCallFlag) {
2512 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2515 if (appData.autoFlipView) {
2516 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2519 if (appData.blindfold) {
2520 XtSetValues(XtNameToWidget(menuBarWidget,
2521 "menuOptions.Blindfold"), args, 1);
2523 if (appData.flashCount > 0) {
2524 XtSetValues(XtNameToWidget(menuBarWidget,
2525 "menuOptions.Flash Moves"),
2529 if (appData.highlightDragging) {
2530 XtSetValues(XtNameToWidget(menuBarWidget,
2531 "menuOptions.Highlight Dragging"),
2535 if (appData.highlightLastMove) {
2536 XtSetValues(XtNameToWidget(menuBarWidget,
2537 "menuOptions.Highlight Last Move"),
2540 if (appData.highlightMoveWithArrow) {
2541 XtSetValues(XtNameToWidget(menuBarWidget,
2542 "menuOptions.Arrow"),
2545 // if (appData.icsAlarm) {
2546 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2549 if (appData.ringBellAfterMoves) {
2550 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2553 if (appData.oneClick) {
2554 XtSetValues(XtNameToWidget(menuBarWidget,
2555 "menuOptions.OneClick"), args, 1);
2557 if (appData.periodicUpdates) {
2558 XtSetValues(XtNameToWidget(menuBarWidget,
2559 "menuOptions.Periodic Updates"), args, 1);
2561 if (appData.ponderNextMove) {
2562 XtSetValues(XtNameToWidget(menuBarWidget,
2563 "menuOptions.Ponder Next Move"), args, 1);
2565 if (appData.popupExitMessage) {
2566 XtSetValues(XtNameToWidget(menuBarWidget,
2567 "menuOptions.Popup Exit Message"), args, 1);
2569 if (appData.popupMoveErrors) {
2570 XtSetValues(XtNameToWidget(menuBarWidget,
2571 "menuOptions.Popup Move Errors"), args, 1);
2573 // if (appData.premove) {
2574 // XtSetValues(XtNameToWidget(menuBarWidget,
2575 // "menuOptions.Premove"), args, 1);
2577 if (appData.showCoords) {
2578 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2581 if (appData.hideThinkingFromHuman) {
2582 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2585 if (appData.testLegality) {
2586 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2590 if (saveSettingsOnExit) {
2591 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2598 ReadBitmap(&wIconPixmap, "icon_white.bm",
2599 icon_white_bits, icon_white_width, icon_white_height);
2600 ReadBitmap(&bIconPixmap, "icon_black.bm",
2601 icon_black_bits, icon_black_width, icon_black_height);
2602 iconPixmap = wIconPixmap;
2604 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2605 XtSetValues(shellWidget, args, i);
2608 * Create a cursor for the board widget.
2610 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2611 XChangeWindowAttributes(xDisplay, xBoardWindow,
2612 CWCursor, &window_attributes);
2615 * Inhibit shell resizing.
2617 shellArgs[0].value = (XtArgVal) &w;
2618 shellArgs[1].value = (XtArgVal) &h;
2619 XtGetValues(shellWidget, shellArgs, 2);
2620 shellArgs[4].value = shellArgs[2].value = w;
2621 shellArgs[5].value = shellArgs[3].value = h;
2622 XtSetValues(shellWidget, &shellArgs[2], 4);
2623 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2624 marginH = h - boardHeight;
2626 CatchDeleteWindow(shellWidget, "QuitProc");
2634 if (appData.animate || appData.animateDragging)
2637 XtAugmentTranslations(formWidget,
2638 XtParseTranslationTable(globalTranslations));
2639 XtAugmentTranslations(boardWidget,
2640 XtParseTranslationTable(boardTranslations));
2641 XtAugmentTranslations(whiteTimerWidget,
2642 XtParseTranslationTable(whiteTranslations));
2643 XtAugmentTranslations(blackTimerWidget,
2644 XtParseTranslationTable(blackTranslations));
2646 /* Why is the following needed on some versions of X instead
2647 * of a translation? */
2648 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2649 (XtEventHandler) EventProc, NULL);
2651 XtAddEventHandler(formWidget, KeyPressMask, False,
2652 (XtEventHandler) MoveTypeInProc, NULL);
2654 /* [AS] Restore layout */
2655 if( wpMoveHistory.visible ) {
2659 if( wpEvalGraph.visible )
2664 if( wpEngineOutput.visible ) {
2665 EngineOutputPopUp();
2670 if (errorExitStatus == -1) {
2671 if (appData.icsActive) {
2672 /* We now wait until we see "login:" from the ICS before
2673 sending the logon script (problems with timestamp otherwise) */
2674 /*ICSInitScript();*/
2675 if (appData.icsInputBox) ICSInputBoxPopUp();
2679 signal(SIGWINCH, TermSizeSigHandler);
2681 signal(SIGINT, IntSigHandler);
2682 signal(SIGTERM, IntSigHandler);
2683 if (*appData.cmailGameName != NULLCHAR) {
2684 signal(SIGUSR1, CmailSigHandler);
2687 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2689 // XtSetKeyboardFocus(shellWidget, formWidget);
2690 XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
2692 XtAppMainLoop(appContext);
2693 if (appData.debugMode) fclose(debugFP); // [DM] debug
2700 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2701 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2703 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2704 unlink(gameCopyFilename);
2705 unlink(gamePasteFilename);
2708 RETSIGTYPE TermSizeSigHandler(int sig)
2721 CmailSigHandler(sig)
2727 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2729 /* Activate call-back function CmailSigHandlerCallBack() */
2730 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2732 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2736 CmailSigHandlerCallBack(isr, closure, message, count, error)
2744 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2746 /**** end signal code ****/
2752 /* try to open the icsLogon script, either in the location given
2753 * or in the users HOME directory
2760 f = fopen(appData.icsLogon, "r");
2763 homedir = getenv("HOME");
2764 if (homedir != NULL)
2766 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2767 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2768 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2769 f = fopen(buf, "r");
2774 ProcessICSInitScript(f);
2776 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2799 if (!menuBarWidget) return;
2800 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2802 DisplayError("menuEdit.Revert", 0);
2804 XtSetSensitive(w, !grey);
2806 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2808 DisplayError("menuEdit.Annotate", 0);
2810 XtSetSensitive(w, !grey);
2815 SetMenuEnables(enab)
2819 if (!menuBarWidget) return;
2820 while (enab->name != NULL) {
2821 w = XtNameToWidget(menuBarWidget, enab->name);
2823 DisplayError(enab->name, 0);
2825 XtSetSensitive(w, enab->value);
2831 Enables icsEnables[] = {
2832 { "menuFile.Mail Move", False },
2833 { "menuFile.Reload CMail Message", False },
2834 { "menuMode.Machine Black", False },
2835 { "menuMode.Machine White", False },
2836 { "menuMode.Analysis Mode", False },
2837 { "menuMode.Analyze File", False },
2838 { "menuMode.Two Machines", False },
2839 { "menuMode.Machine Match", False },
2841 { "menuEngine.Hint", False },
2842 { "menuEngine.Book", False },
2843 { "menuEngine.Move Now", False },
2844 #ifndef OPTIONSDIALOG
2845 { "menuOptions.Periodic Updates", False },
2846 { "menuOptions.Hide Thinking", False },
2847 { "menuOptions.Ponder Next Move", False },
2850 { "menuEngine.Engine #1 Settings", False },
2851 { "menuEngine.Engine #2 Settings", False },
2852 { "menuEngine.Load Engine", False },
2853 { "menuEdit.Annotate", False },
2854 { "menuOptions.Match", False },
2858 Enables ncpEnables[] = {
2859 { "menuFile.Mail Move", False },
2860 { "menuFile.Reload CMail Message", False },
2861 { "menuMode.Machine White", False },
2862 { "menuMode.Machine Black", False },
2863 { "menuMode.Analysis Mode", False },
2864 { "menuMode.Analyze File", False },
2865 { "menuMode.Two Machines", False },
2866 { "menuMode.Machine Match", False },
2867 { "menuMode.ICS Client", False },
2868 { "menuView.ICStex", False },
2869 { "menuView.ICS Input Box", False },
2870 { "Action", False },
2871 { "menuEdit.Revert", False },
2872 { "menuEdit.Annotate", False },
2873 { "menuEngine.Engine #1 Settings", False },
2874 { "menuEngine.Engine #2 Settings", False },
2875 { "menuEngine.Move Now", False },
2876 { "menuEngine.Retract Move", False },
2877 { "menuOptions.ICS", False },
2878 #ifndef OPTIONSDIALOG
2879 { "menuOptions.Auto Flag", False },
2880 { "menuOptions.Auto Flip View", False },
2881 // { "menuOptions.ICS Alarm", False },
2882 { "menuOptions.Move Sound", False },
2883 { "menuOptions.Hide Thinking", False },
2884 { "menuOptions.Periodic Updates", False },
2885 { "menuOptions.Ponder Next Move", False },
2887 { "menuEngine.Hint", False },
2888 { "menuEngine.Book", False },
2892 Enables gnuEnables[] = {
2893 { "menuMode.ICS Client", False },
2894 { "menuView.ICStex", False },
2895 { "menuView.ICS Input Box", False },
2896 { "menuAction.Accept", False },
2897 { "menuAction.Decline", False },
2898 { "menuAction.Rematch", False },
2899 { "menuAction.Adjourn", False },
2900 { "menuAction.Stop Examining", False },
2901 { "menuAction.Stop Observing", False },
2902 { "menuAction.Upload to Examine", False },
2903 { "menuEdit.Revert", False },
2904 { "menuEdit.Annotate", False },
2905 { "menuOptions.ICS", False },
2907 /* The next two options rely on SetCmailMode being called *after* */
2908 /* SetGNUMode so that when GNU is being used to give hints these */
2909 /* menu options are still available */
2911 { "menuFile.Mail Move", False },
2912 { "menuFile.Reload CMail Message", False },
2913 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
2914 { "menuMode.Machine White", True },
2915 { "menuMode.Machine Black", True },
2916 { "menuMode.Analysis Mode", True },
2917 { "menuMode.Analyze File", True },
2918 { "menuMode.Two Machines", True },
2919 { "menuMode.Machine Match", True },
2920 { "menuEngine.Engine #1 Settings", True },
2921 { "menuEngine.Engine #2 Settings", True },
2922 { "menuEngine.Hint", True },
2923 { "menuEngine.Book", True },
2924 { "menuEngine.Move Now", True },
2925 { "menuEngine.Retract Move", True },
2930 Enables cmailEnables[] = {
2932 { "menuAction.Call Flag", False },
2933 { "menuAction.Draw", True },
2934 { "menuAction.Adjourn", False },
2935 { "menuAction.Abort", False },
2936 { "menuAction.Stop Observing", False },
2937 { "menuAction.Stop Examining", False },
2938 { "menuFile.Mail Move", True },
2939 { "menuFile.Reload CMail Message", True },
2943 Enables trainingOnEnables[] = {
2944 { "menuMode.Edit Comment", False },
2945 { "menuMode.Pause", False },
2946 { "menuEdit.Forward", False },
2947 { "menuEdit.Backward", False },
2948 { "menuEdit.Forward to End", False },
2949 { "menuEdit.Back to Start", False },
2950 { "menuEngine.Move Now", False },
2951 { "menuEdit.Truncate Game", False },
2955 Enables trainingOffEnables[] = {
2956 { "menuMode.Edit Comment", True },
2957 { "menuMode.Pause", True },
2958 { "menuEdit.Forward", True },
2959 { "menuEdit.Backward", True },
2960 { "menuEdit.Forward to End", True },
2961 { "menuEdit.Back to Start", True },
2962 { "menuEngine.Move Now", True },
2963 { "menuEdit.Truncate Game", True },
2967 Enables machineThinkingEnables[] = {
2968 { "menuFile.Load Game", False },
2969 // { "menuFile.Load Next Game", False },
2970 // { "menuFile.Load Previous Game", False },
2971 // { "menuFile.Reload Same Game", False },
2972 { "menuEdit.Paste Game", False },
2973 { "menuFile.Load Position", False },
2974 // { "menuFile.Load Next Position", False },
2975 // { "menuFile.Load Previous Position", False },
2976 // { "menuFile.Reload Same Position", False },
2977 { "menuEdit.Paste Position", False },
2978 { "menuMode.Machine White", False },
2979 { "menuMode.Machine Black", False },
2980 { "menuMode.Two Machines", False },
2981 // { "menuMode.Machine Match", False },
2982 { "menuEngine.Retract Move", False },
2986 Enables userThinkingEnables[] = {
2987 { "menuFile.Load Game", True },
2988 // { "menuFile.Load Next Game", True },
2989 // { "menuFile.Load Previous Game", True },
2990 // { "menuFile.Reload Same Game", True },
2991 { "menuEdit.Paste Game", True },
2992 { "menuFile.Load Position", True },
2993 // { "menuFile.Load Next Position", True },
2994 // { "menuFile.Load Previous Position", True },
2995 // { "menuFile.Reload Same Position", True },
2996 { "menuEdit.Paste Position", True },
2997 { "menuMode.Machine White", True },
2998 { "menuMode.Machine Black", True },
2999 { "menuMode.Two Machines", True },
3000 // { "menuMode.Machine Match", True },
3001 { "menuEngine.Retract Move", True },
3007 SetMenuEnables(icsEnables);
3010 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
3011 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3012 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
3020 SetMenuEnables(ncpEnables);
3026 SetMenuEnables(gnuEnables);
3032 SetMenuEnables(cmailEnables);
3038 SetMenuEnables(trainingOnEnables);
3039 if (appData.showButtonBar) {
3040 XtSetSensitive(buttonBarWidget, False);
3046 SetTrainingModeOff()
3048 SetMenuEnables(trainingOffEnables);
3049 if (appData.showButtonBar) {
3050 XtSetSensitive(buttonBarWidget, True);
3055 SetUserThinkingEnables()
3057 if (appData.noChessProgram) return;
3058 SetMenuEnables(userThinkingEnables);
3062 SetMachineThinkingEnables()
3064 if (appData.noChessProgram) return;
3065 SetMenuEnables(machineThinkingEnables);
3067 case MachinePlaysBlack:
3068 case MachinePlaysWhite:
3069 case TwoMachinesPlay:
3070 XtSetSensitive(XtNameToWidget(menuBarWidget,
3071 ModeToWidgetName(gameMode)), True);
3078 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
3079 #define HISTORY_SIZE 64
3080 static char *history[HISTORY_SIZE];
3081 int histIn = 0, histP = 0;
3084 SaveInHistory(char *cmd)
3086 if (history[histIn] != NULL) {
3087 free(history[histIn]);
3088 history[histIn] = NULL;
3090 if (*cmd == NULLCHAR) return;
3091 history[histIn] = StrSave(cmd);
3092 histIn = (histIn + 1) % HISTORY_SIZE;
3093 if (history[histIn] != NULL) {
3094 free(history[histIn]);
3095 history[histIn] = NULL;
3101 PrevInHistory(char *cmd)
3104 if (histP == histIn) {
3105 if (history[histIn] != NULL) free(history[histIn]);
3106 history[histIn] = StrSave(cmd);
3108 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3109 if (newhp == histIn || history[newhp] == NULL) return NULL;
3111 return history[histP];
3117 if (histP == histIn) return NULL;
3118 histP = (histP + 1) % HISTORY_SIZE;
3119 return history[histP];
3121 // end of borrowed code
3123 #define Abs(n) ((n)<0 ? -(n) : (n))
3127 InsertPxlSize(pattern, targetPxlSize)
3131 char *base_fnt_lst, strInt[12], *p, *q;
3132 int alternatives, i, len, strIntLen;
3135 * Replace the "*" (if present) in the pixel-size slot of each
3136 * alternative with the targetPxlSize.
3140 while ((p = strchr(p, ',')) != NULL) {
3144 snprintf(strInt, sizeof(strInt), "%d", targetPxlSize);
3145 strIntLen = strlen(strInt);
3146 base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1);
3150 while (alternatives--) {
3151 char *comma = strchr(p, ',');
3152 for (i=0; i<14; i++) {
3153 char *hyphen = strchr(p, '-');
3155 if (comma && hyphen > comma) break;
3156 len = hyphen + 1 - p;
3157 if (i == 7 && *p == '*' && len == 2) {
3159 memcpy(q, strInt, strIntLen);
3169 len = comma + 1 - p;
3176 return base_fnt_lst;
3180 CreateFontSet(base_fnt_lst)
3184 char **missing_list;
3188 fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
3189 &missing_list, &missing_count, &def_string);
3190 if (appData.debugMode) {
3192 XFontStruct **font_struct_list;
3193 char **font_name_list;
3194 fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
3196 fprintf(debugFP, " got list %s, locale %s\n",
3197 XBaseFontNameListOfFontSet(fntSet),
3198 XLocaleOfFontSet(fntSet));
3199 count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
3200 for (i = 0; i < count; i++) {
3201 fprintf(debugFP, " got charset %s\n", font_name_list[i]);
3204 for (i = 0; i < missing_count; i++) {
3205 fprintf(debugFP, " missing charset %s\n", missing_list[i]);
3208 if (fntSet == NULL) {
3209 fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
3214 #else // not ENABLE_NLS
3216 * Find a font that matches "pattern" that is as close as
3217 * possible to the targetPxlSize. Prefer fonts that are k
3218 * pixels smaller to fonts that are k pixels larger. The
3219 * pattern must be in the X Consortium standard format,
3220 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3221 * The return value should be freed with XtFree when no
3225 FindFont(pattern, targetPxlSize)
3229 char **fonts, *p, *best, *scalable, *scalableTail;
3230 int i, j, nfonts, minerr, err, pxlSize;
3232 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3234 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3235 programName, pattern);
3242 for (i=0; i<nfonts; i++) {
3245 if (*p != '-') continue;
3247 if (*p == NULLCHAR) break;
3248 if (*p++ == '-') j++;
3250 if (j < 7) continue;
3253 scalable = fonts[i];
3256 err = pxlSize - targetPxlSize;
3257 if (Abs(err) < Abs(minerr) ||
3258 (minerr > 0 && err < 0 && -err == minerr)) {
3264 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3265 /* If the error is too big and there is a scalable font,
3266 use the scalable font. */
3267 int headlen = scalableTail - scalable;
3268 p = (char *) XtMalloc(strlen(scalable) + 10);
3269 while (isdigit(*scalableTail)) scalableTail++;
3270 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3272 p = (char *) XtMalloc(strlen(best) + 2);
3273 safeStrCpy(p, best, strlen(best)+1 );
3275 if (appData.debugMode) {
3276 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3277 pattern, targetPxlSize, p);
3279 XFreeFontNames(fonts);
3285 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3286 // must be called before all non-first callse to CreateGCs()
3287 XtReleaseGC(shellWidget, highlineGC);
3288 XtReleaseGC(shellWidget, lightSquareGC);
3289 XtReleaseGC(shellWidget, darkSquareGC);
3290 XtReleaseGC(shellWidget, lineGC);
3291 if (appData.monoMode) {
3292 if (DefaultDepth(xDisplay, xScreen) == 1) {
3293 XtReleaseGC(shellWidget, wbPieceGC);
3295 XtReleaseGC(shellWidget, bwPieceGC);
3298 XtReleaseGC(shellWidget, prelineGC);
3299 XtReleaseGC(shellWidget, jailSquareGC);
3300 XtReleaseGC(shellWidget, wdPieceGC);
3301 XtReleaseGC(shellWidget, wlPieceGC);
3302 XtReleaseGC(shellWidget, wjPieceGC);
3303 XtReleaseGC(shellWidget, bdPieceGC);
3304 XtReleaseGC(shellWidget, blPieceGC);
3305 XtReleaseGC(shellWidget, bjPieceGC);
3309 void CreateGCs(int redo)
3311 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3312 | GCBackground | GCFunction | GCPlaneMask;
3313 XGCValues gc_values;
3316 gc_values.plane_mask = AllPlanes;
3317 gc_values.line_width = lineGap;
3318 gc_values.line_style = LineSolid;
3319 gc_values.function = GXcopy;
3322 DeleteGCs(); // called a second time; clean up old GCs first
3323 } else { // [HGM] grid and font GCs created on first call only
3324 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3325 gc_values.background = XWhitePixel(xDisplay, xScreen);
3326 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3327 XSetFont(xDisplay, coordGC, coordFontID);
3329 // [HGM] make font for holdings counts (white on black)
3330 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3331 gc_values.background = XBlackPixel(xDisplay, xScreen);
3332 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3333 XSetFont(xDisplay, countGC, countFontID);
3335 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3336 gc_values.background = XBlackPixel(xDisplay, xScreen);
3337 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3339 if (appData.monoMode) {
3340 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3341 gc_values.background = XWhitePixel(xDisplay, xScreen);
3342 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3344 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3345 gc_values.background = XBlackPixel(xDisplay, xScreen);
3346 lightSquareGC = wbPieceGC
3347 = XtGetGC(shellWidget, value_mask, &gc_values);
3349 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3350 gc_values.background = XWhitePixel(xDisplay, xScreen);
3351 darkSquareGC = bwPieceGC
3352 = XtGetGC(shellWidget, value_mask, &gc_values);
3354 if (DefaultDepth(xDisplay, xScreen) == 1) {
3355 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3356 gc_values.function = GXcopyInverted;
3357 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3358 gc_values.function = GXcopy;
3359 if (XBlackPixel(xDisplay, xScreen) == 1) {
3360 bwPieceGC = darkSquareGC;
3361 wbPieceGC = copyInvertedGC;
3363 bwPieceGC = copyInvertedGC;
3364 wbPieceGC = lightSquareGC;
3368 gc_values.foreground = highlightSquareColor;
3369 gc_values.background = highlightSquareColor;
3370 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3372 gc_values.foreground = premoveHighlightColor;
3373 gc_values.background = premoveHighlightColor;
3374 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3376 gc_values.foreground = lightSquareColor;
3377 gc_values.background = darkSquareColor;
3378 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3380 gc_values.foreground = darkSquareColor;
3381 gc_values.background = lightSquareColor;
3382 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3384 gc_values.foreground = jailSquareColor;
3385 gc_values.background = jailSquareColor;
3386 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3388 gc_values.foreground = whitePieceColor;
3389 gc_values.background = darkSquareColor;
3390 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3392 gc_values.foreground = whitePieceColor;
3393 gc_values.background = lightSquareColor;
3394 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3396 gc_values.foreground = whitePieceColor;
3397 gc_values.background = jailSquareColor;
3398 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3400 gc_values.foreground = blackPieceColor;
3401 gc_values.background = darkSquareColor;
3402 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3404 gc_values.foreground = blackPieceColor;
3405 gc_values.background = lightSquareColor;
3406 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3408 gc_values.foreground = blackPieceColor;
3409 gc_values.background = jailSquareColor;
3410 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3414 void loadXIM(xim, xmask, filename, dest, mask)
3427 fp = fopen(filename, "rb");
3429 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3436 for (y=0; y<h; ++y) {
3437 for (x=0; x<h; ++x) {
3442 XPutPixel(xim, x, y, blackPieceColor);
3444 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3447 XPutPixel(xim, x, y, darkSquareColor);
3449 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3452 XPutPixel(xim, x, y, whitePieceColor);
3454 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3457 XPutPixel(xim, x, y, lightSquareColor);
3459 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3467 /* create Pixmap of piece */
3468 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3470 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3473 /* create Pixmap of clipmask
3474 Note: We assume the white/black pieces have the same
3475 outline, so we make only 6 masks. This is okay
3476 since the XPM clipmask routines do the same. */
3478 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3480 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3483 /* now create the 1-bit version */
3484 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3487 values.foreground = 1;
3488 values.background = 0;
3490 /* Don't use XtGetGC, not read only */
3491 maskGC = XCreateGC(xDisplay, *mask,
3492 GCForeground | GCBackground, &values);
3493 XCopyPlane(xDisplay, temp, *mask, maskGC,
3494 0, 0, squareSize, squareSize, 0, 0, 1);
3495 XFreePixmap(xDisplay, temp);
3500 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3502 void CreateXIMPieces()
3507 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3512 /* The XSynchronize calls were copied from CreatePieces.
3513 Not sure if needed, but can't hurt */
3514 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3517 /* temp needed by loadXIM() */
3518 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3519 0, 0, ss, ss, AllPlanes, XYPixmap);
3521 if (strlen(appData.pixmapDirectory) == 0) {
3525 if (appData.monoMode) {
3526 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3530 fprintf(stderr, _("\nLoading XIMs...\n"));
3532 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3533 fprintf(stderr, "%d", piece+1);
3534 for (kind=0; kind<4; kind++) {
3535 fprintf(stderr, ".");
3536 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3537 ExpandPathName(appData.pixmapDirectory),
3538 piece <= (int) WhiteKing ? "" : "w",
3539 pieceBitmapNames[piece],
3541 ximPieceBitmap[kind][piece] =
3542 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3543 0, 0, ss, ss, AllPlanes, XYPixmap);
3544 if (appData.debugMode)
3545 fprintf(stderr, _("(File:%s:) "), buf);
3546 loadXIM(ximPieceBitmap[kind][piece],
3548 &(xpmPieceBitmap2[kind][piece]),
3549 &(ximMaskPm2[piece]));
3550 if(piece <= (int)WhiteKing)
3551 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3553 fprintf(stderr," ");
3555 /* Load light and dark squares */
3556 /* If the LSQ and DSQ pieces don't exist, we will
3557 draw them with solid squares. */
3558 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3559 if (access(buf, 0) != 0) {
3563 fprintf(stderr, _("light square "));
3565 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3566 0, 0, ss, ss, AllPlanes, XYPixmap);
3567 if (appData.debugMode)
3568 fprintf(stderr, _("(File:%s:) "), buf);
3570 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3571 fprintf(stderr, _("dark square "));
3572 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3573 ExpandPathName(appData.pixmapDirectory), ss);
3574 if (appData.debugMode)
3575 fprintf(stderr, _("(File:%s:) "), buf);
3577 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3578 0, 0, ss, ss, AllPlanes, XYPixmap);
3579 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3580 xpmJailSquare = xpmLightSquare;
3582 fprintf(stderr, _("Done.\n"));
3584 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3587 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3590 void CreateXPMBoard(char *s, int kind)
3594 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3595 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3596 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3600 void FreeXPMPieces()
3601 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3602 // thisroutine has to be called t free the old piece pixmaps
3604 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3605 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3607 XFreePixmap(xDisplay, xpmLightSquare);
3608 XFreePixmap(xDisplay, xpmDarkSquare);
3612 void CreateXPMPieces()
3616 u_int ss = squareSize;
3618 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3619 XpmColorSymbol symbols[4];
3620 static int redo = False;
3622 if(redo) FreeXPMPieces(); else redo = 1;
3624 /* The XSynchronize calls were copied from CreatePieces.
3625 Not sure if needed, but can't hurt */
3626 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3628 /* Setup translations so piece colors match square colors */
3629 symbols[0].name = "light_piece";
3630 symbols[0].value = appData.whitePieceColor;
3631 symbols[1].name = "dark_piece";
3632 symbols[1].value = appData.blackPieceColor;
3633 symbols[2].name = "light_square";
3634 symbols[2].value = appData.lightSquareColor;
3635 symbols[3].name = "dark_square";
3636 symbols[3].value = appData.darkSquareColor;
3638 attr.valuemask = XpmColorSymbols;
3639 attr.colorsymbols = symbols;
3640 attr.numsymbols = 4;
3642 if (appData.monoMode) {
3643 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3647 if (strlen(appData.pixmapDirectory) == 0) {
3648 XpmPieces* pieces = builtInXpms;