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"
188 #include <gdk-pixbuf/gdk-pixbuf.h>
190 #include "bitmaps/icon_white.bm"
191 #include "bitmaps/icon_black.bm"
192 #include "bitmaps/checkmark.bm"
194 #include "frontend.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
203 #include "callback.h"
204 #include "interface.h"
206 // must be moved to xengineoutput.h
208 void EngineOutputProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
211 void EngineOutputPopDown();
218 #define usleep(t) _sleep2(((t)+500)/1000)
222 # define _(s) gettext (s)
223 # define N_(s) gettext_noop (s)
246 int main P((int argc, char **argv));
247 RETSIGTYPE CmailSigHandler P((int sig));
248 RETSIGTYPE IntSigHandler P((int sig));
249 RETSIGTYPE TermSizeSigHandler P((int sig));
250 void CreateGCs P((void));
251 void CreateXIMPieces P((void));
252 void CreateXPMPieces P((void));
253 void CreatePieces P((void));
254 void CreatePieceMenus P((void));
255 Widget CreateMenuBar P((Menu *mb));
256 char *FindFont P((char *pattern, int targetPxlSize));
257 void PieceMenuPopup P((Widget w, XEvent *event,
258 String *params, Cardinal *num_params));
259 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
261 int EventToSquare P((int x, int limit));
262 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
263 void AnimateUserMove P((Widget w, XEvent * event,
264 String * params, Cardinal * nParams));
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void AskQuestionReplyAction P((Widget w, XEvent *event,
272 String *prms, Cardinal *nprms));
273 void AskQuestionProc P((Widget w, XEvent *event,
274 String *prms, Cardinal *nprms));
275 void AskQuestionPopDown P((void));
276 void PromotionPopDown P((void));
277 void PromotionCallback P((Widget w, XtPointer client_data,
278 XtPointer call_data));
279 void EditCommentPopDown P((void));
280 void EditCommentCallback P((Widget w, XtPointer client_data,
281 XtPointer call_data));
282 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
283 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
285 void PastePositionProc P((Widget w, XEvent *event, String *prms,
287 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
288 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
289 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
290 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
292 void EditCommentProc P((Widget w, XEvent *event,
293 String *prms, Cardinal *nprms));
294 void IcsInputBoxProc P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
297 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
298 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
299 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
301 void DisplayMove P((int moveNumber));
302 void DisplayTitle P((char *title));
303 void ICSInitScript P((void));
304 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
305 void ErrorPopUp P((char *title, char *text, int modal));
306 void ErrorPopDown P((void));
307 static char *ExpandPathName P((char *path));
308 static void CreateAnimVars P((void));
309 static void DragPieceMove P((int x, int y));
310 static void DrawDragPiece P((void));
311 char *ModeToWidgetName P((GameMode mode));
312 void EngineOutputUpdate( FrontEndProgramStats * stats );
313 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
318 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
319 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void ShufflePopDown P(());
321 void EnginePopDown P(());
322 void UciPopDown P(());
323 void TimeControlPopDown P(());
324 void NewVariantPopDown P(());
325 void SettingsPopDown P(());
326 void SetMenuEnables P((Enables *enab));
327 void update_ics_width P(());
328 int get_term_width P(());
330 * XBoard depends on Xt R4 or higher
332 int xtVersion = XtSpecificationRelease;
337 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
338 jailSquareColor, highlightSquareColor, premoveHighlightColor;
339 Pixel lowTimeWarningColor;
341 #define LINE_TYPE_NORMAL 0
342 #define LINE_TYPE_HIGHLIGHT 1
343 #define LINE_TYPE_PRE 2
346 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
347 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
348 wjPieceGC, bjPieceGC;
349 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
350 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
351 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
352 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
353 menuBarWidget, editShell, errorShell, analysisShell,
354 ICSInputShell, fileNameShell, askQuestionShell;
355 Font clockFontID, coordFontID, countFontID;
356 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
357 XtAppContext appContext;
359 char *oldICSInteractionTitle;
363 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
365 Position commentX = -1, commentY = -1;
366 Dimension commentW, commentH;
368 int squareSize, smallLayout = 0, tinyLayout = 0,
369 marginW, marginH, // [HGM] for run-time resizing
370 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
371 ICSInputBoxUp = False, askQuestionUp = False,
372 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
373 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
374 Pixel timerForegroundPixel, timerBackgroundPixel;
375 Pixel buttonForegroundPixel, buttonBackgroundPixel;
376 char *chessDir, *programName, *programVersion,
377 *gameCopyFilename, *gamePasteFilename;
381 Pixmap pieceBitmap[2][(int)BlackPawn];
382 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
383 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
384 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
385 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
386 int useImages=0, useImageSqs;
387 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
388 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
389 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
390 XImage *ximLightSquare, *ximDarkSquare;
393 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
394 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
396 #define White(piece) ((int)(piece) < (int)BlackPawn)
398 /* Variables for doing smooth animation. This whole thing
399 would be much easier if the board was double-buffered,
400 but that would require a fairly major rewrite. */
405 GC blitGC, pieceGC, outlineGC;
406 XPoint startSquare, prevFrame, mouseDelta;
410 int startBoardX, startBoardY;
413 /* There can be two pieces being animated at once: a player
414 can begin dragging a piece before the remote opponent has moved. */
416 static AnimState game, player;
418 /* Bitmaps for use as masks when drawing XPM pieces.
419 Need one for each black and white piece. */
420 static Pixmap xpmMask[BlackKing + 1];
422 /* This magic number is the number of intermediate frames used
423 in each half of the animation. For short moves it's reduced
424 by 1. The total number of frames will be factor * 2 + 1. */
427 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
429 Enables icsEnables[] = {
430 { "menuFile.Mail Move", False },
431 { "menuFile.Reload CMail Message", False },
432 { "menuMode.Machine Black", False },
433 { "menuMode.Machine White", False },
434 { "menuMode.Analysis Mode", False },
435 { "menuMode.Analyze File", False },
436 { "menuMode.Two Machines", False },
438 { "menuHelp.Hint", False },
439 { "menuHelp.Book", False },
440 { "menuStep.Move Now", False },
441 { "menuOptions.Periodic Updates", False },
442 { "menuOptions.Hide Thinking", False },
443 { "menuOptions.Ponder Next Move", False },
448 Enables ncpEnables[] = {
449 { "menuFile.Mail Move", False },
450 { "menuFile.Reload CMail Message", False },
451 { "menuMode.Machine White", False },
452 { "menuMode.Machine Black", False },
453 { "menuMode.Analysis Mode", False },
454 { "menuMode.Analyze File", False },
455 { "menuMode.Two Machines", False },
456 { "menuMode.ICS Client", False },
457 { "menuMode.ICS Input Box", False },
459 { "menuStep.Revert", False },
460 { "menuStep.Move Now", False },
461 { "menuStep.Retract Move", False },
462 { "menuOptions.Auto Comment", False },
463 { "menuOptions.Auto Flag", False },
464 { "menuOptions.Auto Flip View", False },
465 { "menuOptions.Auto Observe", False },
466 { "menuOptions.Auto Raise Board", False },
467 { "menuOptions.Get Move List", False },
468 { "menuOptions.ICS Alarm", False },
469 { "menuOptions.Move Sound", False },
470 { "menuOptions.Quiet Play", False },
471 { "menuOptions.Hide Thinking", False },
472 { "menuOptions.Periodic Updates", False },
473 { "menuOptions.Ponder Next Move", False },
474 { "menuHelp.Hint", False },
475 { "menuHelp.Book", False },
479 Enables gnuEnables[] = {
480 { "menuMode.ICS Client", False },
481 { "menuMode.ICS Input Box", False },
482 { "menuAction.Accept", False },
483 { "menuAction.Decline", False },
484 { "menuAction.Rematch", False },
485 { "menuAction.Adjourn", False },
486 { "menuAction.Stop Examining", False },
487 { "menuAction.Stop Observing", False },
488 { "menuStep.Revert", False },
489 { "menuOptions.Auto Comment", False },
490 { "menuOptions.Auto Observe", False },
491 { "menuOptions.Auto Raise Board", False },
492 { "menuOptions.Get Move List", False },
493 { "menuOptions.Premove", False },
494 { "menuOptions.Quiet Play", False },
496 /* The next two options rely on SetCmailMode being called *after* */
497 /* SetGNUMode so that when GNU is being used to give hints these */
498 /* menu options are still available */
500 { "menuFile.Mail Move", False },
501 { "menuFile.Reload CMail Message", False },
505 Enables cmailEnables[] = {
507 { "menuAction.Call Flag", False },
508 { "menuAction.Draw", True },
509 { "menuAction.Adjourn", False },
510 { "menuAction.Abort", False },
511 { "menuAction.Stop Observing", False },
512 { "menuAction.Stop Examining", False },
513 { "menuFile.Mail Move", True },
514 { "menuFile.Reload CMail Message", True },
518 Enables trainingOnEnables[] = {
519 { "menuMode.Edit Comment", False },
520 { "menuMode.Pause", False },
521 { "menuStep.Forward", False },
522 { "menuStep.Backward", False },
523 { "menuStep.Forward to End", False },
524 { "menuStep.Back to Start", False },
525 { "menuStep.Move Now", False },
526 { "menuStep.Truncate Game", False },
530 Enables trainingOffEnables[] = {
531 { "menuMode.Edit Comment", True },
532 { "menuMode.Pause", True },
533 { "menuStep.Forward", True },
534 { "menuStep.Backward", True },
535 { "menuStep.Forward to End", True },
536 { "menuStep.Back to Start", True },
537 { "menuStep.Move Now", True },
538 { "menuStep.Truncate Game", True },
542 Enables machineThinkingEnables[] = {
543 { "menuFile.Load Game", False },
544 { "menuFile.Load Next Game", False },
545 { "menuFile.Load Previous Game", False },
546 { "menuFile.Reload Same Game", False },
547 { "menuFile.Paste Game", False },
548 { "menuFile.Load Position", False },
549 { "menuFile.Load Next Position", False },
550 { "menuFile.Load Previous Position", False },
551 { "menuFile.Reload Same Position", False },
552 { "menuFile.Paste Position", False },
553 { "menuMode.Machine White", False },
554 { "menuMode.Machine Black", False },
555 { "menuMode.Two Machines", False },
556 { "menuStep.Retract Move", False },
560 Enables userThinkingEnables[] = {
561 { "menuFile.Load Game", True },
562 { "menuFile.Load Next Game", True },
563 { "menuFile.Load Previous Game", True },
564 { "menuFile.Reload Same Game", True },
565 { "menuFile.Paste Game", True },
566 { "menuFile.Load Position", True },
567 { "menuFile.Load Next Position", True },
568 { "menuFile.Load Previous Position", True },
569 { "menuFile.Reload Same Position", True },
570 { "menuFile.Paste Position", True },
571 { "menuMode.Machine White", True },
572 { "menuMode.Machine Black", True },
573 { "menuMode.Two Machines", True },
574 { "menuStep.Retract Move", True },
580 MenuItem fileMenu[] = {
581 {N_("New Shuffle Game ..."), ShuffleMenuProc},
582 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
583 // {"----", NothingProc},
584 // {N_("Save Game"), SaveGameProc},
585 // {"----", NothingProc},
586 {N_("Copy Game"), CopyGameProc},
587 {N_("Paste Game"), PasteGameProc},
588 // {"----", NothingProc},
589 // {N_("Load Position"), LoadPositionProc},
590 // {N_("Load Next Position"), LoadNextPositionProc},
591 // {N_("Load Previous Position"), LoadPrevPositionProc},
592 // {N_("Reload Same Position"), ReloadPositionProc},
593 // {N_("Save Position"), SavePositionProc},
594 // {"----", NothingProc},
595 {N_("Copy Position"), CopyPositionProc},
596 {N_("Paste Position"), PastePositionProc},
597 // {"----", NothingProc},
598 {N_("Mail Move"), MailMoveProc},
599 {N_("Reload CMail Message"), ReloadCmailMsgProc},
600 // {"----", NothingProc},
604 MenuItem modeMenu[] = {
605 // {N_("Machine White"), MachineWhiteProc},
606 // {N_("Machine Black"), MachineBlackProc},
607 // {N_("Two Machines"), TwoMachinesProc},
608 // {N_("Analysis Mode"), AnalyzeModeProc},
609 // {N_("Analyze File"), AnalyzeFileProc },
610 // {N_("ICS Client"), IcsClientProc},
611 // {N_("Edit Game"), EditGameProc},
612 // {N_("Edit Position"), EditPositionProc},
613 // {N_("Training"), TrainingProc},
614 // {"----", NothingProc},
615 {N_("Show Engine Output"), EngineOutputProc},
616 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
617 {N_("Show Game List"), ShowGameListProc},
618 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
619 // {"----", NothingProc},
620 // {N_("Edit Tags"), EditTagsProc},
621 {N_("Edit Comment"), EditCommentProc},
622 {N_("ICS Input Box"), IcsInputBoxProc},
626 MenuItem optionsMenu[] = {
627 // {N_("Flip View"), FlipViewProc},
628 // {"----", NothingProc},
629 {N_("Adjudications ..."), EngineMenuProc},
630 {N_("General Settings ..."), UciMenuProc},
631 {N_("Engine #1 Settings ..."), FirstSettingsProc},
632 {N_("Engine #2 Settings ..."), SecondSettingsProc},
633 {N_("Time Control ..."), TimeControlProc},
634 {"----", NothingProc},
635 // {N_("Always Queen"), AlwaysQueenProc},
636 // {N_("Animate Dragging"), AnimateDraggingProc},
637 // {N_("Animate Moving"), AnimateMovingProc},
638 // {N_("Auto Comment"), AutocommProc},
639 // {N_("Auto Flag"), AutoflagProc},
640 // {N_("Auto Flip View"), AutoflipProc},
641 // {N_("Auto Observe"), AutobsProc},
642 // {N_("Auto Raise Board"), AutoraiseProc},
643 // {N_("Auto Save"), AutosaveProc},
644 // {N_("Blindfold"), BlindfoldProc},
645 // {N_("Flash Moves"), FlashMovesProc},
646 // {N_("Get Move List"), GetMoveListProc},
648 // {N_("Highlight Dragging"), HighlightDraggingProc},
650 // {N_("Highlight Last Move"), HighlightLastMoveProc},
651 // {N_("Move Sound"), MoveSoundProc},
652 // {N_("ICS Alarm"), IcsAlarmProc},
653 // {N_("Old Save Style"), OldSaveStyleProc},
654 // {N_("Periodic Updates"), PeriodicUpdatesProc},
655 // {N_("Ponder Next Move"), PonderNextMoveProc},
656 // {N_("Popup Exit Message"), PopupExitMessageProc},
657 // {N_("Popup Move Errors"), PopupMoveErrorsProc},
658 // {N_("Premove"), PremoveProc},
659 // {N_("Quiet Play"), QuietPlayProc},
660 // {N_("Hide Thinking"), HideThinkingProc},
661 // {N_("Test Legality"), TestLegalityProc},
666 {N_("File"), fileMenu},
667 {N_("Mode"), modeMenu},
668 {N_("Options"), optionsMenu},
672 #define PIECE_MENU_SIZE 18
673 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
674 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
675 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
676 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
677 N_("Empty square"), N_("Clear board") },
678 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
679 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
680 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
681 N_("Empty square"), N_("Clear board") }
683 /* must be in same order as PieceMenuStrings! */
684 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
685 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
686 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
687 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
688 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
689 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
690 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
691 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
692 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
695 #define DROP_MENU_SIZE 6
696 String dropMenuStrings[DROP_MENU_SIZE] = {
697 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
699 /* must be in same order as PieceMenuStrings! */
700 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
701 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
702 WhiteRook, WhiteQueen
710 DropMenuEnables dmEnables[] = {
719 { XtNborderWidth, 0 },
720 { XtNdefaultDistance, 0 },
724 { XtNborderWidth, 0 },
725 { XtNresizable, (XtArgVal) True },
729 { XtNborderWidth, 0 },
734 XtResource clientResources[] = {
735 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
736 XtOffset(AppDataPtr, whitePieceColor), XtRString,
738 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
739 XtOffset(AppDataPtr, blackPieceColor), XtRString,
741 { "lightSquareColor", "lightSquareColor", XtRString,
742 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
743 XtRString, LIGHT_SQUARE_COLOR },
744 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
745 XtOffset(AppDataPtr, darkSquareColor), XtRString,
747 { "highlightSquareColor", "highlightSquareColor", XtRString,
748 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
749 XtRString, HIGHLIGHT_SQUARE_COLOR },
750 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
751 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
752 XtRString, PREMOVE_HIGHLIGHT_COLOR },
753 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
754 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
755 (XtPointer) MOVES_PER_SESSION },
756 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
757 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
758 (XtPointer) TIME_INCREMENT },
759 { "initString", "initString", XtRString, sizeof(String),
760 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
761 { "secondInitString", "secondInitString", XtRString, sizeof(String),
762 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
763 { "firstComputerString", "firstComputerString", XtRString,
764 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
766 { "secondComputerString", "secondComputerString", XtRString,
767 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
769 { "firstChessProgram", "firstChessProgram", XtRString,
770 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
771 XtRString, FIRST_CHESS_PROGRAM },
772 { "secondChessProgram", "secondChessProgram", XtRString,
773 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
774 XtRString, SECOND_CHESS_PROGRAM },
775 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
776 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
777 XtRImmediate, (XtPointer) False },
778 { "noChessProgram", "noChessProgram", XtRBoolean,
779 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
780 XtRImmediate, (XtPointer) False },
781 { "firstHost", "firstHost", XtRString, sizeof(String),
782 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
783 { "secondHost", "secondHost", XtRString, sizeof(String),
784 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
785 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
786 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
787 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
788 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
789 { "bitmapDirectory", "bitmapDirectory", XtRString,
790 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
792 { "remoteShell", "remoteShell", XtRString, sizeof(String),
793 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
794 { "remoteUser", "remoteUser", XtRString, sizeof(String),
795 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
796 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
797 XtOffset(AppDataPtr, timeDelay), XtRString,
798 (XtPointer) TIME_DELAY_QUOTE },
799 { "timeControl", "timeControl", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, timeControl), XtRString,
801 (XtPointer) TIME_CONTROL },
802 { "internetChessServerMode", "internetChessServerMode",
803 XtRBoolean, sizeof(Boolean),
804 XtOffset(AppDataPtr, icsActive), XtRImmediate,
806 { "internetChessServerHost", "internetChessServerHost",
807 XtRString, sizeof(String),
808 XtOffset(AppDataPtr, icsHost),
809 XtRString, (XtPointer) ICS_HOST },
810 { "internetChessServerPort", "internetChessServerPort",
811 XtRString, sizeof(String),
812 XtOffset(AppDataPtr, icsPort), XtRString,
813 (XtPointer) ICS_PORT },
814 { "internetChessServerCommPort", "internetChessServerCommPort",
815 XtRString, sizeof(String),
816 XtOffset(AppDataPtr, icsCommPort), XtRString,
818 { "internetChessServerLogonScript", "internetChessServerLogonScript",
819 XtRString, sizeof(String),
820 XtOffset(AppDataPtr, icsLogon), XtRString,
822 { "internetChessServerHelper", "internetChessServerHelper",
823 XtRString, sizeof(String),
824 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
825 { "internetChessServerInputBox", "internetChessServerInputBox",
826 XtRBoolean, sizeof(Boolean),
827 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
829 { "icsAlarm", "icsAlarm",
830 XtRBoolean, sizeof(Boolean),
831 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
833 { "icsAlarmTime", "icsAlarmTime",
835 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
837 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
838 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
840 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
842 { "gateway", "gateway", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, gateway), XtRString, "" },
844 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
846 { "loadGameIndex", "loadGameIndex",
848 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
850 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
852 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
853 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
854 XtRImmediate, (XtPointer) True },
855 { "autoSaveGames", "autoSaveGames", XtRBoolean,
856 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
857 XtRImmediate, (XtPointer) False },
858 { "blindfold", "blindfold", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
860 XtRImmediate, (XtPointer) False },
861 { "loadPositionFile", "loadPositionFile", XtRString,
862 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
864 { "loadPositionIndex", "loadPositionIndex",
866 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
868 { "savePositionFile", "savePositionFile", XtRString,
869 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
871 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
872 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
873 { "matchGames", "matchGames", XtRInt, sizeof(int),
874 XtOffset(AppDataPtr, matchGames), XtRImmediate,
876 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
877 XtOffset(AppDataPtr, monoMode), XtRImmediate,
879 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
880 XtOffset(AppDataPtr, debugMode), XtRImmediate,
882 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
883 XtOffset(AppDataPtr, clockMode), XtRImmediate,
885 { "boardSize", "boardSize", XtRString, sizeof(String),
886 XtOffset(AppDataPtr, boardSize), XtRString, "" },
887 { "searchTime", "searchTime", XtRString, sizeof(String),
888 XtOffset(AppDataPtr, searchTime), XtRString,
890 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
891 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
893 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
894 XtOffset(AppDataPtr, showCoords), XtRImmediate,
896 { "showJail", "showJail", XtRInt, sizeof(int),
897 XtOffset(AppDataPtr, showJail), XtRImmediate,
899 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
900 XtOffset(AppDataPtr, showThinking), XtRImmediate,
902 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
903 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
905 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
906 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
908 { "clockFont", "clockFont", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
910 { "coordFont", "coordFont", XtRString, sizeof(String),
911 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
912 { "font", "font", XtRString, sizeof(String),
913 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
914 { "ringBellAfterMoves", "ringBellAfterMoves",
915 XtRBoolean, sizeof(Boolean),
916 XtOffset(AppDataPtr, ringBellAfterMoves),
917 XtRImmediate, (XtPointer) False },
918 { "autoCallFlag", "autoCallFlag", XtRBoolean,
919 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
920 XtRImmediate, (XtPointer) False },
921 { "autoFlipView", "autoFlipView", XtRBoolean,
922 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
923 XtRImmediate, (XtPointer) True },
924 { "autoObserve", "autoObserve", XtRBoolean,
925 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
926 XtRImmediate, (XtPointer) False },
927 { "autoComment", "autoComment", XtRBoolean,
928 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
929 XtRImmediate, (XtPointer) False },
930 { "getMoveList", "getMoveList", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
932 XtRImmediate, (XtPointer) True },
934 { "highlightDragging", "highlightDragging", XtRBoolean,
935 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
936 XtRImmediate, (XtPointer) False },
938 { "highlightLastMove", "highlightLastMove", XtRBoolean,
939 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
940 XtRImmediate, (XtPointer) False },
941 { "premove", "premove", XtRBoolean,
942 sizeof(Boolean), XtOffset(AppDataPtr, premove),
943 XtRImmediate, (XtPointer) True },
944 { "testLegality", "testLegality", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
946 XtRImmediate, (XtPointer) True },
947 { "flipView", "flipView", XtRBoolean,
948 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
949 XtRImmediate, (XtPointer) False },
950 { "cmail", "cmailGameName", XtRString, sizeof(String),
951 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
952 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
953 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
954 XtRImmediate, (XtPointer) False },
955 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
956 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
957 XtRImmediate, (XtPointer) False },
958 { "quietPlay", "quietPlay", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
960 XtRImmediate, (XtPointer) False },
961 { "titleInWindow", "titleInWindow", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
963 XtRImmediate, (XtPointer) False },
964 { "localLineEditing", "localLineEditing", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
966 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
968 { "zippyTalk", "zippyTalk", XtRBoolean,
969 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
970 XtRImmediate, (XtPointer) ZIPPY_TALK },
971 { "zippyPlay", "zippyPlay", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
973 XtRImmediate, (XtPointer) ZIPPY_PLAY },
974 { "zippyLines", "zippyLines", XtRString, sizeof(String),
975 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
976 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
977 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
978 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
979 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
980 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
981 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
982 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
983 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
984 ZIPPY_WRONG_PASSWORD },
985 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
986 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
987 { "zippyUseI", "zippyUseI", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
989 XtRImmediate, (XtPointer) ZIPPY_USE_I },
990 { "zippyBughouse", "zippyBughouse", XtRInt,
991 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
992 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
993 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
995 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
996 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
997 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
998 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
999 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1000 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1001 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1002 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1003 { "zippyAbort", "zippyAbort", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1005 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1006 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1007 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1008 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1009 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1010 (XtPointer) ZIPPY_MAX_GAMES },
1011 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1012 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1013 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1014 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1015 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1018 { "flashCount", "flashCount", XtRInt, sizeof(int),
1019 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1020 (XtPointer) FLASH_COUNT },
1021 { "flashRate", "flashRate", XtRInt, sizeof(int),
1022 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1023 (XtPointer) FLASH_RATE },
1024 { "pixmapDirectory", "pixmapDirectory", XtRString,
1025 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1027 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1028 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1029 (XtPointer) MS_LOGIN_DELAY },
1030 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1032 XtRImmediate, (XtPointer) False },
1033 { "colorShout", "colorShout", XtRString,
1034 sizeof(String), XtOffset(AppDataPtr, colorShout),
1035 XtRString, COLOR_SHOUT },
1036 { "colorSShout", "colorSShout", XtRString,
1037 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1038 XtRString, COLOR_SSHOUT },
1039 { "colorChannel1", "colorChannel1", XtRString,
1040 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1041 XtRString, COLOR_CHANNEL1 },
1042 { "colorChannel", "colorChannel", XtRString,
1043 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1044 XtRString, COLOR_CHANNEL },
1045 { "colorKibitz", "colorKibitz", XtRString,
1046 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1047 XtRString, COLOR_KIBITZ },
1048 { "colorTell", "colorTell", XtRString,
1049 sizeof(String), XtOffset(AppDataPtr, colorTell),
1050 XtRString, COLOR_TELL },
1051 { "colorChallenge", "colorChallenge", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1053 XtRString, COLOR_CHALLENGE },
1054 { "colorRequest", "colorRequest", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1056 XtRString, COLOR_REQUEST },
1057 { "colorSeek", "colorSeek", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1059 XtRString, COLOR_SEEK },
1060 { "colorNormal", "colorNormal", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1062 XtRString, COLOR_NORMAL },
1063 { "soundProgram", "soundProgram", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1065 XtRString, "play" },
1066 { "soundShout", "soundShout", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, soundShout),
1069 { "soundSShout", "soundSShout", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1072 { "soundChannel1", "soundChannel1", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1075 { "soundChannel", "soundChannel", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1078 { "soundKibitz", "soundKibitz", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1081 { "soundTell", "soundTell", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundTell),
1084 { "soundChallenge", "soundChallenge", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1087 { "soundRequest", "soundRequest", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1090 { "soundSeek", "soundSeek", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1093 { "soundMove", "soundMove", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundMove),
1096 { "soundIcsWin", "soundIcsWin", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1099 { "soundIcsLoss", "soundIcsLoss", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1102 { "soundIcsDraw", "soundIcsDraw", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1105 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1108 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1111 { "reuseFirst", "reuseFirst", XtRBoolean,
1112 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1113 XtRImmediate, (XtPointer) True },
1114 { "reuseSecond", "reuseSecond", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1116 XtRImmediate, (XtPointer) True },
1117 { "animateDragging", "animateDragging", XtRBoolean,
1118 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1119 XtRImmediate, (XtPointer) True },
1120 { "animateMoving", "animateMoving", XtRBoolean,
1121 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1122 XtRImmediate, (XtPointer) True },
1123 { "animateSpeed", "animateSpeed", XtRInt,
1124 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1125 XtRImmediate, (XtPointer)10 },
1126 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1128 XtRImmediate, (XtPointer) True },
1129 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1130 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1131 XtRImmediate, (XtPointer) False },
1132 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1133 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1134 XtRImmediate, (XtPointer)4 },
1135 { "initialMode", "initialMode", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, initialMode),
1137 XtRImmediate, (XtPointer) "" },
1138 { "variant", "variant", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, variant),
1140 XtRImmediate, (XtPointer) "normal" },
1141 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1142 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1143 XtRImmediate, (XtPointer)PROTOVER },
1144 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1145 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1146 XtRImmediate, (XtPointer)PROTOVER },
1147 { "showButtonBar", "showButtonBar", XtRBoolean,
1148 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1149 XtRImmediate, (XtPointer) True },
1150 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1151 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1152 XtRString, COLOR_LOWTIMEWARNING },
1153 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1154 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1155 XtRImmediate, (XtPointer) False },
1156 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1157 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1158 XtRImmediate, (XtPointer) False },
1159 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1160 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1161 XtRImmediate, (XtPointer) False },
1162 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1163 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1164 XtRImmediate, (XtPointer) False },
1165 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1166 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1167 XtRImmediate, (XtPointer) False },
1168 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1169 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1170 XtRImmediate, (XtPointer) True },
1171 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1172 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1173 XtRImmediate, (XtPointer) 0},
1174 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1175 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1176 XtRImmediate, (XtPointer) 0},
1177 { "pgnEventHeader", "pgnEventHeader", XtRString,
1178 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1179 XtRImmediate, (XtPointer) "Computer Chess Game" },
1180 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1181 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1182 XtRImmediate, (XtPointer) -1},
1183 { "gameListTags", "gameListTags", XtRString,
1184 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1185 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1187 // [HGM] 4.3.xx options
1188 { "boardWidth", "boardWidth", XtRInt,
1189 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1190 XtRImmediate, (XtPointer) -1},
1191 { "boardHeight", "boardHeight", XtRInt,
1192 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1193 XtRImmediate, (XtPointer) -1},
1194 { "matchPause", "matchPause", XtRInt,
1195 sizeof(int), XtOffset(AppDataPtr, matchPause),
1196 XtRImmediate, (XtPointer) 10000},
1197 { "holdingsSize", "holdingsSize", XtRInt,
1198 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1199 XtRImmediate, (XtPointer) -1},
1200 { "flipBlack", "flipBlack", XtRBoolean,
1201 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1202 XtRImmediate, (XtPointer) False},
1203 { "allWhite", "allWhite", XtRBoolean,
1204 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1205 XtRImmediate, (XtPointer) False},
1206 { "pieceToCharTable", "pieceToCharTable", XtRString,
1207 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1208 XtRImmediate, (XtPointer) 0},
1209 { "alphaRank", "alphaRank", XtRBoolean,
1210 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1211 XtRImmediate, (XtPointer) False},
1212 { "testClaims", "testClaims", XtRBoolean,
1213 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1214 XtRImmediate, (XtPointer) True},
1215 { "checkMates", "checkMates", XtRBoolean,
1216 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1217 XtRImmediate, (XtPointer) True},
1218 { "materialDraws", "materialDraws", XtRBoolean,
1219 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1220 XtRImmediate, (XtPointer) True},
1221 { "trivialDraws", "trivialDraws", XtRBoolean,
1222 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1223 XtRImmediate, (XtPointer) False},
1224 { "ruleMoves", "ruleMoves", XtRInt,
1225 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1226 XtRImmediate, (XtPointer) 51},
1227 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1228 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1229 XtRImmediate, (XtPointer) 6},
1230 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, engineComments),
1232 XtRImmediate, (XtPointer) 1},
1233 { "userName", "userName", XtRString,
1234 sizeof(int), XtOffset(AppDataPtr, userName),
1235 XtRImmediate, (XtPointer) 0},
1236 { "autoKibitz", "autoKibitz", XtRBoolean,
1237 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1238 XtRImmediate, (XtPointer) False},
1239 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1240 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1241 XtRImmediate, (XtPointer) 1},
1242 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1243 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1244 XtRImmediate, (XtPointer) 1},
1245 { "timeOddsMode", "timeOddsMode", XtRInt,
1246 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1247 XtRImmediate, (XtPointer) 0},
1248 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1249 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1250 XtRImmediate, (XtPointer) 1},
1251 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1252 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1253 XtRImmediate, (XtPointer) 1},
1254 { "firstNPS", "firstNPS", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1256 XtRImmediate, (XtPointer) -1},
1257 { "secondNPS", "secondNPS", XtRInt,
1258 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1259 XtRImmediate, (XtPointer) -1},
1260 { "serverMoves", "serverMoves", XtRString,
1261 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1262 XtRImmediate, (XtPointer) 0},
1263 { "serverPause", "serverPause", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, serverPause),
1265 XtRImmediate, (XtPointer) 0},
1266 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1267 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1268 XtRImmediate, (XtPointer) False},
1269 { "userName", "userName", XtRString,
1270 sizeof(String), XtOffset(AppDataPtr, userName),
1271 XtRImmediate, (XtPointer) 0},
1272 { "egtFormats", "egtFormats", XtRString,
1273 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1274 XtRImmediate, (XtPointer) 0},
1275 { "rewindIndex", "rewindIndex", XtRInt,
1276 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1277 XtRImmediate, (XtPointer) 0},
1278 { "sameColorGames", "sameColorGames", XtRInt,
1279 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1280 XtRImmediate, (XtPointer) 0},
1281 { "smpCores", "smpCores", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, smpCores),
1283 XtRImmediate, (XtPointer) 1},
1284 { "niceEngines", "niceEngines", XtRInt,
1285 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1286 XtRImmediate, (XtPointer) 0},
1287 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1288 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1289 XtRImmediate, (XtPointer) "xboard.debug"},
1290 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, engineComments),
1292 XtRImmediate, (XtPointer) 1},
1293 { "noGUI", "noGUI", XtRBoolean,
1294 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1295 XtRImmediate, (XtPointer) 0},
1296 { "firstOptions", "firstOptions", XtRString,
1297 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1298 XtRImmediate, (XtPointer) "" },
1299 { "secondOptions", "secondOptions", XtRString,
1300 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1301 XtRImmediate, (XtPointer) "" },
1302 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1303 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1304 XtRImmediate, (XtPointer) 0 },
1305 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1306 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1307 XtRImmediate, (XtPointer) 0 },
1309 // [HGM] Winboard_x UCI options
1310 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1311 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1312 XtRImmediate, (XtPointer) False},
1313 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1314 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1315 XtRImmediate, (XtPointer) False},
1316 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1317 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1318 XtRImmediate, (XtPointer) True},
1319 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1320 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1321 XtRImmediate, (XtPointer) True},
1322 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1323 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1324 XtRImmediate, (XtPointer) False},
1325 { "defaultHashSize", "defaultHashSize", XtRInt,
1326 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1327 XtRImmediate, (XtPointer) 64},
1328 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1329 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1330 XtRImmediate, (XtPointer) 4},
1331 { "polyglotDir", "polyglotDir", XtRString,
1332 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1333 XtRImmediate, (XtPointer) "." },
1334 { "polyglotBook", "polyglotBook", XtRString,
1335 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1336 XtRImmediate, (XtPointer) "" },
1337 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1338 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1339 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1340 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1341 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1342 XtRImmediate, (XtPointer) 0},
1343 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1344 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1345 XtRImmediate, (XtPointer) 0},
1346 { "keepAlive", "keepAlive", XtRInt,
1347 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1348 XtRImmediate, (XtPointer) 0},
1349 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1350 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1351 XtRImmediate, (XtPointer) False},
1352 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1353 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1354 XtRImmediate, (XtPointer) False},
1355 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1356 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1358 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1359 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1360 XtRImmediate, (XtPointer) True},
1361 { "autoDisplayTags", "autoDisplayTags", XtRBoolean,
1362 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayTags),
1363 XtRImmediate, (XtPointer) True},
1364 { "autoDisplayComment", "autoDisplayComment", XtRBoolean,
1365 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayComment),
1366 XtRImmediate, (XtPointer) True},
1367 { "pasteSelection", "pasteSelection", XtRBoolean,
1368 sizeof(Boolean), XtOffset(AppDataPtr, pasteSelection),
1369 XtRImmediate, (XtPointer) False},
1372 XrmOptionDescRec shellOptions[] = {
1373 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1374 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1375 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1376 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1377 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1378 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1379 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1380 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1381 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1382 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1383 { "-initString", "initString", XrmoptionSepArg, NULL },
1384 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1385 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1386 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1387 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1388 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1389 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1390 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1391 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1392 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1393 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1394 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1395 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1396 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1397 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1398 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1399 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1400 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1401 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1402 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1403 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1404 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1405 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1406 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1407 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1408 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1409 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1410 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1411 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1412 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1413 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1414 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1415 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1416 { "-internetChessServerMode", "internetChessServerMode",
1417 XrmoptionSepArg, NULL },
1418 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1419 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1420 { "-internetChessServerHost", "internetChessServerHost",
1421 XrmoptionSepArg, NULL },
1422 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1423 { "-internetChessServerPort", "internetChessServerPort",
1424 XrmoptionSepArg, NULL },
1425 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1426 { "-internetChessServerCommPort", "internetChessServerCommPort",
1427 XrmoptionSepArg, NULL },
1428 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1429 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1430 XrmoptionSepArg, NULL },
1431 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1432 { "-internetChessServerHelper", "internetChessServerHelper",
1433 XrmoptionSepArg, NULL },
1434 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1435 { "-internetChessServerInputBox", "internetChessServerInputBox",
1436 XrmoptionSepArg, NULL },
1437 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1438 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1439 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1440 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1441 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1442 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1443 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1444 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1445 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1446 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1447 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1448 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1449 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1450 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1451 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1452 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1453 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1454 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1455 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1456 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1457 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1458 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1459 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1460 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1461 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1462 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1463 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1464 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1465 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1466 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1467 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1468 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1469 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1470 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1471 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1472 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1473 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1474 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1475 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1476 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1477 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1478 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1479 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1480 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1481 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1482 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1483 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1484 { "-size", "boardSize", XrmoptionSepArg, NULL },
1485 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1486 { "-st", "searchTime", XrmoptionSepArg, NULL },
1487 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1488 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1489 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1490 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1491 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1493 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1494 { "-jail", "showJail", XrmoptionNoArg, "1" },
1495 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1496 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1498 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1499 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1500 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1501 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1502 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1503 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1504 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1505 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1506 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1507 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1508 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1509 { "-font", "font", XrmoptionSepArg, NULL },
1510 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1511 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1512 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1513 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1514 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1515 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1516 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1517 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1518 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1519 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1520 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1521 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1522 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1523 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1524 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1525 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1526 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1527 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1528 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1529 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1531 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1532 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1533 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1535 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1536 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1537 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1538 { "-premove", "premove", XrmoptionSepArg, NULL },
1539 { "-pre", "premove", XrmoptionNoArg, "True" },
1540 { "-xpre", "premove", XrmoptionNoArg, "False" },
1541 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1542 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1543 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1544 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1545 { "-flip", "flipView", XrmoptionNoArg, "True" },
1546 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1547 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1548 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1549 XrmoptionSepArg, NULL },
1550 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1551 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1552 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1553 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1554 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1555 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1556 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1557 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1558 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1559 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1560 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1562 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1563 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1564 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1565 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1566 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1567 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1568 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1569 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1570 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1571 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1572 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1573 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1574 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1575 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1576 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1577 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1578 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1579 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1580 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1581 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1582 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1583 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1584 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1585 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1586 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1587 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1588 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1589 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1590 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1591 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1592 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1594 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1595 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1596 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1597 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1598 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1599 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1600 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1601 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1602 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1603 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1604 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1605 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1606 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1607 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1608 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1609 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1610 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1611 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1612 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1613 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1614 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1615 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1616 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1617 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1618 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1619 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1620 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1621 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1622 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1623 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1624 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1625 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1626 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1627 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1628 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1629 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1630 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1631 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1632 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1633 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1634 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1635 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1636 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1637 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1638 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1639 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1640 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1641 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1642 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1643 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1644 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1645 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1646 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1647 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1648 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1649 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1650 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1651 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1652 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1653 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1654 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1655 { "-variant", "variant", XrmoptionSepArg, NULL },
1656 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1657 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1658 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1659 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1660 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1661 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1662 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1663 /* [AS,HR] New features */
1664 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1665 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1666 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1667 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1668 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1669 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1670 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1671 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1672 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1673 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1674 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1675 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1676 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1677 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1678 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1679 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1680 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1681 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1682 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1683 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1684 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1685 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1686 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1687 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1688 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1689 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1691 /* [HGM,HR] User-selectable board size */
1692 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1693 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1694 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1696 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1697 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1698 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1699 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1700 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1701 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1702 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1703 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1704 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1705 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1706 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1707 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1708 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1709 { "-userName", "userName", XrmoptionSepArg, NULL },
1710 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1711 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1712 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1713 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1714 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1715 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1716 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1717 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1718 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1719 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1720 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1721 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1722 { "-userName", "userName", XrmoptionSepArg, NULL },
1723 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1724 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1725 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1726 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1727 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1728 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1729 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1730 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1731 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1732 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1733 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1734 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1735 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1736 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1737 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1738 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1739 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1740 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1741 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1742 { "-autoDisplayTags", "autoDisplayTags", XrmoptionSepArg, NULL },
1743 { "-autoDisplayComment", "autoDisplayComment", XrmoptionSepArg, NULL },
1744 { "-pasteSelection", "pasteSelection", XrmoptionSepArg, NULL },
1747 XtActionsRec boardActions[] = {
1748 // { "HandleUserMove", HandleUserMove },
1749 { "AnimateUserMove", AnimateUserMove },
1750 // { "FileNameAction", FileNameAction },
1751 { "AskQuestionProc", AskQuestionProc },
1752 { "AskQuestionReplyAction", AskQuestionReplyAction },
1753 { "PieceMenuPopup", PieceMenuPopup },
1754 // { "WhiteClock", WhiteClock },
1755 // { "BlackClock", BlackClock },
1756 { "Iconify", Iconify },
1757 { "LoadSelectedProc", LoadSelectedProc },
1758 // { "LoadPositionProc", LoadPositionProc },
1759 // { "LoadNextPositionProc", LoadNextPositionProc },
1760 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1761 // { "ReloadPositionProc", ReloadPositionProc },
1762 { "CopyPositionProc", CopyPositionProc },
1763 { "PastePositionProc", PastePositionProc },
1764 { "CopyGameProc", CopyGameProc },
1765 { "PasteGameProc", PasteGameProc },
1766 // { "SaveGameProc", SaveGameProc },
1767 // { "SavePositionProc", SavePositionProc },
1768 { "MailMoveProc", MailMoveProc },
1769 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1770 // { "MachineWhiteProc", MachineWhiteProc },
1771 // { "MachineBlackProc", MachineBlackProc },
1772 // { "AnalysisModeProc", AnalyzeModeProc },
1773 // { "AnalyzeFileProc", AnalyzeFileProc },
1774 // { "TwoMachinesProc", TwoMachinesProc },
1775 // { "IcsClientProc", IcsClientProc },
1776 // { "EditGameProc", EditGameProc },
1777 // { "EditPositionProc", EditPositionProc },
1778 // { "TrainingProc", EditPositionProc },
1779 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1780 { "ShowGameListProc", ShowGameListProc },
1781 // { "ShowMoveListProc", HistoryShowProc},
1782 // { "EditTagsProc", EditCommentProc },
1783 { "EditCommentProc", EditCommentProc },
1784 // { "IcsAlarmProc", IcsAlarmProc },
1785 { "IcsInputBoxProc", IcsInputBoxProc },
1786 // { "AcceptProc", AcceptProc },
1787 // { "DeclineProc", DeclineProc },
1788 // { "RematchProc", RematchProc },
1789 // { "CallFlagProc", CallFlagProc },
1790 // { "DrawProc", DrawProc },
1791 // { "AdjournProc", AdjournProc },
1792 // { "AbortProc", AbortProc },
1793 // { "ResignProc", ResignProc },
1794 // { "AdjuWhiteProc", AdjuWhiteProc },
1795 // { "AdjuBlackProc", AdjuBlackProc },
1796 // { "AdjuDrawProc", AdjuDrawProc },
1797 { "EnterKeyProc", EnterKeyProc },
1798 // { "StopObservingProc", StopObservingProc },
1799 // { "StopExaminingProc", StopExaminingProc },
1800 // { "BackwardProc", BackwardProc },
1801 // { "ForwardProc", ForwardProc },
1802 // { "ToStartProc", ToStartProc },
1803 // { "ToEndProc", ToEndProc },
1804 // { "RevertProc", RevertProc },
1805 // { "TruncateGameProc", TruncateGameProc },
1806 // { "MoveNowProc", MoveNowProc },
1807 // { "RetractMoveProc", RetractMoveProc },
1808 // { "AlwaysQueenProc", AlwaysQueenProc },
1809 // { "AnimateDraggingProc", AnimateDraggingProc },
1810 // { "AnimateMovingProc", AnimateMovingProc },
1811 // { "AutoflagProc", AutoflagProc },
1812 // { "AutoflipProc", AutoflipProc },
1813 // { "AutobsProc", AutobsProc },
1814 // { "AutoraiseProc", AutoraiseProc },
1815 // { "AutosaveProc", AutosaveProc },
1816 // { "BlindfoldProc", BlindfoldProc },
1817 // { "FlashMovesProc", FlashMovesProc },
1818 // { "FlipViewProc", FlipViewProc },
1819 // { "GetMoveListProc", GetMoveListProc },
1821 // { "HighlightDraggingProc", HighlightDraggingProc },
1823 // { "HighlightLastMoveProc", HighlightLastMoveProc },
1824 // { "IcsAlarmProc", IcsAlarmProc },
1825 // { "MoveSoundProc", MoveSoundProc },
1826 // { "OldSaveStyleProc", OldSaveStyleProc },
1827 // { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1828 // { "PonderNextMoveProc", PonderNextMoveProc },
1829 // { "PopupExitMessageProc", PopupExitMessageProc },
1830 // { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1831 // { "PremoveProc", PremoveProc },
1832 // { "QuietPlayProc", QuietPlayProc },
1833 // { "ShowThinkingProc", ShowThinkingProc },
1834 // { "HideThinkingProc", HideThinkingProc },
1835 { "TestLegalityProc", TestLegalityProc },
1836 // { "InfoProc", InfoProc },
1837 // { "ManProc", ManProc },
1838 // { "HintProc", HintProc },
1839 // { "BookProc", BookProc },
1840 { "AboutGameProc", AboutGameProc },
1841 { "DebugProc", DebugProc },
1842 { "NothingProc", NothingProc },
1843 { "CommentPopDown", (XtActionProc) CommentPopDown },
1844 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1845 { "TagsPopDown", (XtActionProc) TagsPopDown },
1846 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1847 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1848 // { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1849 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1850 { "GameListPopDown", (XtActionProc) GameListPopDown },
1851 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1852 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1853 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1854 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1855 { "EnginePopDown", (XtActionProc) EnginePopDown },
1856 { "UciPopDown", (XtActionProc) UciPopDown },
1857 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1858 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1859 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1863 char ICSInputTranslations[] =
1864 "<Key>Return: EnterKeyProc() \n";
1866 String xboardResources[] = {
1867 // "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1868 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1869 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1873 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1874 "magenta", "cyan", "white" };
1878 TextColors textColors[(int)NColorClasses];
1880 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1882 parse_color(str, which)
1886 char *p, buf[100], *d;
1889 if (strlen(str) > 99) /* watch bounds on buf */
1894 for (i=0; i<which; ++i) {
1901 /* Could be looking at something like:
1903 .. in which case we want to stop on a comma also */
1904 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1908 return -1; /* Use default for empty field */
1911 if (which == 2 || isdigit(*p))
1914 while (*p && isalpha(*p))
1919 for (i=0; i<8; ++i) {
1920 if (!StrCaseCmp(buf, cnames[i]))
1921 return which? (i+40) : (i+30);
1923 if (!StrCaseCmp(buf, "default")) return -1;
1925 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1930 parse_cpair(cc, str)
1934 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1935 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1940 /* bg and attr are optional */
1941 textColors[(int)cc].bg = parse_color(str, 1);
1942 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1943 textColors[(int)cc].attr = 0;
1949 /* Arrange to catch delete-window events */
1950 Atom wm_delete_window;
1952 CatchDeleteWindow(Widget w, String procname)
1955 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1956 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1957 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1963 /* this should raise the board to the top */
1964 gtk_window_present(GTK_WINDOW(GUI_Window));
1968 #define BoardSize int
1969 void InitDrawingSizes(BoardSize boardSize, int flags)
1970 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1971 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1973 XtGeometryResult gres;
1976 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1977 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1979 timerWidth = (boardWidth - sep) / 2;
1981 if (appData.titleInWindow)
1986 w = boardWidth - 2*bor;
1990 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1994 if(!formWidget) return;
1997 * Inhibit shell resizing.
2000 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2003 for(i=0; i<4; i++) {
2005 for(p=0; p<=(int)WhiteKing; p++)
2006 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2007 if(gameInfo.variant == VariantShogi) {
2008 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2009 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2010 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2011 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2012 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2015 if(gameInfo.variant == VariantGothic) {
2016 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2020 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2021 for(p=0; p<=(int)WhiteKing; p++)
2022 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2023 if(gameInfo.variant == VariantShogi) {
2024 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2025 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2026 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2027 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2028 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2031 if(gameInfo.variant == VariantGothic) {
2032 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2038 for(i=0; i<2; i++) {
2040 for(p=0; p<=(int)WhiteKing; p++)
2041 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2042 if(gameInfo.variant == VariantShogi) {
2043 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2044 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2045 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2046 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2047 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2050 if(gameInfo.variant == VariantGothic) {
2051 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2061 void EscapeExpand(char *p, char *q)
2062 { // [HGM] initstring: routine to shape up string arguments
2063 while(*p++ = *q++) if(p[-1] == '\\')
2065 case 'n': p[-1] = '\n'; break;
2066 case 'r': p[-1] = '\r'; break;
2067 case 't': p[-1] = '\t'; break;
2068 case '\\': p[-1] = '\\'; break;
2069 case 0: *p = 0; return;
2070 default: p[-1] = q[-1]; break;
2079 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2080 XSetWindowAttributes window_attributes;
2082 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2083 XrmValue vFrom, vTo;
2084 XtGeometryResult gres;
2087 int forceMono = False;
2091 // [HGM] before anything else, expand any indirection files amongst options
2092 char *argvCopy[1000]; // 1000 seems enough
2093 char newArgs[10000]; // holds actual characters
2096 srandom(time(0)); // [HGM] book: make random truly random
2099 for(i=0; i<argc; i++) {
2100 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2101 //fprintf(stderr, "arg %s\n", argv[i]);
2102 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2104 FILE *f = fopen(argv[i]+1, "rb");
2105 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2106 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2107 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2109 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2110 newArgs[k++] = 0; // terminate current arg
2111 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2112 argvCopy[j++] = newArgs + k; // get ready for next
2114 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2128 setbuf(stdout, NULL);
2129 setbuf(stderr, NULL);
2132 programName = strrchr(argv[0], '/');
2133 if (programName == NULL)
2134 programName = argv[0];
2139 XtSetLanguageProc(NULL, NULL, NULL);
2140 bindtextdomain(PACKAGE, LOCALEDIR);
2141 textdomain(PACKAGE);
2145 XtAppInitialize(&appContext, "XBoard", shellOptions,
2146 XtNumber(shellOptions),
2147 &argc, argv, xboardResources, NULL, 0);
2150 gtk_init (&argc, &argv);
2152 /* parse glade file to build widgets */
2154 builder = gtk_builder_new ();
2155 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2157 /* test if everything worked ok */
2159 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2160 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2162 GUI_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2163 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2165 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2166 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2168 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2169 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2170 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2171 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2172 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2173 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2174 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2175 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2177 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2178 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2180 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2181 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2183 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2184 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2186 /* EditTags window */
2187 GUI_EditTags = GTK_WIDGET (gtk_builder_get_object (builder, "EditTags"));
2188 if(!GUI_EditTags) printf("Error: gtk_builder didn't work!\n");
2190 GUI_EditTagsTextArea = GTK_WIDGET (gtk_builder_get_object (builder, "EditTagsTextArea"));
2191 if(!GUI_EditTagsTextArea) printf("Error: gtk_builder didn't work!\n");
2194 gtk_builder_connect_signals (builder, NULL);
2196 // don't unref the builder, since we use it to get references to widgets
2197 // g_object_unref (G_OBJECT (builder));
2199 /* end parse glade file */
2203 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2204 programName, argv[1]);
2206 fprintf(stderr, "Recognized options:\n");
2207 for(i = 0; i < XtNumber(shellOptions); i++)
2209 /* print first column */
2210 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2211 (shellOptions[i].argKind == XrmoptionSepArg
2213 /* print second column and end line */
2214 if (++i < XtNumber(shellOptions))
2216 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2217 shellOptions[i].option,
2218 (shellOptions[i].argKind == XrmoptionSepArg
2223 fprintf(stderr, "\n");
2230 if (p == NULL) p = "/tmp";
2231 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2232 gameCopyFilename = (char*) malloc(i);
2233 gamePasteFilename = (char*) malloc(i);
2234 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2235 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2237 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2238 clientResources, XtNumber(clientResources),
2241 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2242 static char buf[MSG_SIZ];
2243 EscapeExpand(buf, appData.initString);
2244 appData.initString = strdup(buf);
2245 EscapeExpand(buf, appData.secondInitString);
2246 appData.secondInitString = strdup(buf);
2247 EscapeExpand(buf, appData.firstComputerString);
2248 appData.firstComputerString = strdup(buf);
2249 EscapeExpand(buf, appData.secondComputerString);
2250 appData.secondComputerString = strdup(buf);
2253 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2256 if (chdir(chessDir) != 0) {
2257 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2263 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2264 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2265 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2266 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2269 setbuf(debugFP, NULL);
2272 /* [HGM,HR] make sure board size is acceptable */
2273 if(appData.NrFiles > BOARD_SIZE ||
2274 appData.NrRanks > BOARD_SIZE )
2275 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2278 /* This feature does not work; animation needs a rewrite */
2279 appData.highlightDragging = FALSE;
2283 xDisplay = XtDisplay(shellWidget);
2284 xScreen = DefaultScreen(xDisplay);
2285 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2287 gameInfo.variant = StringToVariant(appData.variant);
2288 InitPosition(FALSE);
2290 /* calc board size */
2291 if (isdigit(appData.boardSize[0]))
2293 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2294 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2295 &fontPxlSize, &smallLayout, &tinyLayout);
2298 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2299 programName, appData.boardSize);
2304 /* Find some defaults; use the nearest known size */
2305 SizeDefaults *szd, *nearest;
2306 int distance = 99999;
2307 nearest = szd = sizeDefaults;
2308 while (szd->name != NULL)
2310 if (abs(szd->squareSize - squareSize) < distance)
2313 distance = abs(szd->squareSize - squareSize);
2314 if (distance == 0) break;
2318 if (i < 2) lineGap = nearest->lineGap;
2319 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2320 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2321 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2322 if (i < 6) smallLayout = nearest->smallLayout;
2323 if (i < 7) tinyLayout = nearest->tinyLayout;
2328 SizeDefaults *szd = sizeDefaults;
2329 if (*appData.boardSize == NULLCHAR)
2331 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2332 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2336 if (szd->name == NULL) szd--;
2340 while (szd->name != NULL
2341 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2343 if (szd->name == NULL)
2345 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2346 programName, appData.boardSize);
2350 squareSize = szd->squareSize;
2351 lineGap = szd->lineGap;
2352 clockFontPxlSize = szd->clockFontPxlSize;
2353 coordFontPxlSize = szd->coordFontPxlSize;
2354 fontPxlSize = szd->fontPxlSize;
2355 smallLayout = szd->smallLayout;
2356 tinyLayout = szd->tinyLayout;
2358 /* end figuring out what size to use */
2360 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2361 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2364 * Determine what fonts to use.
2366 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2367 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2368 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2369 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2370 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2371 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2372 appData.font = FindFont(appData.font, fontPxlSize);
2373 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2374 countFontStruct = XQueryFont(xDisplay, countFontID);
2375 // appData.font = FindFont(appData.font, fontPxlSize);
2377 xdb = XtDatabase(xDisplay);
2378 XrmPutStringResource(&xdb, "*font", appData.font);
2381 * Detect if there are not enough colors available and adapt.
2383 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2384 appData.monoMode = True;
2387 if (!appData.monoMode) {
2388 vFrom.addr = (caddr_t) appData.lightSquareColor;
2389 vFrom.size = strlen(appData.lightSquareColor);
2390 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2391 if (vTo.addr == NULL) {
2392 appData.monoMode = True;
2395 lightSquareColor = *(Pixel *) vTo.addr;
2398 if (!appData.monoMode) {
2399 vFrom.addr = (caddr_t) appData.darkSquareColor;
2400 vFrom.size = strlen(appData.darkSquareColor);
2401 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2402 if (vTo.addr == NULL) {
2403 appData.monoMode = True;
2406 darkSquareColor = *(Pixel *) vTo.addr;
2409 if (!appData.monoMode) {
2410 vFrom.addr = (caddr_t) appData.whitePieceColor;
2411 vFrom.size = strlen(appData.whitePieceColor);
2412 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2413 if (vTo.addr == NULL) {
2414 appData.monoMode = True;
2417 whitePieceColor = *(Pixel *) vTo.addr;
2420 if (!appData.monoMode) {
2421 vFrom.addr = (caddr_t) appData.blackPieceColor;
2422 vFrom.size = strlen(appData.blackPieceColor);
2423 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2424 if (vTo.addr == NULL) {
2425 appData.monoMode = True;
2428 blackPieceColor = *(Pixel *) vTo.addr;
2432 if (!appData.monoMode) {
2433 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2434 vFrom.size = strlen(appData.highlightSquareColor);
2435 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2436 if (vTo.addr == NULL) {
2437 appData.monoMode = True;
2440 highlightSquareColor = *(Pixel *) vTo.addr;
2444 if (!appData.monoMode) {
2445 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2446 vFrom.size = strlen(appData.premoveHighlightColor);
2447 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2448 if (vTo.addr == NULL) {
2449 appData.monoMode = True;
2452 premoveHighlightColor = *(Pixel *) vTo.addr;
2457 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2460 if (appData.bitmapDirectory == NULL ||
2461 appData.bitmapDirectory[0] == NULLCHAR)
2462 appData.bitmapDirectory = DEF_BITMAP_DIR;
2465 if (appData.lowTimeWarning && !appData.monoMode) {
2466 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2467 vFrom.size = strlen(appData.lowTimeWarningColor);
2468 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2469 if (vTo.addr == NULL)
2470 appData.monoMode = True;
2472 lowTimeWarningColor = *(Pixel *) vTo.addr;
2475 if (appData.monoMode && appData.debugMode) {
2476 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2477 (unsigned long) XWhitePixel(xDisplay, xScreen),
2478 (unsigned long) XBlackPixel(xDisplay, xScreen));
2481 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2482 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2483 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2484 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2485 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2486 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2487 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2488 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2489 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2490 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2492 if (appData.colorize) {
2494 _("%s: can't parse color names; disabling colorization\n"),
2497 appData.colorize = FALSE;
2499 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2500 textColors[ColorNone].attr = 0;
2502 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2508 layoutName = "tinyLayout";
2509 } else if (smallLayout) {
2510 layoutName = "smallLayout";
2512 layoutName = "normalLayout";
2515 if (appData.titleInWindow) {
2516 /* todo check what this appdata does */
2519 if (appData.showButtonBar) {
2520 /* TODO hide button bar if requested */
2524 if (appData.titleInWindow)
2529 if (appData.showButtonBar)
2536 if (appData.showButtonBar)
2546 /* set some checkboxes in the menu according to appData */
2548 if (appData.alwaysPromoteToQueen)
2549 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2551 if (appData.animateDragging)
2552 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2554 if (appData.animate)
2555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2557 if (appData.autoComment)
2558 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2560 if (appData.autoCallFlag)
2561 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2563 if (appData.autoFlipView)
2564 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2566 if (appData.autoObserve)
2567 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2569 if (appData.autoRaiseBoard)
2570 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2572 if (appData.autoSaveGames)
2573 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2575 if (appData.saveGameFile[0] != NULLCHAR)
2577 /* Can't turn this off from menu */
2578 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2579 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2582 if (appData.blindfold)
2583 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2585 if (appData.flashCount > 0)
2586 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2588 if (appData.getMoveList)
2589 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2592 if (appData.highlightDragging)
2593 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2596 if (appData.highlightLastMove)
2597 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2599 if (appData.icsAlarm)
2600 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2602 if (appData.ringBellAfterMoves)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2605 if (appData.oldSaveStyle)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2608 if (appData.periodicUpdates)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2611 if (appData.ponderNextMove)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2614 if (appData.popupExitMessage)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2617 if (appData.popupMoveErrors)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2620 if (appData.premove)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2623 if (appData.quietPlay)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2626 if (appData.showCoords)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2629 if (appData.showThinking)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2632 if (appData.testLegality)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2635 /* end setting check boxes */
2637 /* load square colors */
2638 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2639 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2640 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2642 /* use two icons to indicate if it is white's or black's turn */
2643 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2644 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2645 WindowIcon = WhiteIcon;
2646 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2649 /* realize window */
2650 gtk_widget_show (GUI_Window);
2652 /* recalc boardsize */
2657 if (appData.animate || appData.animateDragging)
2662 if (errorExitStatus == -1) {
2663 if (appData.icsActive) {
2664 /* We now wait until we see "login:" from the ICS before
2665 sending the logon script (problems with timestamp otherwise) */
2666 /*ICSInitScript();*/
2667 if (appData.icsInputBox) ICSInputBoxPopUp();
2671 signal(SIGWINCH, TermSizeSigHandler);
2673 signal(SIGINT, IntSigHandler);
2674 signal(SIGTERM, IntSigHandler);
2675 if (*appData.cmailGameName != NULLCHAR) {
2676 signal(SIGUSR1, CmailSigHandler);
2679 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2683 * Create a cursor for the board widget.
2684 * (This needs to be called after the window has been created to have access to board-window)
2687 BoardCursor = gdk_cursor_new(GDK_HAND2);
2688 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2689 gdk_cursor_destroy(BoardCursor);
2694 if (appData.debugMode) fclose(debugFP); // [DM] debug
2701 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2702 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2704 unlink(gameCopyFilename);
2705 unlink(gamePasteFilename);
2708 RETSIGTYPE TermSizeSigHandler(int sig)
2721 CmailSigHandler(sig)
2727 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2729 /* Activate call-back function CmailSigHandlerCallBack() */
2730 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2732 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2736 CmailSigHandlerCallBack(isr, closure, message, count, error)
2744 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2746 /**** end signal code ****/
2756 f = fopen(appData.icsLogon, "r");
2762 strcat(buf, appData.icsLogon);
2763 f = fopen(buf, "r");
2767 ProcessICSInitScript(f);
2774 EditCommentPopDown();
2780 SetMenuEnables(enab)
2785 if (!builder) return;
2786 while (enab->name != NULL) {
2787 o = gtk_builder_get_object(builder, enab->name);
2788 if(GTK_IS_WIDGET(o))
2789 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2792 if(GTK_IS_ACTION(o))
2793 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2795 DisplayError(enab->name, 0);
2803 SetMenuEnables(icsEnables);
2806 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2807 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2814 SetMenuEnables(ncpEnables);
2820 SetMenuEnables(gnuEnables);
2826 SetMenuEnables(cmailEnables);
2832 SetMenuEnables(trainingOnEnables);
2833 if (appData.showButtonBar) {
2834 // XtSetSensitive(buttonBarWidget, False);
2840 SetTrainingModeOff()
2842 SetMenuEnables(trainingOffEnables);
2843 if (appData.showButtonBar) {
2844 // XtSetSensitive(buttonBarWidget, True);
2849 SetUserThinkingEnables()
2851 if (appData.noChessProgram) return;
2852 SetMenuEnables(userThinkingEnables);
2856 SetMachineThinkingEnables()
2858 if (appData.noChessProgram) return;
2859 SetMenuEnables(machineThinkingEnables);
2861 case MachinePlaysBlack:
2862 case MachinePlaysWhite:
2863 case TwoMachinesPlay:
2864 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2865 // ModeToWidgetName(gameMode)), True);
2872 #define Abs(n) ((n)<0 ? -(n) : (n))
2875 * Find a font that matches "pattern" that is as close as
2876 * possible to the targetPxlSize. Prefer fonts that are k
2877 * pixels smaller to fonts that are k pixels larger. The
2878 * pattern must be in the X Consortium standard format,
2879 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2880 * The return value should be freed with XtFree when no
2883 char *FindFont(pattern, targetPxlSize)
2887 char **fonts, *p, *best, *scalable, *scalableTail;
2888 int i, j, nfonts, minerr, err, pxlSize;
2891 char **missing_list;
2893 char *def_string, *base_fnt_lst, strInt[3];
2895 XFontStruct **fnt_list;
2897 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2898 sprintf(strInt, "%d", targetPxlSize);
2899 p = strstr(pattern, "--");
2900 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2901 strcat(base_fnt_lst, strInt);
2902 strcat(base_fnt_lst, strchr(p + 2, '-'));
2904 if ((fntSet = XCreateFontSet(xDisplay,
2908 &def_string)) == NULL) {
2910 fprintf(stderr, _("Unable to create font set.\n"));
2914 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2916 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2918 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2919 programName, pattern);
2927 for (i=0; i<nfonts; i++) {
2930 if (*p != '-') continue;
2932 if (*p == NULLCHAR) break;
2933 if (*p++ == '-') j++;
2935 if (j < 7) continue;
2938 scalable = fonts[i];
2941 err = pxlSize - targetPxlSize;
2942 if (Abs(err) < Abs(minerr) ||
2943 (minerr > 0 && err < 0 && -err == minerr)) {
2949 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2950 /* If the error is too big and there is a scalable font,
2951 use the scalable font. */
2952 int headlen = scalableTail - scalable;
2953 p = (char *) XtMalloc(strlen(scalable) + 10);
2954 while (isdigit(*scalableTail)) scalableTail++;
2955 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2957 p = (char *) XtMalloc(strlen(best) + 1);
2960 if (appData.debugMode) {
2961 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2962 pattern, targetPxlSize, p);
2965 if (missing_count > 0)
2966 XFreeStringList(missing_list);
2967 XFreeFontSet(xDisplay, fntSet);
2969 XFreeFontNames(fonts);
2976 /* GCs are not needed anymore for GTK just left them in here for the moment, since there is a lot of X-code still around that's wants them*/
2978 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2979 | GCBackground | GCFunction | GCPlaneMask;
2980 XGCValues gc_values;
2983 gc_values.plane_mask = AllPlanes;
2984 gc_values.line_width = lineGap;
2985 gc_values.line_style = LineSolid;
2986 gc_values.function = GXcopy;
2988 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2989 gc_values.background = XWhitePixel(xDisplay, xScreen);
2990 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2991 XSetFont(xDisplay, coordGC, coordFontID);
2993 if (appData.monoMode) {
2994 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2995 gc_values.background = XBlackPixel(xDisplay, xScreen);
2996 lightSquareGC = wbPieceGC
2997 = XtGetGC(shellWidget, value_mask, &gc_values);
2999 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3000 gc_values.background = XWhitePixel(xDisplay, xScreen);
3001 darkSquareGC = bwPieceGC
3002 = XtGetGC(shellWidget, value_mask, &gc_values);
3004 if (DefaultDepth(xDisplay, xScreen) == 1) {
3005 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3006 gc_values.function = GXcopyInverted;
3007 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3008 gc_values.function = GXcopy;
3009 if (XBlackPixel(xDisplay, xScreen) == 1) {
3010 bwPieceGC = darkSquareGC;
3011 wbPieceGC = copyInvertedGC;
3013 bwPieceGC = copyInvertedGC;
3014 wbPieceGC = lightSquareGC;
3018 gc_values.foreground = lightSquareColor;
3019 gc_values.background = darkSquareColor;
3020 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3022 gc_values.foreground = darkSquareColor;
3023 gc_values.background = lightSquareColor;
3024 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3026 gc_values.foreground = jailSquareColor;
3027 gc_values.background = jailSquareColor;
3028 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3030 gc_values.foreground = whitePieceColor;
3031 gc_values.background = darkSquareColor;
3032 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3034 gc_values.foreground = whitePieceColor;
3035 gc_values.background = lightSquareColor;
3036 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3038 gc_values.foreground = whitePieceColor;
3039 gc_values.background = jailSquareColor;
3040 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3042 gc_values.foreground = blackPieceColor;
3043 gc_values.background = darkSquareColor;
3044 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3046 gc_values.foreground = blackPieceColor;
3047 gc_values.background = lightSquareColor;
3048 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3050 gc_values.foreground = blackPieceColor;
3051 gc_values.background = jailSquareColor;
3052 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3061 for(i=0;i<MAXPIECES;i++)
3065 g_free(SVGpieces[i]);
3072 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3073 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3074 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3077 /* get some defaults going */
3078 for(i=WhitePawn; i<DemotePiece+1; i++)
3079 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3081 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3082 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3083 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3084 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3085 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3086 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3088 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3089 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3090 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3091 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3092 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3093 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3099 static void MenuBarSelect(w, addr, index)
3104 XtActionProc proc = (XtActionProc) addr;
3106 (proc)(NULL, NULL, NULL, NULL);
3109 void CreateMenuBarPopup(parent, name, mb)
3119 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3122 XtSetArg(args[j], XtNleftMargin, 20); j++;
3123 XtSetArg(args[j], XtNrightMargin, 20); j++;
3125 while (mi->string != NULL) {
3126 if (strcmp(mi->string, "----") == 0) {
3127 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3130 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3131 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3133 XtAddCallback(entry, XtNcallback,
3134 (XtCallbackProc) MenuBarSelect,
3135 (caddr_t) mi->proc);
3141 Widget CreateMenuBar(mb)
3145 Widget anchor, menuBar;
3147 char menuName[MSG_SIZ];
3150 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3151 XtSetArg(args[j], XtNvSpace, 0); j++;
3152 XtSetArg(args[j], XtNborderWidth, 0); j++;
3153 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3154 formWidget, args, j);
3156 while (mb->name != NULL) {
3157 strcpy(menuName, "menu");
3158 strcat(menuName, mb->name);
3160 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3163 shortName[0] = _(mb->name)[0];
3164 shortName[1] = NULLCHAR;
3165 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3168 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3171 XtSetArg(args[j], XtNborderWidth, 0); j++;
3172 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3174 CreateMenuBarPopup(menuBar, menuName, mb);
3182 CreatePieceMenu(name, color)
3189 ChessSquare selection;
3191 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3192 boardWidget, args, 0);
3194 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3195 String item = pieceMenuStrings[color][i];
3197 if (strcmp(item, "----") == 0) {
3198 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3201 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3202 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3204 selection = pieceMenuTranslation[color][i];
3205 XtAddCallback(entry, XtNcallback,
3206 (XtCallbackProc) PieceMenuSelect,
3207 (caddr_t) selection);
3208 if (selection == WhitePawn || selection == BlackPawn) {
3209 XtSetArg(args[0], XtNpopupOnEntry, entry);
3210 XtSetValues(menu, args, 1);
3223 ChessSquare selection;
3225 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3226 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3228 // XtRegisterGrabAction(PieceMenuPopup, True,
3229 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3230 // GrabModeAsync, GrabModeAsync);
3232 // XtSetArg(args[0], XtNlabel, _("Drop"));
3233 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3234 // boardWidget, args, 1);
3235 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3236 // String item = dropMenuStrings[i];
3238 // if (strcmp(item, "----") == 0) {
3239 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3240 // dropMenu, NULL, 0);
3242 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3243 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3244 // dropMenu, args, 1);
3245 // selection = dropMenuTranslation[i];
3246 // XtAddCallback(entry, XtNcallback,
3247 // (XtCallbackProc) DropMenuSelect,
3248 // (caddr_t) selection);
3253 void SetupDropMenu()
3261 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3262 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3263 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3264 dmEnables[i].piece);
3265 XtSetSensitive(entry, p != NULL || !appData.testLegality
3266 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3267 && !appData.icsActive));
3269 while (p && *p++ == dmEnables[i].piece) count++;
3270 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3272 XtSetArg(args[j], XtNlabel, label); j++;
3273 XtSetValues(entry, args, j);
3277 void PieceMenuPopup(w, event, params, num_params)
3281 Cardinal *num_params;
3284 if (event->type != ButtonPress) return;
3285 if (errorUp) ErrorPopDown();
3289 whichMenu = params[0];
3291 case IcsPlayingWhite:
3292 case IcsPlayingBlack:
3294 case MachinePlaysWhite:
3295 case MachinePlaysBlack:
3296 if (appData.testLegality &&
3297 gameInfo.variant != VariantBughouse &&
3298 gameInfo.variant != VariantCrazyhouse) return;
3300 whichMenu = "menuD";
3306 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3307 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3308 pmFromX = pmFromY = -1;
3312 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3314 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3316 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3319 static void PieceMenuSelect(w, piece, junk)
3324 if (pmFromX < 0 || pmFromY < 0) return;
3325 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3328 static void DropMenuSelect(w, piece, junk)
3333 if (pmFromX < 0 || pmFromY < 0) return;
3334 DropMenuEvent(piece, pmFromX, pmFromY);
3338 * If the user selects on a border boundary, return -1; if off the board,
3339 * return -2. Otherwise map the event coordinate to the square.
3341 int EventToSquare(x, limit)
3349 if ((x % (squareSize + lineGap)) >= squareSize)
3351 x /= (squareSize + lineGap);
3357 static void do_flash_delay(msec)
3363 static void drawHighlight(file, rank, line_type)
3364 int file, rank, line_type;
3369 if (lineGap == 0 || appData.blindfold) return;
3373 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3374 (squareSize + lineGap);
3375 y = lineGap/2 + rank * (squareSize + lineGap);
3379 x = lineGap/2 + file * (squareSize + lineGap);
3380 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3381 (squareSize + lineGap);
3385 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3387 /* draw the highlight */
3388 cairo_move_to (cr, x, y);
3389 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3390 cairo_rel_line_to (cr, squareSize+lineGap,0);
3391 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3392 cairo_close_path (cr);
3394 cairo_set_line_width (cr, lineGap);
3397 /* TODO: use appdata colors */
3398 case LINE_TYPE_HIGHLIGHT:
3399 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3402 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3404 case LINE_TYPE_NORMAL:
3406 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3417 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3418 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3421 SetHighlights(fromX, fromY, toX, toY)
3422 int fromX, fromY, toX, toY;
3424 if (hi1X != fromX || hi1Y != fromY)
3426 if (hi1X >= 0 && hi1Y >= 0)
3428 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3430 if (fromX >= 0 && fromY >= 0)
3432 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3435 if (hi2X != toX || hi2Y != toY)
3437 if (hi2X >= 0 && hi2Y >= 0)
3439 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3441 if (toX >= 0 && toY >= 0)
3443 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3457 SetHighlights(-1, -1, -1, -1);
3462 SetPremoveHighlights(fromX, fromY, toX, toY)
3463 int fromX, fromY, toX, toY;
3465 if (pm1X != fromX || pm1Y != fromY)
3467 if (pm1X >= 0 && pm1Y >= 0)
3469 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3471 if (fromX >= 0 && fromY >= 0)
3473 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3476 if (pm2X != toX || pm2Y != toY)
3478 if (pm2X >= 0 && pm2Y >= 0)
3480 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3482 if (toX >= 0 && toY >= 0)
3484 drawHighlight(toX, toY, LINE_TYPE_PRE);
3497 ClearPremoveHighlights()
3499 SetPremoveHighlights(-1, -1, -1, -1);
3502 static void BlankSquare(x, y, color, piece, dest)
3515 pb = SVGLightSquare;
3517 case 2: /* neutral */
3519 pb = SVGNeutralSquare;
3522 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3526 static void DrawPiece(piece, square_color, x, y, dest)
3528 int square_color, x, y;
3531 /* redraw background, since piece might be transparent in some areas */
3532 BlankSquare(x,y,square_color,piece,dest);
3535 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3536 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3537 GDK_RGB_DITHER_NORMAL, 0, 0);
3541 /* [HR] determine square color depending on chess variant. */
3542 static int SquareColor(row, column)
3547 if (gameInfo.variant == VariantXiangqi) {
3548 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3550 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3552 } else if (row <= 4) {
3558 square_color = ((column + row) % 2) == 1;
3561 /* [hgm] holdings: next line makes all holdings squares light */
3562 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3564 return square_color;
3567 void DrawSquare(row, column, piece, do_flash)
3568 int row, column, do_flash;
3571 int square_color, x, y;
3576 /* Calculate delay in milliseconds (2-delays per complete flash) */
3577 flash_delay = 500 / appData.flashRate;
3579 /* calculate x and y coordinates from row and column */
3582 x = lineGap + ((BOARD_WIDTH-1)-column) *
3583 (squareSize + lineGap);
3584 y = lineGap + row * (squareSize + lineGap);
3588 x = lineGap + column * (squareSize + lineGap);
3589 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3590 (squareSize + lineGap);
3593 square_color = SquareColor(row, column);
3595 // [HGM] holdings: blank out area between board and holdings
3596 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3597 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3598 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3600 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3602 // [HGM] print piece counts next to holdings
3603 string[1] = NULLCHAR;
3606 cairo_text_extents_t extents;
3611 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3613 string[0] = '0' + piece;
3615 /* TODO this has to go into the font-selection */
3616 cairo_select_font_face (cr, "Sans",
3617 CAIRO_FONT_SLANT_NORMAL,
3618 CAIRO_FONT_WEIGHT_NORMAL);
3620 cairo_set_font_size (cr, 12.0);
3621 cairo_text_extents (cr, string, &extents);
3623 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3625 xpos= x + squareSize - extents.width - 2;
3626 ypos= y + extents.y_bearing + 1;
3628 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3631 ypos = y + extents.y_bearing + 1;
3634 /* TODO mono mode? */
3635 cairo_move_to (cr, xpos, ypos);
3636 cairo_text_path (cr, string);
3637 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3638 cairo_fill_preserve (cr);
3639 cairo_set_source_rgb (cr, 0, 0, 0);
3640 cairo_set_line_width (cr, 0.1);
3649 /* square on the board */
3650 if (piece == EmptySquare || appData.blindfold)
3652 BlankSquare(x, y, square_color, piece, xBoardWindow);
3656 if (do_flash && appData.flashCount > 0)
3658 for (i=0; i<appData.flashCount; ++i)
3661 DrawPiece(piece, square_color, x, y, xBoardWindow);
3662 do_flash_delay(flash_delay);
3664 BlankSquare(x, y, square_color, piece, xBoardWindow);
3665 do_flash_delay(flash_delay);
3668 DrawPiece(piece, square_color, x, y, xBoardWindow);
3672 /* show coordinates if necessary */
3673 if(appData.showCoords)
3675 cairo_text_extents_t extents;
3679 /* TODO this has to go into the font-selection */
3680 cairo_select_font_face (cr, "Sans",
3681 CAIRO_FONT_SLANT_NORMAL,
3682 CAIRO_FONT_WEIGHT_NORMAL);
3683 cairo_set_font_size (cr, 12.0);
3685 string[1] = NULLCHAR;
3688 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3690 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3691 column >= BOARD_LEFT && column < BOARD_RGHT)
3693 string[0] = 'a' + column - BOARD_LEFT;
3694 cairo_text_extents (cr, string, &extents);
3696 xpos = x + squareSize - extents.width - 2;
3697 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3699 if (appData.monoMode)
3706 cairo_move_to (cr, xpos, ypos);
3707 cairo_text_path (cr, string);
3708 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3709 cairo_fill_preserve (cr);
3710 cairo_set_source_rgb (cr, 0, 1.0, 0);
3711 cairo_set_line_width (cr, 0.1);
3714 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3717 string[0] = ONE + row;
3718 cairo_text_extents (cr, string, &extents);
3721 ypos = y + extents.height + 1;
3723 if (appData.monoMode)
3730 cairo_move_to (cr, xpos, ypos);
3731 cairo_text_path (cr, string);
3732 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3733 cairo_fill_preserve (cr);
3734 cairo_set_source_rgb (cr, 0, 0, 1.0);
3735 cairo_set_line_width (cr, 0.1);
3747 /* Returns 1 if there are "too many" differences between b1 and b2
3748 (i.e. more than 1 move was made) */
3749 static int too_many_diffs(b1, b2)
3755 for (i=0; i<BOARD_HEIGHT; ++i) {
3756 for (j=0; j<BOARD_WIDTH; ++j) {
3757 if (b1[i][j] != b2[i][j]) {
3758 if (++c > 4) /* Castling causes 4 diffs */
3767 /* Matrix describing castling maneuvers */
3768 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3769 static int castling_matrix[4][5] = {
3770 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3771 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3772 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3773 { 7, 7, 4, 5, 6 } /* 0-0, black */
3776 /* Checks whether castling occurred. If it did, *rrow and *rcol
3777 are set to the destination (row,col) of the rook that moved.
3779 Returns 1 if castling occurred, 0 if not.
3781 Note: Only handles a max of 1 castling move, so be sure
3782 to call too_many_diffs() first.
3784 static int check_castle_draw(newb, oldb, rrow, rcol)
3791 /* For each type of castling... */
3792 for (i=0; i<4; ++i) {
3793 r = castling_matrix[i];
3795 /* Check the 4 squares involved in the castling move */
3797 for (j=1; j<=4; ++j) {
3798 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3805 /* All 4 changed, so it must be a castling move */
3814 static int damage[BOARD_SIZE][BOARD_SIZE];
3817 * event handler for redrawing the board
3819 void DrawPosition( repaint, board)
3820 /*Boolean*/int repaint;
3824 static int lastFlipView = 0;
3825 static int lastBoardValid = 0;
3826 static Board lastBoard;
3829 if (board == NULL) {
3830 if (!lastBoardValid) return;
3833 if (!lastBoardValid || lastFlipView != flipView) {
3834 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3835 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3840 * It would be simpler to clear the window with XClearWindow()
3841 * but this causes a very distracting flicker.
3844 if (!repaint && lastBoardValid && lastFlipView == flipView)
3846 /* If too much changes (begin observing new game, etc.), don't
3848 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3850 /* Special check for castling so we don't flash both the king
3851 and the rook (just flash the king). */
3854 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3856 /* Draw rook with NO flashing. King will be drawn flashing later */
3857 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3858 lastBoard[rrow][rcol] = board[rrow][rcol];
3862 /* First pass -- Draw (newly) empty squares and repair damage.
3863 This prevents you from having a piece show up twice while it
3864 is flashing on its new square */
3865 for (i = 0; i < BOARD_HEIGHT; i++)
3866 for (j = 0; j < BOARD_WIDTH; j++)
3867 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3870 DrawSquare(i, j, board[i][j], 0);
3871 damage[i][j] = False;
3874 /* Second pass -- Draw piece(s) in new position and flash them */
3875 for (i = 0; i < BOARD_HEIGHT; i++)
3876 for (j = 0; j < BOARD_WIDTH; j++)
3877 if (board[i][j] != lastBoard[i][j])
3879 DrawSquare(i, j, board[i][j], do_flash);
3891 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3893 cairo_set_line_width (cr, lineGap);
3895 /* TODO: use appdata colors */
3896 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3900 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3903 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3904 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3906 cairo_move_to (cr, x1, y1);
3907 cairo_rel_line_to (cr, x2,0);
3911 for (j = 0; j < BOARD_WIDTH + 1; j++)
3914 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3915 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3917 cairo_move_to (cr, x1, y1);
3918 cairo_rel_line_to (cr, 0, y2);
3927 for (i = 0; i < BOARD_HEIGHT; i++)
3928 for (j = 0; j < BOARD_WIDTH; j++)
3930 DrawSquare(i, j, board[i][j], 0);
3931 damage[i][j] = False;
3935 CopyBoard(lastBoard, board);
3937 lastFlipView = flipView;
3939 /* Draw highlights */
3940 if (pm1X >= 0 && pm1Y >= 0)
3942 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3944 if (pm2X >= 0 && pm2Y >= 0)
3946 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3948 if (hi1X >= 0 && hi1Y >= 0)
3950 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3952 if (hi2X >= 0 && hi2Y >= 0)
3954 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3957 /* If piece being dragged around board, must redraw that too */
3963 void AnimateUserMove (Widget w, XEvent * event,
3964 String * params, Cardinal * nParams)
3966 DragPieceMove(event->xmotion.x, event->xmotion.y);
3969 Widget CommentCreate(name, text, mutable, callback, lines)
3971 int /*Boolean*/ mutable;
3972 XtCallbackProc callback;
3976 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
3981 XtSetArg(args[j], XtNwidth, &bw_width); j++;
3982 XtGetValues(boardWidget, args, j);
3985 XtSetArg(args[j], XtNresizable, True); j++;
3988 XtCreatePopupShell(name, topLevelShellWidgetClass,
3989 shellWidget, args, j);
3992 XtCreatePopupShell(name, transientShellWidgetClass,
3993 shellWidget, args, j);
3996 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
3997 layoutArgs, XtNumber(layoutArgs));
3999 XtCreateManagedWidget("form", formWidgetClass, layout,
4000 formArgs, XtNumber(formArgs));
4004 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4005 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4007 XtSetArg(args[j], XtNstring, text); j++;
4008 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4009 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4010 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4011 XtSetArg(args[j], XtNright, XtChainRight); j++;
4012 XtSetArg(args[j], XtNresizable, True); j++;
4013 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4014 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4015 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4016 XtSetArg(args[j], XtNautoFill, True); j++;
4017 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4019 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4023 XtSetArg(args[j], XtNfromVert, edit); j++;
4024 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4025 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4026 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4027 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4029 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4030 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4033 XtSetArg(args[j], XtNfromVert, edit); j++;
4034 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4035 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4036 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4037 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4038 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4040 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4041 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4044 XtSetArg(args[j], XtNfromVert, edit); j++;
4045 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4046 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4047 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4048 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4049 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4051 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4052 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4055 XtSetArg(args[j], XtNfromVert, edit); j++;
4056 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4057 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4058 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4059 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4061 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4062 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4065 XtSetArg(args[j], XtNfromVert, edit); j++;
4066 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4067 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4068 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4069 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4070 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4072 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4073 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4076 XtRealizeWidget(shell);
4078 if (commentX == -1) {
4081 Dimension pw_height;
4082 Dimension ew_height;
4085 XtSetArg(args[j], XtNheight, &ew_height); j++;
4086 XtGetValues(edit, args, j);
4089 XtSetArg(args[j], XtNheight, &pw_height); j++;
4090 XtGetValues(shell, args, j);
4091 commentH = pw_height + (lines - 1) * ew_height;
4092 commentW = bw_width - 16;
4094 XSync(xDisplay, False);
4096 /* This code seems to tickle an X bug if it is executed too soon
4097 after xboard starts up. The coordinates get transformed as if
4098 the main window was positioned at (0, 0).
4100 XtTranslateCoords(shellWidget,
4101 (bw_width - commentW) / 2, 0 - commentH / 2,
4102 &commentX, &commentY);
4104 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4105 RootWindowOfScreen(XtScreen(shellWidget)),
4106 (bw_width - commentW) / 2, 0 - commentH / 2,
4111 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4114 XtSetArg(args[j], XtNheight, commentH); j++;
4115 XtSetArg(args[j], XtNwidth, commentW); j++;
4116 XtSetArg(args[j], XtNx, commentX); j++;
4117 XtSetArg(args[j], XtNy, commentY); j++;
4118 XtSetValues(shell, args, j);
4119 XtSetKeyboardFocus(shell, edit);
4124 /* Used for analysis window and ICS input window */
4125 Widget MiscCreate(name, text, mutable, callback, lines)
4127 int /*Boolean*/ mutable;
4128 XtCallbackProc callback;
4132 Widget shell, layout, form, edit;
4134 Dimension bw_width, pw_height, ew_height, w, h;
4140 XtSetArg(args[j], XtNresizable, True); j++;
4143 XtCreatePopupShell(name, topLevelShellWidgetClass,
4144 shellWidget, args, j);
4147 XtCreatePopupShell(name, transientShellWidgetClass,
4148 shellWidget, args, j);
4151 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4152 layoutArgs, XtNumber(layoutArgs));
4154 XtCreateManagedWidget("form", formWidgetClass, layout,
4155 formArgs, XtNumber(formArgs));
4159 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4160 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4162 XtSetArg(args[j], XtNstring, text); j++;
4163 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4164 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4165 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4166 XtSetArg(args[j], XtNright, XtChainRight); j++;
4167 XtSetArg(args[j], XtNresizable, True); j++;
4168 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4169 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4170 XtSetArg(args[j], XtNautoFill, True); j++;
4171 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4173 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4175 XtRealizeWidget(shell);
4178 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4179 XtGetValues(boardWidget, args, j);
4182 XtSetArg(args[j], XtNheight, &ew_height); j++;
4183 XtGetValues(edit, args, j);
4186 XtSetArg(args[j], XtNheight, &pw_height); j++;
4187 XtGetValues(shell, args, j);
4188 h = pw_height + (lines - 1) * ew_height;
4191 XSync(xDisplay, False);
4193 /* This code seems to tickle an X bug if it is executed too soon
4194 after xboard starts up. The coordinates get transformed as if
4195 the main window was positioned at (0, 0).
4197 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4199 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4200 RootWindowOfScreen(XtScreen(shellWidget)),
4201 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4205 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4208 XtSetArg(args[j], XtNheight, h); j++;
4209 XtSetArg(args[j], XtNwidth, w); j++;
4210 XtSetArg(args[j], XtNx, x); j++;
4211 XtSetArg(args[j], XtNy, y); j++;
4212 XtSetValues(shell, args, j);
4218 static int savedIndex; /* gross that this is global */
4220 void EditCommentPopUp(index, title, text)
4229 if (text == NULL) text = "";
4231 if (editShell == NULL) {
4233 CommentCreate(title, text, True, EditCommentCallback, 4);
4234 XtRealizeWidget(editShell);
4235 CatchDeleteWindow(editShell, "EditCommentPopDown");
4237 edit = XtNameToWidget(editShell, "*form.text");
4239 XtSetArg(args[j], XtNstring, text); j++;
4240 XtSetValues(edit, args, j);
4242 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4243 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4244 XtSetValues(editShell, args, j);
4247 XtPopup(editShell, XtGrabNone);
4251 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4252 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4256 void EditCommentCallback(w, client_data, call_data)
4258 XtPointer client_data, call_data;
4266 XtSetArg(args[j], XtNlabel, &name); j++;
4267 XtGetValues(w, args, j);
4269 if (strcmp(name, _("ok")) == 0) {
4270 edit = XtNameToWidget(editShell, "*form.text");
4272 XtSetArg(args[j], XtNstring, &val); j++;
4273 XtGetValues(edit, args, j);
4274 ReplaceComment(savedIndex, val);
4275 EditCommentPopDown();
4276 } else if (strcmp(name, _("cancel")) == 0) {
4277 EditCommentPopDown();
4278 } else if (strcmp(name, _("clear")) == 0) {
4279 edit = XtNameToWidget(editShell, "*form.text");
4280 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4281 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4285 void EditCommentPopDown()
4290 if (!editUp) return;
4292 XtSetArg(args[j], XtNx, &commentX); j++;
4293 XtSetArg(args[j], XtNy, &commentY); j++;
4294 XtSetArg(args[j], XtNheight, &commentH); j++;
4295 XtSetArg(args[j], XtNwidth, &commentW); j++;
4296 XtGetValues(editShell, args, j);
4297 XtPopdown(editShell);
4300 XtSetArg(args[j], XtNleftBitmap, None); j++;
4301 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4305 void ICSInputBoxPopUp()
4310 char *title = _("ICS Input");
4313 if (ICSInputShell == NULL) {
4314 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4315 tr = XtParseTranslationTable(ICSInputTranslations);
4316 edit = XtNameToWidget(ICSInputShell, "*form.text");
4317 XtOverrideTranslations(edit, tr);
4318 XtRealizeWidget(ICSInputShell);
4319 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4322 edit = XtNameToWidget(ICSInputShell, "*form.text");
4324 XtSetArg(args[j], XtNstring, ""); j++;
4325 XtSetValues(edit, args, j);
4327 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4328 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4329 XtSetValues(ICSInputShell, args, j);
4332 XtPopup(ICSInputShell, XtGrabNone);
4333 XtSetKeyboardFocus(ICSInputShell, edit);
4335 ICSInputBoxUp = True;
4337 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4338 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4342 void ICSInputSendText()
4349 edit = XtNameToWidget(ICSInputShell, "*form.text");
4351 XtSetArg(args[j], XtNstring, &val); j++;
4352 XtGetValues(edit, args, j);
4353 SendMultiLineToICS(val);
4354 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4355 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4358 void ICSInputBoxPopDown()
4363 if (!ICSInputBoxUp) return;
4365 XtPopdown(ICSInputShell);
4366 ICSInputBoxUp = False;
4368 XtSetArg(args[j], XtNleftBitmap, None); j++;
4369 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4373 void CommentPopUp(title, text)
4380 if (commentShell == NULL) {
4382 CommentCreate(title, text, False, CommentCallback, 4);
4383 XtRealizeWidget(commentShell);
4384 CatchDeleteWindow(commentShell, "CommentPopDown");
4386 edit = XtNameToWidget(commentShell, "*form.text");
4388 XtSetArg(args[j], XtNstring, text); j++;
4389 XtSetValues(edit, args, j);
4391 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4392 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4393 XtSetValues(commentShell, args, j);
4396 XtPopup(commentShell, XtGrabNone);
4397 XSync(xDisplay, False);
4402 void CommentCallback(w, client_data, call_data)
4404 XtPointer client_data, call_data;
4411 XtSetArg(args[j], XtNlabel, &name); j++;
4412 XtGetValues(w, args, j);
4414 if (strcmp(name, _("close")) == 0) {
4416 } else if (strcmp(name, _("edit")) == 0) {
4423 void CommentPopDown()
4428 if (!commentUp) return;
4430 XtSetArg(args[j], XtNx, &commentX); j++;
4431 XtSetArg(args[j], XtNy, &commentY); j++;
4432 XtSetArg(args[j], XtNwidth, &commentW); j++;
4433 XtSetArg(args[j], XtNheight, &commentH); j++;
4434 XtGetValues(commentShell, args, j);
4435 XtPopdown(commentShell);
4436 XSync(xDisplay, False);
4440 void PromotionPopUp()
4443 Widget dialog, layout;
4445 Dimension bw_width, pw_width;
4449 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4450 XtGetValues(boardWidget, args, j);
4453 XtSetArg(args[j], XtNresizable, True); j++;
4454 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4456 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4457 shellWidget, args, j);
4459 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4460 layoutArgs, XtNumber(layoutArgs));
4463 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4464 XtSetArg(args[j], XtNborderWidth, 0); j++;
4465 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4468 if(gameInfo.variant != VariantShogi) {
4469 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4470 (XtPointer) dialog);
4471 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4472 (XtPointer) dialog);
4473 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4474 (XtPointer) dialog);
4475 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4476 (XtPointer) dialog);
4477 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4478 gameInfo.variant == VariantGiveaway) {
4479 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4480 (XtPointer) dialog);
4482 if(gameInfo.variant == VariantCapablanca ||
4483 gameInfo.variant == VariantGothic ||
4484 gameInfo.variant == VariantCapaRandom) {
4485 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4486 (XtPointer) dialog);
4487 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4488 (XtPointer) dialog);
4490 } else // [HGM] shogi
4492 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4493 (XtPointer) dialog);
4494 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4495 (XtPointer) dialog);
4497 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4498 (XtPointer) dialog);
4500 XtRealizeWidget(promotionShell);
4501 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4504 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4505 XtGetValues(promotionShell, args, j);
4507 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4508 lineGap + squareSize/3 +
4509 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4510 0 : 6*(squareSize + lineGap)), &x, &y);
4513 XtSetArg(args[j], XtNx, x); j++;
4514 XtSetArg(args[j], XtNy, y); j++;
4515 XtSetValues(promotionShell, args, j);
4517 XtPopup(promotionShell, XtGrabNone);
4522 void PromotionPopDown()
4524 if (!promotionUp) return;
4525 XtPopdown(promotionShell);
4526 XtDestroyWidget(promotionShell);
4527 promotionUp = False;
4530 void PromotionCallback(w, client_data, call_data)
4532 XtPointer client_data, call_data;
4538 XtSetArg(args[0], XtNlabel, &name);
4539 XtGetValues(w, args, 1);
4543 if (fromX == -1) return;
4545 if (strcmp(name, _("cancel")) == 0) {
4549 } else if (strcmp(name, _("Knight")) == 0) {
4551 } else if (strcmp(name, _("Promote")) == 0) {
4553 } else if (strcmp(name, _("Defer")) == 0) {
4556 promoChar = ToLower(name[0]);
4559 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
4561 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4562 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4567 void ErrorCallback(w, client_data, call_data)
4569 XtPointer client_data, call_data;
4572 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4574 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4580 if (!errorUp) return;
4584 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4586 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4591 void ErrorPopUp(title, label, modal)
4592 char *title, *label;
4595 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4596 GTK_DIALOG_DESTROY_WITH_PARENT,
4601 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4604 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4605 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4609 g_signal_connect_swapped (GUI_Error, "response",
4610 G_CALLBACK (ErrorPopDownProc),
4613 gtk_widget_show(GTK_WIDGET(GUI_Error));
4619 /* Disable all user input other than deleting the window */
4620 static int frozen = 0;
4624 /* Grab by a widget that doesn't accept input */
4625 // XtAddGrab(messageWidget, TRUE, FALSE);
4629 /* Undo a FreezeUI */
4632 if (!frozen) return;
4633 // XtRemoveGrab(messageWidget);
4637 char *ModeToWidgetName(mode)
4641 case BeginningOfGame:
4642 if (appData.icsActive)
4643 return "menuMode.ICS Client";
4644 else if (appData.noChessProgram ||
4645 *appData.cmailGameName != NULLCHAR)
4646 return "menuMode.Edit Game";
4648 return "menuMode.Machine Black";
4649 case MachinePlaysBlack:
4650 return "menuMode.Machine Black";
4651 case MachinePlaysWhite:
4652 return "menuMode.Machine White";
4654 return "menuMode.Analysis Mode";
4656 return "menuMode.Analyze File";
4657 case TwoMachinesPlay:
4658 return "menuMode.Two Machines";
4660 return "menuMode.Edit Game";
4661 case PlayFromGameFile:
4662 return "menuFile.Load Game";
4664 return "menuMode.Edit Position";
4666 return "menuMode.Training";
4667 case IcsPlayingWhite:
4668 case IcsPlayingBlack:
4672 return "menuMode.ICS Client";
4679 void ModeHighlight()
4681 static int oldPausing = FALSE;
4682 static GameMode oldmode = (GameMode) -1;
4685 // todo this toggling of the pause button doesn't seem to work?
4686 // e.g. select pause from buttonbar doesn't activate menumode.pause
4688 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4690 if (pausing != oldPausing) {
4691 oldPausing = pausing;
4692 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4693 /* toggle background color in showbuttonbar */
4694 if (appData.showButtonBar) {
4696 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4698 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4703 wname = ModeToWidgetName(oldmode);
4705 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4709 /* Maybe all the enables should be handled here, not just this one */
4710 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4711 gameMode == Training || gameMode == PlayFromGameFile);
4716 * Button/menu procedures
4719 int LoadGamePopUp(f, gameNumber, title)
4724 cmailMsgLoaded = FALSE;
4726 if (gameNumber == 0)
4728 int error = GameListBuild(f);
4732 DisplayError(_("Cannot build game list"), error);
4734 else if (!ListEmpty(&gameList)
4735 && ((ListGame *) gameList.tailPred)->number > 1)
4737 // TODO convert to GTK
4738 // GameListPopUp(f, title);
4746 return LoadGame(f, gameNumber, title, FALSE);
4749 void ReloadCmailMsgProc(w, event, prms, nprms)
4755 ReloadCmailMsgEvent(FALSE);
4758 void MailMoveProc(w, event, prms, nprms)
4767 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4768 static char *selected_fen_position=NULL;
4771 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4772 Atom *type_return, XtPointer *value_return,
4773 unsigned long *length_return, int *format_return)
4775 char *selection_tmp;
4777 if (!selected_fen_position) return False; /* should never happen */
4778 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4779 /* note: since no XtSelectionDoneProc was registered, Xt will
4780 * automatically call XtFree on the value returned. So have to
4781 * make a copy of it allocated with XtMalloc */
4782 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4783 strcpy(selection_tmp, selected_fen_position);
4785 *value_return=selection_tmp;
4786 *length_return=strlen(selection_tmp);
4787 *type_return=*target;
4788 *format_return = 8; /* bits per byte */
4790 } else if (*target == XA_TARGETS(xDisplay)) {
4791 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4792 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4793 targets_tmp[1] = XA_STRING;
4794 *value_return = targets_tmp;
4795 *type_return = XA_ATOM;
4797 *format_return = 8 * sizeof(Atom);
4798 if (*format_return > 32) {
4799 *length_return *= *format_return / 32;
4800 *format_return = 32;
4808 /* note: when called from menu all parameters are NULL, so no clue what the
4809 * Widget which was clicked on was, or what the click event was
4811 void CopyPositionProc(w, event, prms, nprms)
4818 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4819 * have a notion of a position that is selected but not copied.
4820 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4822 if (selected_fen_position) free(selected_fen_position);
4823 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
4824 if (!selected_fen_position) return;
4825 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4827 SendPositionSelection,
4828 NULL/* lose_ownership_proc */ ,
4829 NULL/* transfer_done_proc */);
4830 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4832 SendPositionSelection,
4833 NULL/* lose_ownership_proc */ ,
4834 NULL/* transfer_done_proc */);
4837 /* function called when the data to Paste is ready */
4839 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
4840 Atom *type, XtPointer value, unsigned long *len, int *format)
4843 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
4844 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
4845 EditPositionPasteFEN(fenstr);
4849 /* called when Paste Position button is pressed,
4850 * all parameters will be NULL */
4851 void PastePositionProc(w, event, prms, nprms)
4857 XtGetSelectionValue(menuBarWidget,
4858 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
4859 /* (XtSelectionCallbackProc) */ PastePositionCB,
4860 NULL, /* client_data passed to PastePositionCB */
4862 /* better to use the time field from the event that triggered the
4863 * call to this function, but that isn't trivial to get
4871 SendGameSelection(Widget w, Atom *selection, Atom *target,
4872 Atom *type_return, XtPointer *value_return,
4873 unsigned long *length_return, int *format_return)
4875 char *selection_tmp;
4877 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4878 FILE* f = fopen(gameCopyFilename, "r");
4881 if (f == NULL) return False;
4885 selection_tmp = XtMalloc(len + 1);
4886 count = fread(selection_tmp, 1, len, f);
4888 XtFree(selection_tmp);
4891 selection_tmp[len] = NULLCHAR;
4892 *value_return = selection_tmp;
4893 *length_return = len;
4894 *type_return = *target;
4895 *format_return = 8; /* bits per byte */
4897 } else if (*target == XA_TARGETS(xDisplay)) {
4898 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4899 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4900 targets_tmp[1] = XA_STRING;
4901 *value_return = targets_tmp;
4902 *type_return = XA_ATOM;
4904 *format_return = 8 * sizeof(Atom);
4905 if (*format_return > 32) {
4906 *length_return *= *format_return / 32;
4907 *format_return = 32;
4915 /* note: when called from menu all parameters are NULL, so no clue what the
4916 * Widget which was clicked on was, or what the click event was
4918 void CopyGameProc(w, event, prms, nprms)
4926 ret = SaveGameToFile(gameCopyFilename, FALSE);
4930 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4931 * have a notion of a game that is selected but not copied.
4932 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4934 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4937 NULL/* lose_ownership_proc */ ,
4938 NULL/* transfer_done_proc */);
4939 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4942 NULL/* lose_ownership_proc */ ,
4943 NULL/* transfer_done_proc */);
4946 /* function called when the data to Paste is ready */
4948 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
4949 Atom *type, XtPointer value, unsigned long *len, int *format)
4952 if (value == NULL || *len == 0) {
4953 return; /* nothing had been selected to copy */
4955 f = fopen(gamePasteFilename, "w");
4957 DisplayError(_("Can't open temp file"), errno);
4960 fwrite(value, 1, *len, f);
4963 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
4966 /* called when Paste Game button is pressed,
4967 * all parameters will be NULL */
4968 void PasteGameProc(w, event, prms, nprms)
4974 XtGetSelectionValue(menuBarWidget,
4975 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
4976 /* (XtSelectionCallbackProc) */ PasteGameCB,
4977 NULL, /* client_data passed to PasteGameCB */
4979 /* better to use the time field from the event that triggered the
4980 * call to this function, but that isn't trivial to get
4990 SaveGameProc(NULL, NULL);
4995 void EditCommentProc(w, event, prms, nprms)
5002 EditCommentPopDown();
5008 void IcsInputBoxProc(w, event, prms, nprms)
5014 if (ICSInputBoxUp) {
5015 ICSInputBoxPopDown();
5022 void EnterKeyProc(w, event, prms, nprms)
5028 if (ICSInputBoxUp == True)
5033 void DebugProc(w, event, prms, nprms)
5039 appData.debugMode = !appData.debugMode;
5042 void AboutGameProc(w, event, prms, nprms)
5051 void NothingProc(w, event, prms, nprms)
5060 void Iconify(w, event, prms, nprms)
5069 XtSetArg(args[0], XtNiconic, True);
5070 XtSetValues(shellWidget, args, 1);
5073 void DisplayMessage(message, extMessage)
5074 gchar *message, *extMessage;
5081 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5084 message = extMessage;
5087 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5092 void DisplayTitle(text)
5095 gchar title[MSG_SIZ];
5097 if (text == NULL) text = "";
5099 if (appData.titleInWindow)
5104 if (*text != NULLCHAR)
5106 strcpy(title, text);
5108 else if (appData.icsActive)
5110 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5112 else if (appData.cmailGameName[0] != NULLCHAR)
5114 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5116 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5118 else if (gameInfo.variant == VariantGothic)
5120 strcpy(title, GOTHIC);
5124 else if (gameInfo.variant == VariantFalcon)
5126 strcpy(title, FALCON);
5129 else if (appData.noChessProgram)
5131 strcpy(title, programName);
5135 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5137 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5143 void DisplayError(message, error)
5150 if (appData.debugMode || appData.matchMode) {
5151 fprintf(stderr, "%s: %s\n", programName, message);
5154 if (appData.debugMode || appData.matchMode) {
5155 fprintf(stderr, "%s: %s: %s\n",
5156 programName, message, strerror(error));
5158 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5161 ErrorPopUp(_("Error"), message, FALSE);
5165 void DisplayMoveError(message)
5170 DrawPosition(FALSE, NULL);
5171 if (appData.debugMode || appData.matchMode) {
5172 fprintf(stderr, "%s: %s\n", programName, message);
5174 if (appData.popupMoveErrors) {
5175 ErrorPopUp(_("Error"), message, FALSE);
5177 DisplayMessage(message, "");
5182 void DisplayFatalError(message, error, status)
5188 errorExitStatus = status;
5190 fprintf(stderr, "%s: %s\n", programName, message);
5192 fprintf(stderr, "%s: %s: %s\n",
5193 programName, message, strerror(error));
5194 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5197 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5198 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5204 void DisplayInformation(message)
5208 ErrorPopUp(_("Information"), message, TRUE);
5211 void DisplayNote(message)
5215 ErrorPopUp(_("Note"), message, FALSE);
5219 NullXErrorCheck(dpy, error_event)
5221 XErrorEvent *error_event;
5226 void DisplayIcsInteractionTitle(message)
5229 if (oldICSInteractionTitle == NULL) {
5230 /* Magic to find the old window title, adapted from vim */
5231 char *wina = getenv("WINDOWID");
5233 Window win = (Window) atoi(wina);
5234 Window root, parent, *children;
5235 unsigned int nchildren;
5236 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5238 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5239 if (!XQueryTree(xDisplay, win, &root, &parent,
5240 &children, &nchildren)) break;
5241 if (children) XFree((void *)children);
5242 if (parent == root || parent == 0) break;
5245 XSetErrorHandler(oldHandler);
5247 if (oldICSInteractionTitle == NULL) {
5248 oldICSInteractionTitle = "xterm";
5251 printf("\033]0;%s\007", message);
5255 char pendingReplyPrefix[MSG_SIZ];
5256 ProcRef pendingReplyPR;
5258 void AskQuestionProc(w, event, prms, nprms)
5265 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5269 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5272 void AskQuestionPopDown()
5274 if (!askQuestionUp) return;
5275 XtPopdown(askQuestionShell);
5276 XtDestroyWidget(askQuestionShell);
5277 askQuestionUp = False;
5280 void AskQuestionReplyAction(w, event, prms, nprms)
5290 reply = XawDialogGetValueString(w = XtParent(w));
5291 strcpy(buf, pendingReplyPrefix);
5292 if (*buf) strcat(buf, " ");
5295 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5296 AskQuestionPopDown();
5298 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5301 void AskQuestionCallback(w, client_data, call_data)
5303 XtPointer client_data, call_data;
5308 XtSetArg(args[0], XtNlabel, &name);
5309 XtGetValues(w, args, 1);
5311 if (strcmp(name, _("cancel")) == 0) {
5312 AskQuestionPopDown();
5314 AskQuestionReplyAction(w, NULL, NULL, NULL);
5318 void AskQuestion(title, question, replyPrefix, pr)
5319 char *title, *question, *replyPrefix;
5323 Widget popup, layout, dialog, edit;
5329 strcpy(pendingReplyPrefix, replyPrefix);
5330 pendingReplyPR = pr;
5333 XtSetArg(args[i], XtNresizable, True); i++;
5334 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5335 askQuestionShell = popup =
5336 XtCreatePopupShell(title, transientShellWidgetClass,
5337 shellWidget, args, i);
5340 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5341 layoutArgs, XtNumber(layoutArgs));
5344 XtSetArg(args[i], XtNlabel, question); i++;
5345 XtSetArg(args[i], XtNvalue, ""); i++;
5346 XtSetArg(args[i], XtNborderWidth, 0); i++;
5347 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5350 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5351 (XtPointer) dialog);
5352 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5353 (XtPointer) dialog);
5355 XtRealizeWidget(popup);
5356 CatchDeleteWindow(popup, "AskQuestionPopDown");
5358 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5359 &x, &y, &win_x, &win_y, &mask);
5361 XtSetArg(args[0], XtNx, x - 10);
5362 XtSetArg(args[1], XtNy, y - 30);
5363 XtSetValues(popup, args, 2);
5365 XtPopup(popup, XtGrabExclusive);
5366 askQuestionUp = True;
5368 edit = XtNameToWidget(dialog, "*value");
5369 XtSetKeyboardFocus(popup, edit);
5377 if (*name == NULLCHAR) {
5379 } else if (strcmp(name, "$") == 0) {
5380 putc(BELLCHAR, stderr);
5383 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
5391 PlaySound(appData.soundMove);
5397 PlaySound(appData.soundIcsWin);
5403 PlaySound(appData.soundIcsLoss);
5409 PlaySound(appData.soundIcsDraw);
5413 PlayIcsUnfinishedSound()
5415 PlaySound(appData.soundIcsUnfinished);
5421 PlaySound(appData.soundIcsAlarm);
5427 system("stty echo");
5433 system("stty -echo");
5437 Colorize(cc, continuation)
5442 int count, outCount, error;
5444 if (textColors[(int)cc].bg > 0) {
5445 if (textColors[(int)cc].fg > 0) {
5446 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
5447 textColors[(int)cc].fg, textColors[(int)cc].bg);
5449 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5450 textColors[(int)cc].bg);
5453 if (textColors[(int)cc].fg > 0) {
5454 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5455 textColors[(int)cc].fg);
5457 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
5460 count = strlen(buf);
5461 outCount = OutputToProcess(NoProc, buf, count, &error);
5462 if (outCount < count) {
5463 DisplayFatalError(_("Error writing to display"), error, 1);
5466 if (continuation) return;
5469 PlaySound(appData.soundShout);
5472 PlaySound(appData.soundSShout);
5475 PlaySound(appData.soundChannel1);
5478 PlaySound(appData.soundChannel);
5481 PlaySound(appData.soundKibitz);
5484 PlaySound(appData.soundTell);
5486 case ColorChallenge:
5487 PlaySound(appData.soundChallenge);
5490 PlaySound(appData.soundRequest);
5493 PlaySound(appData.soundSeek);
5504 return getpwuid(getuid())->pw_name;
5507 static char *ExpandPathName(path)
5510 static char static_buf[2000];
5511 char *d, *s, buf[2000];
5517 while (*s && isspace(*s))
5526 if (*(s+1) == '/') {
5527 strcpy(d, getpwuid(getuid())->pw_dir);
5532 *strchr(buf, '/') = 0;
5533 pwd = getpwnam(buf);
5536 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
5540 strcpy(d, pwd->pw_dir);
5541 strcat(d, strchr(s+1, '/'));
5552 static char host_name[MSG_SIZ];
5554 #if HAVE_GETHOSTNAME
5555 gethostname(host_name, MSG_SIZ);
5557 #else /* not HAVE_GETHOSTNAME */
5558 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
5559 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
5561 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5563 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5564 #endif /* not HAVE_GETHOSTNAME */
5567 guint delayedEventTimerTag = 0;
5568 DelayedEventCallback delayedEventCallback = 0;
5571 FireDelayedEvent(data)
5575 g_source_remove(delayedEventTimerTag);
5576 delayedEventTimerTag = 0;
5579 delayedEventCallback();
5585 ScheduleDelayedEvent(cb, millisec)
5586 DelayedEventCallback cb; guint millisec;
5588 if(delayedEventTimerTag && delayedEventCallback == cb)
5589 // [HGM] alive: replace, rather than add or flush identical event
5590 g_source_remove(delayedEventTimerTag);
5591 delayedEventCallback = cb;
5592 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
5596 DelayedEventCallback
5599 if (delayedEventTimerTag)
5601 return delayedEventCallback;
5610 CancelDelayedEvent()
5612 if (delayedEventTimerTag)
5614 g_source_remove(delayedEventTimerTag);
5615 delayedEventTimerTag = 0;
5621 guint loadGameTimerTag = 0;
5623 int LoadGameTimerRunning()
5625 return loadGameTimerTag != 0;
5628 int StopLoadGameTimer()
5630 if (loadGameTimerTag != 0) {
5631 g_source_remove(loadGameTimerTag);
5632 loadGameTimerTag = 0;
5640 LoadGameTimerCallback(data)
5644 g_source_remove(loadGameTimerTag);
5645 loadGameTimerTag = 0;
5652 StartLoadGameTimer(millisec)
5656 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
5660 guint analysisClockTag = 0;
5663 AnalysisClockCallback(data)
5666 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
5667 || appData.icsEngineAnalyze)
5669 AnalysisPeriodicEvent(0);
5670 return 1; /* keep on going */
5672 return 0; /* stop timer */
5676 StartAnalysisClock()
5679 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
5683 guint clockTimerTag = 0;
5685 int ClockTimerRunning()
5687 return clockTimerTag != 0;
5690 int StopClockTimer()
5692 if (clockTimerTag != 0)
5694 g_source_remove(clockTimerTag);
5705 ClockTimerCallback(data)
5709 g_source_remove(clockTimerTag);
5717 StartClockTimer(millisec)
5720 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
5725 DisplayTimerLabel(w, color, timer, highlight)
5734 if (appData.clockMode) {
5735 sprintf(buf, "%s: %s", color, TimeString(timer));
5737 sprintf(buf, "%s ", color);
5739 gtk_label_set_text(GTK_LABEL(w),buf);
5741 /* check for low time warning */
5742 // Pixel foregroundOrWarningColor = timerForegroundPixel;
5745 // appData.lowTimeWarning &&
5746 // (timer / 1000) < appData.icsAlarmTime)
5747 // foregroundOrWarningColor = lowTimeWarningColor;
5749 // if (appData.clockMode) {
5750 // sprintf(buf, "%s: %s", color, TimeString(timer));
5751 // XtSetArg(args[0], XtNlabel, buf);
5753 // sprintf(buf, "%s ", color);
5754 // XtSetArg(args[0], XtNlabel, buf);
5759 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
5760 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
5762 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
5763 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
5766 // XtSetValues(w, args, 3);
5771 DisplayWhiteClock(timeRemaining, highlight)
5775 if(appData.noGUI) return;
5777 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
5778 if (highlight && WindowIcon == BlackIcon)
5780 WindowIcon = WhiteIcon;
5781 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5786 DisplayBlackClock(timeRemaining, highlight)
5790 if(appData.noGUI) return;
5792 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
5793 if (highlight && WindowIcon == WhiteIcon)
5795 WindowIcon = BlackIcon;
5796 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5814 int StartChildProcess(cmdLine, dir, pr)
5821 int to_prog[2], from_prog[2];
5825 if (appData.debugMode) {
5826 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
5829 /* We do NOT feed the cmdLine to the shell; we just
5830 parse it into blank-separated arguments in the
5831 most simple-minded way possible.
5834 strcpy(buf, cmdLine);
5839 if (p == NULL) break;
5844 SetUpChildIO(to_prog, from_prog);
5846 if ((pid = fork()) == 0) {
5848 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
5849 close(to_prog[1]); // first close the unused pipe ends
5850 close(from_prog[0]);
5851 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
5852 dup2(from_prog[1], 1);
5853 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
5854 close(from_prog[1]); // and closing again loses one of the pipes!
5855 if(fileno(stderr) >= 2) // better safe than sorry...
5856 dup2(1, fileno(stderr)); /* force stderr to the pipe */
5858 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
5863 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
5865 execvp(argv[0], argv);
5867 /* If we get here, exec failed */
5872 /* Parent process */
5874 close(from_prog[1]);
5876 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
5879 cp->fdFrom = from_prog[0];
5880 cp->fdTo = to_prog[1];
5885 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
5886 static RETSIGTYPE AlarmCallBack(int n)
5892 DestroyChildProcess(pr, signalType)
5896 ChildProc *cp = (ChildProc *) pr;
5898 if (cp->kind != CPReal) return;
5900 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
5901 signal(SIGALRM, AlarmCallBack);
5903 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
5904 kill(cp->pid, SIGKILL); // kill it forcefully
5905 wait((int *) 0); // and wait again
5909 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
5911 /* Process is exiting either because of the kill or because of
5912 a quit command sent by the backend; either way, wait for it to die.
5921 InterruptChildProcess(pr)
5924 ChildProc *cp = (ChildProc *) pr;
5926 if (cp->kind != CPReal) return;
5927 (void) kill(cp->pid, SIGINT); /* stop it thinking */
5930 int OpenTelnet(host, port, pr)
5935 char cmdLine[MSG_SIZ];
5937 if (port[0] == NULLCHAR) {
5938 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
5940 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
5942 return StartChildProcess(cmdLine, "", pr);
5945 int OpenTCP(host, port, pr)
5951 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
5952 #else /* !OMIT_SOCKETS */
5954 struct sockaddr_in sa;
5956 unsigned short uport;
5959 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
5963 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
5964 sa.sin_family = AF_INET;
5965 sa.sin_addr.s_addr = INADDR_ANY;
5966 uport = (unsigned short) 0;
5967 sa.sin_port = htons(uport);
5968 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
5972 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
5973 if (!(hp = gethostbyname(host))) {
5975 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
5976 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
5977 hp->h_addrtype = AF_INET;
5979 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
5980 hp->h_addr_list[0] = (char *) malloc(4);
5981 hp->h_addr_list[0][0] = b0;
5982 hp->h_addr_list[0][1] = b1;
5983 hp->h_addr_list[0][2] = b2;
5984 hp->h_addr_list[0][3] = b3;
5989 sa.sin_family = hp->h_addrtype;
5990 uport = (unsigned short) atoi(port);
5991 sa.sin_port = htons(uport);
5992 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
5994 if (connect(s, (struct sockaddr *) &sa,
5995 sizeof(struct sockaddr_in)) < 0) {
5999 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6006 #endif /* !OMIT_SOCKETS */
6011 int OpenCommPort(name, pr)
6018 fd = open(name, 2, 0);
6019 if (fd < 0) return errno;
6021 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6031 int OpenLoopback(pr)
6037 SetUpChildIO(to, from);
6039 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6042 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6049 int OpenRcmd(host, user, cmd, pr)
6050 char *host, *user, *cmd;
6053 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6057 #define INPUT_SOURCE_BUF_SIZE 8192
6066 char buf[INPUT_SOURCE_BUF_SIZE];
6071 DoInputCallback(io,cond,data)
6076 /* read input from one of the input source (for example a chess program, ICS, etc).
6077 * and call a function that will handle the input
6080 int count; /* how many bytes did we read */
6084 /* All information (callback function, file descriptor, etc) is
6085 * saved in an InputSource structure
6087 InputSource *is = (InputSource *) data;
6091 count = read(is->fd, is->unused,
6092 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6096 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6099 is->unused += count;
6101 /* break input into lines and call the callback function on each
6104 while (p < is->unused)
6106 q = memchr(p, '\n', is->unused - p);
6107 if (q == NULL) break;
6109 (is->func)(is, is->closure, p, q - p, 0);
6112 /* remember not yet used part of the buffer */
6114 while (p < is->unused)
6122 /* read maximum length of input buffer and send the whole buffer
6123 * to the callback function
6125 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6130 (is->func)(is, is->closure, is->buf, count, error);
6136 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6143 GIOChannel *channel;
6144 ChildProc *cp = (ChildProc *) pr;
6146 is = (InputSource *) calloc(1, sizeof(InputSource));
6147 is->lineByLine = lineByLine;
6151 is->fd = fileno(stdin);
6153 is->kind = cp->kind;
6154 is->fd = cp->fdFrom;
6157 is->unused = is->buf;
6161 // is->xid = XtAppAddInput(appContext, is->fd,
6162 // (XtPointer) (XtInputReadMask),
6163 // (XtInputCallbackProc) DoInputCallback,
6167 /* TODO: will this work on windows?*/
6168 printf("DEBUG: fd=%d %d\n",is->fd,is);
6170 channel = g_io_channel_unix_new(is->fd);
6171 g_io_channel_set_close_on_unref (channel, TRUE);
6172 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6173 is->closure = closure;
6174 return (InputSourceRef) is;
6178 RemoveInputSource(isr)
6181 InputSource *is = (InputSource *) isr;
6183 if (is->sid == 0) return;
6184 g_source_remove(is->sid);
6189 int OutputToProcess(pr, message, count, outError)
6195 static int line = 0;
6196 ChildProc *cp = (ChildProc *) pr;
6201 if (appData.noJoin || !appData.useInternalWrap)
6202 outCount = fwrite(message, 1, count, stdout);
6205 int width = get_term_width();
6206 int len = wrap(NULL, message, count, width, &line);
6207 char *msg = malloc(len);
6211 outCount = fwrite(message, 1, count, stdout);
6214 dbgchk = wrap(msg, message, count, width, &line);
6215 if (dbgchk != len && appData.debugMode)
6216 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
6217 outCount = fwrite(msg, 1, dbgchk, stdout);
6223 outCount = write(cp->fdTo, message, count);
6233 /* Output message to process, with "ms" milliseconds of delay
6234 between each character. This is needed when sending the logon
6235 script to ICC, which for some reason doesn't like the
6236 instantaneous send. */
6237 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6244 ChildProc *cp = (ChildProc *) pr;
6249 r = write(cp->fdTo, message++, 1);
6262 /**** Animation code by Hugh Fisher, DCS, ANU.
6264 Known problem: if a window overlapping the board is
6265 moved away while a piece is being animated underneath,
6266 the newly exposed area won't be updated properly.
6267 I can live with this.
6269 Known problem: if you look carefully at the animation
6270 of pieces in mono mode, they are being drawn as solid
6271 shapes without interior detail while moving. Fixing
6272 this would be a major complication for minimal return.
6275 /* Masks for XPM pieces. Black and white pieces can have
6276 different shapes, but in the interest of retaining my
6277 sanity pieces must have the same outline on both light
6278 and dark squares, and all pieces must use the same
6279 background square colors/images. */
6281 static int xpmDone = 0;
6284 CreateAnimMasks (pieceDepth)
6291 unsigned long plane;
6294 /* just return for gtk at the moment */
6297 /* Need a bitmap just to get a GC with right depth */
6298 buf = XCreatePixmap(xDisplay, xBoardWindow,
6300 values.foreground = 1;
6301 values.background = 0;
6302 /* Don't use XtGetGC, not read only */
6303 maskGC = XCreateGC(xDisplay, buf,
6304 GCForeground | GCBackground, &values);
6305 XFreePixmap(xDisplay, buf);
6307 buf = XCreatePixmap(xDisplay, xBoardWindow,
6308 squareSize, squareSize, pieceDepth);
6309 values.foreground = XBlackPixel(xDisplay, xScreen);
6310 values.background = XWhitePixel(xDisplay, xScreen);
6311 bufGC = XCreateGC(xDisplay, buf,
6312 GCForeground | GCBackground, &values);
6314 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6315 /* Begin with empty mask */
6316 if(!xpmDone) // [HGM] pieces: keep using existing
6317 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6318 squareSize, squareSize, 1);
6319 XSetFunction(xDisplay, maskGC, GXclear);
6320 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6321 0, 0, squareSize, squareSize);
6323 /* Take a copy of the piece */
6328 XSetFunction(xDisplay, bufGC, GXcopy);
6329 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6331 0, 0, squareSize, squareSize, 0, 0);
6333 /* XOR the background (light) over the piece */
6334 XSetFunction(xDisplay, bufGC, GXxor);
6336 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6337 0, 0, squareSize, squareSize, 0, 0);
6339 XSetForeground(xDisplay, bufGC, lightSquareColor);
6340 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6343 /* We now have an inverted piece image with the background
6344 erased. Construct mask by just selecting all the non-zero
6345 pixels - no need to reconstruct the original image. */
6346 XSetFunction(xDisplay, maskGC, GXor);
6348 /* Might be quicker to download an XImage and create bitmap
6349 data from it rather than this N copies per piece, but it
6350 only takes a fraction of a second and there is a much
6351 longer delay for loading the pieces. */
6352 for (n = 0; n < pieceDepth; n ++) {
6353 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6354 0, 0, squareSize, squareSize,
6360 XFreePixmap(xDisplay, buf);
6361 XFreeGC(xDisplay, bufGC);
6362 XFreeGC(xDisplay, maskGC);
6366 InitAnimState (anim, info)
6368 XWindowAttributes * info;
6373 /* Each buffer is square size, same depth as window */
6374 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6375 // squareSize, squareSize, info->depth);
6376 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6377 // squareSize, squareSize, info->depth);
6379 // /* Create a plain GC for blitting */
6380 // mask = GCForeground | GCBackground | GCFunction |
6381 // GCPlaneMask | GCGraphicsExposures;
6382 // values.foreground = XBlackPixel(xDisplay, xScreen);
6383 // values.background = XWhitePixel(xDisplay, xScreen);
6384 // values.function = GXcopy;
6385 // values.plane_mask = AllPlanes;
6386 // values.graphics_exposures = False;
6387 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
6389 // /* Piece will be copied from an existing context at
6390 // the start of each new animation/drag. */
6391 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
6393 // /* Outline will be a read-only copy of an existing */
6394 // anim->outlineGC = None;
6400 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
6401 XWindowAttributes info;
6403 /* for gtk at the moment just ... */
6406 if (xpmDone && gameInfo.variant == old) return;
6407 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
6408 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
6410 // InitAnimState(&game, &info);
6411 // InitAnimState(&player, &info);
6413 /* For XPM pieces, we need bitmaps to use as masks. */
6415 // CreateAnimMasks(info.depth);
6421 static Boolean frameWaiting;
6423 static RETSIGTYPE FrameAlarm (sig)
6426 frameWaiting = False;
6427 /* In case System-V style signals. Needed?? */
6428 signal(SIGALRM, FrameAlarm);
6435 struct itimerval delay;
6437 XSync(xDisplay, False);
6440 frameWaiting = True;
6441 signal(SIGALRM, FrameAlarm);
6442 delay.it_interval.tv_sec =
6443 delay.it_value.tv_sec = time / 1000;
6444 delay.it_interval.tv_usec =
6445 delay.it_value.tv_usec = (time % 1000) * 1000;
6446 setitimer(ITIMER_REAL, &delay, NULL);
6447 while (frameWaiting) pause();
6448 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
6449 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
6450 setitimer(ITIMER_REAL, &delay, NULL);
6460 // XSync(xDisplay, False);
6462 usleep(time * 1000);
6467 /* Convert board position to corner of screen rect and color */
6470 ScreenSquare(column, row, pt, color)
6471 int column; int row; XPoint * pt; int * color;
6474 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
6475 pt->y = lineGap + row * (squareSize + lineGap);
6477 pt->x = lineGap + column * (squareSize + lineGap);
6478 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
6480 *color = SquareColor(row, column);
6483 /* Convert window coords to square */
6486 BoardSquare(x, y, column, row)
6487 int x; int y; int * column; int * row;
6489 *column = EventToSquare(x, BOARD_WIDTH);
6490 if (flipView && *column >= 0)
6491 *column = BOARD_WIDTH - 1 - *column;
6492 *row = EventToSquare(y, BOARD_HEIGHT);
6493 if (!flipView && *row >= 0)
6494 *row = BOARD_HEIGHT - 1 - *row;
6499 #undef Max /* just in case */
6501 #define Max(a, b) ((a) > (b) ? (a) : (b))
6502 #define Min(a, b) ((a) < (b) ? (a) : (b))
6505 SetRect(rect, x, y, width, height)
6506 XRectangle * rect; int x; int y; int width; int height;
6510 rect->width = width;
6511 rect->height = height;
6514 /* Test if two frames overlap. If they do, return
6515 intersection rect within old and location of
6516 that rect within new. */
6519 Intersect(old, new, size, area, pt)
6520 XPoint * old; XPoint * new;
6521 int size; XRectangle * area; XPoint * pt;
6523 if (old->x > new->x + size || new->x > old->x + size ||
6524 old->y > new->y + size || new->y > old->y + size) {
6527 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
6528 size - abs(old->x - new->x), size - abs(old->y - new->y));
6529 pt->x = Max(old->x - new->x, 0);
6530 pt->y = Max(old->y - new->y, 0);
6535 /* For two overlapping frames, return the rect(s)
6536 in the old that do not intersect with the new. */
6539 CalcUpdateRects(old, new, size, update, nUpdates)
6540 XPoint * old; XPoint * new; int size;
6541 XRectangle update[]; int * nUpdates;
6545 /* If old = new (shouldn't happen) then nothing to draw */
6546 if (old->x == new->x && old->y == new->y) {
6550 /* Work out what bits overlap. Since we know the rects
6551 are the same size we don't need a full intersect calc. */
6553 /* Top or bottom edge? */
6554 if (new->y > old->y) {
6555 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
6557 } else if (old->y > new->y) {
6558 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
6559 size, old->y - new->y);
6562 /* Left or right edge - don't overlap any update calculated above. */
6563 if (new->x > old->x) {
6564 SetRect(&(update[count]), old->x, Max(new->y, old->y),
6565 new->x - old->x, size - abs(new->y - old->y));
6567 } else if (old->x > new->x) {
6568 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
6569 old->x - new->x, size - abs(new->y - old->y));
6576 /* Generate a series of frame coords from start->mid->finish.
6577 The movement rate doubles until the half way point is
6578 reached, then halves back down to the final destination,
6579 which gives a nice slow in/out effect. The algorithmn
6580 may seem to generate too many intermediates for short
6581 moves, but remember that the purpose is to attract the
6582 viewers attention to the piece about to be moved and
6583 then to where it ends up. Too few frames would be less
6587 Tween(start, mid, finish, factor, frames, nFrames)
6588 XPoint * start; XPoint * mid;
6589 XPoint * finish; int factor;
6590 XPoint frames[]; int * nFrames;
6592 int fraction, n, count;
6596 /* Slow in, stepping 1/16th, then 1/8th, ... */
6598 for (n = 0; n < factor; n++)
6600 for (n = 0; n < factor; n++) {
6601 frames[count].x = start->x + (mid->x - start->x) / fraction;
6602 frames[count].y = start->y + (mid->y - start->y) / fraction;
6604 fraction = fraction / 2;
6608 frames[count] = *mid;
6611 /* Slow out, stepping 1/2, then 1/4, ... */
6613 for (n = 0; n < factor; n++) {
6614 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
6615 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
6617 fraction = fraction * 2;
6622 /* Draw a piece on the screen without disturbing what's there */
6625 SelectGCMask(piece, clip, outline, mask)
6626 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
6630 /* Bitmap for piece being moved. */
6631 if (appData.monoMode) {
6632 *mask = *pieceToSolid(piece);
6633 } else if (useImages) {
6635 *mask = xpmMask[piece];
6637 *mask = ximMaskPm[piece];
6640 *mask = *pieceToSolid(piece);
6643 /* GC for piece being moved. Square color doesn't matter, but
6644 since it gets modified we make a copy of the original. */
6646 if (appData.monoMode)
6651 if (appData.monoMode)
6656 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
6658 /* Outline only used in mono mode and is not modified */
6660 *outline = bwPieceGC;
6662 *outline = wbPieceGC;
6666 OverlayPiece(piece, clip, outline, dest)
6667 ChessSquare piece; GC clip; GC outline; Drawable dest;
6672 /* Draw solid rectangle which will be clipped to shape of piece */
6673 // XFillRectangle(xDisplay, dest, clip,
6674 // 0, 0, squareSize, squareSize)
6676 if (appData.monoMode)
6677 /* Also draw outline in contrasting color for black
6678 on black / white on white cases */
6679 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
6680 // 0, 0, squareSize, squareSize, 0, 0, 1)
6683 /* Copy the piece */
6688 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
6690 // 0, 0, squareSize, squareSize,
6695 /* Animate the movement of a single piece */
6698 BeginAnimation(anim, piece, startColor, start)
6706 /* The old buffer is initialised with the start square (empty) */
6707 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
6708 anim->prevFrame = *start;
6710 /* The piece will be drawn using its own bitmap as a matte */
6711 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
6712 // XSetClipMask(xDisplay, anim->pieceGC, mask);
6716 AnimationFrame(anim, frame, piece)
6721 XRectangle updates[4];
6726 /* Save what we are about to draw into the new buffer */
6727 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
6728 // frame->x, frame->y, squareSize, squareSize,
6731 /* Erase bits of the previous frame */
6732 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
6733 /* Where the new frame overlapped the previous,
6734 the contents in newBuf are wrong. */
6735 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
6736 // overlap.x, overlap.y,
6737 // overlap.width, overlap.height,
6739 /* Repaint the areas in the old that don't overlap new */
6740 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
6741 for (i = 0; i < count; i++)
6742 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6743 // updates[i].x - anim->prevFrame.x,
6744 // updates[i].y - anim->prevFrame.y,
6745 // updates[i].width, updates[i].height,
6746 // updates[i].x, updates[i].y)
6749 /* Easy when no overlap */
6750 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6751 // 0, 0, squareSize, squareSize,
6752 // anim->prevFrame.x, anim->prevFrame.y);
6755 /* Save this frame for next time round */
6756 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
6757 // 0, 0, squareSize, squareSize,
6759 anim->prevFrame = *frame;
6761 /* Draw piece over original screen contents, not current,
6762 and copy entire rect. Wipes out overlapping piece images. */
6763 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
6764 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
6765 // 0, 0, squareSize, squareSize,
6766 // frame->x, frame->y);
6770 EndAnimation (anim, finish)
6774 XRectangle updates[4];
6779 /* The main code will redraw the final square, so we
6780 only need to erase the bits that don't overlap. */
6781 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
6782 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
6783 for (i = 0; i < count; i++)
6784 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6785 // updates[i].x - anim->prevFrame.x,
6786 // updates[i].y - anim->prevFrame.y,
6787 // updates[i].width, updates[i].height,
6788 // updates[i].x, updates[i].y)
6791 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6792 // 0, 0, squareSize, squareSize,
6793 // anim->prevFrame.x, anim->prevFrame.y);
6798 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
6800 ChessSquare piece; int startColor;
6801 XPoint * start; XPoint * finish;
6802 XPoint frames[]; int nFrames;
6806 BeginAnimation(anim, piece, startColor, start);
6807 for (n = 0; n < nFrames; n++) {
6808 AnimationFrame(anim, &(frames[n]), piece);
6809 FrameDelay(appData.animSpeed);
6811 EndAnimation(anim, finish);
6814 /* Main control logic for deciding what to animate and how */
6817 AnimateMove(board, fromX, fromY, toX, toY)
6826 XPoint start, finish, mid;
6827 XPoint frames[kFactor * 2 + 1];
6828 int nFrames, startColor, endColor;
6830 /* Are we animating? */
6831 if (!appData.animate || appData.blindfold)
6834 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
6835 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
6836 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
6838 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
6839 piece = board[fromY][fromX];
6840 if (piece >= EmptySquare) return;
6845 hop = (piece == WhiteKnight || piece == BlackKnight);
6848 if (appData.debugMode) {
6849 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
6850 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
6851 piece, fromX, fromY, toX, toY); }
6853 ScreenSquare(fromX, fromY, &start, &startColor);
6854 ScreenSquare(toX, toY, &finish, &endColor);
6857 /* Knight: make diagonal movement then straight */
6858 if (abs(toY - fromY) < abs(toX - fromX)) {
6859 mid.x = start.x + (finish.x - start.x) / 2;
6863 mid.y = start.y + (finish.y - start.y) / 2;
6866 mid.x = start.x + (finish.x - start.x) / 2;
6867 mid.y = start.y + (finish.y - start.y) / 2;
6870 /* Don't use as many frames for very short moves */
6871 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
6872 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
6874 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
6875 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
6877 /* Be sure end square is redrawn */
6878 damage[toY][toX] = True;
6882 DragPieceBegin(x, y)
6885 int boardX, boardY, color;
6888 /* Are we animating? */
6889 if (!appData.animateDragging || appData.blindfold)
6892 /* Figure out which square we start in and the
6893 mouse position relative to top left corner. */
6894 BoardSquare(x, y, &boardX, &boardY);
6895 player.startBoardX = boardX;
6896 player.startBoardY = boardY;
6897 ScreenSquare(boardX, boardY, &corner, &color);
6898 player.startSquare = corner;
6899 player.startColor = color;
6900 /* As soon as we start dragging, the piece will jump slightly to
6901 be centered over the mouse pointer. */
6902 player.mouseDelta.x = squareSize/2;
6903 player.mouseDelta.y = squareSize/2;
6904 /* Initialise animation */
6905 player.dragPiece = PieceForSquare(boardX, boardY);
6907 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
6908 player.dragActive = True;
6909 BeginAnimation(&player, player.dragPiece, color, &corner);
6910 /* Mark this square as needing to be redrawn. Note that
6911 we don't remove the piece though, since logically (ie
6912 as seen by opponent) the move hasn't been made yet. */
6913 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
6914 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
6915 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
6916 // corner.x, corner.y, squareSize, squareSize,
6917 // 0, 0); // [HGM] zh: unstack in stead of grab
6918 damage[boardY][boardX] = True;
6920 player.dragActive = False;
6930 /* Are we animating? */
6931 if (!appData.animateDragging || appData.blindfold)
6935 if (! player.dragActive)
6937 /* Move piece, maintaining same relative position
6938 of mouse within square */
6939 corner.x = x - player.mouseDelta.x;
6940 corner.y = y - player.mouseDelta.y;
6941 AnimationFrame(&player, &corner, player.dragPiece);
6943 if (appData.highlightDragging) {
6945 BoardSquare(x, y, &boardX, &boardY);
6946 SetHighlights(fromX, fromY, boardX, boardY);
6955 int boardX, boardY, color;
6958 /* Are we animating? */
6959 if (!appData.animateDragging || appData.blindfold)
6963 if (! player.dragActive)
6965 /* Last frame in sequence is square piece is
6966 placed on, which may not match mouse exactly. */
6967 BoardSquare(x, y, &boardX, &boardY);
6968 ScreenSquare(boardX, boardY, &corner, &color);
6969 EndAnimation(&player, &corner);
6971 /* Be sure end square is redrawn */
6972 damage[boardY][boardX] = True;
6974 /* This prevents weird things happening with fast successive
6975 clicks which on my Sun at least can cause motion events
6976 without corresponding press/release. */
6977 player.dragActive = False;
6980 /* Handle expose event while piece being dragged */
6985 if (!player.dragActive || appData.blindfold)
6988 /* What we're doing: logically, the move hasn't been made yet,
6989 so the piece is still in it's original square. But visually
6990 it's being dragged around the board. So we erase the square
6991 that the piece is on and draw it at the last known drag point. */
6992 BlankSquare(player.startSquare.x, player.startSquare.y,
6993 player.startColor, EmptySquare, xBoardWindow);
6994 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
6995 damage[player.startBoardY][player.startBoardX] = TRUE;
6999 SetProgramStats( FrontEndProgramStats * stats )
7002 // [HGM] done, but perhaps backend should call this directly?
7003 EngineOutputUpdate( stats );
7006 #include <sys/ioctl.h>
7007 int get_term_width()
7009 int fd, default_width;
7012 default_width = 79; // this is FICS default anyway...
7014 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7016 if (!ioctl(fd, TIOCGSIZE, &win))
7017 default_width = win.ts_cols;
7018 #elif defined(TIOCGWINSZ)
7020 if (!ioctl(fd, TIOCGWINSZ, &win))
7021 default_width = win.ws_col;
7023 return default_width;
7026 void update_ics_width()
7028 static int old_width = 0;
7029 int new_width = get_term_width();
7031 if (old_width != new_width)
7032 ics_printf("set width %d\n", new_width);
7033 old_width = new_width;
7036 void NotifyFrontendLogin()