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 GenericPopDown P(());
478 void update_ics_width P(());
479 int get_term_width P(());
480 int CopyMemoProc P(());
481 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
482 Boolean IsDrawArrowEnabled P(());
485 * XBoard depends on Xt R4 or higher
487 int xtVersion = XtSpecificationRelease;
492 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
493 jailSquareColor, highlightSquareColor, premoveHighlightColor;
494 Pixel lowTimeWarningColor;
495 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
496 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
497 wjPieceGC, bjPieceGC, prelineGC, countGC;
498 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
499 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
500 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
501 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
502 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
503 ICSInputShell, fileNameShell, askQuestionShell;
504 Widget historyShell, evalGraphShell, gameListShell;
505 int hOffset; // [HGM] dual
506 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
507 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
508 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
510 XFontSet fontSet, clockFontSet;
513 XFontStruct *clockFontStruct;
515 Font coordFontID, countFontID;
516 XFontStruct *coordFontStruct, *countFontStruct;
517 XtAppContext appContext;
519 char *oldICSInteractionTitle;
523 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
525 Position commentX = -1, commentY = -1;
526 Dimension commentW, commentH;
527 typedef unsigned int BoardSize;
529 Boolean chessProgram;
531 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
532 int squareSize, smallLayout = 0, tinyLayout = 0,
533 marginW, marginH, // [HGM] for run-time resizing
534 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
535 ICSInputBoxUp = False, askQuestionUp = False,
536 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
537 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
538 Pixel timerForegroundPixel, timerBackgroundPixel;
539 Pixel buttonForegroundPixel, buttonBackgroundPixel;
540 char *chessDir, *programName, *programVersion,
541 *gameCopyFilename, *gamePasteFilename;
542 Boolean alwaysOnTop = False;
543 Boolean saveSettingsOnExit;
544 char *settingsFileName;
545 char *icsTextMenuString;
547 char *firstChessProgramNames;
548 char *secondChessProgramNames;
550 WindowPlacement wpMain;
551 WindowPlacement wpConsole;
552 WindowPlacement wpComment;
553 WindowPlacement wpMoveHistory;
554 WindowPlacement wpEvalGraph;
555 WindowPlacement wpEngineOutput;
556 WindowPlacement wpGameList;
557 WindowPlacement wpTags;
559 extern Widget shells[];
560 extern Boolean shellUp[];
564 Pixmap pieceBitmap[2][(int)BlackPawn];
565 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
566 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
567 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
568 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
569 Pixmap xpmBoardBitmap[2];
570 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
571 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
572 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
573 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
574 XImage *ximLightSquare, *ximDarkSquare;
577 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
578 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
580 #define White(piece) ((int)(piece) < (int)BlackPawn)
582 /* Variables for doing smooth animation. This whole thing
583 would be much easier if the board was double-buffered,
584 but that would require a fairly major rewrite. */
589 GC blitGC, pieceGC, outlineGC;
590 XPoint startSquare, prevFrame, mouseDelta;
594 int startBoardX, startBoardY;
597 /* There can be two pieces being animated at once: a player
598 can begin dragging a piece before the remote opponent has moved. */
600 static AnimState game, player;
602 /* Bitmaps for use as masks when drawing XPM pieces.
603 Need one for each black and white piece. */
604 static Pixmap xpmMask[BlackKing + 1];
606 /* This magic number is the number of intermediate frames used
607 in each half of the animation. For short moves it's reduced
608 by 1. The total number of frames will be factor * 2 + 1. */
611 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
613 MenuItem fileMenu[] = {
614 {N_("New Game Ctrl+N"), "New Game", ResetProc},
615 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
616 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
617 {"----", NULL, NothingProc},
618 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
619 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
620 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
621 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
622 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
623 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
624 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
625 {"----", NULL, NothingProc},
626 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
627 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
628 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
629 {"----", NULL, NothingProc},
630 {N_("Mail Move"), "Mail Move", MailMoveProc},
631 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
632 {"----", NULL, NothingProc},
633 {N_("Quit Ctr+Q"), "Exit", QuitProc},
637 MenuItem editMenu[] = {
638 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
639 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
640 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
641 {"----", NULL, NothingProc},
642 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
643 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
644 {"----", NULL, NothingProc},
645 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
646 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
647 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
648 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
649 {N_("Edit Book"), "Edit Book", EditBookProc},
650 {"----", NULL, NothingProc},
651 {N_("Revert Home"), "Revert", RevertProc},
652 {N_("Annotate"), "Annotate", AnnotateProc},
653 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
654 {"----", NULL, NothingProc},
655 {N_("Backward Alt+Left"), "Backward", BackwardProc},
656 {N_("Forward Alt+Right"), "Forward", ForwardProc},
657 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
658 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
662 MenuItem viewMenu[] = {
663 {N_("Flip View F2"), "Flip View", FlipViewProc},
664 {"----", NULL, NothingProc},
665 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
666 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
667 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
668 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
669 {N_("ICS text menu"), "ICStex", IcsTextProc},
670 {"----", NULL, NothingProc},
671 {N_("Tags"), "Show Tags", EditTagsProc},
672 {N_("Comments"), "Show Comments", EditCommentProc},
673 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
674 {"----", NULL, NothingProc},
675 {N_("Board..."), "Board Options", BoardOptionsProc},
676 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
680 MenuItem modeMenu[] = {
681 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
682 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
683 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
684 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
685 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
686 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
687 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
688 {N_("Training"), "Training", TrainingProc},
689 {N_("ICS Client"), "ICS Client", IcsClientProc},
690 {"----", NULL, NothingProc},
691 {N_("Machine Match"), "Machine Match", MatchProc},
692 {N_("Pause Pause"), "Pause", PauseProc},
696 MenuItem actionMenu[] = {
697 {N_("Accept F3"), "Accept", AcceptProc},
698 {N_("Decline F4"), "Decline", DeclineProc},
699 {N_("Rematch F12"), "Rematch", RematchProc},
700 {"----", NULL, NothingProc},
701 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
702 {N_("Draw F6"), "Draw", DrawProc},
703 {N_("Adjourn F7"), "Adjourn", AdjournProc},
704 {N_("Abort F8"),"Abort", AbortProc},
705 {N_("Resign F9"), "Resign", ResignProc},
706 {"----", NULL, NothingProc},
707 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
708 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
709 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
710 {"----", NULL, NothingProc},
711 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
712 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
713 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
717 MenuItem engineMenu[] = {
718 {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
719 {"----", NULL, NothingProc},
720 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
721 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
722 {"----", NULL, NothingProc},
723 {N_("Hint"), "Hint", HintProc},
724 {N_("Book"), "Book", BookProc},
725 {"----", NULL, NothingProc},
726 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
727 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
731 MenuItem optionsMenu[] = {
732 #define OPTIONSDIALOG
734 {N_("General ..."), "General", OptionsProc},
736 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
737 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
738 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
739 {N_("ICS ..."), "ICS", IcsOptionsProc},
740 {N_("Match ..."), "Match", MatchOptionsProc},
741 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
742 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
743 // {N_(" ..."), "", OptionsProc},
744 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
745 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
746 {"----", NULL, NothingProc},
747 #ifndef OPTIONSDIALOG
748 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
749 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
750 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
751 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
752 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
753 {N_("Blindfold"), "Blindfold", BlindfoldProc},
754 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
756 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
758 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
759 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
760 {N_("Move Sound"), "Move Sound", MoveSoundProc},
761 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
762 {N_("One-Click Moving"), "OneClick", OneClickProc},
763 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
764 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
765 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
766 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
767 // {N_("Premove"), "Premove", PremoveProc},
768 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
769 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
770 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
771 {"----", NULL, NothingProc},
773 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
774 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
778 MenuItem helpMenu[] = {
779 {N_("Info XBoard"), "Info XBoard", InfoProc},
780 {N_("Man XBoard F1"), "Man XBoard", ManProc},
781 {"----", NULL, NothingProc},
782 {N_("About XBoard"), "About XBoard", AboutProc},
787 {N_("File"), "File", fileMenu},
788 {N_("Edit"), "Edit", editMenu},
789 {N_("View"), "View", viewMenu},
790 {N_("Mode"), "Mode", modeMenu},
791 {N_("Action"), "Action", actionMenu},
792 {N_("Engine"), "Engine", engineMenu},
793 {N_("Options"), "Options", optionsMenu},
794 {N_("Help"), "Help", helpMenu},
798 #define PAUSE_BUTTON "P"
799 MenuItem buttonBar[] = {
800 {"<<", "<<", ToStartProc},
801 {"<", "<", BackwardProc},
802 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
803 {">", ">", ForwardProc},
804 {">>", ">>", ToEndProc},
808 #define PIECE_MENU_SIZE 18
809 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
810 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
811 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
812 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
813 N_("Empty square"), N_("Clear board") },
814 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
815 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
816 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
817 N_("Empty square"), N_("Clear board") }
819 /* must be in same order as pieceMenuStrings! */
820 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
821 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
822 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
823 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
824 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
825 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
826 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
827 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
828 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
831 #define DROP_MENU_SIZE 6
832 String dropMenuStrings[DROP_MENU_SIZE] = {
833 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
835 /* must be in same order as dropMenuStrings! */
836 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
837 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
838 WhiteRook, WhiteQueen
846 DropMenuEnables dmEnables[] = {
864 { XtNborderWidth, 0 },
865 { XtNdefaultDistance, 0 },
869 { XtNborderWidth, 0 },
870 { XtNresizable, (XtArgVal) True },
874 { XtNborderWidth, 0 },
880 { XtNjustify, (XtArgVal) XtJustifyRight },
881 { XtNlabel, (XtArgVal) "..." },
882 { XtNresizable, (XtArgVal) True },
883 { XtNresize, (XtArgVal) False }
886 Arg messageArgs[] = {
887 { XtNjustify, (XtArgVal) XtJustifyLeft },
888 { XtNlabel, (XtArgVal) "..." },
889 { XtNresizable, (XtArgVal) True },
890 { XtNresize, (XtArgVal) False }
894 { XtNborderWidth, 0 },
895 { XtNjustify, (XtArgVal) XtJustifyLeft }
898 XtResource clientResources[] = {
899 { "flashCount", "flashCount", XtRInt, sizeof(int),
900 XtOffset(AppDataPtr, flashCount), XtRImmediate,
901 (XtPointer) FLASH_COUNT },
904 XrmOptionDescRec shellOptions[] = {
905 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
906 { "-flash", "flashCount", XrmoptionNoArg, "3" },
907 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
910 XtActionsRec boardActions[] = {
911 { "DrawPosition", DrawPositionProc },
912 { "HandleUserMove", HandleUserMove },
913 { "AnimateUserMove", AnimateUserMove },
914 { "HandlePV", HandlePV },
915 { "SelectPV", SelectPV },
916 { "StopPV", StopPV },
917 { "FileNameAction", FileNameAction },
918 { "AskQuestionProc", AskQuestionProc },
919 { "AskQuestionReplyAction", AskQuestionReplyAction },
920 { "PieceMenuPopup", PieceMenuPopup },
921 { "WhiteClock", WhiteClock },
922 { "BlackClock", BlackClock },
923 { "Iconify", Iconify },
924 { "ResetProc", ResetProc },
925 { "NewVariantProc", NewVariantProc },
926 { "LoadGameProc", LoadGameProc },
927 { "LoadNextGameProc", LoadNextGameProc },
928 { "LoadPrevGameProc", LoadPrevGameProc },
929 { "LoadSelectedProc", LoadSelectedProc },
930 { "SetFilterProc", SetFilterProc },
931 { "ReloadGameProc", ReloadGameProc },
932 { "LoadPositionProc", LoadPositionProc },
933 { "LoadNextPositionProc", LoadNextPositionProc },
934 { "LoadPrevPositionProc", LoadPrevPositionProc },
935 { "ReloadPositionProc", ReloadPositionProc },
936 { "CopyPositionProc", CopyPositionProc },
937 { "PastePositionProc", PastePositionProc },
938 { "CopyGameProc", CopyGameProc },
939 { "CopyGameListProc", CopyGameListProc },
940 { "PasteGameProc", PasteGameProc },
941 { "SaveGameProc", SaveGameProc },
942 { "SavePositionProc", SavePositionProc },
943 { "MailMoveProc", MailMoveProc },
944 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
945 { "QuitProc", QuitProc },
946 { "MachineWhiteProc", MachineWhiteProc },
947 { "MachineBlackProc", MachineBlackProc },
948 { "AnalysisModeProc", AnalyzeModeProc },
949 { "AnalyzeFileProc", AnalyzeFileProc },
950 { "TwoMachinesProc", TwoMachinesProc },
951 { "IcsClientProc", IcsClientProc },
952 { "EditGameProc", EditGameProc },
953 { "EditPositionProc", EditPositionProc },
954 { "TrainingProc", EditPositionProc },
955 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
956 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
957 { "ShowGameListProc", ShowGameListProc },
958 { "ShowMoveListProc", HistoryShowProc},
959 { "EditTagsProc", EditCommentProc },
960 { "EditBookProc", EditBookProc },
961 { "EditCommentProc", EditCommentProc },
962 { "IcsInputBoxProc", IcsInputBoxProc },
963 { "PauseProc", PauseProc },
964 { "AcceptProc", AcceptProc },
965 { "DeclineProc", DeclineProc },
966 { "RematchProc", RematchProc },
967 { "CallFlagProc", CallFlagProc },
968 { "DrawProc", DrawProc },
969 { "AdjournProc", AdjournProc },
970 { "AbortProc", AbortProc },
971 { "ResignProc", ResignProc },
972 { "AdjuWhiteProc", AdjuWhiteProc },
973 { "AdjuBlackProc", AdjuBlackProc },
974 { "AdjuDrawProc", AdjuDrawProc },
975 { "TypeInProc", TypeInProc },
976 { "EnterKeyProc", EnterKeyProc },
977 { "UpKeyProc", UpKeyProc },
978 { "DownKeyProc", DownKeyProc },
979 { "StopObservingProc", StopObservingProc },
980 { "StopExaminingProc", StopExaminingProc },
981 { "UploadProc", UploadProc },
982 { "BackwardProc", BackwardProc },
983 { "ForwardProc", ForwardProc },
984 { "ToStartProc", ToStartProc },
985 { "ToEndProc", ToEndProc },
986 { "RevertProc", RevertProc },
987 { "AnnotateProc", AnnotateProc },
988 { "TruncateGameProc", TruncateGameProc },
989 { "MoveNowProc", MoveNowProc },
990 { "RetractMoveProc", RetractMoveProc },
991 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
992 { "UciMenuProc", (XtActionProc) UciMenuProc },
993 { "TimeControlProc", (XtActionProc) TimeControlProc },
994 { "FlipViewProc", FlipViewProc },
995 { "PonderNextMoveProc", PonderNextMoveProc },
996 #ifndef OPTIONSDIALOG
997 { "AlwaysQueenProc", AlwaysQueenProc },
998 { "AnimateDraggingProc", AnimateDraggingProc },
999 { "AnimateMovingProc", AnimateMovingProc },
1000 { "AutoflagProc", AutoflagProc },
1001 { "AutoflipProc", AutoflipProc },
1002 { "BlindfoldProc", BlindfoldProc },
1003 { "FlashMovesProc", FlashMovesProc },
1005 { "HighlightDraggingProc", HighlightDraggingProc },
1007 { "HighlightLastMoveProc", HighlightLastMoveProc },
1008 // { "IcsAlarmProc", IcsAlarmProc },
1009 { "MoveSoundProc", MoveSoundProc },
1010 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1011 { "PopupExitMessageProc", PopupExitMessageProc },
1012 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1013 // { "PremoveProc", PremoveProc },
1014 { "ShowCoordsProc", ShowCoordsProc },
1015 { "ShowThinkingProc", ShowThinkingProc },
1016 { "HideThinkingProc", HideThinkingProc },
1017 { "TestLegalityProc", TestLegalityProc },
1019 { "SaveSettingsProc", SaveSettingsProc },
1020 { "SaveOnExitProc", SaveOnExitProc },
1021 { "InfoProc", InfoProc },
1022 { "ManProc", ManProc },
1023 { "HintProc", HintProc },
1024 { "BookProc", BookProc },
1025 { "AboutGameProc", AboutGameProc },
1026 { "AboutProc", AboutProc },
1027 { "DebugProc", DebugProc },
1028 { "NothingProc", NothingProc },
1029 { "CommentClick", (XtActionProc) CommentClick },
1030 { "CommentPopDown", (XtActionProc) CommentPopDown },
1031 { "TagsPopDown", (XtActionProc) TagsPopDown },
1032 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1033 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1034 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1035 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1036 { "GameListPopDown", (XtActionProc) GameListPopDown },
1037 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1038 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1039 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1040 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1041 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1042 { "GenericPopDown", (XtActionProc) GenericPopDown },
1043 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1046 char globalTranslations[] =
1047 ":<Key>F9: ResignProc() \n \
1048 :Ctrl<Key>n: ResetProc() \n \
1049 :Meta<Key>V: NewVariantProc() \n \
1050 :Ctrl<Key>o: LoadGameProc() \n \
1051 :Meta<Key>Next: LoadNextGameProc() \n \
1052 :Meta<Key>Prior: LoadPrevGameProc() \n \
1053 :Ctrl<Key>s: SaveGameProc() \n \
1054 :Ctrl<Key>c: CopyGameProc() \n \
1055 :Ctrl<Key>v: PasteGameProc() \n \
1056 :Ctrl<Key>O: LoadPositionProc() \n \
1057 :Shift<Key>Next: LoadNextPositionProc() \n \
1058 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1059 :Ctrl<Key>S: SavePositionProc() \n \
1060 :Ctrl<Key>C: CopyPositionProc() \n \
1061 :Ctrl<Key>V: PastePositionProc() \n \
1062 :Ctrl<Key>q: QuitProc() \n \
1063 :Ctrl<Key>w: MachineWhiteProc() \n \
1064 :Ctrl<Key>b: MachineBlackProc() \n \
1065 :Ctrl<Key>t: TwoMachinesProc() \n \
1066 :Ctrl<Key>a: AnalysisModeProc() \n \
1067 :Ctrl<Key>f: AnalyzeFileProc() \n \
1068 :Ctrl<Key>e: EditGameProc() \n \
1069 :Ctrl<Key>E: EditPositionProc() \n \
1070 :Meta<Key>O: EngineOutputProc() \n \
1071 :Meta<Key>E: EvalGraphProc() \n \
1072 :Meta<Key>G: ShowGameListProc() \n \
1073 :Meta<Key>H: ShowMoveListProc() \n \
1074 :<Key>Pause: PauseProc() \n \
1075 :<Key>F3: AcceptProc() \n \
1076 :<Key>F4: DeclineProc() \n \
1077 :<Key>F12: RematchProc() \n \
1078 :<Key>F5: CallFlagProc() \n \
1079 :<Key>F6: DrawProc() \n \
1080 :<Key>F7: AdjournProc() \n \
1081 :<Key>F8: AbortProc() \n \
1082 :<Key>F10: StopObservingProc() \n \
1083 :<Key>F11: StopExaminingProc() \n \
1084 :Meta Ctrl<Key>F12: DebugProc() \n \
1085 :Meta<Key>End: ToEndProc() \n \
1086 :Meta<Key>Right: ForwardProc() \n \
1087 :Meta<Key>Home: ToStartProc() \n \
1088 :Meta<Key>Left: BackwardProc() \n \
1089 :<Key>Home: RevertProc() \n \
1090 :<Key>End: TruncateGameProc() \n \
1091 :Ctrl<Key>m: MoveNowProc() \n \
1092 :Ctrl<Key>x: RetractMoveProc() \n \
1093 :Meta<Key>J: EngineMenuProc() \n \
1094 :Meta<Key>U: UciMenuProc() \n \
1095 :Meta<Key>T: TimeControlProc() \n \
1096 :Ctrl<Key>P: PonderNextMoveProc() \n "
1097 #ifndef OPTIONSDIALOG
1099 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1100 :Ctrl<Key>F: AutoflagProc() \n \
1101 :Ctrl<Key>A: AnimateMovingProc() \n \
1102 :Ctrl<Key>L: TestLegalityProc() \n \
1103 :Ctrl<Key>H: HideThinkingProc() \n "
1106 :<Key>-: Iconify() \n \
1107 :<Key>F1: ManProc() \n \
1108 :<Key>F2: FlipViewProc() \n \
1109 <KeyDown>.: BackwardProc() \n \
1110 <KeyUp>.: ForwardProc() \n \
1111 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1112 \"Send to chess program:\",,1) \n \
1113 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1114 \"Send to second chess program:\",,2) \n";
1116 char boardTranslations[] =
1117 "<Btn1Down>: HandleUserMove(0) \n \
1118 Shift<Btn1Up>: HandleUserMove(1) \n \
1119 <Btn1Up>: HandleUserMove(0) \n \
1120 <Btn1Motion>: AnimateUserMove() \n \
1121 <Btn3Motion>: HandlePV() \n \
1122 <Btn3Up>: PieceMenuPopup(menuB) \n \
1123 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1124 PieceMenuPopup(menuB) \n \
1125 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1126 PieceMenuPopup(menuW) \n \
1127 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1128 PieceMenuPopup(menuW) \n \
1129 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1130 PieceMenuPopup(menuB) \n";
1132 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1133 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1135 char ICSInputTranslations[] =
1136 "<Key>Up: UpKeyProc() \n "
1137 "<Key>Down: DownKeyProc() \n "
1138 "<Key>Return: EnterKeyProc() \n";
1140 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1141 // as the widget is destroyed before the up-click can call extend-end
1142 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1144 String xboardResources[] = {
1145 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1146 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1147 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1152 /* Max possible square size */
1153 #define MAXSQSIZE 256
1155 static int xpm_avail[MAXSQSIZE];
1157 #ifdef HAVE_DIR_STRUCT
1159 /* Extract piece size from filename */
1161 xpm_getsize(name, len, ext)
1172 if ((p=strchr(name, '.')) == NULL ||
1173 StrCaseCmp(p+1, ext) != 0)
1179 while (*p && isdigit(*p))
1186 /* Setup xpm_avail */
1188 xpm_getavail(dirname, ext)
1196 for (i=0; i<MAXSQSIZE; ++i)
1199 if (appData.debugMode)
1200 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1202 dir = opendir(dirname);
1205 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1206 programName, dirname);
1210 while ((ent=readdir(dir)) != NULL) {
1211 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1212 if (i > 0 && i < MAXSQSIZE)
1222 xpm_print_avail(fp, ext)
1228 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1229 for (i=1; i<MAXSQSIZE; ++i) {
1235 /* Return XPM piecesize closest to size */
1237 xpm_closest_to(dirname, size, ext)
1243 int sm_diff = MAXSQSIZE;
1247 xpm_getavail(dirname, ext);
1249 if (appData.debugMode)
1250 xpm_print_avail(stderr, ext);
1252 for (i=1; i<MAXSQSIZE; ++i) {
1255 diff = (diff<0) ? -diff : diff;
1256 if (diff < sm_diff) {
1264 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1270 #else /* !HAVE_DIR_STRUCT */
1271 /* If we are on a system without a DIR struct, we can't
1272 read the directory, so we can't collect a list of
1273 filenames, etc., so we can't do any size-fitting. */
1275 xpm_closest_to(dirname, size, ext)
1280 fprintf(stderr, _("\
1281 Warning: No DIR structure found on this system --\n\
1282 Unable to autosize for XPM/XIM pieces.\n\
1283 Please report this error to %s.\n\
1284 Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
1287 #endif /* HAVE_DIR_STRUCT */
1289 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1290 "magenta", "cyan", "white" };
1294 TextColors textColors[(int)NColorClasses];
1296 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1298 parse_color(str, which)
1302 char *p, buf[100], *d;
1305 if (strlen(str) > 99) /* watch bounds on buf */
1310 for (i=0; i<which; ++i) {
1317 /* Could be looking at something like:
1319 .. in which case we want to stop on a comma also */
1320 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1324 return -1; /* Use default for empty field */
1327 if (which == 2 || isdigit(*p))
1330 while (*p && isalpha(*p))
1335 for (i=0; i<8; ++i) {
1336 if (!StrCaseCmp(buf, cnames[i]))
1337 return which? (i+40) : (i+30);
1339 if (!StrCaseCmp(buf, "default")) return -1;
1341 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1346 parse_cpair(cc, str)
1350 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1351 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1356 /* bg and attr are optional */
1357 textColors[(int)cc].bg = parse_color(str, 1);
1358 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1359 textColors[(int)cc].attr = 0;
1365 /* Arrange to catch delete-window events */
1366 Atom wm_delete_window;
1368 CatchDeleteWindow(Widget w, String procname)
1371 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1372 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1373 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1380 XtSetArg(args[0], XtNiconic, False);
1381 XtSetValues(shellWidget, args, 1);
1383 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1386 //---------------------------------------------------------------------------------------------------------
1387 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1390 #define CW_USEDEFAULT (1<<31)
1391 #define ICS_TEXT_MENU_SIZE 90
1392 #define DEBUG_FILE "xboard.debug"
1393 #define SetCurrentDirectory chdir
1394 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1398 // these two must some day move to frontend.h, when they are implemented
1399 Boolean GameListIsUp();
1401 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1404 // front-end part of option handling
1406 // [HGM] This platform-dependent table provides the location for storing the color info
1407 extern char *crWhite, * crBlack;
1411 &appData.whitePieceColor,
1412 &appData.blackPieceColor,
1413 &appData.lightSquareColor,
1414 &appData.darkSquareColor,
1415 &appData.highlightSquareColor,
1416 &appData.premoveHighlightColor,
1417 &appData.lowTimeWarningColor,
1428 // [HGM] font: keep a font for each square size, even non-stndard ones
1429 #define NUM_SIZES 18
1430 #define MAX_SIZE 130
1431 Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1432 char *fontTable[NUM_FONTS][MAX_SIZE];
1435 ParseFont(char *name, int number)
1436 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1438 if(sscanf(name, "size%d:", &size)) {
1439 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1440 // defer processing it until we know if it matches our board size
1441 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1442 fontTable[number][size] = strdup(strchr(name, ':')+1);
1443 fontValid[number][size] = True;
1448 case 0: // CLOCK_FONT
1449 appData.clockFont = strdup(name);
1451 case 1: // MESSAGE_FONT
1452 appData.font = strdup(name);
1454 case 2: // COORD_FONT
1455 appData.coordFont = strdup(name);
1460 fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1465 { // only 2 fonts currently
1466 appData.clockFont = CLOCK_FONT_NAME;
1467 appData.coordFont = COORD_FONT_NAME;
1468 appData.font = DEFAULT_FONT_NAME;
1473 { // no-op, until we identify the code for this already in XBoard and move it here
1477 ParseColor(int n, char *name)
1478 { // in XBoard, just copy the color-name string
1479 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1483 ParseTextAttribs(ColorClass cc, char *s)
1485 (&appData.colorShout)[cc] = strdup(s);
1489 ParseBoardSize(void *addr, char *name)
1491 appData.boardSize = strdup(name);
1496 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1500 SetCommPortDefaults()
1501 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1504 // [HGM] args: these three cases taken out to stay in front-end
1506 SaveFontArg(FILE *f, ArgDescriptor *ad)
1509 int i, n = (int)(intptr_t)ad->argLoc;
1511 case 0: // CLOCK_FONT
1512 name = appData.clockFont;
1514 case 1: // MESSAGE_FONT
1515 name = appData.font;
1517 case 2: // COORD_FONT
1518 name = appData.coordFont;
1523 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1524 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1525 fontTable[n][squareSize] = strdup(name);
1526 fontValid[n][squareSize] = True;
1529 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1530 fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
1535 { // nothing to do, as the sounds are at all times represented by their text-string names already
1539 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1540 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1541 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1545 SaveColor(FILE *f, ArgDescriptor *ad)
1546 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1547 if(colorVariable[(int)(intptr_t)ad->argLoc])
1548 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1552 SaveBoardSize(FILE *f, char *name, void *addr)
1553 { // wrapper to shield back-end from BoardSize & sizeInfo
1554 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1558 ParseCommPortSettings(char *s)
1559 { // no such option in XBoard (yet)
1562 extern Widget engineOutputShell;
1565 GetActualPlacement(Widget wg, WindowPlacement *wp)
1575 XtSetArg(args[i], XtNx, &x); i++;
1576 XtSetArg(args[i], XtNy, &y); i++;
1577 XtSetArg(args[i], XtNwidth, &w); i++;
1578 XtSetArg(args[i], XtNheight, &h); i++;
1579 XtGetValues(wg, args, i);
1588 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1589 // In XBoard this will have to wait until awareness of window parameters is implemented
1590 GetActualPlacement(shellWidget, &wpMain);
1591 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1592 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1593 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1594 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1595 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1596 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1600 PrintCommPortSettings(FILE *f, char *name)
1601 { // This option does not exist in XBoard
1605 MySearchPath(char *installDir, char *name, char *fullname)
1606 { // just append installDir and name. Perhaps ExpandPath should be used here?
1607 name = ExpandPathName(name);
1608 if(name && name[0] == '/')
1609 safeStrCpy(fullname, name, MSG_SIZ );
1611 sprintf(fullname, "%s%c%s", installDir, '/', name);
1617 MyGetFullPathName(char *name, char *fullname)
1618 { // should use ExpandPath?
1619 name = ExpandPathName(name);
1620 safeStrCpy(fullname, name, MSG_SIZ );
1625 EnsureOnScreen(int *x, int *y, int minX, int minY)
1632 { // [HGM] args: allows testing if main window is realized from back-end
1633 return xBoardWindow != 0;
1637 PopUpStartupDialog()
1638 { // start menu not implemented in XBoard
1642 ConvertToLine(int argc, char **argv)
1644 static char line[128*1024], buf[1024];
1648 for(i=1; i<argc; i++)
1650 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1651 && argv[i][0] != '{' )
1652 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1654 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1655 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1658 line[strlen(line)-1] = NULLCHAR;
1662 //--------------------------------------------------------------------------------------------
1664 extern Boolean twoBoards, partnerUp;
1667 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1669 #define BoardSize int
1670 void InitDrawingSizes(BoardSize boardSize, int flags)
1671 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1672 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1674 XtGeometryResult gres;
1677 if(!formWidget) return;
1680 * Enable shell resizing.
1682 shellArgs[0].value = (XtArgVal) &w;
1683 shellArgs[1].value = (XtArgVal) &h;
1684 XtGetValues(shellWidget, shellArgs, 2);
1686 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1687 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1688 XtSetValues(shellWidget, &shellArgs[2], 4);
1690 XtSetArg(args[0], XtNdefaultDistance, &sep);
1691 XtGetValues(formWidget, args, 1);
1693 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1694 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1695 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1697 hOffset = boardWidth + 10;
1698 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1699 secondSegments[i] = gridSegments[i];
1700 secondSegments[i].x1 += hOffset;
1701 secondSegments[i].x2 += hOffset;
1704 XtSetArg(args[0], XtNwidth, boardWidth);
1705 XtSetArg(args[1], XtNheight, boardHeight);
1706 XtSetValues(boardWidget, args, 2);
1708 timerWidth = (boardWidth - sep) / 2;
1709 XtSetArg(args[0], XtNwidth, timerWidth);
1710 XtSetValues(whiteTimerWidget, args, 1);
1711 XtSetValues(blackTimerWidget, args, 1);
1713 XawFormDoLayout(formWidget, False);
1715 if (appData.titleInWindow) {
1717 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1718 XtSetArg(args[i], XtNheight, &h); i++;
1719 XtGetValues(titleWidget, args, i);
1721 w = boardWidth - 2*bor;
1723 XtSetArg(args[0], XtNwidth, &w);
1724 XtGetValues(menuBarWidget, args, 1);
1725 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1728 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1729 if (gres != XtGeometryYes && appData.debugMode) {
1731 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1732 programName, gres, w, h, wr, hr);
1736 XawFormDoLayout(formWidget, True);
1739 * Inhibit shell resizing.
1741 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1742 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1743 shellArgs[4].value = shellArgs[2].value = w;
1744 shellArgs[5].value = shellArgs[3].value = h;
1745 XtSetValues(shellWidget, &shellArgs[0], 6);
1747 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1750 for(i=0; i<4; i++) {
1752 for(p=0; p<=(int)WhiteKing; p++)
1753 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1754 if(gameInfo.variant == VariantShogi) {
1755 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1756 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1757 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1758 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1759 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1762 if(gameInfo.variant == VariantGothic) {
1763 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1766 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1767 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1768 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1771 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1772 for(p=0; p<=(int)WhiteKing; p++)
1773 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1774 if(gameInfo.variant == VariantShogi) {
1775 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1776 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1777 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1778 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1779 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1782 if(gameInfo.variant == VariantGothic) {
1783 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1786 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1787 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1788 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1793 for(i=0; i<2; i++) {
1795 for(p=0; p<=(int)WhiteKing; p++)
1796 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1797 if(gameInfo.variant == VariantShogi) {
1798 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1799 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1800 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1801 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1802 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1805 if(gameInfo.variant == VariantGothic) {
1806 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1809 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1810 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1811 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1821 void ParseIcsTextColors()
1822 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1823 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1824 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1825 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1826 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1827 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1828 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1829 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1830 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1831 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1832 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1834 if (appData.colorize) {
1836 _("%s: can't parse color names; disabling colorization\n"),
1839 appData.colorize = FALSE;
1844 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1845 XrmValue vFrom, vTo;
1846 int forceMono = False;
1848 if (!appData.monoMode) {
1849 vFrom.addr = (caddr_t) appData.lightSquareColor;
1850 vFrom.size = strlen(appData.lightSquareColor);
1851 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1852 if (vTo.addr == NULL) {
1853 appData.monoMode = True;
1856 lightSquareColor = *(Pixel *) vTo.addr;
1859 if (!appData.monoMode) {
1860 vFrom.addr = (caddr_t) appData.darkSquareColor;
1861 vFrom.size = strlen(appData.darkSquareColor);
1862 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1863 if (vTo.addr == NULL) {
1864 appData.monoMode = True;
1867 darkSquareColor = *(Pixel *) vTo.addr;
1870 if (!appData.monoMode) {
1871 vFrom.addr = (caddr_t) appData.whitePieceColor;
1872 vFrom.size = strlen(appData.whitePieceColor);
1873 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1874 if (vTo.addr == NULL) {
1875 appData.monoMode = True;
1878 whitePieceColor = *(Pixel *) vTo.addr;
1881 if (!appData.monoMode) {
1882 vFrom.addr = (caddr_t) appData.blackPieceColor;
1883 vFrom.size = strlen(appData.blackPieceColor);
1884 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1885 if (vTo.addr == NULL) {
1886 appData.monoMode = True;
1889 blackPieceColor = *(Pixel *) vTo.addr;
1893 if (!appData.monoMode) {
1894 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1895 vFrom.size = strlen(appData.highlightSquareColor);
1896 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1897 if (vTo.addr == NULL) {
1898 appData.monoMode = True;
1901 highlightSquareColor = *(Pixel *) vTo.addr;
1905 if (!appData.monoMode) {
1906 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1907 vFrom.size = strlen(appData.premoveHighlightColor);
1908 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1909 if (vTo.addr == NULL) {
1910 appData.monoMode = True;
1913 premoveHighlightColor = *(Pixel *) vTo.addr;
1921 { // [HGM] taken out of main
1923 if (appData.monoMode && // [HGM] no sense to go on to certain doom
1924 (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
1925 appData.bitmapDirectory = DEF_BITMAP_DIR;
1927 if (appData.bitmapDirectory[0] != NULLCHAR) {
1931 CreateXPMBoard(appData.liteBackTextureFile, 1);
1932 CreateXPMBoard(appData.darkBackTextureFile, 0);
1936 /* Create regular pieces */
1937 if (!useImages) CreatePieces();
1946 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1947 XSetWindowAttributes window_attributes;
1949 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1950 XrmValue vFrom, vTo;
1951 XtGeometryResult gres;
1954 int forceMono = False;
1956 srandom(time(0)); // [HGM] book: make random truly random
1958 setbuf(stdout, NULL);
1959 setbuf(stderr, NULL);
1962 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1963 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1967 programName = strrchr(argv[0], '/');
1968 if (programName == NULL)
1969 programName = argv[0];
1974 XtSetLanguageProc(NULL, NULL, NULL);
1975 bindtextdomain(PACKAGE, LOCALEDIR);
1976 textdomain(PACKAGE);
1980 XtAppInitialize(&appContext, "XBoard", shellOptions,
1981 XtNumber(shellOptions),
1982 &argc, argv, xboardResources, NULL, 0);
1983 appData.boardSize = "";
1984 InitAppData(ConvertToLine(argc, argv));
1986 if (p == NULL) p = "/tmp";
1987 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1988 gameCopyFilename = (char*) malloc(i);
1989 gamePasteFilename = (char*) malloc(i);
1990 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1991 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1993 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1994 clientResources, XtNumber(clientResources),
1997 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1998 static char buf[MSG_SIZ];
1999 EscapeExpand(buf, appData.firstInitString);
2000 appData.firstInitString = strdup(buf);
2001 EscapeExpand(buf, appData.secondInitString);
2002 appData.secondInitString = strdup(buf);
2003 EscapeExpand(buf, appData.firstComputerString);
2004 appData.firstComputerString = strdup(buf);
2005 EscapeExpand(buf, appData.secondComputerString);
2006 appData.secondComputerString = strdup(buf);
2009 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2012 if (chdir(chessDir) != 0) {
2013 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2019 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2020 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2021 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2022 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2025 setbuf(debugFP, NULL);
2029 if (appData.debugMode) {
2030 fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
2034 /* [HGM,HR] make sure board size is acceptable */
2035 if(appData.NrFiles > BOARD_FILES ||
2036 appData.NrRanks > BOARD_RANKS )
2037 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2040 /* This feature does not work; animation needs a rewrite */
2041 appData.highlightDragging = FALSE;
2045 xDisplay = XtDisplay(shellWidget);
2046 xScreen = DefaultScreen(xDisplay);
2047 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2049 gameInfo.variant = StringToVariant(appData.variant);
2050 InitPosition(FALSE);
2053 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2055 if (isdigit(appData.boardSize[0])) {
2056 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2057 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2058 &fontPxlSize, &smallLayout, &tinyLayout);
2060 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2061 programName, appData.boardSize);
2065 /* Find some defaults; use the nearest known size */
2066 SizeDefaults *szd, *nearest;
2067 int distance = 99999;
2068 nearest = szd = sizeDefaults;
2069 while (szd->name != NULL) {
2070 if (abs(szd->squareSize - squareSize) < distance) {
2072 distance = abs(szd->squareSize - squareSize);
2073 if (distance == 0) break;
2077 if (i < 2) lineGap = nearest->lineGap;
2078 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2079 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2080 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2081 if (i < 6) smallLayout = nearest->smallLayout;
2082 if (i < 7) tinyLayout = nearest->tinyLayout;
2085 SizeDefaults *szd = sizeDefaults;
2086 if (*appData.boardSize == NULLCHAR) {
2087 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2088 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2091 if (szd->name == NULL) szd--;
2092 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2094 while (szd->name != NULL &&
2095 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2096 if (szd->name == NULL) {
2097 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2098 programName, appData.boardSize);
2102 squareSize = szd->squareSize;
2103 lineGap = szd->lineGap;
2104 clockFontPxlSize = szd->clockFontPxlSize;
2105 coordFontPxlSize = szd->coordFontPxlSize;
2106 fontPxlSize = szd->fontPxlSize;
2107 smallLayout = szd->smallLayout;
2108 tinyLayout = szd->tinyLayout;
2109 // [HGM] font: use defaults from settings file if available and not overruled
2111 if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2112 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2113 if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2114 appData.font = fontTable[MESSAGE_FONT][squareSize];
2115 if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2116 appData.coordFont = fontTable[COORD_FONT][squareSize];
2118 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2119 if (strlen(appData.pixmapDirectory) > 0) {
2120 p = ExpandPathName(appData.pixmapDirectory);
2122 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2123 appData.pixmapDirectory);
2126 if (appData.debugMode) {
2127 fprintf(stderr, _("\
2128 XBoard square size (hint): %d\n\
2129 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2131 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2132 if (appData.debugMode) {
2133 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2136 defaultLineGap = lineGap;
2137 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2139 /* [HR] height treated separately (hacked) */
2140 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2141 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2142 if (appData.showJail == 1) {
2143 /* Jail on top and bottom */
2144 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2145 XtSetArg(boardArgs[2], XtNheight,
2146 boardHeight + 2*(lineGap + squareSize));
2147 } else if (appData.showJail == 2) {
2149 XtSetArg(boardArgs[1], XtNwidth,
2150 boardWidth + 2*(lineGap + squareSize));
2151 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2154 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2155 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2159 * Determine what fonts to use.
2162 appData.font = InsertPxlSize(appData.font, fontPxlSize);
2163 appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
2164 appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
2165 fontSet = CreateFontSet(appData.font);
2166 clockFontSet = CreateFontSet(appData.clockFont);
2168 /* For the coordFont, use the 0th font of the fontset. */
2169 XFontSet coordFontSet = CreateFontSet(appData.coordFont);
2170 XFontStruct **font_struct_list;
2171 char **font_name_list;
2172 XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
2173 coordFontID = XLoadFont(xDisplay, font_name_list[0]);
2174 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2177 appData.font = FindFont(appData.font, fontPxlSize);
2178 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2179 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2180 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2181 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2182 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2183 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2185 countFontID = coordFontID; // [HGM] holdings
2186 countFontStruct = coordFontStruct;
2188 xdb = XtDatabase(xDisplay);
2190 XrmPutLineResource(&xdb, "*international: True");
2191 vTo.size = sizeof(XFontSet);
2192 vTo.addr = (XtPointer) &fontSet;
2193 XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
2195 XrmPutStringResource(&xdb, "*font", appData.font);
2199 * Detect if there are not enough colors available and adapt.
2201 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2202 appData.monoMode = True;
2205 forceMono = MakeColors();
2208 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2210 appData.monoMode = True;
2213 if (appData.lowTimeWarning && !appData.monoMode) {
2214 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2215 vFrom.size = strlen(appData.lowTimeWarningColor);
2216 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2217 if (vTo.addr == NULL)
2218 appData.monoMode = True;
2220 lowTimeWarningColor = *(Pixel *) vTo.addr;
2223 if (appData.monoMode && appData.debugMode) {
2224 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2225 (unsigned long) XWhitePixel(xDisplay, xScreen),
2226 (unsigned long) XBlackPixel(xDisplay, xScreen));
2229 ParseIcsTextColors();
2230 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2231 textColors[ColorNone].attr = 0;
2233 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2239 layoutName = "tinyLayout";
2240 } else if (smallLayout) {
2241 layoutName = "smallLayout";
2243 layoutName = "normalLayout";
2245 /* Outer layoutWidget is there only to provide a name for use in
2246 resources that depend on the layout style */
2248 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2249 layoutArgs, XtNumber(layoutArgs));
2251 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2252 formArgs, XtNumber(formArgs));
2253 XtSetArg(args[0], XtNdefaultDistance, &sep);
2254 XtGetValues(formWidget, args, 1);
2257 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2258 XtSetArg(args[0], XtNtop, XtChainTop);
2259 XtSetArg(args[1], XtNbottom, XtChainTop);
2260 XtSetArg(args[2], XtNright, XtChainLeft);
2261 XtSetValues(menuBarWidget, args, 3);
2263 widgetList[j++] = whiteTimerWidget =
2264 XtCreateWidget("whiteTime", labelWidgetClass,
2265 formWidget, timerArgs, XtNumber(timerArgs));
2267 XtSetArg(args[0], XtNfontSet, clockFontSet);
2269 XtSetArg(args[0], XtNfont, clockFontStruct);
2271 XtSetArg(args[1], XtNtop, XtChainTop);
2272 XtSetArg(args[2], XtNbottom, XtChainTop);
2273 XtSetValues(whiteTimerWidget, args, 3);
2275 widgetList[j++] = blackTimerWidget =
2276 XtCreateWidget("blackTime", labelWidgetClass,
2277 formWidget, timerArgs, XtNumber(timerArgs));
2279 XtSetArg(args[0], XtNfontSet, clockFontSet);
2281 XtSetArg(args[0], XtNfont, clockFontStruct);
2283 XtSetArg(args[1], XtNtop, XtChainTop);
2284 XtSetArg(args[2], XtNbottom, XtChainTop);
2285 XtSetValues(blackTimerWidget, args, 3);
2287 if (appData.titleInWindow) {
2288 widgetList[j++] = titleWidget =
2289 XtCreateWidget("title", labelWidgetClass, formWidget,
2290 titleArgs, XtNumber(titleArgs));
2291 XtSetArg(args[0], XtNtop, XtChainTop);
2292 XtSetArg(args[1], XtNbottom, XtChainTop);
2293 XtSetValues(titleWidget, args, 2);
2296 if (appData.showButtonBar) {
2297 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2298 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2299 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2300 XtSetArg(args[2], XtNtop, XtChainTop);
2301 XtSetArg(args[3], XtNbottom, XtChainTop);
2302 XtSetValues(buttonBarWidget, args, 4);
2305 widgetList[j++] = messageWidget =
2306 XtCreateWidget("message", labelWidgetClass, formWidget,
2307 messageArgs, XtNumber(messageArgs));
2308 XtSetArg(args[0], XtNtop, XtChainTop);
2309 XtSetArg(args[1], XtNbottom, XtChainTop);
2310 XtSetValues(messageWidget, args, 2);
2312 widgetList[j++] = boardWidget =
2313 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2314 XtNumber(boardArgs));
2316 XtManageChildren(widgetList, j);
2318 timerWidth = (boardWidth - sep) / 2;
2319 XtSetArg(args[0], XtNwidth, timerWidth);
2320 XtSetValues(whiteTimerWidget, args, 1);
2321 XtSetValues(blackTimerWidget, args, 1);
2323 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2324 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2325 XtGetValues(whiteTimerWidget, args, 2);
2327 if (appData.showButtonBar) {
2328 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2329 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2330 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2334 * formWidget uses these constraints but they are stored
2338 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2339 XtSetValues(menuBarWidget, args, i);
2340 if (appData.titleInWindow) {
2343 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2344 XtSetValues(whiteTimerWidget, args, i);
2346 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2347 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2348 XtSetValues(blackTimerWidget, args, i);
2350 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2351 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2352 XtSetValues(titleWidget, args, i);
2354 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2355 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2356 XtSetValues(messageWidget, args, i);
2357 if (appData.showButtonBar) {
2359 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2360 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2361 XtSetValues(buttonBarWidget, args, i);
2365 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2366 XtSetValues(whiteTimerWidget, args, i);
2368 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2369 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2370 XtSetValues(blackTimerWidget, args, i);
2372 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2373 XtSetValues(titleWidget, args, i);
2375 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2376 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2377 XtSetValues(messageWidget, args, i);
2378 if (appData.showButtonBar) {
2380 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2381 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2382 XtSetValues(buttonBarWidget, args, i);
2387 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2388 XtSetValues(whiteTimerWidget, args, i);
2390 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2391 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2392 XtSetValues(blackTimerWidget, args, i);
2394 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2395 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2396 XtSetValues(messageWidget, args, i);
2397 if (appData.showButtonBar) {
2399 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2400 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2401 XtSetValues(buttonBarWidget, args, i);
2405 XtSetArg(args[0], XtNfromVert, messageWidget);
2406 XtSetArg(args[1], XtNtop, XtChainTop);
2407 XtSetArg(args[2], XtNbottom, XtChainBottom);
2408 XtSetArg(args[3], XtNleft, XtChainLeft);
2409 XtSetArg(args[4], XtNright, XtChainRight);
2410 XtSetValues(boardWidget, args, 5);
2412 XtRealizeWidget(shellWidget);
2415 XtSetArg(args[0], XtNx, wpMain.x);
2416 XtSetArg(args[1], XtNy, wpMain.y);
2417 XtSetValues(shellWidget, args, 2);
2421 * Correct the width of the message and title widgets.
2422 * It is not known why some systems need the extra fudge term.
2423 * The value "2" is probably larger than needed.
2425 XawFormDoLayout(formWidget, False);
2427 #define WIDTH_FUDGE 2
2429 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2430 XtSetArg(args[i], XtNheight, &h); i++;
2431 XtGetValues(messageWidget, args, i);
2432 if (appData.showButtonBar) {
2434 XtSetArg(args[i], XtNwidth, &w); i++;
2435 XtGetValues(buttonBarWidget, args, i);
2436 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2438 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2441 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2442 if (gres != XtGeometryYes && appData.debugMode) {
2443 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2444 programName, gres, w, h, wr, hr);
2447 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2448 /* The size used for the child widget in layout lags one resize behind
2449 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2451 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2452 if (gres != XtGeometryYes && appData.debugMode) {
2453 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2454 programName, gres, w, h, wr, hr);
2457 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2458 XtSetArg(args[1], XtNright, XtChainRight);
2459 XtSetValues(messageWidget, args, 2);
2461 if (appData.titleInWindow) {
2463 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2464 XtSetArg(args[i], XtNheight, &h); i++;
2465 XtGetValues(titleWidget, args, i);
2467 w = boardWidth - 2*bor;
2469 XtSetArg(args[0], XtNwidth, &w);
2470 XtGetValues(menuBarWidget, args, 1);
2471 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2474 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2475 if (gres != XtGeometryYes && appData.debugMode) {
2477 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2478 programName, gres, w, h, wr, hr);
2481 XawFormDoLayout(formWidget, True);
2483 xBoardWindow = XtWindow(boardWidget);
2485 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2486 // not need to go into InitDrawingSizes().
2490 * Create X checkmark bitmap and initialize option menu checks.
2492 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2493 checkmark_bits, checkmark_width, checkmark_height);
2494 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2495 #ifndef OPTIONSDIALOG
2496 if (appData.alwaysPromoteToQueen) {
2497 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2500 if (appData.animateDragging) {
2501 XtSetValues(XtNameToWidget(menuBarWidget,
2502 "menuOptions.Animate Dragging"),
2505 if (appData.animate) {
2506 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2509 if (appData.autoCallFlag) {
2510 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2513 if (appData.autoFlipView) {
2514 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2517 if (appData.blindfold) {
2518 XtSetValues(XtNameToWidget(menuBarWidget,
2519 "menuOptions.Blindfold"), args, 1);
2521 if (appData.flashCount > 0) {
2522 XtSetValues(XtNameToWidget(menuBarWidget,
2523 "menuOptions.Flash Moves"),
2527 if (appData.highlightDragging) {
2528 XtSetValues(XtNameToWidget(menuBarWidget,
2529 "menuOptions.Highlight Dragging"),
2533 if (appData.highlightLastMove) {
2534 XtSetValues(XtNameToWidget(menuBarWidget,
2535 "menuOptions.Highlight Last Move"),
2538 if (appData.highlightMoveWithArrow) {
2539 XtSetValues(XtNameToWidget(menuBarWidget,
2540 "menuOptions.Arrow"),
2543 // if (appData.icsAlarm) {
2544 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2547 if (appData.ringBellAfterMoves) {
2548 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2551 if (appData.oneClick) {
2552 XtSetValues(XtNameToWidget(menuBarWidget,
2553 "menuOptions.OneClick"), args, 1);
2555 if (appData.periodicUpdates) {
2556 XtSetValues(XtNameToWidget(menuBarWidget,
2557 "menuOptions.Periodic Updates"), args, 1);
2559 if (appData.ponderNextMove) {
2560 XtSetValues(XtNameToWidget(menuBarWidget,
2561 "menuOptions.Ponder Next Move"), args, 1);
2563 if (appData.popupExitMessage) {
2564 XtSetValues(XtNameToWidget(menuBarWidget,
2565 "menuOptions.Popup Exit Message"), args, 1);
2567 if (appData.popupMoveErrors) {
2568 XtSetValues(XtNameToWidget(menuBarWidget,
2569 "menuOptions.Popup Move Errors"), args, 1);
2571 // if (appData.premove) {
2572 // XtSetValues(XtNameToWidget(menuBarWidget,
2573 // "menuOptions.Premove"), args, 1);
2575 if (appData.showCoords) {
2576 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2579 if (appData.hideThinkingFromHuman) {
2580 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2583 if (appData.testLegality) {
2584 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2588 if (saveSettingsOnExit) {
2589 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2596 ReadBitmap(&wIconPixmap, "icon_white.bm",
2597 icon_white_bits, icon_white_width, icon_white_height);
2598 ReadBitmap(&bIconPixmap, "icon_black.bm",
2599 icon_black_bits, icon_black_width, icon_black_height);
2600 iconPixmap = wIconPixmap;
2602 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2603 XtSetValues(shellWidget, args, i);
2606 * Create a cursor for the board widget.
2608 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2609 XChangeWindowAttributes(xDisplay, xBoardWindow,
2610 CWCursor, &window_attributes);
2613 * Inhibit shell resizing.
2615 shellArgs[0].value = (XtArgVal) &w;
2616 shellArgs[1].value = (XtArgVal) &h;
2617 XtGetValues(shellWidget, shellArgs, 2);
2618 shellArgs[4].value = shellArgs[2].value = w;
2619 shellArgs[5].value = shellArgs[3].value = h;
2620 XtSetValues(shellWidget, &shellArgs[2], 4);
2621 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2622 marginH = h - boardHeight;
2624 CatchDeleteWindow(shellWidget, "QuitProc");
2632 if (appData.animate || appData.animateDragging)
2635 XtAugmentTranslations(formWidget,
2636 XtParseTranslationTable(globalTranslations));
2637 XtAugmentTranslations(boardWidget,
2638 XtParseTranslationTable(boardTranslations));
2639 XtAugmentTranslations(whiteTimerWidget,
2640 XtParseTranslationTable(whiteTranslations));
2641 XtAugmentTranslations(blackTimerWidget,
2642 XtParseTranslationTable(blackTranslations));
2644 /* Why is the following needed on some versions of X instead
2645 * of a translation? */
2646 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2647 (XtEventHandler) EventProc, NULL);
2649 XtAddEventHandler(formWidget, KeyPressMask, False,
2650 (XtEventHandler) MoveTypeInProc, NULL);
2652 /* [AS] Restore layout */
2653 if( wpMoveHistory.visible ) {
2657 if( wpEvalGraph.visible )
2662 if( wpEngineOutput.visible ) {
2663 EngineOutputPopUp();
2668 if (errorExitStatus == -1) {
2669 if (appData.icsActive) {
2670 /* We now wait until we see "login:" from the ICS before
2671 sending the logon script (problems with timestamp otherwise) */
2672 /*ICSInitScript();*/
2673 if (appData.icsInputBox) ICSInputBoxPopUp();
2677 signal(SIGWINCH, TermSizeSigHandler);
2679 signal(SIGINT, IntSigHandler);
2680 signal(SIGTERM, IntSigHandler);
2681 if (*appData.cmailGameName != NULLCHAR) {
2682 signal(SIGUSR1, CmailSigHandler);
2685 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2687 // XtSetKeyboardFocus(shellWidget, formWidget);
2688 XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
2690 XtAppMainLoop(appContext);
2691 if (appData.debugMode) fclose(debugFP); // [DM] debug
2698 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2699 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2701 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2702 unlink(gameCopyFilename);
2703 unlink(gamePasteFilename);
2706 RETSIGTYPE TermSizeSigHandler(int sig)
2719 CmailSigHandler(sig)
2725 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2727 /* Activate call-back function CmailSigHandlerCallBack() */
2728 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2730 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2734 CmailSigHandlerCallBack(isr, closure, message, count, error)
2742 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2744 /**** end signal code ****/
2750 /* try to open the icsLogon script, either in the location given
2751 * or in the users HOME directory
2758 f = fopen(appData.icsLogon, "r");
2761 homedir = getenv("HOME");
2762 if (homedir != NULL)
2764 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2765 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2766 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2767 f = fopen(buf, "r");
2772 ProcessICSInitScript(f);
2774 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2797 if (!menuBarWidget) return;
2798 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2800 DisplayError("menuEdit.Revert", 0);
2802 XtSetSensitive(w, !grey);
2804 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2806 DisplayError("menuEdit.Annotate", 0);
2808 XtSetSensitive(w, !grey);
2813 SetMenuEnables(enab)
2817 if (!menuBarWidget) return;
2818 while (enab->name != NULL) {
2819 w = XtNameToWidget(menuBarWidget, enab->name);
2821 DisplayError(enab->name, 0);
2823 XtSetSensitive(w, enab->value);
2829 Enables icsEnables[] = {
2830 { "menuFile.Mail Move", False },
2831 { "menuFile.Reload CMail Message", False },
2832 { "menuMode.Machine Black", False },
2833 { "menuMode.Machine White", False },
2834 { "menuMode.Analysis Mode", False },
2835 { "menuMode.Analyze File", False },
2836 { "menuMode.Two Machines", False },
2837 { "menuMode.Machine Match", False },
2839 { "menuEngine.Hint", False },
2840 { "menuEngine.Book", False },
2841 { "menuEngine.Move Now", False },
2842 #ifndef OPTIONSDIALOG
2843 { "menuOptions.Periodic Updates", False },
2844 { "menuOptions.Hide Thinking", False },
2845 { "menuOptions.Ponder Next Move", False },
2848 { "menuEngine.Engine #1 Settings", False },
2849 { "menuEngine.Engine #2 Settings", False },
2850 { "menuEngine.Load Engine", False },
2851 { "menuEdit.Annotate", False },
2852 { "menuOptions.Match", False },
2856 Enables ncpEnables[] = {
2857 { "menuFile.Mail Move", False },
2858 { "menuFile.Reload CMail Message", False },
2859 { "menuMode.Machine White", False },
2860 { "menuMode.Machine Black", False },
2861 { "menuMode.Analysis Mode", False },
2862 { "menuMode.Analyze File", False },
2863 { "menuMode.Two Machines", False },
2864 { "menuMode.Machine Match", False },
2865 { "menuMode.ICS Client", False },
2866 { "menuView.ICStex", False },
2867 { "menuView.ICS Input Box", False },
2868 { "Action", False },
2869 { "menuEdit.Revert", False },
2870 { "menuEdit.Annotate", False },
2871 { "menuEngine.Engine #1 Settings", False },
2872 { "menuEngine.Engine #2 Settings", False },
2873 { "menuEngine.Move Now", False },
2874 { "menuEngine.Retract Move", False },
2875 { "menuOptions.ICS", False },
2876 #ifndef OPTIONSDIALOG
2877 { "menuOptions.Auto Flag", False },
2878 { "menuOptions.Auto Flip View", False },
2879 // { "menuOptions.ICS Alarm", False },
2880 { "menuOptions.Move Sound", False },
2881 { "menuOptions.Hide Thinking", False },
2882 { "menuOptions.Periodic Updates", False },
2883 { "menuOptions.Ponder Next Move", False },
2885 { "menuEngine.Hint", False },
2886 { "menuEngine.Book", False },
2890 Enables gnuEnables[] = {
2891 { "menuMode.ICS Client", False },
2892 { "menuView.ICStex", False },
2893 { "menuView.ICS Input Box", False },
2894 { "menuAction.Accept", False },
2895 { "menuAction.Decline", False },
2896 { "menuAction.Rematch", False },
2897 { "menuAction.Adjourn", False },
2898 { "menuAction.Stop Examining", False },
2899 { "menuAction.Stop Observing", False },
2900 { "menuAction.Upload to Examine", False },
2901 { "menuEdit.Revert", False },
2902 { "menuEdit.Annotate", False },
2903 { "menuOptions.ICS", False },
2905 /* The next two options rely on SetCmailMode being called *after* */
2906 /* SetGNUMode so that when GNU is being used to give hints these */
2907 /* menu options are still available */
2909 { "menuFile.Mail Move", False },
2910 { "menuFile.Reload CMail Message", False },
2911 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
2912 { "menuMode.Machine White", True },
2913 { "menuMode.Machine Black", True },
2914 { "menuMode.Analysis Mode", True },
2915 { "menuMode.Analyze File", True },
2916 { "menuMode.Two Machines", True },
2917 { "menuMode.Machine Match", True },
2918 { "menuEngine.Engine #1 Settings", True },
2919 { "menuEngine.Engine #2 Settings", True },
2920 { "menuEngine.Hint", True },
2921 { "menuEngine.Book", True },
2922 { "menuEngine.Move Now", True },
2923 { "menuEngine.Retract Move", True },
2928 Enables cmailEnables[] = {
2930 { "menuAction.Call Flag", False },
2931 { "menuAction.Draw", True },
2932 { "menuAction.Adjourn", False },
2933 { "menuAction.Abort", False },
2934 { "menuAction.Stop Observing", False },
2935 { "menuAction.Stop Examining", False },
2936 { "menuFile.Mail Move", True },
2937 { "menuFile.Reload CMail Message", True },
2941 Enables trainingOnEnables[] = {
2942 { "menuMode.Edit Comment", False },
2943 { "menuMode.Pause", False },
2944 { "menuEdit.Forward", False },
2945 { "menuEdit.Backward", False },
2946 { "menuEdit.Forward to End", False },
2947 { "menuEdit.Back to Start", False },
2948 { "menuEngine.Move Now", False },
2949 { "menuEdit.Truncate Game", False },
2953 Enables trainingOffEnables[] = {
2954 { "menuMode.Edit Comment", True },
2955 { "menuMode.Pause", True },
2956 { "menuEdit.Forward", True },
2957 { "menuEdit.Backward", True },
2958 { "menuEdit.Forward to End", True },
2959 { "menuEdit.Back to Start", True },
2960 { "menuEngine.Move Now", True },
2961 { "menuEdit.Truncate Game", True },
2965 Enables machineThinkingEnables[] = {
2966 { "menuFile.Load Game", False },
2967 // { "menuFile.Load Next Game", False },
2968 // { "menuFile.Load Previous Game", False },
2969 // { "menuFile.Reload Same Game", False },
2970 { "menuEdit.Paste Game", False },
2971 { "menuFile.Load Position", False },
2972 // { "menuFile.Load Next Position", False },
2973 // { "menuFile.Load Previous Position", False },
2974 // { "menuFile.Reload Same Position", False },
2975 { "menuEdit.Paste Position", False },
2976 { "menuMode.Machine White", False },
2977 { "menuMode.Machine Black", False },
2978 { "menuMode.Two Machines", False },
2979 // { "menuMode.Machine Match", False },
2980 { "menuEngine.Retract Move", False },
2984 Enables userThinkingEnables[] = {
2985 { "menuFile.Load Game", True },
2986 // { "menuFile.Load Next Game", True },
2987 // { "menuFile.Load Previous Game", True },
2988 // { "menuFile.Reload Same Game", True },
2989 { "menuEdit.Paste Game", True },
2990 { "menuFile.Load Position", True },
2991 // { "menuFile.Load Next Position", True },
2992 // { "menuFile.Load Previous Position", True },
2993 // { "menuFile.Reload Same Position", True },
2994 { "menuEdit.Paste Position", True },
2995 { "menuMode.Machine White", True },
2996 { "menuMode.Machine Black", True },
2997 { "menuMode.Two Machines", True },
2998 // { "menuMode.Machine Match", True },
2999 { "menuEngine.Retract Move", True },
3005 SetMenuEnables(icsEnables);
3008 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
3009 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3010 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
3018 SetMenuEnables(ncpEnables);
3024 SetMenuEnables(gnuEnables);
3030 SetMenuEnables(cmailEnables);
3036 SetMenuEnables(trainingOnEnables);
3037 if (appData.showButtonBar) {
3038 XtSetSensitive(buttonBarWidget, False);
3044 SetTrainingModeOff()
3046 SetMenuEnables(trainingOffEnables);
3047 if (appData.showButtonBar) {
3048 XtSetSensitive(buttonBarWidget, True);
3053 SetUserThinkingEnables()
3055 if (appData.noChessProgram) return;
3056 SetMenuEnables(userThinkingEnables);
3060 SetMachineThinkingEnables()
3062 if (appData.noChessProgram) return;
3063 SetMenuEnables(machineThinkingEnables);
3065 case MachinePlaysBlack:
3066 case MachinePlaysWhite:
3067 case TwoMachinesPlay:
3068 XtSetSensitive(XtNameToWidget(menuBarWidget,
3069 ModeToWidgetName(gameMode)), True);
3076 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
3077 #define HISTORY_SIZE 64
3078 static char *history[HISTORY_SIZE];
3079 int histIn = 0, histP = 0;
3082 SaveInHistory(char *cmd)
3084 if (history[histIn] != NULL) {
3085 free(history[histIn]);
3086 history[histIn] = NULL;
3088 if (*cmd == NULLCHAR) return;
3089 history[histIn] = StrSave(cmd);
3090 histIn = (histIn + 1) % HISTORY_SIZE;
3091 if (history[histIn] != NULL) {
3092 free(history[histIn]);
3093 history[histIn] = NULL;
3099 PrevInHistory(char *cmd)
3102 if (histP == histIn) {
3103 if (history[histIn] != NULL) free(history[histIn]);
3104 history[histIn] = StrSave(cmd);
3106 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3107 if (newhp == histIn || history[newhp] == NULL) return NULL;
3109 return history[histP];
3115 if (histP == histIn) return NULL;
3116 histP = (histP + 1) % HISTORY_SIZE;
3117 return history[histP];
3119 // end of borrowed code
3121 #define Abs(n) ((n)<0 ? -(n) : (n))
3125 InsertPxlSize(pattern, targetPxlSize)
3129 char *base_fnt_lst, strInt[12], *p, *q;
3130 int alternatives, i, len, strIntLen;
3133 * Replace the "*" (if present) in the pixel-size slot of each
3134 * alternative with the targetPxlSize.
3138 while ((p = strchr(p, ',')) != NULL) {
3142 snprintf(strInt, sizeof(strInt), "%d", targetPxlSize);
3143 strIntLen = strlen(strInt);
3144 base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1);
3148 while (alternatives--) {
3149 char *comma = strchr(p, ',');
3150 for (i=0; i<14; i++) {
3151 char *hyphen = strchr(p, '-');
3153 if (comma && hyphen > comma) break;
3154 len = hyphen + 1 - p;
3155 if (i == 7 && *p == '*' && len == 2) {
3157 memcpy(q, strInt, strIntLen);
3167 len = comma + 1 - p;
3174 return base_fnt_lst;
3178 CreateFontSet(base_fnt_lst)
3182 char **missing_list;
3186 fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
3187 &missing_list, &missing_count, &def_string);
3188 if (appData.debugMode) {
3190 XFontStruct **font_struct_list;
3191 char **font_name_list;
3192 fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
3194 fprintf(debugFP, " got list %s, locale %s\n",
3195 XBaseFontNameListOfFontSet(fntSet),
3196 XLocaleOfFontSet(fntSet));
3197 count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
3198 for (i = 0; i < count; i++) {
3199 fprintf(debugFP, " got charset %s\n", font_name_list[i]);
3202 for (i = 0; i < missing_count; i++) {
3203 fprintf(debugFP, " missing charset %s\n", missing_list[i]);
3206 if (fntSet == NULL) {
3207 fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
3212 #else // not ENABLE_NLS
3214 * Find a font that matches "pattern" that is as close as
3215 * possible to the targetPxlSize. Prefer fonts that are k
3216 * pixels smaller to fonts that are k pixels larger. The
3217 * pattern must be in the X Consortium standard format,
3218 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3219 * The return value should be freed with XtFree when no
3223 FindFont(pattern, targetPxlSize)
3227 char **fonts, *p, *best, *scalable, *scalableTail;
3228 int i, j, nfonts, minerr, err, pxlSize;
3230 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3232 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3233 programName, pattern);
3240 for (i=0; i<nfonts; i++) {
3243 if (*p != '-') continue;
3245 if (*p == NULLCHAR) break;
3246 if (*p++ == '-') j++;
3248 if (j < 7) continue;
3251 scalable = fonts[i];
3254 err = pxlSize - targetPxlSize;
3255 if (Abs(err) < Abs(minerr) ||
3256 (minerr > 0 && err < 0 && -err == minerr)) {
3262 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3263 /* If the error is too big and there is a scalable font,
3264 use the scalable font. */
3265 int headlen = scalableTail - scalable;
3266 p = (char *) XtMalloc(strlen(scalable) + 10);
3267 while (isdigit(*scalableTail)) scalableTail++;
3268 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3270 p = (char *) XtMalloc(strlen(best) + 2);
3271 safeStrCpy(p, best, strlen(best)+1 );
3273 if (appData.debugMode) {
3274 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3275 pattern, targetPxlSize, p);
3277 XFreeFontNames(fonts);
3283 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3284 // must be called before all non-first callse to CreateGCs()
3285 XtReleaseGC(shellWidget, highlineGC);
3286 XtReleaseGC(shellWidget, lightSquareGC);
3287 XtReleaseGC(shellWidget, darkSquareGC);
3288 XtReleaseGC(shellWidget, lineGC);
3289 if (appData.monoMode) {
3290 if (DefaultDepth(xDisplay, xScreen) == 1) {
3291 XtReleaseGC(shellWidget, wbPieceGC);
3293 XtReleaseGC(shellWidget, bwPieceGC);
3296 XtReleaseGC(shellWidget, prelineGC);
3297 XtReleaseGC(shellWidget, jailSquareGC);
3298 XtReleaseGC(shellWidget, wdPieceGC);
3299 XtReleaseGC(shellWidget, wlPieceGC);
3300 XtReleaseGC(shellWidget, wjPieceGC);
3301 XtReleaseGC(shellWidget, bdPieceGC);
3302 XtReleaseGC(shellWidget, blPieceGC);
3303 XtReleaseGC(shellWidget, bjPieceGC);
3307 void CreateGCs(int redo)
3309 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3310 | GCBackground | GCFunction | GCPlaneMask;
3311 XGCValues gc_values;
3314 gc_values.plane_mask = AllPlanes;
3315 gc_values.line_width = lineGap;
3316 gc_values.line_style = LineSolid;
3317 gc_values.function = GXcopy;
3320 DeleteGCs(); // called a second time; clean up old GCs first
3321 } else { // [HGM] grid and font GCs created on first call only
3322 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3323 gc_values.background = XWhitePixel(xDisplay, xScreen);
3324 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3325 XSetFont(xDisplay, coordGC, coordFontID);
3327 // [HGM] make font for holdings counts (white on black)
3328 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3329 gc_values.background = XBlackPixel(xDisplay, xScreen);
3330 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3331 XSetFont(xDisplay, countGC, countFontID);
3333 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3334 gc_values.background = XBlackPixel(xDisplay, xScreen);
3335 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3337 if (appData.monoMode) {
3338 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3339 gc_values.background = XWhitePixel(xDisplay, xScreen);
3340 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3342 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3343 gc_values.background = XBlackPixel(xDisplay, xScreen);
3344 lightSquareGC = wbPieceGC
3345 = XtGetGC(shellWidget, value_mask, &gc_values);
3347 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3348 gc_values.background = XWhitePixel(xDisplay, xScreen);
3349 darkSquareGC = bwPieceGC
3350 = XtGetGC(shellWidget, value_mask, &gc_values);
3352 if (DefaultDepth(xDisplay, xScreen) == 1) {
3353 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3354 gc_values.function = GXcopyInverted;
3355 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3356 gc_values.function = GXcopy;
3357 if (XBlackPixel(xDisplay, xScreen) == 1) {
3358 bwPieceGC = darkSquareGC;
3359 wbPieceGC = copyInvertedGC;
3361 bwPieceGC = copyInvertedGC;
3362 wbPieceGC = lightSquareGC;
3366 gc_values.foreground = highlightSquareColor;
3367 gc_values.background = highlightSquareColor;
3368 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3370 gc_values.foreground = premoveHighlightColor;
3371 gc_values.background = premoveHighlightColor;
3372 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3374 gc_values.foreground = lightSquareColor;
3375 gc_values.background = darkSquareColor;
3376 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3378 gc_values.foreground = darkSquareColor;
3379 gc_values.background = lightSquareColor;
3380 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3382 gc_values.foreground = jailSquareColor;
3383 gc_values.background = jailSquareColor;
3384 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3386 gc_values.foreground = whitePieceColor;
3387 gc_values.background = darkSquareColor;
3388 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3390 gc_values.foreground = whitePieceColor;
3391 gc_values.background = lightSquareColor;
3392 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3394 gc_values.foreground = whitePieceColor;
3395 gc_values.background = jailSquareColor;
3396 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3398 gc_values.foreground = blackPieceColor;
3399 gc_values.background = darkSquareColor;
3400 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3402 gc_values.foreground = blackPieceColor;
3403 gc_values.background = lightSquareColor;
3404 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3406 gc_values.foreground = blackPieceColor;
3407 gc_values.background = jailSquareColor;
3408 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3412 void loadXIM(xim, xmask, filename, dest, mask)
3425 fp = fopen(filename, "rb");
3427 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3434 for (y=0; y<h; ++y) {
3435 for (x=0; x<h; ++x) {
3440 XPutPixel(xim, x, y, blackPieceColor);
3442 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3445 XPutPixel(xim, x, y, darkSquareColor);
3447 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3450 XPutPixel(xim, x, y, whitePieceColor);
3452 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3455 XPutPixel(xim, x, y, lightSquareColor);
3457 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3465 /* create Pixmap of piece */
3466 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3468 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3471 /* create Pixmap of clipmask
3472 Note: We assume the white/black pieces have the same
3473 outline, so we make only 6 masks. This is okay
3474 since the XPM clipmask routines do the same. */
3476 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3478 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3481 /* now create the 1-bit version */
3482 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3485 values.foreground = 1;
3486 values.background = 0;
3488 /* Don't use XtGetGC, not read only */
3489 maskGC = XCreateGC(xDisplay, *mask,
3490 GCForeground | GCBackground, &values);
3491 XCopyPlane(xDisplay, temp, *mask, maskGC,
3492 0, 0, squareSize, squareSize, 0, 0, 1);
3493 XFreePixmap(xDisplay, temp);
3498 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3500 void CreateXIMPieces()
3505 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3510 /* The XSynchronize calls were copied from CreatePieces.
3511 Not sure if needed, but can't hurt */
3512 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3515 /* temp needed by loadXIM() */
3516 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3517 0, 0, ss, ss, AllPlanes, XYPixmap);
3519 if (strlen(appData.pixmapDirectory) == 0) {
3523 if (appData.monoMode) {
3524 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3528 fprintf(stderr, _("\nLoading XIMs...\n"));
3530 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3531 fprintf(stderr, "%d", piece+1);
3532 for (kind=0; kind<4; kind++) {
3533 fprintf(stderr, ".");
3534 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3535 ExpandPathName(appData.pixmapDirectory),
3536 piece <= (int) WhiteKing ? "" : "w",
3537 pieceBitmapNames[piece],
3539 ximPieceBitmap[kind][piece] =
3540 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3541 0, 0, ss, ss, AllPlanes, XYPixmap);
3542 if (appData.debugMode)
3543 fprintf(stderr, _("(File:%s:) "), buf);
3544 loadXIM(ximPieceBitmap[kind][piece],
3546 &(xpmPieceBitmap2[kind][piece]),
3547 &(ximMaskPm2[piece]));
3548 if(piece <= (int)WhiteKing)
3549 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3551 fprintf(stderr," ");
3553 /* Load light and dark squares */
3554 /* If the LSQ and DSQ pieces don't exist, we will
3555 draw them with solid squares. */
3556 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3557 if (access(buf, 0) != 0) {
3561 fprintf(stderr, _("light square "));
3563 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3564 0, 0, ss, ss, AllPlanes, XYPixmap);
3565 if (appData.debugMode)
3566 fprintf(stderr, _("(File:%s:) "), buf);
3568 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3569 fprintf(stderr, _("dark square "));
3570 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3571 ExpandPathName(appData.pixmapDirectory), ss);
3572 if (appData.debugMode)
3573 fprintf(stderr, _("(File:%s:) "), buf);
3575 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3576 0, 0, ss, ss, AllPlanes, XYPixmap);
3577 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3578 xpmJailSquare = xpmLightSquare;
3580 fprintf(stderr, _("Done.\n"));
3582 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3585 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3588 void CreateXPMBoard(char *s, int kind)
3592 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3593 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3594 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3598 void FreeXPMPieces()
3599 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3600 // thisroutine has to be called t free the old piece pixmaps
3602 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3603 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3605 XFreePixmap(xDisplay, xpmLightSquare);
3606 XFreePixmap(xDisplay, xpmDarkSquare);
3610 void CreateXPMPieces()
3614 u_int ss = squareSize;
3616 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3617 XpmColorSymbol symbols[4];
3618 static int redo = False;
3620 if(redo) FreeXPMPieces(); else redo = 1;
3622 /* The XSynchronize calls were copied from CreatePieces.
3623 Not sure if needed, but can't hurt */
3624 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3626 /* Setup translations so piece colors match square colors */
3627 symbols[0].name = "light_piece";
3628 symbols[0].value = appData.whitePieceColor;
3629 symbols[1].name = "dark_piece";
3630 symbols[1].value = appData.blackPieceColor;
3631 symbols[2].name = "light_square";
3632 symbols[2].value = appData.lightSquareColor;
3633 symbols[3].name = "dark_square";
3634 symbols[3].value = appData.darkSquareColor;
3636 attr.valuemask = XpmColorSymbols;
3637 attr.colorsymbols = symbols;
3638 attr.numsymbols = 4;
3640 if (appData.monoMode) {
3641 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3645 if (strlen(appData.pixmapDirectory) == 0) {
3646 XpmPieces* pieces = builtInXpms;
3649 while (pieces->size != squareSize && pieces->size) pieces++;
3650 if (!pieces->size) {
3651 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);