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, 2012 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)
245 int main P((int argc, char **argv));
246 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
247 char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
248 RETSIGTYPE CmailSigHandler P((int sig));
249 RETSIGTYPE IntSigHandler P((int sig));
250 RETSIGTYPE TermSizeSigHandler P((int sig));
251 void CreateGCs P((int redo));
252 void CreateAnyPieces P((void));
253 void CreateXIMPieces P((void));
254 void CreateXPMPieces P((void));
255 void CreateXPMBoard P((char *s, int n));
256 void CreatePieces P((void));
257 void CreatePieceMenus P((void));
258 Widget CreateMenuBar P((Menu *mb, int boardWidth));
259 Widget CreateButtonBar P ((MenuItem *mi));
261 char *InsertPxlSize P((char *pattern, int targetPxlSize));
262 XFontSet CreateFontSet P((char *base_fnt_lst));
264 char *FindFont P((char *pattern, int targetPxlSize));
266 void PieceMenuPopup P((Widget w, XEvent *event,
267 String *params, Cardinal *num_params));
268 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
269 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
270 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
271 u_int wreq, u_int hreq));
272 void CreateGrid P((void));
273 int EventToSquare P((int x, int limit));
274 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
275 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
276 void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
277 void HandleUserMove P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void AnimateUserMove P((Widget w, XEvent * event,
280 String * params, Cardinal * nParams));
281 void HandlePV P((Widget w, XEvent * event,
282 String * params, Cardinal * nParams));
283 void SelectPV P((Widget w, XEvent * event,
284 String * params, Cardinal * nParams));
285 void StopPV P((Widget w, XEvent * event,
286 String * params, Cardinal * nParams));
287 void WhiteClock P((Widget w, XEvent *event,
288 String *prms, Cardinal *nprms));
289 void BlackClock P((Widget w, XEvent *event,
290 String *prms, Cardinal *nprms));
291 void DrawPositionProc P((Widget w, XEvent *event,
292 String *prms, Cardinal *nprms));
293 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
295 void CommentClick P((Widget w, XEvent * event,
296 String * params, Cardinal * nParams));
297 void CommentPopUp P((char *title, char *label));
298 void CommentPopDown P((void));
299 void ICSInputBoxPopUp P((void));
300 void ICSInputBoxPopDown P((void));
301 void FileNamePopUp P((char *label, char *def, char *filter,
302 FileProc proc, char *openMode));
303 void FileNamePopDown P((void));
304 void FileNameCallback P((Widget w, XtPointer client_data,
305 XtPointer call_data));
306 void FileNameAction P((Widget w, XEvent *event,
307 String *prms, Cardinal *nprms));
308 void AskQuestionReplyAction P((Widget w, XEvent *event,
309 String *prms, Cardinal *nprms));
310 void AskQuestionProc P((Widget w, XEvent *event,
311 String *prms, Cardinal *nprms));
312 void AskQuestionPopDown P((void));
313 void PromotionPopDown P((void));
314 void PromotionCallback P((Widget w, XtPointer client_data,
315 XtPointer call_data));
316 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
317 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
318 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
319 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
321 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
323 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
325 void LoadPositionProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
329 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
331 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
333 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
335 void PastePositionProc P((Widget w, XEvent *event, String *prms,
337 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
341 void SavePositionProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
346 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
350 void MachineWhiteProc P((Widget w, XEvent *event,
351 String *prms, Cardinal *nprms));
352 void AnalyzeModeProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void AnalyzeFileProc P((Widget w, XEvent *event,
355 String *prms, Cardinal *nprms));
356 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
358 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void IcsClientProc P((Widget w, XEvent *event, String *prms,
362 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void EditPositionProc P((Widget w, XEvent *event,
364 String *prms, Cardinal *nprms));
365 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void EditCommentProc P((Widget w, XEvent *event,
367 String *prms, Cardinal *nprms));
368 void IcsInputBoxProc P((Widget w, XEvent *event,
369 String *prms, Cardinal *nprms));
370 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void StopObservingProc P((Widget w, XEvent *event, String *prms,
387 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
389 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 Boolean TempBackwardActive = False;
395 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
401 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
403 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
406 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
408 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
410 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
412 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
413 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
415 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
418 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
420 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
422 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
423 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
424 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
427 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
429 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
431 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
433 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
436 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
438 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
440 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
442 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
449 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
450 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void DisplayMove P((int moveNumber));
453 void DisplayTitle P((char *title));
454 void ICSInitScript P((void));
455 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
456 void ErrorPopUp P((char *title, char *text, int modal));
457 void ErrorPopDown P((void));
458 static char *ExpandPathName P((char *path));
459 static void CreateAnimVars P((void));
460 static void DragPieceMove P((int x, int y));
461 static void DrawDragPiece P((void));
462 char *ModeToWidgetName P((GameMode mode));
463 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
467 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
468 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
469 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
470 void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
471 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
472 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
473 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
474 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
475 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
476 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
477 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
478 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
479 void EditBookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
480 void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
481 void GameListOptionsPopDown P(());
482 void GenericPopDown P(());
483 void update_ics_width P(());
484 int get_term_width P(());
485 int CopyMemoProc P(());
486 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
487 Boolean IsDrawArrowEnabled P(());
490 * XBoard depends on Xt R4 or higher
492 int xtVersion = XtSpecificationRelease;
497 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
498 jailSquareColor, highlightSquareColor, premoveHighlightColor;
499 Pixel lowTimeWarningColor;
500 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
501 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
502 wjPieceGC, bjPieceGC, prelineGC, countGC;
503 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
504 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
505 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
506 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
507 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
508 ICSInputShell, fileNameShell, askQuestionShell;
509 Widget historyShell, evalGraphShell, gameListShell;
510 int hOffset; // [HGM] dual
511 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
512 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
513 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
515 XFontSet fontSet, clockFontSet;
518 XFontStruct *clockFontStruct;
520 Font coordFontID, countFontID;
521 XFontStruct *coordFontStruct, *countFontStruct;
522 XtAppContext appContext;
524 char *oldICSInteractionTitle;
528 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
530 Position commentX = -1, commentY = -1;
531 Dimension commentW, commentH;
532 typedef unsigned int BoardSize;
534 Boolean chessProgram;
536 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
537 int squareSize, smallLayout = 0, tinyLayout = 0,
538 marginW, marginH, // [HGM] for run-time resizing
539 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
540 ICSInputBoxUp = False, askQuestionUp = False,
541 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
542 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
543 Pixel timerForegroundPixel, timerBackgroundPixel;
544 Pixel buttonForegroundPixel, buttonBackgroundPixel;
545 char *chessDir, *programName, *programVersion,
546 *gameCopyFilename, *gamePasteFilename;
547 Boolean alwaysOnTop = False;
548 Boolean saveSettingsOnExit;
549 char *settingsFileName;
550 char *icsTextMenuString;
552 char *firstChessProgramNames;
553 char *secondChessProgramNames;
555 WindowPlacement wpMain;
556 WindowPlacement wpConsole;
557 WindowPlacement wpComment;
558 WindowPlacement wpMoveHistory;
559 WindowPlacement wpEvalGraph;
560 WindowPlacement wpEngineOutput;
561 WindowPlacement wpGameList;
562 WindowPlacement wpTags;
564 extern Widget shells[];
565 extern Boolean shellUp[];
569 Pixmap pieceBitmap[2][(int)BlackPawn];
570 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
571 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
572 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
573 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
574 Pixmap xpmBoardBitmap[2];
575 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
576 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
577 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
578 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
579 XImage *ximLightSquare, *ximDarkSquare;
582 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
583 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
585 #define White(piece) ((int)(piece) < (int)BlackPawn)
587 /* Variables for doing smooth animation. This whole thing
588 would be much easier if the board was double-buffered,
589 but that would require a fairly major rewrite. */
594 GC blitGC, pieceGC, outlineGC;
595 XPoint startSquare, prevFrame, mouseDelta;
599 int startBoardX, startBoardY;
602 /* There can be two pieces being animated at once: a player
603 can begin dragging a piece before the remote opponent has moved. */
605 static AnimState game, player;
607 /* Bitmaps for use as masks when drawing XPM pieces.
608 Need one for each black and white piece. */
609 static Pixmap xpmMask[BlackKing + 1];
611 /* This magic number is the number of intermediate frames used
612 in each half of the animation. For short moves it's reduced
613 by 1. The total number of frames will be factor * 2 + 1. */
616 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
618 MenuItem fileMenu[] = {
619 {N_("New Game Ctrl+N"), "New Game", ResetProc},
620 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
621 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
622 {"----", NULL, NothingProc},
623 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
624 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
625 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
626 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
627 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
628 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
629 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
630 {"----", NULL, NothingProc},
631 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
632 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
633 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
634 {"----", NULL, NothingProc},
635 {N_("Mail Move"), "Mail Move", MailMoveProc},
636 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
637 {"----", NULL, NothingProc},
638 {N_("Quit Ctr+Q"), "Exit", QuitProc},
642 MenuItem editMenu[] = {
643 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
644 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
645 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
646 {"----", NULL, NothingProc},
647 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
648 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
649 {"----", NULL, NothingProc},
650 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
651 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
652 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
653 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
654 {N_("Edit Book"), "Edit Book", EditBookProc},
655 {"----", NULL, NothingProc},
656 {N_("Revert Home"), "Revert", RevertProc},
657 {N_("Annotate"), "Annotate", AnnotateProc},
658 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
659 {"----", NULL, NothingProc},
660 {N_("Backward Alt+Left"), "Backward", BackwardProc},
661 {N_("Forward Alt+Right"), "Forward", ForwardProc},
662 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
663 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
667 MenuItem viewMenu[] = {
668 {N_("Flip View F2"), "Flip View", FlipViewProc},
669 {"----", NULL, NothingProc},
670 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
671 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
672 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
673 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
674 {N_("ICS text menu"), "ICStex", IcsTextProc},
675 {"----", NULL, NothingProc},
676 {N_("Tags"), "Show Tags", EditTagsProc},
677 {N_("Comments"), "Show Comments", EditCommentProc},
678 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
679 {"----", NULL, NothingProc},
680 {N_("Board..."), "Board Options", BoardOptionsProc},
681 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
685 MenuItem modeMenu[] = {
686 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
687 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
688 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
689 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
690 {N_("Analyze Game Ctrl+G"), "Analyze File", AnalyzeFileProc },
691 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
692 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
693 {N_("Training"), "Training", TrainingProc},
694 {N_("ICS Client"), "ICS Client", IcsClientProc},
695 {"----", NULL, NothingProc},
696 {N_("Machine Match"), "Machine Match", MatchProc},
697 {N_("Pause Pause"), "Pause", PauseProc},
701 MenuItem actionMenu[] = {
702 {N_("Accept F3"), "Accept", AcceptProc},
703 {N_("Decline F4"), "Decline", DeclineProc},
704 {N_("Rematch F12"), "Rematch", RematchProc},
705 {"----", NULL, NothingProc},
706 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
707 {N_("Draw F6"), "Draw", DrawProc},
708 {N_("Adjourn F7"), "Adjourn", AdjournProc},
709 {N_("Abort F8"),"Abort", AbortProc},
710 {N_("Resign F9"), "Resign", ResignProc},
711 {"----", NULL, NothingProc},
712 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
713 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
714 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
715 {"----", NULL, NothingProc},
716 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
717 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
718 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
722 MenuItem engineMenu[] = {
723 {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
724 {"----", NULL, NothingProc},
725 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
726 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
727 {"----", NULL, NothingProc},
728 {N_("Hint"), "Hint", HintProc},
729 {N_("Book"), "Book", BookProc},
730 {"----", NULL, NothingProc},
731 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
732 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
736 MenuItem optionsMenu[] = {
737 #define OPTIONSDIALOG
739 {N_("General ..."), "General", OptionsProc},
741 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
742 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
743 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
744 {N_("ICS ..."), "ICS", IcsOptionsProc},
745 {N_("Match ..."), "Match", MatchOptionsProc},
746 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
747 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
748 // {N_(" ..."), "", OptionsProc},
749 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
750 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
751 {"----", NULL, NothingProc},
752 #ifndef OPTIONSDIALOG
753 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
754 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
755 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
756 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
757 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
758 {N_("Blindfold"), "Blindfold", BlindfoldProc},
759 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
761 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
763 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
764 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
765 {N_("Move Sound"), "Move Sound", MoveSoundProc},
766 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
767 {N_("One-Click Moving"), "OneClick", OneClickProc},
768 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
769 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
770 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
771 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
772 // {N_("Premove"), "Premove", PremoveProc},
773 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
774 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
775 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
776 {"----", NULL, NothingProc},
778 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
779 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
783 MenuItem helpMenu[] = {
784 {N_("Info XBoard"), "Info XBoard", InfoProc},
785 {N_("Man XBoard F1"), "Man XBoard", ManProc},
786 {"----", NULL, NothingProc},
787 {N_("About XBoard"), "About XBoard", AboutProc},
792 {N_("File"), "File", fileMenu},
793 {N_("Edit"), "Edit", editMenu},
794 {N_("View"), "View", viewMenu},
795 {N_("Mode"), "Mode", modeMenu},
796 {N_("Action"), "Action", actionMenu},
797 {N_("Engine"), "Engine", engineMenu},
798 {N_("Options"), "Options", optionsMenu},
799 {N_("Help"), "Help", helpMenu},
803 #define PAUSE_BUTTON "P"
804 MenuItem buttonBar[] = {
805 {"<<", "<<", ToStartProc},
806 {"<", "<", BackwardProc},
807 {N_(PAUSE_BUTTON), PAUSE_BUTTON, PauseProc},
808 {">", ">", ForwardProc},
809 {">>", ">>", ToEndProc},
813 #define PIECE_MENU_SIZE 18
814 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
815 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
816 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
817 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
818 N_("Empty square"), N_("Clear board") },
819 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
820 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
821 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
822 N_("Empty square"), N_("Clear board") }
824 /* must be in same order as pieceMenuStrings! */
825 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
826 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
827 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
828 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
829 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
830 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
831 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
832 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
833 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
836 #define DROP_MENU_SIZE 6
837 String dropMenuStrings[DROP_MENU_SIZE] = {
838 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
840 /* must be in same order as dropMenuStrings! */
841 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
842 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
843 WhiteRook, WhiteQueen
851 DropMenuEnables dmEnables[] = {
869 { XtNborderWidth, 0 },
870 { XtNdefaultDistance, 0 },
874 { XtNborderWidth, 0 },
875 { XtNresizable, (XtArgVal) True },
879 { XtNborderWidth, 0 },
885 { XtNjustify, (XtArgVal) XtJustifyRight },
886 { XtNlabel, (XtArgVal) "..." },
887 { XtNresizable, (XtArgVal) True },
888 { XtNresize, (XtArgVal) False }
891 Arg messageArgs[] = {
892 { XtNjustify, (XtArgVal) XtJustifyLeft },
893 { XtNlabel, (XtArgVal) "..." },
894 { XtNresizable, (XtArgVal) True },
895 { XtNresize, (XtArgVal) False }
899 { XtNborderWidth, 0 },
900 { XtNjustify, (XtArgVal) XtJustifyLeft }
903 XtResource clientResources[] = {
904 { "flashCount", "flashCount", XtRInt, sizeof(int),
905 XtOffset(AppDataPtr, flashCount), XtRImmediate,
906 (XtPointer) FLASH_COUNT },
909 XrmOptionDescRec shellOptions[] = {
910 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
911 { "-flash", "flashCount", XrmoptionNoArg, "3" },
912 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
915 XtActionsRec boardActions[] = {
916 { "DrawPosition", DrawPositionProc },
917 { "HandleUserMove", HandleUserMove },
918 { "AnimateUserMove", AnimateUserMove },
919 { "HandlePV", HandlePV },
920 { "SelectPV", SelectPV },
921 { "StopPV", StopPV },
922 { "FileNameAction", FileNameAction },
923 { "AskQuestionProc", AskQuestionProc },
924 { "AskQuestionReplyAction", AskQuestionReplyAction },
925 { "PieceMenuPopup", PieceMenuPopup },
926 { "WhiteClock", WhiteClock },
927 { "BlackClock", BlackClock },
928 { "ResetProc", ResetProc },
929 { "NewVariantProc", NewVariantProc },
930 { "LoadGameProc", LoadGameProc },
931 { "LoadNextGameProc", LoadNextGameProc },
932 { "LoadPrevGameProc", LoadPrevGameProc },
933 { "LoadSelectedProc", LoadSelectedProc },
934 { "SetFilterProc", SetFilterProc },
935 { "ReloadGameProc", ReloadGameProc },
936 { "LoadPositionProc", LoadPositionProc },
937 { "LoadNextPositionProc", LoadNextPositionProc },
938 { "LoadPrevPositionProc", LoadPrevPositionProc },
939 { "ReloadPositionProc", ReloadPositionProc },
940 { "CopyPositionProc", CopyPositionProc },
941 { "PastePositionProc", PastePositionProc },
942 { "CopyGameProc", CopyGameProc },
943 { "CopyGameListProc", CopyGameListProc },
944 { "PasteGameProc", PasteGameProc },
945 { "SaveGameProc", SaveGameProc },
946 { "SavePositionProc", SavePositionProc },
947 { "MailMoveProc", MailMoveProc },
948 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
949 { "QuitProc", QuitProc },
950 { "MachineWhiteProc", MachineWhiteProc },
951 { "MachineBlackProc", MachineBlackProc },
952 { "AnalysisModeProc", AnalyzeModeProc },
953 { "AnalyzeFileProc", AnalyzeFileProc },
954 { "TwoMachinesProc", TwoMachinesProc },
955 { "IcsClientProc", IcsClientProc },
956 { "EditGameProc", EditGameProc },
957 { "EditPositionProc", EditPositionProc },
958 { "TrainingProc", EditPositionProc },
959 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
960 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
961 { "ShowGameListProc", ShowGameListProc },
962 { "ShowMoveListProc", HistoryShowProc},
963 { "EditTagsProc", EditCommentProc },
964 { "EditBookProc", EditBookProc },
965 { "EditCommentProc", EditCommentProc },
966 { "IcsInputBoxProc", IcsInputBoxProc },
967 { "PauseProc", PauseProc },
968 { "AcceptProc", AcceptProc },
969 { "DeclineProc", DeclineProc },
970 { "RematchProc", RematchProc },
971 { "CallFlagProc", CallFlagProc },
972 { "DrawProc", DrawProc },
973 { "AdjournProc", AdjournProc },
974 { "AbortProc", AbortProc },
975 { "ResignProc", ResignProc },
976 { "AdjuWhiteProc", AdjuWhiteProc },
977 { "AdjuBlackProc", AdjuBlackProc },
978 { "AdjuDrawProc", AdjuDrawProc },
979 { "TypeInProc", TypeInProc },
980 { "EnterKeyProc", EnterKeyProc },
981 { "UpKeyProc", UpKeyProc },
982 { "DownKeyProc", DownKeyProc },
983 { "StopObservingProc", StopObservingProc },
984 { "StopExaminingProc", StopExaminingProc },
985 { "UploadProc", UploadProc },
986 { "BackwardProc", BackwardProc },
987 { "ForwardProc", ForwardProc },
988 { "TempBackwardProc", TempBackwardProc },
989 { "TempForwardProc", TempForwardProc },
990 { "ToStartProc", ToStartProc },
991 { "ToEndProc", ToEndProc },
992 { "RevertProc", RevertProc },
993 { "AnnotateProc", AnnotateProc },
994 { "TruncateGameProc", TruncateGameProc },
995 { "MoveNowProc", MoveNowProc },
996 { "RetractMoveProc", RetractMoveProc },
997 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
998 { "UciMenuProc", (XtActionProc) UciMenuProc },
999 { "TimeControlProc", (XtActionProc) TimeControlProc },
1000 { "FlipViewProc", FlipViewProc },
1001 { "PonderNextMoveProc", PonderNextMoveProc },
1002 #ifndef OPTIONSDIALOG
1003 { "AlwaysQueenProc", AlwaysQueenProc },
1004 { "AnimateDraggingProc", AnimateDraggingProc },
1005 { "AnimateMovingProc", AnimateMovingProc },
1006 { "AutoflagProc", AutoflagProc },
1007 { "AutoflipProc", AutoflipProc },
1008 { "BlindfoldProc", BlindfoldProc },
1009 { "FlashMovesProc", FlashMovesProc },
1011 { "HighlightDraggingProc", HighlightDraggingProc },
1013 { "HighlightLastMoveProc", HighlightLastMoveProc },
1014 // { "IcsAlarmProc", IcsAlarmProc },
1015 { "MoveSoundProc", MoveSoundProc },
1016 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1017 { "PopupExitMessageProc", PopupExitMessageProc },
1018 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1019 // { "PremoveProc", PremoveProc },
1020 { "ShowCoordsProc", ShowCoordsProc },
1021 { "ShowThinkingProc", ShowThinkingProc },
1022 { "HideThinkingProc", HideThinkingProc },
1023 { "TestLegalityProc", TestLegalityProc },
1025 { "SaveSettingsProc", SaveSettingsProc },
1026 { "SaveOnExitProc", SaveOnExitProc },
1027 { "InfoProc", InfoProc },
1028 { "ManProc", ManProc },
1029 { "HintProc", HintProc },
1030 { "BookProc", BookProc },
1031 { "AboutGameProc", AboutGameProc },
1032 { "AboutProc", AboutProc },
1033 { "DebugProc", DebugProc },
1034 { "NothingProc", NothingProc },
1035 { "CommentClick", (XtActionProc) CommentClick },
1036 { "CommentPopDown", (XtActionProc) CommentPopDown },
1037 { "TagsPopDown", (XtActionProc) TagsPopDown },
1038 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1039 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1040 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1041 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1042 { "GameListPopDown", (XtActionProc) GameListPopDown },
1043 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1044 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1045 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1046 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1047 { "GenericPopDown", (XtActionProc) GenericPopDown },
1048 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1049 { "SelectMove", (XtActionProc) SelectMove },
1052 char globalTranslations[] =
1053 ":<Key>F9: ResignProc() \n \
1054 :Ctrl<Key>n: ResetProc() \n \
1055 :Meta<Key>V: NewVariantProc() \n \
1056 :Ctrl<Key>o: LoadGameProc() \n \
1057 :Meta<Key>Next: LoadNextGameProc() \n \
1058 :Meta<Key>Prior: LoadPrevGameProc() \n \
1059 :Ctrl<Key>Down: LoadSelectedProc(3) \n \
1060 :Ctrl<Key>Up: LoadSelectedProc(-3) \n \
1061 :Ctrl<Key>s: SaveGameProc() \n \
1062 :Ctrl<Key>c: CopyGameProc() \n \
1063 :Ctrl<Key>v: PasteGameProc() \n \
1064 :Ctrl<Key>O: LoadPositionProc() \n \
1065 :Shift<Key>Next: LoadNextPositionProc() \n \
1066 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1067 :Ctrl<Key>S: SavePositionProc() \n \
1068 :Ctrl<Key>C: CopyPositionProc() \n \
1069 :Ctrl<Key>V: PastePositionProc() \n \
1070 :Ctrl<Key>q: QuitProc() \n \
1071 :Ctrl<Key>w: MachineWhiteProc() \n \
1072 :Ctrl<Key>b: MachineBlackProc() \n \
1073 :Ctrl<Key>t: TwoMachinesProc() \n \
1074 :Ctrl<Key>a: AnalysisModeProc() \n \
1075 :Ctrl<Key>g: AnalyzeFileProc() \n \
1076 :Ctrl<Key>e: EditGameProc() \n \
1077 :Ctrl<Key>E: EditPositionProc() \n \
1078 :Meta<Key>O: EngineOutputProc() \n \
1079 :Meta<Key>E: EvalGraphProc() \n \
1080 :Meta<Key>G: ShowGameListProc() \n \
1081 :Meta<Key>H: ShowMoveListProc() \n \
1082 :<Key>Pause: PauseProc() \n \
1083 :<Key>F3: AcceptProc() \n \
1084 :<Key>F4: DeclineProc() \n \
1085 :<Key>F12: RematchProc() \n \
1086 :<Key>F5: CallFlagProc() \n \
1087 :<Key>F6: DrawProc() \n \
1088 :<Key>F7: AdjournProc() \n \
1089 :<Key>F8: AbortProc() \n \
1090 :<Key>F10: StopObservingProc() \n \
1091 :<Key>F11: StopExaminingProc() \n \
1092 :Meta Ctrl<Key>F12: DebugProc() \n \
1093 :Meta<Key>End: ToEndProc() \n \
1094 :Meta<Key>Right: ForwardProc() \n \
1095 :Meta<Key>Home: ToStartProc() \n \
1096 :Meta<Key>Left: BackwardProc() \n \
1097 :<Key>Left: BackwardProc() \n \
1098 :<Key>Right: ForwardProc() \n \
1099 :<Key>Home: RevertProc() \n \
1100 :<Key>End: TruncateGameProc() \n \
1101 :Ctrl<Key>m: MoveNowProc() \n \
1102 :Ctrl<Key>x: RetractMoveProc() \n \
1103 :Meta<Key>J: EngineMenuProc() \n \
1104 :Meta<Key>U: UciMenuProc() \n \
1105 :Meta<Key>T: TimeControlProc() \n \
1106 :Ctrl<Key>P: PonderNextMoveProc() \n "
1107 #ifndef OPTIONSDIALOG
1109 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1110 :Ctrl<Key>F: AutoflagProc() \n \
1111 :Ctrl<Key>A: AnimateMovingProc() \n \
1112 :Ctrl<Key>L: TestLegalityProc() \n \
1113 :Ctrl<Key>H: HideThinkingProc() \n "
1116 :<Key>F1: ManProc() \n \
1117 :<Key>F2: FlipViewProc() \n \
1118 :<KeyDown>Return: TempBackwardProc() \n \
1119 :<KeyUp>Return: TempForwardProc() \n";
1121 char boardTranslations[] =
1122 "<Btn1Down>: HandleUserMove(0) \n \
1123 Shift<Btn1Up>: HandleUserMove(1) \n \
1124 <Btn1Up>: HandleUserMove(0) \n \
1125 <Btn1Motion>: AnimateUserMove() \n \
1126 <Btn3Motion>: HandlePV() \n \
1127 <Btn3Up>: PieceMenuPopup(menuB) \n \
1128 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1129 PieceMenuPopup(menuB) \n \
1130 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1131 PieceMenuPopup(menuW) \n \
1132 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1133 PieceMenuPopup(menuW) \n \
1134 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1135 PieceMenuPopup(menuB) \n";
1137 char whiteTranslations[] =
1138 "Shift<BtnDown>: WhiteClock(1)\n \
1139 <BtnDown>: WhiteClock(0)\n";
1140 char blackTranslations[] =
1141 "Shift<BtnDown>: BlackClock(1)\n \
1142 <BtnDown>: BlackClock(0)\n";
1144 char ICSInputTranslations[] =
1145 "<Key>Up: UpKeyProc() \n "
1146 "<Key>Down: DownKeyProc() \n "
1147 "<Key>Return: EnterKeyProc() \n";
1149 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1150 // as the widget is destroyed before the up-click can call extend-end
1151 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1153 String xboardResources[] = {
1154 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1155 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1156 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1161 /* Max possible square size */
1162 #define MAXSQSIZE 256
1164 static int xpm_avail[MAXSQSIZE];
1166 #ifdef HAVE_DIR_STRUCT
1168 /* Extract piece size from filename */
1170 xpm_getsize (char *name, int len, char *ext)
1178 if ((p=strchr(name, '.')) == NULL ||
1179 StrCaseCmp(p+1, ext) != 0)
1185 while (*p && isdigit(*p))
1192 /* Setup xpm_avail */
1194 xpm_getavail (char *dirname, char *ext)
1200 for (i=0; i<MAXSQSIZE; ++i)
1203 if (appData.debugMode)
1204 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1206 dir = opendir(dirname);
1209 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1210 programName, dirname);
1214 while ((ent=readdir(dir)) != NULL) {
1215 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1216 if (i > 0 && i < MAXSQSIZE)
1226 xpm_print_avail (FILE *fp, char *ext)
1230 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1231 for (i=1; i<MAXSQSIZE; ++i) {
1237 /* Return XPM piecesize closest to size */
1239 xpm_closest_to (char *dirname, int size, char *ext)
1242 int sm_diff = MAXSQSIZE;
1246 xpm_getavail(dirname, ext);
1248 if (appData.debugMode)
1249 xpm_print_avail(stderr, ext);
1251 for (i=1; i<MAXSQSIZE; ++i) {
1254 diff = (diff<0) ? -diff : diff;
1255 if (diff < sm_diff) {
1263 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1269 #else /* !HAVE_DIR_STRUCT */
1270 /* If we are on a system without a DIR struct, we can't
1271 read the directory, so we can't collect a list of
1272 filenames, etc., so we can't do any size-fitting. */
1274 xpm_closest_to (char *dirname, int size, char *ext)
1276 fprintf(stderr, _("\
1277 Warning: No DIR structure found on this system --\n\
1278 Unable to autosize for XPM/XIM pieces.\n\
1279 Please report this error to %s.\n\
1280 Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
1283 #endif /* HAVE_DIR_STRUCT */
1285 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1286 "magenta", "cyan", "white" };
1290 TextColors textColors[(int)NColorClasses];
1292 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1294 parse_color (char *str, int which)
1296 char *p, buf[100], *d;
1299 if (strlen(str) > 99) /* watch bounds on buf */
1304 for (i=0; i<which; ++i) {
1311 /* Could be looking at something like:
1313 .. in which case we want to stop on a comma also */
1314 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1318 return -1; /* Use default for empty field */
1321 if (which == 2 || isdigit(*p))
1324 while (*p && isalpha(*p))
1329 for (i=0; i<8; ++i) {
1330 if (!StrCaseCmp(buf, cnames[i]))
1331 return which? (i+40) : (i+30);
1333 if (!StrCaseCmp(buf, "default")) return -1;
1335 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1340 parse_cpair (ColorClass cc, char *str)
1342 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1343 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1348 /* bg and attr are optional */
1349 textColors[(int)cc].bg = parse_color(str, 1);
1350 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1351 textColors[(int)cc].attr = 0;
1357 /* Arrange to catch delete-window events */
1358 Atom wm_delete_window;
1360 CatchDeleteWindow (Widget w, String procname)
1363 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1364 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1365 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1372 XtSetArg(args[0], XtNiconic, False);
1373 XtSetValues(shellWidget, args, 1);
1375 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1378 //---------------------------------------------------------------------------------------------------------
1379 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1382 #define CW_USEDEFAULT (1<<31)
1383 #define ICS_TEXT_MENU_SIZE 90
1384 #define DEBUG_FILE "xboard.debug"
1385 #define SetCurrentDirectory chdir
1386 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1390 // these two must some day move to frontend.h, when they are implemented
1391 Boolean GameListIsUp();
1393 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1396 // front-end part of option handling
1398 // [HGM] This platform-dependent table provides the location for storing the color info
1399 extern char *crWhite, * crBlack;
1403 &appData.whitePieceColor,
1404 &appData.blackPieceColor,
1405 &appData.lightSquareColor,
1406 &appData.darkSquareColor,
1407 &appData.highlightSquareColor,
1408 &appData.premoveHighlightColor,
1409 &appData.lowTimeWarningColor,
1420 // [HGM] font: keep a font for each square size, even non-stndard ones
1421 #define NUM_SIZES 18
1422 #define MAX_SIZE 130
1423 Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1424 char *fontTable[NUM_FONTS][MAX_SIZE];
1427 ParseFont (char *name, int number)
1428 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1430 if(sscanf(name, "size%d:", &size)) {
1431 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1432 // defer processing it until we know if it matches our board size
1433 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1434 fontTable[number][size] = strdup(strchr(name, ':')+1);
1435 fontValid[number][size] = True;
1440 case 0: // CLOCK_FONT
1441 appData.clockFont = strdup(name);
1443 case 1: // MESSAGE_FONT
1444 appData.font = strdup(name);
1446 case 2: // COORD_FONT
1447 appData.coordFont = strdup(name);
1452 fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1457 { // only 2 fonts currently
1458 appData.clockFont = CLOCK_FONT_NAME;
1459 appData.coordFont = COORD_FONT_NAME;
1460 appData.font = DEFAULT_FONT_NAME;
1465 { // no-op, until we identify the code for this already in XBoard and move it here
1469 ParseColor (int n, char *name)
1470 { // in XBoard, just copy the color-name string
1471 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1475 ParseTextAttribs (ColorClass cc, char *s)
1477 (&appData.colorShout)[cc] = strdup(s);
1481 ParseBoardSize (void *addr, char *name)
1483 appData.boardSize = strdup(name);
1488 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1492 SetCommPortDefaults ()
1493 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1496 // [HGM] args: these three cases taken out to stay in front-end
1498 SaveFontArg (FILE *f, ArgDescriptor *ad)
1501 int i, n = (int)(intptr_t)ad->argLoc;
1503 case 0: // CLOCK_FONT
1504 name = appData.clockFont;
1506 case 1: // MESSAGE_FONT
1507 name = appData.font;
1509 case 2: // COORD_FONT
1510 name = appData.coordFont;
1515 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1516 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1517 fontTable[n][squareSize] = strdup(name);
1518 fontValid[n][squareSize] = True;
1521 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1522 fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
1527 { // nothing to do, as the sounds are at all times represented by their text-string names already
1531 SaveAttribsArg (FILE *f, ArgDescriptor *ad)
1532 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1533 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1537 SaveColor (FILE *f, ArgDescriptor *ad)
1538 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1539 if(colorVariable[(int)(intptr_t)ad->argLoc])
1540 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1544 SaveBoardSize (FILE *f, char *name, void *addr)
1545 { // wrapper to shield back-end from BoardSize & sizeInfo
1546 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1550 ParseCommPortSettings (char *s)
1551 { // no such option in XBoard (yet)
1554 extern Widget engineOutputShell;
1557 GetActualPlacement (Widget wg, WindowPlacement *wp)
1567 XtSetArg(args[i], XtNx, &x); i++;
1568 XtSetArg(args[i], XtNy, &y); i++;
1569 XtSetArg(args[i], XtNwidth, &w); i++;
1570 XtSetArg(args[i], XtNheight, &h); i++;
1571 XtGetValues(wg, args, i);
1580 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1581 // In XBoard this will have to wait until awareness of window parameters is implemented
1582 GetActualPlacement(shellWidget, &wpMain);
1583 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput);
1584 if(MoveHistoryIsUp()) GetActualPlacement(shells[7], &wpMoveHistory);
1585 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1586 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1587 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1588 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1592 PrintCommPortSettings (FILE *f, char *name)
1593 { // This option does not exist in XBoard
1597 MySearchPath (char *installDir, char *name, char *fullname)
1598 { // just append installDir and name. Perhaps ExpandPath should be used here?
1599 name = ExpandPathName(name);
1600 if(name && name[0] == '/')
1601 safeStrCpy(fullname, name, MSG_SIZ );
1603 sprintf(fullname, "%s%c%s", installDir, '/', name);
1609 MyGetFullPathName (char *name, char *fullname)
1610 { // should use ExpandPath?
1611 name = ExpandPathName(name);
1612 safeStrCpy(fullname, name, MSG_SIZ );
1617 EnsureOnScreen (int *x, int *y, int minX, int minY)
1624 { // [HGM] args: allows testing if main window is realized from back-end
1625 return xBoardWindow != 0;
1629 PopUpStartupDialog ()
1630 { // start menu not implemented in XBoard
1634 ConvertToLine (int argc, char **argv)
1636 static char line[128*1024], buf[1024];
1640 for(i=1; i<argc; i++)
1642 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') || argv[i][0] == NULLCHAR)
1643 && argv[i][0] != '{' )
1644 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1646 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1647 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1650 line[strlen(line)-1] = NULLCHAR;
1654 //--------------------------------------------------------------------------------------------
1656 extern Boolean twoBoards, partnerUp;
1659 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1661 #define BoardSize int
1663 InitDrawingSizes (BoardSize boardSize, int flags)
1664 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1665 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1667 XtGeometryResult gres;
1669 static Dimension oldWidth, oldHeight;
1670 static VariantClass oldVariant;
1671 static int oldDual = -1, oldMono = -1;
1673 if(!formWidget) return;
1675 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1676 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1677 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1679 if(boardWidth != oldWidth || boardHeight != oldHeight || oldDual != twoBoards) { // do resizing stuff only if size actually changed
1681 * Enable shell resizing.
1683 shellArgs[0].value = (XtArgVal) &w;
1684 shellArgs[1].value = (XtArgVal) &h;
1685 XtGetValues(shellWidget, shellArgs, 2);
1687 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1688 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1689 XtSetValues(shellWidget, &shellArgs[2], 4);
1691 XtSetArg(args[0], XtNdefaultDistance, &sep);
1692 XtGetValues(formWidget, args, 1);
1694 oldWidth = boardWidth; oldHeight = boardHeight; oldDual = twoBoards;
1696 hOffset = boardWidth + 10;
1697 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1698 secondSegments[i] = gridSegments[i];
1699 secondSegments[i].x1 += hOffset;
1700 secondSegments[i].x2 += hOffset;
1703 XtSetArg(args[0], XtNwidth, boardWidth);
1704 XtSetArg(args[1], XtNheight, boardHeight);
1705 XtSetValues(boardWidget, args, 2);
1707 timerWidth = (boardWidth - sep) / 2;
1708 XtSetArg(args[0], XtNwidth, timerWidth);
1709 XtSetValues(whiteTimerWidget, args, 1);
1710 XtSetValues(blackTimerWidget, args, 1);
1712 XawFormDoLayout(formWidget, False);
1714 if (appData.titleInWindow) {
1716 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1717 XtSetArg(args[i], XtNheight, &h); i++;
1718 XtGetValues(titleWidget, args, i);
1720 w = boardWidth - 2*bor;
1722 XtSetArg(args[0], XtNwidth, &w);
1723 XtGetValues(menuBarWidget, args, 1);
1724 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1727 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1728 if (gres != XtGeometryYes && appData.debugMode) {
1730 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1731 programName, gres, w, h, wr, hr);
1735 XawFormDoLayout(formWidget, True);
1738 * Inhibit shell resizing.
1740 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1741 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1742 shellArgs[4].value = shellArgs[2].value = w;
1743 shellArgs[5].value = shellArgs[3].value = h;
1744 XtSetValues(shellWidget, &shellArgs[0], 6);
1747 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1750 if(gameInfo.variant != oldVariant) { // and only if variant changed
1753 for(i=0; i<4; i++) {
1755 for(p=0; p<=(int)WhiteKing; p++)
1756 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1757 if(gameInfo.variant == VariantShogi) {
1758 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1759 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1760 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1761 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1762 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1765 if(gameInfo.variant == VariantGothic) {
1766 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1769 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1770 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1771 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1774 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1775 for(p=0; p<=(int)WhiteKing; p++)
1776 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1777 if(gameInfo.variant == VariantShogi) {
1778 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1779 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1780 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1781 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1782 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1785 if(gameInfo.variant == VariantGothic) {
1786 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1789 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1790 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1791 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1796 for(i=0; i<2; i++) {
1798 for(p=0; p<=(int)WhiteKing; p++)
1799 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1800 if(gameInfo.variant == VariantShogi) {
1801 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1802 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1803 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1804 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1805 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1808 if(gameInfo.variant == VariantGothic) {
1809 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1812 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1813 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1814 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1820 if(appData.monoMode == oldMono)
1823 oldMono = appData.monoMode;
1828 ParseIcsTextColors ()
1829 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1830 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1831 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1832 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1833 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1834 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1835 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1836 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1837 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1838 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1839 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1841 if (appData.colorize) {
1843 _("%s: can't parse color names; disabling colorization\n"),
1846 appData.colorize = FALSE;
1852 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1853 XrmValue vFrom, vTo;
1854 int forceMono = False;
1856 if (!appData.monoMode) {
1857 vFrom.addr = (caddr_t) appData.lightSquareColor;
1858 vFrom.size = strlen(appData.lightSquareColor);
1859 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1860 if (vTo.addr == NULL) {
1861 appData.monoMode = True;
1864 lightSquareColor = *(Pixel *) vTo.addr;
1867 if (!appData.monoMode) {
1868 vFrom.addr = (caddr_t) appData.darkSquareColor;
1869 vFrom.size = strlen(appData.darkSquareColor);
1870 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1871 if (vTo.addr == NULL) {
1872 appData.monoMode = True;
1875 darkSquareColor = *(Pixel *) vTo.addr;
1878 if (!appData.monoMode) {
1879 vFrom.addr = (caddr_t) appData.whitePieceColor;
1880 vFrom.size = strlen(appData.whitePieceColor);
1881 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1882 if (vTo.addr == NULL) {
1883 appData.monoMode = True;
1886 whitePieceColor = *(Pixel *) vTo.addr;
1889 if (!appData.monoMode) {
1890 vFrom.addr = (caddr_t) appData.blackPieceColor;
1891 vFrom.size = strlen(appData.blackPieceColor);
1892 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1893 if (vTo.addr == NULL) {
1894 appData.monoMode = True;
1897 blackPieceColor = *(Pixel *) vTo.addr;
1901 if (!appData.monoMode) {
1902 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1903 vFrom.size = strlen(appData.highlightSquareColor);
1904 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1905 if (vTo.addr == NULL) {
1906 appData.monoMode = True;
1909 highlightSquareColor = *(Pixel *) vTo.addr;
1913 if (!appData.monoMode) {
1914 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1915 vFrom.size = strlen(appData.premoveHighlightColor);
1916 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1917 if (vTo.addr == NULL) {
1918 appData.monoMode = True;
1921 premoveHighlightColor = *(Pixel *) vTo.addr;
1929 { // [HGM] taken out of main
1931 if (appData.monoMode && // [HGM] no sense to go on to certain doom
1932 (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
1933 appData.bitmapDirectory = strdup(DEF_BITMAP_DIR);
1935 if (appData.bitmapDirectory[0] != NULLCHAR) {
1939 CreateXPMBoard(appData.liteBackTextureFile, 1);
1940 CreateXPMBoard(appData.darkBackTextureFile, 0);
1944 /* Create regular pieces */
1945 if (!useImages) CreatePieces();
1950 main (int argc, char **argv)
1952 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1953 XSetWindowAttributes window_attributes;
1955 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1956 XrmValue vFrom, vTo;
1957 XtGeometryResult gres;
1960 int forceMono = False;
1962 srandom(time(0)); // [HGM] book: make random truly random
1964 setbuf(stdout, NULL);
1965 setbuf(stderr, NULL);
1968 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1969 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1973 programName = strrchr(argv[0], '/');
1974 if (programName == NULL)
1975 programName = argv[0];
1980 XtSetLanguageProc(NULL, NULL, NULL);
1981 bindtextdomain(PACKAGE, LOCALEDIR);
1982 textdomain(PACKAGE);
1986 XtAppInitialize(&appContext, "XBoard", shellOptions,
1987 XtNumber(shellOptions),
1988 &argc, argv, xboardResources, NULL, 0);
1989 appData.boardSize = "";
1990 InitAppData(ConvertToLine(argc, argv));
1992 if (p == NULL) p = "/tmp";
1993 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1994 gameCopyFilename = (char*) malloc(i);
1995 gamePasteFilename = (char*) malloc(i);
1996 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1997 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1999 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2000 clientResources, XtNumber(clientResources),
2003 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2004 static char buf[MSG_SIZ];
2005 EscapeExpand(buf, appData.firstInitString);
2006 appData.firstInitString = strdup(buf);
2007 EscapeExpand(buf, appData.secondInitString);
2008 appData.secondInitString = strdup(buf);
2009 EscapeExpand(buf, appData.firstComputerString);
2010 appData.firstComputerString = strdup(buf);
2011 EscapeExpand(buf, appData.secondComputerString);
2012 appData.secondComputerString = strdup(buf);
2015 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2018 if (chdir(chessDir) != 0) {
2019 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2025 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2026 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2027 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2028 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2031 setbuf(debugFP, NULL);
2035 if (appData.debugMode) {
2036 fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
2040 /* [HGM,HR] make sure board size is acceptable */
2041 if(appData.NrFiles > BOARD_FILES ||
2042 appData.NrRanks > BOARD_RANKS )
2043 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2046 /* This feature does not work; animation needs a rewrite */
2047 appData.highlightDragging = FALSE;
2051 xDisplay = XtDisplay(shellWidget);
2052 xScreen = DefaultScreen(xDisplay);
2053 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2055 gameInfo.variant = StringToVariant(appData.variant);
2056 InitPosition(FALSE);
2059 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2061 if (isdigit(appData.boardSize[0])) {
2062 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2063 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2064 &fontPxlSize, &smallLayout, &tinyLayout);
2066 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2067 programName, appData.boardSize);
2071 /* Find some defaults; use the nearest known size */
2072 SizeDefaults *szd, *nearest;
2073 int distance = 99999;
2074 nearest = szd = sizeDefaults;
2075 while (szd->name != NULL) {
2076 if (abs(szd->squareSize - squareSize) < distance) {
2078 distance = abs(szd->squareSize - squareSize);
2079 if (distance == 0) break;
2083 if (i < 2) lineGap = nearest->lineGap;
2084 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2085 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2086 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2087 if (i < 6) smallLayout = nearest->smallLayout;
2088 if (i < 7) tinyLayout = nearest->tinyLayout;
2091 SizeDefaults *szd = sizeDefaults;
2092 if (*appData.boardSize == NULLCHAR) {
2093 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2094 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2097 if (szd->name == NULL) szd--;
2098 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2100 while (szd->name != NULL &&
2101 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2102 if (szd->name == NULL) {
2103 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2104 programName, appData.boardSize);
2108 squareSize = szd->squareSize;
2109 lineGap = szd->lineGap;
2110 clockFontPxlSize = szd->clockFontPxlSize;
2111 coordFontPxlSize = szd->coordFontPxlSize;
2112 fontPxlSize = szd->fontPxlSize;
2113 smallLayout = szd->smallLayout;
2114 tinyLayout = szd->tinyLayout;
2115 // [HGM] font: use defaults from settings file if available and not overruled
2117 if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2118 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2119 if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2120 appData.font = fontTable[MESSAGE_FONT][squareSize];
2121 if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2122 appData.coordFont = fontTable[COORD_FONT][squareSize];
2124 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2125 if (strlen(appData.pixmapDirectory) > 0) {
2126 p = ExpandPathName(appData.pixmapDirectory);
2128 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2129 appData.pixmapDirectory);
2132 if (appData.debugMode) {
2133 fprintf(stderr, _("\
2134 XBoard square size (hint): %d\n\
2135 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2137 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2138 if (appData.debugMode) {
2139 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2142 defaultLineGap = lineGap;
2143 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2145 /* [HR] height treated separately (hacked) */
2146 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2147 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2148 if (appData.showJail == 1) {
2149 /* Jail on top and bottom */
2150 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2151 XtSetArg(boardArgs[2], XtNheight,
2152 boardHeight + 2*(lineGap + squareSize));
2153 } else if (appData.showJail == 2) {
2155 XtSetArg(boardArgs[1], XtNwidth,
2156 boardWidth + 2*(lineGap + squareSize));
2157 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2160 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2161 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2165 * Determine what fonts to use.
2168 appData.font = InsertPxlSize(appData.font, fontPxlSize);
2169 appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
2170 appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
2171 fontSet = CreateFontSet(appData.font);
2172 clockFontSet = CreateFontSet(appData.clockFont);
2174 /* For the coordFont, use the 0th font of the fontset. */
2175 XFontSet coordFontSet = CreateFontSet(appData.coordFont);
2176 XFontStruct **font_struct_list;
2177 char **font_name_list;
2178 XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
2179 coordFontID = XLoadFont(xDisplay, font_name_list[0]);
2180 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2183 appData.font = FindFont(appData.font, fontPxlSize);
2184 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2185 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2186 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2187 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2188 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2189 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2191 countFontID = coordFontID; // [HGM] holdings
2192 countFontStruct = coordFontStruct;
2194 xdb = XtDatabase(xDisplay);
2196 XrmPutLineResource(&xdb, "*international: True");
2197 vTo.size = sizeof(XFontSet);
2198 vTo.addr = (XtPointer) &fontSet;
2199 XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
2201 XrmPutStringResource(&xdb, "*font", appData.font);
2205 * Detect if there are not enough colors available and adapt.
2207 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2208 appData.monoMode = True;
2211 forceMono = MakeColors();
2214 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2216 appData.monoMode = True;
2219 if (appData.lowTimeWarning && !appData.monoMode) {
2220 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2221 vFrom.size = strlen(appData.lowTimeWarningColor);
2222 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2223 if (vTo.addr == NULL)
2224 appData.monoMode = True;
2226 lowTimeWarningColor = *(Pixel *) vTo.addr;
2229 if (appData.monoMode && appData.debugMode) {
2230 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2231 (unsigned long) XWhitePixel(xDisplay, xScreen),
2232 (unsigned long) XBlackPixel(xDisplay, xScreen));
2235 ParseIcsTextColors();
2236 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2237 textColors[ColorNone].attr = 0;
2239 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2245 layoutName = "tinyLayout";
2246 } else if (smallLayout) {
2247 layoutName = "smallLayout";
2249 layoutName = "normalLayout";
2251 /* Outer layoutWidget is there only to provide a name for use in
2252 resources that depend on the layout style */
2254 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2255 layoutArgs, XtNumber(layoutArgs));
2257 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2258 formArgs, XtNumber(formArgs));
2259 XtSetArg(args[0], XtNdefaultDistance, &sep);
2260 XtGetValues(formWidget, args, 1);
2263 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar, boardWidth);
2264 XtSetArg(args[0], XtNtop, XtChainTop);
2265 XtSetArg(args[1], XtNbottom, XtChainTop);
2266 XtSetArg(args[2], XtNright, XtChainLeft);
2267 XtSetValues(menuBarWidget, args, 3);
2269 widgetList[j++] = whiteTimerWidget =
2270 XtCreateWidget("whiteTime", labelWidgetClass,
2271 formWidget, timerArgs, XtNumber(timerArgs));
2273 XtSetArg(args[0], XtNfontSet, clockFontSet);
2275 XtSetArg(args[0], XtNfont, clockFontStruct);
2277 XtSetArg(args[1], XtNtop, XtChainTop);
2278 XtSetArg(args[2], XtNbottom, XtChainTop);
2279 XtSetValues(whiteTimerWidget, args, 3);
2281 widgetList[j++] = blackTimerWidget =
2282 XtCreateWidget("blackTime", labelWidgetClass,
2283 formWidget, timerArgs, XtNumber(timerArgs));
2285 XtSetArg(args[0], XtNfontSet, clockFontSet);
2287 XtSetArg(args[0], XtNfont, clockFontStruct);
2289 XtSetArg(args[1], XtNtop, XtChainTop);
2290 XtSetArg(args[2], XtNbottom, XtChainTop);
2291 XtSetValues(blackTimerWidget, args, 3);
2293 if (appData.titleInWindow) {
2294 widgetList[j++] = titleWidget =
2295 XtCreateWidget("title", labelWidgetClass, formWidget,
2296 titleArgs, XtNumber(titleArgs));
2297 XtSetArg(args[0], XtNtop, XtChainTop);
2298 XtSetArg(args[1], XtNbottom, XtChainTop);
2299 XtSetValues(titleWidget, args, 2);
2302 if (appData.showButtonBar) {
2303 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2304 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2305 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2306 XtSetArg(args[2], XtNtop, XtChainTop);
2307 XtSetArg(args[3], XtNbottom, XtChainTop);
2308 XtSetValues(buttonBarWidget, args, 4);
2311 widgetList[j++] = messageWidget =
2312 XtCreateWidget("message", labelWidgetClass, formWidget,
2313 messageArgs, XtNumber(messageArgs));
2314 XtSetArg(args[0], XtNtop, XtChainTop);
2315 XtSetArg(args[1], XtNbottom, XtChainTop);
2316 XtSetValues(messageWidget, args, 2);
2318 widgetList[j++] = boardWidget =
2319 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2320 XtNumber(boardArgs));
2322 XtManageChildren(widgetList, j);
2324 timerWidth = (boardWidth - sep) / 2;
2325 XtSetArg(args[0], XtNwidth, timerWidth);
2326 XtSetValues(whiteTimerWidget, args, 1);
2327 XtSetValues(blackTimerWidget, args, 1);
2329 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2330 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2331 XtGetValues(whiteTimerWidget, args, 2);
2333 if (appData.showButtonBar) {
2334 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2335 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2336 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2340 * formWidget uses these constraints but they are stored
2344 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2345 XtSetValues(menuBarWidget, args, i);
2346 if (appData.titleInWindow) {
2349 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2350 XtSetValues(whiteTimerWidget, args, i);
2352 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2353 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2354 XtSetValues(blackTimerWidget, args, i);
2356 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2357 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2358 XtSetValues(titleWidget, args, i);
2360 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2361 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2362 XtSetValues(messageWidget, args, i);
2363 if (appData.showButtonBar) {
2365 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2366 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2367 XtSetValues(buttonBarWidget, args, i);
2371 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2372 XtSetValues(whiteTimerWidget, args, i);
2374 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2375 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2376 XtSetValues(blackTimerWidget, args, i);
2378 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2379 XtSetValues(titleWidget, args, i);
2381 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2382 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2383 XtSetValues(messageWidget, args, i);
2384 if (appData.showButtonBar) {
2386 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2387 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2388 XtSetValues(buttonBarWidget, args, i);
2393 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2394 XtSetValues(whiteTimerWidget, args, i);
2396 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2397 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2398 XtSetValues(blackTimerWidget, args, i);
2400 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2401 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2402 XtSetValues(messageWidget, args, i);
2403 if (appData.showButtonBar) {
2405 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2406 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2407 XtSetValues(buttonBarWidget, args, i);
2411 XtSetArg(args[0], XtNfromVert, messageWidget);
2412 XtSetArg(args[1], XtNtop, XtChainTop);
2413 XtSetArg(args[2], XtNbottom, XtChainBottom);
2414 XtSetArg(args[3], XtNleft, XtChainLeft);
2415 XtSetArg(args[4], XtNright, XtChainRight);
2416 XtSetValues(boardWidget, args, 5);
2418 XtRealizeWidget(shellWidget);
2421 XtSetArg(args[0], XtNx, wpMain.x);
2422 XtSetArg(args[1], XtNy, wpMain.y);
2423 XtSetValues(shellWidget, args, 2);
2427 * Correct the width of the message and title widgets.
2428 * It is not known why some systems need the extra fudge term.
2429 * The value "2" is probably larger than needed.
2431 XawFormDoLayout(formWidget, False);
2433 #define WIDTH_FUDGE 2
2435 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2436 XtSetArg(args[i], XtNheight, &h); i++;
2437 XtGetValues(messageWidget, args, i);
2438 if (appData.showButtonBar) {
2440 XtSetArg(args[i], XtNwidth, &w); i++;
2441 XtGetValues(buttonBarWidget, args, i);
2442 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2444 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2447 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2448 if (gres != XtGeometryYes && appData.debugMode) {
2449 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2450 programName, gres, w, h, wr, hr);
2453 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2454 /* The size used for the child widget in layout lags one resize behind
2455 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2457 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2458 if (gres != XtGeometryYes && appData.debugMode) {
2459 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2460 programName, gres, w, h, wr, hr);
2463 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2464 XtSetArg(args[1], XtNright, XtChainRight);
2465 XtSetValues(messageWidget, args, 2);
2467 if (appData.titleInWindow) {
2469 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2470 XtSetArg(args[i], XtNheight, &h); i++;
2471 XtGetValues(titleWidget, args, i);
2473 w = boardWidth - 2*bor;
2475 XtSetArg(args[0], XtNwidth, &w);
2476 XtGetValues(menuBarWidget, args, 1);
2477 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2480 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2481 if (gres != XtGeometryYes && appData.debugMode) {
2483 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2484 programName, gres, w, h, wr, hr);
2487 XawFormDoLayout(formWidget, True);
2489 xBoardWindow = XtWindow(boardWidget);
2491 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2492 // not need to go into InitDrawingSizes().
2496 * Create X checkmark bitmap and initialize option menu checks.
2498 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2499 checkmark_bits, checkmark_width, checkmark_height);
2500 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2501 #ifndef OPTIONSDIALOG
2502 if (appData.alwaysPromoteToQueen) {
2503 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2506 if (appData.animateDragging) {
2507 XtSetValues(XtNameToWidget(menuBarWidget,
2508 "menuOptions.Animate Dragging"),
2511 if (appData.animate) {
2512 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2515 if (appData.autoCallFlag) {
2516 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2519 if (appData.autoFlipView) {
2520 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2523 if (appData.blindfold) {
2524 XtSetValues(XtNameToWidget(menuBarWidget,
2525 "menuOptions.Blindfold"), args, 1);
2527 if (appData.flashCount > 0) {
2528 XtSetValues(XtNameToWidget(menuBarWidget,
2529 "menuOptions.Flash Moves"),
2533 if (appData.highlightDragging) {
2534 XtSetValues(XtNameToWidget(menuBarWidget,
2535 "menuOptions.Highlight Dragging"),
2539 if (appData.highlightLastMove) {
2540 XtSetValues(XtNameToWidget(menuBarWidget,
2541 "menuOptions.Highlight Last Move"),
2544 if (appData.highlightMoveWithArrow) {
2545 XtSetValues(XtNameToWidget(menuBarWidget,
2546 "menuOptions.Arrow"),
2549 // if (appData.icsAlarm) {
2550 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2553 if (appData.ringBellAfterMoves) {
2554 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2557 if (appData.oneClick) {
2558 XtSetValues(XtNameToWidget(menuBarWidget,
2559 "menuOptions.OneClick"), args, 1);
2561 if (appData.periodicUpdates) {
2562 XtSetValues(XtNameToWidget(menuBarWidget,
2563 "menuOptions.Periodic Updates"), args, 1);
2565 if (appData.ponderNextMove) {
2566 XtSetValues(XtNameToWidget(menuBarWidget,
2567 "menuOptions.Ponder Next Move"), args, 1);
2569 if (appData.popupExitMessage) {
2570 XtSetValues(XtNameToWidget(menuBarWidget,
2571 "menuOptions.Popup Exit Message"), args, 1);
2573 if (appData.popupMoveErrors) {
2574 XtSetValues(XtNameToWidget(menuBarWidget,
2575 "menuOptions.Popup Move Errors"), args, 1);
2577 // if (appData.premove) {
2578 // XtSetValues(XtNameToWidget(menuBarWidget,
2579 // "menuOptions.Premove"), args, 1);
2581 if (appData.showCoords) {
2582 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2585 if (appData.hideThinkingFromHuman) {
2586 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2589 if (appData.testLegality) {
2590 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2594 if (saveSettingsOnExit) {
2595 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2602 ReadBitmap(&wIconPixmap, "icon_white.bm",
2603 icon_white_bits, icon_white_width, icon_white_height);
2604 ReadBitmap(&bIconPixmap, "icon_black.bm",
2605 icon_black_bits, icon_black_width, icon_black_height);
2606 iconPixmap = wIconPixmap;
2608 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2609 XtSetValues(shellWidget, args, i);
2612 * Create a cursor for the board widget.
2614 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2615 XChangeWindowAttributes(xDisplay, xBoardWindow,
2616 CWCursor, &window_attributes);
2619 * Inhibit shell resizing.
2621 shellArgs[0].value = (XtArgVal) &w;
2622 shellArgs[1].value = (XtArgVal) &h;
2623 XtGetValues(shellWidget, shellArgs, 2);
2624 shellArgs[4].value = shellArgs[2].value = w;
2625 shellArgs[5].value = shellArgs[3].value = h;
2626 XtSetValues(shellWidget, &shellArgs[2], 4);
2627 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2628 marginH = h - boardHeight;
2630 CatchDeleteWindow(shellWidget, "QuitProc");
2638 if (appData.animate || appData.animateDragging)
2641 XtAugmentTranslations(formWidget,
2642 XtParseTranslationTable(globalTranslations));
2643 XtAugmentTranslations(boardWidget,
2644 XtParseTranslationTable(boardTranslations));
2645 XtAugmentTranslations(whiteTimerWidget,
2646 XtParseTranslationTable(whiteTranslations));
2647 XtAugmentTranslations(blackTimerWidget,
2648 XtParseTranslationTable(blackTranslations));
2650 /* Why is the following needed on some versions of X instead
2651 * of a translation? */
2652 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2653 (XtEventHandler) EventProc, NULL);
2655 XtAddEventHandler(formWidget, KeyPressMask, False,
2656 (XtEventHandler) MoveTypeInProc, NULL);
2658 /* [AS] Restore layout */
2659 if( wpMoveHistory.visible ) {
2663 if( wpEvalGraph.visible )
2668 if( wpEngineOutput.visible ) {
2669 EngineOutputPopUp();
2674 if (errorExitStatus == -1) {
2675 if (appData.icsActive) {
2676 /* We now wait until we see "login:" from the ICS before
2677 sending the logon script (problems with timestamp otherwise) */
2678 /*ICSInitScript();*/
2679 if (appData.icsInputBox) ICSInputBoxPopUp();
2683 signal(SIGWINCH, TermSizeSigHandler);
2685 signal(SIGINT, IntSigHandler);
2686 signal(SIGTERM, IntSigHandler);
2687 if (*appData.cmailGameName != NULLCHAR) {
2688 signal(SIGUSR1, CmailSigHandler);
2691 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2693 // XtSetKeyboardFocus(shellWidget, formWidget);
2694 XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
2696 XtAppMainLoop(appContext);
2697 if (appData.debugMode) fclose(debugFP); // [DM] debug
2701 static Boolean noEcho;
2706 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2707 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2709 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2710 unlink(gameCopyFilename);
2711 unlink(gamePasteFilename);
2712 if(noEcho) EchoOn();
2716 TermSizeSigHandler (int sig)
2722 IntSigHandler (int sig)
2728 CmailSigHandler (int sig)
2733 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2735 /* Activate call-back function CmailSigHandlerCallBack() */
2736 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2738 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2742 CmailSigHandlerCallBack (InputSourceRef isr, VOIDSTAR closure, char *message, int count, int error)
2745 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2747 /**** end signal code ****/
2753 /* try to open the icsLogon script, either in the location given
2754 * or in the users HOME directory
2761 f = fopen(appData.icsLogon, "r");
2764 homedir = getenv("HOME");
2765 if (homedir != NULL)
2767 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2768 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2769 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2770 f = fopen(buf, "r");
2775 ProcessICSInitScript(f);
2777 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2796 GreyRevert (Boolean grey)
2799 if (!menuBarWidget) return;
2800 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2802 DisplayError("menuEdit.Revert", 0);
2804 XtSetSensitive(w, !grey);
2806 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2808 DisplayError("menuEdit.Annotate", 0);
2810 XtSetSensitive(w, !grey);
2815 SetMenuEnables (Enables *enab)
2818 if (!menuBarWidget) return;
2819 while (enab->name != NULL) {
2820 w = XtNameToWidget(menuBarWidget, enab->name);
2822 DisplayError(enab->name, 0);
2824 XtSetSensitive(w, enab->value);
2830 Enables icsEnables[] = {
2831 { "menuFile.Mail Move", False },
2832 { "menuFile.Reload CMail Message", False },
2833 { "menuMode.Machine Black", False },
2834 { "menuMode.Machine White", False },
2835 { "menuMode.Analysis Mode", False },
2836 { "menuMode.Analyze File", False },
2837 { "menuMode.Two Machines", False },
2838 { "menuMode.Machine Match", False },
2840 { "menuEngine.Hint", False },
2841 { "menuEngine.Book", False },
2842 { "menuEngine.Move Now", False },
2843 #ifndef OPTIONSDIALOG
2844 { "menuOptions.Periodic Updates", False },
2845 { "menuOptions.Hide Thinking", False },
2846 { "menuOptions.Ponder Next Move", False },
2849 { "menuEngine.Engine #1 Settings", False },
2850 { "menuEngine.Engine #2 Settings", False },
2851 { "menuEngine.Load Engine", False },
2852 { "menuEdit.Annotate", False },
2853 { "menuOptions.Match", False },
2857 Enables ncpEnables[] = {
2858 { "menuFile.Mail Move", False },
2859 { "menuFile.Reload CMail Message", False },
2860 { "menuMode.Machine White", False },
2861 { "menuMode.Machine Black", False },
2862 { "menuMode.Analysis Mode", False },
2863 { "menuMode.Analyze File", False },
2864 { "menuMode.Two Machines", False },
2865 { "menuMode.Machine Match", False },
2866 { "menuMode.ICS Client", False },
2867 { "menuView.ICStex", False },
2868 { "menuView.ICS Input Box", False },
2869 { "Action", False },
2870 { "menuEdit.Revert", False },
2871 { "menuEdit.Annotate", False },
2872 { "menuEngine.Engine #1 Settings", False },
2873 { "menuEngine.Engine #2 Settings", False },
2874 { "menuEngine.Move Now", False },
2875 { "menuEngine.Retract Move", False },
2876 { "menuOptions.ICS", False },
2877 #ifndef OPTIONSDIALOG
2878 { "menuOptions.Auto Flag", False },
2879 { "menuOptions.Auto Flip View", False },
2880 // { "menuOptions.ICS Alarm", False },
2881 { "menuOptions.Move Sound", False },
2882 { "menuOptions.Hide Thinking", False },
2883 { "menuOptions.Periodic Updates", False },
2884 { "menuOptions.Ponder Next Move", False },
2886 { "menuEngine.Hint", False },
2887 { "menuEngine.Book", False },
2891 Enables gnuEnables[] = {
2892 { "menuMode.ICS Client", False },
2893 { "menuView.ICStex", False },
2894 { "menuView.ICS Input Box", False },
2895 { "menuAction.Accept", False },
2896 { "menuAction.Decline", False },
2897 { "menuAction.Rematch", False },
2898 { "menuAction.Adjourn", False },
2899 { "menuAction.Stop Examining", False },
2900 { "menuAction.Stop Observing", False },
2901 { "menuAction.Upload to Examine", False },
2902 { "menuEdit.Revert", False },
2903 { "menuEdit.Annotate", False },
2904 { "menuOptions.ICS", False },
2906 /* The next two options rely on SetCmailMode being called *after* */
2907 /* SetGNUMode so that when GNU is being used to give hints these */
2908 /* menu options are still available */
2910 { "menuFile.Mail Move", False },
2911 { "menuFile.Reload CMail Message", False },
2912 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
2913 { "menuMode.Machine White", True },
2914 { "menuMode.Machine Black", True },
2915 { "menuMode.Analysis Mode", True },
2916 { "menuMode.Analyze File", True },
2917 { "menuMode.Two Machines", True },
2918 { "menuMode.Machine Match", True },
2919 { "menuEngine.Engine #1 Settings", True },
2920 { "menuEngine.Engine #2 Settings", True },
2921 { "menuEngine.Hint", True },
2922 { "menuEngine.Book", True },
2923 { "menuEngine.Move Now", True },
2924 { "menuEngine.Retract Move", True },
2929 Enables cmailEnables[] = {
2931 { "menuAction.Call Flag", False },
2932 { "menuAction.Draw", True },
2933 { "menuAction.Adjourn", False },
2934 { "menuAction.Abort", False },
2935 { "menuAction.Stop Observing", False },
2936 { "menuAction.Stop Examining", False },
2937 { "menuFile.Mail Move", True },
2938 { "menuFile.Reload CMail Message", True },
2942 Enables trainingOnEnables[] = {
2943 { "menuMode.Edit Comment", False },
2944 { "menuMode.Pause", False },
2945 { "menuEdit.Forward", False },
2946 { "menuEdit.Backward", False },
2947 { "menuEdit.Forward to End", False },
2948 { "menuEdit.Back to Start", False },
2949 { "menuEngine.Move Now", False },
2950 { "menuEdit.Truncate Game", False },
2954 Enables trainingOffEnables[] = {
2955 { "menuMode.Edit Comment", True },
2956 { "menuMode.Pause", True },
2957 { "menuEdit.Forward", True },
2958 { "menuEdit.Backward", True },
2959 { "menuEdit.Forward to End", True },
2960 { "menuEdit.Back to Start", True },
2961 { "menuEngine.Move Now", True },
2962 { "menuEdit.Truncate Game", True },
2966 Enables machineThinkingEnables[] = {
2967 { "menuFile.Load Game", False },
2968 // { "menuFile.Load Next Game", False },
2969 // { "menuFile.Load Previous Game", False },
2970 // { "menuFile.Reload Same Game", False },
2971 { "menuEdit.Paste Game", False },
2972 { "menuFile.Load Position", False },
2973 // { "menuFile.Load Next Position", False },
2974 // { "menuFile.Load Previous Position", False },
2975 // { "menuFile.Reload Same Position", False },
2976 { "menuEdit.Paste Position", False },
2977 { "menuMode.Machine White", False },
2978 { "menuMode.Machine Black", False },
2979 { "menuMode.Two Machines", False },
2980 // { "menuMode.Machine Match", False },
2981 { "menuEngine.Retract Move", False },
2985 Enables userThinkingEnables[] = {
2986 { "menuFile.Load Game", True },
2987 // { "menuFile.Load Next Game", True },
2988 // { "menuFile.Load Previous Game", True },
2989 // { "menuFile.Reload Same Game", True },
2990 { "menuEdit.Paste Game", True },
2991 { "menuFile.Load Position", True },
2992 // { "menuFile.Load Next Position", True },
2993 // { "menuFile.Load Previous Position", True },
2994 // { "menuFile.Reload Same Position", True },
2995 { "menuEdit.Paste Position", True },
2996 { "menuMode.Machine White", True },
2997 { "menuMode.Machine Black", True },
2998 { "menuMode.Two Machines", True },
2999 // { "menuMode.Machine Match", True },
3000 { "menuEngine.Retract Move", True },
3007 SetMenuEnables(icsEnables);
3010 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
3011 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3012 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
3020 SetMenuEnables(ncpEnables);
3026 SetMenuEnables(gnuEnables);
3032 SetMenuEnables(cmailEnables);
3036 SetTrainingModeOn ()
3038 SetMenuEnables(trainingOnEnables);
3039 if (appData.showButtonBar) {
3040 XtSetSensitive(buttonBarWidget, False);
3046 SetTrainingModeOff ()
3048 SetMenuEnables(trainingOffEnables);
3049 if (appData.showButtonBar) {
3050 XtSetSensitive(buttonBarWidget, True);
3055 SetUserThinkingEnables ()
3057 if (appData.noChessProgram) return;
3058 SetMenuEnables(userThinkingEnables);
3062 SetMachineThinkingEnables ()
3064 if (appData.noChessProgram) return;
3065 SetMenuEnables(machineThinkingEnables);
3067 case MachinePlaysBlack:
3068 case MachinePlaysWhite:
3069 case TwoMachinesPlay:
3070 XtSetSensitive(XtNameToWidget(menuBarWidget,
3071 ModeToWidgetName(gameMode)), True);
3078 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
3079 #define HISTORY_SIZE 64
3080 static char *history[HISTORY_SIZE];
3081 int histIn = 0, histP = 0;
3084 SaveInHistory (char *cmd)
3086 if (history[histIn] != NULL) {
3087 free(history[histIn]);
3088 history[histIn] = NULL;
3090 if (*cmd == NULLCHAR) return;
3091 history[histIn] = StrSave(cmd);
3092 histIn = (histIn + 1) % HISTORY_SIZE;
3093 if (history[histIn] != NULL) {
3094 free(history[histIn]);
3095 history[histIn] = NULL;
3101 PrevInHistory (char *cmd)
3104 if (histP == histIn) {
3105 if (history[histIn] != NULL) free(history[histIn]);
3106 history[histIn] = StrSave(cmd);
3108 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3109 if (newhp == histIn || history[newhp] == NULL) return NULL;
3111 return history[histP];
3117 if (histP == histIn) return NULL;
3118 histP = (histP + 1) % HISTORY_SIZE;
3119 return history[histP];
3121 // end of borrowed code
3123 #define Abs(n) ((n)<0 ? -(n) : (n))
3127 InsertPxlSize (char *pattern, int 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 (char *base_fnt_lst)
3181 char **missing_list;
3185 fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
3186 &missing_list, &missing_count, &def_string);
3187 if (appData.debugMode) {
3189 XFontStruct **font_struct_list;
3190 char **font_name_list;
3191 fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
3193 fprintf(debugFP, " got list %s, locale %s\n",
3194 XBaseFontNameListOfFontSet(fntSet),
3195 XLocaleOfFontSet(fntSet));
3196 count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
3197 for (i = 0; i < count; i++) {
3198 fprintf(debugFP, " got charset %s\n", font_name_list[i]);
3201 for (i = 0; i < missing_count; i++) {
3202 fprintf(debugFP, " missing charset %s\n", missing_list[i]);
3205 if (fntSet == NULL) {
3206 fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
3211 #else // not ENABLE_NLS
3213 * Find a font that matches "pattern" that is as close as
3214 * possible to the targetPxlSize. Prefer fonts that are k
3215 * pixels smaller to fonts that are k pixels larger. The
3216 * pattern must be in the X Consortium standard format,
3217 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3218 * The return value should be freed with XtFree when no
3222 FindFont (char *pattern, int targetPxlSize)
3224 char **fonts, *p, *best, *scalable, *scalableTail;
3225 int i, j, nfonts, minerr, err, pxlSize;
3227 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3229 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3230 programName, pattern);
3237 for (i=0; i<nfonts; i++) {
3240 if (*p != '-') continue;
3242 if (*p == NULLCHAR) break;
3243 if (*p++ == '-') j++;
3245 if (j < 7) continue;
3248 scalable = fonts[i];
3251 err = pxlSize - targetPxlSize;
3252 if (Abs(err) < Abs(minerr) ||
3253 (minerr > 0 && err < 0 && -err == minerr)) {
3259 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3260 /* If the error is too big and there is a scalable font,
3261 use the scalable font. */
3262 int headlen = scalableTail - scalable;
3263 p = (char *) XtMalloc(strlen(scalable) + 10);
3264 while (isdigit(*scalableTail)) scalableTail++;
3265 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3267 p = (char *) XtMalloc(strlen(best) + 2);
3268 safeStrCpy(p, best, strlen(best)+1 );
3270 if (appData.debugMode) {
3271 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3272 pattern, targetPxlSize, p);
3274 XFreeFontNames(fonts);
3281 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3282 // must be called before all non-first callse to CreateGCs()
3283 XtReleaseGC(shellWidget, highlineGC);
3284 XtReleaseGC(shellWidget, lightSquareGC);
3285 XtReleaseGC(shellWidget, darkSquareGC);
3286 XtReleaseGC(shellWidget, lineGC);
3287 if (appData.monoMode) {
3288 if (DefaultDepth(xDisplay, xScreen) == 1) {
3289 XtReleaseGC(shellWidget, wbPieceGC);
3291 XtReleaseGC(shellWidget, bwPieceGC);
3294 XtReleaseGC(shellWidget, prelineGC);
3295 XtReleaseGC(shellWidget, jailSquareGC);
3296 XtReleaseGC(shellWidget, wdPieceGC);
3297 XtReleaseGC(shellWidget, wlPieceGC);
3298 XtReleaseGC(shellWidget, wjPieceGC);
3299 XtReleaseGC(shellWidget, bdPieceGC);
3300 XtReleaseGC(shellWidget, blPieceGC);
3301 XtReleaseGC(shellWidget, bjPieceGC);
3306 CreateGCs (int redo)
3308 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3309 | GCBackground | GCFunction | GCPlaneMask;
3310 XGCValues gc_values;
3313 gc_values.plane_mask = AllPlanes;
3314 gc_values.line_width = lineGap;
3315 gc_values.line_style = LineSolid;
3316 gc_values.function = GXcopy;
3319 DeleteGCs(); // called a second time; clean up old GCs first
3320 } else { // [HGM] grid and font GCs created on first call only
3321 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3322 gc_values.background = XWhitePixel(xDisplay, xScreen);
3323 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3324 XSetFont(xDisplay, coordGC, coordFontID);
3326 // [HGM] make font for holdings counts (white on black)
3327 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3328 gc_values.background = XBlackPixel(xDisplay, xScreen);
3329 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3330 XSetFont(xDisplay, countGC, countFontID);
3332 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3333 gc_values.background = XBlackPixel(xDisplay, xScreen);
3334 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3336 if (appData.monoMode) {
3337 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3338 gc_values.background = XWhitePixel(xDisplay, xScreen);
3339 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3341 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3342 gc_values.background = XBlackPixel(xDisplay, xScreen);
3343 lightSquareGC = wbPieceGC
3344 = XtGetGC(shellWidget, value_mask, &gc_values);
3346 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3347 gc_values.background = XWhitePixel(xDisplay, xScreen);
3348 darkSquareGC = bwPieceGC
3349 = XtGetGC(shellWidget, value_mask, &gc_values);
3351 if (DefaultDepth(xDisplay, xScreen) == 1) {
3352 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3353 gc_values.function = GXcopyInverted;
3354 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3355 gc_values.function = GXcopy;
3356 if (XBlackPixel(xDisplay, xScreen) == 1) {
3357 bwPieceGC = darkSquareGC;
3358 wbPieceGC = copyInvertedGC;
3360 bwPieceGC = copyInvertedGC;
3361 wbPieceGC = lightSquareGC;
3365 gc_values.foreground = highlightSquareColor;
3366 gc_values.background = highlightSquareColor;
3367 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3369 gc_values.foreground = premoveHighlightColor;
3370 gc_values.background = premoveHighlightColor;
3371 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3373 gc_values.foreground = lightSquareColor;
3374 gc_values.background = darkSquareColor;
3375 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3377 gc_values.foreground = darkSquareColor;
3378 gc_values.background = lightSquareColor;
3379 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3381 gc_values.foreground = jailSquareColor;
3382 gc_values.background = jailSquareColor;
3383 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3385 gc_values.foreground = whitePieceColor;
3386 gc_values.background = darkSquareColor;
3387 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3389 gc_values.foreground = whitePieceColor;
3390 gc_values.background = lightSquareColor;
3391 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3393 gc_values.foreground = whitePieceColor;
3394 gc_values.background = jailSquareColor;
3395 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3397 gc_values.foreground = blackPieceColor;
3398 gc_values.background = darkSquareColor;
3399 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3401 gc_values.foreground = blackPieceColor;
3402 gc_values.background = lightSquareColor;
3403 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3405 gc_values.foreground = blackPieceColor;
3406 gc_values.background = jailSquareColor;
3407 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3412 loadXIM (XImage *xim, XImage *xmask, char *filename, Pixmap *dest, Pixmap *mask)
3420 fp = fopen(filename, "rb");
3422 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3429 for (y=0; y<h; ++y) {
3430 for (x=0; x<h; ++x) {
3435 XPutPixel(xim, x, y, blackPieceColor);
3437 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3440 XPutPixel(xim, x, y, darkSquareColor);
3442 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3445 XPutPixel(xim, x, y, whitePieceColor);
3447 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3450 XPutPixel(xim, x, y, lightSquareColor);
3452 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3460 /* create Pixmap of piece */
3461 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3463 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3466 /* create Pixmap of clipmask
3467 Note: We assume the white/black pieces have the same
3468 outline, so we make only 6 masks. This is okay
3469 since the XPM clipmask routines do the same. */
3471 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3473 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3476 /* now create the 1-bit version */
3477 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3480 values.foreground = 1;
3481 values.background = 0;
3483 /* Don't use XtGetGC, not read only */
3484 maskGC = XCreateGC(xDisplay, *mask,
3485 GCForeground | GCBackground, &values);
3486 XCopyPlane(xDisplay, temp, *mask, maskGC,
3487 0, 0, squareSize, squareSize, 0, 0, 1);
3488 XFreePixmap(xDisplay, temp);
3493 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3501 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3506 /* The XSynchronize calls were copied from CreatePieces.
3507 Not sure if needed, but can't hurt */
3508 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3511 /* temp needed by loadXIM() */
3512 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3513 0, 0, ss, ss, AllPlanes, XYPixmap);
3515 if (strlen(appData.pixmapDirectory) == 0) {
3519 if (appData.monoMode) {
3520 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3524 fprintf(stderr, _("\nLoading XIMs...\n"));
3526 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3527 fprintf(stderr, "%d", piece+1);
3528 for (kind=0; kind<4; kind++) {
3529 fprintf(stderr, ".");
3530 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3531 ExpandPathName(appData.pixmapDirectory),
3532 piece <= (int) WhiteKing ? "" : "w",
3533 pieceBitmapNames[piece],
3535 ximPieceBitmap[kind][piece] =
3536 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3537 0, 0, ss, ss, AllPlanes, XYPixmap);
3538 if (appData.debugMode)
3539 fprintf(stderr, _("(File:%s:) "), buf);
3540 loadXIM(ximPieceBitmap[kind][piece],
3542 &(xpmPieceBitmap2[kind][piece]),
3543 &(ximMaskPm2[piece]));
3544 if(piece <= (int)WhiteKing)
3545 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3547 fprintf(stderr," ");
3549 /* Load light and dark squares */
3550 /* If the LSQ and DSQ pieces don't exist, we will
3551 draw them with solid squares. */
3552 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3553 if (access(buf, 0) != 0) {
3557 fprintf(stderr, _("light square "));
3559 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3560 0, 0, ss, ss, AllPlanes, XYPixmap);
3561 if (appData.debugMode)
3562 fprintf(stderr, _("(File:%s:) "), buf);
3564 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3565 fprintf(stderr, _("dark square "));
3566 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3567 ExpandPathName(appData.pixmapDirectory), ss);
3568 if (appData.debugMode)
3569 fprintf(stderr, _("(File:%s:) "), buf);
3571 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3572 0, 0, ss, ss, AllPlanes, XYPixmap);
3573 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3574 xpmJailSquare = xpmLightSquare;
3576 fprintf(stderr, _("Done.\n"));
3578 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3581 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3585 CreateXPMBoard (char *s, int kind)
3589 if(!appData.useBitmaps || s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3590 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3591 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3597 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3598 // thisroutine has to be called t free the old piece pixmaps
3600 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3601 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3603 XFreePixmap(xDisplay, xpmLightSquare);
3604 XFreePixmap(xDisplay, xpmDarkSquare);
3613 u_int ss = squareSize;
3615 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3616 XpmColorSymbol symbols[4];
3617 static int redo = False;
3619 if(redo) FreeXPMPieces(); else redo = 1;
3621 /* The XSynchronize calls were copied from CreatePieces.
3622 Not sure if needed, but can't hurt */
3623 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3625 /* Setup translations so piece colors match square colors */
3626 symbols[0].name = "light_piece";
3627 symbols[0].value = appData.whitePieceColor;
3628 symbols[1].name = "dark_piece";
3629 symbols[1].value = appData.blackPieceColor;
3630 symbols[2].name = "light_square";
3631 symbols[2].value = appData.lightSquareColor;
3632 symbols[3].name = "dark_square";
3633 symbols[3].value = appData.darkSquareColor;
3635 attr.valuemask = XpmColorSymbols;
3636 attr.colorsymbols = symbols;
3637 attr.numsymbols = 4;
3639 if (appData.monoMode) {
3640 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3644 if (strlen(appData.pixmapDirectory) == 0) {
3645 XpmPieces* pieces = builtInXpms;
3648 while (pieces->size != squareSize && pieces->size) pieces++;
3649 if (!pieces->size) {