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 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. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
147 #include <X11/Xmu/Atoms.h>
149 #include <X11/Xaw3d/Dialog.h>
150 #include <X11/Xaw3d/Form.h>
151 #include <X11/Xaw3d/List.h>
152 #include <X11/Xaw3d/Label.h>
153 #include <X11/Xaw3d/SimpleMenu.h>
154 #include <X11/Xaw3d/SmeBSB.h>
155 #include <X11/Xaw3d/SmeLine.h>
156 #include <X11/Xaw3d/Box.h>
157 #include <X11/Xaw3d/MenuButton.h>
158 #include <X11/Xaw3d/Text.h>
159 #include <X11/Xaw3d/AsciiText.h>
161 #include <X11/Xaw/Dialog.h>
162 #include <X11/Xaw/Form.h>
163 #include <X11/Xaw/List.h>
164 #include <X11/Xaw/Label.h>
165 #include <X11/Xaw/SimpleMenu.h>
166 #include <X11/Xaw/SmeBSB.h>
167 #include <X11/Xaw/SmeLine.h>
168 #include <X11/Xaw/Box.h>
169 #include <X11/Xaw/MenuButton.h>
170 #include <X11/Xaw/Text.h>
171 #include <X11/Xaw/AsciiText.h>
174 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
179 #include "pixmaps/pixmaps.h"
180 #define IMAGE_EXT "xpm"
182 #define IMAGE_EXT "xim"
183 #include "bitmaps/bitmaps.h"
186 #include "bitmaps/icon_white.bm"
187 #include "bitmaps/icon_black.bm"
188 #include "bitmaps/checkmark.bm"
190 #include "frontend.h"
195 #include "xgamelist.h"
196 #include "xhistory.h"
197 #include "xedittags.h"
200 // must be moved to xengineoutput.h
202 void EngineOutputProc P((Widget w, XEvent *event,
203 String *prms, Cardinal *nprms));
204 void EvalGraphProc P((Widget w, XEvent *event,
205 String *prms, Cardinal *nprms));
212 #define usleep(t) _sleep2(((t)+500)/1000)
216 # define _(s) gettext (s)
217 # define N_(s) gettext_noop (s)
233 int main P((int argc, char **argv));
234 RETSIGTYPE CmailSigHandler P((int sig));
235 RETSIGTYPE IntSigHandler P((int sig));
236 RETSIGTYPE TermSizeSigHandler P((int sig));
237 void CreateGCs P((void));
238 void CreateXIMPieces P((void));
239 void CreateXPMPieces P((void));
240 void CreatePieces P((void));
241 void CreatePieceMenus P((void));
242 Widget CreateMenuBar P((Menu *mb));
243 Widget CreateButtonBar P ((MenuItem *mi));
244 char *FindFont P((char *pattern, int targetPxlSize));
245 void PieceMenuPopup P((Widget w, XEvent *event,
246 String *params, Cardinal *num_params));
247 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
248 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
249 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
250 u_int wreq, u_int hreq));
251 void CreateGrid P((void));
252 int EventToSquare P((int x, int limit));
253 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
254 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
255 void HandleUserMove P((Widget w, XEvent *event,
256 String *prms, Cardinal *nprms));
257 void AnimateUserMove P((Widget w, XEvent * event,
258 String * params, Cardinal * nParams));
259 void HandlePV P((Widget w, XEvent * event,
260 String * params, Cardinal * nParams));
261 void WhiteClock P((Widget w, XEvent *event,
262 String *prms, Cardinal *nprms));
263 void BlackClock P((Widget w, XEvent *event,
264 String *prms, Cardinal *nprms));
265 void DrawPositionProc P((Widget w, XEvent *event,
266 String *prms, Cardinal *nprms));
267 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
269 void CommentPopUp P((char *title, char *label));
270 void CommentPopDown P((void));
271 void CommentCallback P((Widget w, XtPointer client_data,
272 XtPointer call_data));
273 void ICSInputBoxPopUp P((void));
274 void ICSInputBoxPopDown P((void));
275 void FileNamePopUp P((char *label, char *def,
276 FileProc proc, char *openMode));
277 void FileNamePopDown P((void));
278 void FileNameCallback P((Widget w, XtPointer client_data,
279 XtPointer call_data));
280 void FileNameAction P((Widget w, XEvent *event,
281 String *prms, Cardinal *nprms));
282 void AskQuestionReplyAction P((Widget w, XEvent *event,
283 String *prms, Cardinal *nprms));
284 void AskQuestionProc P((Widget w, XEvent *event,
285 String *prms, Cardinal *nprms));
286 void AskQuestionPopDown P((void));
287 void PromotionPopDown P((void));
288 void PromotionCallback P((Widget w, XtPointer client_data,
289 XtPointer call_data));
290 void EditCommentPopDown P((void));
291 void EditCommentCallback P((Widget w, XtPointer client_data,
292 XtPointer call_data));
293 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
294 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
295 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
296 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
298 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
300 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
302 void LoadPositionProc P((Widget w, XEvent *event,
303 String *prms, Cardinal *nprms));
304 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
306 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
308 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
310 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
312 void PastePositionProc P((Widget w, XEvent *event, String *prms,
314 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void SavePositionProc P((Widget w, XEvent *event,
318 String *prms, Cardinal *nprms));
319 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
322 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
326 void MachineWhiteProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void AnalyzeModeProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void AnalyzeFileProc P((Widget w, XEvent *event,
331 String *prms, Cardinal *nprms));
332 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
334 void IcsClientProc P((Widget w, XEvent *event, String *prms,
336 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditPositionProc P((Widget w, XEvent *event,
338 String *prms, Cardinal *nprms));
339 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
340 void EditCommentProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void IcsInputBoxProc P((Widget w, XEvent *event,
343 String *prms, Cardinal *nprms));
344 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
355 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
356 void StopObservingProc P((Widget w, XEvent *event, String *prms,
358 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
360 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
364 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
367 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
369 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
372 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
374 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
376 void AutocommProc P((Widget w, XEvent *event, String *prms,
378 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutobsProc P((Widget w, XEvent *event, String *prms,
382 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
384 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
387 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
388 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
390 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
392 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
394 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
398 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
400 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
402 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
404 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
406 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
407 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
408 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
410 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
412 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
414 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
416 void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
423 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
424 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
425 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
426 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
427 void DisplayMove P((int moveNumber));
428 void DisplayTitle P((char *title));
429 void ICSInitScript P((void));
430 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
431 void ErrorPopUp P((char *title, char *text, int modal));
432 void ErrorPopDown P((void));
433 static char *ExpandPathName P((char *path));
434 static void CreateAnimVars P((void));
435 static void DragPieceMove P((int x, int y));
436 static void DrawDragPiece P((void));
437 char *ModeToWidgetName P((GameMode mode));
438 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
445 void ShufflePopDown P(());
446 void EnginePopDown P(());
447 void UciPopDown P(());
448 void TimeControlPopDown P(());
449 void NewVariantPopDown P(());
450 void SettingsPopDown P(());
451 void update_ics_width P(());
452 int get_term_width P(());
453 int CopyMemoProc P(());
455 * XBoard depends on Xt R4 or higher
457 int xtVersion = XtSpecificationRelease;
462 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
463 jailSquareColor, highlightSquareColor, premoveHighlightColor;
464 Pixel lowTimeWarningColor;
465 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
466 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
467 wjPieceGC, bjPieceGC, prelineGC, countGC;
468 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
469 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
470 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
471 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
472 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
473 ICSInputShell, fileNameShell, askQuestionShell;
474 Widget historyShell, evalGraphShell, gameListShell;
475 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
476 XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
477 Font clockFontID, coordFontID, countFontID;
478 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
479 XtAppContext appContext;
481 char *oldICSInteractionTitle;
485 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
487 Position commentX = -1, commentY = -1;
488 Dimension commentW, commentH;
489 typedef unsigned int BoardSize;
491 Boolean chessProgram;
493 int minX, minY; // [HGM] placement: volatile limits on upper-left corner
494 int squareSize, smallLayout = 0, tinyLayout = 0,
495 marginW, marginH, // [HGM] for run-time resizing
496 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
497 ICSInputBoxUp = False, askQuestionUp = False,
498 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
499 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
500 Pixel timerForegroundPixel, timerBackgroundPixel;
501 Pixel buttonForegroundPixel, buttonBackgroundPixel;
502 char *chessDir, *programName, *programVersion,
503 *gameCopyFilename, *gamePasteFilename;
504 Boolean alwaysOnTop = False;
505 Boolean saveSettingsOnExit;
506 char *settingsFileName;
507 char *icsTextMenuString;
509 char *firstChessProgramNames;
510 char *secondChessProgramNames;
512 WindowPlacement wpMain;
513 WindowPlacement wpConsole;
514 WindowPlacement wpComment;
515 WindowPlacement wpMoveHistory;
516 WindowPlacement wpEvalGraph;
517 WindowPlacement wpEngineOutput;
518 WindowPlacement wpGameList;
519 WindowPlacement wpTags;
523 Pixmap pieceBitmap[2][(int)BlackPawn];
524 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
525 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
526 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
527 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
528 int useImages, useImageSqs;
529 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
530 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
531 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
532 XImage *ximLightSquare, *ximDarkSquare;
535 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
536 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
538 #define White(piece) ((int)(piece) < (int)BlackPawn)
540 /* Variables for doing smooth animation. This whole thing
541 would be much easier if the board was double-buffered,
542 but that would require a fairly major rewrite. */
547 GC blitGC, pieceGC, outlineGC;
548 XPoint startSquare, prevFrame, mouseDelta;
552 int startBoardX, startBoardY;
555 /* There can be two pieces being animated at once: a player
556 can begin dragging a piece before the remote opponent has moved. */
558 static AnimState game, player;
560 /* Bitmaps for use as masks when drawing XPM pieces.
561 Need one for each black and white piece. */
562 static Pixmap xpmMask[BlackKing + 1];
564 /* This magic number is the number of intermediate frames used
565 in each half of the animation. For short moves it's reduced
566 by 1. The total number of frames will be factor * 2 + 1. */
569 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
571 MenuItem fileMenu[] = {
572 {N_("New Game"), ResetProc},
573 {N_("New Shuffle Game ..."), ShuffleMenuProc},
574 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
575 {"----", NothingProc},
576 {N_("Load Game"), LoadGameProc},
577 {N_("Load Next Game"), LoadNextGameProc},
578 {N_("Load Previous Game"), LoadPrevGameProc},
579 {N_("Reload Same Game"), ReloadGameProc},
580 {N_("Save Game"), SaveGameProc},
581 {"----", NothingProc},
582 {N_("Copy Game"), CopyGameProc},
583 {N_("Paste Game"), PasteGameProc},
584 {"----", NothingProc},
585 {N_("Load Position"), LoadPositionProc},
586 {N_("Load Next Position"), LoadNextPositionProc},
587 {N_("Load Previous Position"), LoadPrevPositionProc},
588 {N_("Reload Same Position"), ReloadPositionProc},
589 {N_("Save Position"), SavePositionProc},
590 {"----", NothingProc},
591 {N_("Copy Position"), CopyPositionProc},
592 {N_("Paste Position"), PastePositionProc},
593 {"----", NothingProc},
594 {N_("Mail Move"), MailMoveProc},
595 {N_("Reload CMail Message"), ReloadCmailMsgProc},
596 {"----", NothingProc},
597 {N_("Exit"), QuitProc},
601 MenuItem modeMenu[] = {
602 {N_("Machine White"), MachineWhiteProc},
603 {N_("Machine Black"), MachineBlackProc},
604 {N_("Two Machines"), TwoMachinesProc},
605 {N_("Analysis Mode"), AnalyzeModeProc},
606 {N_("Analyze File"), AnalyzeFileProc },
607 {N_("ICS Client"), IcsClientProc},
608 {N_("Edit Game"), EditGameProc},
609 {N_("Edit Position"), EditPositionProc},
610 {N_("Training"), TrainingProc},
611 {"----", NothingProc},
612 {N_("Show Engine Output"), EngineOutputProc},
613 {N_("Show Evaluation Graph"), EvalGraphProc},
614 {N_("Show Game List"), ShowGameListProc},
615 {N_("Show Move History"), HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
616 {"----", NothingProc},
617 {N_("Edit Tags"), EditTagsProc},
618 {N_("Edit Comment"), EditCommentProc},
619 {N_("ICS Input Box"), IcsInputBoxProc},
620 {N_("Pause"), PauseProc},
624 MenuItem actionMenu[] = {
625 {N_("Accept"), AcceptProc},
626 {N_("Decline"), DeclineProc},
627 {N_("Rematch"), RematchProc},
628 {"----", NothingProc},
629 {N_("Call Flag"), CallFlagProc},
630 {N_("Draw"), DrawProc},
631 {N_("Adjourn"), AdjournProc},
632 {N_("Abort"), AbortProc},
633 {N_("Resign"), ResignProc},
634 {"----", NothingProc},
635 {N_("Stop Observing"), StopObservingProc},
636 {N_("Stop Examining"), StopExaminingProc},
637 {"----", NothingProc},
638 {N_("Adjudicate to White"), AdjuWhiteProc},
639 {N_("Adjudicate to Black"), AdjuBlackProc},
640 {N_("Adjudicate Draw"), AdjuDrawProc},
644 MenuItem stepMenu[] = {
645 {N_("Backward"), BackwardProc},
646 {N_("Forward"), ForwardProc},
647 {N_("Back to Start"), ToStartProc},
648 {N_("Forward to End"), ToEndProc},
649 {N_("Revert"), RevertProc},
650 {N_("Truncate Game"), TruncateGameProc},
651 {"----", NothingProc},
652 {N_("Move Now"), MoveNowProc},
653 {N_("Retract Move"), RetractMoveProc},
657 MenuItem optionsMenu[] = {
658 {N_("Flip View"), FlipViewProc},
659 {"----", NothingProc},
660 {N_("Adjudications ..."), EngineMenuProc},
661 {N_("General Settings ..."), UciMenuProc},
662 {N_("Engine #1 Settings ..."), FirstSettingsProc},
663 {N_("Engine #2 Settings ..."), SecondSettingsProc},
664 {N_("Time Control ..."), TimeControlProc},
665 {"----", NothingProc},
666 {N_("Always Queen"), AlwaysQueenProc},
667 {N_("Animate Dragging"), AnimateDraggingProc},
668 {N_("Animate Moving"), AnimateMovingProc},
669 {N_("Auto Comment"), AutocommProc},
670 {N_("Auto Flag"), AutoflagProc},
671 {N_("Auto Flip View"), AutoflipProc},
672 {N_("Auto Observe"), AutobsProc},
673 {N_("Auto Raise Board"), AutoraiseProc},
674 {N_("Auto Save"), AutosaveProc},
675 {N_("Blindfold"), BlindfoldProc},
676 {N_("Flash Moves"), FlashMovesProc},
677 {N_("Get Move List"), GetMoveListProc},
679 {N_("Highlight Dragging"), HighlightDraggingProc},
681 {N_("Highlight Last Move"), HighlightLastMoveProc},
682 {N_("Move Sound"), MoveSoundProc},
683 {N_("ICS Alarm"), IcsAlarmProc},
684 {N_("Old Save Style"), OldSaveStyleProc},
685 {N_("Periodic Updates"), PeriodicUpdatesProc},
686 {N_("Ponder Next Move"), PonderNextMoveProc},
687 {N_("Popup Exit Message"), PopupExitMessageProc},
688 {N_("Popup Move Errors"), PopupMoveErrorsProc},
689 {N_("Premove"), PremoveProc},
690 {N_("Quiet Play"), QuietPlayProc},
691 {N_("Show Coords"), ShowCoordsProc},
692 {N_("Hide Thinking"), HideThinkingProc},
693 {N_("Test Legality"), TestLegalityProc},
694 {"----", NothingProc},
695 {N_("Save Settings Now"), SaveSettingsProc},
696 {N_("Save Settings on Exit"), SaveOnExitProc},
700 MenuItem helpMenu[] = {
701 {N_("Info XBoard"), InfoProc},
702 {N_("Man XBoard"), ManProc},
703 {"----", NothingProc},
704 {N_("Hint"), HintProc},
705 {N_("Book"), BookProc},
706 {"----", NothingProc},
707 {N_("About XBoard"), AboutProc},
712 {N_("File"), fileMenu},
713 {N_("Mode"), modeMenu},
714 {N_("Action"), actionMenu},
715 {N_("Step"), stepMenu},
716 {N_("Options"), optionsMenu},
717 {N_("Help"), helpMenu},
721 #define PAUSE_BUTTON N_("P")
722 MenuItem buttonBar[] = {
725 {PAUSE_BUTTON, PauseProc},
731 #define PIECE_MENU_SIZE 18
732 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
733 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
734 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
735 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
736 N_("Empty square"), N_("Clear board") },
737 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
738 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
739 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
740 N_("Empty square"), N_("Clear board") }
742 /* must be in same order as PieceMenuStrings! */
743 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
744 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
745 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
746 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
747 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
748 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
749 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
750 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
751 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
754 #define DROP_MENU_SIZE 6
755 String dropMenuStrings[DROP_MENU_SIZE] = {
756 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
758 /* must be in same order as PieceMenuStrings! */
759 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
760 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
761 WhiteRook, WhiteQueen
769 DropMenuEnables dmEnables[] = {
787 { XtNborderWidth, 0 },
788 { XtNdefaultDistance, 0 },
792 { XtNborderWidth, 0 },
793 { XtNresizable, (XtArgVal) True },
797 { XtNborderWidth, 0 },
803 { XtNjustify, (XtArgVal) XtJustifyRight },
804 { XtNlabel, (XtArgVal) "..." },
805 { XtNresizable, (XtArgVal) True },
806 { XtNresize, (XtArgVal) False }
809 Arg messageArgs[] = {
810 { XtNjustify, (XtArgVal) XtJustifyLeft },
811 { XtNlabel, (XtArgVal) "..." },
812 { XtNresizable, (XtArgVal) True },
813 { XtNresize, (XtArgVal) False }
817 { XtNborderWidth, 0 },
818 { XtNjustify, (XtArgVal) XtJustifyLeft }
821 XtResource clientResources[] = {
822 { "flashCount", "flashCount", XtRInt, sizeof(int),
823 XtOffset(AppDataPtr, flashCount), XtRImmediate,
824 (XtPointer) FLASH_COUNT },
827 XrmOptionDescRec shellOptions[] = {
828 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
829 { "-flash", "flashCount", XrmoptionNoArg, "3" },
830 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
833 XtActionsRec boardActions[] = {
834 { "DrawPosition", DrawPositionProc },
835 { "HandleUserMove", HandleUserMove },
836 { "AnimateUserMove", AnimateUserMove },
837 { "HandlePV", HandlePV },
838 { "UnLoadPV", UnLoadPV },
839 { "FileNameAction", FileNameAction },
840 { "AskQuestionProc", AskQuestionProc },
841 { "AskQuestionReplyAction", AskQuestionReplyAction },
842 { "PieceMenuPopup", PieceMenuPopup },
843 { "WhiteClock", WhiteClock },
844 { "BlackClock", BlackClock },
845 { "Iconify", Iconify },
846 { "ResetProc", ResetProc },
847 { "LoadGameProc", LoadGameProc },
848 { "LoadNextGameProc", LoadNextGameProc },
849 { "LoadPrevGameProc", LoadPrevGameProc },
850 { "LoadSelectedProc", LoadSelectedProc },
851 { "ReloadGameProc", ReloadGameProc },
852 { "LoadPositionProc", LoadPositionProc },
853 { "LoadNextPositionProc", LoadNextPositionProc },
854 { "LoadPrevPositionProc", LoadPrevPositionProc },
855 { "ReloadPositionProc", ReloadPositionProc },
856 { "CopyPositionProc", CopyPositionProc },
857 { "PastePositionProc", PastePositionProc },
858 { "CopyGameProc", CopyGameProc },
859 { "PasteGameProc", PasteGameProc },
860 { "SaveGameProc", SaveGameProc },
861 { "SavePositionProc", SavePositionProc },
862 { "MailMoveProc", MailMoveProc },
863 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
864 { "QuitProc", QuitProc },
865 { "MachineWhiteProc", MachineWhiteProc },
866 { "MachineBlackProc", MachineBlackProc },
867 { "AnalysisModeProc", AnalyzeModeProc },
868 { "AnalyzeFileProc", AnalyzeFileProc },
869 { "TwoMachinesProc", TwoMachinesProc },
870 { "IcsClientProc", IcsClientProc },
871 { "EditGameProc", EditGameProc },
872 { "EditPositionProc", EditPositionProc },
873 { "TrainingProc", EditPositionProc },
874 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
875 { "EvalGraphProc", EvalGraphProc}, // [HGM] Winboard_x avaluation graph window
876 { "ShowGameListProc", ShowGameListProc },
877 { "ShowMoveListProc", HistoryShowProc},
878 { "EditTagsProc", EditCommentProc },
879 { "EditCommentProc", EditCommentProc },
880 { "IcsAlarmProc", IcsAlarmProc },
881 { "IcsInputBoxProc", IcsInputBoxProc },
882 { "PauseProc", PauseProc },
883 { "AcceptProc", AcceptProc },
884 { "DeclineProc", DeclineProc },
885 { "RematchProc", RematchProc },
886 { "CallFlagProc", CallFlagProc },
887 { "DrawProc", DrawProc },
888 { "AdjournProc", AdjournProc },
889 { "AbortProc", AbortProc },
890 { "ResignProc", ResignProc },
891 { "AdjuWhiteProc", AdjuWhiteProc },
892 { "AdjuBlackProc", AdjuBlackProc },
893 { "AdjuDrawProc", AdjuDrawProc },
894 { "EnterKeyProc", EnterKeyProc },
895 { "StopObservingProc", StopObservingProc },
896 { "StopExaminingProc", StopExaminingProc },
897 { "BackwardProc", BackwardProc },
898 { "ForwardProc", ForwardProc },
899 { "ToStartProc", ToStartProc },
900 { "ToEndProc", ToEndProc },
901 { "RevertProc", RevertProc },
902 { "TruncateGameProc", TruncateGameProc },
903 { "MoveNowProc", MoveNowProc },
904 { "RetractMoveProc", RetractMoveProc },
905 { "AlwaysQueenProc", AlwaysQueenProc },
906 { "AnimateDraggingProc", AnimateDraggingProc },
907 { "AnimateMovingProc", AnimateMovingProc },
908 { "AutoflagProc", AutoflagProc },
909 { "AutoflipProc", AutoflipProc },
910 { "AutobsProc", AutobsProc },
911 { "AutoraiseProc", AutoraiseProc },
912 { "AutosaveProc", AutosaveProc },
913 { "BlindfoldProc", BlindfoldProc },
914 { "FlashMovesProc", FlashMovesProc },
915 { "FlipViewProc", FlipViewProc },
916 { "GetMoveListProc", GetMoveListProc },
918 { "HighlightDraggingProc", HighlightDraggingProc },
920 { "HighlightLastMoveProc", HighlightLastMoveProc },
921 { "IcsAlarmProc", IcsAlarmProc },
922 { "MoveSoundProc", MoveSoundProc },
923 { "OldSaveStyleProc", OldSaveStyleProc },
924 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
925 { "PonderNextMoveProc", PonderNextMoveProc },
926 { "PopupExitMessageProc", PopupExitMessageProc },
927 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
928 { "PremoveProc", PremoveProc },
929 { "QuietPlayProc", QuietPlayProc },
930 { "ShowCoordsProc", ShowCoordsProc },
931 { "ShowThinkingProc", ShowThinkingProc },
932 { "HideThinkingProc", HideThinkingProc },
933 { "TestLegalityProc", TestLegalityProc },
934 { "SaveSettingsProc", SaveSettingsProc },
935 { "SaveOnExitProc", SaveOnExitProc },
936 { "InfoProc", InfoProc },
937 { "ManProc", ManProc },
938 { "HintProc", HintProc },
939 { "BookProc", BookProc },
940 { "AboutGameProc", AboutGameProc },
941 { "AboutProc", AboutProc },
942 { "DebugProc", DebugProc },
943 { "NothingProc", NothingProc },
944 { "CommentPopDown", (XtActionProc) CommentPopDown },
945 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
946 { "TagsPopDown", (XtActionProc) TagsPopDown },
947 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
948 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
949 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
950 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
951 { "GameListPopDown", (XtActionProc) GameListPopDown },
952 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
953 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
954 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
955 { "EvalGraphPopDown", (XtActionProc) EvalGraphPopDown },
956 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
957 { "EnginePopDown", (XtActionProc) EnginePopDown },
958 { "UciPopDown", (XtActionProc) UciPopDown },
959 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
960 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
961 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
962 { "CopyMemoProc", (XtActionProc) CopyMemoProc },
965 char globalTranslations[] =
966 ":<Key>R: ResignProc() \n \
967 :<Key>r: ResetProc() \n \
968 :<Key>g: LoadGameProc() \n \
969 :<Key>N: LoadNextGameProc() \n \
970 :<Key>P: LoadPrevGameProc() \n \
971 :<Key>Q: QuitProc() \n \
972 :<Key>F: ToEndProc() \n \
973 :<Key>f: ForwardProc() \n \
974 :<Key>B: ToStartProc() \n \
975 :<Key>b: BackwardProc() \n \
976 :<Key>p: PauseProc() \n \
977 :<Key>d: DrawProc() \n \
978 :<Key>t: CallFlagProc() \n \
979 :<Key>i: Iconify() \n \
980 :<Key>c: Iconify() \n \
981 :<Key>v: FlipViewProc() \n \
982 <KeyDown>Control_L: BackwardProc() \n \
983 <KeyUp>Control_L: ForwardProc() \n \
984 <KeyDown>Control_R: BackwardProc() \n \
985 <KeyUp>Control_R: ForwardProc() \n \
986 Shift<Key>1: AskQuestionProc(\"Direct command\",\
987 \"Send to chess program:\",,1) \n \
988 Shift<Key>2: AskQuestionProc(\"Direct command\",\
989 \"Send to second chess program:\",,2) \n";
991 char boardTranslations[] =
992 "<Btn1Down>: HandleUserMove() \n \
993 <Btn1Up>: HandleUserMove() \n \
994 <Btn1Motion>: AnimateUserMove() \n \
995 <Btn3Motion>: HandlePV() \n \
996 <Btn3Up>: UnLoadPV() \n \
997 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
998 PieceMenuPopup(menuB) \n \
999 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1000 PieceMenuPopup(menuW) \n \
1001 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1002 PieceMenuPopup(menuW) \n \
1003 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1004 PieceMenuPopup(menuB) \n";
1006 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1007 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1009 char ICSInputTranslations[] =
1010 "<Key>Return: EnterKeyProc() \n";
1012 String xboardResources[] = {
1013 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1014 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1015 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1020 /* Max possible square size */
1021 #define MAXSQSIZE 256
1023 static int xpm_avail[MAXSQSIZE];
1025 #ifdef HAVE_DIR_STRUCT
1027 /* Extract piece size from filename */
1029 xpm_getsize(name, len, ext)
1040 if ((p=strchr(name, '.')) == NULL ||
1041 StrCaseCmp(p+1, ext) != 0)
1047 while (*p && isdigit(*p))
1054 /* Setup xpm_avail */
1056 xpm_getavail(dirname, ext)
1064 for (i=0; i<MAXSQSIZE; ++i)
1067 if (appData.debugMode)
1068 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1070 dir = opendir(dirname);
1073 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1074 programName, dirname);
1078 while ((ent=readdir(dir)) != NULL) {
1079 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1080 if (i > 0 && i < MAXSQSIZE)
1090 xpm_print_avail(fp, ext)
1096 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1097 for (i=1; i<MAXSQSIZE; ++i) {
1103 /* Return XPM piecesize closest to size */
1105 xpm_closest_to(dirname, size, ext)
1111 int sm_diff = MAXSQSIZE;
1115 xpm_getavail(dirname, ext);
1117 if (appData.debugMode)
1118 xpm_print_avail(stderr, ext);
1120 for (i=1; i<MAXSQSIZE; ++i) {
1123 diff = (diff<0) ? -diff : diff;
1124 if (diff < sm_diff) {
1132 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1138 #else /* !HAVE_DIR_STRUCT */
1139 /* If we are on a system without a DIR struct, we can't
1140 read the directory, so we can't collect a list of
1141 filenames, etc., so we can't do any size-fitting. */
1143 xpm_closest_to(dirname, size, ext)
1148 fprintf(stderr, _("\
1149 Warning: No DIR structure found on this system --\n\
1150 Unable to autosize for XPM/XIM pieces.\n\
1151 Please report this error to frankm@hiwaay.net.\n\
1152 Include system type & operating system in message.\n"));
1155 #endif /* HAVE_DIR_STRUCT */
1157 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1158 "magenta", "cyan", "white" };
1162 TextColors textColors[(int)NColorClasses];
1164 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1166 parse_color(str, which)
1170 char *p, buf[100], *d;
1173 if (strlen(str) > 99) /* watch bounds on buf */
1178 for (i=0; i<which; ++i) {
1185 /* Could be looking at something like:
1187 .. in which case we want to stop on a comma also */
1188 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1192 return -1; /* Use default for empty field */
1195 if (which == 2 || isdigit(*p))
1198 while (*p && isalpha(*p))
1203 for (i=0; i<8; ++i) {
1204 if (!StrCaseCmp(buf, cnames[i]))
1205 return which? (i+40) : (i+30);
1207 if (!StrCaseCmp(buf, "default")) return -1;
1209 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1214 parse_cpair(cc, str)
1218 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1219 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1224 /* bg and attr are optional */
1225 textColors[(int)cc].bg = parse_color(str, 1);
1226 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1227 textColors[(int)cc].attr = 0;
1233 /* Arrange to catch delete-window events */
1234 Atom wm_delete_window;
1236 CatchDeleteWindow(Widget w, String procname)
1239 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1240 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1241 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1248 XtSetArg(args[0], XtNiconic, False);
1249 XtSetValues(shellWidget, args, 1);
1251 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1254 //---------------------------------------------------------------------------------------------------------
1255 // some symbol definitions to provide the proper (= XBoard) context for the code in args.h
1258 #define CW_USEDEFAULT (1<<31)
1259 #define ICS_TEXT_MENU_SIZE 90
1260 #define DEBUG_FILE "xboard.debug"
1261 #define SetCurrentDirectory chdir
1262 #define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
1266 // these two must some day move to frontend.h, when they are implemented
1267 Boolean GameListIsUp();
1269 // The option definition and parsing code common to XBoard and WinBoard is collected in this file
1272 // front-end part of option handling
1274 // [HGM] This platform-dependent table provides the location for storing the color info
1275 extern char *crWhite, * crBlack;
1279 &appData.whitePieceColor,
1280 &appData.blackPieceColor,
1281 &appData.lightSquareColor,
1282 &appData.darkSquareColor,
1283 &appData.highlightSquareColor,
1284 &appData.premoveHighlightColor,
1297 ParseFont(char *name, int number)
1298 { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
1300 case 0: // CLOCK_FONT
1301 appData.clockFont = strdup(name);
1303 case 1: // MESSAGE_FONT
1304 appData.font = strdup(name);
1306 case 2: // COORD_FONT
1307 appData.coordFont = strdup(name);
1316 { // only 2 fonts currently
1317 appData.clockFont = CLOCK_FONT_NAME;
1318 appData.coordFont = COORD_FONT_NAME;
1319 appData.font = DEFAULT_FONT_NAME;
1324 { // no-op, until we identify the code for this already in XBoard and move it here
1328 ParseColor(int n, char *name)
1329 { // in XBoard, just copy the color-name string
1330 if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
1334 ParseTextAttribs(ColorClass cc, char *s)
1336 (&appData.colorShout)[cc] = strdup(s);
1340 ParseBoardSize(void *addr, char *name)
1342 appData.boardSize = strdup(name);
1347 { // In XBoard the sound-playing program takes care of obtaining the actual sound
1351 SetCommPortDefaults()
1352 { // for now, this is a no-op, as the corresponding option does not exist in XBoard
1355 // [HGM] args: these three cases taken out to stay in front-end
1357 SaveFontArg(FILE *f, ArgDescriptor *ad)
1360 switch((int)ad->argLoc) {
1361 case 0: // CLOCK_FONT
1362 name = appData.clockFont;
1364 case 1: // MESSAGE_FONT
1365 name = appData.font;
1367 case 2: // COORD_FONT
1368 name = appData.coordFont;
1373 // Do not save fonts for now, as the saved font would be board-size specific
1374 // and not suitable for a re-start at another board size
1375 // fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, name);
1380 { // nothing to do, as the sounds are at all times represented by their text-string names already
1384 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
1385 { // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
1386 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
1390 SaveColor(FILE *f, ArgDescriptor *ad)
1391 { // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
1392 if(colorVariable[(int)ad->argLoc])
1393 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
1397 SaveBoardSize(FILE *f, char *name, void *addr)
1398 { // wrapper to shield back-end from BoardSize & sizeInfo
1399 fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
1403 ParseCommPortSettings(char *s)
1404 { // no such option in XBoard (yet)
1407 extern Widget engineOutputShell;
1408 extern Widget tagsShell, editTagsShell;
1410 GetActualPlacement(Widget wg, WindowPlacement *wp)
1420 XtSetArg(args[i], XtNx, &x); i++;
1421 XtSetArg(args[i], XtNy, &y); i++;
1422 XtSetArg(args[i], XtNwidth, &w); i++;
1423 XtSetArg(args[i], XtNheight, &h); i++;
1424 XtGetValues(wg, args, i);
1433 { // wrapper to shield use of window handles from back-end (make addressible by number?)
1434 // In XBoard this will have to wait until awareness of window parameters is implemented
1435 GetActualPlacement(shellWidget, &wpMain);
1436 if(EngineOutputIsUp()) GetActualPlacement(engineOutputShell, &wpEngineOutput); else
1437 if(MoveHistoryIsUp()) GetActualPlacement(historyShell, &wpMoveHistory);
1438 if(EvalGraphIsUp()) GetActualPlacement(evalGraphShell, &wpEvalGraph);
1439 if(GameListIsUp()) GetActualPlacement(gameListShell, &wpGameList);
1440 if(commentShell) GetActualPlacement(commentShell, &wpComment);
1441 else GetActualPlacement(editShell, &wpComment);
1442 if(tagsShell) GetActualPlacement(tagsShell, &wpTags);
1443 else GetActualPlacement(editTagsShell, &wpTags);
1447 PrintCommPortSettings(FILE *f, char *name)
1448 { // This option does not exist in XBoard
1452 MySearchPath(char *installDir, char *name, char *fullname)
1453 { // just append installDir and name. Perhaps ExpandPath should be used here?
1454 name = ExpandPathName(name);
1455 if(name && name[0] == '/') strcpy(fullname, name); else {
1456 sprintf(fullname, "%s%c%s", installDir, '/', name);
1462 MyGetFullPathName(char *name, char *fullname)
1463 { // should use ExpandPath?
1464 name = ExpandPathName(name);
1465 strcpy(fullname, name);
1470 EnsureOnScreen(int *x, int *y, int minX, int minY)
1477 { // [HGM] args: allows testing if main window is realized from back-end
1478 return xBoardWindow != 0;
1482 PopUpStartupDialog()
1483 { // start menu not implemented in XBoard
1486 ConvertToLine(int argc, char **argv)
1488 static char line[128*1024], buf[1024];
1492 for(i=1; i<argc; i++) {
1493 if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') )
1494 && argv[i][0] != '{' )
1495 sprintf(buf, "{%s} ", argv[i]);
1496 else sprintf(buf, "%s ", argv[i]);
1499 line[strlen(line)-1] = NULLCHAR;
1503 //--------------------------------------------------------------------------------------------
1506 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
1508 #define BoardSize int
1509 void InitDrawingSizes(BoardSize boardSize, int flags)
1510 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1511 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1513 XtGeometryResult gres;
1516 if(!formWidget) return;
1519 * Enable shell resizing.
1521 shellArgs[0].value = (XtArgVal) &w;
1522 shellArgs[1].value = (XtArgVal) &h;
1523 XtGetValues(shellWidget, shellArgs, 2);
1525 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
1526 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
1527 XtSetValues(shellWidget, &shellArgs[2], 4);
1529 XtSetArg(args[0], XtNdefaultDistance, &sep);
1530 XtGetValues(formWidget, args, 1);
1532 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1533 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1536 XtSetArg(args[0], XtNwidth, boardWidth);
1537 XtSetArg(args[1], XtNheight, boardHeight);
1538 XtSetValues(boardWidget, args, 2);
1540 timerWidth = (boardWidth - sep) / 2;
1541 XtSetArg(args[0], XtNwidth, timerWidth);
1542 XtSetValues(whiteTimerWidget, args, 1);
1543 XtSetValues(blackTimerWidget, args, 1);
1545 XawFormDoLayout(formWidget, False);
1547 if (appData.titleInWindow) {
1549 XtSetArg(args[i], XtNborderWidth, &bor); i++;
1550 XtSetArg(args[i], XtNheight, &h); i++;
1551 XtGetValues(titleWidget, args, i);
1553 w = boardWidth - 2*bor;
1555 XtSetArg(args[0], XtNwidth, &w);
1556 XtGetValues(menuBarWidget, args, 1);
1557 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1560 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
1561 if (gres != XtGeometryYes && appData.debugMode) {
1563 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
1564 programName, gres, w, h, wr, hr);
1568 XawFormDoLayout(formWidget, True);
1571 * Inhibit shell resizing.
1573 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
1574 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
1575 shellArgs[4].value = shellArgs[2].value = w;
1576 shellArgs[5].value = shellArgs[3].value = h;
1577 XtSetValues(shellWidget, &shellArgs[0], 6);
1579 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
1582 for(i=0; i<4; i++) {
1584 for(p=0; p<=(int)WhiteKing; p++)
1585 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
1586 if(gameInfo.variant == VariantShogi) {
1587 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
1588 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
1589 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
1590 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
1591 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
1594 if(gameInfo.variant == VariantGothic) {
1595 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
1599 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
1600 for(p=0; p<=(int)WhiteKing; p++)
1601 ximMaskPm[p] = ximMaskPm2[p]; // defaults
1602 if(gameInfo.variant == VariantShogi) {
1603 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
1604 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
1605 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
1606 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
1607 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
1610 if(gameInfo.variant == VariantGothic) {
1611 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
1617 for(i=0; i<2; i++) {
1619 for(p=0; p<=(int)WhiteKing; p++)
1620 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
1621 if(gameInfo.variant == VariantShogi) {
1622 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
1623 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
1624 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
1625 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
1626 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
1629 if(gameInfo.variant == VariantGothic) {
1630 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
1641 void EscapeExpand(char *p, char *q)
1642 { // [HGM] initstring: routine to shape up string arguments
1643 while(*p++ = *q++) if(p[-1] == '\\')
1645 case 'n': p[-1] = '\n'; break;
1646 case 'r': p[-1] = '\r'; break;
1647 case 't': p[-1] = '\t'; break;
1648 case '\\': p[-1] = '\\'; break;
1649 case 0: *p = 0; return;
1650 default: p[-1] = q[-1]; break;
1659 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1660 XSetWindowAttributes window_attributes;
1662 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1663 XrmValue vFrom, vTo;
1664 XtGeometryResult gres;
1667 int forceMono = False;
1669 srandom(time(0)); // [HGM] book: make random truly random
1671 setbuf(stdout, NULL);
1672 setbuf(stderr, NULL);
1675 if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
1676 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1680 programName = strrchr(argv[0], '/');
1681 if (programName == NULL)
1682 programName = argv[0];
1687 XtSetLanguageProc(NULL, NULL, NULL);
1688 bindtextdomain(PACKAGE, LOCALEDIR);
1689 textdomain(PACKAGE);
1693 XtAppInitialize(&appContext, "XBoard", shellOptions,
1694 XtNumber(shellOptions),
1695 &argc, argv, xboardResources, NULL, 0);
1696 appData.boardSize = "";
1697 InitAppData(ConvertToLine(argc, argv));
1699 if (p == NULL) p = "/tmp";
1700 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1701 gameCopyFilename = (char*) malloc(i);
1702 gamePasteFilename = (char*) malloc(i);
1703 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
1704 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
1706 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1707 clientResources, XtNumber(clientResources),
1710 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
1711 static char buf[MSG_SIZ];
1712 EscapeExpand(buf, appData.initString);
1713 appData.initString = strdup(buf);
1714 EscapeExpand(buf, appData.secondInitString);
1715 appData.secondInitString = strdup(buf);
1716 EscapeExpand(buf, appData.firstComputerString);
1717 appData.firstComputerString = strdup(buf);
1718 EscapeExpand(buf, appData.secondComputerString);
1719 appData.secondComputerString = strdup(buf);
1722 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1725 if (chdir(chessDir) != 0) {
1726 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1732 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
1733 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
1734 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
1735 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
1738 setbuf(debugFP, NULL);
1741 /* [HGM,HR] make sure board size is acceptable */
1742 if(appData.NrFiles > BOARD_FILES ||
1743 appData.NrRanks > BOARD_RANKS )
1744 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
1747 /* This feature does not work; animation needs a rewrite */
1748 appData.highlightDragging = FALSE;
1752 xDisplay = XtDisplay(shellWidget);
1753 xScreen = DefaultScreen(xDisplay);
1754 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1756 gameInfo.variant = StringToVariant(appData.variant);
1757 InitPosition(FALSE);
1760 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
1762 if (isdigit(appData.boardSize[0])) {
1763 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1764 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1765 &fontPxlSize, &smallLayout, &tinyLayout);
1767 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1768 programName, appData.boardSize);
1772 /* Find some defaults; use the nearest known size */
1773 SizeDefaults *szd, *nearest;
1774 int distance = 99999;
1775 nearest = szd = sizeDefaults;
1776 while (szd->name != NULL) {
1777 if (abs(szd->squareSize - squareSize) < distance) {
1779 distance = abs(szd->squareSize - squareSize);
1780 if (distance == 0) break;
1784 if (i < 2) lineGap = nearest->lineGap;
1785 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1786 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1787 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1788 if (i < 6) smallLayout = nearest->smallLayout;
1789 if (i < 7) tinyLayout = nearest->tinyLayout;
1792 SizeDefaults *szd = sizeDefaults;
1793 if (*appData.boardSize == NULLCHAR) {
1794 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1795 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1798 if (szd->name == NULL) szd--;
1799 appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
1801 while (szd->name != NULL &&
1802 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1803 if (szd->name == NULL) {
1804 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1805 programName, appData.boardSize);
1809 squareSize = szd->squareSize;
1810 lineGap = szd->lineGap;
1811 clockFontPxlSize = szd->clockFontPxlSize;
1812 coordFontPxlSize = szd->coordFontPxlSize;
1813 fontPxlSize = szd->fontPxlSize;
1814 smallLayout = szd->smallLayout;
1815 tinyLayout = szd->tinyLayout;
1818 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1819 if (strlen(appData.pixmapDirectory) > 0) {
1820 p = ExpandPathName(appData.pixmapDirectory);
1822 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1823 appData.pixmapDirectory);
1826 if (appData.debugMode) {
1827 fprintf(stderr, _("\
1828 XBoard square size (hint): %d\n\
1829 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1831 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1832 if (appData.debugMode) {
1833 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1837 /* [HR] height treated separately (hacked) */
1838 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1839 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1840 if (appData.showJail == 1) {
1841 /* Jail on top and bottom */
1842 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1843 XtSetArg(boardArgs[2], XtNheight,
1844 boardHeight + 2*(lineGap + squareSize));
1845 } else if (appData.showJail == 2) {
1847 XtSetArg(boardArgs[1], XtNwidth,
1848 boardWidth + 2*(lineGap + squareSize));
1849 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1852 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1853 XtSetArg(boardArgs[2], XtNheight, boardHeight);
1857 * Determine what fonts to use.
1859 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1860 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1861 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1862 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1863 coordFontID = XLoadFont(xDisplay, appData.coordFont);
1864 coordFontStruct = XQueryFont(xDisplay, coordFontID);
1865 appData.font = FindFont(appData.font, fontPxlSize);
1866 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
1867 countFontStruct = XQueryFont(xDisplay, countFontID);
1868 // appData.font = FindFont(appData.font, fontPxlSize);
1870 xdb = XtDatabase(xDisplay);
1871 XrmPutStringResource(&xdb, "*font", appData.font);
1874 * Detect if there are not enough colors available and adapt.
1876 if (DefaultDepth(xDisplay, xScreen) <= 2) {
1877 appData.monoMode = True;
1880 if (!appData.monoMode) {
1881 vFrom.addr = (caddr_t) appData.lightSquareColor;
1882 vFrom.size = strlen(appData.lightSquareColor);
1883 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1884 if (vTo.addr == NULL) {
1885 appData.monoMode = True;
1888 lightSquareColor = *(Pixel *) vTo.addr;
1891 if (!appData.monoMode) {
1892 vFrom.addr = (caddr_t) appData.darkSquareColor;
1893 vFrom.size = strlen(appData.darkSquareColor);
1894 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1895 if (vTo.addr == NULL) {
1896 appData.monoMode = True;
1899 darkSquareColor = *(Pixel *) vTo.addr;
1902 if (!appData.monoMode) {
1903 vFrom.addr = (caddr_t) appData.whitePieceColor;
1904 vFrom.size = strlen(appData.whitePieceColor);
1905 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1906 if (vTo.addr == NULL) {
1907 appData.monoMode = True;
1910 whitePieceColor = *(Pixel *) vTo.addr;
1913 if (!appData.monoMode) {
1914 vFrom.addr = (caddr_t) appData.blackPieceColor;
1915 vFrom.size = strlen(appData.blackPieceColor);
1916 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1917 if (vTo.addr == NULL) {
1918 appData.monoMode = True;
1921 blackPieceColor = *(Pixel *) vTo.addr;
1925 if (!appData.monoMode) {
1926 vFrom.addr = (caddr_t) appData.highlightSquareColor;
1927 vFrom.size = strlen(appData.highlightSquareColor);
1928 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1929 if (vTo.addr == NULL) {
1930 appData.monoMode = True;
1933 highlightSquareColor = *(Pixel *) vTo.addr;
1937 if (!appData.monoMode) {
1938 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
1939 vFrom.size = strlen(appData.premoveHighlightColor);
1940 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1941 if (vTo.addr == NULL) {
1942 appData.monoMode = True;
1945 premoveHighlightColor = *(Pixel *) vTo.addr;
1950 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
1953 if (appData.bitmapDirectory == NULL ||
1954 appData.bitmapDirectory[0] == NULLCHAR)
1955 appData.bitmapDirectory = DEF_BITMAP_DIR;
1958 if (appData.lowTimeWarning && !appData.monoMode) {
1959 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
1960 vFrom.size = strlen(appData.lowTimeWarningColor);
1961 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
1962 if (vTo.addr == NULL)
1963 appData.monoMode = True;
1965 lowTimeWarningColor = *(Pixel *) vTo.addr;
1968 if (appData.monoMode && appData.debugMode) {
1969 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
1970 (unsigned long) XWhitePixel(xDisplay, xScreen),
1971 (unsigned long) XBlackPixel(xDisplay, xScreen));
1974 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
1975 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
1976 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
1977 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
1978 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
1979 parse_cpair(ColorTell, appData.colorTell) < 0 ||
1980 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
1981 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
1982 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
1983 parse_cpair(ColorNormal, appData.colorNormal) < 0)
1985 if (appData.colorize) {
1987 _("%s: can't parse color names; disabling colorization\n"),
1990 appData.colorize = FALSE;
1992 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
1993 textColors[ColorNone].attr = 0;
1995 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2001 layoutName = "tinyLayout";
2002 } else if (smallLayout) {
2003 layoutName = "smallLayout";
2005 layoutName = "normalLayout";
2007 /* Outer layoutWidget is there only to provide a name for use in
2008 resources that depend on the layout style */
2010 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2011 layoutArgs, XtNumber(layoutArgs));
2013 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2014 formArgs, XtNumber(formArgs));
2015 XtSetArg(args[0], XtNdefaultDistance, &sep);
2016 XtGetValues(formWidget, args, 1);
2019 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2020 XtSetArg(args[0], XtNtop, XtChainTop);
2021 XtSetArg(args[1], XtNbottom, XtChainTop);
2022 XtSetArg(args[2], XtNright, XtChainLeft);
2023 XtSetValues(menuBarWidget, args, 3);
2025 widgetList[j++] = whiteTimerWidget =
2026 XtCreateWidget("whiteTime", labelWidgetClass,
2027 formWidget, timerArgs, XtNumber(timerArgs));
2028 XtSetArg(args[0], XtNfont, clockFontStruct);
2029 XtSetArg(args[1], XtNtop, XtChainTop);
2030 XtSetArg(args[2], XtNbottom, XtChainTop);
2031 XtSetValues(whiteTimerWidget, args, 3);
2033 widgetList[j++] = blackTimerWidget =
2034 XtCreateWidget("blackTime", labelWidgetClass,
2035 formWidget, timerArgs, XtNumber(timerArgs));
2036 XtSetArg(args[0], XtNfont, clockFontStruct);
2037 XtSetArg(args[1], XtNtop, XtChainTop);
2038 XtSetArg(args[2], XtNbottom, XtChainTop);
2039 XtSetValues(blackTimerWidget, args, 3);
2041 if (appData.titleInWindow) {
2042 widgetList[j++] = titleWidget =
2043 XtCreateWidget("title", labelWidgetClass, formWidget,
2044 titleArgs, XtNumber(titleArgs));
2045 XtSetArg(args[0], XtNtop, XtChainTop);
2046 XtSetArg(args[1], XtNbottom, XtChainTop);
2047 XtSetValues(titleWidget, args, 2);
2050 if (appData.showButtonBar) {
2051 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2052 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2053 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2054 XtSetArg(args[2], XtNtop, XtChainTop);
2055 XtSetArg(args[3], XtNbottom, XtChainTop);
2056 XtSetValues(buttonBarWidget, args, 4);
2059 widgetList[j++] = messageWidget =
2060 XtCreateWidget("message", labelWidgetClass, formWidget,
2061 messageArgs, XtNumber(messageArgs));
2062 XtSetArg(args[0], XtNtop, XtChainTop);
2063 XtSetArg(args[1], XtNbottom, XtChainTop);
2064 XtSetValues(messageWidget, args, 2);
2066 widgetList[j++] = boardWidget =
2067 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2068 XtNumber(boardArgs));
2070 XtManageChildren(widgetList, j);
2072 timerWidth = (boardWidth - sep) / 2;
2073 XtSetArg(args[0], XtNwidth, timerWidth);
2074 XtSetValues(whiteTimerWidget, args, 1);
2075 XtSetValues(blackTimerWidget, args, 1);
2077 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2078 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2079 XtGetValues(whiteTimerWidget, args, 2);
2081 if (appData.showButtonBar) {
2082 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2083 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2084 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2088 * formWidget uses these constraints but they are stored
2092 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2093 XtSetValues(menuBarWidget, args, i);
2094 if (appData.titleInWindow) {
2097 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2098 XtSetValues(whiteTimerWidget, args, i);
2100 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2101 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2102 XtSetValues(blackTimerWidget, args, i);
2104 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2105 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2106 XtSetValues(titleWidget, args, i);
2108 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2109 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2110 XtSetValues(messageWidget, args, i);
2111 if (appData.showButtonBar) {
2113 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2114 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2115 XtSetValues(buttonBarWidget, args, i);
2119 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2120 XtSetValues(whiteTimerWidget, args, i);
2122 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2123 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2124 XtSetValues(blackTimerWidget, args, i);
2126 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2127 XtSetValues(titleWidget, args, i);
2129 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2130 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2131 XtSetValues(messageWidget, args, i);
2132 if (appData.showButtonBar) {
2134 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2135 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2136 XtSetValues(buttonBarWidget, args, i);
2141 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2142 XtSetValues(whiteTimerWidget, args, i);
2144 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2145 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2146 XtSetValues(blackTimerWidget, args, i);
2148 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2149 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2150 XtSetValues(messageWidget, args, i);
2151 if (appData.showButtonBar) {
2153 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2154 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2155 XtSetValues(buttonBarWidget, args, i);
2159 XtSetArg(args[0], XtNfromVert, messageWidget);
2160 XtSetArg(args[1], XtNtop, XtChainTop);
2161 XtSetArg(args[2], XtNbottom, XtChainBottom);
2162 XtSetArg(args[3], XtNleft, XtChainLeft);
2163 XtSetArg(args[4], XtNright, XtChainRight);
2164 XtSetValues(boardWidget, args, 5);
2166 XtRealizeWidget(shellWidget);
2169 XtSetArg(args[0], XtNx, wpMain.x);
2170 XtSetArg(args[1], XtNy, wpMain.y);
2171 XtSetValues(shellWidget, args, 2);
2175 * Correct the width of the message and title widgets.
2176 * It is not known why some systems need the extra fudge term.
2177 * The value "2" is probably larger than needed.
2179 XawFormDoLayout(formWidget, False);
2181 #define WIDTH_FUDGE 2
2183 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2184 XtSetArg(args[i], XtNheight, &h); i++;
2185 XtGetValues(messageWidget, args, i);
2186 if (appData.showButtonBar) {
2188 XtSetArg(args[i], XtNwidth, &w); i++;
2189 XtGetValues(buttonBarWidget, args, i);
2190 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2192 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2195 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2196 if (gres != XtGeometryYes && appData.debugMode) {
2197 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2198 programName, gres, w, h, wr, hr);
2201 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2202 /* The size used for the child widget in layout lags one resize behind
2203 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2205 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2206 if (gres != XtGeometryYes && appData.debugMode) {
2207 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2208 programName, gres, w, h, wr, hr);
2211 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2212 XtSetArg(args[1], XtNright, XtChainRight);
2213 XtSetValues(messageWidget, args, 2);
2215 if (appData.titleInWindow) {
2217 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2218 XtSetArg(args[i], XtNheight, &h); i++;
2219 XtGetValues(titleWidget, args, i);
2221 w = boardWidth - 2*bor;
2223 XtSetArg(args[0], XtNwidth, &w);
2224 XtGetValues(menuBarWidget, args, 1);
2225 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2228 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2229 if (gres != XtGeometryYes && appData.debugMode) {
2231 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2232 programName, gres, w, h, wr, hr);
2235 XawFormDoLayout(formWidget, True);
2237 xBoardWindow = XtWindow(boardWidget);
2239 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2240 // not need to go into InitDrawingSizes().
2244 * Create X checkmark bitmap and initialize option menu checks.
2246 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2247 checkmark_bits, checkmark_width, checkmark_height);
2248 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2249 if (appData.alwaysPromoteToQueen) {
2250 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2253 if (appData.animateDragging) {
2254 XtSetValues(XtNameToWidget(menuBarWidget,
2255 "menuOptions.Animate Dragging"),
2258 if (appData.animate) {
2259 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2262 if (appData.autoComment) {
2263 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2266 if (appData.autoCallFlag) {
2267 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2270 if (appData.autoFlipView) {
2271 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2274 if (appData.autoObserve) {
2275 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2278 if (appData.autoRaiseBoard) {
2279 XtSetValues(XtNameToWidget(menuBarWidget,
2280 "menuOptions.Auto Raise Board"), args, 1);
2282 if (appData.autoSaveGames) {
2283 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2286 if (appData.saveGameFile[0] != NULLCHAR) {
2287 /* Can't turn this off from menu */
2288 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2290 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2294 if (appData.blindfold) {
2295 XtSetValues(XtNameToWidget(menuBarWidget,
2296 "menuOptions.Blindfold"), args, 1);
2298 if (appData.flashCount > 0) {
2299 XtSetValues(XtNameToWidget(menuBarWidget,
2300 "menuOptions.Flash Moves"),
2303 if (appData.getMoveList) {
2304 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2308 if (appData.highlightDragging) {
2309 XtSetValues(XtNameToWidget(menuBarWidget,
2310 "menuOptions.Highlight Dragging"),
2314 if (appData.highlightLastMove) {
2315 XtSetValues(XtNameToWidget(menuBarWidget,
2316 "menuOptions.Highlight Last Move"),
2319 if (appData.icsAlarm) {
2320 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2323 if (appData.ringBellAfterMoves) {
2324 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2327 if (appData.oldSaveStyle) {
2328 XtSetValues(XtNameToWidget(menuBarWidget,
2329 "menuOptions.Old Save Style"), args, 1);
2331 if (appData.periodicUpdates) {
2332 XtSetValues(XtNameToWidget(menuBarWidget,
2333 "menuOptions.Periodic Updates"), args, 1);
2335 if (appData.ponderNextMove) {
2336 XtSetValues(XtNameToWidget(menuBarWidget,
2337 "menuOptions.Ponder Next Move"), args, 1);
2339 if (appData.popupExitMessage) {
2340 XtSetValues(XtNameToWidget(menuBarWidget,
2341 "menuOptions.Popup Exit Message"), args, 1);
2343 if (appData.popupMoveErrors) {
2344 XtSetValues(XtNameToWidget(menuBarWidget,
2345 "menuOptions.Popup Move Errors"), args, 1);
2347 if (appData.premove) {
2348 XtSetValues(XtNameToWidget(menuBarWidget,
2349 "menuOptions.Premove"), args, 1);
2351 if (appData.quietPlay) {
2352 XtSetValues(XtNameToWidget(menuBarWidget,
2353 "menuOptions.Quiet Play"), args, 1);
2355 if (appData.showCoords) {
2356 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2359 if (appData.hideThinkingFromHuman) {
2360 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2363 if (appData.testLegality) {
2364 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2367 if (saveSettingsOnExit) {
2368 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"),
2375 ReadBitmap(&wIconPixmap, "icon_white.bm",
2376 icon_white_bits, icon_white_width, icon_white_height);
2377 ReadBitmap(&bIconPixmap, "icon_black.bm",
2378 icon_black_bits, icon_black_width, icon_black_height);
2379 iconPixmap = wIconPixmap;
2381 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2382 XtSetValues(shellWidget, args, i);
2385 * Create a cursor for the board widget.
2387 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2388 XChangeWindowAttributes(xDisplay, xBoardWindow,
2389 CWCursor, &window_attributes);
2392 * Inhibit shell resizing.
2394 shellArgs[0].value = (XtArgVal) &w;
2395 shellArgs[1].value = (XtArgVal) &h;
2396 XtGetValues(shellWidget, shellArgs, 2);
2397 shellArgs[4].value = shellArgs[2].value = w;
2398 shellArgs[5].value = shellArgs[3].value = h;
2399 XtSetValues(shellWidget, &shellArgs[2], 4);
2400 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2401 marginH = h - boardHeight;
2403 CatchDeleteWindow(shellWidget, "QuitProc");
2408 if (appData.bitmapDirectory[0] != NULLCHAR) {
2415 /* Create regular pieces */
2416 if (!useImages) CreatePieces();
2421 if (appData.animate || appData.animateDragging)
2424 XtAugmentTranslations(formWidget,
2425 XtParseTranslationTable(globalTranslations));
2426 XtAugmentTranslations(boardWidget,
2427 XtParseTranslationTable(boardTranslations));
2428 XtAugmentTranslations(whiteTimerWidget,
2429 XtParseTranslationTable(whiteTranslations));
2430 XtAugmentTranslations(blackTimerWidget,
2431 XtParseTranslationTable(blackTranslations));
2433 /* Why is the following needed on some versions of X instead
2434 * of a translation? */
2435 XtAddEventHandler(boardWidget, ExposureMask, False,
2436 (XtEventHandler) EventProc, NULL);
2439 /* [AS] Restore layout */
2440 if( wpMoveHistory.visible ) {
2444 if( wpEvalGraph.visible )
2449 if( wpEngineOutput.visible ) {
2450 EngineOutputPopUp();
2455 if (errorExitStatus == -1) {
2456 if (appData.icsActive) {
2457 /* We now wait until we see "login:" from the ICS before
2458 sending the logon script (problems with timestamp otherwise) */
2459 /*ICSInitScript();*/
2460 if (appData.icsInputBox) ICSInputBoxPopUp();
2464 signal(SIGWINCH, TermSizeSigHandler);
2466 signal(SIGINT, IntSigHandler);
2467 signal(SIGTERM, IntSigHandler);
2468 if (*appData.cmailGameName != NULLCHAR) {
2469 signal(SIGUSR1, CmailSigHandler);
2472 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2475 XtAppMainLoop(appContext);
2476 if (appData.debugMode) fclose(debugFP); // [DM] debug
2483 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2484 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2486 if (saveSettingsOnExit) SaveSettings(settingsFileName);
2487 unlink(gameCopyFilename);
2488 unlink(gamePasteFilename);
2491 RETSIGTYPE TermSizeSigHandler(int sig)
2504 CmailSigHandler(sig)
2510 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2512 /* Activate call-back function CmailSigHandlerCallBack() */
2513 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2515 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2519 CmailSigHandlerCallBack(isr, closure, message, count, error)
2527 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2529 /**** end signal code ****/
2539 f = fopen(appData.icsLogon, "r");
2545 strcat(buf, appData.icsLogon);
2546 f = fopen(buf, "r");
2550 ProcessICSInitScript(f);
2557 EditCommentPopDown();
2572 if (!menuBarWidget) return;
2573 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2575 DisplayError("menuStep.Revert", 0);
2577 XtSetSensitive(w, !grey);
2582 SetMenuEnables(enab)
2586 if (!menuBarWidget) return;
2587 while (enab->name != NULL) {
2588 w = XtNameToWidget(menuBarWidget, enab->name);
2590 DisplayError(enab->name, 0);
2592 XtSetSensitive(w, enab->value);
2598 Enables icsEnables[] = {
2599 { "menuFile.Mail Move", False },
2600 { "menuFile.Reload CMail Message", False },
2601 { "menuMode.Machine Black", False },
2602 { "menuMode.Machine White", False },
2603 { "menuMode.Analysis Mode", False },
2604 { "menuMode.Analyze File", False },
2605 { "menuMode.Two Machines", False },
2607 { "menuHelp.Hint", False },
2608 { "menuHelp.Book", False },
2609 { "menuStep.Move Now", False },
2610 { "menuOptions.Periodic Updates", False },
2611 { "menuOptions.Hide Thinking", False },
2612 { "menuOptions.Ponder Next Move", False },
2617 Enables ncpEnables[] = {
2618 { "menuFile.Mail Move", False },
2619 { "menuFile.Reload CMail Message", False },
2620 { "menuMode.Machine White", False },
2621 { "menuMode.Machine Black", False },
2622 { "menuMode.Analysis Mode", False },
2623 { "menuMode.Analyze File", False },
2624 { "menuMode.Two Machines", False },
2625 { "menuMode.ICS Client", False },
2626 { "menuMode.ICS Input Box", False },
2627 { "Action", False },
2628 { "menuStep.Revert", False },
2629 { "menuStep.Move Now", False },
2630 { "menuStep.Retract Move", False },
2631 { "menuOptions.Auto Comment", False },
2632 { "menuOptions.Auto Flag", False },
2633 { "menuOptions.Auto Flip View", False },
2634 { "menuOptions.Auto Observe", False },
2635 { "menuOptions.Auto Raise Board", False },
2636 { "menuOptions.Get Move List", False },
2637 { "menuOptions.ICS Alarm", False },
2638 { "menuOptions.Move Sound", False },
2639 { "menuOptions.Quiet Play", False },
2640 { "menuOptions.Hide Thinking", False },
2641 { "menuOptions.Periodic Updates", False },
2642 { "menuOptions.Ponder Next Move", False },
2643 { "menuHelp.Hint", False },
2644 { "menuHelp.Book", False },
2648 Enables gnuEnables[] = {
2649 { "menuMode.ICS Client", False },
2650 { "menuMode.ICS Input Box", False },
2651 { "menuAction.Accept", False },
2652 { "menuAction.Decline", False },
2653 { "menuAction.Rematch", False },
2654 { "menuAction.Adjourn", False },
2655 { "menuAction.Stop Examining", False },
2656 { "menuAction.Stop Observing", False },
2657 { "menuStep.Revert", False },
2658 { "menuOptions.Auto Comment", False },
2659 { "menuOptions.Auto Observe", False },
2660 { "menuOptions.Auto Raise Board", False },
2661 { "menuOptions.Get Move List", False },
2662 { "menuOptions.Premove", False },
2663 { "menuOptions.Quiet Play", False },
2665 /* The next two options rely on SetCmailMode being called *after* */
2666 /* SetGNUMode so that when GNU is being used to give hints these */
2667 /* menu options are still available */
2669 { "menuFile.Mail Move", False },
2670 { "menuFile.Reload CMail Message", False },
2674 Enables cmailEnables[] = {
2676 { "menuAction.Call Flag", False },
2677 { "menuAction.Draw", True },
2678 { "menuAction.Adjourn", False },
2679 { "menuAction.Abort", False },
2680 { "menuAction.Stop Observing", False },
2681 { "menuAction.Stop Examining", False },
2682 { "menuFile.Mail Move", True },
2683 { "menuFile.Reload CMail Message", True },
2687 Enables trainingOnEnables[] = {
2688 { "menuMode.Edit Comment", False },
2689 { "menuMode.Pause", False },
2690 { "menuStep.Forward", False },
2691 { "menuStep.Backward", False },
2692 { "menuStep.Forward to End", False },
2693 { "menuStep.Back to Start", False },
2694 { "menuStep.Move Now", False },
2695 { "menuStep.Truncate Game", False },
2699 Enables trainingOffEnables[] = {
2700 { "menuMode.Edit Comment", True },
2701 { "menuMode.Pause", True },
2702 { "menuStep.Forward", True },
2703 { "menuStep.Backward", True },
2704 { "menuStep.Forward to End", True },
2705 { "menuStep.Back to Start", True },
2706 { "menuStep.Move Now", True },
2707 { "menuStep.Truncate Game", True },
2711 Enables machineThinkingEnables[] = {
2712 { "menuFile.Load Game", False },
2713 { "menuFile.Load Next Game", False },
2714 { "menuFile.Load Previous Game", False },
2715 { "menuFile.Reload Same Game", False },
2716 { "menuFile.Paste Game", False },
2717 { "menuFile.Load Position", False },
2718 { "menuFile.Load Next Position", False },
2719 { "menuFile.Load Previous Position", False },
2720 { "menuFile.Reload Same Position", False },
2721 { "menuFile.Paste Position", False },
2722 { "menuMode.Machine White", False },
2723 { "menuMode.Machine Black", False },
2724 { "menuMode.Two Machines", False },
2725 { "menuStep.Retract Move", False },
2729 Enables userThinkingEnables[] = {
2730 { "menuFile.Load Game", True },
2731 { "menuFile.Load Next Game", True },
2732 { "menuFile.Load Previous Game", True },
2733 { "menuFile.Reload Same Game", True },
2734 { "menuFile.Paste Game", True },
2735 { "menuFile.Load Position", True },
2736 { "menuFile.Load Next Position", True },
2737 { "menuFile.Load Previous Position", True },
2738 { "menuFile.Reload Same Position", True },
2739 { "menuFile.Paste Position", True },
2740 { "menuMode.Machine White", True },
2741 { "menuMode.Machine Black", True },
2742 { "menuMode.Two Machines", True },
2743 { "menuStep.Retract Move", True },
2749 SetMenuEnables(icsEnables);
2752 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2753 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2760 SetMenuEnables(ncpEnables);
2766 SetMenuEnables(gnuEnables);
2772 SetMenuEnables(cmailEnables);
2778 SetMenuEnables(trainingOnEnables);
2779 if (appData.showButtonBar) {
2780 XtSetSensitive(buttonBarWidget, False);
2786 SetTrainingModeOff()
2788 SetMenuEnables(trainingOffEnables);
2789 if (appData.showButtonBar) {
2790 XtSetSensitive(buttonBarWidget, True);
2795 SetUserThinkingEnables()
2797 if (appData.noChessProgram) return;
2798 SetMenuEnables(userThinkingEnables);
2802 SetMachineThinkingEnables()
2804 if (appData.noChessProgram) return;
2805 SetMenuEnables(machineThinkingEnables);
2807 case MachinePlaysBlack:
2808 case MachinePlaysWhite:
2809 case TwoMachinesPlay:
2810 XtSetSensitive(XtNameToWidget(menuBarWidget,
2811 ModeToWidgetName(gameMode)), True);
2818 #define Abs(n) ((n)<0 ? -(n) : (n))
2821 * Find a font that matches "pattern" that is as close as
2822 * possible to the targetPxlSize. Prefer fonts that are k
2823 * pixels smaller to fonts that are k pixels larger. The
2824 * pattern must be in the X Consortium standard format,
2825 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2826 * The return value should be freed with XtFree when no
2829 char *FindFont(pattern, targetPxlSize)
2833 char **fonts, *p, *best, *scalable, *scalableTail;
2834 int i, j, nfonts, minerr, err, pxlSize;
2837 char **missing_list;
2839 char *def_string, *base_fnt_lst, strInt[3];
2841 XFontStruct **fnt_list;
2843 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2844 sprintf(strInt, "%d", targetPxlSize);
2845 p = strstr(pattern, "--");
2846 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2847 strcat(base_fnt_lst, strInt);
2848 strcat(base_fnt_lst, strchr(p + 2, '-'));
2850 if ((fntSet = XCreateFontSet(xDisplay,
2854 &def_string)) == NULL) {
2856 fprintf(stderr, _("Unable to create font set.\n"));
2860 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2862 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2864 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2865 programName, pattern);
2873 for (i=0; i<nfonts; i++) {
2876 if (*p != '-') continue;
2878 if (*p == NULLCHAR) break;
2879 if (*p++ == '-') j++;
2881 if (j < 7) continue;
2884 scalable = fonts[i];
2887 err = pxlSize - targetPxlSize;
2888 if (Abs(err) < Abs(minerr) ||
2889 (minerr > 0 && err < 0 && -err == minerr)) {
2895 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2896 /* If the error is too big and there is a scalable font,
2897 use the scalable font. */
2898 int headlen = scalableTail - scalable;
2899 p = (char *) XtMalloc(strlen(scalable) + 10);
2900 while (isdigit(*scalableTail)) scalableTail++;
2901 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2903 p = (char *) XtMalloc(strlen(best) + 1);
2906 if (appData.debugMode) {
2907 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2908 pattern, targetPxlSize, p);
2911 if (missing_count > 0)
2912 XFreeStringList(missing_list);
2913 XFreeFontSet(xDisplay, fntSet);
2915 XFreeFontNames(fonts);
2922 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2923 | GCBackground | GCFunction | GCPlaneMask;
2924 XGCValues gc_values;
2927 gc_values.plane_mask = AllPlanes;
2928 gc_values.line_width = lineGap;
2929 gc_values.line_style = LineSolid;
2930 gc_values.function = GXcopy;
2932 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2933 gc_values.background = XBlackPixel(xDisplay, xScreen);
2934 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2936 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2937 gc_values.background = XWhitePixel(xDisplay, xScreen);
2938 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2939 XSetFont(xDisplay, coordGC, coordFontID);
2941 // [HGM] make font for holdings counts (white on black0
2942 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2943 gc_values.background = XBlackPixel(xDisplay, xScreen);
2944 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
2945 XSetFont(xDisplay, countGC, countFontID);
2947 if (appData.monoMode) {
2948 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2949 gc_values.background = XWhitePixel(xDisplay, xScreen);
2950 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2952 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2953 gc_values.background = XBlackPixel(xDisplay, xScreen);
2954 lightSquareGC = wbPieceGC
2955 = XtGetGC(shellWidget, value_mask, &gc_values);
2957 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2958 gc_values.background = XWhitePixel(xDisplay, xScreen);
2959 darkSquareGC = bwPieceGC
2960 = XtGetGC(shellWidget, value_mask, &gc_values);
2962 if (DefaultDepth(xDisplay, xScreen) == 1) {
2963 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
2964 gc_values.function = GXcopyInverted;
2965 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
2966 gc_values.function = GXcopy;
2967 if (XBlackPixel(xDisplay, xScreen) == 1) {
2968 bwPieceGC = darkSquareGC;
2969 wbPieceGC = copyInvertedGC;
2971 bwPieceGC = copyInvertedGC;
2972 wbPieceGC = lightSquareGC;
2976 gc_values.foreground = highlightSquareColor;
2977 gc_values.background = highlightSquareColor;
2978 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2980 gc_values.foreground = premoveHighlightColor;
2981 gc_values.background = premoveHighlightColor;
2982 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2984 gc_values.foreground = lightSquareColor;
2985 gc_values.background = darkSquareColor;
2986 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2988 gc_values.foreground = darkSquareColor;
2989 gc_values.background = lightSquareColor;
2990 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2992 gc_values.foreground = jailSquareColor;
2993 gc_values.background = jailSquareColor;
2994 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2996 gc_values.foreground = whitePieceColor;
2997 gc_values.background = darkSquareColor;
2998 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3000 gc_values.foreground = whitePieceColor;
3001 gc_values.background = lightSquareColor;
3002 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3004 gc_values.foreground = whitePieceColor;
3005 gc_values.background = jailSquareColor;
3006 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3008 gc_values.foreground = blackPieceColor;
3009 gc_values.background = darkSquareColor;
3010 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3012 gc_values.foreground = blackPieceColor;
3013 gc_values.background = lightSquareColor;
3014 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3016 gc_values.foreground = blackPieceColor;
3017 gc_values.background = jailSquareColor;
3018 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3022 void loadXIM(xim, xmask, filename, dest, mask)
3035 fp = fopen(filename, "rb");
3037 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3044 for (y=0; y<h; ++y) {
3045 for (x=0; x<h; ++x) {
3050 XPutPixel(xim, x, y, blackPieceColor);
3052 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3055 XPutPixel(xim, x, y, darkSquareColor);
3057 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3060 XPutPixel(xim, x, y, whitePieceColor);
3062 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3065 XPutPixel(xim, x, y, lightSquareColor);
3067 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3073 /* create Pixmap of piece */
3074 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3076 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3079 /* create Pixmap of clipmask
3080 Note: We assume the white/black pieces have the same
3081 outline, so we make only 6 masks. This is okay
3082 since the XPM clipmask routines do the same. */
3084 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3086 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3089 /* now create the 1-bit version */
3090 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3093 values.foreground = 1;
3094 values.background = 0;
3096 /* Don't use XtGetGC, not read only */
3097 maskGC = XCreateGC(xDisplay, *mask,
3098 GCForeground | GCBackground, &values);
3099 XCopyPlane(xDisplay, temp, *mask, maskGC,
3100 0, 0, squareSize, squareSize, 0, 0, 1);
3101 XFreePixmap(xDisplay, temp);
3106 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3108 void CreateXIMPieces()
3113 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3118 /* The XSynchronize calls were copied from CreatePieces.
3119 Not sure if needed, but can't hurt */
3120 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3123 /* temp needed by loadXIM() */
3124 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3125 0, 0, ss, ss, AllPlanes, XYPixmap);
3127 if (strlen(appData.pixmapDirectory) == 0) {
3131 if (appData.monoMode) {
3132 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3136 fprintf(stderr, _("\nLoading XIMs...\n"));
3138 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3139 fprintf(stderr, "%d", piece+1);
3140 for (kind=0; kind<4; kind++) {
3141 fprintf(stderr, ".");
3142 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3143 ExpandPathName(appData.pixmapDirectory),
3144 piece <= (int) WhiteKing ? "" : "w",
3145 pieceBitmapNames[piece],
3147 ximPieceBitmap[kind][piece] =
3148 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3149 0, 0, ss, ss, AllPlanes, XYPixmap);
3150 if (appData.debugMode)
3151 fprintf(stderr, _("(File:%s:) "), buf);
3152 loadXIM(ximPieceBitmap[kind][piece],
3154 &(xpmPieceBitmap2[kind][piece]),
3155 &(ximMaskPm2[piece]));
3156 if(piece <= (int)WhiteKing)
3157 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3159 fprintf(stderr," ");
3161 /* Load light and dark squares */
3162 /* If the LSQ and DSQ pieces don't exist, we will
3163 draw them with solid squares. */
3164 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3165 if (access(buf, 0) != 0) {
3169 fprintf(stderr, _("light square "));
3171 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3172 0, 0, ss, ss, AllPlanes, XYPixmap);
3173 if (appData.debugMode)
3174 fprintf(stderr, _("(File:%s:) "), buf);
3176 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3177 fprintf(stderr, _("dark square "));
3178 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3179 ExpandPathName(appData.pixmapDirectory), ss);
3180 if (appData.debugMode)
3181 fprintf(stderr, _("(File:%s:) "), buf);
3183 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3184 0, 0, ss, ss, AllPlanes, XYPixmap);
3185 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3186 xpmJailSquare = xpmLightSquare;
3188 fprintf(stderr, _("Done.\n"));
3190 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3194 void CreateXPMPieces()
3198 u_int ss = squareSize;
3200 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3201 XpmColorSymbol symbols[4];
3203 /* The XSynchronize calls were copied from CreatePieces.
3204 Not sure if needed, but can't hurt */
3205 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3207 /* Setup translations so piece colors match square colors */
3208 symbols[0].name = "light_piece";
3209 symbols[0].value = appData.whitePieceColor;
3210 symbols[1].name = "dark_piece";
3211 symbols[1].value = appData.blackPieceColor;
3212 symbols[2].name = "light_square";
3213 symbols[2].value = appData.lightSquareColor;
3214 symbols[3].name = "dark_square";
3215 symbols[3].value = appData.darkSquareColor;
3217 attr.valuemask = XpmColorSymbols;
3218 attr.colorsymbols = symbols;
3219 attr.numsymbols = 4;
3221 if (appData.monoMode) {
3222 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3226 if (strlen(appData.pixmapDirectory) == 0) {
3227 XpmPieces* pieces = builtInXpms;
3230 while (pieces->size != squareSize && pieces->size) pieces++;
3231 if (!pieces->size) {
3232 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3235 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3236 for (kind=0; kind<4; kind++) {
3238 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3239 pieces->xpm[piece][kind],
3240 &(xpmPieceBitmap2[kind][piece]),
3241 NULL, &attr)) != 0) {
3242 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3246 if(piece <= (int) WhiteKing)
3247 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3251 xpmJailSquare = xpmLightSquare;
3255 fprintf(stderr, _("\nLoading XPMs...\n"));
3258 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3259 fprintf(stderr, "%d ", piece+1);
3260 for (kind=0; kind<4; kind++) {
3261 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3262 ExpandPathName(appData.pixmapDirectory),
3263 piece > (int) WhiteKing ? "w" : "",
3264 pieceBitmapNames[piece],
3266 if (appData.debugMode) {
3267 fprintf(stderr, _("(File:%s:) "), buf);
3269 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3270 &(xpmPieceBitmap2[kind][piece]),
3271 NULL, &attr)) != 0) {
3272 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3273 // [HGM] missing: read of unorthodox piece failed; substitute King.
3274 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3275 ExpandPathName(appData.pixmapDirectory),
3277 if (appData.debugMode) {
3278 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3280 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3281 &(xpmPieceBitmap2[kind][piece]),
3285 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3290 if(piece <= (int) WhiteKing)
3291 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3294 /* Load light and dark squares */
3295 /* If the LSQ and DSQ pieces don't exist, we will
3296 draw them with solid squares. */
3297 fprintf(stderr, _("light square "));
3298 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3299 if (access(buf, 0) != 0) {
3303 if (appData.debugMode)
3304 fprintf(stderr, _("(File:%s:) "), buf);
3306 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3307 &xpmLightSquare, NULL, &attr)) != 0) {
3308 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3311 fprintf(stderr, _("dark square "));
3312 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3313 ExpandPathName(appData.pixmapDirectory), ss);
3314 if (appData.debugMode) {
3315 fprintf(stderr, _("(File:%s:) "), buf);
3317 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3318 &xpmDarkSquare, NULL, &attr)) != 0) {
3319 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3323 xpmJailSquare = xpmLightSquare;
3324 fprintf(stderr, _("Done.\n"));
3326 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3329 #endif /* HAVE_LIBXPM */
3332 /* No built-in bitmaps */
3337 u_int ss = squareSize;
3339 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3342 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3343 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3344 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3345 pieceBitmapNames[piece],
3346 ss, kind == SOLID ? 's' : 'o');
3347 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
3348 if(piece <= (int)WhiteKing)
3349 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3353 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3357 /* With built-in bitmaps */
3360 BuiltInBits* bib = builtInBits;
3363 u_int ss = squareSize;
3365 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3368 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3370 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3371 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3372 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
3373 pieceBitmapNames[piece],
3374 ss, kind == SOLID ? 's' : 'o');
3375 ReadBitmap(&pieceBitmap2[kind][piece], buf,
3376 bib->bits[kind][piece], ss, ss);
3377 if(piece <= (int)WhiteKing)
3378 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
3382 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3387 void ReadBitmap(pm, name, bits, wreq, hreq)
3390 unsigned char bits[];
3396 char msg[MSG_SIZ], fullname[MSG_SIZ];
3398 if (*appData.bitmapDirectory != NULLCHAR) {
3399 strcpy(fullname, appData.bitmapDirectory);
3400 strcat(fullname, "/");
3401 strcat(fullname, name);
3402 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3403 &w, &h, pm, &x_hot, &y_hot);
3404 fprintf(stderr, "load %s\n", name);
3405 if (errcode != BitmapSuccess) {
3407 case BitmapOpenFailed:
3408 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3410 case BitmapFileInvalid:
3411 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3413 case BitmapNoMemory:
3414 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
3418 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
3422 fprintf(stderr, _("%s: %s...using built-in\n"),
3424 } else if (w != wreq || h != hreq) {
3426 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3427 programName, fullname, w, h, wreq, hreq);
3433 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3442 if (lineGap == 0) return;
3444 /* [HR] Split this into 2 loops for non-square boards. */
3446 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
3447 gridSegments[i].x1 = 0;
3448 gridSegments[i].x2 =
3449 lineGap + BOARD_WIDTH * (squareSize + lineGap);
3450 gridSegments[i].y1 = gridSegments[i].y2
3451 = lineGap / 2 + (i * (squareSize + lineGap));
3454 for (j = 0; j < BOARD_WIDTH + 1; j++) {
3455 gridSegments[j + i].y1 = 0;
3456 gridSegments[j + i].y2 =
3457 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3458 gridSegments[j + i].x1 = gridSegments[j + i].x2
3459 = lineGap / 2 + (j * (squareSize + lineGap));
3463 static void MenuBarSelect(w, addr, index)
3468 XtActionProc proc = (XtActionProc) addr;
3470 (proc)(NULL, NULL, NULL, NULL);
3473 void CreateMenuBarPopup(parent, name, mb)
3483 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3486 XtSetArg(args[j], XtNleftMargin, 20); j++;
3487 XtSetArg(args[j], XtNrightMargin, 20); j++;
3489 while (mi->string != NULL) {
3490 if (strcmp(mi->string, "----") == 0) {
3491 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3494 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3495 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3497 XtAddCallback(entry, XtNcallback,
3498 (XtCallbackProc) MenuBarSelect,
3499 (caddr_t) mi->proc);
3505 Widget CreateMenuBar(mb)
3509 Widget anchor, menuBar;
3511 char menuName[MSG_SIZ];
3514 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3515 XtSetArg(args[j], XtNvSpace, 0); j++;
3516 XtSetArg(args[j], XtNborderWidth, 0); j++;
3517 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3518 formWidget, args, j);
3520 while (mb->name != NULL) {
3521 strcpy(menuName, "menu");
3522 strcat(menuName, mb->name);
3524 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3527 shortName[0] = _(mb->name)[0];
3528 shortName[1] = NULLCHAR;
3529 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3532 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3535 XtSetArg(args[j], XtNborderWidth, 0); j++;
3536 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3538 CreateMenuBarPopup(menuBar, menuName, mb);
3544 Widget CreateButtonBar(mi)
3548 Widget button, buttonBar;
3552 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3554 XtSetArg(args[j], XtNhSpace, 0); j++;
3556 XtSetArg(args[j], XtNborderWidth, 0); j++;
3557 XtSetArg(args[j], XtNvSpace, 0); j++;
3558 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3559 formWidget, args, j);
3561 while (mi->string != NULL) {
3564 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3565 XtSetArg(args[j], XtNborderWidth, 0); j++;
3567 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3568 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3569 buttonBar, args, j);
3570 XtAddCallback(button, XtNcallback,
3571 (XtCallbackProc) MenuBarSelect,
3572 (caddr_t) mi->proc);
3579 CreatePieceMenu(name, color)
3586 ChessSquare selection;
3588 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3589 boardWidget, args, 0);
3591 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3592 String item = pieceMenuStrings[color][i];
3594 if (strcmp(item, "----") == 0) {
3595 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3598 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3599 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3601 selection = pieceMenuTranslation[color][i];
3602 XtAddCallback(entry, XtNcallback,
3603 (XtCallbackProc) PieceMenuSelect,
3604 (caddr_t) selection);
3605 if (selection == WhitePawn || selection == BlackPawn) {
3606 XtSetArg(args[0], XtNpopupOnEntry, entry);
3607 XtSetValues(menu, args, 1);
3620 ChessSquare selection;
3622 whitePieceMenu = CreatePieceMenu("menuW", 0);
3623 blackPieceMenu = CreatePieceMenu("menuB", 1);
3625 XtRegisterGrabAction(PieceMenuPopup, True,
3626 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3627 GrabModeAsync, GrabModeAsync);
3629 XtSetArg(args[0], XtNlabel, _("Drop"));
3630 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3631 boardWidget, args, 1);