2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
66 # if HAVE_SYS_SOCKET_H
67 # include <sys/socket.h>
68 # include <netinet/in.h>
70 # else /* not HAVE_SYS_SOCKET_H */
71 # if HAVE_LAN_SOCKET_H
72 # include <lan/socket.h>
74 # include <lan/netdb.h>
75 # else /* not HAVE_LAN_SOCKET_H */
76 # define OMIT_SOCKETS 1
77 # endif /* not HAVE_LAN_SOCKET_H */
78 # endif /* not HAVE_SYS_SOCKET_H */
79 #endif /* !OMIT_SOCKETS */
84 #else /* not STDC_HEADERS */
85 extern char *getenv();
88 # else /* not HAVE_STRING_H */
90 # endif /* not HAVE_STRING_H */
91 #endif /* not STDC_HEADERS */
94 # include <sys/fcntl.h>
95 #else /* not HAVE_SYS_FCNTL_H */
98 # endif /* HAVE_FCNTL_H */
99 #endif /* not HAVE_SYS_FCNTL_H */
101 #if HAVE_SYS_SYSTEMINFO_H
102 # include <sys/systeminfo.h>
103 #endif /* HAVE_SYS_SYSTEMINFO_H */
105 #if TIME_WITH_SYS_TIME
106 # include <sys/time.h>
110 # include <sys/time.h>
121 # include <sys/wait.h>
126 # define NAMLEN(dirent) strlen((dirent)->d_name)
127 # define HAVE_DIR_STRUCT
129 # define dirent direct
130 # define NAMLEN(dirent) (dirent)->d_namlen
132 # include <sys/ndir.h>
133 # define HAVE_DIR_STRUCT
136 # include <sys/dir.h>
137 # define HAVE_DIR_STRUCT
141 # define HAVE_DIR_STRUCT
149 #include <X11/Intrinsic.h>
150 #include <X11/StringDefs.h>
151 #include <X11/Shell.h>
152 #include <X11/cursorfont.h>
153 #include <X11/Xatom.h>
154 #include <X11/Xmu/Atoms.h>
156 #include <X11/Xaw3d/Dialog.h>
157 #include <X11/Xaw3d/Form.h>
158 #include <X11/Xaw3d/List.h>
159 #include <X11/Xaw3d/Label.h>
160 #include <X11/Xaw3d/SimpleMenu.h>
161 #include <X11/Xaw3d/SmeBSB.h>
162 #include <X11/Xaw3d/SmeLine.h>
163 #include <X11/Xaw3d/Box.h>
164 #include <X11/Xaw3d/MenuButton.h>
165 #include <X11/Xaw3d/Text.h>
166 #include <X11/Xaw3d/AsciiText.h>
168 #include <X11/Xaw/Dialog.h>
169 #include <X11/Xaw/Form.h>
170 #include <X11/Xaw/List.h>
171 #include <X11/Xaw/Label.h>
172 #include <X11/Xaw/SimpleMenu.h>
173 #include <X11/Xaw/SmeBSB.h>
174 #include <X11/Xaw/SmeLine.h>
175 #include <X11/Xaw/Box.h>
176 #include <X11/Xaw/MenuButton.h>
177 #include <X11/Xaw/Text.h>
178 #include <X11/Xaw/AsciiText.h>
181 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
186 #include "pixmaps/pixmaps.h"
187 #define IMAGE_EXT "xpm"
189 #define IMAGE_EXT "xim"
190 #include "bitmaps/bitmaps.h"
193 #include "bitmaps/icon_white.bm"
194 #include "bitmaps/icon_black.bm"
195 #include "bitmaps/checkmark.bm"
197 #include "frontend.h"
199 #include "backendz.h"
203 #include "xgamelist.h"
204 #include "xhistory.h"
205 #include "xedittags.h"
208 // must be moved to xengineoutput.h
210 void EngineOutputProc P((Widget w, XEvent *event,
211 String *prms, Cardinal *nprms));
212 void EvalGraphProc P((Widget w, XEvent *event,
213 String *prms, Cardinal *nprms));
220 #define usleep(t) _sleep2(((t)+500)/1000)
224 # define _(s) gettext (s)
225 # define N_(s) gettext_noop (s)
243 int main P((int argc, char **argv));
244 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
245 char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 RETSIGTYPE TermSizeSigHandler P((int sig));
249 void CreateGCs P((int redo));
250 void CreateAnyPieces P((void));
251 void CreateXIMPieces P((void));
252 void CreateXPMPieces P((void));
253 void CreateXPMBoard P((char *s, int n));
254 void CreatePieces P((void));
255 void CreatePieceMenus P((void));
256 Widget CreateMenuBar P((Menu *mb));
257 Widget CreateButtonBar P ((MenuItem *mi));
259 char *InsertPxlSize P((char *pattern, int targetPxlSize));
260 XFontSet CreateFontSet P((char *base_fnt_lst));
262 char *FindFont P((char *pattern, int targetPxlSize));
264 void PieceMenuPopup P((Widget w, XEvent *event,
265 String *params, Cardinal *num_params));
266 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
267 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
268 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
269 u_int wreq, u_int hreq));
270 void CreateGrid P((void));
271 int EventToSquare P((int x, int limit));
272 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
273 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
274 void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
275 void HandleUserMove P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void AnimateUserMove P((Widget w, XEvent * event,
278 String * params, Cardinal * nParams));
279 void HandlePV P((Widget w, XEvent * event,
280 String * params, Cardinal * nParams));
281 void SelectPV P((Widget w, XEvent * event,
282 String * params, Cardinal * nParams));
283 void StopPV P((Widget w, XEvent * event,
284 String * params, Cardinal * nParams));
285 void WhiteClock P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void BlackClock P((Widget w, XEvent *event,
288 String *prms, Cardinal *nprms));
289 void DrawPositionProc P((Widget w, XEvent *event,
290 String *prms, Cardinal *nprms));
291 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
293 void CommentClick P((Widget w, XEvent * event,
294 String * params, Cardinal * nParams));
295 void CommentPopUp P((char *title, char *label));
296 void CommentPopDown P((void));
297 void ICSInputBoxPopUp P((void));
298 void ICSInputBoxPopDown P((void));
299 void FileNamePopUp P((char *label, char *def, char *filter,
300 FileProc proc, char *openMode));
301 void FileNamePopDown P((void));
302 void FileNameCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void FileNameAction P((Widget w, XEvent *event,
305 String *prms, Cardinal *nprms));
306 void AskQuestionReplyAction P((Widget w, XEvent *event,
307 String *prms, Cardinal *nprms));
308 void AskQuestionProc P((Widget w, XEvent *event,
309 String *prms, Cardinal *nprms));
310 void AskQuestionPopDown P((void));
311 void PromotionPopDown P((void));
312 void PromotionCallback P((Widget w, XtPointer client_data,
313 XtPointer call_data));
314 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
315 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
319 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
321 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
323 void LoadPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
327 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
329 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
331 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
333 void PastePositionProc P((Widget w, XEvent *event, String *prms,
335 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void SavePositionProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
344 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
348 void MachineWhiteProc P((Widget w, XEvent *event,
349 String *prms, Cardinal *nprms));
350 void AnalyzeModeProc P((Widget w, XEvent *event,
351 String *prms, Cardinal *nprms));
352 void AnalyzeFileProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
356 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void IcsClientProc P((Widget w, XEvent *event, String *prms,
360 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void EditPositionProc P((Widget w, XEvent *event,
362 String *prms, Cardinal *nprms));
363 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void EditCommentProc P((Widget w, XEvent *event,
365 String *prms, Cardinal *nprms));
366 void IcsInputBoxProc P((Widget w, XEvent *event,
367 String *prms, Cardinal *nprms));
368 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void StopObservingProc P((Widget w, XEvent *event, String *prms,
385 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
387 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 Boolean TempBackwardActive = False;
393 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
399 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
401 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
404 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
406 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
408 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
413 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
416 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
418 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
420 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
423 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
425 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
427 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
429 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
431 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
434 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
436 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
438 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
440 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
449 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
450 void DisplayMove P((int moveNumber));
451 void DisplayTitle P((char *title));
452 void ICSInitScript P((void));
453 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
454 void ErrorPopUp P((char *title, char *text, int modal));
455 void ErrorPopDown P((void));
456 static char *ExpandPathName P((char *path));
457 static void CreateAnimVars P((void));
458 static void DragPieceMove P((int x, int y));
459 static void DrawDragPiece P((void));
460 char *ModeToWidgetName P((GameMode mode));
461 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
467 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
468 void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
469 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
470 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
471 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
472 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
473 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
474 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
475 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
476 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
477 void EditBookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
478 void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
479 void GameListOptionsPopDown P(());
480 void GenericPopDown P(());
481 void update_ics_width P(());
482 int get_term_width P(());
483 int CopyMemoProc P(());
484 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
485 Boolean IsDrawArrowEnabled P(());
488 * XBoard depends on Xt R4 or higher
490 int xtVersion = XtSpecificationRelease;
495 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
496 jailSquareColor, highlightSquareColor, premoveHighlightColor;
497 Pixel lowTimeWarningColor;
498 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
499 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
500 wjPieceGC, bjPieceGC, prelineGC, countGC;
501 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
502 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
503 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
504 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
505 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
506 ICSInputShell, fileNameShell, askQuestionShell;
507 Widget historyShell, evalGraphShell, gameListShell;
508 int hOffset; // [HGM] dual
509 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
510 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
511 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
513 XFontSet fontSet, clockFontSet;
516 XFontStruct *clockFontStruct;
518 Font coordFontID, countFontID;
519 XFontStruct *coordFontStruct, *countFontStruct;
520 XtAppContext appContext;
522 char *oldICSInteractionTitle;
526 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
528 Position commentX = -1, commentY = -1;
529 Dimension commentW, commentH;
530 typedef unsigned int BoardSize;
532 Boolean chessProgram;
534 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
535 int squareSize, smallLayout = 0, tinyLayout = 0,
536 marginW, marginH, // [HGM] for run-time resizing
537 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
538 ICSInputBoxUp = False, askQuestionUp = False,
539 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
540 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
541 Pixel timerForegroundPixel, timerBackgroundPixel;
542 Pixel buttonForegroundPixel, buttonBackgroundPixel;
543 char *chessDir, *programName, *programVersion,
544 *gameCopyFilename, *gamePasteFilename;
545 Boolean alwaysOnTop = False;
546 Boolean saveSettingsOnExit;
547 char *settingsFileName;
548 char *icsTextMenuString;
550 char *firstChessProgramNames;
551 char *secondChessProgramNames;
553 WindowPlacement wpMain;
554 WindowPlacement wpConsole;
555 WindowPlacement wpComment;
556 WindowPlacement wpMoveHistory;
557 WindowPlacement wpEvalGraph;
558 WindowPlacement wpEngineOutput;
559 WindowPlacement wpGameList;
560 WindowPlacement wpTags;
562 extern Widget shells[];
563 extern Boolean shellUp[];
567 Pixmap pieceBitmap[2][(int)BlackPawn];
568 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
569 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
570 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
571 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
572 Pixmap xpmBoardBitmap[2];
573 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
574 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
575 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
576 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
577 XImage *ximLightSquare, *ximDarkSquare;
580 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
581 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
583 #define White(piece) ((int)(piece) < (int)BlackPawn)
585 /* Variables for doing smooth animation. This whole thing
586 would be much easier if the board was double-buffered,
587 but that would require a fairly major rewrite. */
592 GC blitGC, pieceGC, outlineGC;
593 XPoint startSquare, prevFrame, mouseDelta;
597 int startBoardX, startBoardY;
600 /* There can be two pieces being animated at once: a player
601 can begin dragging a piece before the remote opponent has moved. */
603 static AnimState game, player;
605 /* Bitmaps for use as masks when drawing XPM pieces.
606 Need one for each black and white piece. */
607 static Pixmap xpmMask[BlackKing + 1];
609 /* This magic number is the number of intermediate frames used
610 in each half of the animation. For short moves it's reduced
611 by 1. The total number of frames will be factor * 2 + 1. */
614 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
616 MenuItem fileMenu[] = {
617 {N_("New Game Ctrl+N"), "New Game", ResetProc},
618 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
619 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
620 {"----", NULL, NothingProc},
621 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
622 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
623 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
624 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
625 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
626 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
627 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
628 {"----", NULL, NothingProc},
629 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
630 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
631 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
632 {"----", NULL, NothingProc},
633 {N_("Mail Move"), "Mail Move", MailMoveProc},
634 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
635 {"----", NULL, NothingProc},
636 {N_("Quit Ctr+Q"), "Exit", QuitProc},
640 MenuItem editMenu[] = {
641 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
642 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
643 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
644 {"----", NULL, NothingProc},
645 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
646 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
647 {"----", NULL, NothingProc},
648 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
649 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
650 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
651 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
652 {N_("Edit Book"), "Edit Book", EditBookProc},
653 {"----", NULL, NothingProc},
654 {N_("Revert Home"), "Revert", RevertProc},
655 {N_("Annotate"), "Annotate", AnnotateProc},
656 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
657 {"----", NULL, NothingProc},
658 {N_("Backward Alt+Left"), "Backward", BackwardProc},
659 {N_("Forward Alt+Right"), "Forward", ForwardProc},
660 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
661 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
665 MenuItem viewMenu[] = {
666 {N_("Flip View F2"), "Flip View", FlipViewProc},
667 {"----", NULL, NothingProc},
668 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
669 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
670 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
671 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
672 {N_("ICS text menu"), "ICStex", IcsTextProc},
673 {"----", NULL, NothingProc},
674 {N_("Tags"), "Show Tags", EditTagsProc},
675 {N_("Comments"), "Show Comments", EditCommentProc},
676 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
677 {"----", NULL, NothingProc},
678 {N_("Board..."), "Board Options", BoardOptionsProc},
679 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
683 MenuItem modeMenu[] = {
684 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
685 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
686 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
687 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
688 {N_("Analyze Game Ctrl+G"), "Analyze File", AnalyzeFileProc },
689 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
690 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
691 {N_("Training"), "Training", TrainingProc},
692 {N_("ICS Client"), "ICS Client", IcsClientProc},
693 {"----", NULL, NothingProc},
694 {N_("Machine Match"), "Machine Match", MatchProc},
695 {N_("Pause Pause"), "Pause", PauseProc},
699 MenuItem actionMenu[] = {
700 {N_("Accept F3"), "Accept", AcceptProc},
701 {N_("Decline F4"), "Decline", DeclineProc},
702 {N_("Rematch F12"), "Rematch", RematchProc},
703 {"----", NULL, NothingProc},
704 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
705 {N_("Draw F6"), "Draw", DrawProc},
706 {N_("Adjourn F7"), "Adjourn", AdjournProc},
707 {N_("Abort F8"),"Abort", AbortProc},
708 {N_("Resign F9"), "Resign", ResignProc},
709 {"----", NULL, NothingProc},
710 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
711 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
712 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
713 {"----", NULL, NothingProc},
714 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
715 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
716 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
720 MenuItem engineMenu[] = {
721 {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
722 {"----", NULL, NothingProc},
723 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
724 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
725 {"----", NULL, NothingProc},
726 {N_("Hint"), "Hint", HintProc},
727 {N_("Book"), "Book", BookProc},
728 {"----", NULL, NothingProc},
729 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
730 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
734 MenuItem optionsMenu[] = {
735 #define OPTIONSDIALOG
737 {N_("General ..."), "General", OptionsProc},
739 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
740 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
741 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
742 {N_("ICS ..."), "ICS", IcsOptionsProc},
743 {N_("Match ..."), "Match", MatchOptionsProc},
744 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
745 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
746 // {N_(" ..."), "", OptionsProc},
747 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
748 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
749 {"----", NULL, NothingProc},
750 #ifndef OPTIONSDIALOG
751 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
752 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
753 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
754 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
755 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
756 {N_("Blindfold"), "Blindfold", BlindfoldProc},
757 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
759 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
761 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
762 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
763 {N_("Move Sound"), "Move Sound", MoveSoundProc},
764 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
765 {N_("One-Click Moving"), "OneClick", OneClickProc},
766 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
767 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
768 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
769 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
770 // {N_("Premove"), "Premove", PremoveProc},
771 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
772 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
773 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
774 {"----", NULL, NothingProc},
776 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
777 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
781 MenuItem helpMenu[] = {
782 {N_("Info XBoard"), "Info XBoard", InfoProc},
783 {N_("Man XBoard F1"), "Man XBoard", ManProc},
784 {"----", NULL, NothingProc},
785 {N_("About XBoard"), "About XBoard", AboutProc},
790 {N_("File"), "File", fileMenu},
791 {N_("Edit"), "Edit", editMenu},
792 {N_("View"), "View", viewMenu},
793 {N_("Mode"), "Mode", modeMenu},
794 {N_("Action"), "Action", actionMenu},
795 {N_("Engine"), "Engine", engineMenu},
796 {N_("Options"), "Options", optionsMenu},
797 {N_("Help"), "Help", helpMenu},
801 #define PAUSE_BUTTON "P"
802 MenuItem buttonBar[] = {
803 {"<<", "<<", ToStartProc},
804 {"<", "<", BackwardProc},
805 {N_(PAUSE_BUTTON), PAUSE_BUTTON, PauseProc},
806 {">", ">", ForwardProc},
807 {">>", ">>", ToEndProc},
811 #define PIECE_MENU_SIZE 18
812 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
813 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
814 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
815 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
816 N_("Empty square"), N_("Clear board") },
817 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
818 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
819 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
820 N_("Empty square"), N_("Clear board") }
822 /* must be in same order as pieceMenuStrings! */
823 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
824 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
825 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
826 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
827 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
828 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
829 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
830 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
831 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
834 #define DROP_MENU_SIZE 6
835 String dropMenuStrings[DROP_MENU_SIZE] = {
836 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
838 /* must be in same order as dropMenuStrings! */
839 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
840 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
841 WhiteRook, WhiteQueen
849 DropMenuEnables dmEnables[] = {
867 { XtNborderWidth, 0 },
868 { XtNdefaultDistance, 0 },
872 { XtNborderWidth, 0 },
873 { XtNresizable, (XtArgVal) True },
877 { XtNborderWidth, 0 },
883 { XtNjustify, (XtArgVal) XtJustifyRight },
884 { XtNlabel, (XtArgVal) "..." },
885 { XtNresizable, (XtArgVal) True },
886 { XtNresize, (XtArgVal) False }
889 Arg messageArgs[] = {
890 { XtNjustify, (XtArgVal) XtJustifyLeft },
891 { XtNlabel, (XtArgVal) "..." },
892 { XtNresizable, (XtArgVal) True },
893 { XtNresize, (XtArgVal) False }
897 { XtNborderWidth, 0 },
898 { XtNjustify, (XtArgVal) XtJustifyLeft }
901 XtResource clientResources[] = {
902 { "flashCount", "flashCount", XtRInt, sizeof(int),
903 XtOffset(AppDataPtr, flashCount), XtRImmediate,
904 (XtPointer) FLASH_COUNT },
907 XrmOptionDescRec shellOptions[] = {
908 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
909 { "-flash", "flashCount", XrmoptionNoArg, "3" },
910 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
913 XtActionsRec boardActions[] = {
914 { "DrawPosition", DrawPositionProc },
915 { "HandleUserMove", HandleUserMove },
916 { "AnimateUserMove", AnimateUserMove },
917 { "HandlePV", HandlePV },
918 { "SelectPV", SelectPV },
919 { "StopPV", StopPV },
920 { "FileNameAction", FileNameAction },
921 { "AskQuestionProc", AskQuestionProc },
922 { "AskQuestionReplyAction", AskQuestionReplyAction },
923 { "PieceMenuPopup", PieceMenuPopup },
924 { "WhiteClock", WhiteClock },
925 { "BlackClock", BlackClock },
926 { "ResetProc", ResetProc },
927 { "NewVariantProc", NewVariantProc },
928 { "LoadGameProc", LoadGameProc },
929 { "LoadNextGameProc", LoadNextGameProc },
930 { "LoadPrevGameProc", LoadPrevGameProc },
931 { "LoadSelectedProc", LoadSelectedProc },
932 { "SetFilterProc", SetFilterProc },
933 { "ReloadGameProc", ReloadGameProc },
934 { "LoadPositionProc", LoadPositionProc },
935 { "LoadNextPositionProc", LoadNextPositionProc },
936 { "LoadPrevPositionProc", LoadPrevPositionProc },
937 { "ReloadPositionProc", ReloadPositionProc },
938 { "CopyPositionProc", CopyPositionProc },
939 { "PastePositionProc", PastePositionProc },
940 { "CopyGameProc", CopyGameProc },
941 { "CopyGameListProc", CopyGameListProc },
942 { "PasteGameProc", PasteGameProc },
943 { "SaveGameProc", SaveGameProc },
944 { "SavePositionProc", SavePositionProc },
945 { "MailMoveProc", MailMoveProc },
946 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
947 { "QuitProc", QuitProc },
948 { "MachineWhiteProc", MachineWhiteProc },
949 { "MachineBlackProc", MachineBlackProc },
950 { "AnalysisModeProc", AnalyzeModeProc },
951 { "AnalyzeFileProc", AnalyzeFileProc },
952 { "TwoMachinesProc", TwoMachinesProc },
953 { "IcsClientProc", IcsClientProc },
954 { "EditGameProc", EditGameProc },
955 { "EditPositionProc", EditPositionProc },
956 { "TrainingProc", EditPositionProc },
957 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
958 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
959 { "ShowGameListProc", ShowGameListProc },
960 { "ShowMoveListProc", HistoryShowProc},
961 { "EditTagsProc", EditCommentProc },
962 { "EditBookProc", EditBookProc },
963 { "EditCommentProc", EditCommentProc },
964 { "IcsInputBoxProc", IcsInputBoxProc },
965 { "PauseProc", PauseProc },
966 { "AcceptProc", AcceptProc },
967 { "DeclineProc", DeclineProc },
968 { "RematchProc", RematchProc },
969 { "CallFlagProc", CallFlagProc },
970 { "DrawProc", DrawProc },
971 { "AdjournProc", AdjournProc },
972 { "AbortProc", AbortProc },
973 { "ResignProc", ResignProc },
974 { "AdjuWhiteProc", AdjuWhiteProc },
975 { "AdjuBlackProc", AdjuBlackProc },
976 { "AdjuDrawProc", AdjuDrawProc },
977 { "TypeInProc", TypeInProc },
978 { "EnterKeyProc", EnterKeyProc },
979 { "UpKeyProc", UpKeyProc },
980 { "DownKeyProc", DownKeyProc },
981 { "StopObservingProc", StopObservingProc },
982 { "StopExaminingProc", StopExaminingProc },
983 { "UploadProc", UploadProc },
984 { "BackwardProc", BackwardProc },
985 { "ForwardProc", ForwardProc },
986 { "TempBackwardProc", TempBackwardProc },
987 { "TempForwardProc", TempForwardProc },
988 { "ToStartProc", ToStartProc },
989 { "ToEndProc", ToEndProc },
990 { "RevertProc", RevertProc },
991 { "AnnotateProc", AnnotateProc },
992 { "TruncateGameProc", TruncateGameProc },
993 { "MoveNowProc", MoveNowProc },
994 { "RetractMoveProc", RetractMoveProc },
995 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
996 { "UciMenuProc", (XtActionProc) UciMenuProc },
997 { "TimeControlProc", (XtActionProc) TimeControlProc },
998 { "FlipViewProc", FlipViewProc },
999 { "PonderNextMoveProc", PonderNextMoveProc },
1000 #ifndef OPTIONSDIALOG
1001 { "AlwaysQueenProc", AlwaysQueenProc },
1002 { "AnimateDraggingProc", AnimateDraggingProc },
1003 { "AnimateMovingProc", AnimateMovingProc },
1004 { "AutoflagProc", AutoflagProc },
1005 { "AutoflipProc", AutoflipProc },
1006 { "BlindfoldProc", BlindfoldProc },
1007 { "FlashMovesProc", FlashMovesProc },
1009 { "HighlightDraggingProc", HighlightDraggingProc },
1011 { "HighlightLastMoveProc", HighlightLastMoveProc },
1012 // { "IcsAlarmProc", IcsAlarmProc },
1013 { "MoveSoundProc", MoveSoundProc },
1014 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1015 { "PopupExitMessageProc", PopupExitMessageProc },
1016 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1017 // { "PremoveProc", PremoveProc },
1018 { "ShowCoordsProc", ShowCoordsProc },
1019 { "ShowThinkingProc", ShowThinkingProc },
1020 { "HideThinkingProc", HideThinkingProc },
1021 { "TestLegalityProc", TestLegalityProc },
1023 { "SaveSettingsProc", SaveSettingsProc },
1024 { "SaveOnExitProc", SaveOnExitProc },
1025 { "InfoProc", InfoProc },
1026 { "ManProc", ManProc },
1027 { "HintProc", HintProc },
1028 { "BookProc", BookProc },
1029 { "AboutGameProc", AboutGameProc },
1030 { "AboutProc", AboutProc },
1031 { "DebugProc", DebugProc },
1032 { "NothingProc", NothingProc },
1033 { "CommentClick", (XtActionProc) CommentClick },
1034 { "CommentPopDown", (XtActionProc) CommentPopDown },
1035 { "TagsPopDown", (XtActionProc) TagsPopDown },
1036 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1037 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1038 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1039 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1040 { "GameListPopDown", (XtActionProc) GameListPopDown },
1041 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1042 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1043 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1044 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1045 { "GenericPopDown", (XtActionProc) GenericPopDown },
1046 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1047 { "SelectMove", (XtActionProc) SelectMove },
1050 char globalTranslations[] =
1051 ":<Key>F9: ResignProc() \n \
1052 :Ctrl<Key>n: ResetProc() \n \
1053 :Meta<Key>V: NewVariantProc() \n \
1054 :Ctrl<Key>o: LoadGameProc() \n \
1055 :Meta<Key>Next: LoadNextGameProc() \n \
1056 :Meta<Key>Prior: LoadPrevGameProc() \n \
1057 :Ctrl<Key>Down: LoadSelectedProc(3) \n \
1058 :Ctrl<Key>Up: LoadSelectedProc(-3) \n \
1059 :Ctrl<Key>s: SaveGameProc() \n \
1060 :Ctrl<Key>c: CopyGameProc() \n \
1061 :Ctrl<Key>v: PasteGameProc() \n \
1062 :Ctrl<Key>O: LoadPositionProc() \n \
1063 :Shift<Key>Next: LoadNextPositionProc() \n \
1064 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1065 :Ctrl<Key>S: SavePositionProc() \n \
1066 :Ctrl<Key>C: CopyPositionProc() \n \
1067 :Ctrl<Key>V: PastePositionProc() \n \
1068 :Ctrl<Key>q: QuitProc() \n \
1069 :Ctrl<Key>w: MachineWhiteProc() \n \
1070 :Ctrl<Key>b: MachineBlackProc() \n \
1071 :Ctrl<Key>t: TwoMachinesProc() \n \
1072 :Ctrl<Key>a: AnalysisModeProc() \n \
1073 :Ctrl<Key>g: AnalyzeFileProc() \n \
1074 :Ctrl<Key>e: EditGameProc() \n \
1075 :Ctrl<Key>E: EditPositionProc() \n \
1076 :Meta<Key>O: EngineOutputProc() \n \
1077 :Meta<Key>E: EvalGraphProc() \n \
1078 :Meta<Key>G: ShowGameListProc() \n \
1079 :Meta<Key>H: ShowMoveListProc() \n \
1080 :<Key>Pause: PauseProc() \n \
1081 :<Key>F3: AcceptProc() \n \
1082 :<Key>F4: DeclineProc() \n \
1083 :<Key>F12: RematchProc() \n \
1084 :<Key>F5: CallFlagProc() \n \
1085 :<Key>F6: DrawProc() \n \
1086 :<Key>F7: AdjournProc() \n \
1087 :<Key>F8: AbortProc() \n \
1088 :<Key>F10: StopObservingProc() \n \
1089 :<Key>F11: StopExaminingProc() \n \
1090 :Meta Ctrl<Key>F12: DebugProc() \n \
1091 :Meta<Key>End: ToEndProc() \n \
1092 :Meta<Key>Right: ForwardProc() \n \
1093 :Meta<Key>Home: ToStartProc() \n \
1094 :Meta<Key>Left: BackwardProc() \n \
1095 :<Key>Left: BackwardProc() \n \
1096 :<Key>Right: ForwardProc() \n \
1097 :<Key>Home: RevertProc() \n \
1098 :<Key>End: TruncateGameProc() \n \
1099 :Ctrl<Key>m: MoveNowProc() \n \
1100 :Ctrl<Key>x: RetractMoveProc() \n \
1101 :Meta<Key>J: EngineMenuProc() \n \
1102 :Meta<Key>U: UciMenuProc() \n \
1103 :Meta<Key>T: TimeControlProc() \n \
1104 :Ctrl<Key>P: PonderNextMoveProc() \n "
1105 #ifndef OPTIONSDIALOG
1107 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1108 :Ctrl<Key>F: AutoflagProc() \n \
1109 :Ctrl<Key>A: AnimateMovingProc() \n \
1110 :Ctrl<Key>L: TestLegalityProc() \n \
1111 :Ctrl<Key>H: HideThinkingProc() \n "
1114 :<Key>F1: ManProc() \n \
1115 :<Key>F2: FlipViewProc() \n \
1116 :Ctrl<KeyDown>.: TempBackwardProc() \n \
1117 :Ctrl<KeyUp>.: TempForwardProc() \n \
1118 :Ctrl<Key>1: AskQuestionProc(\"Direct command\",\
1119 \"Send to chess program:\",,1) \n \
1120 :Ctrl<Key>2: AskQuestionProc(\"Direct command\",\
1121 \"Send to second chess program:\",,2) \n";
1123 char boardTranslations[] =
1124 "<Btn1Down>: HandleUserMove(0) \n \
1125 Shift<Btn1Up>: HandleUserMove(1) \n \
1126 <Btn1Up>: HandleUserMove(0) \n \
1127 <Btn1Motion>: AnimateUserMove() \n \
1128 <Btn3Motion>: HandlePV() \n \
1129 <Btn3Up>: PieceMenuPopup(menuB) \n \
1130 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1131 PieceMenuPopup(menuB) \n \
1132 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1133 PieceMenuPopup(menuW) \n \
1134 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1135 PieceMenuPopup(menuW) \n \
1136 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1137 PieceMenuPopup(menuB) \n";
1139 char whiteTranslations[] =
1140 "Shift<BtnDown>: WhiteClock(1)\n \
1141 <BtnDown>: WhiteClock(0)\n";
1142 char blackTranslations[] =
1143 "Shift<BtnDown>: BlackClock(1)\n \
1144 <BtnDown>: BlackClock(0)\n";
1146 char ICSInputTranslations[] =
1147 "<Key>Up: UpKeyProc() \n "
1148 "<Key>Down: DownKeyProc() \n "
1149 "<Key>Return: EnterKeyProc() \n";
1151 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1152 // as the widget is destroyed before the up-click can call extend-end
1153 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1155 String xboardResources[] = {
1156 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1157 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1158 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1163 /* Max possible square size */
1164 #define MAXSQSIZE 256
1166 static int xpm_avail[MAXSQSIZE];
1168 #ifdef HAVE_DIR_STRUCT
1170 /* Extract piece size from filename */
1172 xpm_getsize(name, len, ext)
1183 if ((p=strchr(name, '.')) == NULL ||
1184 StrCaseCmp(p+1, ext) != 0)
1190 while (*p && isdigit(*p))
1197 /* Setup xpm_avail */
1199 xpm_getavail(dirname, ext)
1207 for (i=0; i<MAXSQSIZE; ++i)
1210 if (appData.debugMode)
1211 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1213 dir = opendir(dirname);
1216 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1217 programName, dirname);
1221 while ((ent=readdir(dir)) != NULL) {
1222 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1223 if (i > 0 && i < MAXSQSIZE)
1233 xpm_print_avail(fp, ext)
1239 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1240 for (i=1; i<MAXSQSIZE; ++i) {
1246 /* Return XPM piecesize closest to size */
1248 xpm_closest_to(dirname, size, ext)
1254 int sm_diff = MAXSQSIZE;
1258 xpm_getavail(dirname, ext);
1260 if (appData.debugMode)
1261 xpm_print_avail(stderr, ext);
1263 for (i=1; i<MAXSQSIZE; ++i) {
1266 diff = (diff<0) ? -diff : diff;
1267 if (diff < sm_diff) {
1275 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1281 #else /* !HAVE_DIR_STRUCT */
1282 /* If we are on a system without a DIR struct, we can't
1283 read the directory, so we can't collect a list of
1284 filenames, etc., so we can't do any size-fitting. */
1286 xpm_closest_to(dirname, size, ext)
1291 fprintf(stderr, _("\
1292 Warning: No DIR structure found on this system --\n\
1293 Unable to autosize for XPM/XIM pieces.\n\
1294 Please report this error to %s.\n\
1295 Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
1298 #endif /* HAVE_DIR_STRUCT */
1300 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1301 "magenta", "cyan", "white" };
1305 TextColors textColors[(int)NColorClasses];
1307 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1309 parse_color(str, which)
1313 char *p, buf[100], *d;
1316 if (strlen(str) > 99) /* watch bounds on buf */
1321 for (i=0; i<which; ++i) {
1328 /* Could be looking at something like:
1330 .. in which case we want to stop on a comma also */
1331 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1335 return -1; /* Use default for empty field */
1338 if (which == 2 || isdigit(*p))
1341 while (*p && isalpha(*p))
1346 for (i=0; i<8; ++i) {
1347 if (!StrCaseCmp(buf, cnames[i]))
1348 return which? (i+40) : (i+30);
1350 if (!StrCaseCmp(buf, "default")) return -1;
1352 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1357 parse_cpair(cc, str)
1361 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1362 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1367 /* bg and attr are optional */
1368 textColors[(int)cc].bg = parse_color(str, 1);
1369 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1370 textColors[(int)cc].attr = 0;
1376 /* Arrange to catch delete-window events */
1377 Atom wm_delete_window;
1379 CatchDeleteWindow(Widget w, String procname)
1382 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1383 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1384 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1391 XtSetArg(args[0], XtNiconic, False);
1392 XtSetValues(shellWidget, args, 1);
1394 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1397 //---------------------------------------------------------------------------------------------------------
1398 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1401 #define CW_USEDEFAULT (1<<31)
1402 #define ICS_TEXT_MENU_SIZE 90
1403 #define DEBUG_FILE "xboard.debug"
1404 #define SetCurrentDirectory chdir
1405 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1409 // these two must some day move to frontend.h, when they are implemented
1410 Boolean GameListIsUp();
1412 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1415 // front-end part of option handling
1417 // [HGM] This platform-dependent table provides the location for storing the color info
1418 extern char *crWhite, * crBlack;
1422 &appData.whitePieceColor,
1423 &appData.blackPieceColor,
1424 &appData.lightSquareColor,
1425 &appData.darkSquareColor,
1426 &appData.highlightSquareColor,
1427 &appData.premoveHighlightColor,
1428 &appData.lowTimeWarningColor,
1439 // [HGM] font: keep a font for each square size, even non-stndard ones
1440 #define NUM_SIZES 18
1441 #define MAX_SIZE 130
1442 Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1443 char *fontTable[NUM_FONTS][MAX_SIZE];
1446 ParseFont(char *name, int number)
1447 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1449 if(sscanf(name, "size%d:", &size)) {
1450 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1451 // defer processing it until we know if it matches our board size
1452 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1453 fontTable[number][size] = strdup(strchr(name, ':')+1);
1454 fontValid[number][size] = True;
1459 case 0: // CLOCK_FONT
1460 appData.clockFont = strdup(name);
1462 case 1: // MESSAGE_FONT
1463 appData.font = strdup(name);
1465 case 2: // COORD_FONT
1466 appData.coordFont = strdup(name);
1471 fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1476 { // only 2 fonts currently
1477 appData.clockFont = CLOCK_FONT_NAME;
1478 appData.coordFont = COORD_FONT_NAME;
1479 appData.font = DEFAULT_FONT_NAME;
1484 { // no-op, until we identify the code for this already in XBoard and move it here
1488 ParseColor(int n, char *name)
1489 { // in XBoard, just copy the color-name string
1490 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1494 ParseTextAttribs(ColorClass cc, char *s)
1496 (&appData.colorShout)[cc] = strdup(s);
1500 ParseBoardSize(void *addr, char *name)
1502 appData.boardSize = strdup(name);
1507 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1511 SetCommPortDefaults()
1512 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1515 // [HGM] args: these three cases taken out to stay in front-end
1517 SaveFontArg(FILE *f, ArgDescriptor *ad)
1520 int i, n = (int)(intptr_t)ad->argLoc;
1522 case 0: // CLOCK_FONT
1523 name = appData.clockFont;
1525 case 1: // MESSAGE_FONT
1526 name = appData.font;
1528 case 2: // COORD_FONT
1529 name = appData.coordFont;
1534 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1535 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1536 fontTable[n][squareSize] = strdup(name);
1537 fontValid[n][squareSize] = True;
1540 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1541 fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
1546 { // nothing to do, as the sounds are at all times represented by their text-string names already
1550 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1551 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1552 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1556 SaveColor(FILE *f, ArgDescriptor *ad)
1557 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1558 if(colorVariable[(int)(intptr_t)ad->argLoc])
1559 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1563 SaveBoardSize(FILE *f, char *name, void *addr)
1564 { // wrapper to shield back-end from BoardSize & sizeInfo
1565 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1569 ParseCommPortSettings(char *s)
1570 { // no such option in XBoard (yet)
1573 extern Widget engineOutputShell;
1576 GetActualPlacement(Widget wg, WindowPlacement *wp)
1586 XtSetArg(args[i], XtNx, &x); i++;
1587 XtSetArg(args[i], XtNy, &y); i++;
1588 XtSetArg(args[i], XtNwidth, &w); i++;
1589 XtSetArg(args[i], XtNheight, &h); i++;
1590 XtGetValues(wg, args, i);
1599 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1600 // In XBoard this will have to wait until awareness of window parameters is implemented
1601 GetActualPlacement(shellWidget, &wpMain);
1602 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput);
1603 if(MoveHistoryIsUp()) GetActualPlacement(shells[7], &wpMoveHistory);
1604 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1605 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1606 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1607 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1611 PrintCommPortSettings(FILE *f, char *name)
1612 { // This option does not exist in XBoard
1616 MySearchPath(char *installDir, char *name, char *fullname)
1617 { // just append installDir and name. Perhaps ExpandPath should be used here?
1618 name = ExpandPathName(name);
1619 if(name && name[0] == '/')
1620 safeStrCpy(fullname, name, MSG_SIZ );
1622 sprintf(fullname, "%s%c%s", installDir, '/', name);
1628 MyGetFullPathName(char *name, char *fullname)
1629 { // should use ExpandPath?
1630 name = ExpandPathName(name);
1631 safeStrCpy(fullname, name, MSG_SIZ );
1636 EnsureOnScreen(int *x, int *y, int minX, int minY)
1643 { // [HGM] args: allows testing if main window is realized from back-end
1644 return xBoardWindow != 0;
1648 PopUpStartupDialog()
1649 { // start menu not implemented in XBoard
1653 ConvertToLine(int argc, char **argv)
1655 static char line[128*1024], buf[1024];
1659 for(i=1; i<argc; i++)
1661 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') || argv[i][0] == NULLCHAR)
1662 && argv[i][0] != '{' )
1663 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1665 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1666 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1669 line[strlen(line)-1] = NULLCHAR;
1673 //--------------------------------------------------------------------------------------------
1675 extern Boolean twoBoards, partnerUp;
1678 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1680 #define BoardSize int
1681 void InitDrawingSizes(BoardSize boardSize, int flags)
1682 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1683 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1685 XtGeometryResult gres;
1687 static Dimension oldWidth, oldHeight;
1688 static VariantClass oldVariant;
1689 static int oldDual = -1;
1691 if(!formWidget) return;
1693 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1694 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1695 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1697 if(boardWidth != oldWidth || boardHeight != oldHeight || oldDual != twoBoards) { // do resizing stuff only if size actually changed
1699 * Enable shell resizing.
1701 shellArgs[0].value = (XtArgVal) &w;
1702 shellArgs[1].value = (XtArgVal) &h;
1703 XtGetValues(shellWidget, shellArgs, 2);
1705 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1706 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1707 XtSetValues(shellWidget, &shellArgs[2], 4);
1709 XtSetArg(args[0], XtNdefaultDistance, &sep);
1710 XtGetValues(formWidget, args, 1);
1712 oldWidth = boardWidth; oldHeight = boardHeight; oldDual = twoBoards;
1714 hOffset = boardWidth + 10;
1715 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1716 secondSegments[i] = gridSegments[i];
1717 secondSegments[i].x1 += hOffset;
1718 secondSegments[i].x2 += hOffset;
1721 XtSetArg(args[0], XtNwidth, boardWidth);
1722 XtSetArg(args[1], XtNheight, boardHeight);
1723 XtSetValues(boardWidget, args, 2);
1725 timerWidth = (boardWidth - sep) / 2;
1726 XtSetArg(args[0], XtNwidth, timerWidth);
1727 XtSetValues(whiteTimerWidget, args, 1);
1728 XtSetValues(blackTimerWidget, args, 1);
1730 XawFormDoLayout(formWidget, False);
1732 if (appData.titleInWindow) {
1734 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1735 XtSetArg(args[i], XtNheight, &h); i++;
1736 XtGetValues(titleWidget, args, i);
1738 w = boardWidth - 2*bor;
1740 XtSetArg(args[0], XtNwidth, &w);
1741 XtGetValues(menuBarWidget, args, 1);
1742 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1745 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1746 if (gres != XtGeometryYes && appData.debugMode) {
1748 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1749 programName, gres, w, h, wr, hr);
1753 XawFormDoLayout(formWidget, True);
1756 * Inhibit shell resizing.
1758 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1759 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1760 shellArgs[4].value = shellArgs[2].value = w;
1761 shellArgs[5].value = shellArgs[3].value = h;
1762 XtSetValues(shellWidget, &shellArgs[0], 6);
1765 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1768 if(gameInfo.variant == oldVariant) return; // and only if variant changed
1771 for(i=0; i<4; i++) {
1773 for(p=0; p<=(int)WhiteKing; p++)
1774 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1775 if(gameInfo.variant == VariantShogi) {
1776 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1777 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1778 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1779 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1780 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1783 if(gameInfo.variant == VariantGothic) {
1784 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1787 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1788 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1789 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1792 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1793 for(p=0; p<=(int)WhiteKing; p++)
1794 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1795 if(gameInfo.variant == VariantShogi) {
1796 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1797 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1798 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1799 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1800 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1803 if(gameInfo.variant == VariantGothic) {
1804 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1807 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1808 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1809 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1814 for(i=0; i<2; i++) {
1816 for(p=0; p<=(int)WhiteKing; p++)
1817 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1818 if(gameInfo.variant == VariantShogi) {
1819 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1820 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1821 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1822 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1823 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1826 if(gameInfo.variant == VariantGothic) {
1827 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1830 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1831 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1832 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1842 void ParseIcsTextColors()
1843 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1844 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1845 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1846 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1847 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1848 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1849 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1850 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1851 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1852 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1853 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1855 if (appData.colorize) {
1857 _("%s: can't parse color names; disabling colorization\n"),
1860 appData.colorize = FALSE;
1865 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1866 XrmValue vFrom, vTo;
1867 int forceMono = False;
1869 if (!appData.monoMode) {
1870 vFrom.addr = (caddr_t) appData.lightSquareColor;
1871 vFrom.size = strlen(appData.lightSquareColor);
1872 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1873 if (vTo.addr == NULL) {
1874 appData.monoMode = True;
1877 lightSquareColor = *(Pixel *) vTo.addr;
1880 if (!appData.monoMode) {
1881 vFrom.addr = (caddr_t) appData.darkSquareColor;
1882 vFrom.size = strlen(appData.darkSquareColor);
1883 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1884 if (vTo.addr == NULL) {
1885 appData.monoMode = True;
1888 darkSquareColor = *(Pixel *) vTo.addr;
1891 if (!appData.monoMode) {
1892 vFrom.addr = (caddr_t) appData.whitePieceColor;
1893 vFrom.size = strlen(appData.whitePieceColor);
1894 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1895 if (vTo.addr == NULL) {
1896 appData.monoMode = True;
1899 whitePieceColor = *(Pixel *) vTo.addr;
1902 if (!appData.monoMode) {
1903 vFrom.addr = (caddr_t) appData.blackPieceColor;
1904 vFrom.size = strlen(appData.blackPieceColor);
1905 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1906 if (vTo.addr == NULL) {
1907 appData.monoMode = True;
1910 blackPieceColor = *(Pixel *) vTo.addr;
1914 if (!appData.monoMode) {
1915 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1916 vFrom.size = strlen(appData.highlightSquareColor);
1917 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1918 if (vTo.addr == NULL) {
1919 appData.monoMode = True;
1922 highlightSquareColor = *(Pixel *) vTo.addr;
1926 if (!appData.monoMode) {
1927 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1928 vFrom.size = strlen(appData.premoveHighlightColor);
1929 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1930 if (vTo.addr == NULL) {
1931 appData.monoMode = True;
1934 premoveHighlightColor = *(Pixel *) vTo.addr;
1942 { // [HGM] taken out of main
1944 if (appData.monoMode && // [HGM] no sense to go on to certain doom
1945 (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
1946 appData.bitmapDirectory = strdup(DEF_BITMAP_DIR);
1948 if (appData.bitmapDirectory[0] != NULLCHAR) {
1952 CreateXPMBoard(appData.liteBackTextureFile, 1);
1953 CreateXPMBoard(appData.darkBackTextureFile, 0);
1957 /* Create regular pieces */
1958 if (!useImages) CreatePieces();
1967 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1968 XSetWindowAttributes window_attributes;
1970 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1971 XrmValue vFrom, vTo;
1972 XtGeometryResult gres;
1975 int forceMono = False;
1977 srandom(time(0)); // [HGM] book: make random truly random
1979 setbuf(stdout, NULL);
1980 setbuf(stderr, NULL);
1983 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1984 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1988 programName = strrchr(argv[0], '/');
1989 if (programName == NULL)
1990 programName = argv[0];
1995 XtSetLanguageProc(NULL, NULL, NULL);
1996 bindtextdomain(PACKAGE, LOCALEDIR);
1997 textdomain(PACKAGE);
2001 XtAppInitialize(&appContext, "XBoard", shellOptions,
2002 XtNumber(shellOptions),
2003 &argc, argv, xboardResources, NULL, 0);
2004 appData.boardSize = "";
2005 InitAppData(ConvertToLine(argc, argv));
2007 if (p == NULL) p = "/tmp";
2008 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2009 gameCopyFilename = (char*) malloc(i);
2010 gamePasteFilename = (char*) malloc(i);
2011 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2012 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2014 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2015 clientResources, XtNumber(clientResources),
2018 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2019 static char buf[MSG_SIZ];
2020 EscapeExpand(buf, appData.firstInitString);
2021 appData.firstInitString = strdup(buf);
2022 EscapeExpand(buf, appData.secondInitString);
2023 appData.secondInitString = strdup(buf);
2024 EscapeExpand(buf, appData.firstComputerString);
2025 appData.firstComputerString = strdup(buf);
2026 EscapeExpand(buf, appData.secondComputerString);
2027 appData.secondComputerString = strdup(buf);
2030 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2033 if (chdir(chessDir) != 0) {
2034 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2040 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2041 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2042 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2043 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2046 setbuf(debugFP, NULL);
2050 if (appData.debugMode) {
2051 fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
2055 /* [HGM,HR] make sure board size is acceptable */
2056 if(appData.NrFiles > BOARD_FILES ||
2057 appData.NrRanks > BOARD_RANKS )
2058 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2061 /* This feature does not work; animation needs a rewrite */
2062 appData.highlightDragging = FALSE;
2066 xDisplay = XtDisplay(shellWidget);
2067 xScreen = DefaultScreen(xDisplay);
2068 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2070 gameInfo.variant = StringToVariant(appData.variant);
2071 InitPosition(FALSE);
2074 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2076 if (isdigit(appData.boardSize[0])) {
2077 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2078 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2079 &fontPxlSize, &smallLayout, &tinyLayout);
2081 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2082 programName, appData.boardSize);
2086 /* Find some defaults; use the nearest known size */
2087 SizeDefaults *szd, *nearest;
2088 int distance = 99999;
2089 nearest = szd = sizeDefaults;
2090 while (szd->name != NULL) {
2091 if (abs(szd->squareSize - squareSize) < distance) {
2093 distance = abs(szd->squareSize - squareSize);
2094 if (distance == 0) break;
2098 if (i < 2) lineGap = nearest->lineGap;
2099 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2100 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2101 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2102 if (i < 6) smallLayout = nearest->smallLayout;
2103 if (i < 7) tinyLayout = nearest->tinyLayout;
2106 SizeDefaults *szd = sizeDefaults;
2107 if (*appData.boardSize == NULLCHAR) {
2108 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2109 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2112 if (szd->name == NULL) szd--;
2113 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2115 while (szd->name != NULL &&
2116 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2117 if (szd->name == NULL) {
2118 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2119 programName, appData.boardSize);
2123 squareSize = szd->squareSize;
2124 lineGap = szd->lineGap;
2125 clockFontPxlSize = szd->clockFontPxlSize;
2126 coordFontPxlSize = szd->coordFontPxlSize;
2127 fontPxlSize = szd->fontPxlSize;
2128 smallLayout = szd->smallLayout;
2129 tinyLayout = szd->tinyLayout;
2130 // [HGM] font: use defaults from settings file if available and not overruled
2132 if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2133 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2134 if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2135 appData.font = fontTable[MESSAGE_FONT][squareSize];
2136 if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2137 appData.coordFont = fontTable[COORD_FONT][squareSize];
2139 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2140 if (strlen(appData.pixmapDirectory) > 0) {
2141 p = ExpandPathName(appData.pixmapDirectory);
2143 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2144 appData.pixmapDirectory);
2147 if (appData.debugMode) {
2148 fprintf(stderr, _("\
2149 XBoard square size (hint): %d\n\
2150 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2152 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2153 if (appData.debugMode) {
2154 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2157 defaultLineGap = lineGap;
2158 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2160 /* [HR] height treated separately (hacked) */
2161 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2162 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2163 if (appData.showJail == 1) {
2164 /* Jail on top and bottom */
2165 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2166 XtSetArg(boardArgs[2], XtNheight,
2167 boardHeight + 2*(lineGap + squareSize));
2168 } else if (appData.showJail == 2) {
2170 XtSetArg(boardArgs[1], XtNwidth,
2171 boardWidth + 2*(lineGap + squareSize));
2172 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2175 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2176 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2180 * Determine what fonts to use.
2183 appData.font = InsertPxlSize(appData.font, fontPxlSize);
2184 appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
2185 appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
2186 fontSet = CreateFontSet(appData.font);
2187 clockFontSet = CreateFontSet(appData.clockFont);
2189 /* For the coordFont, use the 0th font of the fontset. */
2190 XFontSet coordFontSet = CreateFontSet(appData.coordFont);
2191 XFontStruct **font_struct_list;
2192 char **font_name_list;
2193 XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
2194 coordFontID = XLoadFont(xDisplay, font_name_list[0]);
2195 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2198 appData.font = FindFont(appData.font, fontPxlSize);
2199 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2200 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2201 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2202 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2203 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2204 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2206 countFontID = coordFontID; // [HGM] holdings
2207 countFontStruct = coordFontStruct;
2209 xdb = XtDatabase(xDisplay);
2211 XrmPutLineResource(&xdb, "*international: True");
2212 vTo.size = sizeof(XFontSet);
2213 vTo.addr = (XtPointer) &fontSet;
2214 XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
2216 XrmPutStringResource(&xdb, "*font", appData.font);
2220 * Detect if there are not enough colors available and adapt.
2222 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2223 appData.monoMode = True;
2226 forceMono = MakeColors();
2229 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2231 appData.monoMode = True;
2234 if (appData.lowTimeWarning && !appData.monoMode) {
2235 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2236 vFrom.size = strlen(appData.lowTimeWarningColor);
2237 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2238 if (vTo.addr == NULL)
2239 appData.monoMode = True;
2241 lowTimeWarningColor = *(Pixel *) vTo.addr;
2244 if (appData.monoMode && appData.debugMode) {
2245 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2246 (unsigned long) XWhitePixel(xDisplay, xScreen),
2247 (unsigned long) XBlackPixel(xDisplay, xScreen));
2250 ParseIcsTextColors();
2251 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2252 textColors[ColorNone].attr = 0;
2254 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2260 layoutName = "tinyLayout";
2261 } else if (smallLayout) {
2262 layoutName = "smallLayout";
2264 layoutName = "normalLayout";
2266 /* Outer layoutWidget is there only to provide a name for use in
2267 resources that depend on the layout style */
2269 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2270 layoutArgs, XtNumber(layoutArgs));
2272 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2273 formArgs, XtNumber(formArgs));
2274 XtSetArg(args[0], XtNdefaultDistance, &sep);
2275 XtGetValues(formWidget, args, 1);
2278 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2279 XtSetArg(args[0], XtNtop, XtChainTop);
2280 XtSetArg(args[1], XtNbottom, XtChainTop);
2281 XtSetArg(args[2], XtNright, XtChainLeft);
2282 XtSetValues(menuBarWidget, args, 3);
2284 widgetList[j++] = whiteTimerWidget =
2285 XtCreateWidget("whiteTime", labelWidgetClass,
2286 formWidget, timerArgs, XtNumber(timerArgs));
2288 XtSetArg(args[0], XtNfontSet, clockFontSet);
2290 XtSetArg(args[0], XtNfont, clockFontStruct);
2292 XtSetArg(args[1], XtNtop, XtChainTop);
2293 XtSetArg(args[2], XtNbottom, XtChainTop);
2294 XtSetValues(whiteTimerWidget, args, 3);
2296 widgetList[j++] = blackTimerWidget =
2297 XtCreateWidget("blackTime", labelWidgetClass,
2298 formWidget, timerArgs, XtNumber(timerArgs));
2300 XtSetArg(args[0], XtNfontSet, clockFontSet);
2302 XtSetArg(args[0], XtNfont, clockFontStruct);
2304 XtSetArg(args[1], XtNtop, XtChainTop);
2305 XtSetArg(args[2], XtNbottom, XtChainTop);
2306 XtSetValues(blackTimerWidget, args, 3);
2308 if (appData.titleInWindow) {
2309 widgetList[j++] = titleWidget =
2310 XtCreateWidget("title", labelWidgetClass, formWidget,
2311 titleArgs, XtNumber(titleArgs));
2312 XtSetArg(args[0], XtNtop, XtChainTop);
2313 XtSetArg(args[1], XtNbottom, XtChainTop);
2314 XtSetValues(titleWidget, args, 2);
2317 if (appData.showButtonBar) {
2318 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2319 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2320 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2321 XtSetArg(args[2], XtNtop, XtChainTop);
2322 XtSetArg(args[3], XtNbottom, XtChainTop);
2323 XtSetValues(buttonBarWidget, args, 4);
2326 widgetList[j++] = messageWidget =
2327 XtCreateWidget("message", labelWidgetClass, formWidget,
2328 messageArgs, XtNumber(messageArgs));
2329 XtSetArg(args[0], XtNtop, XtChainTop);
2330 XtSetArg(args[1], XtNbottom, XtChainTop);
2331 XtSetValues(messageWidget, args, 2);
2333 widgetList[j++] = boardWidget =
2334 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2335 XtNumber(boardArgs));
2337 XtManageChildren(widgetList, j);
2339 timerWidth = (boardWidth - sep) / 2;
2340 XtSetArg(args[0], XtNwidth, timerWidth);
2341 XtSetValues(whiteTimerWidget, args, 1);
2342 XtSetValues(blackTimerWidget, args, 1);
2344 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2345 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2346 XtGetValues(whiteTimerWidget, args, 2);
2348 if (appData.showButtonBar) {
2349 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2350 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2351 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2355 * formWidget uses these constraints but they are stored
2359 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2360 XtSetValues(menuBarWidget, args, i);
2361 if (appData.titleInWindow) {
2364 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2365 XtSetValues(whiteTimerWidget, args, i);
2367 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2368 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2369 XtSetValues(blackTimerWidget, args, i);
2371 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2372 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2373 XtSetValues(titleWidget, args, i);
2375 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2376 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2377 XtSetValues(messageWidget, args, i);
2378 if (appData.showButtonBar) {
2380 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2381 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2382 XtSetValues(buttonBarWidget, args, i);
2386 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2387 XtSetValues(whiteTimerWidget, args, i);
2389 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2390 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2391 XtSetValues(blackTimerWidget, args, i);
2393 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2394 XtSetValues(titleWidget, args, i);
2396 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2397 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2398 XtSetValues(messageWidget, args, i);
2399 if (appData.showButtonBar) {
2401 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2402 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2403 XtSetValues(buttonBarWidget, args, i);
2408 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2409 XtSetValues(whiteTimerWidget, args, i);
2411 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2412 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2413 XtSetValues(blackTimerWidget, args, i);
2415 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2416 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2417 XtSetValues(messageWidget, args, i);
2418 if (appData.showButtonBar) {
2420 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2421 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2422 XtSetValues(buttonBarWidget, args, i);
2426 XtSetArg(args[0], XtNfromVert, messageWidget);
2427 XtSetArg(args[1], XtNtop, XtChainTop);
2428 XtSetArg(args[2], XtNbottom, XtChainBottom);
2429 XtSetArg(args[3], XtNleft, XtChainLeft);
2430 XtSetArg(args[4], XtNright, XtChainRight);
2431 XtSetValues(boardWidget, args, 5);
2433 XtRealizeWidget(shellWidget);
2436 XtSetArg(args[0], XtNx, wpMain.x);
2437 XtSetArg(args[1], XtNy, wpMain.y);
2438 XtSetValues(shellWidget, args, 2);
2442 * Correct the width of the message and title widgets.
2443 * It is not known why some systems need the extra fudge term.
2444 * The value "2" is probably larger than needed.
2446 XawFormDoLayout(formWidget, False);
2448 #define WIDTH_FUDGE 2
2450 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2451 XtSetArg(args[i], XtNheight, &h); i++;
2452 XtGetValues(messageWidget, args, i);
2453 if (appData.showButtonBar) {
2455 XtSetArg(args[i], XtNwidth, &w); i++;
2456 XtGetValues(buttonBarWidget, args, i);
2457 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2459 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2462 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2463 if (gres != XtGeometryYes && appData.debugMode) {
2464 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2465 programName, gres, w, h, wr, hr);
2468 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2469 /* The size used for the child widget in layout lags one resize behind
2470 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2472 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2473 if (gres != XtGeometryYes && appData.debugMode) {
2474 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2475 programName, gres, w, h, wr, hr);
2478 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2479 XtSetArg(args[1], XtNright, XtChainRight);
2480 XtSetValues(messageWidget, args, 2);
2482 if (appData.titleInWindow) {
2484 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2485 XtSetArg(args[i], XtNheight, &h); i++;
2486 XtGetValues(titleWidget, args, i);
2488 w = boardWidth - 2*bor;
2490 XtSetArg(args[0], XtNwidth, &w);
2491 XtGetValues(menuBarWidget, args, 1);
2492 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2495 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2496 if (gres != XtGeometryYes && appData.debugMode) {
2498 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2499 programName, gres, w, h, wr, hr);
2502 XawFormDoLayout(formWidget, True);
2504 xBoardWindow = XtWindow(boardWidget);
2506 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2507 // not need to go into InitDrawingSizes().
2511 * Create X checkmark bitmap and initialize option menu checks.
2513 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2514 checkmark_bits, checkmark_width, checkmark_height);
2515 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2516 #ifndef OPTIONSDIALOG
2517 if (appData.alwaysPromoteToQueen) {
2518 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2521 if (appData.animateDragging) {
2522 XtSetValues(XtNameToWidget(menuBarWidget,
2523 "menuOptions.Animate Dragging"),
2526 if (appData.animate) {
2527 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2530 if (appData.autoCallFlag) {
2531 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2534 if (appData.autoFlipView) {
2535 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2538 if (appData.blindfold) {
2539 XtSetValues(XtNameToWidget(menuBarWidget,
2540 "menuOptions.Blindfold"), args, 1);
2542 if (appData.flashCount > 0) {
2543 XtSetValues(XtNameToWidget(menuBarWidget,
2544 "menuOptions.Flash Moves"),
2548 if (appData.highlightDragging) {
2549 XtSetValues(XtNameToWidget(menuBarWidget,
2550 "menuOptions.Highlight Dragging"),
2554 if (appData.highlightLastMove) {
2555 XtSetValues(XtNameToWidget(menuBarWidget,
2556 "menuOptions.Highlight Last Move"),
2559 if (appData.highlightMoveWithArrow) {
2560 XtSetValues(XtNameToWidget(menuBarWidget,
2561 "menuOptions.Arrow"),
2564 // if (appData.icsAlarm) {
2565 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2568 if (appData.ringBellAfterMoves) {
2569 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2572 if (appData.oneClick) {
2573 XtSetValues(XtNameToWidget(menuBarWidget,
2574 "menuOptions.OneClick"), args, 1);
2576 if (appData.periodicUpdates) {
2577 XtSetValues(XtNameToWidget(menuBarWidget,
2578 "menuOptions.Periodic Updates"), args, 1);
2580 if (appData.ponderNextMove) {
2581 XtSetValues(XtNameToWidget(menuBarWidget,
2582 "menuOptions.Ponder Next Move"), args, 1);
2584 if (appData.popupExitMessage) {
2585 XtSetValues(XtNameToWidget(menuBarWidget,
2586 "menuOptions.Popup Exit Message"), args, 1);
2588 if (appData.popupMoveErrors) {
2589 XtSetValues(XtNameToWidget(menuBarWidget,
2590 "menuOptions.Popup Move Errors"), args, 1);
2592 // if (appData.premove) {
2593 // XtSetValues(XtNameToWidget(menuBarWidget,
2594 // "menuOptions.Premove"), args, 1);
2596 if (appData.showCoords) {
2597 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2600 if (appData.hideThinkingFromHuman) {
2601 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2604 if (appData.testLegality) {
2605 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2609 if (saveSettingsOnExit) {
2610 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2617 ReadBitmap(&wIconPixmap, "icon_white.bm",
2618 icon_white_bits, icon_white_width, icon_white_height);
2619 ReadBitmap(&bIconPixmap, "icon_black.bm",
2620 icon_black_bits, icon_black_width, icon_black_height);
2621 iconPixmap = wIconPixmap;
2623 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2624 XtSetValues(shellWidget, args, i);
2627 * Create a cursor for the board widget.
2629 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2630 XChangeWindowAttributes(xDisplay, xBoardWindow,
2631 CWCursor, &window_attributes);
2634 * Inhibit shell resizing.
2636 shellArgs[0].value = (XtArgVal) &w;
2637 shellArgs[1].value = (XtArgVal) &h;
2638 XtGetValues(shellWidget, shellArgs, 2);
2639 shellArgs[4].value = shellArgs[2].value = w;
2640 shellArgs[5].value = shellArgs[3].value = h;
2641 XtSetValues(shellWidget, &shellArgs[2], 4);
2642 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2643 marginH = h - boardHeight;
2645 CatchDeleteWindow(shellWidget, "QuitProc");
2653 if (appData.animate || appData.animateDragging)
2656 XtAugmentTranslations(formWidget,
2657 XtParseTranslationTable(globalTranslations));
2658 XtAugmentTranslations(boardWidget,
2659 XtParseTranslationTable(boardTranslations));
2660 XtAugmentTranslations(whiteTimerWidget,
2661 XtParseTranslationTable(whiteTranslations));
2662 XtAugmentTranslations(blackTimerWidget,
2663 XtParseTranslationTable(blackTranslations));
2665 /* Why is the following needed on some versions of X instead
2666 * of a translation? */
2667 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2668 (XtEventHandler) EventProc, NULL);
2670 XtAddEventHandler(formWidget, KeyPressMask, False,
2671 (XtEventHandler) MoveTypeInProc, NULL);
2673 /* [AS] Restore layout */
2674 if( wpMoveHistory.visible ) {
2678 if( wpEvalGraph.visible )
2683 if( wpEngineOutput.visible ) {
2684 EngineOutputPopUp();
2689 if (errorExitStatus == -1) {
2690 if (appData.icsActive) {
2691 /* We now wait until we see "login:" from the ICS before
2692 sending the logon script (problems with timestamp otherwise) */
2693 /*ICSInitScript();*/
2694 if (appData.icsInputBox) ICSInputBoxPopUp();
2698 signal(SIGWINCH, TermSizeSigHandler);
2700 signal(SIGINT, IntSigHandler);
2701 signal(SIGTERM, IntSigHandler);
2702 if (*appData.cmailGameName != NULLCHAR) {
2703 signal(SIGUSR1, CmailSigHandler);
2706 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2708 // XtSetKeyboardFocus(shellWidget, formWidget);
2709 XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
2711 XtAppMainLoop(appContext);
2712 if (appData.debugMode) fclose(debugFP); // [DM] debug
2716 static Boolean noEcho;
2721 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2722 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2724 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2725 unlink(gameCopyFilename);
2726 unlink(gamePasteFilename);
2727 if(noEcho) EchoOn();
2730 RETSIGTYPE TermSizeSigHandler(int sig)
2743 CmailSigHandler(sig)
2749 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2751 /* Activate call-back function CmailSigHandlerCallBack() */
2752 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2754 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2758 CmailSigHandlerCallBack(isr, closure, message, count, error)
2766 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2768 /**** end signal code ****/
2774 /* try to open the icsLogon script, either in the location given
2775 * or in the users HOME directory
2782 f = fopen(appData.icsLogon, "r");
2785 homedir = getenv("HOME");
2786 if (homedir != NULL)
2788 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2789 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2790 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2791 f = fopen(buf, "r");
2796 ProcessICSInitScript(f);
2798 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2821 if (!menuBarWidget) return;
2822 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2824 DisplayError("menuEdit.Revert", 0);
2826 XtSetSensitive(w, !grey);
2828 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2830 DisplayError("menuEdit.Annotate", 0);
2832 XtSetSensitive(w, !grey);
2837 SetMenuEnables(enab)
2841 if (!menuBarWidget) return;
2842 while (enab->name != NULL) {
2843 w = XtNameToWidget(menuBarWidget, enab->name);
2845 DisplayError(enab->name, 0);
2847 XtSetSensitive(w, enab->value);
2853 Enables icsEnables[] = {
2854 { "menuFile.Mail Move", False },
2855 { "menuFile.Reload CMail Message", False },
2856 { "menuMode.Machine Black", False },
2857 { "menuMode.Machine White", False },
2858 { "menuMode.Analysis Mode", False },
2859 { "menuMode.Analyze File", False },
2860 { "menuMode.Two Machines", False },
2861 { "menuMode.Machine Match", False },
2863 { "menuEngine.Hint", False },
2864 { "menuEngine.Book", False },
2865 { "menuEngine.Move Now", False },
2866 #ifndef OPTIONSDIALOG
2867 { "menuOptions.Periodic Updates", False },
2868 { "menuOptions.Hide Thinking", False },
2869 { "menuOptions.Ponder Next Move", False },
2872 { "menuEngine.Engine #1 Settings", False },
2873 { "menuEngine.Engine #2 Settings", False },
2874 { "menuEngine.Load Engine", False },
2875 { "menuEdit.Annotate", False },
2876 { "menuOptions.Match", False },
2880 Enables ncpEnables[] = {
2881 { "menuFile.Mail Move", False },
2882 { "menuFile.Reload CMail Message", False },
2883 { "menuMode.Machine White", False },
2884 { "menuMode.Machine Black", False },
2885 { "menuMode.Analysis Mode", False },
2886 { "menuMode.Analyze File", False },
2887 { "menuMode.Two Machines", False },
2888 { "menuMode.Machine Match", False },
2889 { "menuMode.ICS Client", False },
2890 { "menuView.ICStex", False },
2891 { "menuView.ICS Input Box", False },
2892 { "Action", False },
2893 { "menuEdit.Revert", False },
2894 { "menuEdit.Annotate", False },
2895 { "menuEngine.Engine #1 Settings", False },
2896 { "menuEngine.Engine #2 Settings", False },
2897 { "menuEngine.Move Now", False },
2898 { "menuEngine.Retract Move", False },
2899 { "menuOptions.ICS", False },
2900 #ifndef OPTIONSDIALOG
2901 { "menuOptions.Auto Flag", False },
2902 { "menuOptions.Auto Flip View", False },
2903 // { "menuOptions.ICS Alarm", False },
2904 { "menuOptions.Move Sound", False },
2905 { "menuOptions.Hide Thinking", False },
2906 { "menuOptions.Periodic Updates", False },
2907 { "menuOptions.Ponder Next Move", False },
2909 { "menuEngine.Hint", False },
2910 { "menuEngine.Book", False },
2914 Enables gnuEnables[] = {
2915 { "menuMode.ICS Client", False },
2916 { "menuView.ICStex", False },
2917 { "menuView.ICS Input Box", False },
2918 { "menuAction.Accept", False },
2919 { "menuAction.Decline", False },
2920 { "menuAction.Rematch", False },
2921 { "menuAction.Adjourn", False },
2922 { "menuAction.Stop Examining", False },
2923 { "menuAction.Stop Observing", False },
2924 { "menuAction.Upload to Examine", False },
2925 { "menuEdit.Revert", False },
2926 { "menuEdit.Annotate", False },
2927 { "menuOptions.ICS", False },
2929 /* The next two options rely on SetCmailMode being called *after* */
2930 /* SetGNUMode so that when GNU is being used to give hints these */
2931 /* menu options are still available */
2933 { "menuFile.Mail Move", False },
2934 { "menuFile.Reload CMail Message", False },
2935 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
2936 { "menuMode.Machine White", True },
2937 { "menuMode.Machine Black", True },
2938 { "menuMode.Analysis Mode", True },
2939 { "menuMode.Analyze File", True },
2940 { "menuMode.Two Machines", True },
2941 { "menuMode.Machine Match", True },
2942 { "menuEngine.Engine #1 Settings", True },
2943 { "menuEngine.Engine #2 Settings", True },
2944 { "menuEngine.Hint", True },
2945 { "menuEngine.Book", True },
2946 { "menuEngine.Move Now", True },
2947 { "menuEngine.Retract Move", True },
2952 Enables cmailEnables[] = {
2954 { "menuAction.Call Flag", False },
2955 { "menuAction.Draw", True },
2956 { "menuAction.Adjourn", False },
2957 { "menuAction.Abort", False },
2958 { "menuAction.Stop Observing", False },
2959 { "menuAction.Stop Examining", False },
2960 { "menuFile.Mail Move", True },
2961 { "menuFile.Reload CMail Message", True },
2965 Enables trainingOnEnables[] = {
2966 { "menuMode.Edit Comment", False },
2967 { "menuMode.Pause", False },
2968 { "menuEdit.Forward", False },
2969 { "menuEdit.Backward", False },
2970 { "menuEdit.Forward to End", False },
2971 { "menuEdit.Back to Start", False },
2972 { "menuEngine.Move Now", False },
2973 { "menuEdit.Truncate Game", False },
2977 Enables trainingOffEnables[] = {
2978 { "menuMode.Edit Comment", True },
2979 { "menuMode.Pause", True },
2980 { "menuEdit.Forward", True },
2981 { "menuEdit.Backward", True },
2982 { "menuEdit.Forward to End", True },
2983 { "menuEdit.Back to Start", True },
2984 { "menuEngine.Move Now", True },
2985 { "menuEdit.Truncate Game", True },
2989 Enables machineThinkingEnables[] = {
2990 { "menuFile.Load Game", False },
2991 // { "menuFile.Load Next Game", False },
2992 // { "menuFile.Load Previous Game", False },
2993 // { "menuFile.Reload Same Game", False },
2994 { "menuEdit.Paste Game", False },
2995 { "menuFile.Load Position", False },
2996 // { "menuFile.Load Next Position", False },
2997 // { "menuFile.Load Previous Position", False },
2998 // { "menuFile.Reload Same Position", False },
2999 { "menuEdit.Paste Position", False },
3000 { "menuMode.Machine White", False },
3001 { "menuMode.Machine Black", False },
3002 { "menuMode.Two Machines", False },
3003 // { "menuMode.Machine Match", False },
3004 { "menuEngine.Retract Move", False },
3008 Enables userThinkingEnables[] = {
3009 { "menuFile.Load Game", True },
3010 // { "menuFile.Load Next Game", True },
3011 // { "menuFile.Load Previous Game", True },
3012 // { "menuFile.Reload Same Game", True },
3013 { "menuEdit.Paste Game", True },
3014 { "menuFile.Load Position", True },
3015 // { "menuFile.Load Next Position", True },
3016 // { "menuFile.Load Previous Position", True },
3017 // { "menuFile.Reload Same Position", True },
3018 { "menuEdit.Paste Position", True },
3019 { "menuMode.Machine White", True },
3020 { "menuMode.Machine Black", True },
3021 { "menuMode.Two Machines", True },
3022 // { "menuMode.Machine Match", True },
3023 { "menuEngine.Retract Move", True },
3029 SetMenuEnables(icsEnables);
3032 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
3033 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3034 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
3042 SetMenuEnables(ncpEnables);
3048 SetMenuEnables(gnuEnables);
3054 SetMenuEnables(cmailEnables);
3060 SetMenuEnables(trainingOnEnables);
3061 if (appData.showButtonBar) {
3062 XtSetSensitive(buttonBarWidget, False);
3068 SetTrainingModeOff()
3070 SetMenuEnables(trainingOffEnables);
3071 if (appData.showButtonBar) {
3072 XtSetSensitive(buttonBarWidget, True);
3077 SetUserThinkingEnables()
3079 if (appData.noChessProgram) return;
3080 SetMenuEnables(userThinkingEnables);
3084 SetMachineThinkingEnables()
3086 if (appData.noChessProgram) return;
3087 SetMenuEnables(machineThinkingEnables);
3089 case MachinePlaysBlack:
3090 case MachinePlaysWhite:
3091 case TwoMachinesPlay:
3092 XtSetSensitive(XtNameToWidget(menuBarWidget,
3093 ModeToWidgetName(gameMode)), True);
3100 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
3101 #define HISTORY_SIZE 64
3102 static char *history[HISTORY_SIZE];
3103 int histIn = 0, histP = 0;
3106 SaveInHistory(char *cmd)
3108 if (history[histIn] != NULL) {
3109 free(history[histIn]);
3110 history[histIn] = NULL;
3112 if (*cmd == NULLCHAR) return;
3113 history[histIn] = StrSave(cmd);
3114 histIn = (histIn + 1) % HISTORY_SIZE;
3115 if (history[histIn] != NULL) {
3116 free(history[histIn]);
3117 history[histIn] = NULL;
3123 PrevInHistory(char *cmd)
3126 if (histP == histIn) {
3127 if (history[histIn] != NULL) free(history[histIn]);
3128 history[histIn] = StrSave(cmd);
3130 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3131 if (newhp == histIn || history[newhp] == NULL) return NULL;
3133 return history[histP];
3139 if (histP == histIn) return NULL;
3140 histP = (histP + 1) % HISTORY_SIZE;
3141 return history[histP];
3143 // end of borrowed code
3145 #define Abs(n) ((n)<0 ? -(n) : (n))
3149 InsertPxlSize(pattern, targetPxlSize)
3153 char *base_fnt_lst, strInt[12], *p, *q;
3154 int alternatives, i, len, strIntLen;
3157 * Replace the "*" (if present) in the pixel-size slot of each
3158 * alternative with the targetPxlSize.
3162 while ((p = strchr(p, ',')) != NULL) {
3166 snprintf(strInt, sizeof(strInt), "%d", targetPxlSize);
3167 strIntLen = strlen(strInt);
3168 base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1);
3172 while (alternatives--) {
3173 char *comma = strchr(p, ',');
3174 for (i=0; i<14; i++) {
3175 char *hyphen = strchr(p, '-');
3177 if (comma && hyphen > comma) break;
3178 len = hyphen + 1 - p;
3179 if (i == 7 && *p == '*' && len == 2) {
3181 memcpy(q, strInt, strIntLen);
3191 len = comma + 1 - p;
3198 return base_fnt_lst;
3202 CreateFontSet(base_fnt_lst)
3206 char **missing_list;
3210 fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
3211 &missing_list, &missing_count, &def_string);
3212 if (appData.debugMode) {
3214 XFontStruct **font_struct_list;
3215 char **font_name_list;
3216 fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
3218 fprintf(debugFP, " got list %s, locale %s\n",
3219 XBaseFontNameListOfFontSet(fntSet),
3220 XLocaleOfFontSet(fntSet));
3221 count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
3222 for (i = 0; i < count; i++) {
3223 fprintf(debugFP, " got charset %s\n", font_name_list[i]);
3226 for (i = 0; i < missing_count; i++) {
3227 fprintf(debugFP, " missing charset %s\n", missing_list[i]);
3230 if (fntSet == NULL) {
3231 fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
3236 #else // not ENABLE_NLS
3238 * Find a font that matches "pattern" that is as close as
3239 * possible to the targetPxlSize. Prefer fonts that are k
3240 * pixels smaller to fonts that are k pixels larger. The
3241 * pattern must be in the X Consortium standard format,
3242 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3243 * The return value should be freed with XtFree when no
3247 FindFont(pattern, targetPxlSize)
3251 char **fonts, *p, *best, *scalable, *scalableTail;
3252 int i, j, nfonts, minerr, err, pxlSize;
3254 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3256 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3257 programName, pattern);
3264 for (i=0; i<nfonts; i++) {
3267 if (*p != '-') continue;
3269 if (*p == NULLCHAR) break;
3270 if (*p++ == '-') j++;
3272 if (j < 7) continue;
3275 scalable = fonts[i];
3278 err = pxlSize - targetPxlSize;
3279 if (Abs(err) < Abs(minerr) ||
3280 (minerr > 0 && err < 0 && -err == minerr)) {
3286 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3287 /* If the error is too big and there is a scalable font,
3288 use the scalable font. */
3289 int headlen = scalableTail - scalable;
3290 p = (char *) XtMalloc(strlen(scalable) + 10);
3291 while (isdigit(*scalableTail)) scalableTail++;
3292 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3294 p = (char *) XtMalloc(strlen(best) + 2);
3295 safeStrCpy(p, best, strlen(best)+1 );
3297 if (appData.debugMode) {
3298 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3299 pattern, targetPxlSize, p);
3301 XFreeFontNames(fonts);
3307 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3308 // must be called before all non-first callse to CreateGCs()
3309 XtReleaseGC(shellWidget, highlineGC);
3310 XtReleaseGC(shellWidget, lightSquareGC);
3311 XtReleaseGC(shellWidget, darkSquareGC);
3312 XtReleaseGC(shellWidget, lineGC);
3313 if (appData.monoMode) {
3314 if (DefaultDepth(xDisplay, xScreen) == 1) {
3315 XtReleaseGC(shellWidget, wbPieceGC);
3317 XtReleaseGC(shellWidget, bwPieceGC);
3320 XtReleaseGC(shellWidget, prelineGC);
3321 XtReleaseGC(shellWidget, jailSquareGC);
3322 XtReleaseGC(shellWidget, wdPieceGC);
3323 XtReleaseGC(shellWidget, wlPieceGC);
3324 XtReleaseGC(shellWidget, wjPieceGC);
3325 XtReleaseGC(shellWidget, bdPieceGC);
3326 XtReleaseGC(shellWidget, blPieceGC);
3327 XtReleaseGC(shellWidget, bjPieceGC);
3331 void CreateGCs(int redo)
3333 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3334 | GCBackground | GCFunction | GCPlaneMask;
3335 XGCValues gc_values;
3338 gc_values.plane_mask = AllPlanes;
3339 gc_values.line_width = lineGap;
3340 gc_values.line_style = LineSolid;
3341 gc_values.function = GXcopy;
3344 DeleteGCs(); // called a second time; clean up old GCs first
3345 } else { // [HGM] grid and font GCs created on first call only
3346 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3347 gc_values.background = XWhitePixel(xDisplay, xScreen);
3348 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3349 XSetFont(xDisplay, coordGC, coordFontID);
3351 // [HGM] make font for holdings counts (white on black)
3352 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3353 gc_values.background = XBlackPixel(xDisplay, xScreen);
3354 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3355 XSetFont(xDisplay, countGC, countFontID);
3357 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3358 gc_values.background = XBlackPixel(xDisplay, xScreen);
3359 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3361 if (appData.monoMode) {
3362 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3363 gc_values.background = XWhitePixel(xDisplay, xScreen);
3364 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3366 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3367 gc_values.background = XBlackPixel(xDisplay, xScreen);
3368 lightSquareGC = wbPieceGC
3369 = XtGetGC(shellWidget, value_mask, &gc_values);
3371 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3372 gc_values.background = XWhitePixel(xDisplay, xScreen);
3373 darkSquareGC = bwPieceGC
3374 = XtGetGC(shellWidget, value_mask, &gc_values);
3376 if (DefaultDepth(xDisplay, xScreen) == 1) {
3377 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3378 gc_values.function = GXcopyInverted;
3379 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3380 gc_values.function = GXcopy;
3381 if (XBlackPixel(xDisplay, xScreen) == 1) {
3382 bwPieceGC = darkSquareGC;
3383 wbPieceGC = copyInvertedGC;
3385 bwPieceGC = copyInvertedGC;
3386 wbPieceGC = lightSquareGC;
3390 gc_values.foreground = highlightSquareColor;
3391 gc_values.background = highlightSquareColor;
3392 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3394 gc_values.foreground = premoveHighlightColor;
3395 gc_values.background = premoveHighlightColor;
3396 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3398 gc_values.foreground = lightSquareColor;
3399 gc_values.background = darkSquareColor;
3400 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3402 gc_values.foreground = darkSquareColor;
3403 gc_values.background = lightSquareColor;
3404 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3406 gc_values.foreground = jailSquareColor;
3407 gc_values.background = jailSquareColor;
3408 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3410 gc_values.foreground = whitePieceColor;
3411 gc_values.background = darkSquareColor;
3412 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3414 gc_values.foreground = whitePieceColor;
3415 gc_values.background = lightSquareColor;
3416 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3418 gc_values.foreground = whitePieceColor;
3419 gc_values.background = jailSquareColor;
3420 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3422 gc_values.foreground = blackPieceColor;
3423 gc_values.background = darkSquareColor;
3424 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3426 gc_values.foreground = blackPieceColor;
3427 gc_values.background = lightSquareColor;
3428 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3430 gc_values.foreground = blackPieceColor;
3431 gc_values.background = jailSquareColor;
3432 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3436 void loadXIM(xim, xmask, filename, dest, mask)
3449 fp = fopen(filename, "rb");
3451 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3458 for (y=0; y<h; ++y) {
3459 for (x=0; x<h; ++x) {
3464 XPutPixel(xim, x, y, blackPieceColor);
3466 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3469 XPutPixel(xim, x, y, darkSquareColor);
3471 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3474 XPutPixel(xim, x, y, whitePieceColor);
3476 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3479 XPutPixel(xim, x, y, lightSquareColor);
3481 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3489 /* create Pixmap of piece */
3490 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3492 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3495 /* create Pixmap of clipmask
3496 Note: We assume the white/black pieces have the same
3497 outline, so we make only 6 masks. This is okay
3498 since the XPM clipmask routines do the same. */
3500 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3502 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3505 /* now create the 1-bit version */
3506 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3509 values.foreground = 1;
3510 values.background = 0;
3512 /* Don't use XtGetGC, not read only */
3513 maskGC = XCreateGC(xDisplay, *mask,
3514 GCForeground | GCBackground, &values);
3515 XCopyPlane(xDisplay, temp, *mask, maskGC,
3516 0, 0, squareSize, squareSize, 0, 0, 1);
3517 XFreePixmap(xDisplay, temp);
3522 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3524 void CreateXIMPieces()
3529 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3534 /* The XSynchronize calls were copied from CreatePieces.
3535 Not sure if needed, but can't hurt */
3536 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3539 /* temp needed by loadXIM() */
3540 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3541 0, 0, ss, ss, AllPlanes, XYPixmap);
3543 if (strlen(appData.pixmapDirectory) == 0) {
3547 if (appData.monoMode) {
3548 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3552 fprintf(stderr, _("\nLoading XIMs...\n"));
3554 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3555 fprintf(stderr, "%d", piece+1);
3556 for (kind=0; kind<4; kind++) {
3557 fprintf(stderr, ".");
3558 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3559 ExpandPathName(appData.pixmapDirectory),
3560 piece <= (int) WhiteKing ? "" : "w",
3561 pieceBitmapNames[piece],
3563 ximPieceBitmap[kind][piece] =
3564 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3565 0, 0, ss, ss, AllPlanes, XYPixmap);
3566 if (appData.debugMode)
3567 fprintf(stderr, _("(File:%s:) "), buf);
3568 loadXIM(ximPieceBitmap[kind][piece],
3570 &(xpmPieceBitmap2[kind][piece]),
3571 &(ximMaskPm2[piece]));
3572 if(piece <= (int)WhiteKing)
3573 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3575 fprintf(stderr," ");
3577 /* Load light and dark squares */
3578 /* If the LSQ and DSQ pieces don't exist, we will
3579 draw them with solid squares. */
3580 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3581 if (access(buf, 0) != 0) {
3585 fprintf(stderr, _("light square "));
3587 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3588 0, 0, ss, ss, AllPlanes, XYPixmap);
3589 if (appData.debugMode)
3590 fprintf(stderr, _("(File:%s:) "), buf);
3592 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3593 fprintf(stderr, _("dark square "));
3594 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3595 ExpandPathName(appData.pixmapDirectory), ss);
3596 if (appData.debugMode)
3597 fprintf(stderr, _("(File:%s:) "), buf);
3599 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3600 0, 0, ss, ss, AllPlanes, XYPixmap);
3601 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3602 xpmJailSquare = xpmLightSquare;
3604 fprintf(stderr, _("Done.\n"));
3606 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3609 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3612 void CreateXPMBoard(char *s, int kind)
3616 if(!appData.useBitmaps || s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3617 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3618 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3622 void FreeXPMPieces()
3623 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3624 // thisroutine has to be called t free the old piece pixmaps
3626 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3627 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3629 XFreePixmap(xDisplay, xpmLightSquare);
3630 XFreePixmap(xDisplay, xpmDarkSquare);
3634 void CreateXPMPieces()
3638 u_int ss = squareSize;
3640 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3641 XpmColorSymbol symbols[4];
3642 static int redo = False;
3644 if(redo) FreeXPMPieces(); else redo = 1;
3646 /* The XSynchronize calls were copied from CreatePieces.
3647 Not sure if needed, but can't hurt */
3648 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3650 /* Setup translations so piece colors match square colors */