2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
60 #include <sys/types.h>
66 # if HAVE_SYS_SOCKET_H
67 # include <sys/socket.h>
68 # include <netinet/in.h>
70 # else /* not HAVE_SYS_SOCKET_H */
71 # if HAVE_LAN_SOCKET_H
72 # include <lan/socket.h>
74 # include <lan/netdb.h>
75 # else /* not HAVE_LAN_SOCKET_H */
76 # define OMIT_SOCKETS 1
77 # endif /* not HAVE_LAN_SOCKET_H */
78 # endif /* not HAVE_SYS_SOCKET_H */
79 #endif /* !OMIT_SOCKETS */
84 #else /* not STDC_HEADERS */
85 extern char *getenv();
88 # else /* not HAVE_STRING_H */
90 # endif /* not HAVE_STRING_H */
91 #endif /* not STDC_HEADERS */
94 # include <sys/fcntl.h>
95 #else /* not HAVE_SYS_FCNTL_H */
98 # endif /* HAVE_FCNTL_H */
99 #endif /* not HAVE_SYS_FCNTL_H */
101 #if HAVE_SYS_SYSTEMINFO_H
102 # include <sys/systeminfo.h>
103 #endif /* HAVE_SYS_SYSTEMINFO_H */
105 #if TIME_WITH_SYS_TIME
106 # include <sys/time.h>
110 # include <sys/time.h>
121 # include <sys/wait.h>
126 # define NAMLEN(dirent) strlen((dirent)->d_name)
127 # define HAVE_DIR_STRUCT
129 # define dirent direct
130 # define NAMLEN(dirent) (dirent)->d_namlen
132 # include <sys/ndir.h>
133 # define HAVE_DIR_STRUCT
136 # include <sys/dir.h>
137 # define HAVE_DIR_STRUCT
141 # define HAVE_DIR_STRUCT
149 #include <X11/Intrinsic.h>
150 #include <X11/StringDefs.h>
151 #include <X11/Shell.h>
152 #include <X11/cursorfont.h>
153 #include <X11/Xatom.h>
154 #include <X11/Xmu/Atoms.h>
156 #include <X11/Xaw3d/Dialog.h>
157 #include <X11/Xaw3d/Form.h>
158 #include <X11/Xaw3d/List.h>
159 #include <X11/Xaw3d/Label.h>
160 #include <X11/Xaw3d/SimpleMenu.h>
161 #include <X11/Xaw3d/SmeBSB.h>
162 #include <X11/Xaw3d/SmeLine.h>
163 #include <X11/Xaw3d/Box.h>
164 #include <X11/Xaw3d/MenuButton.h>
165 #include <X11/Xaw3d/Text.h>
166 #include <X11/Xaw3d/AsciiText.h>
168 #include <X11/Xaw/Dialog.h>
169 #include <X11/Xaw/Form.h>
170 #include <X11/Xaw/List.h>
171 #include <X11/Xaw/Label.h>
172 #include <X11/Xaw/SimpleMenu.h>
173 #include <X11/Xaw/SmeBSB.h>
174 #include <X11/Xaw/SmeLine.h>
175 #include <X11/Xaw/Box.h>
176 #include <X11/Xaw/MenuButton.h>
177 #include <X11/Xaw/Text.h>
178 #include <X11/Xaw/AsciiText.h>
181 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
186 #include "pixmaps/pixmaps.h"
187 #define IMAGE_EXT "xpm"
189 #define IMAGE_EXT "xim"
190 #include "bitmaps/bitmaps.h"
193 #include "bitmaps/icon_white.bm"
194 #include "bitmaps/icon_black.bm"
195 #include "bitmaps/checkmark.bm"
197 #include "frontend.h"
199 #include "backendz.h"
203 #include "xgamelist.h"
204 #include "xhistory.h"
205 #include "xedittags.h"
208 // must be moved to xengineoutput.h
210 void EngineOutputProc P((Widget w, XEvent *event,
211 String *prms, Cardinal *nprms));
212 void EvalGraphProc P((Widget w, XEvent *event,
213 String *prms, Cardinal *nprms));
220 #define usleep(t) _sleep2(((t)+500)/1000)
224 # define _(s) gettext (s)
225 # define N_(s) gettext_noop (s)
243 int main P((int argc, char **argv));
244 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
245 char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
246 RETSIGTYPE CmailSigHandler P((int sig));
247 RETSIGTYPE IntSigHandler P((int sig));
248 RETSIGTYPE TermSizeSigHandler P((int sig));
249 void CreateGCs P((int redo));
250 void CreateAnyPieces P((void));
251 void CreateXIMPieces P((void));
252 void CreateXPMPieces P((void));
253 void CreateXPMBoard P((char *s, int n));
254 void CreatePieces P((void));
255 void CreatePieceMenus P((void));
256 Widget CreateMenuBar P((Menu *mb));
257 Widget CreateButtonBar P ((MenuItem *mi));
259 char *InsertPxlSize P((char *pattern, int targetPxlSize));
260 XFontSet CreateFontSet P((char *base_fnt_lst));
262 char *FindFont P((char *pattern, int targetPxlSize));
264 void PieceMenuPopup P((Widget w, XEvent *event,
265 String *params, Cardinal *num_params));
266 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
267 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
268 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
269 u_int wreq, u_int hreq));
270 void CreateGrid P((void));
271 int EventToSquare P((int x, int limit));
272 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
273 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
274 void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
275 void HandleUserMove P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void AnimateUserMove P((Widget w, XEvent * event,
278 String * params, Cardinal * nParams));
279 void HandlePV P((Widget w, XEvent * event,
280 String * params, Cardinal * nParams));
281 void SelectPV P((Widget w, XEvent * event,
282 String * params, Cardinal * nParams));
283 void StopPV P((Widget w, XEvent * event,
284 String * params, Cardinal * nParams));
285 void WhiteClock P((Widget w, XEvent *event,
286 String *prms, Cardinal *nprms));
287 void BlackClock P((Widget w, XEvent *event,
288 String *prms, Cardinal *nprms));
289 void DrawPositionProc P((Widget w, XEvent *event,
290 String *prms, Cardinal *nprms));
291 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
293 void CommentClick P((Widget w, XEvent * event,
294 String * params, Cardinal * nParams));
295 void CommentPopUp P((char *title, char *label));
296 void CommentPopDown P((void));
297 void ICSInputBoxPopUp P((void));
298 void ICSInputBoxPopDown P((void));
299 void FileNamePopUp P((char *label, char *def, char *filter,
300 FileProc proc, char *openMode));
301 void FileNamePopDown P((void));
302 void FileNameCallback P((Widget w, XtPointer client_data,
303 XtPointer call_data));
304 void FileNameAction P((Widget w, XEvent *event,
305 String *prms, Cardinal *nprms));
306 void AskQuestionReplyAction P((Widget w, XEvent *event,
307 String *prms, Cardinal *nprms));
308 void AskQuestionProc P((Widget w, XEvent *event,
309 String *prms, Cardinal *nprms));
310 void AskQuestionPopDown P((void));
311 void PromotionPopDown P((void));
312 void PromotionCallback P((Widget w, XtPointer client_data,
313 XtPointer call_data));
314 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
315 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
319 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
321 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
323 void LoadPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
327 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
329 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
331 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
333 void PastePositionProc P((Widget w, XEvent *event, String *prms,
335 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void SavePositionProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
344 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
348 void MachineWhiteProc P((Widget w, XEvent *event,
349 String *prms, Cardinal *nprms));
350 void AnalyzeModeProc P((Widget w, XEvent *event,
351 String *prms, Cardinal *nprms));
352 void AnalyzeFileProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
356 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void IcsClientProc P((Widget w, XEvent *event, String *prms,
360 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void EditPositionProc P((Widget w, XEvent *event,
362 String *prms, Cardinal *nprms));
363 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void EditCommentProc P((Widget w, XEvent *event,
365 String *prms, Cardinal *nprms));
366 void IcsInputBoxProc P((Widget w, XEvent *event,
367 String *prms, Cardinal *nprms));
368 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
375 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void StopObservingProc P((Widget w, XEvent *event, String *prms,
385 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
387 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
396 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
398 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
401 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
403 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
405 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
410 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
413 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
415 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
417 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
422 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
424 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
426 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
428 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
431 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
433 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
435 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
437 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
446 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
447 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
448 void DisplayMove P((int moveNumber));
449 void DisplayTitle P((char *title));
450 void ICSInitScript P((void));
451 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
452 void ErrorPopUp P((char *title, char *text, int modal));
453 void ErrorPopDown P((void));
454 static char *ExpandPathName P((char *path));
455 static void CreateAnimVars P((void));
456 static void DragPieceMove P((int x, int y));
457 static void DrawDragPiece P((void));
458 char *ModeToWidgetName P((GameMode mode));
459 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
467 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
468 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
469 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
470 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
471 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
472 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
473 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
474 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
475 void EditBookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
476 void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
477 void GameListOptionsPopDown P(());
478 void GenericPopDown P(());
479 void update_ics_width P(());
480 int get_term_width P(());
481 int CopyMemoProc P(());
482 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
483 Boolean IsDrawArrowEnabled P(());
486 * XBoard depends on Xt R4 or higher
488 int xtVersion = XtSpecificationRelease;
493 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
494 jailSquareColor, highlightSquareColor, premoveHighlightColor;
495 Pixel lowTimeWarningColor;
496 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
497 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
498 wjPieceGC, bjPieceGC, prelineGC, countGC;
499 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
500 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
501 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
502 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
503 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
504 ICSInputShell, fileNameShell, askQuestionShell;
505 Widget historyShell, evalGraphShell, gameListShell;
506 int hOffset; // [HGM] dual
507 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
508 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
509 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
511 XFontSet fontSet, clockFontSet;
514 XFontStruct *clockFontStruct;
516 Font coordFontID, countFontID;
517 XFontStruct *coordFontStruct, *countFontStruct;
518 XtAppContext appContext;
520 char *oldICSInteractionTitle;
524 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
526 Position commentX = -1, commentY = -1;
527 Dimension commentW, commentH;
528 typedef unsigned int BoardSize;
530 Boolean chessProgram;
532 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
533 int squareSize, smallLayout = 0, tinyLayout = 0,
534 marginW, marginH, // [HGM] for run-time resizing
535 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
536 ICSInputBoxUp = False, askQuestionUp = False,
537 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
538 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
539 Pixel timerForegroundPixel, timerBackgroundPixel;
540 Pixel buttonForegroundPixel, buttonBackgroundPixel;
541 char *chessDir, *programName, *programVersion,
542 *gameCopyFilename, *gamePasteFilename;
543 Boolean alwaysOnTop = False;
544 Boolean saveSettingsOnExit;
545 char *settingsFileName;
546 char *icsTextMenuString;
548 char *firstChessProgramNames;
549 char *secondChessProgramNames;
551 WindowPlacement wpMain;
552 WindowPlacement wpConsole;
553 WindowPlacement wpComment;
554 WindowPlacement wpMoveHistory;
555 WindowPlacement wpEvalGraph;
556 WindowPlacement wpEngineOutput;
557 WindowPlacement wpGameList;
558 WindowPlacement wpTags;
560 extern Widget shells[];
561 extern Boolean shellUp[];
565 Pixmap pieceBitmap[2][(int)BlackPawn];
566 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
567 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
568 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
569 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
570 Pixmap xpmBoardBitmap[2];
571 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
572 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
573 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
574 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
575 XImage *ximLightSquare, *ximDarkSquare;
578 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
579 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
581 #define White(piece) ((int)(piece) < (int)BlackPawn)
583 /* Variables for doing smooth animation. This whole thing
584 would be much easier if the board was double-buffered,
585 but that would require a fairly major rewrite. */
590 GC blitGC, pieceGC, outlineGC;
591 XPoint startSquare, prevFrame, mouseDelta;
595 int startBoardX, startBoardY;
598 /* There can be two pieces being animated at once: a player
599 can begin dragging a piece before the remote opponent has moved. */
601 static AnimState game, player;
603 /* Bitmaps for use as masks when drawing XPM pieces.
604 Need one for each black and white piece. */
605 static Pixmap xpmMask[BlackKing + 1];
607 /* This magic number is the number of intermediate frames used
608 in each half of the animation. For short moves it's reduced
609 by 1. The total number of frames will be factor * 2 + 1. */
612 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
614 MenuItem fileMenu[] = {
615 {N_("New Game Ctrl+N"), "New Game", ResetProc},
616 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
617 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
618 {"----", NULL, NothingProc},
619 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
620 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
621 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
622 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
623 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
624 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
625 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
626 {"----", NULL, NothingProc},
627 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
628 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
629 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
630 {"----", NULL, NothingProc},
631 {N_("Mail Move"), "Mail Move", MailMoveProc},
632 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
633 {"----", NULL, NothingProc},
634 {N_("Quit Ctr+Q"), "Exit", QuitProc},
638 MenuItem editMenu[] = {
639 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
640 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
641 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
642 {"----", NULL, NothingProc},
643 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
644 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
645 {"----", NULL, NothingProc},
646 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
647 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
648 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
649 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
650 {N_("Edit Book"), "Edit Book", EditBookProc},
651 {"----", NULL, NothingProc},
652 {N_("Revert Home"), "Revert", RevertProc},
653 {N_("Annotate"), "Annotate", AnnotateProc},
654 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
655 {"----", NULL, NothingProc},
656 {N_("Backward Alt+Left"), "Backward", BackwardProc},
657 {N_("Forward Alt+Right"), "Forward", ForwardProc},
658 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
659 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
663 MenuItem viewMenu[] = {
664 {N_("Flip View F2"), "Flip View", FlipViewProc},
665 {"----", NULL, NothingProc},
666 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
667 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
668 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
669 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
670 {N_("ICS text menu"), "ICStex", IcsTextProc},
671 {"----", NULL, NothingProc},
672 {N_("Tags"), "Show Tags", EditTagsProc},
673 {N_("Comments"), "Show Comments", EditCommentProc},
674 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
675 {"----", NULL, NothingProc},
676 {N_("Board..."), "Board Options", BoardOptionsProc},
677 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
681 MenuItem modeMenu[] = {
682 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
683 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
684 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
685 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
686 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
687 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
688 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
689 {N_("Training"), "Training", TrainingProc},
690 {N_("ICS Client"), "ICS Client", IcsClientProc},
691 {"----", NULL, NothingProc},
692 {N_("Machine Match"), "Machine Match", MatchProc},
693 {N_("Pause Pause"), "Pause", PauseProc},
697 MenuItem actionMenu[] = {
698 {N_("Accept F3"), "Accept", AcceptProc},
699 {N_("Decline F4"), "Decline", DeclineProc},
700 {N_("Rematch F12"), "Rematch", RematchProc},
701 {"----", NULL, NothingProc},
702 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
703 {N_("Draw F6"), "Draw", DrawProc},
704 {N_("Adjourn F7"), "Adjourn", AdjournProc},
705 {N_("Abort F8"),"Abort", AbortProc},
706 {N_("Resign F9"), "Resign", ResignProc},
707 {"----", NULL, NothingProc},
708 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
709 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
710 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
711 {"----", NULL, NothingProc},
712 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
713 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
714 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
718 MenuItem engineMenu[] = {
719 {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
720 {"----", NULL, NothingProc},
721 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
722 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
723 {"----", NULL, NothingProc},
724 {N_("Hint"), "Hint", HintProc},
725 {N_("Book"), "Book", BookProc},
726 {"----", NULL, NothingProc},
727 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
728 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
732 MenuItem optionsMenu[] = {
733 #define OPTIONSDIALOG
735 {N_("General ..."), "General", OptionsProc},
737 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
738 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
739 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
740 {N_("ICS ..."), "ICS", IcsOptionsProc},
741 {N_("Match ..."), "Match", MatchOptionsProc},
742 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
743 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
744 // {N_(" ..."), "", OptionsProc},
745 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
746 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
747 {"----", NULL, NothingProc},
748 #ifndef OPTIONSDIALOG
749 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
750 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
751 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
752 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
753 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
754 {N_("Blindfold"), "Blindfold", BlindfoldProc},
755 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
757 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
759 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
760 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
761 {N_("Move Sound"), "Move Sound", MoveSoundProc},
762 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
763 {N_("One-Click Moving"), "OneClick", OneClickProc},
764 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
765 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
766 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
767 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
768 // {N_("Premove"), "Premove", PremoveProc},
769 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
770 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
771 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
772 {"----", NULL, NothingProc},
774 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
775 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
779 MenuItem helpMenu[] = {
780 {N_("Info XBoard"), "Info XBoard", InfoProc},
781 {N_("Man XBoard F1"), "Man XBoard", ManProc},
782 {"----", NULL, NothingProc},
783 {N_("About XBoard"), "About XBoard", AboutProc},
788 {N_("File"), "File", fileMenu},
789 {N_("Edit"), "Edit", editMenu},
790 {N_("View"), "View", viewMenu},
791 {N_("Mode"), "Mode", modeMenu},
792 {N_("Action"), "Action", actionMenu},
793 {N_("Engine"), "Engine", engineMenu},
794 {N_("Options"), "Options", optionsMenu},
795 {N_("Help"), "Help", helpMenu},
799 #define PAUSE_BUTTON "P"
800 MenuItem buttonBar[] = {
801 {"<<", "<<", ToStartProc},
802 {"<", "<", BackwardProc},
803 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
804 {">", ">", ForwardProc},
805 {">>", ">>", ToEndProc},
809 #define PIECE_MENU_SIZE 18
810 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
811 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
812 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
813 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
814 N_("Empty square"), N_("Clear board") },
815 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
816 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
817 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
818 N_("Empty square"), N_("Clear board") }
820 /* must be in same order as pieceMenuStrings! */
821 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
822 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
823 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
824 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
825 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
826 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
827 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
828 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
829 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
832 #define DROP_MENU_SIZE 6
833 String dropMenuStrings[DROP_MENU_SIZE] = {
834 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
836 /* must be in same order as dropMenuStrings! */
837 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
838 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
839 WhiteRook, WhiteQueen
847 DropMenuEnables dmEnables[] = {
865 { XtNborderWidth, 0 },
866 { XtNdefaultDistance, 0 },
870 { XtNborderWidth, 0 },
871 { XtNresizable, (XtArgVal) True },
875 { XtNborderWidth, 0 },
881 { XtNjustify, (XtArgVal) XtJustifyRight },
882 { XtNlabel, (XtArgVal) "..." },
883 { XtNresizable, (XtArgVal) True },
884 { XtNresize, (XtArgVal) False }
887 Arg messageArgs[] = {
888 { XtNjustify, (XtArgVal) XtJustifyLeft },
889 { XtNlabel, (XtArgVal) "..." },
890 { XtNresizable, (XtArgVal) True },
891 { XtNresize, (XtArgVal) False }
895 { XtNborderWidth, 0 },
896 { XtNjustify, (XtArgVal) XtJustifyLeft }
899 XtResource clientResources[] = {
900 { "flashCount", "flashCount", XtRInt, sizeof(int),
901 XtOffset(AppDataPtr, flashCount), XtRImmediate,
902 (XtPointer) FLASH_COUNT },
905 XrmOptionDescRec shellOptions[] = {
906 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
907 { "-flash", "flashCount", XrmoptionNoArg, "3" },
908 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
911 XtActionsRec boardActions[] = {
912 { "DrawPosition", DrawPositionProc },
913 { "HandleUserMove", HandleUserMove },
914 { "AnimateUserMove", AnimateUserMove },
915 { "HandlePV", HandlePV },
916 { "SelectPV", SelectPV },
917 { "StopPV", StopPV },
918 { "FileNameAction", FileNameAction },
919 { "AskQuestionProc", AskQuestionProc },
920 { "AskQuestionReplyAction", AskQuestionReplyAction },
921 { "PieceMenuPopup", PieceMenuPopup },
922 { "WhiteClock", WhiteClock },
923 { "BlackClock", BlackClock },
924 { "Iconify", Iconify },
925 { "ResetProc", ResetProc },
926 { "NewVariantProc", NewVariantProc },
927 { "LoadGameProc", LoadGameProc },
928 { "LoadNextGameProc", LoadNextGameProc },
929 { "LoadPrevGameProc", LoadPrevGameProc },
930 { "LoadSelectedProc", LoadSelectedProc },
931 { "SetFilterProc", SetFilterProc },
932 { "ReloadGameProc", ReloadGameProc },
933 { "LoadPositionProc", LoadPositionProc },
934 { "LoadNextPositionProc", LoadNextPositionProc },
935 { "LoadPrevPositionProc", LoadPrevPositionProc },
936 { "ReloadPositionProc", ReloadPositionProc },
937 { "CopyPositionProc", CopyPositionProc },
938 { "PastePositionProc", PastePositionProc },
939 { "CopyGameProc", CopyGameProc },
940 { "CopyGameListProc", CopyGameListProc },
941 { "PasteGameProc", PasteGameProc },
942 { "SaveGameProc", SaveGameProc },
943 { "SavePositionProc", SavePositionProc },
944 { "MailMoveProc", MailMoveProc },
945 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
946 { "QuitProc", QuitProc },
947 { "MachineWhiteProc", MachineWhiteProc },
948 { "MachineBlackProc", MachineBlackProc },
949 { "AnalysisModeProc", AnalyzeModeProc },
950 { "AnalyzeFileProc", AnalyzeFileProc },
951 { "TwoMachinesProc", TwoMachinesProc },
952 { "IcsClientProc", IcsClientProc },
953 { "EditGameProc", EditGameProc },
954 { "EditPositionProc", EditPositionProc },
955 { "TrainingProc", EditPositionProc },
956 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
957 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
958 { "ShowGameListProc", ShowGameListProc },
959 { "ShowMoveListProc", HistoryShowProc},
960 { "EditTagsProc", EditCommentProc },
961 { "EditBookProc", EditBookProc },
962 { "EditCommentProc", EditCommentProc },
963 { "IcsInputBoxProc", IcsInputBoxProc },
964 { "PauseProc", PauseProc },
965 { "AcceptProc", AcceptProc },
966 { "DeclineProc", DeclineProc },
967 { "RematchProc", RematchProc },
968 { "CallFlagProc", CallFlagProc },
969 { "DrawProc", DrawProc },
970 { "AdjournProc", AdjournProc },
971 { "AbortProc", AbortProc },
972 { "ResignProc", ResignProc },
973 { "AdjuWhiteProc", AdjuWhiteProc },
974 { "AdjuBlackProc", AdjuBlackProc },
975 { "AdjuDrawProc", AdjuDrawProc },
976 { "TypeInProc", TypeInProc },
977 { "EnterKeyProc", EnterKeyProc },
978 { "UpKeyProc", UpKeyProc },
979 { "DownKeyProc", DownKeyProc },
980 { "StopObservingProc", StopObservingProc },
981 { "StopExaminingProc", StopExaminingProc },
982 { "UploadProc", UploadProc },
983 { "BackwardProc", BackwardProc },
984 { "ForwardProc", ForwardProc },
985 { "ToStartProc", ToStartProc },
986 { "ToEndProc", ToEndProc },
987 { "RevertProc", RevertProc },
988 { "AnnotateProc", AnnotateProc },
989 { "TruncateGameProc", TruncateGameProc },
990 { "MoveNowProc", MoveNowProc },
991 { "RetractMoveProc", RetractMoveProc },
992 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
993 { "UciMenuProc", (XtActionProc) UciMenuProc },
994 { "TimeControlProc", (XtActionProc) TimeControlProc },
995 { "FlipViewProc", FlipViewProc },
996 { "PonderNextMoveProc", PonderNextMoveProc },
997 #ifndef OPTIONSDIALOG
998 { "AlwaysQueenProc", AlwaysQueenProc },
999 { "AnimateDraggingProc", AnimateDraggingProc },
1000 { "AnimateMovingProc", AnimateMovingProc },
1001 { "AutoflagProc", AutoflagProc },
1002 { "AutoflipProc", AutoflipProc },
1003 { "BlindfoldProc", BlindfoldProc },
1004 { "FlashMovesProc", FlashMovesProc },
1006 { "HighlightDraggingProc", HighlightDraggingProc },
1008 { "HighlightLastMoveProc", HighlightLastMoveProc },
1009 // { "IcsAlarmProc", IcsAlarmProc },
1010 { "MoveSoundProc", MoveSoundProc },
1011 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1012 { "PopupExitMessageProc", PopupExitMessageProc },
1013 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1014 // { "PremoveProc", PremoveProc },
1015 { "ShowCoordsProc", ShowCoordsProc },
1016 { "ShowThinkingProc", ShowThinkingProc },
1017 { "HideThinkingProc", HideThinkingProc },
1018 { "TestLegalityProc", TestLegalityProc },
1020 { "SaveSettingsProc", SaveSettingsProc },
1021 { "SaveOnExitProc", SaveOnExitProc },
1022 { "InfoProc", InfoProc },
1023 { "ManProc", ManProc },
1024 { "HintProc", HintProc },
1025 { "BookProc", BookProc },
1026 { "AboutGameProc", AboutGameProc },
1027 { "AboutProc", AboutProc },
1028 { "DebugProc", DebugProc },
1029 { "NothingProc", NothingProc },
1030 { "CommentClick", (XtActionProc) CommentClick },
1031 { "CommentPopDown", (XtActionProc) CommentPopDown },
1032 { "TagsPopDown", (XtActionProc) TagsPopDown },
1033 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1034 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1035 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1036 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1037 { "GameListPopDown", (XtActionProc) GameListPopDown },
1038 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1039 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1040 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1041 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1042 { "GenericPopDown", (XtActionProc) GenericPopDown },
1043 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1044 { "SelectMove", (XtActionProc) SelectMove },
1047 char globalTranslations[] =
1048 ":<Key>F9: ResignProc() \n \
1049 :Ctrl<Key>n: ResetProc() \n \
1050 :Meta<Key>V: NewVariantProc() \n \
1051 :Ctrl<Key>o: LoadGameProc() \n \
1052 :Meta<Key>Next: LoadNextGameProc() \n \
1053 :Meta<Key>Prior: LoadPrevGameProc() \n \
1054 :Ctrl<Key>s: SaveGameProc() \n \
1055 :Ctrl<Key>c: CopyGameProc() \n \
1056 :Ctrl<Key>v: PasteGameProc() \n \
1057 :Ctrl<Key>O: LoadPositionProc() \n \
1058 :Shift<Key>Next: LoadNextPositionProc() \n \
1059 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1060 :Ctrl<Key>S: SavePositionProc() \n \
1061 :Ctrl<Key>C: CopyPositionProc() \n \
1062 :Ctrl<Key>V: PastePositionProc() \n \
1063 :Ctrl<Key>q: QuitProc() \n \
1064 :Ctrl<Key>w: MachineWhiteProc() \n \
1065 :Ctrl<Key>b: MachineBlackProc() \n \
1066 :Ctrl<Key>t: TwoMachinesProc() \n \
1067 :Ctrl<Key>a: AnalysisModeProc() \n \
1068 :Ctrl<Key>f: AnalyzeFileProc() \n \
1069 :Ctrl<Key>e: EditGameProc() \n \
1070 :Ctrl<Key>E: EditPositionProc() \n \
1071 :Meta<Key>O: EngineOutputProc() \n \
1072 :Meta<Key>E: EvalGraphProc() \n \
1073 :Meta<Key>G: ShowGameListProc() \n \
1074 :Meta<Key>H: ShowMoveListProc() \n \
1075 :<Key>Pause: PauseProc() \n \
1076 :<Key>F3: AcceptProc() \n \
1077 :<Key>F4: DeclineProc() \n \
1078 :<Key>F12: RematchProc() \n \
1079 :<Key>F5: CallFlagProc() \n \
1080 :<Key>F6: DrawProc() \n \
1081 :<Key>F7: AdjournProc() \n \
1082 :<Key>F8: AbortProc() \n \
1083 :<Key>F10: StopObservingProc() \n \
1084 :<Key>F11: StopExaminingProc() \n \
1085 :Meta Ctrl<Key>F12: DebugProc() \n \
1086 :Meta<Key>End: ToEndProc() \n \
1087 :Meta<Key>Right: ForwardProc() \n \
1088 :Meta<Key>Home: ToStartProc() \n \
1089 :Meta<Key>Left: BackwardProc() \n \
1090 :<Key>Home: RevertProc() \n \
1091 :<Key>End: TruncateGameProc() \n \
1092 :Ctrl<Key>m: MoveNowProc() \n \
1093 :Ctrl<Key>x: RetractMoveProc() \n \
1094 :Meta<Key>J: EngineMenuProc() \n \
1095 :Meta<Key>U: UciMenuProc() \n \
1096 :Meta<Key>T: TimeControlProc() \n \
1097 :Ctrl<Key>P: PonderNextMoveProc() \n "
1098 #ifndef OPTIONSDIALOG
1100 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1101 :Ctrl<Key>F: AutoflagProc() \n \
1102 :Ctrl<Key>A: AnimateMovingProc() \n \
1103 :Ctrl<Key>L: TestLegalityProc() \n \
1104 :Ctrl<Key>H: HideThinkingProc() \n "
1107 :<Key>-: Iconify() \n \
1108 :<Key>F1: ManProc() \n \
1109 :<Key>F2: FlipViewProc() \n \
1110 <KeyDown>.: BackwardProc() \n \
1111 <KeyUp>.: ForwardProc() \n \
1112 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1113 \"Send to chess program:\",,1) \n \
1114 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1115 \"Send to second chess program:\",,2) \n";
1117 char boardTranslations[] =
1118 "<Btn1Down>: HandleUserMove(0) \n \
1119 Shift<Btn1Up>: HandleUserMove(1) \n \
1120 <Btn1Up>: HandleUserMove(0) \n \
1121 <Btn1Motion>: AnimateUserMove() \n \
1122 <Btn3Motion>: HandlePV() \n \
1123 <Btn3Up>: PieceMenuPopup(menuB) \n \
1124 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1125 PieceMenuPopup(menuB) \n \
1126 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1127 PieceMenuPopup(menuW) \n \
1128 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1129 PieceMenuPopup(menuW) \n \
1130 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1131 PieceMenuPopup(menuB) \n";
1133 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1134 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1136 char ICSInputTranslations[] =
1137 "<Key>Up: UpKeyProc() \n "
1138 "<Key>Down: DownKeyProc() \n "
1139 "<Key>Return: EnterKeyProc() \n";
1141 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1142 // as the widget is destroyed before the up-click can call extend-end
1143 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1145 String xboardResources[] = {
1146 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1147 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1148 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1153 /* Max possible square size */
1154 #define MAXSQSIZE 256
1156 static int xpm_avail[MAXSQSIZE];
1158 #ifdef HAVE_DIR_STRUCT
1160 /* Extract piece size from filename */
1162 xpm_getsize(name, len, ext)
1173 if ((p=strchr(name, '.')) == NULL ||
1174 StrCaseCmp(p+1, ext) != 0)
1180 while (*p && isdigit(*p))
1187 /* Setup xpm_avail */
1189 xpm_getavail(dirname, ext)
1197 for (i=0; i<MAXSQSIZE; ++i)
1200 if (appData.debugMode)
1201 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1203 dir = opendir(dirname);
1206 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1207 programName, dirname);
1211 while ((ent=readdir(dir)) != NULL) {
1212 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1213 if (i > 0 && i < MAXSQSIZE)
1223 xpm_print_avail(fp, ext)
1229 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1230 for (i=1; i<MAXSQSIZE; ++i) {
1236 /* Return XPM piecesize closest to size */
1238 xpm_closest_to(dirname, size, ext)
1244 int sm_diff = MAXSQSIZE;
1248 xpm_getavail(dirname, ext);
1250 if (appData.debugMode)
1251 xpm_print_avail(stderr, ext);
1253 for (i=1; i<MAXSQSIZE; ++i) {
1256 diff = (diff<0) ? -diff : diff;
1257 if (diff < sm_diff) {
1265 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1271 #else /* !HAVE_DIR_STRUCT */
1272 /* If we are on a system without a DIR struct, we can't
1273 read the directory, so we can't collect a list of
1274 filenames, etc., so we can't do any size-fitting. */
1276 xpm_closest_to(dirname, size, ext)
1281 fprintf(stderr, _("\
1282 Warning: No DIR structure found on this system --\n\
1283 Unable to autosize for XPM/XIM pieces.\n\
1284 Please report this error to %s.\n\
1285 Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
1288 #endif /* HAVE_DIR_STRUCT */
1290 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1291 "magenta", "cyan", "white" };
1295 TextColors textColors[(int)NColorClasses];
1297 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1299 parse_color(str, which)
1303 char *p, buf[100], *d;
1306 if (strlen(str) > 99) /* watch bounds on buf */
1311 for (i=0; i<which; ++i) {
1318 /* Could be looking at something like:
1320 .. in which case we want to stop on a comma also */
1321 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1325 return -1; /* Use default for empty field */
1328 if (which == 2 || isdigit(*p))
1331 while (*p && isalpha(*p))
1336 for (i=0; i<8; ++i) {
1337 if (!StrCaseCmp(buf, cnames[i]))
1338 return which? (i+40) : (i+30);
1340 if (!StrCaseCmp(buf, "default")) return -1;
1342 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1347 parse_cpair(cc, str)
1351 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1352 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1357 /* bg and attr are optional */
1358 textColors[(int)cc].bg = parse_color(str, 1);
1359 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1360 textColors[(int)cc].attr = 0;
1366 /* Arrange to catch delete-window events */
1367 Atom wm_delete_window;
1369 CatchDeleteWindow(Widget w, String procname)
1372 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1373 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1374 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1381 XtSetArg(args[0], XtNiconic, False);
1382 XtSetValues(shellWidget, args, 1);
1384 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1387 //---------------------------------------------------------------------------------------------------------
1388 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1391 #define CW_USEDEFAULT (1<<31)
1392 #define ICS_TEXT_MENU_SIZE 90
1393 #define DEBUG_FILE "xboard.debug"
1394 #define SetCurrentDirectory chdir
1395 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1399 // these two must some day move to frontend.h, when they are implemented
1400 Boolean GameListIsUp();
1402 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1405 // front-end part of option handling
1407 // [HGM] This platform-dependent table provides the location for storing the color info
1408 extern char *crWhite, * crBlack;
1412 &appData.whitePieceColor,
1413 &appData.blackPieceColor,
1414 &appData.lightSquareColor,
1415 &appData.darkSquareColor,
1416 &appData.highlightSquareColor,
1417 &appData.premoveHighlightColor,
1418 &appData.lowTimeWarningColor,
1429 // [HGM] font: keep a font for each square size, even non-stndard ones
1430 #define NUM_SIZES 18
1431 #define MAX_SIZE 130
1432 Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1433 char *fontTable[NUM_FONTS][MAX_SIZE];
1436 ParseFont(char *name, int number)
1437 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1439 if(sscanf(name, "size%d:", &size)) {
1440 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1441 // defer processing it until we know if it matches our board size
1442 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1443 fontTable[number][size] = strdup(strchr(name, ':')+1);
1444 fontValid[number][size] = True;
1449 case 0: // CLOCK_FONT
1450 appData.clockFont = strdup(name);
1452 case 1: // MESSAGE_FONT
1453 appData.font = strdup(name);
1455 case 2: // COORD_FONT
1456 appData.coordFont = strdup(name);
1461 fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1466 { // only 2 fonts currently
1467 appData.clockFont = CLOCK_FONT_NAME;
1468 appData.coordFont = COORD_FONT_NAME;
1469 appData.font = DEFAULT_FONT_NAME;
1474 { // no-op, until we identify the code for this already in XBoard and move it here
1478 ParseColor(int n, char *name)
1479 { // in XBoard, just copy the color-name string
1480 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1484 ParseTextAttribs(ColorClass cc, char *s)
1486 (&appData.colorShout)[cc] = strdup(s);
1490 ParseBoardSize(void *addr, char *name)
1492 appData.boardSize = strdup(name);
1497 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1501 SetCommPortDefaults()
1502 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1505 // [HGM] args: these three cases taken out to stay in front-end
1507 SaveFontArg(FILE *f, ArgDescriptor *ad)
1510 int i, n = (int)(intptr_t)ad->argLoc;
1512 case 0: // CLOCK_FONT
1513 name = appData.clockFont;
1515 case 1: // MESSAGE_FONT
1516 name = appData.font;
1518 case 2: // COORD_FONT
1519 name = appData.coordFont;
1524 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1525 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1526 fontTable[n][squareSize] = strdup(name);
1527 fontValid[n][squareSize] = True;
1530 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1531 fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
1536 { // nothing to do, as the sounds are at all times represented by their text-string names already
1540 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1541 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1542 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1546 SaveColor(FILE *f, ArgDescriptor *ad)
1547 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1548 if(colorVariable[(int)(intptr_t)ad->argLoc])
1549 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1553 SaveBoardSize(FILE *f, char *name, void *addr)
1554 { // wrapper to shield back-end from BoardSize & sizeInfo
1555 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1559 ParseCommPortSettings(char *s)
1560 { // no such option in XBoard (yet)
1563 extern Widget engineOutputShell;
1566 GetActualPlacement(Widget wg, WindowPlacement *wp)
1576 XtSetArg(args[i], XtNx, &x); i++;
1577 XtSetArg(args[i], XtNy, &y); i++;
1578 XtSetArg(args[i], XtNwidth, &w); i++;
1579 XtSetArg(args[i], XtNheight, &h); i++;
1580 XtGetValues(wg, args, i);
1589 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1590 // In XBoard this will have to wait until awareness of window parameters is implemented
1591 GetActualPlacement(shellWidget, &wpMain);
1592 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput);
1593 if(MoveHistoryIsUp()) GetActualPlacement(shells[7], &wpMoveHistory);
1594 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1595 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1596 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1597 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1601 PrintCommPortSettings(FILE *f, char *name)
1602 { // This option does not exist in XBoard
1606 MySearchPath(char *installDir, char *name, char *fullname)
1607 { // just append installDir and name. Perhaps ExpandPath should be used here?
1608 name = ExpandPathName(name);
1609 if(name && name[0] == '/')
1610 safeStrCpy(fullname, name, MSG_SIZ );
1612 sprintf(fullname, "%s%c%s", installDir, '/', name);
1618 MyGetFullPathName(char *name, char *fullname)
1619 { // should use ExpandPath?
1620 name = ExpandPathName(name);
1621 safeStrCpy(fullname, name, MSG_SIZ );
1626 EnsureOnScreen(int *x, int *y, int minX, int minY)
1633 { // [HGM] args: allows testing if main window is realized from back-end
1634 return xBoardWindow != 0;
1638 PopUpStartupDialog()
1639 { // start menu not implemented in XBoard
1643 ConvertToLine(int argc, char **argv)
1645 static char line[128*1024], buf[1024];
1649 for(i=1; i<argc; i++)
1651 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') || argv[i][0] == NULLCHAR)
1652 && argv[i][0] != '{' )
1653 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1655 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1656 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1659 line[strlen(line)-1] = NULLCHAR;
1663 //--------------------------------------------------------------------------------------------
1665 extern Boolean twoBoards, partnerUp;
1668 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1670 #define BoardSize int
1671 void InitDrawingSizes(BoardSize boardSize, int flags)
1672 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1673 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1675 XtGeometryResult gres;
1678 if(!formWidget) return;
1681 * Enable shell resizing.
1683 shellArgs[0].value = (XtArgVal) &w;
1684 shellArgs[1].value = (XtArgVal) &h;
1685 XtGetValues(shellWidget, shellArgs, 2);
1687 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1688 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1689 XtSetValues(shellWidget, &shellArgs[2], 4);
1691 XtSetArg(args[0], XtNdefaultDistance, &sep);
1692 XtGetValues(formWidget, args, 1);
1694 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1695 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1696 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1698 hOffset = boardWidth + 10;
1699 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1700 secondSegments[i] = gridSegments[i];
1701 secondSegments[i].x1 += hOffset;
1702 secondSegments[i].x2 += hOffset;
1705 XtSetArg(args[0], XtNwidth, boardWidth);
1706 XtSetArg(args[1], XtNheight, boardHeight);
1707 XtSetValues(boardWidget, args, 2);
1709 timerWidth = (boardWidth - sep) / 2;
1710 XtSetArg(args[0], XtNwidth, timerWidth);
1711 XtSetValues(whiteTimerWidget, args, 1);
1712 XtSetValues(blackTimerWidget, args, 1);
1714 XawFormDoLayout(formWidget, False);
1716 if (appData.titleInWindow) {
1718 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1719 XtSetArg(args[i], XtNheight, &h); i++;
1720 XtGetValues(titleWidget, args, i);
1722 w = boardWidth - 2*bor;
1724 XtSetArg(args[0], XtNwidth, &w);
1725 XtGetValues(menuBarWidget, args, 1);
1726 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1729 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1730 if (gres != XtGeometryYes && appData.debugMode) {
1732 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1733 programName, gres, w, h, wr, hr);
1737 XawFormDoLayout(formWidget, True);
1740 * Inhibit shell resizing.
1742 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1743 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1744 shellArgs[4].value = shellArgs[2].value = w;
1745 shellArgs[5].value = shellArgs[3].value = h;
1746 XtSetValues(shellWidget, &shellArgs[0], 6);
1748 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1751 for(i=0; i<4; i++) {
1753 for(p=0; p<=(int)WhiteKing; p++)
1754 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1755 if(gameInfo.variant == VariantShogi) {
1756 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1757 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1758 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1759 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1760 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1763 if(gameInfo.variant == VariantGothic) {
1764 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1767 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1768 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1769 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1772 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1773 for(p=0; p<=(int)WhiteKing; p++)
1774 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1775 if(gameInfo.variant == VariantShogi) {
1776 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1777 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1778 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1779 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1780 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1783 if(gameInfo.variant == VariantGothic) {
1784 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1787 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1788 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1789 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1794 for(i=0; i<2; i++) {
1796 for(p=0; p<=(int)WhiteKing; p++)
1797 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1798 if(gameInfo.variant == VariantShogi) {
1799 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1800 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1801 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1802 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1803 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1806 if(gameInfo.variant == VariantGothic) {
1807 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1810 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1811 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1812 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1822 void ParseIcsTextColors()
1823 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1824 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1825 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1826 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1827 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1828 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1829 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1830 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1831 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1832 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1833 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1835 if (appData.colorize) {
1837 _("%s: can't parse color names; disabling colorization\n"),
1840 appData.colorize = FALSE;
1845 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1846 XrmValue vFrom, vTo;
1847 int forceMono = False;
1849 if (!appData.monoMode) {
1850 vFrom.addr = (caddr_t) appData.lightSquareColor;
1851 vFrom.size = strlen(appData.lightSquareColor);
1852 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1853 if (vTo.addr == NULL) {
1854 appData.monoMode = True;
1857 lightSquareColor = *(Pixel *) vTo.addr;
1860 if (!appData.monoMode) {
1861 vFrom.addr = (caddr_t) appData.darkSquareColor;
1862 vFrom.size = strlen(appData.darkSquareColor);
1863 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1864 if (vTo.addr == NULL) {
1865 appData.monoMode = True;
1868 darkSquareColor = *(Pixel *) vTo.addr;
1871 if (!appData.monoMode) {
1872 vFrom.addr = (caddr_t) appData.whitePieceColor;
1873 vFrom.size = strlen(appData.whitePieceColor);
1874 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1875 if (vTo.addr == NULL) {
1876 appData.monoMode = True;
1879 whitePieceColor = *(Pixel *) vTo.addr;
1882 if (!appData.monoMode) {
1883 vFrom.addr = (caddr_t) appData.blackPieceColor;
1884 vFrom.size = strlen(appData.blackPieceColor);
1885 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1886 if (vTo.addr == NULL) {
1887 appData.monoMode = True;
1890 blackPieceColor = *(Pixel *) vTo.addr;
1894 if (!appData.monoMode) {
1895 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1896 vFrom.size = strlen(appData.highlightSquareColor);
1897 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1898 if (vTo.addr == NULL) {
1899 appData.monoMode = True;
1902 highlightSquareColor = *(Pixel *) vTo.addr;
1906 if (!appData.monoMode) {
1907 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1908 vFrom.size = strlen(appData.premoveHighlightColor);
1909 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1910 if (vTo.addr == NULL) {
1911 appData.monoMode = True;
1914 premoveHighlightColor = *(Pixel *) vTo.addr;
1922 { // [HGM] taken out of main
1924 if (appData.monoMode && // [HGM] no sense to go on to certain doom
1925 (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
1926 appData.bitmapDirectory = DEF_BITMAP_DIR;
1928 if (appData.bitmapDirectory[0] != NULLCHAR) {
1932 CreateXPMBoard(appData.liteBackTextureFile, 1);
1933 CreateXPMBoard(appData.darkBackTextureFile, 0);
1937 /* Create regular pieces */
1938 if (!useImages) CreatePieces();
1947 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1948 XSetWindowAttributes window_attributes;
1950 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1951 XrmValue vFrom, vTo;
1952 XtGeometryResult gres;
1955 int forceMono = False;
1957 srandom(time(0)); // [HGM] book: make random truly random
1959 setbuf(stdout, NULL);
1960 setbuf(stderr, NULL);
1963 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1964 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1968 programName = strrchr(argv[0], '/');
1969 if (programName == NULL)
1970 programName = argv[0];
1975 XtSetLanguageProc(NULL, NULL, NULL);
1976 bindtextdomain(PACKAGE, LOCALEDIR);
1977 textdomain(PACKAGE);
1981 XtAppInitialize(&appContext, "XBoard", shellOptions,
1982 XtNumber(shellOptions),
1983 &argc, argv, xboardResources, NULL, 0);
1984 appData.boardSize = "";
1985 InitAppData(ConvertToLine(argc, argv));
1987 if (p == NULL) p = "/tmp";
1988 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1989 gameCopyFilename = (char*) malloc(i);
1990 gamePasteFilename = (char*) malloc(i);
1991 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1992 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1994 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1995 clientResources, XtNumber(clientResources),
1998 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1999 static char buf[MSG_SIZ];
2000 EscapeExpand(buf, appData.firstInitString);
2001 appData.firstInitString = strdup(buf);
2002 EscapeExpand(buf, appData.secondInitString);
2003 appData.secondInitString = strdup(buf);
2004 EscapeExpand(buf, appData.firstComputerString);
2005 appData.firstComputerString = strdup(buf);
2006 EscapeExpand(buf, appData.secondComputerString);
2007 appData.secondComputerString = strdup(buf);
2010 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2013 if (chdir(chessDir) != 0) {
2014 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2020 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2021 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2022 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2023 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2026 setbuf(debugFP, NULL);
2030 if (appData.debugMode) {
2031 fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
2035 /* [HGM,HR] make sure board size is acceptable */
2036 if(appData.NrFiles > BOARD_FILES ||
2037 appData.NrRanks > BOARD_RANKS )
2038 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2041 /* This feature does not work; animation needs a rewrite */
2042 appData.highlightDragging = FALSE;
2046 xDisplay = XtDisplay(shellWidget);
2047 xScreen = DefaultScreen(xDisplay);
2048 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2050 gameInfo.variant = StringToVariant(appData.variant);
2051 InitPosition(FALSE);
2054 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2056 if (isdigit(appData.boardSize[0])) {
2057 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2058 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2059 &fontPxlSize, &smallLayout, &tinyLayout);
2061 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2062 programName, appData.boardSize);
2066 /* Find some defaults; use the nearest known size */
2067 SizeDefaults *szd, *nearest;
2068 int distance = 99999;
2069 nearest = szd = sizeDefaults;
2070 while (szd->name != NULL) {
2071 if (abs(szd->squareSize - squareSize) < distance) {
2073 distance = abs(szd->squareSize - squareSize);
2074 if (distance == 0) break;
2078 if (i < 2) lineGap = nearest->lineGap;
2079 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2080 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2081 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2082 if (i < 6) smallLayout = nearest->smallLayout;
2083 if (i < 7) tinyLayout = nearest->tinyLayout;
2086 SizeDefaults *szd = sizeDefaults;
2087 if (*appData.boardSize == NULLCHAR) {
2088 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2089 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2092 if (szd->name == NULL) szd--;
2093 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2095 while (szd->name != NULL &&
2096 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2097 if (szd->name == NULL) {
2098 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2099 programName, appData.boardSize);
2103 squareSize = szd->squareSize;
2104 lineGap = szd->lineGap;
2105 clockFontPxlSize = szd->clockFontPxlSize;
2106 coordFontPxlSize = szd->coordFontPxlSize;
2107 fontPxlSize = szd->fontPxlSize;
2108 smallLayout = szd->smallLayout;
2109 tinyLayout = szd->tinyLayout;
2110 // [HGM] font: use defaults from settings file if available and not overruled
2112 if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2113 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2114 if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2115 appData.font = fontTable[MESSAGE_FONT][squareSize];
2116 if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2117 appData.coordFont = fontTable[COORD_FONT][squareSize];
2119 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2120 if (strlen(appData.pixmapDirectory) > 0) {
2121 p = ExpandPathName(appData.pixmapDirectory);
2123 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2124 appData.pixmapDirectory);
2127 if (appData.debugMode) {
2128 fprintf(stderr, _("\
2129 XBoard square size (hint): %d\n\
2130 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2132 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2133 if (appData.debugMode) {
2134 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2137 defaultLineGap = lineGap;
2138 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2140 /* [HR] height treated separately (hacked) */
2141 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2142 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2143 if (appData.showJail == 1) {
2144 /* Jail on top and bottom */
2145 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2146 XtSetArg(boardArgs[2], XtNheight,
2147 boardHeight + 2*(lineGap + squareSize));
2148 } else if (appData.showJail == 2) {
2150 XtSetArg(boardArgs[1], XtNwidth,
2151 boardWidth + 2*(lineGap + squareSize));
2152 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2155 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2156 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2160 * Determine what fonts to use.
2163 appData.font = InsertPxlSize(appData.font, fontPxlSize);
2164 appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
2165 appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
2166 fontSet = CreateFontSet(appData.font);
2167 clockFontSet = CreateFontSet(appData.clockFont);
2169 /* For the coordFont, use the 0th font of the fontset. */
2170 XFontSet coordFontSet = CreateFontSet(appData.coordFont);
2171 XFontStruct **font_struct_list;
2172 char **font_name_list;
2173 XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
2174 coordFontID = XLoadFont(xDisplay, font_name_list[0]);
2175 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2178 appData.font = FindFont(appData.font, fontPxlSize);
2179 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2180 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2181 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2182 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2183 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2184 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2186 countFontID = coordFontID; // [HGM] holdings
2187 countFontStruct = coordFontStruct;
2189 xdb = XtDatabase(xDisplay);
2191 XrmPutLineResource(&xdb, "*international: True");
2192 vTo.size = sizeof(XFontSet);
2193 vTo.addr = (XtPointer) &fontSet;
2194 XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
2196 XrmPutStringResource(&xdb, "*font", appData.font);
2200 * Detect if there are not enough colors available and adapt.
2202 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2203 appData.monoMode = True;
2206 forceMono = MakeColors();
2209 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2211 appData.monoMode = True;
2214 if (appData.lowTimeWarning && !appData.monoMode) {
2215 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2216 vFrom.size = strlen(appData.lowTimeWarningColor);
2217 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2218 if (vTo.addr == NULL)
2219 appData.monoMode = True;
2221 lowTimeWarningColor = *(Pixel *) vTo.addr;
2224 if (appData.monoMode && appData.debugMode) {
2225 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2226 (unsigned long) XWhitePixel(xDisplay, xScreen),
2227 (unsigned long) XBlackPixel(xDisplay, xScreen));
2230 ParseIcsTextColors();
2231 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2232 textColors[ColorNone].attr = 0;
2234 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2240 layoutName = "tinyLayout";
2241 } else if (smallLayout) {
2242 layoutName = "smallLayout";
2244 layoutName = "normalLayout";
2246 /* Outer layoutWidget is there only to provide a name for use in
2247 resources that depend on the layout style */
2249 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2250 layoutArgs, XtNumber(layoutArgs));
2252 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2253 formArgs, XtNumber(formArgs));
2254 XtSetArg(args[0], XtNdefaultDistance, &sep);
2255 XtGetValues(formWidget, args, 1);
2258 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2259 XtSetArg(args[0], XtNtop, XtChainTop);
2260 XtSetArg(args[1], XtNbottom, XtChainTop);
2261 XtSetArg(args[2], XtNright, XtChainLeft);
2262 XtSetValues(menuBarWidget, args, 3);
2264 widgetList[j++] = whiteTimerWidget =
2265 XtCreateWidget("whiteTime", labelWidgetClass,
2266 formWidget, timerArgs, XtNumber(timerArgs));
2268 XtSetArg(args[0], XtNfontSet, clockFontSet);
2270 XtSetArg(args[0], XtNfont, clockFontStruct);
2272 XtSetArg(args[1], XtNtop, XtChainTop);
2273 XtSetArg(args[2], XtNbottom, XtChainTop);
2274 XtSetValues(whiteTimerWidget, args, 3);
2276 widgetList[j++] = blackTimerWidget =
2277 XtCreateWidget("blackTime", labelWidgetClass,
2278 formWidget, timerArgs, XtNumber(timerArgs));
2280 XtSetArg(args[0], XtNfontSet, clockFontSet);
2282 XtSetArg(args[0], XtNfont, clockFontStruct);
2284 XtSetArg(args[1], XtNtop, XtChainTop);
2285 XtSetArg(args[2], XtNbottom, XtChainTop);
2286 XtSetValues(blackTimerWidget, args, 3);
2288 if (appData.titleInWindow) {
2289 widgetList[j++] = titleWidget =
2290 XtCreateWidget("title", labelWidgetClass, formWidget,
2291 titleArgs, XtNumber(titleArgs));
2292 XtSetArg(args[0], XtNtop, XtChainTop);
2293 XtSetArg(args[1], XtNbottom, XtChainTop);
2294 XtSetValues(titleWidget, args, 2);
2297 if (appData.showButtonBar) {
2298 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2299 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2300 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2301 XtSetArg(args[2], XtNtop, XtChainTop);
2302 XtSetArg(args[3], XtNbottom, XtChainTop);
2303 XtSetValues(buttonBarWidget, args, 4);
2306 widgetList[j++] = messageWidget =
2307 XtCreateWidget("message", labelWidgetClass, formWidget,
2308 messageArgs, XtNumber(messageArgs));
2309 XtSetArg(args[0], XtNtop, XtChainTop);
2310 XtSetArg(args[1], XtNbottom, XtChainTop);
2311 XtSetValues(messageWidget, args, 2);
2313 widgetList[j++] = boardWidget =
2314 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2315 XtNumber(boardArgs));
2317 XtManageChildren(widgetList, j);
2319 timerWidth = (boardWidth - sep) / 2;
2320 XtSetArg(args[0], XtNwidth, timerWidth);
2321 XtSetValues(whiteTimerWidget, args, 1);
2322 XtSetValues(blackTimerWidget, args, 1);
2324 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2325 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2326 XtGetValues(whiteTimerWidget, args, 2);
2328 if (appData.showButtonBar) {
2329 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2330 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2331 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2335 * formWidget uses these constraints but they are stored
2339 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2340 XtSetValues(menuBarWidget, args, i);
2341 if (appData.titleInWindow) {
2344 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2345 XtSetValues(whiteTimerWidget, args, i);
2347 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2348 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2349 XtSetValues(blackTimerWidget, args, i);
2351 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2352 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2353 XtSetValues(titleWidget, args, i);
2355 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2356 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2357 XtSetValues(messageWidget, args, i);
2358 if (appData.showButtonBar) {
2360 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2361 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2362 XtSetValues(buttonBarWidget, args, i);
2366 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2367 XtSetValues(whiteTimerWidget, args, i);
2369 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2370 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2371 XtSetValues(blackTimerWidget, args, i);
2373 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2374 XtSetValues(titleWidget, args, i);
2376 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2377 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2378 XtSetValues(messageWidget, args, i);
2379 if (appData.showButtonBar) {
2381 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2382 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2383 XtSetValues(buttonBarWidget, args, i);
2388 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2389 XtSetValues(whiteTimerWidget, args, i);
2391 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2392 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2393 XtSetValues(blackTimerWidget, args, i);
2395 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2396 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2397 XtSetValues(messageWidget, args, i);
2398 if (appData.showButtonBar) {
2400 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2401 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2402 XtSetValues(buttonBarWidget, args, i);
2406 XtSetArg(args[0], XtNfromVert, messageWidget);
2407 XtSetArg(args[1], XtNtop, XtChainTop);
2408 XtSetArg(args[2], XtNbottom, XtChainBottom);
2409 XtSetArg(args[3], XtNleft, XtChainLeft);
2410 XtSetArg(args[4], XtNright, XtChainRight);
2411 XtSetValues(boardWidget, args, 5);
2413 XtRealizeWidget(shellWidget);
2416 XtSetArg(args[0], XtNx, wpMain.x);
2417 XtSetArg(args[1], XtNy, wpMain.y);
2418 XtSetValues(shellWidget, args, 2);
2422 * Correct the width of the message and title widgets.
2423 * It is not known why some systems need the extra fudge term.
2424 * The value "2" is probably larger than needed.
2426 XawFormDoLayout(formWidget, False);
2428 #define WIDTH_FUDGE 2
2430 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2431 XtSetArg(args[i], XtNheight, &h); i++;
2432 XtGetValues(messageWidget, args, i);
2433 if (appData.showButtonBar) {
2435 XtSetArg(args[i], XtNwidth, &w); i++;
2436 XtGetValues(buttonBarWidget, args, i);
2437 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2439 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2442 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2443 if (gres != XtGeometryYes && appData.debugMode) {
2444 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2445 programName, gres, w, h, wr, hr);
2448 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2449 /* The size used for the child widget in layout lags one resize behind
2450 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2452 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2453 if (gres != XtGeometryYes && appData.debugMode) {
2454 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2455 programName, gres, w, h, wr, hr);
2458 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2459 XtSetArg(args[1], XtNright, XtChainRight);
2460 XtSetValues(messageWidget, args, 2);
2462 if (appData.titleInWindow) {
2464 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2465 XtSetArg(args[i], XtNheight, &h); i++;
2466 XtGetValues(titleWidget, args, i);
2468 w = boardWidth - 2*bor;
2470 XtSetArg(args[0], XtNwidth, &w);
2471 XtGetValues(menuBarWidget, args, 1);
2472 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2475 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2476 if (gres != XtGeometryYes && appData.debugMode) {
2478 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2479 programName, gres, w, h, wr, hr);
2482 XawFormDoLayout(formWidget, True);
2484 xBoardWindow = XtWindow(boardWidget);
2486 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2487 // not need to go into InitDrawingSizes().
2491 * Create X checkmark bitmap and initialize option menu checks.
2493 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2494 checkmark_bits, checkmark_width, checkmark_height);
2495 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2496 #ifndef OPTIONSDIALOG
2497 if (appData.alwaysPromoteToQueen) {
2498 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2501 if (appData.animateDragging) {
2502 XtSetValues(XtNameToWidget(menuBarWidget,
2503 "menuOptions.Animate Dragging"),
2506 if (appData.animate) {
2507 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2510 if (appData.autoCallFlag) {
2511 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2514 if (appData.autoFlipView) {
2515 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2518 if (appData.blindfold) {
2519 XtSetValues(XtNameToWidget(menuBarWidget,
2520 "menuOptions.Blindfold"), args, 1);
2522 if (appData.flashCount > 0) {
2523 XtSetValues(XtNameToWidget(menuBarWidget,
2524 "menuOptions.Flash Moves"),
2528 if (appData.highlightDragging) {
2529 XtSetValues(XtNameToWidget(menuBarWidget,
2530 "menuOptions.Highlight Dragging"),
2534 if (appData.highlightLastMove) {
2535 XtSetValues(XtNameToWidget(menuBarWidget,
2536 "menuOptions.Highlight Last Move"),
2539 if (appData.highlightMoveWithArrow) {
2540 XtSetValues(XtNameToWidget(menuBarWidget,
2541 "menuOptions.Arrow"),
2544 // if (appData.icsAlarm) {
2545 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2548 if (appData.ringBellAfterMoves) {
2549 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2552 if (appData.oneClick) {
2553 XtSetValues(XtNameToWidget(menuBarWidget,
2554 "menuOptions.OneClick"), args, 1);
2556 if (appData.periodicUpdates) {
2557 XtSetValues(XtNameToWidget(menuBarWidget,
2558 "menuOptions.Periodic Updates"), args, 1);
2560 if (appData.ponderNextMove) {
2561 XtSetValues(XtNameToWidget(menuBarWidget,
2562 "menuOptions.Ponder Next Move"), args, 1);
2564 if (appData.popupExitMessage) {
2565 XtSetValues(XtNameToWidget(menuBarWidget,
2566 "menuOptions.Popup Exit Message"), args, 1);
2568 if (appData.popupMoveErrors) {
2569 XtSetValues(XtNameToWidget(menuBarWidget,
2570 "menuOptions.Popup Move Errors"), args, 1);
2572 // if (appData.premove) {
2573 // XtSetValues(XtNameToWidget(menuBarWidget,
2574 // "menuOptions.Premove"), args, 1);
2576 if (appData.showCoords) {
2577 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2580 if (appData.hideThinkingFromHuman) {
2581 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2584 if (appData.testLegality) {
2585 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2589 if (saveSettingsOnExit) {
2590 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2597 ReadBitmap(&wIconPixmap, "icon_white.bm",
2598 icon_white_bits, icon_white_width, icon_white_height);
2599 ReadBitmap(&bIconPixmap, "icon_black.bm",
2600 icon_black_bits, icon_black_width, icon_black_height);
2601 iconPixmap = wIconPixmap;
2603 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2604 XtSetValues(shellWidget, args, i);
2607 * Create a cursor for the board widget.
2609 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2610 XChangeWindowAttributes(xDisplay, xBoardWindow,
2611 CWCursor, &window_attributes);
2614 * Inhibit shell resizing.
2616 shellArgs[0].value = (XtArgVal) &w;
2617 shellArgs[1].value = (XtArgVal) &h;
2618 XtGetValues(shellWidget, shellArgs, 2);
2619 shellArgs[4].value = shellArgs[2].value = w;
2620 shellArgs[5].value = shellArgs[3].value = h;
2621 XtSetValues(shellWidget, &shellArgs[2], 4);
2622 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2623 marginH = h - boardHeight;
2625 CatchDeleteWindow(shellWidget, "QuitProc");
2633 if (appData.animate || appData.animateDragging)
2636 XtAugmentTranslations(formWidget,
2637 XtParseTranslationTable(globalTranslations));
2638 XtAugmentTranslations(boardWidget,
2639 XtParseTranslationTable(boardTranslations));
2640 XtAugmentTranslations(whiteTimerWidget,
2641 XtParseTranslationTable(whiteTranslations));
2642 XtAugmentTranslations(blackTimerWidget,
2643 XtParseTranslationTable(blackTranslations));
2645 /* Why is the following needed on some versions of X instead
2646 * of a translation? */
2647 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2648 (XtEventHandler) EventProc, NULL);
2650 XtAddEventHandler(formWidget, KeyPressMask, False,
2651 (XtEventHandler) MoveTypeInProc, NULL);
2653 /* [AS] Restore layout */
2654 if( wpMoveHistory.visible ) {
2658 if( wpEvalGraph.visible )
2663 if( wpEngineOutput.visible ) {
2664 EngineOutputPopUp();
2669 if (errorExitStatus == -1) {
2670 if (appData.icsActive) {
2671 /* We now wait until we see "login:" from the ICS before
2672 sending the logon script (problems with timestamp otherwise) */
2673 /*ICSInitScript();*/
2674 if (appData.icsInputBox) ICSInputBoxPopUp();
2678 signal(SIGWINCH, TermSizeSigHandler);
2680 signal(SIGINT, IntSigHandler);
2681 signal(SIGTERM, IntSigHandler);
2682 if (*appData.cmailGameName != NULLCHAR) {
2683 signal(SIGUSR1, CmailSigHandler);
2686 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2688 // XtSetKeyboardFocus(shellWidget, formWidget);
2689 XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
2691 XtAppMainLoop(appContext);
2692 if (appData.debugMode) fclose(debugFP); // [DM] debug
2696 static Boolean noEcho;
2701 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2702 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2704 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2705 unlink(gameCopyFilename);
2706 unlink(gamePasteFilename);
2707 if(noEcho) EchoOn();
2710 RETSIGTYPE TermSizeSigHandler(int sig)
2723 CmailSigHandler(sig)
2729 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2731 /* Activate call-back function CmailSigHandlerCallBack() */
2732 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2734 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2738 CmailSigHandlerCallBack(isr, closure, message, count, error)
2746 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2748 /**** end signal code ****/
2754 /* try to open the icsLogon script, either in the location given
2755 * or in the users HOME directory
2762 f = fopen(appData.icsLogon, "r");
2765 homedir = getenv("HOME");
2766 if (homedir != NULL)
2768 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2769 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2770 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2771 f = fopen(buf, "r");
2776 ProcessICSInitScript(f);
2778 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2801 if (!menuBarWidget) return;
2802 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2804 DisplayError("menuEdit.Revert", 0);
2806 XtSetSensitive(w, !grey);
2808 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2810 DisplayError("menuEdit.Annotate", 0);
2812 XtSetSensitive(w, !grey);
2817 SetMenuEnables(enab)
2821 if (!menuBarWidget) return;
2822 while (enab->name != NULL) {
2823 w = XtNameToWidget(menuBarWidget, enab->name);
2825 DisplayError(enab->name, 0);
2827 XtSetSensitive(w, enab->value);
2833 Enables icsEnables[] = {
2834 { "menuFile.Mail Move", False },
2835 { "menuFile.Reload CMail Message", False },
2836 { "menuMode.Machine Black", False },
2837 { "menuMode.Machine White", False },
2838 { "menuMode.Analysis Mode", False },
2839 { "menuMode.Analyze File", False },
2840 { "menuMode.Two Machines", False },
2841 { "menuMode.Machine Match", False },
2843 { "menuEngine.Hint", False },
2844 { "menuEngine.Book", False },
2845 { "menuEngine.Move Now", False },
2846 #ifndef OPTIONSDIALOG
2847 { "menuOptions.Periodic Updates", False },
2848 { "menuOptions.Hide Thinking", False },
2849 { "menuOptions.Ponder Next Move", False },
2852 { "menuEngine.Engine #1 Settings", False },
2853 { "menuEngine.Engine #2 Settings", False },
2854 { "menuEngine.Load Engine", False },
2855 { "menuEdit.Annotate", False },
2856 { "menuOptions.Match", False },
2860 Enables ncpEnables[] = {
2861 { "menuFile.Mail Move", False },
2862 { "menuFile.Reload CMail Message", False },
2863 { "menuMode.Machine White", False },
2864 { "menuMode.Machine Black", False },
2865 { "menuMode.Analysis Mode", False },
2866 { "menuMode.Analyze File", False },
2867 { "menuMode.Two Machines", False },
2868 { "menuMode.Machine Match", False },
2869 { "menuMode.ICS Client", False },
2870 { "menuView.ICStex", False },
2871 { "menuView.ICS Input Box", False },
2872 { "Action", False },
2873 { "menuEdit.Revert", False },
2874 { "menuEdit.Annotate", False },
2875 { "menuEngine.Engine #1 Settings", False },
2876 { "menuEngine.Engine #2 Settings", False },
2877 { "menuEngine.Move Now", False },
2878 { "menuEngine.Retract Move", False },
2879 { "menuOptions.ICS", False },
2880 #ifndef OPTIONSDIALOG
2881 { "menuOptions.Auto Flag", False },
2882 { "menuOptions.Auto Flip View", False },
2883 // { "menuOptions.ICS Alarm", False },
2884 { "menuOptions.Move Sound", False },
2885 { "menuOptions.Hide Thinking", False },
2886 { "menuOptions.Periodic Updates", False },
2887 { "menuOptions.Ponder Next Move", False },
2889 { "menuEngine.Hint", False },
2890 { "menuEngine.Book", False },
2894 Enables gnuEnables[] = {
2895 { "menuMode.ICS Client", False },
2896 { "menuView.ICStex", False },
2897 { "menuView.ICS Input Box", False },
2898 { "menuAction.Accept", False },
2899 { "menuAction.Decline", False },
2900 { "menuAction.Rematch", False },
2901 { "menuAction.Adjourn", False },
2902 { "menuAction.Stop Examining", False },
2903 { "menuAction.Stop Observing", False },
2904 { "menuAction.Upload to Examine", False },
2905 { "menuEdit.Revert", False },
2906 { "menuEdit.Annotate", False },
2907 { "menuOptions.ICS", False },
2909 /* The next two options rely on SetCmailMode being called *after* */
2910 /* SetGNUMode so that when GNU is being used to give hints these */
2911 /* menu options are still available */
2913 { "menuFile.Mail Move", False },
2914 { "menuFile.Reload CMail Message", False },
2915 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
2916 { "menuMode.Machine White", True },
2917 { "menuMode.Machine Black", True },
2918 { "menuMode.Analysis Mode", True },
2919 { "menuMode.Analyze File", True },
2920 { "menuMode.Two Machines", True },
2921 { "menuMode.Machine Match", True },
2922 { "menuEngine.Engine #1 Settings", True },
2923 { "menuEngine.Engine #2 Settings", True },
2924 { "menuEngine.Hint", True },
2925 { "menuEngine.Book", True },
2926 { "menuEngine.Move Now", True },
2927 { "menuEngine.Retract Move", True },
2932 Enables cmailEnables[] = {
2934 { "menuAction.Call Flag", False },
2935 { "menuAction.Draw", True },
2936 { "menuAction.Adjourn", False },
2937 { "menuAction.Abort", False },
2938 { "menuAction.Stop Observing", False },
2939 { "menuAction.Stop Examining", False },
2940 { "menuFile.Mail Move", True },
2941 { "menuFile.Reload CMail Message", True },
2945 Enables trainingOnEnables[] = {
2946 { "menuMode.Edit Comment", False },
2947 { "menuMode.Pause", False },
2948 { "menuEdit.Forward", False },
2949 { "menuEdit.Backward", False },
2950 { "menuEdit.Forward to End", False },
2951 { "menuEdit.Back to Start", False },
2952 { "menuEngine.Move Now", False },
2953 { "menuEdit.Truncate Game", False },
2957 Enables trainingOffEnables[] = {
2958 { "menuMode.Edit Comment", True },
2959 { "menuMode.Pause", True },
2960 { "menuEdit.Forward", True },
2961 { "menuEdit.Backward", True },
2962 { "menuEdit.Forward to End", True },
2963 { "menuEdit.Back to Start", True },
2964 { "menuEngine.Move Now", True },
2965 { "menuEdit.Truncate Game", True },
2969 Enables machineThinkingEnables[] = {
2970 { "menuFile.Load Game", False },
2971 // { "menuFile.Load Next Game", False },
2972 // { "menuFile.Load Previous Game", False },
2973 // { "menuFile.Reload Same Game", False },
2974 { "menuEdit.Paste Game", False },
2975 { "menuFile.Load Position", False },
2976 // { "menuFile.Load Next Position", False },
2977 // { "menuFile.Load Previous Position", False },
2978 // { "menuFile.Reload Same Position", False },
2979 { "menuEdit.Paste Position", False },
2980 { "menuMode.Machine White", False },
2981 { "menuMode.Machine Black", False },
2982 { "menuMode.Two Machines", False },
2983 // { "menuMode.Machine Match", False },
2984 { "menuEngine.Retract Move", False },
2988 Enables userThinkingEnables[] = {
2989 { "menuFile.Load Game", True },
2990 // { "menuFile.Load Next Game", True },
2991 // { "menuFile.Load Previous Game", True },
2992 // { "menuFile.Reload Same Game", True },
2993 { "menuEdit.Paste Game", True },
2994 { "menuFile.Load Position", True },
2995 // { "menuFile.Load Next Position", True },
2996 // { "menuFile.Load Previous Position", True },
2997 // { "menuFile.Reload Same Position", True },
2998 { "menuEdit.Paste Position", True },
2999 { "menuMode.Machine White", True },
3000 { "menuMode.Machine Black", True },
3001 { "menuMode.Two Machines", True },
3002 // { "menuMode.Machine Match", True },
3003 { "menuEngine.Retract Move", True },
3009 SetMenuEnables(icsEnables);
3012 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
3013 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3014 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
3022 SetMenuEnables(ncpEnables);
3028 SetMenuEnables(gnuEnables);
3034 SetMenuEnables(cmailEnables);
3040 SetMenuEnables(trainingOnEnables);
3041 if (appData.showButtonBar) {
3042 XtSetSensitive(buttonBarWidget, False);
3048 SetTrainingModeOff()
3050 SetMenuEnables(trainingOffEnables);
3051 if (appData.showButtonBar) {
3052 XtSetSensitive(buttonBarWidget, True);
3057 SetUserThinkingEnables()
3059 if (appData.noChessProgram) return;
3060 SetMenuEnables(userThinkingEnables);
3064 SetMachineThinkingEnables()
3066 if (appData.noChessProgram) return;
3067 SetMenuEnables(machineThinkingEnables);
3069 case MachinePlaysBlack:
3070 case MachinePlaysWhite:
3071 case TwoMachinesPlay:
3072 XtSetSensitive(XtNameToWidget(menuBarWidget,
3073 ModeToWidgetName(gameMode)), True);
3080 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
3081 #define HISTORY_SIZE 64
3082 static char *history[HISTORY_SIZE];
3083 int histIn = 0, histP = 0;
3086 SaveInHistory(char *cmd)
3088 if (history[histIn] != NULL) {
3089 free(history[histIn]);
3090 history[histIn] = NULL;
3092 if (*cmd == NULLCHAR) return;
3093 history[histIn] = StrSave(cmd);
3094 histIn = (histIn + 1) % HISTORY_SIZE;
3095 if (history[histIn] != NULL) {
3096 free(history[histIn]);
3097 history[histIn] = NULL;
3103 PrevInHistory(char *cmd)
3106 if (histP == histIn) {
3107 if (history[histIn] != NULL) free(history[histIn]);
3108 history[histIn] = StrSave(cmd);
3110 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3111 if (newhp == histIn || history[newhp] == NULL) return NULL;
3113 return history[histP];
3119 if (histP == histIn) return NULL;
3120 histP = (histP + 1) % HISTORY_SIZE;
3121 return history[histP];
3123 // end of borrowed code
3125 #define Abs(n) ((n)<0 ? -(n) : (n))
3129 InsertPxlSize(pattern, targetPxlSize)
3133 char *base_fnt_lst, strInt[12], *p, *q;
3134 int alternatives, i, len, strIntLen;
3137 * Replace the "*" (if present) in the pixel-size slot of each
3138 * alternative with the targetPxlSize.
3142 while ((p = strchr(p, ',')) != NULL) {
3146 snprintf(strInt, sizeof(strInt), "%d", targetPxlSize);
3147 strIntLen = strlen(strInt);
3148 base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1);
3152 while (alternatives--) {
3153 char *comma = strchr(p, ',');
3154 for (i=0; i<14; i++) {
3155 char *hyphen = strchr(p, '-');
3157 if (comma && hyphen > comma) break;
3158 len = hyphen + 1 - p;
3159 if (i == 7 && *p == '*' && len == 2) {
3161 memcpy(q, strInt, strIntLen);
3171 len = comma + 1 - p;
3178 return base_fnt_lst;
3182 CreateFontSet(base_fnt_lst)
3186 char **missing_list;
3190 fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
3191 &missing_list, &missing_count, &def_string);
3192 if (appData.debugMode) {
3194 XFontStruct **font_struct_list;
3195 char **font_name_list;
3196 fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
3198 fprintf(debugFP, " got list %s, locale %s\n",
3199 XBaseFontNameListOfFontSet(fntSet),
3200 XLocaleOfFontSet(fntSet));
3201 count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
3202 for (i = 0; i < count; i++) {
3203 fprintf(debugFP, " got charset %s\n", font_name_list[i]);
3206 for (i = 0; i < missing_count; i++) {
3207 fprintf(debugFP, " missing charset %s\n", missing_list[i]);
3210 if (fntSet == NULL) {
3211 fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
3216 #else // not ENABLE_NLS
3218 * Find a font that matches "pattern" that is as close as
3219 * possible to the targetPxlSize. Prefer fonts that are k
3220 * pixels smaller to fonts that are k pixels larger. The
3221 * pattern must be in the X Consortium standard format,
3222 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3223 * The return value should be freed with XtFree when no
3227 FindFont(pattern, targetPxlSize)
3231 char **fonts, *p, *best, *scalable, *scalableTail;
3232 int i, j, nfonts, minerr, err, pxlSize;
3234 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3236 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3237 programName, pattern);
3244 for (i=0; i<nfonts; i++) {
3247 if (*p != '-') continue;
3249 if (*p == NULLCHAR) break;
3250 if (*p++ == '-') j++;
3252 if (j < 7) continue;
3255 scalable = fonts[i];
3258 err = pxlSize - targetPxlSize;
3259 if (Abs(err) < Abs(minerr) ||
3260 (minerr > 0 && err < 0 && -err == minerr)) {
3266 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3267 /* If the error is too big and there is a scalable font,
3268 use the scalable font. */
3269 int headlen = scalableTail - scalable;
3270 p = (char *) XtMalloc(strlen(scalable) + 10);
3271 while (isdigit(*scalableTail)) scalableTail++;
3272 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3274 p = (char *) XtMalloc(strlen(best) + 2);
3275 safeStrCpy(p, best, strlen(best)+1 );
3277 if (appData.debugMode) {
3278 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3279 pattern, targetPxlSize, p);
3281 XFreeFontNames(fonts);
3287 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3288 // must be called before all non-first callse to CreateGCs()
3289 XtReleaseGC(shellWidget, highlineGC);
3290 XtReleaseGC(shellWidget, lightSquareGC);
3291 XtReleaseGC(shellWidget, darkSquareGC);
3292 XtReleaseGC(shellWidget, lineGC);
3293 if (appData.monoMode) {
3294 if (DefaultDepth(xDisplay, xScreen) == 1) {
3295 XtReleaseGC(shellWidget, wbPieceGC);
3297 XtReleaseGC(shellWidget, bwPieceGC);
3300 XtReleaseGC(shellWidget, prelineGC);
3301 XtReleaseGC(shellWidget, jailSquareGC);
3302 XtReleaseGC(shellWidget, wdPieceGC);
3303 XtReleaseGC(shellWidget, wlPieceGC);
3304 XtReleaseGC(shellWidget, wjPieceGC);
3305 XtReleaseGC(shellWidget, bdPieceGC);
3306 XtReleaseGC(shellWidget, blPieceGC);
3307 XtReleaseGC(shellWidget, bjPieceGC);
3311 void CreateGCs(int redo)
3313 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3314 | GCBackground | GCFunction | GCPlaneMask;
3315 XGCValues gc_values;
3318 gc_values.plane_mask = AllPlanes;
3319 gc_values.line_width = lineGap;
3320 gc_values.line_style = LineSolid;
3321 gc_values.function = GXcopy;
3324 DeleteGCs(); // called a second time; clean up old GCs first
3325 } else { // [HGM] grid and font GCs created on first call only
3326 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3327 gc_values.background = XWhitePixel(xDisplay, xScreen);
3328 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3329 XSetFont(xDisplay, coordGC, coordFontID);
3331 // [HGM] make font for holdings counts (white on black)
3332 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3333 gc_values.background = XBlackPixel(xDisplay, xScreen);
3334 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3335 XSetFont(xDisplay, countGC, countFontID);
3337 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3338 gc_values.background = XBlackPixel(xDisplay, xScreen);
3339 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3341 if (appData.monoMode) {
3342 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3343 gc_values.background = XWhitePixel(xDisplay, xScreen);
3344 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3346 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3347 gc_values.background = XBlackPixel(xDisplay, xScreen);
3348 lightSquareGC = wbPieceGC
3349 = XtGetGC(shellWidget, value_mask, &gc_values);
3351 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3352 gc_values.background = XWhitePixel(xDisplay, xScreen);
3353 darkSquareGC = bwPieceGC
3354 = XtGetGC(shellWidget, value_mask, &gc_values);
3356 if (DefaultDepth(xDisplay, xScreen) == 1) {
3357 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3358 gc_values.function = GXcopyInverted;
3359 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3360 gc_values.function = GXcopy;
3361 if (XBlackPixel(xDisplay, xScreen) == 1) {
3362 bwPieceGC = darkSquareGC;
3363 wbPieceGC = copyInvertedGC;
3365 bwPieceGC = copyInvertedGC;
3366 wbPieceGC = lightSquareGC;
3370 gc_values.foreground = highlightSquareColor;
3371 gc_values.background = highlightSquareColor;
3372 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3374 gc_values.foreground = premoveHighlightColor;
3375 gc_values.background = premoveHighlightColor;
3376 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3378 gc_values.foreground = lightSquareColor;
3379 gc_values.background = darkSquareColor;
3380 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3382 gc_values.foreground = darkSquareColor;
3383 gc_values.background = lightSquareColor;
3384 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3386 gc_values.foreground = jailSquareColor;
3387 gc_values.background = jailSquareColor;
3388 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3390 gc_values.foreground = whitePieceColor;
3391 gc_values.background = darkSquareColor;
3392 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3394 gc_values.foreground = whitePieceColor;
3395 gc_values.background = lightSquareColor;
3396 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3398 gc_values.foreground = whitePieceColor;
3399 gc_values.background = jailSquareColor;
3400 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3402 gc_values.foreground = blackPieceColor;
3403 gc_values.background = darkSquareColor;
3404 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3406 gc_values.foreground = blackPieceColor;
3407 gc_values.background = lightSquareColor;
3408 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3410 gc_values.foreground = blackPieceColor;
3411 gc_values.background = jailSquareColor;
3412 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3416 void loadXIM(xim, xmask, filename, dest, mask)
3429 fp = fopen(filename, "rb");
3431 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3438 for (y=0; y<h; ++y) {
3439 for (x=0; x<h; ++x) {
3444 XPutPixel(xim, x, y, blackPieceColor);
3446 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3449 XPutPixel(xim, x, y, darkSquareColor);
3451 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3454 XPutPixel(xim, x, y, whitePieceColor);
3456 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3459 XPutPixel(xim, x, y, lightSquareColor);
3461 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3469 /* create Pixmap of piece */
3470 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3472 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3475 /* create Pixmap of clipmask
3476 Note: We assume the white/black pieces have the same
3477 outline, so we make only 6 masks. This is okay
3478 since the XPM clipmask routines do the same. */
3480 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3482 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3485 /* now create the 1-bit version */
3486 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3489 values.foreground = 1;
3490 values.background = 0;
3492 /* Don't use XtGetGC, not read only */
3493 maskGC = XCreateGC(xDisplay, *mask,
3494 GCForeground | GCBackground, &values);
3495 XCopyPlane(xDisplay, temp, *mask, maskGC,
3496 0, 0, squareSize, squareSize, 0, 0, 1);
3497 XFreePixmap(xDisplay, temp);
3502 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3504 void CreateXIMPieces()
3509 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3514 /* The XSynchronize calls were copied from CreatePieces.
3515 Not sure if needed, but can't hurt */
3516 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3519 /* temp needed by loadXIM() */
3520 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3521 0, 0, ss, ss, AllPlanes, XYPixmap);
3523 if (strlen(appData.pixmapDirectory) == 0) {
3527 if (appData.monoMode) {
3528 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3532 fprintf(stderr, _("\nLoading XIMs...\n"));
3534 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3535 fprintf(stderr, "%d", piece+1);
3536 for (kind=0; kind<4; kind++) {
3537 fprintf(stderr, ".");
3538 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3539 ExpandPathName(appData.pixmapDirectory),
3540 piece <= (int) WhiteKing ? "" : "w",
3541 pieceBitmapNames[piece],
3543 ximPieceBitmap[kind][piece] =
3544 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3545 0, 0, ss, ss, AllPlanes, XYPixmap);
3546 if (appData.debugMode)
3547 fprintf(stderr, _("(File:%s:) "), buf);
3548 loadXIM(ximPieceBitmap[kind][piece],
3550 &(xpmPieceBitmap2[kind][piece]),
3551 &(ximMaskPm2[piece]));
3552 if(piece <= (int)WhiteKing)
3553 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3555 fprintf(stderr," ");
3557 /* Load light and dark squares */
3558 /* If the LSQ and DSQ pieces don't exist, we will
3559 draw them with solid squares. */
3560 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3561 if (access(buf, 0) != 0) {
3565 fprintf(stderr, _("light square "));
3567 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3568 0, 0, ss, ss, AllPlanes, XYPixmap);
3569 if (appData.debugMode)
3570 fprintf(stderr, _("(File:%s:) "), buf);
3572 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3573 fprintf(stderr, _("dark square "));
3574 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3575 ExpandPathName(appData.pixmapDirectory), ss);
3576 if (appData.debugMode)
3577 fprintf(stderr, _("(File:%s:) "), buf);
3579 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3580 0, 0, ss, ss, AllPlanes, XYPixmap);
3581 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3582 xpmJailSquare = xpmLightSquare;
3584 fprintf(stderr, _("Done.\n"));
3586 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3589 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3592 void CreateXPMBoard(char *s, int kind)
3596 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3597 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3598 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3602 void FreeXPMPieces()
3603 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3604 // thisroutine has to be called t free the old piece pixmaps
3606 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3607 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3609 XFreePixmap(xDisplay, xpmLightSquare);
3610 XFreePixmap(xDisplay, xpmDarkSquare);
3614 void CreateXPMPieces()
3618 u_int ss = squareSize;
3620 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3621 XpmColorSymbol symbols[4];
3622 static int redo = False;
3624 if(redo) FreeXPMPieces(); else redo = 1;
3626 /* The XSynchronize calls were copied from CreatePieces.
3627 Not sure if needed, but can't hurt */
3628 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3630 /* Setup translations so piece colors match square colors */
3631 symbols[0].name = "light_piece";
3632 symbols[0].value = appData.whitePieceColor;
3633 symbols[1].name = "dark_piece";
3634 symbols[1].value = appData.blackPieceColor;
3635 symbols[2].name = "light_square";
3636 symbols[2].value = appData.lightSquareColor;
3637 symbols[3].name = "dark_square";
3638 symbols[3].value = appData.darkSquareColor;
3640 attr.valuemask = XpmColorSymbols;
3641 attr.colorsymbols = symbols;
3642 attr.numsymbols = 4;
3644 if (appData.monoMode) {
3645 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3649 if (strlen(appData.pixmapDirectory) == 0) {
3650 XpmPieces* pieces = builtInXpms;
3653 while (pieces->size != squareSize && pieces->size) pieces++;
3654 if (!pieces->size) {
3655 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3658 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3659 for (kind=0; kind<4; kind++) {
3661 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3662 pieces->xpm[piece][kind],
3663 &(xpmPieceBitmap2[kind][piece]),
3664 NULL, &attr)) != 0) {
3665 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3669 if(piece <= (int) WhiteKing)
3670 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3674 xpmJailSquare = xpmLightSquare;
3678 fprintf(stderr, _("\nLoading XPMs...\n"));
3681 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3682 fprintf(stderr, "%d ", piece+1);
3683 for (kind=0; kind<4; kind++) {
3684 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3685 ExpandPathName(appData.pixmapDirectory),
3686 piece > (int) WhiteKing ? "w" : "",
3687 pieceBitmapNames[piece],
3689 if (appData.debugMode) {
3690 fprintf(stderr, _("(File:%s:) "), buf);
3692 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3693 &(xpmPieceBitmap2[kind][piece]),
3694 NULL, &attr)) != 0) {
3695 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3696 // [HGM] missing: read of unorthodox piece failed; substitute King.
3697 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3698 ExpandPathName(appData.pixmapDirectory),
3700 if (appData.debugMode) {
3701 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3703 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3704 &(xpmPieceBitmap2[kind][piece]),
3708 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3713 if(piece <= (int) WhiteKing)
3714 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3717 /* Load light and dark squares */
3718 /* If the LSQ and DSQ pieces don't exist, we will
3719 draw them with solid squares. */
3720 fprintf(stderr, _("light square "));
3721 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3722 if (access(buf, 0) != 0) {
3726 if (appData.debugMode)
3727 fprintf(stderr, _("(File:%s:) "), buf);
3729 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3730 &xpmLightSquare, NULL, &attr)) != 0) {
3731 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3734 fprintf(stderr, _("dark square "));
3735 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3736 ExpandPathName(appData.pixmapDirectory), ss);
3737 if (appData.debugMode) {
3738 fprintf(stderr, _("(File:%s:) "), buf);
3740 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3741 &xpmDarkSquare, NULL, &attr)) != 0) {
3742 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3746 xpmJailSquare = xpmLightSquare;
3747 fprintf(stderr, _("Done.\n"));
3749 oldVariant = -1; // kludge to force re-makig of animation masks
3750 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3753 #endif /* HAVE_LIBXPM */
3756 /* No built-in bitmaps */
3761 u_int ss = squareSize;
3763 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3766 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3767 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3768 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3769 pieceBitmapNames[piece],
3770 ss, kind == SOLID ? 's' : 'o');
3771 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3772 if(piece <= (int)WhiteKing)
3773 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3777 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3781 /* With built-in bitmaps */
3784 BuiltInBits* bib = builtInBits;
3787 u_int ss = squareSize;
3789 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3792 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3794 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3795 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3796 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3797 pieceBitmapNames[piece],
3798 ss, kind == SOLID ? 's' : 'o');
3799 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3800 bib->bits[kind][piece], ss, ss);
3801 if(piece <= (int)WhiteKing)
3802 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3806 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3811 void ReadBitmap(pm, name, bits, wreq, hreq)
3814 unsigned char bits[];
3820 char msg[MSG_SIZ], fullname[MSG_SIZ];
3822 if (*appData.bitmapDirectory != NULLCHAR) {
3823 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3824 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3825 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3826 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3827 &w, &h, pm, &x_hot, &y_hot);
3828 fprintf(stderr, "load %s\n", name);
3829 if (errcode != BitmapSuccess) {
3831 case BitmapOpenFailed:
3832 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3834 case BitmapFileInvalid:
3835 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3837 case BitmapNoMemory:
3838 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3842 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3846 fprintf(stderr, _("%s: %s...using built-in\n"),
3848 } else if (w != wreq || h != hreq) {
3850 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3851 programName, fullname, w, h, wreq, hreq);
3857 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3866 if (lineGap == 0) return;
3868 /* [HR] Split this into 2 loops for non-square boards. */
3870 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3871 gridSegments[i].x1 = 0;
3872 gridSegments[i].x2 =
3873 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3874 gridSegments[i].y1 = gridSegments[i].y2
3875 = lineGap / 2 + (i * (squareSize + lineGap));
3878 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3879 gridSegments[j + i].y1 = 0;
3880 gridSegments[j + i].y2 =
3881 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3882 gridSegments[j + i].x1 = gridSegments[j + i].x2
3883 = lineGap / 2 + (j * (squareSize + lineGap));
3887 static void MenuBarSelect(w, addr, index)
3892 XtActionProc proc = (XtActionProc) addr;
3894 (proc)(NULL, NULL, NULL, NULL);
3897 void CreateMenuBarPopup(parent, name, mb)
3907 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3910 XtSetArg(args[j], XtNleftMargin, 20); j++;
3911 XtSetArg(args[j], XtNrightMargin, 20); j++;
3913 while (mi->string != NULL) {
3914 if (strcmp(mi->string, "----") == 0) {
3915 entry = XtCreateManagedWidget(_(mi->string), smeLineObjectClass,
3918 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3919 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3921 XtAddCallback(entry, XtNcallback,
3922 (XtCallbackProc) MenuBarSelect,
3923 (caddr_t) mi->proc);
3929 Widget CreateMenuBar(mb)
3933 Widget anchor, menuBar;
3935 char menuName[MSG_SIZ];
3938 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3939 XtSetArg(args[j], XtNvSpace, 0); j++;
3940 XtSetArg(args[j], XtNborderWidth, 0); j++;
3941 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3942 formWidget, args, j);
3944 while (mb->name != NULL) {
3945 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3946 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3948 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3951 shortName[0] = mb->name[0];
3952 shortName[1] = NULLCHAR;
3953 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3956 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3959 XtSetArg(args[j], XtNborderWidth, 0); j++;
3960 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3962 CreateMenuBarPopup(menuBar, menuName, mb);
3968 Widget CreateButtonBar(mi)
3972 Widget button, buttonBar;
3976 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3978 XtSetArg(args[j], XtNhSpace, 0); j++;
3980 XtSetArg(args[j], XtNborderWidth, 0); j++;
3981 XtSetArg(args[j], XtNvSpace, 0); j++;
3982 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3983 formWidget, args, j);
3985 while (mi->string != NULL) {
3988 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3989 XtSetArg(args[j], XtNborderWidth, 0); j++;
3991 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3992 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3993 buttonBar, args, j);
3994 XtAddCallback(button, XtNcallback,
3995 (XtCallbackProc) MenuBarSelect,
3996 (caddr_t) mi->proc);
4003 CreatePieceMenu(name, color)
4010 ChessSquare selection;
4012 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4013 boardWidget, args, 0);
4015 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4016 String item = pieceMenuStrings[color][i];
4018 if (strcmp(item, "----") == 0) {
4019 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4022 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4023 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4025 selection = pieceMenuTranslation[color][i];
4026 XtAddCallback(entry, XtNcallback,
4027 (XtCallbackProc) PieceMenuSelect,
4028 (caddr_t) selection);
4029 if (selection == WhitePawn || selection == BlackPawn) {
4030 XtSetArg(args[0], XtNpopupOnEntry, entry);
4031 XtSetValues(menu, args, 1);
4044 ChessSquare selection;
4046 whitePieceMenu = CreatePieceMenu("menuW", 0);
4047 blackPieceMenu = CreatePieceMenu("menuB", 1);
4049 XtRegisterGrabAction(PieceMenuPopup, True,
4050 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4051 GrabModeAsync, GrabModeAsync);
4053 XtSetArg(args[0], XtNlabel, _("Drop"));
4054 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4055 boardWidget, args, 1);
4056 for (i = 0; i < DROP_MENU_SIZE; i++) {
4057 String item = dropMenuStrings[i];
4059 if (strcmp(item, "----") == 0) {
4060 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4063 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4064 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4066 selection = dropMenuTranslation[i];
4067 XtAddCallback(entry, XtNcallback,
4068 (XtCallbackProc) DropMenuSelect,
4069 (caddr_t) selection);
4074 void SetupDropMenu()
4082 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4083 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4084 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4085 dmEnables[i].piece);
4086 XtSetSensitive(entry, p != NULL || !appData.testLegality
4087 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4088 && !appData.icsActive));
4090 while (p && *p++ == dmEnables[i].piece) count++;
4091 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4093 XtSetArg(args[j], XtNlabel, label); j++;
4094 XtSetValues(entry, args, j);
4098 void PieceMenuPopup(w, event, params, num_params)
4102 Cardinal *num_params;
4104 String whichMenu; int menuNr = -2;
4105 shiftKey = strcmp(params[0], "menuW"); // used to indicate black
4106 if (event->type == ButtonRelease)
4107 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
4108 else if (event->type == ButtonPress)
4109 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
4111 case 0: whichMenu = params[0]; break;
4112 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
4114 case -1: if (errorUp) ErrorPopDown();
4117 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4120 static void PieceMenuSelect(w, piece, junk)
4125 if (pmFromX < 0 || pmFromY < 0) return;
4126 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4129 static void DropMenuSelect(w, piece, junk)
4134 if (pmFromX < 0 || pmFromY < 0) return;
4135 DropMenuEvent(piece, pmFromX, pmFromY);
4138 void WhiteClock(w, event, prms, nprms)
4147 void BlackClock(w, event, prms, nprms)
4158 * If the user selects on a border boundary, return -1; if off the board,
4159 * return -2. Otherwise map the event coordinate to the square.
4161 int EventToSquare(x, limit)
4169 if ((x % (squareSize + lineGap)) >= squareSize)
4171 x /= (squareSize + lineGap);
4177 static void do_flash_delay(msec)
4183 static void drawHighlight(file, rank, gc)
4189 if (lineGap == 0) return;
4192 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4193 (squareSize + lineGap);
4194 y = lineGap/2 + rank * (squareSize + lineGap);
4196 x = lineGap/2 + file * (squareSize + lineGap);
4197 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4198 (squareSize + lineGap);
4201 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4202 squareSize+lineGap, squareSize+lineGap);
4205 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4206 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4209 SetHighlights(fromX, fromY, toX, toY)
4210 int fromX, fromY, toX, toY;
4212 if (hi1X != fromX || hi1Y != fromY) {
4213 if (hi1X >= 0 && hi1Y >= 0) {
4214 drawHighlight(hi1X, hi1Y, lineGC);
4216 } // [HGM] first erase both, then draw new!
4217 if (hi2X != toX || hi2Y != toY) {
4218 if (hi2X >= 0 && hi2Y >= 0) {
4219 drawHighlight(hi2X, hi2Y, lineGC);
4222 if (hi1X != fromX || hi1Y != fromY) {
4223 if (fromX >= 0 && fromY >= 0) {
4224 drawHighlight(fromX, fromY, highlineGC);
4227 if (hi2X != toX || hi2Y != toY) {
4228 if (toX >= 0 && toY >= 0) {
4229 drawHighlight(toX, toY, highlineGC);
4241 SetHighlights(-1, -1, -1, -1);
4246 SetPremoveHighlights(fromX, fromY, toX, toY)
4247 int fromX, fromY, toX, toY;
4249 if (pm1X != fromX || pm1Y != fromY) {
4250 if (pm1X >= 0 && pm1Y >= 0) {
4251 drawHighlight(pm1X, pm1Y, lineGC);
4253 if (fromX >= 0 && fromY >= 0) {
4254 drawHighlight(fromX, fromY, prelineGC);
4257 if (pm2X != toX || pm2Y != toY) {
4258 if (pm2X >= 0 && pm2Y >= 0) {
4259 drawHighlight(pm2X, pm2Y, lineGC);
4261 if (toX >= 0 && toY >= 0) {
4262 drawHighlight(toX, toY, prelineGC);
4272 ClearPremoveHighlights()
4274 SetPremoveHighlights(-1, -1, -1, -1);
4277 static int CutOutSquare(x, y, x0, y0, kind)
4278 int x, y, *x0, *y0, kind;
4280 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4281 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4283 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4284 if(textureW[kind] < W*squareSize)