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
145 #include <X11/Intrinsic.h>
146 #include <X11/StringDefs.h>
147 #include <X11/Shell.h>
148 #include <X11/cursorfont.h>
149 #include <X11/Xatom.h>
150 #include <X11/Xmu/Atoms.h>
152 #include <X11/Xaw3d/Dialog.h>
153 #include <X11/Xaw3d/Form.h>
154 #include <X11/Xaw3d/List.h>
155 #include <X11/Xaw3d/Label.h>
156 #include <X11/Xaw3d/SimpleMenu.h>
157 #include <X11/Xaw3d/SmeBSB.h>
158 #include <X11/Xaw3d/SmeLine.h>
159 #include <X11/Xaw3d/Box.h>
160 #include <X11/Xaw3d/MenuButton.h>
161 #include <X11/Xaw3d/Text.h>
162 #include <X11/Xaw3d/AsciiText.h>
164 #include <X11/Xaw/Dialog.h>
165 #include <X11/Xaw/Form.h>
166 #include <X11/Xaw/List.h>
167 #include <X11/Xaw/Label.h>
168 #include <X11/Xaw/SimpleMenu.h>
169 #include <X11/Xaw/SmeBSB.h>
170 #include <X11/Xaw/SmeLine.h>
171 #include <X11/Xaw/Box.h>
172 #include <X11/Xaw/MenuButton.h>
173 #include <X11/Xaw/Text.h>
174 #include <X11/Xaw/AsciiText.h>
177 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
182 #include "pixmaps/pixmaps.h"
183 #define IMAGE_EXT "xpm"
185 #define IMAGE_EXT "xim"
186 #include "bitmaps/bitmaps.h"
189 #include "bitmaps/icon_white.bm"
190 #include "bitmaps/icon_black.bm"
191 #include "bitmaps/checkmark.bm"
193 #include "frontend.h"
195 #include "backendz.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
204 // must be moved to xengineoutput.h
206 void EngineOutputProc P((Widget w, XEvent *event,
207 String *prms, Cardinal *nprms));
208 void EvalGraphProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
216 #define usleep(t) _sleep2(((t)+500)/1000)
220 # define _(s) gettext (s)
221 # define N_(s) gettext_noop (s)
239 int main P((int argc, char **argv));
240 FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
241 char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
242 RETSIGTYPE CmailSigHandler P((int sig));
243 RETSIGTYPE IntSigHandler P((int sig));
244 RETSIGTYPE TermSizeSigHandler P((int sig));
245 void CreateGCs P((int redo));
246 void CreateAnyPieces P((void));
247 void CreateXIMPieces P((void));
248 void CreateXPMPieces P((void));
249 void CreateXPMBoard P((char *s, int n));
250 void CreatePieces P((void));
251 void CreatePieceMenus P((void));
252 Widget CreateMenuBar P((Menu *mb));
253 Widget CreateButtonBar P ((MenuItem *mi));
254 char *FindFont P((char *pattern, int targetPxlSize));
255 void PieceMenuPopup P((Widget w, XEvent *event,
256 String *params, Cardinal *num_params));
257 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
260 u_int wreq, u_int hreq));
261 void CreateGrid P((void));
262 int EventToSquare P((int x, int limit));
263 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
264 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
265 void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
266 void HandleUserMove P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void AnimateUserMove P((Widget w, XEvent * event,
269 String * params, Cardinal * nParams));
270 void HandlePV P((Widget w, XEvent * event,
271 String * params, Cardinal * nParams));
272 void SelectPV P((Widget w, XEvent * event,
273 String * params, Cardinal * nParams));
274 void StopPV P((Widget w, XEvent * event,
275 String * params, Cardinal * nParams));
276 void WhiteClock P((Widget w, XEvent *event,
277 String *prms, Cardinal *nprms));
278 void BlackClock P((Widget w, XEvent *event,
279 String *prms, Cardinal *nprms));
280 void DrawPositionProc P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
284 void CommentClick P((Widget w, XEvent * event,
285 String * params, Cardinal * nParams));
286 void CommentPopUp P((char *title, char *label));
287 void CommentPopDown P((void));
288 void ICSInputBoxPopUp P((void));
289 void ICSInputBoxPopDown P((void));
290 void FileNamePopUp P((char *label, char *def, char *filter,
291 FileProc proc, char *openMode));
292 void FileNamePopDown P((void));
293 void FileNameCallback P((Widget w, XtPointer client_data,
294 XtPointer call_data));
295 void FileNameAction P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void AskQuestionReplyAction P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void AskQuestionProc P((Widget w, XEvent *event,
300 String *prms, Cardinal *nprms));
301 void AskQuestionPopDown P((void));
302 void PromotionPopDown P((void));
303 void PromotionCallback P((Widget w, XtPointer client_data,
304 XtPointer call_data));
305 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
306 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
308 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
310 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
312 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
314 void LoadPositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
318 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
320 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
322 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
324 void PastePositionProc P((Widget w, XEvent *event, String *prms,
326 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void CopyGameListProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void SavePositionProc P((Widget w, XEvent *event,
331 String *prms, Cardinal *nprms));
332 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
335 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
339 void MachineWhiteProc P((Widget w, XEvent *event,
340 String *prms, Cardinal *nprms));
341 void AnalyzeModeProc P((Widget w, XEvent *event,
342 String *prms, Cardinal *nprms));
343 void AnalyzeFileProc P((Widget w, XEvent *event,
344 String *prms, Cardinal *nprms));
345 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
347 void MatchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void MatchOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void IcsClientProc P((Widget w, XEvent *event, String *prms,
351 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EditPositionProc P((Widget w, XEvent *event,
353 String *prms, Cardinal *nprms));
354 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void EditCommentProc P((Widget w, XEvent *event,
356 String *prms, Cardinal *nprms));
357 void IcsInputBoxProc P((Widget w, XEvent *event,
358 String *prms, Cardinal *nprms));
359 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
372 void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
373 void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
374 void StopObservingProc P((Widget w, XEvent *event, String *prms,
376 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
378 void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
387 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
389 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
392 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
394 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
396 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
401 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
404 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
406 void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
408 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
409 //void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
410 void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
411 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
413 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
415 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
417 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
419 //void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
422 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
424 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
426 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
428 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
429 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
430 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
431 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
432 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
433 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
434 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
435 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
436 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void DisplayMove P((int moveNumber));
440 void DisplayTitle P((char *title));
441 void ICSInitScript P((void));
442 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
443 void ErrorPopUp P((char *title, char *text, int modal));
444 void ErrorPopDown P((void));
445 static char *ExpandPathName P((char *path));
446 static void CreateAnimVars P((void));
447 static void DragPieceMove P((int x, int y));
448 static void DrawDragPiece P((void));
449 char *ModeToWidgetName P((GameMode mode));
450 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
451 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
452 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
453 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
454 void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
455 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
456 void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
457 void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
458 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
459 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
460 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
461 void IcsOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
462 void SoundOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
463 void BoardOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
464 void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
465 void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
466 void GameListOptionsPopDown P(());
467 void ShufflePopDown P(());
468 void TimeControlPopDown P(());
469 void GenericPopDown P(());
470 void update_ics_width P(());
471 int get_term_width P(());
472 int CopyMemoProc P(());
473 void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
474 Boolean IsDrawArrowEnabled P(());
477 * XBoard depends on Xt R4 or higher
479 int xtVersion = XtSpecificationRelease;
484 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
485 jailSquareColor, highlightSquareColor, premoveHighlightColor;
486 Pixel lowTimeWarningColor;
487 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
488 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
489 wjPieceGC, bjPieceGC, prelineGC, countGC;
490 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
491 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
492 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
493 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
494 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
495 ICSInputShell, fileNameShell, askQuestionShell;
496 Widget historyShell, evalGraphShell, gameListShell;
497 int hOffset; // [HGM] dual
498 XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
499 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
500 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
501 Font clockFontID, coordFontID, countFontID;
502 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
503 XtAppContext appContext;
505 char *oldICSInteractionTitle;
509 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
511 Position commentX = -1, commentY = -1;
512 Dimension commentW, commentH;
513 typedef unsigned int BoardSize;
515 Boolean chessProgram;
517 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
518 int squareSize, smallLayout = 0, tinyLayout = 0,
519 marginW, marginH, // [HGM] for run-time resizing
520 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
521 ICSInputBoxUp = False, askQuestionUp = False,
522 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
523 errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap;
524 Pixel timerForegroundPixel, timerBackgroundPixel;
525 Pixel buttonForegroundPixel, buttonBackgroundPixel;
526 char *chessDir, *programName, *programVersion,
527 *gameCopyFilename, *gamePasteFilename;
528 Boolean alwaysOnTop = False;
529 Boolean saveSettingsOnExit;
530 char *settingsFileName;
531 char *icsTextMenuString;
533 char *firstChessProgramNames;
534 char *secondChessProgramNames;
536 WindowPlacement wpMain;
537 WindowPlacement wpConsole;
538 WindowPlacement wpComment;
539 WindowPlacement wpMoveHistory;
540 WindowPlacement wpEvalGraph;
541 WindowPlacement wpEngineOutput;
542 WindowPlacement wpGameList;
543 WindowPlacement wpTags;
545 extern Widget shells[];
546 extern Boolean shellUp[];
550 Pixmap pieceBitmap[2][(int)BlackPawn];
551 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
552 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
553 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
554 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
555 Pixmap xpmBoardBitmap[2];
556 int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
557 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
558 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
559 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
560 XImage *ximLightSquare, *ximDarkSquare;
563 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
564 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
566 #define White(piece) ((int)(piece) < (int)BlackPawn)
568 /* Variables for doing smooth animation. This whole thing
569 would be much easier if the board was double-buffered,
570 but that would require a fairly major rewrite. */
575 GC blitGC, pieceGC, outlineGC;
576 XPoint startSquare, prevFrame, mouseDelta;
580 int startBoardX, startBoardY;
583 /* There can be two pieces being animated at once: a player
584 can begin dragging a piece before the remote opponent has moved. */
586 static AnimState game, player;
588 /* Bitmaps for use as masks when drawing XPM pieces.
589 Need one for each black and white piece. */
590 static Pixmap xpmMask[BlackKing + 1];
592 /* This magic number is the number of intermediate frames used
593 in each half of the animation. For short moves it's reduced
594 by 1. The total number of frames will be factor * 2 + 1. */
597 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
599 MenuItem fileMenu[] = {
600 {N_("New Game Ctrl+N"), "New Game", ResetProc},
601 {N_("New Shuffle Game ..."), "New Shuffle Game", ShuffleMenuProc},
602 {N_("New Variant ... Alt+Shift+V"), "New Variant", NewVariantProc}, // [HGM] variant: not functional yet
603 {"----", NULL, NothingProc},
604 {N_("Load Game Ctrl+O"), "Load Game", LoadGameProc},
605 {N_("Load Position Ctrl+Shift+O"), "Load Position", LoadPositionProc},
606 // {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
607 // {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
608 // {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
609 {N_("Next Position Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
610 {N_("Prev Position Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
611 {"----", NULL, NothingProc},
612 // {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
613 {N_("Save Game Ctrl+S"), "Save Game", SaveGameProc},
614 {N_("Save Position Ctrl+Shift+S"), "Save Position", SavePositionProc},
615 {"----", NULL, NothingProc},
616 {N_("Mail Move"), "Mail Move", MailMoveProc},
617 {N_("Reload CMail Message"), "Reload CMail Message", ReloadCmailMsgProc},
618 {"----", NULL, NothingProc},
619 {N_("Quit Ctr+Q"), "Exit", QuitProc},
623 MenuItem editMenu[] = {
624 {N_("Copy Game Ctrl+C"), "Copy Game", CopyGameProc},
625 {N_("Copy Position Ctrl+Shift+C"), "Copy Position", CopyPositionProc},
626 {N_("Copy Game List"), "Copy Game List", CopyGameListProc},
627 {"----", NULL, NothingProc},
628 {N_("Paste Game Ctrl+V"), "Paste Game", PasteGameProc},
629 {N_("Paste Position Ctrl+Shift+V"), "Paste Position", PastePositionProc},
630 {"----", NULL, NothingProc},
631 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
632 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
633 {N_("Edit Tags"), "Edit Tags", EditTagsProc},
634 {N_("Edit Comment"), "Edit Comment", EditCommentProc},
635 {"----", NULL, NothingProc},
636 {N_("Revert Home"), "Revert", RevertProc},
637 {N_("Annotate"), "Annotate", AnnotateProc},
638 {N_("Truncate Game End"), "Truncate Game", TruncateGameProc},
639 {"----", NULL, NothingProc},
640 {N_("Backward Alt+Left"), "Backward", BackwardProc},
641 {N_("Forward Alt+Right"), "Forward", ForwardProc},
642 {N_("Back to Start Alt+Home"), "Back to Start", ToStartProc},
643 {N_("Forward to End Alt+End"), "Forward to End", ToEndProc},
647 MenuItem viewMenu[] = {
648 {N_("Flip View F2"), "Flip View", FlipViewProc},
649 {"----", NULL, NothingProc},
650 {N_("Engine Output Alt+Shift+O"), "Show Engine Output", EngineOutputProc},
651 {N_("Move History Alt+Shift+H"), "Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
652 {N_("Evaluation Graph Alt+Shift+E"), "Show Evaluation Graph", EvalGraphProc},
653 {N_("Game List Alt+Shift+G"), "Show Game List", ShowGameListProc},
654 {N_("ICS text menu"), "ICStex", IcsTextProc},
655 {"----", NULL, NothingProc},
656 {N_("Tags"), "Show Tags", EditTagsProc},
657 {N_("Comments"), "Show Comments", EditCommentProc},
658 {N_("ICS Input Box"), "ICS Input Box", IcsInputBoxProc},
659 {"----", NULL, NothingProc},
660 {N_("Board..."), "Board Options", BoardOptionsProc},
661 {N_("Game List Tags..."), "Game List", GameListOptionsPopUp},
665 MenuItem modeMenu[] = {
666 {N_("Machine White Ctrl+W"), "Machine White", MachineWhiteProc},
667 {N_("Machine Black Ctrl+B"), "Machine Black", MachineBlackProc},
668 {N_("Two Machines Ctrl+T"), "Two Machines", TwoMachinesProc},
669 {N_("Analysis Mode Ctrl+A"), "Analysis Mode", AnalyzeModeProc},
670 {N_("Analyze File Ctrl+F"), "Analyze File", AnalyzeFileProc },
671 {N_("Edit Game Ctrl+E"), "Edit Game", EditGameProc},
672 {N_("Edit Position Ctrl+Shift+E"), "Edit Position", EditPositionProc},
673 {N_("Training"), "Training", TrainingProc},
674 {N_("ICS Client"), "ICS Client", IcsClientProc},
675 {"----", NULL, NothingProc},
676 {N_("Machine Match"), "Machine Match", MatchProc},
677 {N_("Pause Pause"), "Pause", PauseProc},
681 MenuItem actionMenu[] = {
682 {N_("Accept F3"), "Accept", AcceptProc},
683 {N_("Decline F4"), "Decline", DeclineProc},
684 {N_("Rematch F12"), "Rematch", RematchProc},
685 {"----", NULL, NothingProc},
686 {N_("Call Flag F5"), "Call Flag", CallFlagProc},
687 {N_("Draw F6"), "Draw", DrawProc},
688 {N_("Adjourn F7"), "Adjourn", AdjournProc},
689 {N_("Abort F8"),"Abort", AbortProc},
690 {N_("Resign F9"), "Resign", ResignProc},
691 {"----", NULL, NothingProc},
692 {N_("Stop Observing F10"), "Stop Observing", StopObservingProc},
693 {N_("Stop Examining F11"), "Stop Examining", StopExaminingProc},
694 {N_("Upload to Examine"), "Upload to Examine", UploadProc},
695 {"----", NULL, NothingProc},
696 {N_("Adjudicate to White"), "Adjudicate to White", AdjuWhiteProc},
697 {N_("Adjudicate to Black"), "Adjudicate to Black", AdjuBlackProc},
698 {N_("Adjudicate Draw"), "Adjudicate Draw", AdjuDrawProc},
702 MenuItem engineMenu[] = {
703 {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
704 {"----", NULL, NothingProc},
705 {N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
706 {N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
707 {"----", NULL, NothingProc},
708 {N_("Hint"), "Hint", HintProc},
709 {N_("Book"), "Book", BookProc},
710 {"----", NULL, NothingProc},
711 {N_("Move Now Ctrl+M"), "Move Now", MoveNowProc},
712 {N_("Retract Move Ctrl+X"), "Retract Move", RetractMoveProc},
716 MenuItem optionsMenu[] = {
717 #define OPTIONSDIALOG
719 {N_("General ..."), "General", OptionsProc},
721 {N_("Time Control ... Alt+Shift+T"), "Time Control", TimeControlProc},
722 {N_("Common Engine ... Alt+Shift+U"), "Common Engine", UciMenuProc},
723 {N_("Adjudications ... Alt+Shift+J"), "Adjudications", EngineMenuProc},
724 {N_("ICS ..."), "ICS", IcsOptionsProc},
725 {N_("Match ..."), "Match", MatchOptionsProc},
726 {N_("Load Game ..."), "Load Game", LoadOptionsProc},
727 {N_("Save Game ..."), "Save Game", SaveOptionsProc},
728 // {N_(" ..."), "", OptionsProc},
729 {N_("Game List ..."), "Game List", GameListOptionsPopUp},
730 {N_("Sounds ..."), "Sounds", SoundOptionsProc},
731 {"----", NULL, NothingProc},
732 #ifndef OPTIONSDIALOG
733 {N_("Always Queen Ctrl+Shift+Q"), "Always Queen", AlwaysQueenProc},
734 {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
735 {N_("Animate Moving Ctrl+Shift+A"), "Animate Moving", AnimateMovingProc},
736 {N_("Auto Flag Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
737 {N_("Auto Flip View"), "Auto Flip View", AutoflipProc},
738 {N_("Blindfold"), "Blindfold", BlindfoldProc},
739 {N_("Flash Moves"), "Flash Moves", FlashMovesProc},
741 {N_("Highlight Dragging"), "Highlight Dragging", HighlightDraggingProc},
743 {N_("Highlight Last Move"), "Highlight Last Move", HighlightLastMoveProc},
744 {N_("Highlight With Arrow"), "Arrow", HighlightArrowProc},
745 {N_("Move Sound"), "Move Sound", MoveSoundProc},
746 // {N_("ICS Alarm"), "ICS Alarm", IcsAlarmProc},
747 {N_("One-Click Moving"), "OneClick", OneClickProc},
748 {N_("Periodic Updates"), "Periodic Updates", PeriodicUpdatesProc},
749 {N_("Ponder Next Move Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
750 {N_("Popup Exit Message"), "Popup Exit Message", PopupExitMessageProc},
751 {N_("Popup Move Errors"), "Popup Move Errors", PopupMoveErrorsProc},
752 // {N_("Premove"), "Premove", PremoveProc},
753 {N_("Show Coords"), "Show Coords", ShowCoordsProc},
754 {N_("Hide Thinking Ctrl+Shift+H"), "Hide Thinking", HideThinkingProc},
755 {N_("Test Legality Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
756 {"----", NULL, NothingProc},
758 {N_("Save Settings Now"), "Save Settings Now", SaveSettingsProc},
759 {N_("Save Settings on Exit"), "Save Settings on Exit", SaveOnExitProc},
763 MenuItem helpMenu[] = {
764 {N_("Info XBoard"), "Info XBoard", InfoProc},
765 {N_("Man XBoard F1"), "Man XBoard", ManProc},
766 {"----", NULL, NothingProc},
767 {N_("About XBoard"), "About XBoard", AboutProc},
772 {N_("File"), "File", fileMenu},
773 {N_("Edit"), "Edit", editMenu},
774 {N_("View"), "View", viewMenu},
775 {N_("Mode"), "Mode", modeMenu},
776 {N_("Action"), "Action", actionMenu},
777 {N_("Engine"), "Engine", engineMenu},
778 {N_("Options"), "Options", optionsMenu},
779 {N_("Help"), "Help", helpMenu},
783 #define PAUSE_BUTTON "P"
784 MenuItem buttonBar[] = {
785 {"<<", "<<", ToStartProc},
786 {"<", "<", BackwardProc},
787 {PAUSE_BUTTON, PAUSE_BUTTON, PauseProc},
788 {">", ">", ForwardProc},
789 {">>", ">>", ToEndProc},
793 #define PIECE_MENU_SIZE 18
794 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
795 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
796 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
797 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
798 N_("Empty square"), N_("Clear board") },
799 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
800 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
801 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
802 N_("Empty square"), N_("Clear board") }
804 /* must be in same order as PieceMenuStrings! */
805 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
806 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
807 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
808 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
809 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
810 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
811 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
812 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
813 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
816 #define DROP_MENU_SIZE 6
817 String dropMenuStrings[DROP_MENU_SIZE] = {
818 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
820 /* must be in same order as PieceMenuStrings! */
821 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
822 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
823 WhiteRook, WhiteQueen
831 DropMenuEnables dmEnables[] = {
849 { XtNborderWidth, 0 },
850 { XtNdefaultDistance, 0 },
854 { XtNborderWidth, 0 },
855 { XtNresizable, (XtArgVal) True },
859 { XtNborderWidth, 0 },
865 { XtNjustify, (XtArgVal) XtJustifyRight },
866 { XtNlabel, (XtArgVal) "..." },
867 { XtNresizable, (XtArgVal) True },
868 { XtNresize, (XtArgVal) False }
871 Arg messageArgs[] = {
872 { XtNjustify, (XtArgVal) XtJustifyLeft },
873 { XtNlabel, (XtArgVal) "..." },
874 { XtNresizable, (XtArgVal) True },
875 { XtNresize, (XtArgVal) False }
879 { XtNborderWidth, 0 },
880 { XtNjustify, (XtArgVal) XtJustifyLeft }
883 XtResource clientResources[] = {
884 { "flashCount", "flashCount", XtRInt, sizeof(int),
885 XtOffset(AppDataPtr, flashCount), XtRImmediate,
886 (XtPointer) FLASH_COUNT },
889 XrmOptionDescRec shellOptions[] = {
890 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
891 { "-flash", "flashCount", XrmoptionNoArg, "3" },
892 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
895 XtActionsRec boardActions[] = {
896 { "DrawPosition", DrawPositionProc },
897 { "HandleUserMove", HandleUserMove },
898 { "AnimateUserMove", AnimateUserMove },
899 { "HandlePV", HandlePV },
900 { "SelectPV", SelectPV },
901 { "StopPV", StopPV },
902 { "FileNameAction", FileNameAction },
903 { "AskQuestionProc", AskQuestionProc },
904 { "AskQuestionReplyAction", AskQuestionReplyAction },
905 { "PieceMenuPopup", PieceMenuPopup },
906 { "WhiteClock", WhiteClock },
907 { "BlackClock", BlackClock },
908 { "Iconify", Iconify },
909 { "ResetProc", ResetProc },
910 { "NewVariantProc", NewVariantProc },
911 { "LoadGameProc", LoadGameProc },
912 { "LoadNextGameProc", LoadNextGameProc },
913 { "LoadPrevGameProc", LoadPrevGameProc },
914 { "LoadSelectedProc", LoadSelectedProc },
915 { "SetFilterProc", SetFilterProc },
916 { "ReloadGameProc", ReloadGameProc },
917 { "LoadPositionProc", LoadPositionProc },
918 { "LoadNextPositionProc", LoadNextPositionProc },
919 { "LoadPrevPositionProc", LoadPrevPositionProc },
920 { "ReloadPositionProc", ReloadPositionProc },
921 { "CopyPositionProc", CopyPositionProc },
922 { "PastePositionProc", PastePositionProc },
923 { "CopyGameProc", CopyGameProc },
924 { "CopyGameListProc", CopyGameListProc },
925 { "PasteGameProc", PasteGameProc },
926 { "SaveGameProc", SaveGameProc },
927 { "SavePositionProc", SavePositionProc },
928 { "MailMoveProc", MailMoveProc },
929 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
930 { "QuitProc", QuitProc },
931 { "MachineWhiteProc", MachineWhiteProc },
932 { "MachineBlackProc", MachineBlackProc },
933 { "AnalysisModeProc", AnalyzeModeProc },
934 { "AnalyzeFileProc", AnalyzeFileProc },
935 { "TwoMachinesProc", TwoMachinesProc },
936 { "IcsClientProc", IcsClientProc },
937 { "EditGameProc", EditGameProc },
938 { "EditPositionProc", EditPositionProc },
939 { "TrainingProc", EditPositionProc },
940 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
941 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
942 { "ShowGameListProc", ShowGameListProc },
943 { "ShowMoveListProc", HistoryShowProc},
944 { "EditTagsProc", EditCommentProc },
945 { "EditCommentProc", EditCommentProc },
946 { "IcsInputBoxProc", IcsInputBoxProc },
947 { "PauseProc", PauseProc },
948 { "AcceptProc", AcceptProc },
949 { "DeclineProc", DeclineProc },
950 { "RematchProc", RematchProc },
951 { "CallFlagProc", CallFlagProc },
952 { "DrawProc", DrawProc },
953 { "AdjournProc", AdjournProc },
954 { "AbortProc", AbortProc },
955 { "ResignProc", ResignProc },
956 { "AdjuWhiteProc", AdjuWhiteProc },
957 { "AdjuBlackProc", AdjuBlackProc },
958 { "AdjuDrawProc", AdjuDrawProc },
959 { "TypeInProc", TypeInProc },
960 { "EnterKeyProc", EnterKeyProc },
961 { "UpKeyProc", UpKeyProc },
962 { "DownKeyProc", DownKeyProc },
963 { "StopObservingProc", StopObservingProc },
964 { "StopExaminingProc", StopExaminingProc },
965 { "UploadProc", UploadProc },
966 { "BackwardProc", BackwardProc },
967 { "ForwardProc", ForwardProc },
968 { "ToStartProc", ToStartProc },
969 { "ToEndProc", ToEndProc },
970 { "RevertProc", RevertProc },
971 { "AnnotateProc", AnnotateProc },
972 { "TruncateGameProc", TruncateGameProc },
973 { "MoveNowProc", MoveNowProc },
974 { "RetractMoveProc", RetractMoveProc },
975 { "EngineMenuProc", (XtActionProc) EngineMenuProc },
976 { "UciMenuProc", (XtActionProc) UciMenuProc },
977 { "TimeControlProc", (XtActionProc) TimeControlProc },
978 { "FlipViewProc", FlipViewProc },
979 { "PonderNextMoveProc", PonderNextMoveProc },
980 #ifndef OPTIONSDIALOG
981 { "AlwaysQueenProc", AlwaysQueenProc },
982 { "AnimateDraggingProc", AnimateDraggingProc },
983 { "AnimateMovingProc", AnimateMovingProc },
984 { "AutoflagProc", AutoflagProc },
985 { "AutoflipProc", AutoflipProc },
986 { "BlindfoldProc", BlindfoldProc },
987 { "FlashMovesProc", FlashMovesProc },
989 { "HighlightDraggingProc", HighlightDraggingProc },
991 { "HighlightLastMoveProc", HighlightLastMoveProc },
992 // { "IcsAlarmProc", IcsAlarmProc },
993 { "MoveSoundProc", MoveSoundProc },
994 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
995 { "PopupExitMessageProc", PopupExitMessageProc },
996 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
997 // { "PremoveProc", PremoveProc },
998 { "ShowCoordsProc", ShowCoordsProc },
999 { "ShowThinkingProc", ShowThinkingProc },
1000 { "HideThinkingProc", HideThinkingProc },
1001 { "TestLegalityProc", TestLegalityProc },
1003 { "SaveSettingsProc", SaveSettingsProc },
1004 { "SaveOnExitProc", SaveOnExitProc },
1005 { "InfoProc", InfoProc },
1006 { "ManProc", ManProc },
1007 { "HintProc", HintProc },
1008 { "BookProc", BookProc },
1009 { "AboutGameProc", AboutGameProc },
1010 { "AboutProc", AboutProc },
1011 { "DebugProc", DebugProc },
1012 { "NothingProc", NothingProc },
1013 { "CommentClick", (XtActionProc) CommentClick },
1014 { "CommentPopDown", (XtActionProc) CommentPopDown },
1015 { "TagsPopDown", (XtActionProc) TagsPopDown },
1016 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1017 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1018 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1019 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1020 { "GameListPopDown", (XtActionProc) GameListPopDown },
1021 { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
1022 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1023 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1024 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1025 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
1026 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1027 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1028 { "GenericPopDown", (XtActionProc) GenericPopDown },
1029 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
1032 char globalTranslations[] =
1033 ":<Key>F9: ResignProc() \n \
1034 :Ctrl<Key>n: ResetProc() \n \
1035 :Meta<Key>V: NewVariantProc() \n \
1036 :Ctrl<Key>o: LoadGameProc() \n \
1037 :Meta<Key>Next: LoadNextGameProc() \n \
1038 :Meta<Key>Prior: LoadPrevGameProc() \n \
1039 :Ctrl<Key>s: SaveGameProc() \n \
1040 :Ctrl<Key>c: CopyGameProc() \n \
1041 :Ctrl<Key>v: PasteGameProc() \n \
1042 :Ctrl<Key>O: LoadPositionProc() \n \
1043 :Shift<Key>Next: LoadNextPositionProc() \n \
1044 :Shift<Key>Prior: LoadPrevPositionProc() \n \
1045 :Ctrl<Key>S: SavePositionProc() \n \
1046 :Ctrl<Key>C: CopyPositionProc() \n \
1047 :Ctrl<Key>V: PastePositionProc() \n \
1048 :Ctrl<Key>q: QuitProc() \n \
1049 :Ctrl<Key>w: MachineWhiteProc() \n \
1050 :Ctrl<Key>b: MachineBlackProc() \n \
1051 :Ctrl<Key>t: TwoMachinesProc() \n \
1052 :Ctrl<Key>a: AnalysisModeProc() \n \
1053 :Ctrl<Key>f: AnalyzeFileProc() \n \
1054 :Ctrl<Key>e: EditGameProc() \n \
1055 :Ctrl<Key>E: EditPositionProc() \n \
1056 :Meta<Key>O: EngineOutputProc() \n \
1057 :Meta<Key>E: EvalGraphProc() \n \
1058 :Meta<Key>G: ShowGameListProc() \n \
1059 :Meta<Key>H: ShowMoveListProc() \n \
1060 :<Key>Pause: PauseProc() \n \
1061 :<Key>F3: AcceptProc() \n \
1062 :<Key>F4: DeclineProc() \n \
1063 :<Key>F12: RematchProc() \n \
1064 :<Key>F5: CallFlagProc() \n \
1065 :<Key>F6: DrawProc() \n \
1066 :<Key>F7: AdjournProc() \n \
1067 :<Key>F8: AbortProc() \n \
1068 :<Key>F10: StopObservingProc() \n \
1069 :<Key>F11: StopExaminingProc() \n \
1070 :Meta Ctrl<Key>F12: DebugProc() \n \
1071 :Meta<Key>End: ToEndProc() \n \
1072 :Meta<Key>Right: ForwardProc() \n \
1073 :Meta<Key>Home: ToStartProc() \n \
1074 :Meta<Key>Left: BackwardProc() \n \
1075 :<Key>Home: RevertProc() \n \
1076 :<Key>End: TruncateGameProc() \n \
1077 :Ctrl<Key>m: MoveNowProc() \n \
1078 :Ctrl<Key>x: RetractMoveProc() \n \
1079 :Meta<Key>J: EngineMenuProc() \n \
1080 :Meta<Key>U: UciMenuProc() \n \
1081 :Meta<Key>T: TimeControlProc() \n \
1082 :Ctrl<Key>P: PonderNextMoveProc() \n "
1083 #ifndef OPTIONSDIALOG
1085 :Ctrl<Key>Q: AlwaysQueenProc() \n \
1086 :Ctrl<Key>F: AutoflagProc() \n \
1087 :Ctrl<Key>A: AnimateMovingProc() \n \
1088 :Ctrl<Key>L: TestLegalityProc() \n \
1089 :Ctrl<Key>H: HideThinkingProc() \n "
1092 :<Key>-: Iconify() \n \
1093 :<Key>F1: ManProc() \n \
1094 :<Key>F2: FlipViewProc() \n \
1095 <KeyDown>.: BackwardProc() \n \
1096 <KeyUp>.: ForwardProc() \n \
1097 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1098 \"Send to chess program:\",,1) \n \
1099 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1100 \"Send to second chess program:\",,2) \n";
1102 char boardTranslations[] =
1103 "<Btn1Down>: HandleUserMove(0) \n \
1104 Shift<Btn1Up>: HandleUserMove(1) \n \
1105 <Btn1Up>: HandleUserMove(0) \n \
1106 <Btn1Motion>: AnimateUserMove() \n \
1107 <Btn3Motion>: HandlePV() \n \
1108 <Btn3Up>: PieceMenuPopup(menuB) \n \
1109 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1110 PieceMenuPopup(menuB) \n \
1111 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1112 PieceMenuPopup(menuW) \n \
1113 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1114 PieceMenuPopup(menuW) \n \
1115 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1116 PieceMenuPopup(menuB) \n";
1118 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1119 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1121 char ICSInputTranslations[] =
1122 "<Key>Up: UpKeyProc() \n "
1123 "<Key>Down: DownKeyProc() \n "
1124 "<Key>Return: EnterKeyProc() \n";
1126 // [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
1127 // as the widget is destroyed before the up-click can call extend-end
1128 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
1130 String xboardResources[] = {
1131 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1132 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1133 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1138 /* Max possible square size */
1139 #define MAXSQSIZE 256
1141 static int xpm_avail[MAXSQSIZE];
1143 #ifdef HAVE_DIR_STRUCT
1145 /* Extract piece size from filename */
1147 xpm_getsize(name, len, ext)
1158 if ((p=strchr(name, '.')) == NULL ||
1159 StrCaseCmp(p+1, ext) != 0)
1165 while (*p && isdigit(*p))
1172 /* Setup xpm_avail */
1174 xpm_getavail(dirname, ext)
1182 for (i=0; i<MAXSQSIZE; ++i)
1185 if (appData.debugMode)
1186 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1188 dir = opendir(dirname);
1191 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1192 programName, dirname);
1196 while ((ent=readdir(dir)) != NULL) {
1197 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1198 if (i > 0 && i < MAXSQSIZE)
1208 xpm_print_avail(fp, ext)
1214 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1215 for (i=1; i<MAXSQSIZE; ++i) {
1221 /* Return XPM piecesize closest to size */
1223 xpm_closest_to(dirname, size, ext)
1229 int sm_diff = MAXSQSIZE;
1233 xpm_getavail(dirname, ext);
1235 if (appData.debugMode)
1236 xpm_print_avail(stderr, ext);
1238 for (i=1; i<MAXSQSIZE; ++i) {
1241 diff = (diff<0) ? -diff : diff;
1242 if (diff < sm_diff) {
1250 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1256 #else /* !HAVE_DIR_STRUCT */
1257 /* If we are on a system without a DIR struct, we can't
1258 read the directory, so we can't collect a list of
1259 filenames, etc., so we can't do any size-fitting. */
1261 xpm_closest_to(dirname, size, ext)
1266 fprintf(stderr, _("\
1267 Warning: No DIR structure found on this system --\n\
1268 Unable to autosize for XPM/XIM pieces.\n\
1269 Please report this error to %s.\n\
1270 Include system type & operating system in message.\n"), PACKAGE_BUGREPORT););
1273 #endif /* HAVE_DIR_STRUCT */
1275 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1276 "magenta", "cyan", "white" };
1280 TextColors textColors[(int)NColorClasses];
1282 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1284 parse_color(str, which)
1288 char *p, buf[100], *d;
1291 if (strlen(str) > 99) /* watch bounds on buf */
1296 for (i=0; i<which; ++i) {
1303 /* Could be looking at something like:
1305 .. in which case we want to stop on a comma also */
1306 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1310 return -1; /* Use default for empty field */
1313 if (which == 2 || isdigit(*p))
1316 while (*p && isalpha(*p))
1321 for (i=0; i<8; ++i) {
1322 if (!StrCaseCmp(buf, cnames[i]))
1323 return which? (i+40) : (i+30);
1325 if (!StrCaseCmp(buf, "default")) return -1;
1327 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1332 parse_cpair(cc, str)
1336 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1337 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1342 /* bg and attr are optional */
1343 textColors[(int)cc].bg = parse_color(str, 1);
1344 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1345 textColors[(int)cc].attr = 0;
1351 /* Arrange to catch delete-window events */
1352 Atom wm_delete_window;
1354 CatchDeleteWindow(Widget w, String procname)
1357 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1358 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1359 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1366 XtSetArg(args[0], XtNiconic, False);
1367 XtSetValues(shellWidget, args, 1);
1369 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1372 //---------------------------------------------------------------------------------------------------------
1373 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1376 #define CW_USEDEFAULT (1<<31)
1377 #define ICS_TEXT_MENU_SIZE 90
1378 #define DEBUG_FILE "xboard.debug"
1379 #define SetCurrentDirectory chdir
1380 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1384 // these two must some day move to frontend.h, when they are implemented
1385 Boolean GameListIsUp();
1387 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1390 // front-end part of option handling
1392 // [HGM] This platform-dependent table provides the location for storing the color info
1393 extern char *crWhite, * crBlack;
1397 &appData.whitePieceColor,
1398 &appData.blackPieceColor,
1399 &appData.lightSquareColor,
1400 &appData.darkSquareColor,
1401 &appData.highlightSquareColor,
1402 &appData.premoveHighlightColor,
1403 &appData.lowTimeWarningColor,
1414 // [HGM] font: keep a font for each square size, even non-stndard ones
1415 #define NUM_SIZES 18
1416 #define MAX_SIZE 130
1417 Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
1418 char *fontTable[NUM_FONTS][MAX_SIZE];
1421 ParseFont(char *name, int number)
1422 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1424 if(sscanf(name, "size%d:", &size)) {
1425 // [HGM] font: font is meant for specific boardSize (likely from settings file);
1426 // defer processing it until we know if it matches our board size
1427 if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
1428 fontTable[number][size] = strdup(strchr(name, ':')+1);
1429 fontValid[number][size] = True;
1434 case 0: // CLOCK_FONT
1435 appData.clockFont = strdup(name);
1437 case 1: // MESSAGE_FONT
1438 appData.font = strdup(name);
1440 case 2: // COORD_FONT
1441 appData.coordFont = strdup(name);
1446 fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
1451 { // only 2 fonts currently
1452 appData.clockFont = CLOCK_FONT_NAME;
1453 appData.coordFont = COORD_FONT_NAME;
1454 appData.font = DEFAULT_FONT_NAME;
1459 { // no-op, until we identify the code for this already in XBoard and move it here
1463 ParseColor(int n, char *name)
1464 { // in XBoard, just copy the color-name string
1465 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1469 ParseTextAttribs(ColorClass cc, char *s)
1471 (&appData.colorShout)[cc] = strdup(s);
1475 ParseBoardSize(void *addr, char *name)
1477 appData.boardSize = strdup(name);
1482 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1486 SetCommPortDefaults()
1487 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1490 // [HGM] args: these three cases taken out to stay in front-end
1492 SaveFontArg(FILE *f, ArgDescriptor *ad)
1495 int i, n = (int)(intptr_t)ad->argLoc;
1497 case 0: // CLOCK_FONT
1498 name = appData.clockFont;
1500 case 1: // MESSAGE_FONT
1501 name = appData.font;
1503 case 2: // COORD_FONT
1504 name = appData.coordFont;
1509 for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
1510 if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
1511 fontTable[n][squareSize] = strdup(name);
1512 fontValid[n][squareSize] = True;
1515 for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
1516 fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
1521 { // nothing to do, as the sounds are at all times represented by their text-string names already
1525 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1526 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1527 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
1531 SaveColor(FILE *f, ArgDescriptor *ad)
1532 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1533 if(colorVariable[(int)(intptr_t)ad->argLoc])
1534 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
1538 SaveBoardSize(FILE *f, char *name, void *addr)
1539 { // wrapper to shield back-end from BoardSize & sizeInfo
1540 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1544 ParseCommPortSettings(char *s)
1545 { // no such option in XBoard (yet)
1548 extern Widget engineOutputShell;
1551 GetActualPlacement(Widget wg, WindowPlacement *wp)
1561 XtSetArg(args[i], XtNx, &x); i++;
1562 XtSetArg(args[i], XtNy, &y); i++;
1563 XtSetArg(args[i], XtNwidth, &w); i++;
1564 XtSetArg(args[i], XtNheight, &h); i++;
1565 XtGetValues(wg, args, i);
1574 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1575 // In XBoard this will have to wait until awareness of window parameters is implemented
1576 GetActualPlacement(shellWidget, &wpMain);
1577 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1578 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1579 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1580 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1581 if(shellUp[1]) GetActualPlacement(shells[1], &wpComment);
1582 if(shellUp[2]) GetActualPlacement(shells[2], &wpTags);
1586 PrintCommPortSettings(FILE *f, char *name)
1587 { // This option does not exist in XBoard
1591 MySearchPath(char *installDir, char *name, char *fullname)
1592 { // just append installDir and name. Perhaps ExpandPath should be used here?
1593 name = ExpandPathName(name);
1594 if(name && name[0] == '/')
1595 safeStrCpy(fullname, name, MSG_SIZ );
1597 sprintf(fullname, "%s%c%s", installDir, '/', name);
1603 MyGetFullPathName(char *name, char *fullname)
1604 { // should use ExpandPath?
1605 name = ExpandPathName(name);
1606 safeStrCpy(fullname, name, MSG_SIZ );
1611 EnsureOnScreen(int *x, int *y, int minX, int minY)
1618 { // [HGM] args: allows testing if main window is realized from back-end
1619 return xBoardWindow != 0;
1623 PopUpStartupDialog()
1624 { // start menu not implemented in XBoard
1628 ConvertToLine(int argc, char **argv)
1630 static char line[128*1024], buf[1024];
1634 for(i=1; i<argc; i++)
1636 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1637 && argv[i][0] != '{' )
1638 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
1640 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
1641 strncat(line, buf, 128*1024 - strlen(line) - 1 );
1644 line[strlen(line)-1] = NULLCHAR;
1648 //--------------------------------------------------------------------------------------------
1650 extern Boolean twoBoards, partnerUp;
1653 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1655 #define BoardSize int
1656 void InitDrawingSizes(BoardSize boardSize, int flags)
1657 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1658 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1660 XtGeometryResult gres;
1663 if(!formWidget) return;
1666 * Enable shell resizing.
1668 shellArgs[0].value = (XtArgVal) &w;
1669 shellArgs[1].value = (XtArgVal) &h;
1670 XtGetValues(shellWidget, shellArgs, 2);
1672 shellArgs[4].value = 3*w; shellArgs[2].value = 10;
1673 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1674 XtSetValues(shellWidget, &shellArgs[2], 4);
1676 XtSetArg(args[0], XtNdefaultDistance, &sep);
1677 XtGetValues(formWidget, args, 1);
1679 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
1680 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1681 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1683 hOffset = boardWidth + 10;
1684 for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
1685 secondSegments[i] = gridSegments[i];
1686 secondSegments[i].x1 += hOffset;
1687 secondSegments[i].x2 += hOffset;
1690 XtSetArg(args[0], XtNwidth, boardWidth);
1691 XtSetArg(args[1], XtNheight, boardHeight);
1692 XtSetValues(boardWidget, args, 2);
1694 timerWidth = (boardWidth - sep) / 2;
1695 XtSetArg(args[0], XtNwidth, timerWidth);
1696 XtSetValues(whiteTimerWidget, args, 1);
1697 XtSetValues(blackTimerWidget, args, 1);
1699 XawFormDoLayout(formWidget, False);
1701 if (appData.titleInWindow) {
1703 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1704 XtSetArg(args[i], XtNheight, &h); i++;
1705 XtGetValues(titleWidget, args, i);
1707 w = boardWidth - 2*bor;
1709 XtSetArg(args[0], XtNwidth, &w);
1710 XtGetValues(menuBarWidget, args, 1);
1711 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1714 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1715 if (gres != XtGeometryYes && appData.debugMode) {
1717 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1718 programName, gres, w, h, wr, hr);
1722 XawFormDoLayout(formWidget, True);
1725 * Inhibit shell resizing.
1727 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
1728 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1729 shellArgs[4].value = shellArgs[2].value = w;
1730 shellArgs[5].value = shellArgs[3].value = h;
1731 XtSetValues(shellWidget, &shellArgs[0], 6);
1733 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1736 for(i=0; i<4; i++) {
1738 for(p=0; p<=(int)WhiteKing; p++)
1739 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1740 if(gameInfo.variant == VariantShogi) {
1741 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1742 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1743 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1744 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1745 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1748 if(gameInfo.variant == VariantGothic) {
1749 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1752 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1753 xpmPieceBitmap[i][(int)WhiteAngel] = xpmPieceBitmap2[i][(int)WhiteFalcon];
1754 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
1757 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1758 for(p=0; p<=(int)WhiteKing; p++)
1759 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1760 if(gameInfo.variant == VariantShogi) {
1761 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1762 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1763 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1764 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1765 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1768 if(gameInfo.variant == VariantGothic) {
1769 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1772 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1773 ximMaskPm[(int)WhiteAngel] = ximMaskPm2[(int)WhiteFalcon];
1774 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
1779 for(i=0; i<2; i++) {
1781 for(p=0; p<=(int)WhiteKing; p++)
1782 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1783 if(gameInfo.variant == VariantShogi) {
1784 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1785 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1786 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1787 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1788 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1791 if(gameInfo.variant == VariantGothic) {
1792 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1795 if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
1796 pieceBitmap[i][(int)WhiteAngel] = pieceBitmap2[i][(int)WhiteFalcon];
1797 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
1807 void ParseIcsTextColors()
1808 { // [HGM] tken out of main(), so it can be called from ICS-Options dialog
1809 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1810 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1811 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1812 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1813 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1814 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1815 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1816 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1817 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1818 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1820 if (appData.colorize) {
1822 _("%s: can't parse color names; disabling colorization\n"),
1825 appData.colorize = FALSE;
1830 { // [HGM] taken out of main(), so it can be called from BoardOptions dialog
1831 XrmValue vFrom, vTo;
1832 int forceMono = False;
1834 if (!appData.monoMode) {
1835 vFrom.addr = (caddr_t) appData.lightSquareColor;
1836 vFrom.size = strlen(appData.lightSquareColor);
1837 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1838 if (vTo.addr == NULL) {
1839 appData.monoMode = True;
1842 lightSquareColor = *(Pixel *) vTo.addr;
1845 if (!appData.monoMode) {
1846 vFrom.addr = (caddr_t) appData.darkSquareColor;
1847 vFrom.size = strlen(appData.darkSquareColor);
1848 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1849 if (vTo.addr == NULL) {
1850 appData.monoMode = True;
1853 darkSquareColor = *(Pixel *) vTo.addr;
1856 if (!appData.monoMode) {
1857 vFrom.addr = (caddr_t) appData.whitePieceColor;
1858 vFrom.size = strlen(appData.whitePieceColor);
1859 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1860 if (vTo.addr == NULL) {
1861 appData.monoMode = True;
1864 whitePieceColor = *(Pixel *) vTo.addr;
1867 if (!appData.monoMode) {
1868 vFrom.addr = (caddr_t) appData.blackPieceColor;
1869 vFrom.size = strlen(appData.blackPieceColor);
1870 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1871 if (vTo.addr == NULL) {
1872 appData.monoMode = True;
1875 blackPieceColor = *(Pixel *) vTo.addr;
1879 if (!appData.monoMode) {
1880 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1881 vFrom.size = strlen(appData.highlightSquareColor);
1882 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1883 if (vTo.addr == NULL) {
1884 appData.monoMode = True;
1887 highlightSquareColor = *(Pixel *) vTo.addr;
1891 if (!appData.monoMode) {
1892 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1893 vFrom.size = strlen(appData.premoveHighlightColor);
1894 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1895 if (vTo.addr == NULL) {
1896 appData.monoMode = True;
1899 premoveHighlightColor = *(Pixel *) vTo.addr;
1907 { // [HGM] taken out of main
1909 if (appData.monoMode && // [HGM] no sense to go on to certain doom
1910 (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
1911 appData.bitmapDirectory = DEF_BITMAP_DIR;
1913 if (appData.bitmapDirectory[0] != NULLCHAR) {
1917 CreateXPMBoard(appData.liteBackTextureFile, 1);
1918 CreateXPMBoard(appData.darkBackTextureFile, 0);
1922 /* Create regular pieces */
1923 if (!useImages) CreatePieces();
1932 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1933 XSetWindowAttributes window_attributes;
1935 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1936 XrmValue vFrom, vTo;
1937 XtGeometryResult gres;
1940 int forceMono = False;
1942 srandom(time(0)); // [HGM] book: make random truly random
1944 setbuf(stdout, NULL);
1945 setbuf(stderr, NULL);
1948 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1949 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1953 programName = strrchr(argv[0], '/');
1954 if (programName == NULL)
1955 programName = argv[0];
1960 XtSetLanguageProc(NULL, NULL, NULL);
1961 bindtextdomain(PACKAGE, LOCALEDIR);
1962 textdomain(PACKAGE);
1966 XtAppInitialize(&appContext, "XBoard", shellOptions,
1967 XtNumber(shellOptions),
1968 &argc, argv, xboardResources, NULL, 0);
1969 appData.boardSize = "";
1970 InitAppData(ConvertToLine(argc, argv));
1972 if (p == NULL) p = "/tmp";
1973 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1974 gameCopyFilename = (char*) malloc(i);
1975 gamePasteFilename = (char*) malloc(i);
1976 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1977 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1979 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1980 clientResources, XtNumber(clientResources),
1983 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1984 static char buf[MSG_SIZ];
1985 EscapeExpand(buf, appData.firstInitString);
1986 appData.firstInitString = strdup(buf);
1987 EscapeExpand(buf, appData.secondInitString);
1988 appData.secondInitString = strdup(buf);
1989 EscapeExpand(buf, appData.firstComputerString);
1990 appData.firstComputerString = strdup(buf);
1991 EscapeExpand(buf, appData.secondComputerString);
1992 appData.secondComputerString = strdup(buf);
1995 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1998 if (chdir(chessDir) != 0) {
1999 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2005 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2006 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2007 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2008 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2011 setbuf(debugFP, NULL);
2014 /* [HGM,HR] make sure board size is acceptable */
2015 if(appData.NrFiles > BOARD_FILES ||
2016 appData.NrRanks > BOARD_RANKS )
2017 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2020 /* This feature does not work; animation needs a rewrite */
2021 appData.highlightDragging = FALSE;
2025 xDisplay = XtDisplay(shellWidget);
2026 xScreen = DefaultScreen(xDisplay);
2027 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2029 gameInfo.variant = StringToVariant(appData.variant);
2030 InitPosition(FALSE);
2033 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2035 if (isdigit(appData.boardSize[0])) {
2036 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2037 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2038 &fontPxlSize, &smallLayout, &tinyLayout);
2040 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2041 programName, appData.boardSize);
2045 /* Find some defaults; use the nearest known size */
2046 SizeDefaults *szd, *nearest;
2047 int distance = 99999;
2048 nearest = szd = sizeDefaults;
2049 while (szd->name != NULL) {
2050 if (abs(szd->squareSize - squareSize) < distance) {
2052 distance = abs(szd->squareSize - squareSize);
2053 if (distance == 0) break;
2057 if (i < 2) lineGap = nearest->lineGap;
2058 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2059 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2060 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2061 if (i < 6) smallLayout = nearest->smallLayout;
2062 if (i < 7) tinyLayout = nearest->tinyLayout;
2065 SizeDefaults *szd = sizeDefaults;
2066 if (*appData.boardSize == NULLCHAR) {
2067 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2068 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2071 if (szd->name == NULL) szd--;
2072 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
2074 while (szd->name != NULL &&
2075 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2076 if (szd->name == NULL) {
2077 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2078 programName, appData.boardSize);
2082 squareSize = szd->squareSize;
2083 lineGap = szd->lineGap;
2084 clockFontPxlSize = szd->clockFontPxlSize;
2085 coordFontPxlSize = szd->coordFontPxlSize;
2086 fontPxlSize = szd->fontPxlSize;
2087 smallLayout = szd->smallLayout;
2088 tinyLayout = szd->tinyLayout;
2089 // [HGM] font: use defaults from settings file if available and not overruled
2091 if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
2092 appData.clockFont = fontTable[CLOCK_FONT][squareSize];
2093 if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
2094 appData.font = fontTable[MESSAGE_FONT][squareSize];
2095 if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
2096 appData.coordFont = fontTable[COORD_FONT][squareSize];
2098 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2099 if (strlen(appData.pixmapDirectory) > 0) {
2100 p = ExpandPathName(appData.pixmapDirectory);
2102 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2103 appData.pixmapDirectory);
2106 if (appData.debugMode) {
2107 fprintf(stderr, _("\
2108 XBoard square size (hint): %d\n\
2109 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2111 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2112 if (appData.debugMode) {
2113 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2116 defaultLineGap = lineGap;
2117 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
2119 /* [HR] height treated separately (hacked) */
2120 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2121 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2122 if (appData.showJail == 1) {
2123 /* Jail on top and bottom */
2124 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2125 XtSetArg(boardArgs[2], XtNheight,
2126 boardHeight + 2*(lineGap + squareSize));
2127 } else if (appData.showJail == 2) {
2129 XtSetArg(boardArgs[1], XtNwidth,
2130 boardWidth + 2*(lineGap + squareSize));
2131 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2134 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2135 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2139 * Determine what fonts to use.
2141 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2142 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2143 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2144 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2145 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2146 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2147 appData.font = FindFont(appData.font, fontPxlSize);
2148 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2149 countFontStruct = XQueryFont(xDisplay, countFontID);
2150 // appData.font = FindFont(appData.font, fontPxlSize);
2152 xdb = XtDatabase(xDisplay);
2153 XrmPutStringResource(&xdb, "*font", appData.font);
2156 * Detect if there are not enough colors available and adapt.
2158 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2159 appData.monoMode = True;
2162 forceMono = MakeColors();
2165 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2167 appData.monoMode = True;
2170 if (appData.lowTimeWarning && !appData.monoMode) {
2171 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2172 vFrom.size = strlen(appData.lowTimeWarningColor);
2173 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2174 if (vTo.addr == NULL)
2175 appData.monoMode = True;
2177 lowTimeWarningColor = *(Pixel *) vTo.addr;
2180 if (appData.monoMode && appData.debugMode) {
2181 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2182 (unsigned long) XWhitePixel(xDisplay, xScreen),
2183 (unsigned long) XBlackPixel(xDisplay, xScreen));
2186 ParseIcsTextColors();
2187 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2188 textColors[ColorNone].attr = 0;
2190 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2196 layoutName = "tinyLayout";
2197 } else if (smallLayout) {
2198 layoutName = "smallLayout";
2200 layoutName = "normalLayout";
2202 /* Outer layoutWidget is there only to provide a name for use in
2203 resources that depend on the layout style */
2205 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2206 layoutArgs, XtNumber(layoutArgs));
2208 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2209 formArgs, XtNumber(formArgs));
2210 XtSetArg(args[0], XtNdefaultDistance, &sep);
2211 XtGetValues(formWidget, args, 1);
2214 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2215 XtSetArg(args[0], XtNtop, XtChainTop);
2216 XtSetArg(args[1], XtNbottom, XtChainTop);
2217 XtSetArg(args[2], XtNright, XtChainLeft);
2218 XtSetValues(menuBarWidget, args, 3);
2220 widgetList[j++] = whiteTimerWidget =
2221 XtCreateWidget("whiteTime", labelWidgetClass,
2222 formWidget, timerArgs, XtNumber(timerArgs));
2223 XtSetArg(args[0], XtNfont, clockFontStruct);
2224 XtSetArg(args[1], XtNtop, XtChainTop);
2225 XtSetArg(args[2], XtNbottom, XtChainTop);
2226 XtSetValues(whiteTimerWidget, args, 3);
2228 widgetList[j++] = blackTimerWidget =
2229 XtCreateWidget("blackTime", labelWidgetClass,
2230 formWidget, timerArgs, XtNumber(timerArgs));
2231 XtSetArg(args[0], XtNfont, clockFontStruct);
2232 XtSetArg(args[1], XtNtop, XtChainTop);
2233 XtSetArg(args[2], XtNbottom, XtChainTop);
2234 XtSetValues(blackTimerWidget, args, 3);
2236 if (appData.titleInWindow) {
2237 widgetList[j++] = titleWidget =
2238 XtCreateWidget("title", labelWidgetClass, formWidget,
2239 titleArgs, XtNumber(titleArgs));
2240 XtSetArg(args[0], XtNtop, XtChainTop);
2241 XtSetArg(args[1], XtNbottom, XtChainTop);
2242 XtSetValues(titleWidget, args, 2);
2245 if (appData.showButtonBar) {
2246 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2247 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2248 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2249 XtSetArg(args[2], XtNtop, XtChainTop);
2250 XtSetArg(args[3], XtNbottom, XtChainTop);
2251 XtSetValues(buttonBarWidget, args, 4);
2254 widgetList[j++] = messageWidget =
2255 XtCreateWidget("message", labelWidgetClass, formWidget,
2256 messageArgs, XtNumber(messageArgs));
2257 XtSetArg(args[0], XtNtop, XtChainTop);
2258 XtSetArg(args[1], XtNbottom, XtChainTop);
2259 XtSetValues(messageWidget, args, 2);
2261 widgetList[j++] = boardWidget =
2262 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2263 XtNumber(boardArgs));
2265 XtManageChildren(widgetList, j);
2267 timerWidth = (boardWidth - sep) / 2;
2268 XtSetArg(args[0], XtNwidth, timerWidth);
2269 XtSetValues(whiteTimerWidget, args, 1);
2270 XtSetValues(blackTimerWidget, args, 1);
2272 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2273 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2274 XtGetValues(whiteTimerWidget, args, 2);
2276 if (appData.showButtonBar) {
2277 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2278 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2279 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2283 * formWidget uses these constraints but they are stored
2287 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2288 XtSetValues(menuBarWidget, args, i);
2289 if (appData.titleInWindow) {
2292 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2293 XtSetValues(whiteTimerWidget, args, i);
2295 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2296 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2297 XtSetValues(blackTimerWidget, args, i);
2299 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2300 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2301 XtSetValues(titleWidget, args, i);
2303 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2304 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2305 XtSetValues(messageWidget, args, i);
2306 if (appData.showButtonBar) {
2308 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2309 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2310 XtSetValues(buttonBarWidget, args, i);
2314 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2315 XtSetValues(whiteTimerWidget, args, i);
2317 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2318 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2319 XtSetValues(blackTimerWidget, args, i);
2321 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2322 XtSetValues(titleWidget, args, i);
2324 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2325 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2326 XtSetValues(messageWidget, args, i);
2327 if (appData.showButtonBar) {
2329 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2330 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2331 XtSetValues(buttonBarWidget, args, i);
2336 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2337 XtSetValues(whiteTimerWidget, args, i);
2339 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2340 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2341 XtSetValues(blackTimerWidget, args, i);
2343 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2344 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2345 XtSetValues(messageWidget, args, i);
2346 if (appData.showButtonBar) {
2348 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2349 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2350 XtSetValues(buttonBarWidget, args, i);
2354 XtSetArg(args[0], XtNfromVert, messageWidget);
2355 XtSetArg(args[1], XtNtop, XtChainTop);
2356 XtSetArg(args[2], XtNbottom, XtChainBottom);
2357 XtSetArg(args[3], XtNleft, XtChainLeft);
2358 XtSetArg(args[4], XtNright, XtChainRight);
2359 XtSetValues(boardWidget, args, 5);
2361 XtRealizeWidget(shellWidget);
2364 XtSetArg(args[0], XtNx, wpMain.x);
2365 XtSetArg(args[1], XtNy, wpMain.y);
2366 XtSetValues(shellWidget, args, 2);
2370 * Correct the width of the message and title widgets.
2371 * It is not known why some systems need the extra fudge term.
2372 * The value "2" is probably larger than needed.
2374 XawFormDoLayout(formWidget, False);
2376 #define WIDTH_FUDGE 2
2378 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2379 XtSetArg(args[i], XtNheight, &h); i++;
2380 XtGetValues(messageWidget, args, i);
2381 if (appData.showButtonBar) {
2383 XtSetArg(args[i], XtNwidth, &w); i++;
2384 XtGetValues(buttonBarWidget, args, i);
2385 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2387 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2390 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2391 if (gres != XtGeometryYes && appData.debugMode) {
2392 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2393 programName, gres, w, h, wr, hr);
2396 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2397 /* The size used for the child widget in layout lags one resize behind
2398 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2400 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2401 if (gres != XtGeometryYes && appData.debugMode) {
2402 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2403 programName, gres, w, h, wr, hr);
2406 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2407 XtSetArg(args[1], XtNright, XtChainRight);
2408 XtSetValues(messageWidget, args, 2);
2410 if (appData.titleInWindow) {
2412 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2413 XtSetArg(args[i], XtNheight, &h); i++;
2414 XtGetValues(titleWidget, args, i);
2416 w = boardWidth - 2*bor;
2418 XtSetArg(args[0], XtNwidth, &w);
2419 XtGetValues(menuBarWidget, args, 1);
2420 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2423 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2424 if (gres != XtGeometryYes && appData.debugMode) {
2426 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2427 programName, gres, w, h, wr, hr);
2430 XawFormDoLayout(formWidget, True);
2432 xBoardWindow = XtWindow(boardWidget);
2434 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2435 // not need to go into InitDrawingSizes().
2439 * Create X checkmark bitmap and initialize option menu checks.
2441 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2442 checkmark_bits, checkmark_width, checkmark_height);
2443 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2444 #ifndef OPTIONSDIALOG
2445 if (appData.alwaysPromoteToQueen) {
2446 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2449 if (appData.animateDragging) {
2450 XtSetValues(XtNameToWidget(menuBarWidget,
2451 "menuOptions.Animate Dragging"),
2454 if (appData.animate) {
2455 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2458 if (appData.autoCallFlag) {
2459 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2462 if (appData.autoFlipView) {
2463 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2466 if (appData.blindfold) {
2467 XtSetValues(XtNameToWidget(menuBarWidget,
2468 "menuOptions.Blindfold"), args, 1);
2470 if (appData.flashCount > 0) {
2471 XtSetValues(XtNameToWidget(menuBarWidget,
2472 "menuOptions.Flash Moves"),
2476 if (appData.highlightDragging) {
2477 XtSetValues(XtNameToWidget(menuBarWidget,
2478 "menuOptions.Highlight Dragging"),
2482 if (appData.highlightLastMove) {
2483 XtSetValues(XtNameToWidget(menuBarWidget,
2484 "menuOptions.Highlight Last Move"),
2487 if (appData.highlightMoveWithArrow) {
2488 XtSetValues(XtNameToWidget(menuBarWidget,
2489 "menuOptions.Arrow"),
2492 // if (appData.icsAlarm) {
2493 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2496 if (appData.ringBellAfterMoves) {
2497 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2500 if (appData.oneClick) {
2501 XtSetValues(XtNameToWidget(menuBarWidget,
2502 "menuOptions.OneClick"), args, 1);
2504 if (appData.periodicUpdates) {
2505 XtSetValues(XtNameToWidget(menuBarWidget,
2506 "menuOptions.Periodic Updates"), args, 1);
2508 if (appData.ponderNextMove) {
2509 XtSetValues(XtNameToWidget(menuBarWidget,
2510 "menuOptions.Ponder Next Move"), args, 1);
2512 if (appData.popupExitMessage) {
2513 XtSetValues(XtNameToWidget(menuBarWidget,
2514 "menuOptions.Popup Exit Message"), args, 1);
2516 if (appData.popupMoveErrors) {
2517 XtSetValues(XtNameToWidget(menuBarWidget,
2518 "menuOptions.Popup Move Errors"), args, 1);
2520 // if (appData.premove) {
2521 // XtSetValues(XtNameToWidget(menuBarWidget,
2522 // "menuOptions.Premove"), args, 1);
2524 if (appData.showCoords) {
2525 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2528 if (appData.hideThinkingFromHuman) {
2529 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2532 if (appData.testLegality) {
2533 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2537 if (saveSettingsOnExit) {
2538 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2545 ReadBitmap(&wIconPixmap, "icon_white.bm",
2546 icon_white_bits, icon_white_width, icon_white_height);
2547 ReadBitmap(&bIconPixmap, "icon_black.bm",
2548 icon_black_bits, icon_black_width, icon_black_height);
2549 iconPixmap = wIconPixmap;
2551 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2552 XtSetValues(shellWidget, args, i);
2555 * Create a cursor for the board widget.
2557 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2558 XChangeWindowAttributes(xDisplay, xBoardWindow,
2559 CWCursor, &window_attributes);
2562 * Inhibit shell resizing.
2564 shellArgs[0].value = (XtArgVal) &w;
2565 shellArgs[1].value = (XtArgVal) &h;
2566 XtGetValues(shellWidget, shellArgs, 2);
2567 shellArgs[4].value = shellArgs[2].value = w;
2568 shellArgs[5].value = shellArgs[3].value = h;
2569 XtSetValues(shellWidget, &shellArgs[2], 4);
2570 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2571 marginH = h - boardHeight;
2573 CatchDeleteWindow(shellWidget, "QuitProc");
2581 if (appData.animate || appData.animateDragging)
2584 XtAugmentTranslations(formWidget,
2585 XtParseTranslationTable(globalTranslations));
2586 XtAugmentTranslations(boardWidget,
2587 XtParseTranslationTable(boardTranslations));
2588 XtAugmentTranslations(whiteTimerWidget,
2589 XtParseTranslationTable(whiteTranslations));
2590 XtAugmentTranslations(blackTimerWidget,
2591 XtParseTranslationTable(blackTranslations));
2593 /* Why is the following needed on some versions of X instead
2594 * of a translation? */
2595 XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False,
2596 (XtEventHandler) EventProc, NULL);
2598 XtAddEventHandler(formWidget, KeyPressMask, False,
2599 (XtEventHandler) MoveTypeInProc, NULL);
2601 /* [AS] Restore layout */
2602 if( wpMoveHistory.visible ) {
2606 if( wpEvalGraph.visible )
2611 if( wpEngineOutput.visible ) {
2612 EngineOutputPopUp();
2617 if (errorExitStatus == -1) {
2618 if (appData.icsActive) {
2619 /* We now wait until we see "login:" from the ICS before
2620 sending the logon script (problems with timestamp otherwise) */
2621 /*ICSInitScript();*/
2622 if (appData.icsInputBox) ICSInputBoxPopUp();
2626 signal(SIGWINCH, TermSizeSigHandler);
2628 signal(SIGINT, IntSigHandler);
2629 signal(SIGTERM, IntSigHandler);
2630 if (*appData.cmailGameName != NULLCHAR) {
2631 signal(SIGUSR1, CmailSigHandler);
2634 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2636 // XtSetKeyboardFocus(shellWidget, formWidget);
2637 XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
2639 XtAppMainLoop(appContext);
2640 if (appData.debugMode) fclose(debugFP); // [DM] debug
2647 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2648 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2650 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2651 unlink(gameCopyFilename);
2652 unlink(gamePasteFilename);
2655 RETSIGTYPE TermSizeSigHandler(int sig)
2668 CmailSigHandler(sig)
2674 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2676 /* Activate call-back function CmailSigHandlerCallBack() */
2677 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2679 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2683 CmailSigHandlerCallBack(isr, closure, message, count, error)
2691 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2693 /**** end signal code ****/
2699 /* try to open the icsLogon script, either in the location given
2700 * or in the users HOME directory
2707 f = fopen(appData.icsLogon, "r");
2710 homedir = getenv("HOME");
2711 if (homedir != NULL)
2713 safeStrCpy(buf, homedir, sizeof(buf)/sizeof(buf[0]) );
2714 strncat(buf, "/", MSG_SIZ - strlen(buf) - 1);
2715 strncat(buf, appData.icsLogon, MSG_SIZ - strlen(buf) - 1);
2716 f = fopen(buf, "r");
2721 ProcessICSInitScript(f);
2723 printf("Warning: Couldn't open icsLogon file (checked %s and %s).\n", appData.icsLogon, buf);
2746 if (!menuBarWidget) return;
2747 w = XtNameToWidget(menuBarWidget, "menuEdit.Revert");
2749 DisplayError("menuEdit.Revert", 0);
2751 XtSetSensitive(w, !grey);
2753 w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate");
2755 DisplayError("menuEdit.Annotate", 0);
2757 XtSetSensitive(w, !grey);
2762 SetMenuEnables(enab)
2766 if (!menuBarWidget) return;
2767 while (enab->name != NULL) {
2768 w = XtNameToWidget(menuBarWidget, enab->name);
2770 DisplayError(enab->name, 0);
2772 XtSetSensitive(w, enab->value);
2778 Enables icsEnables[] = {
2779 { "menuFile.Mail Move", False },
2780 { "menuFile.Reload CMail Message", False },
2781 { "menuMode.Machine Black", False },
2782 { "menuMode.Machine White", False },
2783 { "menuMode.Analysis Mode", False },
2784 { "menuMode.Analyze File", False },
2785 { "menuMode.Two Machines", False },
2786 { "menuMode.Machine Match", False },
2788 { "menuEngine.Hint", False },
2789 { "menuEngine.Book", False },
2790 { "menuEngine.Move Now", False },
2791 #ifndef OPTIONSDIALOG
2792 { "menuOptions.Periodic Updates", False },
2793 { "menuOptions.Hide Thinking", False },
2794 { "menuOptions.Ponder Next Move", False },
2797 { "menuEngine.Engine #1 Settings", False },
2798 { "menuEngine.Engine #2 Settings", False },
2799 { "menuEngine.Load Engine", False },
2800 { "menuEdit.Annotate", False },
2801 { "menuOptions.Match", False },
2805 Enables ncpEnables[] = {
2806 { "menuFile.Mail Move", False },
2807 { "menuFile.Reload CMail Message", False },
2808 { "menuMode.Machine White", False },
2809 { "menuMode.Machine Black", False },
2810 { "menuMode.Analysis Mode", False },
2811 { "menuMode.Analyze File", False },
2812 { "menuMode.Two Machines", False },
2813 { "menuMode.Machine Match", False },
2814 { "menuMode.ICS Client", False },
2815 { "menuView.ICStex", False },
2816 { "menuView.ICS Input Box", False },
2817 { "Action", False },
2818 { "menuEdit.Revert", False },
2819 { "menuEdit.Annotate", False },
2820 { "menuEngine.Engine #1 Settings", False },
2821 { "menuEngine.Engine #2 Settings", False },
2822 { "menuEngine.Move Now", False },
2823 { "menuEngine.Retract Move", False },
2824 { "menuOptions.ICS", False },
2825 #ifndef OPTIONSDIALOG
2826 { "menuOptions.Auto Flag", False },
2827 { "menuOptions.Auto Flip View", False },
2828 // { "menuOptions.ICS Alarm", False },
2829 { "menuOptions.Move Sound", False },
2830 { "menuOptions.Hide Thinking", False },
2831 { "menuOptions.Periodic Updates", False },
2832 { "menuOptions.Ponder Next Move", False },
2834 { "menuEngine.Hint", False },
2835 { "menuEngine.Book", False },
2839 Enables gnuEnables[] = {
2840 { "menuMode.ICS Client", False },
2841 { "menuView.ICStex", False },
2842 { "menuView.ICS Input Box", False },
2843 { "menuAction.Accept", False },
2844 { "menuAction.Decline", False },
2845 { "menuAction.Rematch", False },
2846 { "menuAction.Adjourn", False },
2847 { "menuAction.Stop Examining", False },
2848 { "menuAction.Stop Observing", False },
2849 { "menuAction.Upload to Examine", False },
2850 { "menuEdit.Revert", False },
2851 { "menuEdit.Annotate", False },
2852 { "menuOptions.ICS", False },
2854 /* The next two options rely on SetCmailMode being called *after* */
2855 /* SetGNUMode so that when GNU is being used to give hints these */
2856 /* menu options are still available */
2858 { "menuFile.Mail Move", False },
2859 { "menuFile.Reload CMail Message", False },
2860 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
2861 { "menuMode.Machine White", True },
2862 { "menuMode.Machine Black", True },
2863 { "menuMode.Analysis Mode", True },
2864 { "menuMode.Analyze File", True },
2865 { "menuMode.Two Machines", True },
2866 { "menuMode.Machine Match", True },
2867 { "menuEngine.Engine #1 Settings", True },
2868 { "menuEngine.Engine #2 Settings", True },
2869 { "menuEngine.Hint", True },
2870 { "menuEngine.Book", True },
2871 { "menuEngine.Move Now", True },
2872 { "menuEngine.Retract Move", True },
2877 Enables cmailEnables[] = {
2879 { "menuAction.Call Flag", False },
2880 { "menuAction.Draw", True },
2881 { "menuAction.Adjourn", False },
2882 { "menuAction.Abort", False },
2883 { "menuAction.Stop Observing", False },
2884 { "menuAction.Stop Examining", False },
2885 { "menuFile.Mail Move", True },
2886 { "menuFile.Reload CMail Message", True },
2890 Enables trainingOnEnables[] = {
2891 { "menuMode.Edit Comment", False },
2892 { "menuMode.Pause", False },
2893 { "menuEdit.Forward", False },
2894 { "menuEdit.Backward", False },
2895 { "menuEdit.Forward to End", False },
2896 { "menuEdit.Back to Start", False },
2897 { "menuEngine.Move Now", False },
2898 { "menuEdit.Truncate Game", False },
2902 Enables trainingOffEnables[] = {
2903 { "menuMode.Edit Comment", True },
2904 { "menuMode.Pause", True },
2905 { "menuEdit.Forward", True },
2906 { "menuEdit.Backward", True },
2907 { "menuEdit.Forward to End", True },
2908 { "menuEdit.Back to Start", True },
2909 { "menuEngine.Move Now", True },
2910 { "menuEdit.Truncate Game", True },
2914 Enables machineThinkingEnables[] = {
2915 { "menuFile.Load Game", False },
2916 // { "menuFile.Load Next Game", False },
2917 // { "menuFile.Load Previous Game", False },
2918 // { "menuFile.Reload Same Game", False },
2919 { "menuEdit.Paste Game", False },
2920 { "menuFile.Load Position", False },
2921 // { "menuFile.Load Next Position", False },
2922 // { "menuFile.Load Previous Position", False },
2923 // { "menuFile.Reload Same Position", False },
2924 { "menuEdit.Paste Position", False },
2925 { "menuMode.Machine White", False },
2926 { "menuMode.Machine Black", False },
2927 { "menuMode.Two Machines", False },
2928 // { "menuMode.Machine Match", False },
2929 { "menuEngine.Retract Move", False },
2933 Enables userThinkingEnables[] = {
2934 { "menuFile.Load Game", True },
2935 // { "menuFile.Load Next Game", True },
2936 // { "menuFile.Load Previous Game", True },
2937 // { "menuFile.Reload Same Game", True },
2938 { "menuEdit.Paste Game", True },
2939 { "menuFile.Load Position", True },
2940 // { "menuFile.Load Next Position", True },
2941 // { "menuFile.Load Previous Position", True },
2942 // { "menuFile.Reload Same Position", True },
2943 { "menuEdit.Paste Position", True },
2944 { "menuMode.Machine White", True },
2945 { "menuMode.Machine Black", True },
2946 { "menuMode.Two Machines", True },
2947 // { "menuMode.Machine Match", True },
2948 { "menuEngine.Retract Move", True },
2954 SetMenuEnables(icsEnables);
2957 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
2958 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2959 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True);
2967 SetMenuEnables(ncpEnables);
2973 SetMenuEnables(gnuEnables);
2979 SetMenuEnables(cmailEnables);
2985 SetMenuEnables(trainingOnEnables);
2986 if (appData.showButtonBar) {
2987 XtSetSensitive(buttonBarWidget, False);
2993 SetTrainingModeOff()
2995 SetMenuEnables(trainingOffEnables);
2996 if (appData.showButtonBar) {
2997 XtSetSensitive(buttonBarWidget, True);
3002 SetUserThinkingEnables()
3004 if (appData.noChessProgram) return;
3005 SetMenuEnables(userThinkingEnables);
3009 SetMachineThinkingEnables()
3011 if (appData.noChessProgram) return;
3012 SetMenuEnables(machineThinkingEnables);
3014 case MachinePlaysBlack:
3015 case MachinePlaysWhite:
3016 case TwoMachinesPlay:
3017 XtSetSensitive(XtNameToWidget(menuBarWidget,
3018 ModeToWidgetName(gameMode)), True);
3025 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
3026 #define HISTORY_SIZE 64
3027 static char *history[HISTORY_SIZE];
3028 int histIn = 0, histP = 0;
3031 SaveInHistory(char *cmd)
3033 if (history[histIn] != NULL) {
3034 free(history[histIn]);
3035 history[histIn] = NULL;
3037 if (*cmd == NULLCHAR) return;
3038 history[histIn] = StrSave(cmd);
3039 histIn = (histIn + 1) % HISTORY_SIZE;
3040 if (history[histIn] != NULL) {
3041 free(history[histIn]);
3042 history[histIn] = NULL;
3048 PrevInHistory(char *cmd)
3051 if (histP == histIn) {
3052 if (history[histIn] != NULL) free(history[histIn]);
3053 history[histIn] = StrSave(cmd);
3055 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
3056 if (newhp == histIn || history[newhp] == NULL) return NULL;
3058 return history[histP];
3064 if (histP == histIn) return NULL;
3065 histP = (histP + 1) % HISTORY_SIZE;
3066 return history[histP];
3068 // end of borrowed code
3070 #define Abs(n) ((n)<0 ? -(n) : (n))
3073 * Find a font that matches "pattern" that is as close as
3074 * possible to the targetPxlSize. Prefer fonts that are k
3075 * pixels smaller to fonts that are k pixels larger. The
3076 * pattern must be in the X Consortium standard format,
3077 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3078 * The return value should be freed with XtFree when no
3082 FindFont(pattern, targetPxlSize)
3086 char **fonts, *p, *best, *scalable, *scalableTail;
3087 int i, j, nfonts, minerr, err, pxlSize;
3090 char **missing_list;
3092 char *def_string, *base_fnt_lst, strInt[3];
3094 XFontStruct **fnt_list;
3095 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3096 snprintf(strInt, sizeof(strInt)/sizeof(strInt[0]), "%d", targetPxlSize);
3097 p = strstr(pattern, "--");
3098 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3099 strcat(base_fnt_lst, strInt);
3100 strcat(base_fnt_lst, strchr(p + 2, '-'));
3102 if ((fntSet = XCreateFontSet(xDisplay,
3106 &def_string)) == NULL) {
3108 fprintf(stderr, _("Unable to create font set.\n"));
3112 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3114 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3116 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3117 programName, pattern);
3125 for (i=0; i<nfonts; i++) {
3128 if (*p != '-') continue;
3130 if (*p == NULLCHAR) break;
3131 if (*p++ == '-') j++;
3133 if (j < 7) continue;
3136 scalable = fonts[i];
3139 err = pxlSize - targetPxlSize;
3140 if (Abs(err) < Abs(minerr) ||
3141 (minerr > 0 && err < 0 && -err == minerr)) {
3147 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3148 /* If the error is too big and there is a scalable font,
3149 use the scalable font. */
3150 int headlen = scalableTail - scalable;
3151 p = (char *) XtMalloc(strlen(scalable) + 10);
3152 while (isdigit(*scalableTail)) scalableTail++;
3153 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3155 p = (char *) XtMalloc(strlen(best) + 2);
3156 safeStrCpy(p, best, strlen(best)+1 );
3158 if (appData.debugMode) {
3159 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3160 pattern, targetPxlSize, p);
3163 if (missing_count > 0)
3164 XFreeStringList(missing_list);
3165 XFreeFontSet(xDisplay, fntSet);
3167 XFreeFontNames(fonts);
3173 { // [HGM] deletes GCs that are to be remade, to prevent resource leak;
3174 // must be called before all non-first callse to CreateGCs()
3175 XtReleaseGC(shellWidget, highlineGC);
3176 XtReleaseGC(shellWidget, lightSquareGC);
3177 XtReleaseGC(shellWidget, darkSquareGC);
3178 XtReleaseGC(shellWidget, lineGC);
3179 if (appData.monoMode) {
3180 if (DefaultDepth(xDisplay, xScreen) == 1) {
3181 XtReleaseGC(shellWidget, wbPieceGC);
3183 XtReleaseGC(shellWidget, bwPieceGC);
3186 XtReleaseGC(shellWidget, prelineGC);
3187 XtReleaseGC(shellWidget, jailSquareGC);
3188 XtReleaseGC(shellWidget, wdPieceGC);
3189 XtReleaseGC(shellWidget, wlPieceGC);
3190 XtReleaseGC(shellWidget, wjPieceGC);
3191 XtReleaseGC(shellWidget, bdPieceGC);
3192 XtReleaseGC(shellWidget, blPieceGC);
3193 XtReleaseGC(shellWidget, bjPieceGC);
3197 void CreateGCs(int redo)
3199 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3200 | GCBackground | GCFunction | GCPlaneMask;
3201 XGCValues gc_values;
3204 gc_values.plane_mask = AllPlanes;
3205 gc_values.line_width = lineGap;
3206 gc_values.line_style = LineSolid;
3207 gc_values.function = GXcopy;
3210 DeleteGCs(); // called a second time; clean up old GCs first
3211 } else { // [HGM] grid and font GCs created on first call only
3212 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3213 gc_values.background = XWhitePixel(xDisplay, xScreen);
3214 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3215 XSetFont(xDisplay, coordGC, coordFontID);
3217 // [HGM] make font for holdings counts (white on black)
3218 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3219 gc_values.background = XBlackPixel(xDisplay, xScreen);
3220 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3221 XSetFont(xDisplay, countGC, countFontID);
3223 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3224 gc_values.background = XBlackPixel(xDisplay, xScreen);
3225 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3227 if (appData.monoMode) {
3228 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3229 gc_values.background = XWhitePixel(xDisplay, xScreen);
3230 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3232 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3233 gc_values.background = XBlackPixel(xDisplay, xScreen);
3234 lightSquareGC = wbPieceGC
3235 = XtGetGC(shellWidget, value_mask, &gc_values);
3237 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3238 gc_values.background = XWhitePixel(xDisplay, xScreen);
3239 darkSquareGC = bwPieceGC
3240 = XtGetGC(shellWidget, value_mask, &gc_values);
3242 if (DefaultDepth(xDisplay, xScreen) == 1) {
3243 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3244 gc_values.function = GXcopyInverted;
3245 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3246 gc_values.function = GXcopy;
3247 if (XBlackPixel(xDisplay, xScreen) == 1) {
3248 bwPieceGC = darkSquareGC;
3249 wbPieceGC = copyInvertedGC;
3251 bwPieceGC = copyInvertedGC;
3252 wbPieceGC = lightSquareGC;
3256 gc_values.foreground = highlightSquareColor;
3257 gc_values.background = highlightSquareColor;
3258 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3260 gc_values.foreground = premoveHighlightColor;
3261 gc_values.background = premoveHighlightColor;
3262 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3264 gc_values.foreground = lightSquareColor;
3265 gc_values.background = darkSquareColor;
3266 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3268 gc_values.foreground = darkSquareColor;
3269 gc_values.background = lightSquareColor;
3270 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3272 gc_values.foreground = jailSquareColor;
3273 gc_values.background = jailSquareColor;
3274 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3276 gc_values.foreground = whitePieceColor;
3277 gc_values.background = darkSquareColor;
3278 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3280 gc_values.foreground = whitePieceColor;
3281 gc_values.background = lightSquareColor;
3282 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3284 gc_values.foreground = whitePieceColor;
3285 gc_values.background = jailSquareColor;
3286 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3288 gc_values.foreground = blackPieceColor;
3289 gc_values.background = darkSquareColor;
3290 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3292 gc_values.foreground = blackPieceColor;
3293 gc_values.background = lightSquareColor;
3294 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3296 gc_values.foreground = blackPieceColor;
3297 gc_values.background = jailSquareColor;
3298 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3302 void loadXIM(xim, xmask, filename, dest, mask)
3315 fp = fopen(filename, "rb");
3317 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3324 for (y=0; y<h; ++y) {
3325 for (x=0; x<h; ++x) {
3330 XPutPixel(xim, x, y, blackPieceColor);
3332 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3335 XPutPixel(xim, x, y, darkSquareColor);
3337 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3340 XPutPixel(xim, x, y, whitePieceColor);
3342 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3345 XPutPixel(xim, x, y, lightSquareColor);
3347 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3355 /* create Pixmap of piece */
3356 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3358 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3361 /* create Pixmap of clipmask
3362 Note: We assume the white/black pieces have the same
3363 outline, so we make only 6 masks. This is okay
3364 since the XPM clipmask routines do the same. */
3366 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3368 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3371 /* now create the 1-bit version */
3372 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3375 values.foreground = 1;
3376 values.background = 0;
3378 /* Don't use XtGetGC, not read only */
3379 maskGC = XCreateGC(xDisplay, *mask,
3380 GCForeground | GCBackground, &values);
3381 XCopyPlane(xDisplay, temp, *mask, maskGC,
3382 0, 0, squareSize, squareSize, 0, 0, 1);
3383 XFreePixmap(xDisplay, temp);
3388 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3390 void CreateXIMPieces()
3395 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3400 /* The XSynchronize calls were copied from CreatePieces.
3401 Not sure if needed, but can't hurt */
3402 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3405 /* temp needed by loadXIM() */
3406 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3407 0, 0, ss, ss, AllPlanes, XYPixmap);
3409 if (strlen(appData.pixmapDirectory) == 0) {
3413 if (appData.monoMode) {
3414 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3418 fprintf(stderr, _("\nLoading XIMs...\n"));
3420 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3421 fprintf(stderr, "%d", piece+1);
3422 for (kind=0; kind<4; kind++) {
3423 fprintf(stderr, ".");
3424 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3425 ExpandPathName(appData.pixmapDirectory),
3426 piece <= (int) WhiteKing ? "" : "w",
3427 pieceBitmapNames[piece],
3429 ximPieceBitmap[kind][piece] =
3430 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3431 0, 0, ss, ss, AllPlanes, XYPixmap);
3432 if (appData.debugMode)
3433 fprintf(stderr, _("(File:%s:) "), buf);
3434 loadXIM(ximPieceBitmap[kind][piece],
3436 &(xpmPieceBitmap2[kind][piece]),
3437 &(ximMaskPm2[piece]));
3438 if(piece <= (int)WhiteKing)
3439 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3441 fprintf(stderr," ");
3443 /* Load light and dark squares */
3444 /* If the LSQ and DSQ pieces don't exist, we will
3445 draw them with solid squares. */
3446 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3447 if (access(buf, 0) != 0) {
3451 fprintf(stderr, _("light square "));
3453 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3454 0, 0, ss, ss, AllPlanes, XYPixmap);
3455 if (appData.debugMode)
3456 fprintf(stderr, _("(File:%s:) "), buf);
3458 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3459 fprintf(stderr, _("dark square "));
3460 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3461 ExpandPathName(appData.pixmapDirectory), ss);
3462 if (appData.debugMode)
3463 fprintf(stderr, _("(File:%s:) "), buf);
3465 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3466 0, 0, ss, ss, AllPlanes, XYPixmap);
3467 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3468 xpmJailSquare = xpmLightSquare;
3470 fprintf(stderr, _("Done.\n"));
3472 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3475 static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
3478 void CreateXPMBoard(char *s, int kind)
3482 if(s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
3483 if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
3484 useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
3488 void FreeXPMPieces()
3489 { // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
3490 // thisroutine has to be called t free the old piece pixmaps
3492 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
3493 for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
3495 XFreePixmap(xDisplay, xpmLightSquare);
3496 XFreePixmap(xDisplay, xpmDarkSquare);
3500 void CreateXPMPieces()
3504 u_int ss = squareSize;
3506 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3507 XpmColorSymbol symbols[4];
3508 static int redo = False;
3510 if(redo) FreeXPMPieces(); else redo = 1;
3512 /* The XSynchronize calls were copied from CreatePieces.
3513 Not sure if needed, but can't hurt */
3514 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3516 /* Setup translations so piece colors match square colors */
3517 symbols[0].name = "light_piece";
3518 symbols[0].value = appData.whitePieceColor;
3519 symbols[1].name = "dark_piece";
3520 symbols[1].value = appData.blackPieceColor;
3521 symbols[2].name = "light_square";
3522 symbols[2].value = appData.lightSquareColor;
3523 symbols[3].name = "dark_square";
3524 symbols[3].value = appData.darkSquareColor;
3526 attr.valuemask = XpmColorSymbols;
3527 attr.colorsymbols = symbols;
3528 attr.numsymbols = 4;
3530 if (appData.monoMode) {
3531 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3535 if (strlen(appData.pixmapDirectory) == 0) {
3536 XpmPieces* pieces = builtInXpms;
3539 while (pieces->size != squareSize && pieces->size) pieces++;
3540 if (!pieces->size) {
3541 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3544 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3545 for (kind=0; kind<4; kind++) {
3547 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3548 pieces->xpm[piece][kind],
3549 &(xpmPieceBitmap2[kind][piece]),
3550 NULL, &attr)) != 0) {
3551 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3555 if(piece <= (int) WhiteKing)
3556 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3560 xpmJailSquare = xpmLightSquare;
3564 fprintf(stderr, _("\nLoading XPMs...\n"));
3567 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3568 fprintf(stderr, "%d ", piece+1);
3569 for (kind=0; kind<4; kind++) {
3570 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3571 ExpandPathName(appData.pixmapDirectory),
3572 piece > (int) WhiteKing ? "w" : "",
3573 pieceBitmapNames[piece],
3575 if (appData.debugMode) {
3576 fprintf(stderr, _("(File:%s:) "), buf);
3578 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3579 &(xpmPieceBitmap2[kind][piece]),
3580 NULL, &attr)) != 0) {
3581 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3582 // [HGM] missing: read of unorthodox piece failed; substitute King.
3583 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3584 ExpandPathName(appData.pixmapDirectory),
3586 if (appData.debugMode) {
3587 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3589 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3590 &(xpmPieceBitmap2[kind][piece]),
3594 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3599 if(piece <= (int) WhiteKing)
3600 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3603 /* Load light and dark squares */
3604 /* If the LSQ and DSQ pieces don't exist, we will
3605 draw them with solid squares. */
3606 fprintf(stderr, _("light square "));
3607 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3608 if (access(buf, 0) != 0) {
3612 if (appData.debugMode)
3613 fprintf(stderr, _("(File:%s:) "), buf);
3615 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3616 &xpmLightSquare, NULL, &attr)) != 0) {
3617 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3620 fprintf(stderr, _("dark square "));
3621 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3622 ExpandPathName(appData.pixmapDirectory), ss);
3623 if (appData.debugMode) {
3624 fprintf(stderr, _("(File:%s:) "), buf);
3626 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3627 &xpmDarkSquare, NULL, &attr)) != 0) {
3628 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3632 xpmJailSquare = xpmLightSquare;
3633 fprintf(stderr, _("Done.\n"));
3635 oldVariant = -1; // kludge to force re-makig of animation masks
3636 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3639 #endif /* HAVE_LIBXPM */
3642 /* No built-in bitmaps */
3647 u_int ss = squareSize;
3649 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3652 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3653 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3654 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3655 pieceBitmapNames[piece],
3656 ss, kind == SOLID ? 's' : 'o');
3657 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3658 if(piece <= (int)WhiteKing)
3659 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3663 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3667 /* With built-in bitmaps */
3670 BuiltInBits* bib = builtInBits;
3673 u_int ss = squareSize;
3675 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3678 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3680 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3681 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3682 snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3683 pieceBitmapNames[piece],
3684 ss, kind == SOLID ? 's' : 'o');
3685 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3686 bib->bits[kind][piece], ss, ss);
3687 if(piece <= (int)WhiteKing)
3688 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3692 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3697 void ReadBitmap(pm, name, bits, wreq, hreq)
3700 unsigned char bits[];
3706 char msg[MSG_SIZ], fullname[MSG_SIZ];
3708 if (*appData.bitmapDirectory != NULLCHAR) {
3709 safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
3710 strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
3711 strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
3712 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3713 &w, &h, pm, &x_hot, &y_hot);
3714 fprintf(stderr, "load %s\n", name);
3715 if (errcode != BitmapSuccess) {
3717 case BitmapOpenFailed:
3718 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3720 case BitmapFileInvalid:
3721 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3723 case BitmapNoMemory:
3724 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3728 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3732 fprintf(stderr, _("%s: %s...using built-in\n"),
3734 } else if (w != wreq || h != hreq) {
3736 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3737 programName, fullname, w, h, wreq, hreq);
3743 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3752 if (lineGap == 0) return;
3754 /* [HR] Split this into 2 loops for non-square boards. */
3756 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3757 gridSegments[i].x1 = 0;
3758 gridSegments[i].x2 =
3759 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3760 gridSegments[i].y1 = gridSegments[i].y2
3761 = lineGap / 2 + (i * (squareSize + lineGap));
3764 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3765 gridSegments[j + i].y1 = 0;
3766 gridSegments[j + i].y2 =
3767 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3768 gridSegments[j + i].x1 = gridSegments[j + i].x2
3769 = lineGap / 2 + (j * (squareSize + lineGap));
3773 static void MenuBarSelect(w, addr, index)
3778 XtActionProc proc = (XtActionProc) addr;
3780 (proc)(NULL, NULL, NULL, NULL);
3783 void CreateMenuBarPopup(parent, name, mb)
3793 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3796 XtSetArg(args[j], XtNleftMargin, 20); j++;
3797 XtSetArg(args[j], XtNrightMargin, 20); j++;
3799 while (mi->string != NULL) {
3800 if (strcmp(mi->string, "----") == 0) {
3801 entry = XtCreateManagedWidget(_(mi->string), smeLineObjectClass,
3804 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3805 entry = XtCreateManagedWidget(mi->ref, smeBSBObjectClass,
3807 XtAddCallback(entry, XtNcallback,
3808 (XtCallbackProc) MenuBarSelect,
3809 (caddr_t) mi->proc);
3815 Widget CreateMenuBar(mb)
3819 Widget anchor, menuBar;
3821 char menuName[MSG_SIZ];
3824 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3825 XtSetArg(args[j], XtNvSpace, 0); j++;
3826 XtSetArg(args[j], XtNborderWidth, 0); j++;
3827 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3828 formWidget, args, j);
3830 while (mb->name != NULL) {
3831 safeStrCpy(menuName, "menu", sizeof(menuName)/sizeof(menuName[0]) );
3832 strncat(menuName, mb->ref, MSG_SIZ - strlen(menuName) - 1);
3834 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3837 shortName[0] = mb->name[0];
3838 shortName[1] = NULLCHAR;
3839 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3842 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3845 XtSetArg(args[j], XtNborderWidth, 0); j++;
3846 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3848 CreateMenuBarPopup(menuBar, menuName, mb);
3854 Widget CreateButtonBar(mi)
3858 Widget button, buttonBar;
3862 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3864 XtSetArg(args[j], XtNhSpace, 0); j++;
3866 XtSetArg(args[j], XtNborderWidth, 0); j++;
3867 XtSetArg(args[j], XtNvSpace, 0); j++;
3868 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3869 formWidget, args, j);
3871 while (mi->string != NULL) {
3874 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3875 XtSetArg(args[j], XtNborderWidth, 0); j++;
3877 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3878 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3879 buttonBar, args, j);
3880 XtAddCallback(button, XtNcallback,
3881 (XtCallbackProc) MenuBarSelect,
3882 (caddr_t) mi->proc);
3889 CreatePieceMenu(name, color)
3896 ChessSquare selection;
3898 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3899 boardWidget, args, 0);
3901 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3902 String item = pieceMenuStrings[color][i];
3904 if (strcmp(item, "----") == 0) {
3905 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3908 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3909 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3911 selection = pieceMenuTranslation[color][i];
3912 XtAddCallback(entry, XtNcallback,
3913 (XtCallbackProc) PieceMenuSelect,
3914 (caddr_t) selection);
3915 if (selection == WhitePawn || selection == BlackPawn) {
3916 XtSetArg(args[0], XtNpopupOnEntry, entry);
3917 XtSetValues(menu, args, 1);
3930 ChessSquare selection;
3932 whitePieceMenu = CreatePieceMenu("menuW", 0);
3933 blackPieceMenu = CreatePieceMenu("menuB", 1);
3935 XtRegisterGrabAction(PieceMenuPopup, True,
3936 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3937 GrabModeAsync, GrabModeAsync);
3939 XtSetArg(args[0], XtNlabel, _("Drop"));
3940 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3941 boardWidget, args, 1);
3942 for (i = 0; i < DROP_MENU_SIZE; i++) {
3943 String item = dropMenuStrings[i];
3945 if (strcmp(item, "----") == 0) {
3946 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3949 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3950 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3952 selection = dropMenuTranslation[i];
3953 XtAddCallback(entry, XtNcallback,
3954 (XtCallbackProc) DropMenuSelect,
3955 (caddr_t) selection);
3960 void SetupDropMenu()
3968 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3969 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3970 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3971 dmEnables[i].piece);
3972 XtSetSensitive(entry, p != NULL || !appData.testLegality
3973 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3974 && !appData.icsActive));
3976 while (p && *p++ == dmEnables[i].piece) count++;
3977 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3979 XtSetArg(args[j], XtNlabel, label); j++;
3980 XtSetValues(entry, args, j);
3984 void PieceMenuPopup(w, event, params, num_params)
3988 Cardinal *num_params;
3990 String whichMenu; int menuNr = -2;
3991 shiftKey = strcmp(params[0], "menuW"); // used to indicate black
3992 if (event->type == ButtonRelease)
3993 menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3994 else if (event->type == ButtonPress)
3995 menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
3997 case 0: whichMenu = params[0]; break;
3998 case 1: SetupDropMenu(); whichMenu = "menuD"; break;
4000 case -1: if (errorUp) ErrorPopDown();
4003 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4006 static void PieceMenuSelect(w, piece, junk)
4011 if (pmFromX < 0 || pmFromY < 0) return;
4012 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4015 static void DropMenuSelect(w, piece, junk)
4020 if (pmFromX < 0 || pmFromY < 0) return;
4021 DropMenuEvent(piece, pmFromX, pmFromY);
4024 void WhiteClock(w, event, prms, nprms)
4033 void BlackClock(w, event, prms, nprms)
4044 * If the user selects on a border boundary, return -1; if off the board,
4045 * return -2. Otherwise map the event coordinate to the square.
4047 int EventToSquare(x, limit)
4055 if ((x % (squareSize + lineGap)) >= squareSize)
4057 x /= (squareSize + lineGap);
4063 static void do_flash_delay(msec)
4069 static void drawHighlight(file, rank, gc)
4075 if (lineGap == 0) return;
4078 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4079 (squareSize + lineGap);
4080 y = lineGap/2 + rank * (squareSize + lineGap);
4082 x = lineGap/2 + file * (squareSize + lineGap);
4083 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4084 (squareSize + lineGap);
4087 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4088 squareSize+lineGap, squareSize+lineGap);
4091 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4092 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4095 SetHighlights(fromX, fromY, toX, toY)
4096 int fromX, fromY, toX, toY;
4098 if (hi1X != fromX || hi1Y != fromY) {
4099 if (hi1X >= 0 && hi1Y >= 0) {
4100 drawHighlight(hi1X, hi1Y, lineGC);
4102 } // [HGM] first erase both, then draw new!
4103 if (hi2X != toX || hi2Y != toY) {
4104 if (hi2X >= 0 && hi2Y >= 0) {
4105 drawHighlight(hi2X, hi2Y, lineGC);
4108 if (hi1X != fromX || hi1Y != fromY) {
4109 if (fromX >= 0 && fromY >= 0) {
4110 drawHighlight(fromX, fromY, highlineGC);
4113 if (hi2X != toX || hi2Y != toY) {
4114 if (toX >= 0 && toY >= 0) {
4115 drawHighlight(toX, toY, highlineGC);
4127 SetHighlights(-1, -1, -1, -1);
4132 SetPremoveHighlights(fromX, fromY, toX, toY)
4133 int fromX, fromY, toX, toY;
4135 if (pm1X != fromX || pm1Y != fromY) {
4136 if (pm1X >= 0 && pm1Y >= 0) {
4137 drawHighlight(pm1X, pm1Y, lineGC);
4139 if (fromX >= 0 && fromY >= 0) {
4140 drawHighlight(fromX, fromY, prelineGC);
4143 if (pm2X != toX || pm2Y != toY) {
4144 if (pm2X >= 0 && pm2Y >= 0) {
4145 drawHighlight(pm2X, pm2Y, lineGC);
4147 if (toX >= 0 && toY >= 0) {
4148 drawHighlight(toX, toY, prelineGC);
4158 ClearPremoveHighlights()
4160 SetPremoveHighlights(-1, -1, -1, -1);
4163 static int CutOutSquare(x, y, x0, y0, kind)
4164 int x, y, *x0, *y0, kind;
4166 int W = BOARD_WIDTH, H = BOARD_HEIGHT;
4167 int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
4169 if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
4170 if(textureW[kind] < W*squareSize)
4171 *x0 = (textureW[kind] - squareSize) * nx/(W-1);
4173 *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
4174 if(textureH[kind] < H*squareSize)
4175 *y0 = (textureH[kind] - squareSize) * ny/(H-1);
4177 *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
4181 static void BlankSquare(x, y, color, piece, dest, fac)
4182 int x, y, color, fac;
4185 { // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
4187 if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
4188 XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
4189 squareSize, squareSize, x*fac, y*fac);
4191 if (useImages && useImageSqs) {
4195 pm = xpmLightSquare;
4200 case 2: /* neutral */
4205 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4206 squareSize, squareSize, x*fac, y*fac);
4216 case 2: /* neutral */
4221 XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
4226 I split out the routines to draw a piece so that I could
4227 make a generic flash routine.
4229 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4231 int square_color, x, y;
4234 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4235 switch (square_color) {
4237 case 2: /* neutral */
4239 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4240 ? *pieceToOutline(piece)
4241 : *pieceToSolid(piece),
4242 dest, bwPieceGC, 0, 0,
4243 squareSize, squareSize, x, y);
4246 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4247 ? *pieceToSolid(piece)
4248 : *pieceToOutline(piece),
4249 dest, wbPieceGC, 0, 0,
4250 squareSize, squareSize, x, y);
4255 static void monoDrawPiece(piece, square_color, x, y, dest)
4257 int square_color, x, y;
4260 switch (square_color) {
4262 case 2: /* neutral */
4264 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4265 ? *pieceToOutline(piece)
4266 : *pieceToSolid(piece),
4267 dest, bwPieceGC, 0, 0,
4268 squareSize, squareSize, x, y, 1);
4271 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn