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));
216 #define usleep(t) _sleep2(((t)+500)/1000)
220 # define _(s) gettext (s)
221 # define N_(s) gettext_noop (s)
244 int main P((int argc, char **argv));
245 RETSIGTYPE CmailSigHandler P((int sig));
246 RETSIGTYPE IntSigHandler P((int sig));
247 RETSIGTYPE TermSizeSigHandler P((int sig));
248 void CreateGCs P((void));
249 void CreateXIMPieces P((void));
250 void CreateXPMPieces P((void));
251 void CreatePieces P((void));
252 void CreatePieceMenus P((void));
253 Widget CreateMenuBar P((Menu *mb));
254 char *FindFont P((char *pattern, int targetPxlSize));
255 void PieceMenuPopup P((Widget w, XEvent *event,
256 String *params, Cardinal *num_params));
257 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
258 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
259 int EventToSquare P((int x, int limit));
260 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
261 void AnimateUserMove P((Widget w, XEvent * event,
262 String * params, Cardinal * nParams));
263 void CommentPopUp P((char *title, char *label));
264 void CommentPopDown P((void));
265 void CommentCallback P((Widget w, XtPointer client_data,
266 XtPointer call_data));
267 void ICSInputBoxPopUp P((void));
268 void ICSInputBoxPopDown P((void));
269 void AskQuestionReplyAction P((Widget w, XEvent *event,
270 String *prms, Cardinal *nprms));
271 void AskQuestionProc P((Widget w, XEvent *event,
272 String *prms, Cardinal *nprms));
273 void AskQuestionPopDown P((void));
274 void PromotionPopDown P((void));
275 void PromotionCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void EditCommentPopDown P((void));
278 void EditCommentCallback P((Widget w, XtPointer client_data,
279 XtPointer call_data));
280 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
281 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
283 void PastePositionProc P((Widget w, XEvent *event, String *prms,
285 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
286 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
287 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
288 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
290 void EditCommentProc P((Widget w, XEvent *event,
291 String *prms, Cardinal *nprms));
292 void IcsInputBoxProc P((Widget w, XEvent *event,
293 String *prms, Cardinal *nprms));
294 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
295 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
296 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
297 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
298 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
299 void DisplayMove P((int moveNumber));
300 void DisplayTitle P((char *title));
301 void ICSInitScript P((void));
302 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
303 void ErrorPopUp P((char *title, char *text, int modal));
304 void ErrorPopDown P((void));
305 static char *ExpandPathName P((char *path));
306 static void CreateAnimVars P((void));
307 static void DragPieceMove P((int x, int y));
308 static void DrawDragPiece P((void));
309 char *ModeToWidgetName P((GameMode mode));
310 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
311 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ShufflePopDown P(());
318 void EnginePopDown P(());
319 void UciPopDown P(());
320 void TimeControlPopDown P(());
321 void NewVariantPopDown P(());
322 void SettingsPopDown P(());
323 void SetMenuEnables P((Enables *enab));
324 void update_ics_width P(());
325 int get_term_width P(());
327 * XBoard depends on Xt R4 or higher
329 int xtVersion = XtSpecificationRelease;
334 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
335 jailSquareColor, highlightSquareColor, premoveHighlightColor;
336 Pixel lowTimeWarningColor;
338 #define LINE_TYPE_NORMAL 0
339 #define LINE_TYPE_HIGHLIGHT 1
340 #define LINE_TYPE_PRE 2
343 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
344 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
345 wjPieceGC, bjPieceGC;
346 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
347 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
348 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
349 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
350 menuBarWidget, editShell, errorShell, analysisShell,
351 ICSInputShell, fileNameShell, askQuestionShell;
353 //XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
354 //XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6];
356 Font clockFontID, coordFontID, countFontID;
357 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
358 XtAppContext appContext;
360 char *oldICSInteractionTitle;
364 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
366 Position commentX = -1, commentY = -1;
367 Dimension commentW, commentH;
369 int squareSize, smallLayout = 0, tinyLayout = 0,
370 marginW, marginH, // [HGM] for run-time resizing
371 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
372 ICSInputBoxUp = False, askQuestionUp = False,
373 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
374 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
375 Pixel timerForegroundPixel, timerBackgroundPixel;
376 Pixel buttonForegroundPixel, buttonBackgroundPixel;
377 char *chessDir, *programName, *programVersion,
378 *gameCopyFilename, *gamePasteFilename;
382 Pixmap pieceBitmap[2][(int)BlackPawn];
383 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
384 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
385 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
386 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
387 int useImages=0, useImageSqs;
388 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
389 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
390 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
391 XImage *ximLightSquare, *ximDarkSquare;
394 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
395 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
397 #define White(piece) ((int)(piece) < (int)BlackPawn)
399 /* Variables for doing smooth animation. This whole thing
400 would be much easier if the board was double-buffered,
401 but that would require a fairly major rewrite. */
406 GC blitGC, pieceGC, outlineGC;
407 XPoint startSquare, prevFrame, mouseDelta;
411 int startBoardX, startBoardY;
414 /* There can be two pieces being animated at once: a player
415 can begin dragging a piece before the remote opponent has moved. */
417 static AnimState game, player;
419 /* Bitmaps for use as masks when drawing XPM pieces.
420 Need one for each black and white piece. */
421 static Pixmap xpmMask[BlackKing + 1];
423 /* This magic number is the number of intermediate frames used
424 in each half of the animation. For short moves it's reduced
425 by 1. The total number of frames will be factor * 2 + 1. */
428 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
430 Enables icsEnables[] = {
431 { "menuFile.Mail Move", False },
432 { "menuFile.Reload CMail Message", False },
433 { "menuMode.Machine Black", False },
434 { "menuMode.Machine White", False },
435 { "menuMode.Analysis Mode", False },
436 { "menuMode.Analyze File", False },
437 { "menuMode.Two Machines", False },
439 { "menuHelp.Hint", False },
440 { "menuHelp.Book", False },
441 { "menuStep.Move Now", False },
442 { "menuOptions.Periodic Updates", False },
443 { "menuOptions.Hide Thinking", False },
444 { "menuOptions.Ponder Next Move", False },
449 Enables ncpEnables[] = {
450 { "menuFile.Mail Move", False },
451 { "menuFile.Reload CMail Message", False },
452 { "menuMode.Machine White", False },
453 { "menuMode.Machine Black", False },
454 { "menuMode.Analysis Mode", False },
455 { "menuMode.Analyze File", False },
456 { "menuMode.Two Machines", False },
457 { "menuMode.ICS Client", False },
458 { "menuMode.ICS Input Box", False },
460 { "menuStep.Revert", False },
461 { "menuStep.Move Now", False },
462 { "menuStep.Retract Move", False },
463 { "menuOptions.Auto Comment", False },
464 { "menuOptions.Auto Flag", False },
465 { "menuOptions.Auto Flip View", False },
466 { "menuOptions.Auto Observe", False },
467 { "menuOptions.Auto Raise Board", False },
468 { "menuOptions.Get Move List", False },
469 { "menuOptions.ICS Alarm", False },
470 { "menuOptions.Move Sound", False },
471 { "menuOptions.Quiet Play", False },
472 { "menuOptions.Hide Thinking", False },
473 { "menuOptions.Periodic Updates", False },
474 { "menuOptions.Ponder Next Move", False },
475 { "menuHelp.Hint", False },
476 { "menuHelp.Book", False },
480 Enables gnuEnables[] = {
481 { "menuMode.ICS Client", False },
482 { "menuMode.ICS Input Box", False },
483 { "menuAction.Accept", False },
484 { "menuAction.Decline", False },
485 { "menuAction.Rematch", False },
486 { "menuAction.Adjourn", False },
487 { "menuAction.Stop Examining", False },
488 { "menuAction.Stop Observing", False },
489 { "menuStep.Revert", False },
490 { "menuOptions.Auto Comment", False },
491 { "menuOptions.Auto Observe", False },
492 { "menuOptions.Auto Raise Board", False },
493 { "menuOptions.Get Move List", False },
494 { "menuOptions.Premove", False },
495 { "menuOptions.Quiet Play", False },
497 /* The next two options rely on SetCmailMode being called *after* */
498 /* SetGNUMode so that when GNU is being used to give hints these */
499 /* menu options are still available */
501 { "menuFile.Mail Move", False },
502 { "menuFile.Reload CMail Message", False },
506 Enables cmailEnables[] = {
508 { "menuAction.Call Flag", False },
509 { "menuAction.Draw", True },
510 { "menuAction.Adjourn", False },
511 { "menuAction.Abort", False },
512 { "menuAction.Stop Observing", False },
513 { "menuAction.Stop Examining", False },
514 { "menuFile.Mail Move", True },
515 { "menuFile.Reload CMail Message", True },
519 Enables trainingOnEnables[] = {
520 { "menuMode.Edit Comment", False },
521 { "menuMode.Pause", False },
522 { "menuStep.Forward", False },
523 { "menuStep.Backward", False },
524 { "menuStep.Forward to End", False },
525 { "menuStep.Back to Start", False },
526 { "menuStep.Move Now", False },
527 { "menuStep.Truncate Game", False },
531 Enables trainingOffEnables[] = {
532 { "menuMode.Edit Comment", True },
533 { "menuMode.Pause", True },
534 { "menuStep.Forward", True },
535 { "menuStep.Backward", True },
536 { "menuStep.Forward to End", True },
537 { "menuStep.Back to Start", True },
538 { "menuStep.Move Now", True },
539 { "menuStep.Truncate Game", True },
543 Enables machineThinkingEnables[] = {
544 { "menuFile.Load Game", False },
545 { "menuFile.Load Next Game", False },
546 { "menuFile.Load Previous Game", False },
547 { "menuFile.Reload Same Game", False },
548 { "menuFile.Paste Game", False },
549 { "menuFile.Load Position", False },
550 { "menuFile.Load Next Position", False },
551 { "menuFile.Load Previous Position", False },
552 { "menuFile.Reload Same Position", False },
553 { "menuFile.Paste Position", False },
554 { "menuMode.Machine White", False },
555 { "menuMode.Machine Black", False },
556 { "menuMode.Two Machines", False },
557 { "menuStep.Retract Move", False },
561 Enables userThinkingEnables[] = {
562 { "menuFile.Load Game", True },
563 { "menuFile.Load Next Game", True },
564 { "menuFile.Load Previous Game", True },
565 { "menuFile.Reload Same Game", True },
566 { "menuFile.Paste Game", True },
567 { "menuFile.Load Position", True },
568 { "menuFile.Load Next Position", True },
569 { "menuFile.Load Previous Position", True },
570 { "menuFile.Reload Same Position", True },
571 { "menuFile.Paste Position", True },
572 { "menuMode.Machine White", True },
573 { "menuMode.Machine Black", True },
574 { "menuMode.Two Machines", True },
575 { "menuStep.Retract Move", True },
581 MenuItem fileMenu[] = {
582 {N_("New Shuffle Game ..."), ShuffleMenuProc},
583 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
584 // {"----", NothingProc},
585 // {N_("Save Game"), SaveGameProc},
586 // {"----", NothingProc},
587 {N_("Copy Game"), CopyGameProc},
588 {N_("Paste Game"), PasteGameProc},
589 // {"----", NothingProc},
590 // {N_("Load Position"), LoadPositionProc},
591 // {N_("Load Next Position"), LoadNextPositionProc},
592 // {N_("Load Previous Position"), LoadPrevPositionProc},
593 // {N_("Reload Same Position"), ReloadPositionProc},
594 // {N_("Save Position"), SavePositionProc},
595 // {"----", NothingProc},
596 {N_("Copy Position"), CopyPositionProc},
597 {N_("Paste Position"), PastePositionProc},
598 // {"----", NothingProc},
599 {N_("Mail Move"), MailMoveProc},
600 {N_("Reload CMail Message"), ReloadCmailMsgProc},
601 // {"----", NothingProc},
605 MenuItem modeMenu[] = {
606 // {N_("Machine White"), MachineWhiteProc},
607 // {N_("Machine Black"), MachineBlackProc},
608 // {N_("Two Machines"), TwoMachinesProc},
609 // {N_("Analysis Mode"), AnalyzeModeProc},
610 // {N_("Analyze File"), AnalyzeFileProc },
611 // {N_("ICS Client"), IcsClientProc},
612 // {N_("Edit Game"), EditGameProc},
613 // {N_("Edit Position"), EditPositionProc},
614 // {N_("Training"), TrainingProc},
615 // {"----", NothingProc},
616 {N_("Show Engine Output"), EngineOutputProc},
617 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
618 {N_("Show Game List"), ShowGameListProc},
619 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
620 // {"----", NothingProc},
621 // {N_("Edit Tags"), EditTagsProc},
622 {N_("Edit Comment"), EditCommentProc},
623 {N_("ICS Input Box"), IcsInputBoxProc},
627 MenuItem optionsMenu[] = {
628 // {N_("Flip View"), FlipViewProc},
629 // {"----", NothingProc},
630 {N_("Adjudications ..."), EngineMenuProc},
631 {N_("General Settings ..."), UciMenuProc},
632 {N_("Engine #1 Settings ..."), FirstSettingsProc},
633 {N_("Engine #2 Settings ..."), SecondSettingsProc},
634 {N_("Time Control ..."), TimeControlProc},
635 {"----", NothingProc},
636 // {N_("Always Queen"), AlwaysQueenProc},
637 // {N_("Animate Dragging"), AnimateDraggingProc},
638 // {N_("Animate Moving"), AnimateMovingProc},
639 // {N_("Auto Comment"), AutocommProc},
640 // {N_("Auto Flag"), AutoflagProc},
641 // {N_("Auto Flip View"), AutoflipProc},
642 // {N_("Auto Observe"), AutobsProc},
643 // {N_("Auto Raise Board"), AutoraiseProc},
644 // {N_("Auto Save"), AutosaveProc},
645 // {N_("Blindfold"), BlindfoldProc},
646 // {N_("Flash Moves"), FlashMovesProc},
647 // {N_("Get Move List"), GetMoveListProc},
649 // {N_("Highlight Dragging"), HighlightDraggingProc},
651 // {N_("Highlight Last Move"), HighlightLastMoveProc},
652 // {N_("Move Sound"), MoveSoundProc},
653 // {N_("ICS Alarm"), IcsAlarmProc},
654 // {N_("Old Save Style"), OldSaveStyleProc},
655 // {N_("Periodic Updates"), PeriodicUpdatesProc},
656 // {N_("Ponder Next Move"), PonderNextMoveProc},
657 // {N_("Popup Exit Message"), PopupExitMessageProc},
658 // {N_("Popup Move Errors"), PopupMoveErrorsProc},
659 // {N_("Premove"), PremoveProc},
660 // {N_("Quiet Play"), QuietPlayProc},
661 // {N_("Hide Thinking"), HideThinkingProc},
662 // {N_("Test Legality"), TestLegalityProc},
667 {N_("File"), fileMenu},
668 {N_("Mode"), modeMenu},
669 {N_("Options"), optionsMenu},
673 #define PIECE_MENU_SIZE 18
674 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
675 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
676 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
677 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
678 N_("Empty square"), N_("Clear board") },
679 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
680 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
681 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
682 N_("Empty square"), N_("Clear board") }
684 /* must be in same order as PieceMenuStrings! */
685 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
686 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
687 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
688 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
689 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
690 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
691 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
692 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
693 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
696 #define DROP_MENU_SIZE 6
697 String dropMenuStrings[DROP_MENU_SIZE] = {
698 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
700 /* must be in same order as PieceMenuStrings! */
701 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
702 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
703 WhiteRook, WhiteQueen
711 DropMenuEnables dmEnables[] = {
720 { XtNborderWidth, 0 },
721 { XtNdefaultDistance, 0 },
725 { XtNborderWidth, 0 },
726 { XtNresizable, (XtArgVal) True },
730 { XtNborderWidth, 0 },
735 XtResource clientResources[] = {
736 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
737 XtOffset(AppDataPtr, whitePieceColor), XtRString,
739 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
740 XtOffset(AppDataPtr, blackPieceColor), XtRString,
742 { "lightSquareColor", "lightSquareColor", XtRString,
743 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
744 XtRString, LIGHT_SQUARE_COLOR },
745 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
746 XtOffset(AppDataPtr, darkSquareColor), XtRString,
748 { "highlightSquareColor", "highlightSquareColor", XtRString,
749 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
750 XtRString, HIGHLIGHT_SQUARE_COLOR },
751 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
752 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
753 XtRString, PREMOVE_HIGHLIGHT_COLOR },
754 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
755 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
756 (XtPointer) MOVES_PER_SESSION },
757 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
758 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
759 (XtPointer) TIME_INCREMENT },
760 { "initString", "initString", XtRString, sizeof(String),
761 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
762 { "secondInitString", "secondInitString", XtRString, sizeof(String),
763 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
764 { "firstComputerString", "firstComputerString", XtRString,
765 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
767 { "secondComputerString", "secondComputerString", XtRString,
768 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
770 { "firstChessProgram", "firstChessProgram", XtRString,
771 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
772 XtRString, FIRST_CHESS_PROGRAM },
773 { "secondChessProgram", "secondChessProgram", XtRString,
774 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
775 XtRString, SECOND_CHESS_PROGRAM },
776 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
777 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
778 XtRImmediate, (XtPointer) False },
779 { "noChessProgram", "noChessProgram", XtRBoolean,
780 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
781 XtRImmediate, (XtPointer) False },
782 { "firstHost", "firstHost", XtRString, sizeof(String),
783 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
784 { "secondHost", "secondHost", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
786 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
787 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
788 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
789 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
790 { "bitmapDirectory", "bitmapDirectory", XtRString,
791 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
793 { "remoteShell", "remoteShell", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
795 { "remoteUser", "remoteUser", XtRString, sizeof(String),
796 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
797 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
798 XtOffset(AppDataPtr, timeDelay), XtRString,
799 (XtPointer) TIME_DELAY_QUOTE },
800 { "timeControl", "timeControl", XtRString, sizeof(String),
801 XtOffset(AppDataPtr, timeControl), XtRString,
802 (XtPointer) TIME_CONTROL },
803 { "internetChessServerMode", "internetChessServerMode",
804 XtRBoolean, sizeof(Boolean),
805 XtOffset(AppDataPtr, icsActive), XtRImmediate,
807 { "internetChessServerHost", "internetChessServerHost",
808 XtRString, sizeof(String),
809 XtOffset(AppDataPtr, icsHost),
810 XtRString, (XtPointer) ICS_HOST },
811 { "internetChessServerPort", "internetChessServerPort",
812 XtRString, sizeof(String),
813 XtOffset(AppDataPtr, icsPort), XtRString,
814 (XtPointer) ICS_PORT },
815 { "internetChessServerCommPort", "internetChessServerCommPort",
816 XtRString, sizeof(String),
817 XtOffset(AppDataPtr, icsCommPort), XtRString,
819 { "internetChessServerLogonScript", "internetChessServerLogonScript",
820 XtRString, sizeof(String),
821 XtOffset(AppDataPtr, icsLogon), XtRString,
823 { "internetChessServerHelper", "internetChessServerHelper",
824 XtRString, sizeof(String),
825 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
826 { "internetChessServerInputBox", "internetChessServerInputBox",
827 XtRBoolean, sizeof(Boolean),
828 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
830 { "icsAlarm", "icsAlarm",
831 XtRBoolean, sizeof(Boolean),
832 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
834 { "icsAlarmTime", "icsAlarmTime",
836 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
838 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
839 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
841 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
842 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
843 { "gateway", "gateway", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, gateway), XtRString, "" },
845 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
847 { "loadGameIndex", "loadGameIndex",
849 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
851 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
852 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
853 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
854 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
855 XtRImmediate, (XtPointer) True },
856 { "autoSaveGames", "autoSaveGames", XtRBoolean,
857 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
858 XtRImmediate, (XtPointer) False },
859 { "blindfold", "blindfold", XtRBoolean,
860 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
861 XtRImmediate, (XtPointer) False },
862 { "loadPositionFile", "loadPositionFile", XtRString,
863 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
865 { "loadPositionIndex", "loadPositionIndex",
867 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
869 { "savePositionFile", "savePositionFile", XtRString,
870 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
872 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
873 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
874 { "matchGames", "matchGames", XtRInt, sizeof(int),
875 XtOffset(AppDataPtr, matchGames), XtRImmediate,
877 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
878 XtOffset(AppDataPtr, monoMode), XtRImmediate,
880 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
881 XtOffset(AppDataPtr, debugMode), XtRImmediate,
883 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
884 XtOffset(AppDataPtr, clockMode), XtRImmediate,
886 { "boardSize", "boardSize", XtRString, sizeof(String),
887 XtOffset(AppDataPtr, boardSize), XtRString, "" },
888 { "searchTime", "searchTime", XtRString, sizeof(String),
889 XtOffset(AppDataPtr, searchTime), XtRString,
891 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
892 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
894 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
895 XtOffset(AppDataPtr, showCoords), XtRImmediate,
897 { "showJail", "showJail", XtRInt, sizeof(int),
898 XtOffset(AppDataPtr, showJail), XtRImmediate,
900 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
901 XtOffset(AppDataPtr, showThinking), XtRImmediate,
903 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
904 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
906 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
907 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
909 { "clockFont", "clockFont", XtRString, sizeof(String),
910 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
911 { "coordFont", "coordFont", XtRString, sizeof(String),
912 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
913 { "font", "font", XtRString, sizeof(String),
914 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
915 { "ringBellAfterMoves", "ringBellAfterMoves",
916 XtRBoolean, sizeof(Boolean),
917 XtOffset(AppDataPtr, ringBellAfterMoves),
918 XtRImmediate, (XtPointer) False },
919 { "autoCallFlag", "autoCallFlag", XtRBoolean,
920 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
921 XtRImmediate, (XtPointer) False },
922 { "autoFlipView", "autoFlipView", XtRBoolean,
923 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
924 XtRImmediate, (XtPointer) True },
925 { "autoObserve", "autoObserve", XtRBoolean,
926 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
927 XtRImmediate, (XtPointer) False },
928 { "autoComment", "autoComment", XtRBoolean,
929 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
930 XtRImmediate, (XtPointer) False },
931 { "getMoveList", "getMoveList", XtRBoolean,
932 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
933 XtRImmediate, (XtPointer) True },
935 { "highlightDragging", "highlightDragging", XtRBoolean,
936 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
937 XtRImmediate, (XtPointer) False },
939 { "highlightLastMove", "highlightLastMove", XtRBoolean,
940 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
941 XtRImmediate, (XtPointer) False },
942 { "premove", "premove", XtRBoolean,
943 sizeof(Boolean), XtOffset(AppDataPtr, premove),
944 XtRImmediate, (XtPointer) True },
945 { "testLegality", "testLegality", XtRBoolean,
946 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
947 XtRImmediate, (XtPointer) True },
948 { "flipView", "flipView", XtRBoolean,
949 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
950 XtRImmediate, (XtPointer) False },
951 { "cmail", "cmailGameName", XtRString, sizeof(String),
952 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
953 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
954 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
955 XtRImmediate, (XtPointer) False },
956 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
957 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
958 XtRImmediate, (XtPointer) False },
959 { "quietPlay", "quietPlay", XtRBoolean,
960 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
961 XtRImmediate, (XtPointer) False },
962 { "titleInWindow", "titleInWindow", XtRBoolean,
963 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
964 XtRImmediate, (XtPointer) False },
965 { "localLineEditing", "localLineEditing", XtRBoolean,
966 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
967 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
969 { "zippyTalk", "zippyTalk", XtRBoolean,
970 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
971 XtRImmediate, (XtPointer) ZIPPY_TALK },
972 { "zippyPlay", "zippyPlay", XtRBoolean,
973 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
974 XtRImmediate, (XtPointer) ZIPPY_PLAY },
975 { "zippyLines", "zippyLines", XtRString, sizeof(String),
976 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
977 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
978 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
979 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
980 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
981 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
982 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
983 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
984 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
985 ZIPPY_WRONG_PASSWORD },
986 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
987 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
988 { "zippyUseI", "zippyUseI", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
990 XtRImmediate, (XtPointer) ZIPPY_USE_I },
991 { "zippyBughouse", "zippyBughouse", XtRInt,
992 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
993 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
994 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
995 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
996 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
997 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
998 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
999 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1000 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1001 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1002 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1003 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1004 { "zippyAbort", "zippyAbort", XtRBoolean,
1005 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1006 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1007 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1008 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1009 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1010 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1011 (XtPointer) ZIPPY_MAX_GAMES },
1012 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1013 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1014 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1015 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1016 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1019 { "flashCount", "flashCount", XtRInt, sizeof(int),
1020 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1021 (XtPointer) FLASH_COUNT },
1022 { "flashRate", "flashRate", XtRInt, sizeof(int),
1023 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1024 (XtPointer) FLASH_RATE },
1025 { "pixmapDirectory", "pixmapDirectory", XtRString,
1026 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1028 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1029 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1030 (XtPointer) MS_LOGIN_DELAY },
1031 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1032 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1033 XtRImmediate, (XtPointer) False },
1034 { "colorShout", "colorShout", XtRString,
1035 sizeof(String), XtOffset(AppDataPtr, colorShout),
1036 XtRString, COLOR_SHOUT },
1037 { "colorSShout", "colorSShout", XtRString,
1038 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1039 XtRString, COLOR_SSHOUT },
1040 { "colorChannel1", "colorChannel1", XtRString,
1041 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1042 XtRString, COLOR_CHANNEL1 },
1043 { "colorChannel", "colorChannel", XtRString,
1044 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1045 XtRString, COLOR_CHANNEL },
1046 { "colorKibitz", "colorKibitz", XtRString,
1047 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1048 XtRString, COLOR_KIBITZ },
1049 { "colorTell", "colorTell", XtRString,
1050 sizeof(String), XtOffset(AppDataPtr, colorTell),
1051 XtRString, COLOR_TELL },
1052 { "colorChallenge", "colorChallenge", XtRString,
1053 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1054 XtRString, COLOR_CHALLENGE },
1055 { "colorRequest", "colorRequest", XtRString,
1056 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1057 XtRString, COLOR_REQUEST },
1058 { "colorSeek", "colorSeek", XtRString,
1059 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1060 XtRString, COLOR_SEEK },
1061 { "colorNormal", "colorNormal", XtRString,
1062 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1063 XtRString, COLOR_NORMAL },
1064 { "soundProgram", "soundProgram", XtRString,
1065 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1066 XtRString, "play" },
1067 { "soundShout", "soundShout", XtRString,
1068 sizeof(String), XtOffset(AppDataPtr, soundShout),
1070 { "soundSShout", "soundSShout", XtRString,
1071 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1073 { "soundChannel1", "soundChannel1", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1076 { "soundChannel", "soundChannel", XtRString,
1077 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1079 { "soundKibitz", "soundKibitz", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1082 { "soundTell", "soundTell", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, soundTell),
1085 { "soundChallenge", "soundChallenge", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1088 { "soundRequest", "soundRequest", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1091 { "soundSeek", "soundSeek", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1094 { "soundMove", "soundMove", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, soundMove),
1097 { "soundIcsWin", "soundIcsWin", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1100 { "soundIcsLoss", "soundIcsLoss", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1103 { "soundIcsDraw", "soundIcsDraw", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1106 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1109 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1112 { "reuseFirst", "reuseFirst", XtRBoolean,
1113 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1114 XtRImmediate, (XtPointer) True },
1115 { "reuseSecond", "reuseSecond", XtRBoolean,
1116 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1117 XtRImmediate, (XtPointer) True },
1118 { "animateDragging", "animateDragging", XtRBoolean,
1119 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1120 XtRImmediate, (XtPointer) True },
1121 { "animateMoving", "animateMoving", XtRBoolean,
1122 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1123 XtRImmediate, (XtPointer) True },
1124 { "animateSpeed", "animateSpeed", XtRInt,
1125 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1126 XtRImmediate, (XtPointer)10 },
1127 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1128 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1129 XtRImmediate, (XtPointer) True },
1130 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1131 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1132 XtRImmediate, (XtPointer) False },
1133 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1134 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1135 XtRImmediate, (XtPointer)4 },
1136 { "initialMode", "initialMode", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, initialMode),
1138 XtRImmediate, (XtPointer) "" },
1139 { "variant", "variant", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, variant),
1141 XtRImmediate, (XtPointer) "normal" },
1142 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1143 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1144 XtRImmediate, (XtPointer)PROTOVER },
1145 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1146 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1147 XtRImmediate, (XtPointer)PROTOVER },
1148 { "showButtonBar", "showButtonBar", XtRBoolean,
1149 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1150 XtRImmediate, (XtPointer) True },
1151 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1153 XtRString, COLOR_LOWTIMEWARNING },
1154 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1155 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1156 XtRImmediate, (XtPointer) False },
1157 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1158 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1159 XtRImmediate, (XtPointer) False },
1160 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1161 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1162 XtRImmediate, (XtPointer) False },
1163 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1164 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1165 XtRImmediate, (XtPointer) False },
1166 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1167 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1168 XtRImmediate, (XtPointer) False },
1169 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1171 XtRImmediate, (XtPointer) True },
1172 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1173 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1174 XtRImmediate, (XtPointer) 0},
1175 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1176 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1177 XtRImmediate, (XtPointer) 0},
1178 { "pgnEventHeader", "pgnEventHeader", XtRString,
1179 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1180 XtRImmediate, (XtPointer) "Computer Chess Game" },
1181 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1182 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1183 XtRImmediate, (XtPointer) -1},
1184 { "gameListTags", "gameListTags", XtRString,
1185 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1186 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1188 // [HGM] 4.3.xx options
1189 { "boardWidth", "boardWidth", XtRInt,
1190 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1191 XtRImmediate, (XtPointer) -1},
1192 { "boardHeight", "boardHeight", XtRInt,
1193 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1194 XtRImmediate, (XtPointer) -1},
1195 { "matchPause", "matchPause", XtRInt,
1196 sizeof(int), XtOffset(AppDataPtr, matchPause),
1197 XtRImmediate, (XtPointer) 10000},
1198 { "holdingsSize", "holdingsSize", XtRInt,
1199 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1200 XtRImmediate, (XtPointer) -1},
1201 { "flipBlack", "flipBlack", XtRBoolean,
1202 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1203 XtRImmediate, (XtPointer) False},
1204 { "allWhite", "allWhite", XtRBoolean,
1205 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1206 XtRImmediate, (XtPointer) False},
1207 { "pieceToCharTable", "pieceToCharTable", XtRString,
1208 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1209 XtRImmediate, (XtPointer) 0},
1210 { "alphaRank", "alphaRank", XtRBoolean,
1211 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1212 XtRImmediate, (XtPointer) False},
1213 { "testClaims", "testClaims", XtRBoolean,
1214 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1215 XtRImmediate, (XtPointer) True},
1216 { "checkMates", "checkMates", XtRBoolean,
1217 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1218 XtRImmediate, (XtPointer) True},
1219 { "materialDraws", "materialDraws", XtRBoolean,
1220 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1221 XtRImmediate, (XtPointer) True},
1222 { "trivialDraws", "trivialDraws", XtRBoolean,
1223 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1224 XtRImmediate, (XtPointer) False},
1225 { "ruleMoves", "ruleMoves", XtRInt,
1226 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1227 XtRImmediate, (XtPointer) 51},
1228 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1229 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1230 XtRImmediate, (XtPointer) 6},
1231 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1232 sizeof(int), XtOffset(AppDataPtr, engineComments),
1233 XtRImmediate, (XtPointer) 1},
1234 { "userName", "userName", XtRString,
1235 sizeof(int), XtOffset(AppDataPtr, userName),
1236 XtRImmediate, (XtPointer) 0},
1237 { "autoKibitz", "autoKibitz", XtRBoolean,
1238 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1239 XtRImmediate, (XtPointer) False},
1240 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1241 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1242 XtRImmediate, (XtPointer) 1},
1243 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1245 XtRImmediate, (XtPointer) 1},
1246 { "timeOddsMode", "timeOddsMode", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1248 XtRImmediate, (XtPointer) 0},
1249 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1251 XtRImmediate, (XtPointer) 1},
1252 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1254 XtRImmediate, (XtPointer) 1},
1255 { "firstNPS", "firstNPS", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1257 XtRImmediate, (XtPointer) -1},
1258 { "secondNPS", "secondNPS", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1260 XtRImmediate, (XtPointer) -1},
1261 { "serverMoves", "serverMoves", XtRString,
1262 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1263 XtRImmediate, (XtPointer) 0},
1264 { "serverPause", "serverPause", XtRInt,
1265 sizeof(int), XtOffset(AppDataPtr, serverPause),
1266 XtRImmediate, (XtPointer) 0},
1267 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1268 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1269 XtRImmediate, (XtPointer) False},
1270 { "userName", "userName", XtRString,
1271 sizeof(String), XtOffset(AppDataPtr, userName),
1272 XtRImmediate, (XtPointer) 0},
1273 { "egtFormats", "egtFormats", XtRString,
1274 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1275 XtRImmediate, (XtPointer) 0},
1276 { "rewindIndex", "rewindIndex", XtRInt,
1277 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1278 XtRImmediate, (XtPointer) 0},
1279 { "sameColorGames", "sameColorGames", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1281 XtRImmediate, (XtPointer) 0},
1282 { "smpCores", "smpCores", XtRInt,
1283 sizeof(int), XtOffset(AppDataPtr, smpCores),
1284 XtRImmediate, (XtPointer) 1},
1285 { "niceEngines", "niceEngines", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1287 XtRImmediate, (XtPointer) 0},
1288 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1289 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1290 XtRImmediate, (XtPointer) "xboard.debug"},
1291 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, engineComments),
1293 XtRImmediate, (XtPointer) 1},
1294 { "noGUI", "noGUI", XtRBoolean,
1295 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1296 XtRImmediate, (XtPointer) 0},
1297 { "firstOptions", "firstOptions", XtRString,
1298 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1299 XtRImmediate, (XtPointer) "" },
1300 { "secondOptions", "secondOptions", XtRString,
1301 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1302 XtRImmediate, (XtPointer) "" },
1303 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1304 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1305 XtRImmediate, (XtPointer) 0 },
1306 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1307 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1308 XtRImmediate, (XtPointer) 0 },
1310 // [HGM] Winboard_x UCI options
1311 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1312 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1313 XtRImmediate, (XtPointer) False},
1314 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1315 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1316 XtRImmediate, (XtPointer) False},
1317 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1318 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1319 XtRImmediate, (XtPointer) True},
1320 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1321 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1322 XtRImmediate, (XtPointer) True},
1323 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1324 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1325 XtRImmediate, (XtPointer) False},
1326 { "defaultHashSize", "defaultHashSize", XtRInt,
1327 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1328 XtRImmediate, (XtPointer) 64},
1329 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1330 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1331 XtRImmediate, (XtPointer) 4},
1332 { "polyglotDir", "polyglotDir", XtRString,
1333 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1334 XtRImmediate, (XtPointer) "." },
1335 { "polyglotBook", "polyglotBook", XtRString,
1336 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1337 XtRImmediate, (XtPointer) "" },
1338 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1339 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1340 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1341 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1342 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1343 XtRImmediate, (XtPointer) 0},
1344 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1345 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1346 XtRImmediate, (XtPointer) 0},
1347 { "keepAlive", "keepAlive", XtRInt,
1348 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1349 XtRImmediate, (XtPointer) 0},
1350 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1351 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1352 XtRImmediate, (XtPointer) False},
1353 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1354 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1355 XtRImmediate, (XtPointer) False},
1356 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1357 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1359 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1360 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1361 XtRImmediate, (XtPointer) True},
1362 { "autoDisplayTags", "autoDisplayTags", XtRBoolean,
1363 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayTags),
1364 XtRImmediate, (XtPointer) True},
1365 { "autoDisplayComment", "autoDisplayComment", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayComment),
1367 XtRImmediate, (XtPointer) True},
1368 { "pasteSelection", "pasteSelection", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, pasteSelection),
1370 XtRImmediate, (XtPointer) False},
1373 XrmOptionDescRec shellOptions[] = {
1374 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1375 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1376 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1377 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1378 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1379 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1380 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1381 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1382 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1383 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1384 { "-initString", "initString", XrmoptionSepArg, NULL },
1385 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1386 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1387 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1388 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1389 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1390 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1391 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1392 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1393 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1394 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1395 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1396 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1397 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1398 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1399 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1400 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1401 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1402 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1403 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1404 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1405 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1406 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1407 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1408 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1409 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1410 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1411 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1412 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1413 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1414 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1415 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1416 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1417 { "-internetChessServerMode", "internetChessServerMode",
1418 XrmoptionSepArg, NULL },
1419 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1420 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1421 { "-internetChessServerHost", "internetChessServerHost",
1422 XrmoptionSepArg, NULL },
1423 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1424 { "-internetChessServerPort", "internetChessServerPort",
1425 XrmoptionSepArg, NULL },
1426 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1427 { "-internetChessServerCommPort", "internetChessServerCommPort",
1428 XrmoptionSepArg, NULL },
1429 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1430 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1431 XrmoptionSepArg, NULL },
1432 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1433 { "-internetChessServerHelper", "internetChessServerHelper",
1434 XrmoptionSepArg, NULL },
1435 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1436 { "-internetChessServerInputBox", "internetChessServerInputBox",
1437 XrmoptionSepArg, NULL },
1438 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1439 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1440 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1441 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1442 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1443 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1444 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1445 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1446 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1447 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1448 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1449 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1450 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1451 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1452 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1453 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1454 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1455 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1456 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1457 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1458 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1459 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1460 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1461 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1462 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1463 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1464 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1465 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1466 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1467 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1468 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1469 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1470 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1471 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1472 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1473 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1474 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1475 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1476 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1477 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1478 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1479 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1480 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1481 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1482 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1483 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1484 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1485 { "-size", "boardSize", XrmoptionSepArg, NULL },
1486 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1487 { "-st", "searchTime", XrmoptionSepArg, NULL },
1488 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1489 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1490 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1491 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1492 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1494 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1495 { "-jail", "showJail", XrmoptionNoArg, "1" },
1496 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1497 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1499 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1500 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1501 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1502 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1503 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1504 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1505 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1506 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1507 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1508 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1509 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1510 { "-font", "font", XrmoptionSepArg, NULL },
1511 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1512 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1513 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1514 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1515 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1516 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1517 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1518 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1519 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1520 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1521 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1522 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1523 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1524 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1525 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1526 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1527 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1528 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1529 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1530 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1532 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1533 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1534 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1536 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1537 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1538 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1539 { "-premove", "premove", XrmoptionSepArg, NULL },
1540 { "-pre", "premove", XrmoptionNoArg, "True" },
1541 { "-xpre", "premove", XrmoptionNoArg, "False" },
1542 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1543 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1544 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1545 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1546 { "-flip", "flipView", XrmoptionNoArg, "True" },
1547 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1548 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1549 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1550 XrmoptionSepArg, NULL },
1551 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1552 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1553 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1554 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1555 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1556 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1557 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1558 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1559 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1560 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1561 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1563 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1564 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1565 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1566 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1567 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1568 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1569 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1570 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1571 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1572 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1573 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1574 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1575 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1576 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1577 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1578 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1579 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1580 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1581 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1582 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1583 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1584 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1585 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1586 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1587 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1588 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1589 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1590 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1591 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1592 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1593 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1595 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1596 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1597 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1598 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1599 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1600 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1601 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1602 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1603 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1604 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1605 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1606 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1607 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1608 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1609 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1610 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1611 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1612 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1613 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1614 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1615 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1616 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1617 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1618 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1619 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1620 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1621 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1622 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1623 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1624 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1625 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1626 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1627 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1628 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1629 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1630 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1631 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1632 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1633 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1634 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1635 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1636 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1637 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1638 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1639 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1640 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1641 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1642 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1643 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1644 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1645 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1646 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1647 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1648 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1649 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1650 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1651 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1652 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1653 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1654 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1655 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1656 { "-variant", "variant", XrmoptionSepArg, NULL },
1657 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1658 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1659 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1660 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1661 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1662 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1663 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1664 /* [AS,HR] New features */
1665 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1666 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1667 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1668 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1669 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1670 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1671 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1672 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1673 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1674 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1675 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1676 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1677 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1678 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1679 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1680 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1681 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1682 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1683 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1684 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1685 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1686 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1687 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1688 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1689 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1690 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1692 /* [HGM,HR] User-selectable board size */
1693 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1694 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1695 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1697 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1698 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1699 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1700 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1701 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1702 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1703 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1704 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1705 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1706 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1707 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1708 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1709 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1710 { "-userName", "userName", XrmoptionSepArg, NULL },
1711 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1712 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1713 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1714 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1715 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1716 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1717 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1718 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1719 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1720 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1721 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1722 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1723 { "-userName", "userName", XrmoptionSepArg, NULL },
1724 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1725 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1726 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1727 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1728 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1729 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1730 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1731 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1732 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1733 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1734 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1735 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1736 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1737 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1738 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1739 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1740 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1741 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1742 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1743 { "-autoDisplayTags", "autoDisplayTags", XrmoptionSepArg, NULL },
1744 { "-autoDisplayComment", "autoDisplayComment", XrmoptionSepArg, NULL },
1745 { "-pasteSelection", "pasteSelection", XrmoptionSepArg, NULL },
1748 XtActionsRec boardActions[] = {
1749 // { "HandleUserMove", HandleUserMove },
1750 { "AnimateUserMove", AnimateUserMove },
1751 // { "FileNameAction", FileNameAction },
1752 { "AskQuestionProc", AskQuestionProc },
1753 { "AskQuestionReplyAction", AskQuestionReplyAction },
1754 { "PieceMenuPopup", PieceMenuPopup },
1755 // { "WhiteClock", WhiteClock },
1756 // { "BlackClock", BlackClock },
1757 { "Iconify", Iconify },
1758 { "LoadSelectedProc", LoadSelectedProc },
1759 // { "LoadPositionProc", LoadPositionProc },
1760 // { "LoadNextPositionProc", LoadNextPositionProc },
1761 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1762 // { "ReloadPositionProc", ReloadPositionProc },
1763 { "CopyPositionProc", CopyPositionProc },
1764 { "PastePositionProc", PastePositionProc },
1765 { "CopyGameProc", CopyGameProc },
1766 { "PasteGameProc", PasteGameProc },
1767 // { "SaveGameProc", SaveGameProc },
1768 // { "SavePositionProc", SavePositionProc },
1769 { "MailMoveProc", MailMoveProc },
1770 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1771 // { "MachineWhiteProc", MachineWhiteProc },
1772 // { "MachineBlackProc", MachineBlackProc },
1773 // { "AnalysisModeProc", AnalyzeModeProc },
1774 // { "AnalyzeFileProc", AnalyzeFileProc },
1775 // { "TwoMachinesProc", TwoMachinesProc },
1776 // { "IcsClientProc", IcsClientProc },
1777 // { "EditGameProc", EditGameProc },
1778 // { "EditPositionProc", EditPositionProc },
1779 // { "TrainingProc", EditPositionProc },
1780 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1781 { "ShowGameListProc", ShowGameListProc },
1782 // { "ShowMoveListProc", HistoryShowProc},
1783 // { "EditTagsProc", EditCommentProc },
1784 { "EditCommentProc", EditCommentProc },
1785 // { "IcsAlarmProc", IcsAlarmProc },
1786 { "IcsInputBoxProc", IcsInputBoxProc },
1787 // { "AcceptProc", AcceptProc },
1788 // { "DeclineProc", DeclineProc },
1789 // { "RematchProc", RematchProc },
1790 // { "CallFlagProc", CallFlagProc },
1791 // { "DrawProc", DrawProc },
1792 // { "AdjournProc", AdjournProc },
1793 // { "AbortProc", AbortProc },
1794 // { "ResignProc", ResignProc },
1795 // { "AdjuWhiteProc", AdjuWhiteProc },
1796 // { "AdjuBlackProc", AdjuBlackProc },
1797 // { "AdjuDrawProc", AdjuDrawProc },
1798 { "EnterKeyProc", EnterKeyProc },
1799 // { "StopObservingProc", StopObservingProc },
1800 // { "StopExaminingProc", StopExaminingProc },
1801 // { "BackwardProc", BackwardProc },
1802 // { "ForwardProc", ForwardProc },
1803 // { "ToStartProc", ToStartProc },
1804 // { "ToEndProc", ToEndProc },
1805 // { "RevertProc", RevertProc },
1806 // { "TruncateGameProc", TruncateGameProc },
1807 // { "MoveNowProc", MoveNowProc },
1808 // { "RetractMoveProc", RetractMoveProc },
1809 // { "AlwaysQueenProc", AlwaysQueenProc },
1810 // { "AnimateDraggingProc", AnimateDraggingProc },
1811 // { "AnimateMovingProc", AnimateMovingProc },
1812 // { "AutoflagProc", AutoflagProc },
1813 // { "AutoflipProc", AutoflipProc },
1814 // { "AutobsProc", AutobsProc },
1815 // { "AutoraiseProc", AutoraiseProc },
1816 // { "AutosaveProc", AutosaveProc },
1817 // { "BlindfoldProc", BlindfoldProc },
1818 // { "FlashMovesProc", FlashMovesProc },
1819 // { "FlipViewProc", FlipViewProc },
1820 // { "GetMoveListProc", GetMoveListProc },
1822 // { "HighlightDraggingProc", HighlightDraggingProc },
1824 // { "HighlightLastMoveProc", HighlightLastMoveProc },
1825 // { "IcsAlarmProc", IcsAlarmProc },
1826 // { "MoveSoundProc", MoveSoundProc },
1827 // { "OldSaveStyleProc", OldSaveStyleProc },
1828 // { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1829 // { "PonderNextMoveProc", PonderNextMoveProc },
1830 // { "PopupExitMessageProc", PopupExitMessageProc },
1831 // { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1832 // { "PremoveProc", PremoveProc },
1833 // { "QuietPlayProc", QuietPlayProc },
1834 // { "ShowThinkingProc", ShowThinkingProc },
1835 // { "HideThinkingProc", HideThinkingProc },
1836 { "TestLegalityProc", TestLegalityProc },
1837 // { "InfoProc", InfoProc },
1838 // { "ManProc", ManProc },
1839 // { "HintProc", HintProc },
1840 // { "BookProc", BookProc },
1841 { "AboutGameProc", AboutGameProc },
1842 { "DebugProc", DebugProc },
1843 { "NothingProc", NothingProc },
1844 { "CommentPopDown", (XtActionProc) CommentPopDown },
1845 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1846 { "TagsPopDown", (XtActionProc) TagsPopDown },
1847 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1848 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1849 // { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1850 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1851 { "GameListPopDown", (XtActionProc) GameListPopDown },
1852 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1853 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1854 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1855 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1856 { "EnginePopDown", (XtActionProc) EnginePopDown },
1857 { "UciPopDown", (XtActionProc) UciPopDown },
1858 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1859 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1860 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1864 char ICSInputTranslations[] =
1865 "<Key>Return: EnterKeyProc() \n";
1867 String xboardResources[] = {
1868 // "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1869 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1870 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1874 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1875 "magenta", "cyan", "white" };
1879 TextColors textColors[(int)NColorClasses];
1881 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1883 parse_color(str, which)
1887 char *p, buf[100], *d;
1890 if (strlen(str) > 99) /* watch bounds on buf */
1895 for (i=0; i<which; ++i) {
1902 /* Could be looking at something like:
1904 .. in which case we want to stop on a comma also */
1905 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1909 return -1; /* Use default for empty field */
1912 if (which == 2 || isdigit(*p))
1915 while (*p && isalpha(*p))
1920 for (i=0; i<8; ++i) {
1921 if (!StrCaseCmp(buf, cnames[i]))
1922 return which? (i+40) : (i+30);
1924 if (!StrCaseCmp(buf, "default")) return -1;
1926 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1931 parse_cpair(cc, str)
1935 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1936 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1941 /* bg and attr are optional */
1942 textColors[(int)cc].bg = parse_color(str, 1);
1943 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1944 textColors[(int)cc].attr = 0;
1950 /* Arrange to catch delete-window events */
1951 Atom wm_delete_window;
1953 CatchDeleteWindow(Widget w, String procname)
1956 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1957 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1958 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1964 /* this should raise the board to the top */
1965 gtk_window_present(GTK_WINDOW(GUI_Window));
1969 #define BoardSize int
1970 void InitDrawingSizes(BoardSize boardSize, int flags)
1971 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1972 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1974 XtGeometryResult gres;
1977 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1978 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1980 timerWidth = (boardWidth - sep) / 2;
1982 if (appData.titleInWindow)
1987 w = boardWidth - 2*bor;
1991 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
1995 if(!formWidget) return;
1998 * Inhibit shell resizing.
2001 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2004 for(i=0; i<4; i++) {
2006 for(p=0; p<=(int)WhiteKing; p++)
2007 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2008 if(gameInfo.variant == VariantShogi) {
2009 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2010 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2011 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2012 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2013 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2016 if(gameInfo.variant == VariantGothic) {
2017 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2021 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2022 for(p=0; p<=(int)WhiteKing; p++)
2023 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2024 if(gameInfo.variant == VariantShogi) {
2025 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2026 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2027 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2028 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2029 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2032 if(gameInfo.variant == VariantGothic) {
2033 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2039 for(i=0; i<2; i++) {
2041 for(p=0; p<=(int)WhiteKing; p++)
2042 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2043 if(gameInfo.variant == VariantShogi) {
2044 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2045 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2046 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2047 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2048 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2051 if(gameInfo.variant == VariantGothic) {
2052 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2062 void EscapeExpand(char *p, char *q)
2063 { // [HGM] initstring: routine to shape up string arguments
2064 while(*p++ = *q++) if(p[-1] == '\\')
2066 case 'n': p[-1] = '\n'; break;
2067 case 'r': p[-1] = '\r'; break;
2068 case 't': p[-1] = '\t'; break;
2069 case '\\': p[-1] = '\\'; break;
2070 case 0: *p = 0; return;
2071 default: p[-1] = q[-1]; break;
2080 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2081 XSetWindowAttributes window_attributes;
2083 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2084 XrmValue vFrom, vTo;
2085 XtGeometryResult gres;
2088 int forceMono = False;
2092 // [HGM] before anything else, expand any indirection files amongst options
2093 char *argvCopy[1000]; // 1000 seems enough
2094 char newArgs[10000]; // holds actual characters
2097 srandom(time(0)); // [HGM] book: make random truly random
2100 for(i=0; i<argc; i++) {
2101 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2102 //fprintf(stderr, "arg %s\n", argv[i]);
2103 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2105 FILE *f = fopen(argv[i]+1, "rb");
2106 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2107 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2108 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2110 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2111 newArgs[k++] = 0; // terminate current arg
2112 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2113 argvCopy[j++] = newArgs + k; // get ready for next
2115 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2129 setbuf(stdout, NULL);
2130 setbuf(stderr, NULL);
2133 programName = strrchr(argv[0], '/');
2134 if (programName == NULL)
2135 programName = argv[0];
2140 XtSetLanguageProc(NULL, NULL, NULL);
2141 bindtextdomain(PACKAGE, LOCALEDIR);
2142 textdomain(PACKAGE);
2146 XtAppInitialize(&appContext, "XBoard", shellOptions,
2147 XtNumber(shellOptions),
2148 &argc, argv, xboardResources, NULL, 0);
2151 gtk_init (&argc, &argv);
2153 /* parse glade file to build widgets */
2155 builder = gtk_builder_new ();
2156 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2158 /* test if everything worked ok */
2160 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2161 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2163 GUI_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2164 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2166 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2167 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2169 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2170 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2171 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2172 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2173 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2174 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2175 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2176 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2178 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2179 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2181 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2182 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2184 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2185 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2187 /* EditTags window */
2188 GUI_EditTags = GTK_WIDGET (gtk_builder_get_object (builder, "EditTags"));
2189 if(!GUI_EditTags) printf("Error: gtk_builder didn't work!\n");
2191 GUI_EditTagsTextArea = GTK_WIDGET (gtk_builder_get_object (builder, "EditTagsTextArea"));
2192 if(!GUI_EditTagsTextArea) printf("Error: gtk_builder didn't work!\n");
2195 gtk_builder_connect_signals (builder, NULL);
2197 // don't unref the builder, since we use it to get references to widgets
2198 // g_object_unref (G_OBJECT (builder));
2200 /* end parse glade file */
2204 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2205 programName, argv[1]);
2207 fprintf(stderr, "Recognized options:\n");
2208 for(i = 0; i < XtNumber(shellOptions); i++)
2210 /* print first column */
2211 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2212 (shellOptions[i].argKind == XrmoptionSepArg
2214 /* print second column and end line */
2215 if (++i < XtNumber(shellOptions))
2217 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2218 shellOptions[i].option,
2219 (shellOptions[i].argKind == XrmoptionSepArg
2224 fprintf(stderr, "\n");
2231 if (p == NULL) p = "/tmp";
2232 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2233 gameCopyFilename = (char*) malloc(i);
2234 gamePasteFilename = (char*) malloc(i);
2235 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2236 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2238 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2239 clientResources, XtNumber(clientResources),
2242 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2243 static char buf[MSG_SIZ];
2244 EscapeExpand(buf, appData.initString);
2245 appData.initString = strdup(buf);
2246 EscapeExpand(buf, appData.secondInitString);
2247 appData.secondInitString = strdup(buf);
2248 EscapeExpand(buf, appData.firstComputerString);
2249 appData.firstComputerString = strdup(buf);
2250 EscapeExpand(buf, appData.secondComputerString);
2251 appData.secondComputerString = strdup(buf);
2254 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2257 if (chdir(chessDir) != 0) {
2258 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2264 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2265 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2266 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2267 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2270 setbuf(debugFP, NULL);
2273 /* [HGM,HR] make sure board size is acceptable */
2274 if(appData.NrFiles > BOARD_FILES ||
2275 appData.NrRanks > BOARD_RANKS )
2276 DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
2279 /* This feature does not work; animation needs a rewrite */
2280 appData.highlightDragging = FALSE;
2284 xDisplay = XtDisplay(shellWidget);
2285 xScreen = DefaultScreen(xDisplay);
2286 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2288 gameInfo.variant = StringToVariant(appData.variant);
2289 InitPosition(FALSE);
2291 /* calc board size */
2292 if (isdigit(appData.boardSize[0]))
2294 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2295 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2296 &fontPxlSize, &smallLayout, &tinyLayout);
2299 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2300 programName, appData.boardSize);
2305 /* Find some defaults; use the nearest known size */
2306 SizeDefaults *szd, *nearest;
2307 int distance = 99999;
2308 nearest = szd = sizeDefaults;
2309 while (szd->name != NULL)
2311 if (abs(szd->squareSize - squareSize) < distance)
2314 distance = abs(szd->squareSize - squareSize);
2315 if (distance == 0) break;
2319 if (i < 2) lineGap = nearest->lineGap;
2320 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2321 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2322 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2323 if (i < 6) smallLayout = nearest->smallLayout;
2324 if (i < 7) tinyLayout = nearest->tinyLayout;
2329 SizeDefaults *szd = sizeDefaults;
2330 if (*appData.boardSize == NULLCHAR)
2332 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2333 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2337 if (szd->name == NULL) szd--;
2341 while (szd->name != NULL
2342 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2344 if (szd->name == NULL)
2346 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2347 programName, appData.boardSize);
2351 squareSize = szd->squareSize;
2352 lineGap = szd->lineGap;
2353 clockFontPxlSize = szd->clockFontPxlSize;
2354 coordFontPxlSize = szd->coordFontPxlSize;
2355 fontPxlSize = szd->fontPxlSize;
2356 smallLayout = szd->smallLayout;
2357 tinyLayout = szd->tinyLayout;
2359 /* end figuring out what size to use */
2361 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2362 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2365 * Determine what fonts to use.
2367 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2368 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2369 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2370 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2371 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2372 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2373 appData.font = FindFont(appData.font, fontPxlSize);
2374 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2375 countFontStruct = XQueryFont(xDisplay, countFontID);
2376 // appData.font = FindFont(appData.font, fontPxlSize);
2378 xdb = XtDatabase(xDisplay);
2379 XrmPutStringResource(&xdb, "*font", appData.font);
2382 * Detect if there are not enough colors available and adapt.
2384 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2385 appData.monoMode = True;
2388 if (!appData.monoMode) {
2389 vFrom.addr = (caddr_t) appData.lightSquareColor;
2390 vFrom.size = strlen(appData.lightSquareColor);
2391 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2392 if (vTo.addr == NULL) {
2393 appData.monoMode = True;
2396 lightSquareColor = *(Pixel *) vTo.addr;
2399 if (!appData.monoMode) {
2400 vFrom.addr = (caddr_t) appData.darkSquareColor;
2401 vFrom.size = strlen(appData.darkSquareColor);
2402 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2403 if (vTo.addr == NULL) {
2404 appData.monoMode = True;
2407 darkSquareColor = *(Pixel *) vTo.addr;
2410 if (!appData.monoMode) {
2411 vFrom.addr = (caddr_t) appData.whitePieceColor;
2412 vFrom.size = strlen(appData.whitePieceColor);
2413 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2414 if (vTo.addr == NULL) {
2415 appData.monoMode = True;
2418 whitePieceColor = *(Pixel *) vTo.addr;
2421 if (!appData.monoMode) {
2422 vFrom.addr = (caddr_t) appData.blackPieceColor;
2423 vFrom.size = strlen(appData.blackPieceColor);
2424 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2425 if (vTo.addr == NULL) {
2426 appData.monoMode = True;
2429 blackPieceColor = *(Pixel *) vTo.addr;
2433 if (!appData.monoMode) {
2434 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2435 vFrom.size = strlen(appData.highlightSquareColor);
2436 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2437 if (vTo.addr == NULL) {
2438 appData.monoMode = True;
2441 highlightSquareColor = *(Pixel *) vTo.addr;
2445 if (!appData.monoMode) {
2446 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2447 vFrom.size = strlen(appData.premoveHighlightColor);
2448 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2449 if (vTo.addr == NULL) {
2450 appData.monoMode = True;
2453 premoveHighlightColor = *(Pixel *) vTo.addr;
2458 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2461 if (appData.bitmapDirectory == NULL ||
2462 appData.bitmapDirectory[0] == NULLCHAR)
2463 appData.bitmapDirectory = DEF_BITMAP_DIR;
2466 if (appData.lowTimeWarning && !appData.monoMode) {
2467 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2468 vFrom.size = strlen(appData.lowTimeWarningColor);
2469 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2470 if (vTo.addr == NULL)
2471 appData.monoMode = True;
2473 lowTimeWarningColor = *(Pixel *) vTo.addr;
2476 if (appData.monoMode && appData.debugMode) {
2477 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2478 (unsigned long) XWhitePixel(xDisplay, xScreen),
2479 (unsigned long) XBlackPixel(xDisplay, xScreen));
2482 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2483 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2484 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2485 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2486 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2487 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2488 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2489 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2490 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2491 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2493 if (appData.colorize) {
2495 _("%s: can't parse color names; disabling colorization\n"),
2498 appData.colorize = FALSE;
2500 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2501 textColors[ColorNone].attr = 0;
2503 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2509 layoutName = "tinyLayout";
2510 } else if (smallLayout) {
2511 layoutName = "smallLayout";
2513 layoutName = "normalLayout";
2516 if (appData.titleInWindow) {
2517 /* todo check what this appdata does */
2520 if (appData.showButtonBar) {
2521 /* TODO hide button bar if requested */
2525 if (appData.titleInWindow)
2530 if (appData.showButtonBar)
2537 if (appData.showButtonBar)
2547 /* set some checkboxes in the menu according to appData */
2549 if (appData.alwaysPromoteToQueen)
2550 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2552 if (appData.animateDragging)
2553 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2555 if (appData.animate)
2556 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2558 if (appData.autoComment)
2559 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2561 if (appData.autoCallFlag)
2562 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2564 if (appData.autoFlipView)
2565 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2567 if (appData.autoObserve)
2568 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2570 if (appData.autoRaiseBoard)
2571 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2573 if (appData.autoSaveGames)
2574 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2576 if (appData.saveGameFile[0] != NULLCHAR)
2578 /* Can't turn this off from menu */
2579 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2580 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2583 if (appData.blindfold)
2584 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2586 if (appData.flashCount > 0)
2587 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2589 if (appData.getMoveList)
2590 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2593 if (appData.highlightDragging)
2594 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2597 if (appData.highlightLastMove)
2598 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2600 if (appData.icsAlarm)
2601 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2603 if (appData.ringBellAfterMoves)
2604 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2606 if (appData.oldSaveStyle)
2607 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2609 if (appData.periodicUpdates)
2610 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2612 if (appData.ponderNextMove)
2613 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2615 if (appData.popupExitMessage)
2616 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2618 if (appData.popupMoveErrors)
2619 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2621 if (appData.premove)
2622 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2624 if (appData.quietPlay)
2625 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2627 if (appData.showCoords)
2628 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2630 if (appData.showThinking)
2631 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2633 if (appData.testLegality)
2634 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2636 /* end setting check boxes */
2638 /* load square colors */
2639 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2640 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2641 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2643 /* use two icons to indicate if it is white's or black's turn */
2644 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2645 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2646 WindowIcon = WhiteIcon;
2647 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2650 /* realize window */
2651 gtk_widget_show (GUI_Window);
2653 /* recalc boardsize */
2658 if (appData.animate || appData.animateDragging)
2663 if (errorExitStatus == -1) {
2664 if (appData.icsActive) {
2665 /* We now wait until we see "login:" from the ICS before
2666 sending the logon script (problems with timestamp otherwise) */
2667 /*ICSInitScript();*/
2668 if (appData.icsInputBox) ICSInputBoxPopUp();
2672 signal(SIGWINCH, TermSizeSigHandler);
2674 signal(SIGINT, IntSigHandler);
2675 signal(SIGTERM, IntSigHandler);
2676 if (*appData.cmailGameName != NULLCHAR) {
2677 signal(SIGUSR1, CmailSigHandler);
2680 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2684 * Create a cursor for the board widget.
2685 * (This needs to be called after the window has been created to have access to board-window)
2688 BoardCursor = gdk_cursor_new(GDK_HAND2);
2689 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2690 gdk_cursor_destroy(BoardCursor);
2695 if (appData.debugMode) fclose(debugFP); // [DM] debug
2702 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2703 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2705 unlink(gameCopyFilename);
2706 unlink(gamePasteFilename);
2709 RETSIGTYPE TermSizeSigHandler(int sig)
2722 CmailSigHandler(sig)
2728 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2730 /* Activate call-back function CmailSigHandlerCallBack() */
2731 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2733 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2737 CmailSigHandlerCallBack(isr, closure, message, count, error)
2745 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2747 /**** end signal code ****/
2757 f = fopen(appData.icsLogon, "r");
2763 strcat(buf, appData.icsLogon);
2764 f = fopen(buf, "r");
2768 ProcessICSInitScript(f);
2775 EditCommentPopDown();
2785 if (!menuBarWidget) return;
2786 w = XtNameToWidget(menuBarWidget, "menuStep.Revert");
2788 DisplayError("menuStep.Revert", 0);
2790 XtSetSensitive(w, !grey);
2795 SetMenuEnables(enab)
2800 if (!builder) return;
2801 while (enab->name != NULL) {
2802 o = gtk_builder_get_object(builder, enab->name);
2803 if(GTK_IS_WIDGET(o))
2804 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2807 if(GTK_IS_ACTION(o))
2808 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2810 DisplayError(enab->name, 0);
2818 SetMenuEnables(icsEnables);
2821 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2822 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2829 SetMenuEnables(ncpEnables);
2835 SetMenuEnables(gnuEnables);
2841 SetMenuEnables(cmailEnables);
2847 SetMenuEnables(trainingOnEnables);
2848 if (appData.showButtonBar) {
2849 // XtSetSensitive(buttonBarWidget, False);
2855 SetTrainingModeOff()
2857 SetMenuEnables(trainingOffEnables);
2858 if (appData.showButtonBar) {
2859 // XtSetSensitive(buttonBarWidget, True);
2864 SetUserThinkingEnables()
2866 if (appData.noChessProgram) return;
2867 SetMenuEnables(userThinkingEnables);
2871 SetMachineThinkingEnables()
2873 if (appData.noChessProgram) return;
2874 SetMenuEnables(machineThinkingEnables);
2876 case MachinePlaysBlack:
2877 case MachinePlaysWhite:
2878 case TwoMachinesPlay:
2879 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2880 // ModeToWidgetName(gameMode)), True);
2887 #define Abs(n) ((n)<0 ? -(n) : (n))
2890 * Find a font that matches "pattern" that is as close as
2891 * possible to the targetPxlSize. Prefer fonts that are k
2892 * pixels smaller to fonts that are k pixels larger. The
2893 * pattern must be in the X Consortium standard format,
2894 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2895 * The return value should be freed with XtFree when no
2898 char *FindFont(pattern, targetPxlSize)
2902 char **fonts, *p, *best, *scalable, *scalableTail;
2903 int i, j, nfonts, minerr, err, pxlSize;
2906 char **missing_list;
2908 char *def_string, *base_fnt_lst, strInt[3];
2910 XFontStruct **fnt_list;
2912 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2913 sprintf(strInt, "%d", targetPxlSize);
2914 p = strstr(pattern, "--");
2915 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2916 strcat(base_fnt_lst, strInt);
2917 strcat(base_fnt_lst, strchr(p + 2, '-'));
2919 if ((fntSet = XCreateFontSet(xDisplay,
2923 &def_string)) == NULL) {
2925 fprintf(stderr, _("Unable to create font set.\n"));
2929 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2931 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2933 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2934 programName, pattern);
2942 for (i=0; i<nfonts; i++) {
2945 if (*p != '-') continue;
2947 if (*p == NULLCHAR) break;
2948 if (*p++ == '-') j++;
2950 if (j < 7) continue;
2953 scalable = fonts[i];
2956 err = pxlSize - targetPxlSize;
2957 if (Abs(err) < Abs(minerr) ||
2958 (minerr > 0 && err < 0 && -err == minerr)) {
2964 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2965 /* If the error is too big and there is a scalable font,
2966 use the scalable font. */
2967 int headlen = scalableTail - scalable;
2968 p = (char *) XtMalloc(strlen(scalable) + 10);
2969 while (isdigit(*scalableTail)) scalableTail++;
2970 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2972 p = (char *) XtMalloc(strlen(best) + 1);
2975 if (appData.debugMode) {
2976 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2977 pattern, targetPxlSize, p);
2980 if (missing_count > 0)
2981 XFreeStringList(missing_list);
2982 XFreeFontSet(xDisplay, fntSet);
2984 XFreeFontNames(fonts);
2991 /* 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*/
2993 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2994 | GCBackground | GCFunction | GCPlaneMask;
2995 XGCValues gc_values;
2998 gc_values.plane_mask = AllPlanes;
2999 gc_values.line_width = lineGap;
3000 gc_values.line_style = LineSolid;
3001 gc_values.function = GXcopy;
3003 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3004 gc_values.background = XWhitePixel(xDisplay, xScreen);
3005 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3006 XSetFont(xDisplay, coordGC, coordFontID);
3008 if (appData.monoMode) {
3009 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3010 gc_values.background = XBlackPixel(xDisplay, xScreen);
3011 lightSquareGC = wbPieceGC
3012 = XtGetGC(shellWidget, value_mask, &gc_values);
3014 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3015 gc_values.background = XWhitePixel(xDisplay, xScreen);
3016 darkSquareGC = bwPieceGC
3017 = XtGetGC(shellWidget, value_mask, &gc_values);
3019 if (DefaultDepth(xDisplay, xScreen) == 1) {
3020 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3021 gc_values.function = GXcopyInverted;
3022 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3023 gc_values.function = GXcopy;
3024 if (XBlackPixel(xDisplay, xScreen) == 1) {
3025 bwPieceGC = darkSquareGC;
3026 wbPieceGC = copyInvertedGC;
3028 bwPieceGC = copyInvertedGC;
3029 wbPieceGC = lightSquareGC;
3033 gc_values.foreground = lightSquareColor;
3034 gc_values.background = darkSquareColor;
3035 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3037 gc_values.foreground = darkSquareColor;
3038 gc_values.background = lightSquareColor;
3039 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3041 gc_values.foreground = jailSquareColor;
3042 gc_values.background = jailSquareColor;
3043 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 gc_values.foreground = whitePieceColor;
3046 gc_values.background = darkSquareColor;
3047 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 gc_values.foreground = whitePieceColor;
3050 gc_values.background = lightSquareColor;
3051 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = whitePieceColor;
3054 gc_values.background = jailSquareColor;
3055 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3057 gc_values.foreground = blackPieceColor;
3058 gc_values.background = darkSquareColor;
3059 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3061 gc_values.foreground = blackPieceColor;
3062 gc_values.background = lightSquareColor;
3063 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3065 gc_values.foreground = blackPieceColor;
3066 gc_values.background = jailSquareColor;
3067 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 for(i=0;i<MAXPIECES;i++)
3080 g_free(SVGpieces[i]);
3087 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3088 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3089 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3092 /* get some defaults going */
3093 for(i=WhitePawn; i<DemotePiece+1; i++)
3094 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3096 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3097 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3098 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3099 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3100 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3101 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3103 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3104 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3105 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3106 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3107 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3108 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3114 static void MenuBarSelect(w, addr, index)
3119 XtActionProc proc = (XtActionProc) addr;
3121 (proc)(NULL, NULL, NULL, NULL);
3124 void CreateMenuBarPopup(parent, name, mb)
3134 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3137 XtSetArg(args[j], XtNleftMargin, 20); j++;
3138 XtSetArg(args[j], XtNrightMargin, 20); j++;
3140 while (mi->string != NULL) {
3141 if (strcmp(mi->string, "----") == 0) {
3142 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3145 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3146 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3148 XtAddCallback(entry, XtNcallback,
3149 (XtCallbackProc) MenuBarSelect,
3150 (caddr_t) mi->proc);
3156 Widget CreateMenuBar(mb)
3160 Widget anchor, menuBar;
3162 char menuName[MSG_SIZ];
3165 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3166 XtSetArg(args[j], XtNvSpace, 0); j++;
3167 XtSetArg(args[j], XtNborderWidth, 0); j++;
3168 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3169 formWidget, args, j);
3171 while (mb->name != NULL) {
3172 strcpy(menuName, "menu");
3173 strcat(menuName, mb->name);
3175 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3178 shortName[0] = _(mb->name)[0];
3179 shortName[1] = NULLCHAR;
3180 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3183 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3186 XtSetArg(args[j], XtNborderWidth, 0); j++;
3187 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3189 CreateMenuBarPopup(menuBar, menuName, mb);
3197 CreatePieceMenu(name, color)
3204 ChessSquare selection;
3206 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3207 boardWidget, args, 0);
3209 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3210 String item = pieceMenuStrings[color][i];
3212 if (strcmp(item, "----") == 0) {
3213 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3216 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3217 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3219 selection = pieceMenuTranslation[color][i];
3220 XtAddCallback(entry, XtNcallback,
3221 (XtCallbackProc) PieceMenuSelect,
3222 (caddr_t) selection);
3223 if (selection == WhitePawn || selection == BlackPawn) {
3224 XtSetArg(args[0], XtNpopupOnEntry, entry);
3225 XtSetValues(menu, args, 1);
3238 ChessSquare selection;
3240 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3241 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3243 // XtRegisterGrabAction(PieceMenuPopup, True,
3244 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3245 // GrabModeAsync, GrabModeAsync);
3247 // XtSetArg(args[0], XtNlabel, _("Drop"));
3248 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3249 // boardWidget, args, 1);
3250 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3251 // String item = dropMenuStrings[i];
3253 // if (strcmp(item, "----") == 0) {
3254 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3255 // dropMenu, NULL, 0);
3257 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3258 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3259 // dropMenu, args, 1);
3260 // selection = dropMenuTranslation[i];
3261 // XtAddCallback(entry, XtNcallback,
3262 // (XtCallbackProc) DropMenuSelect,
3263 // (caddr_t) selection);
3268 void SetupDropMenu()
3276 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3277 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3278 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3279 dmEnables[i].piece);
3280 XtSetSensitive(entry, p != NULL || !appData.testLegality
3281 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3282 && !appData.icsActive));
3284 while (p && *p++ == dmEnables[i].piece) count++;
3285 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3287 XtSetArg(args[j], XtNlabel, label); j++;
3288 XtSetValues(entry, args, j);
3292 void PieceMenuPopup(w, event, params, num_params)
3296 Cardinal *num_params;
3299 if (event->type != ButtonPress) return;
3300 if (errorUp) ErrorPopDown();
3304 whichMenu = params[0];
3306 case IcsPlayingWhite:
3307 case IcsPlayingBlack:
3309 case MachinePlaysWhite:
3310 case MachinePlaysBlack:
3311 if (appData.testLegality &&
3312 gameInfo.variant != VariantBughouse &&
3313 gameInfo.variant != VariantCrazyhouse) return;
3315 whichMenu = "menuD";
3321 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3322 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3323 pmFromX = pmFromY = -1;
3327 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3329 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3331 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3334 static void PieceMenuSelect(w, piece, junk)
3339 if (pmFromX < 0 || pmFromY < 0) return;
3340 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3343 static void DropMenuSelect(w, piece, junk)
3348 if (pmFromX < 0 || pmFromY < 0) return;
3349 DropMenuEvent(piece, pmFromX, pmFromY);
3353 * If the user selects on a border boundary, return -1; if off the board,
3354 * return -2. Otherwise map the event coordinate to the square.
3356 int EventToSquare(x, limit)
3364 if ((x % (squareSize + lineGap)) >= squareSize)
3366 x /= (squareSize + lineGap);
3372 static void do_flash_delay(msec)
3378 static void drawHighlight(file, rank, line_type)
3379 int file, rank, line_type;
3384 if (lineGap == 0 || appData.blindfold) return;
3388 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3389 (squareSize + lineGap);
3390 y = lineGap/2 + rank * (squareSize + lineGap);
3394 x = lineGap/2 + file * (squareSize + lineGap);
3395 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3396 (squareSize + lineGap);
3400 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3402 /* draw the highlight */
3403 cairo_move_to (cr, x, y);
3404 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3405 cairo_rel_line_to (cr, squareSize+lineGap,0);
3406 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3407 cairo_close_path (cr);
3409 cairo_set_line_width (cr, lineGap);
3412 /* TODO: use appdata colors */
3413 case LINE_TYPE_HIGHLIGHT:
3414 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3417 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3419 case LINE_TYPE_NORMAL:
3421 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3432 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3433 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3436 SetHighlights(fromX, fromY, toX, toY)
3437 int fromX, fromY, toX, toY;
3439 if (hi1X != fromX || hi1Y != fromY)
3441 if (hi1X >= 0 && hi1Y >= 0)
3443 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3445 if (fromX >= 0 && fromY >= 0)
3447 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3450 if (hi2X != toX || hi2Y != toY)
3452 if (hi2X >= 0 && hi2Y >= 0)
3454 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3456 if (toX >= 0 && toY >= 0)
3458 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3472 SetHighlights(-1, -1, -1, -1);
3477 SetPremoveHighlights(fromX, fromY, toX, toY)
3478 int fromX, fromY, toX, toY;
3480 if (pm1X != fromX || pm1Y != fromY)
3482 if (pm1X >= 0 && pm1Y >= 0)
3484 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3486 if (fromX >= 0 && fromY >= 0)
3488 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3491 if (pm2X != toX || pm2Y != toY)
3493 if (pm2X >= 0 && pm2Y >= 0)
3495 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3497 if (toX >= 0 && toY >= 0)
3499 drawHighlight(toX, toY, LINE_TYPE_PRE);
3512 ClearPremoveHighlights()
3514 SetPremoveHighlights(-1, -1, -1, -1);
3517 static void BlankSquare(x, y, color, piece, dest)
3530 pb = SVGLightSquare;
3532 case 2: /* neutral */
3534 pb = SVGNeutralSquare;
3537 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3541 static void DrawPiece(piece, square_color, x, y, dest)
3543 int square_color, x, y;
3546 /* redraw background, since piece might be transparent in some areas */
3547 BlankSquare(x,y,square_color,piece,dest);
3550 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3551 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3552 GDK_RGB_DITHER_NORMAL, 0, 0);
3556 /* [HR] determine square color depending on chess variant. */
3557 static int SquareColor(row, column)
3562 if (gameInfo.variant == VariantXiangqi) {
3563 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3565 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3567 } else if (row <= 4) {
3573 square_color = ((column + row) % 2) == 1;
3576 /* [hgm] holdings: next line makes all holdings squares light */
3577 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3579 return square_color;
3582 void DrawSquare(row, column, piece, do_flash)
3583 int row, column, do_flash;
3586 int square_color, x, y;
3591 /* Calculate delay in milliseconds (2-delays per complete flash) */
3592 flash_delay = 500 / appData.flashRate;
3594 /* calculate x and y coordinates from row and column */
3597 x = lineGap + ((BOARD_WIDTH-1)-column) *
3598 (squareSize + lineGap);
3599 y = lineGap + row * (squareSize + lineGap);
3603 x = lineGap + column * (squareSize + lineGap);
3604 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3605 (squareSize + lineGap);
3608 square_color = SquareColor(row, column);
3610 // [HGM] holdings: blank out area between board and holdings
3611 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3612 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3613 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3615 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3617 // [HGM] print piece counts next to holdings
3618 string[1] = NULLCHAR;
3621 cairo_text_extents_t extents;
3626 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3628 string[0] = '0' + piece;
3630 /* TODO this has to go into the font-selection */
3631 cairo_select_font_face (cr, "Sans",
3632 CAIRO_FONT_SLANT_NORMAL,
3633 CAIRO_FONT_WEIGHT_NORMAL);
3635 cairo_set_font_size (cr, 12.0);
3636 cairo_text_extents (cr, string, &extents);
3638 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3640 xpos= x + squareSize - extents.width - 2;
3641 ypos= y + extents.y_bearing + 1;
3643 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3646 ypos = y + extents.y_bearing + 1;
3649 /* TODO mono mode? */
3650 cairo_move_to (cr, xpos, ypos);
3651 cairo_text_path (cr, string);
3652 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3653 cairo_fill_preserve (cr);
3654 cairo_set_source_rgb (cr, 0, 0, 0);
3655 cairo_set_line_width (cr, 0.1);
3664 /* square on the board */
3665 if (piece == EmptySquare || appData.blindfold)
3667 BlankSquare(x, y, square_color, piece, xBoardWindow);
3671 if (do_flash && appData.flashCount > 0)
3673 for (i=0; i<appData.flashCount; ++i)
3676 DrawPiece(piece, square_color, x, y, xBoardWindow);
3677 do_flash_delay(flash_delay);
3679 BlankSquare(x, y, square_color, piece, xBoardWindow);
3680 do_flash_delay(flash_delay);
3683 DrawPiece(piece, square_color, x, y, xBoardWindow);
3687 /* show coordinates if necessary */
3688 if(appData.showCoords)
3690 cairo_text_extents_t extents;
3694 /* TODO this has to go into the font-selection */
3695 cairo_select_font_face (cr, "Sans",
3696 CAIRO_FONT_SLANT_NORMAL,
3697 CAIRO_FONT_WEIGHT_NORMAL);
3698 cairo_set_font_size (cr, 12.0);
3700 string[1] = NULLCHAR;
3703 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3705 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3706 column >= BOARD_LEFT && column < BOARD_RGHT)
3708 string[0] = 'a' + column - BOARD_LEFT;
3709 cairo_text_extents (cr, string, &extents);
3711 xpos = x + squareSize - extents.width - 2;
3712 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3714 if (appData.monoMode)
3721 cairo_move_to (cr, xpos, ypos);
3722 cairo_text_path (cr, string);
3723 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3724 cairo_fill_preserve (cr);
3725 cairo_set_source_rgb (cr, 0, 1.0, 0);
3726 cairo_set_line_width (cr, 0.1);
3729 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3732 string[0] = ONE + row;
3733 cairo_text_extents (cr, string, &extents);
3736 ypos = y + extents.height + 1;
3738 if (appData.monoMode)
3745 cairo_move_to (cr, xpos, ypos);
3746 cairo_text_path (cr, string);
3747 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3748 cairo_fill_preserve (cr);
3749 cairo_set_source_rgb (cr, 0, 0, 1.0);
3750 cairo_set_line_width (cr, 0.1);
3762 /* Returns 1 if there are "too many" differences between b1 and b2
3763 (i.e. more than 1 move was made) */
3764 static int too_many_diffs(b1, b2)
3770 for (i=0; i<BOARD_HEIGHT; ++i) {
3771 for (j=0; j<BOARD_WIDTH; ++j) {
3772 if (b1[i][j] != b2[i][j]) {
3773 if (++c > 4) /* Castling causes 4 diffs */
3782 /* Matrix describing castling maneuvers */
3783 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3784 static int castling_matrix[4][5] = {
3785 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3786 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3787 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3788 { 7, 7, 4, 5, 6 } /* 0-0, black */
3791 /* Checks whether castling occurred. If it did, *rrow and *rcol
3792 are set to the destination (row,col) of the rook that moved.
3794 Returns 1 if castling occurred, 0 if not.
3796 Note: Only handles a max of 1 castling move, so be sure
3797 to call too_many_diffs() first.
3799 static int check_castle_draw(newb, oldb, rrow, rcol)
3806 /* For each type of castling... */
3807 for (i=0; i<4; ++i) {
3808 r = castling_matrix[i];
3810 /* Check the 4 squares involved in the castling move */
3812 for (j=1; j<=4; ++j) {
3813 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3820 /* All 4 changed, so it must be a castling move */
3829 static int damage[BOARD_RANKS][BOARD_FILES];
3832 * event handler for redrawing the board
3834 void DrawPosition( repaint, board)
3835 /*Boolean*/int repaint;
3839 static int lastFlipView = 0;
3840 static int lastBoardValid = 0;
3841 static Board lastBoard;
3844 if (board == NULL) {
3845 if (!lastBoardValid) return;
3848 if (!lastBoardValid || lastFlipView != flipView) {
3849 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3850 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3855 * It would be simpler to clear the window with XClearWindow()
3856 * but this causes a very distracting flicker.
3859 if (!repaint && lastBoardValid && lastFlipView == flipView)
3861 /* If too much changes (begin observing new game, etc.), don't
3863 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3865 /* Special check for castling so we don't flash both the king
3866 and the rook (just flash the king). */
3869 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3871 /* Draw rook with NO flashing. King will be drawn flashing later */
3872 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3873 lastBoard[rrow][rcol] = board[rrow][rcol];
3877 /* First pass -- Draw (newly) empty squares and repair damage.
3878 This prevents you from having a piece show up twice while it
3879 is flashing on its new square */
3880 for (i = 0; i < BOARD_HEIGHT; i++)
3881 for (j = 0; j < BOARD_WIDTH; j++)
3882 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3885 DrawSquare(i, j, board[i][j], 0);
3886 damage[i][j] = False;
3889 /* Second pass -- Draw piece(s) in new position and flash them */
3890 for (i = 0; i < BOARD_HEIGHT; i++)
3891 for (j = 0; j < BOARD_WIDTH; j++)
3892 if (board[i][j] != lastBoard[i][j])
3894 DrawSquare(i, j, board[i][j], do_flash);
3906 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3908 cairo_set_line_width (cr, lineGap);
3910 /* TODO: use appdata colors */
3911 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3915 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3918 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3919 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3921 cairo_move_to (cr, x1, y1);
3922 cairo_rel_line_to (cr, x2,0);
3926 for (j = 0; j < BOARD_WIDTH + 1; j++)
3929 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3930 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3932 cairo_move_to (cr, x1, y1);
3933 cairo_rel_line_to (cr, 0, y2);
3942 for (i = 0; i < BOARD_HEIGHT; i++)
3943 for (j = 0; j < BOARD_WIDTH; j++)
3945 DrawSquare(i, j, board[i][j], 0);
3946 damage[i][j] = False;
3950 CopyBoard(lastBoard, board);
3952 lastFlipView = flipView;
3954 /* Draw highlights */
3955 if (pm1X >= 0 && pm1Y >= 0)
3957 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3959 if (pm2X >= 0 && pm2Y >= 0)
3961 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3963 if (hi1X >= 0 && hi1Y >= 0)
3965 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3967 if (hi2X >= 0 && hi2Y >= 0)
3969 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3972 /* If piece being dragged around board, must redraw that too */
3978 void AnimateUserMove (Widget w, XEvent * event,
3979 String * params, Cardinal * nParams)
3981 DragPieceMove(event->xmotion.x, event->xmotion.y);
3984 Widget CommentCreate(name, text, mutable, callback, lines)
3986 int /*Boolean*/ mutable;
3987 XtCallbackProc callback;
3991 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
3996 XtSetArg(args[j], XtNwidth, &bw_width); j++;
3997 XtGetValues(boardWidget, args, j);
4000 XtSetArg(args[j], XtNresizable, True); j++;
4003 XtCreatePopupShell(name, topLevelShellWidgetClass,
4004 shellWidget, args, j);
4007 XtCreatePopupShell(name, transientShellWidgetClass,
4008 shellWidget, args, j);
4011 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4012 layoutArgs, XtNumber(layoutArgs));
4014 XtCreateManagedWidget("form", formWidgetClass, layout,
4015 formArgs, XtNumber(formArgs));
4019 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4020 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4022 XtSetArg(args[j], XtNstring, text); j++;
4023 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4024 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4025 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4026 XtSetArg(args[j], XtNright, XtChainRight); j++;
4027 XtSetArg(args[j], XtNresizable, True); j++;
4028 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4029 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4030 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4031 XtSetArg(args[j], XtNautoFill, True); j++;
4032 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4034 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4038 XtSetArg(args[j], XtNfromVert, edit); j++;
4039 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4040 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4041 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4042 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4044 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4045 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4048 XtSetArg(args[j], XtNfromVert, edit); j++;
4049 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4050 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4051 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4052 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4053 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4055 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4056 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4059 XtSetArg(args[j], XtNfromVert, edit); j++;
4060 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4061 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4062 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4063 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4064 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4066 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4067 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4070 XtSetArg(args[j], XtNfromVert, edit); j++;
4071 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4072 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4073 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4074 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4076 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4077 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4080 XtSetArg(args[j], XtNfromVert, edit); j++;
4081 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4082 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4083 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4084 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4085 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4087 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4088 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4091 XtRealizeWidget(shell);
4093 if (commentX == -1) {
4096 Dimension pw_height;
4097 Dimension ew_height;
4100 XtSetArg(args[j], XtNheight, &ew_height); j++;
4101 XtGetValues(edit, args, j);
4104 XtSetArg(args[j], XtNheight, &pw_height); j++;
4105 XtGetValues(shell, args, j);
4106 commentH = pw_height + (lines - 1) * ew_height;
4107 commentW = bw_width - 16;
4109 XSync(xDisplay, False);
4111 /* This code seems to tickle an X bug if it is executed too soon
4112 after xboard starts up. The coordinates get transformed as if
4113 the main window was positioned at (0, 0).
4115 XtTranslateCoords(shellWidget,
4116 (bw_width - commentW) / 2, 0 - commentH / 2,
4117 &commentX, &commentY);
4119 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4120 RootWindowOfScreen(XtScreen(shellWidget)),
4121 (bw_width - commentW) / 2, 0 - commentH / 2,
4126 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4129 XtSetArg(args[j], XtNheight, commentH); j++;
4130 XtSetArg(args[j], XtNwidth, commentW); j++;
4131 XtSetArg(args[j], XtNx, commentX); j++;
4132 XtSetArg(args[j], XtNy, commentY); j++;
4133 XtSetValues(shell, args, j);
4134 XtSetKeyboardFocus(shell, edit);
4139 /* Used for analysis window and ICS input window */
4140 Widget MiscCreate(name, text, mutable, callback, lines)
4142 int /*Boolean*/ mutable;
4143 XtCallbackProc callback;
4147 Widget shell, layout, form, edit;
4149 Dimension bw_width, pw_height, ew_height, w, h;
4155 XtSetArg(args[j], XtNresizable, True); j++;
4158 XtCreatePopupShell(name, topLevelShellWidgetClass,
4159 shellWidget, args, j);
4162 XtCreatePopupShell(name, transientShellWidgetClass,
4163 shellWidget, args, j);
4166 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4167 layoutArgs, XtNumber(layoutArgs));
4169 XtCreateManagedWidget("form", formWidgetClass, layout,
4170 formArgs, XtNumber(formArgs));
4174 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4175 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4177 XtSetArg(args[j], XtNstring, text); j++;
4178 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4179 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4180 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4181 XtSetArg(args[j], XtNright, XtChainRight); j++;
4182 XtSetArg(args[j], XtNresizable, True); j++;
4183 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4184 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4185 XtSetArg(args[j], XtNautoFill, True); j++;
4186 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4188 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4190 XtRealizeWidget(shell);
4193 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4194 XtGetValues(boardWidget, args, j);
4197 XtSetArg(args[j], XtNheight, &ew_height); j++;
4198 XtGetValues(edit, args, j);
4201 XtSetArg(args[j], XtNheight, &pw_height); j++;
4202 XtGetValues(shell, args, j);
4203 h = pw_height + (lines - 1) * ew_height;
4206 XSync(xDisplay, False);
4208 /* This code seems to tickle an X bug if it is executed too soon
4209 after xboard starts up. The coordinates get transformed as if
4210 the main window was positioned at (0, 0).
4212 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4214 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4215 RootWindowOfScreen(XtScreen(shellWidget)),
4216 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4220 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4223 XtSetArg(args[j], XtNheight, h); j++;
4224 XtSetArg(args[j], XtNwidth, w); j++;
4225 XtSetArg(args[j], XtNx, x); j++;
4226 XtSetArg(args[j], XtNy, y); j++;
4227 XtSetValues(shell, args, j);
4233 static int savedIndex; /* gross that this is global */
4235 void EditCommentPopUp(index, title, text)
4244 if (text == NULL) text = "";
4246 if (editShell == NULL) {
4248 CommentCreate(title, text, True, EditCommentCallback, 4);
4249 XtRealizeWidget(editShell);
4250 CatchDeleteWindow(editShell, "EditCommentPopDown");
4252 edit = XtNameToWidget(editShell, "*form.text");
4254 XtSetArg(args[j], XtNstring, text); j++;
4255 XtSetValues(edit, args, j);
4257 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4258 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4259 XtSetValues(editShell, args, j);
4262 XtPopup(editShell, XtGrabNone);
4266 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4267 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4271 void EditCommentCallback(w, client_data, call_data)
4273 XtPointer client_data, call_data;
4281 XtSetArg(args[j], XtNlabel, &name); j++;
4282 XtGetValues(w, args, j);
4284 if (strcmp(name, _("ok")) == 0) {
4285 edit = XtNameToWidget(editShell, "*form.text");
4287 XtSetArg(args[j], XtNstring, &val); j++;
4288 XtGetValues(edit, args, j);
4289 ReplaceComment(savedIndex, val);
4290 EditCommentPopDown();
4291 } else if (strcmp(name, _("cancel")) == 0) {
4292 EditCommentPopDown();
4293 } else if (strcmp(name, _("clear")) == 0) {
4294 edit = XtNameToWidget(editShell, "*form.text");
4295 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4296 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4300 void EditCommentPopDown()
4305 if (!editUp) return;
4307 XtSetArg(args[j], XtNx, &commentX); j++;
4308 XtSetArg(args[j], XtNy, &commentY); j++;
4309 XtSetArg(args[j], XtNheight, &commentH); j++;
4310 XtSetArg(args[j], XtNwidth, &commentW); j++;
4311 XtGetValues(editShell, args, j);
4312 XtPopdown(editShell);
4315 XtSetArg(args[j], XtNleftBitmap, None); j++;
4316 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4320 void ICSInputBoxPopUp()
4325 char *title = _("ICS Input");
4328 if (ICSInputShell == NULL) {
4329 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4330 tr = XtParseTranslationTable(ICSInputTranslations);
4331 edit = XtNameToWidget(ICSInputShell, "*form.text");
4332 XtOverrideTranslations(edit, tr);
4333 XtRealizeWidget(ICSInputShell);
4334 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4337 edit = XtNameToWidget(ICSInputShell, "*form.text");
4339 XtSetArg(args[j], XtNstring, ""); j++;
4340 XtSetValues(edit, args, j);
4342 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4343 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4344 XtSetValues(ICSInputShell, args, j);
4347 XtPopup(ICSInputShell, XtGrabNone);
4348 XtSetKeyboardFocus(ICSInputShell, edit);
4350 ICSInputBoxUp = True;
4352 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4353 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4357 void ICSInputSendText()
4364 edit = XtNameToWidget(ICSInputShell, "*form.text");
4366 XtSetArg(args[j], XtNstring, &val); j++;
4367 XtGetValues(edit, args, j);
4368 SendMultiLineToICS(val);
4369 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4370 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4373 void ICSInputBoxPopDown()
4378 if (!ICSInputBoxUp) return;
4380 XtPopdown(ICSInputShell);
4381 ICSInputBoxUp = False;
4383 XtSetArg(args[j], XtNleftBitmap, None); j++;
4384 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4388 void CommentPopUp(title, text)
4395 if (commentShell == NULL) {
4397 CommentCreate(title, text, False, CommentCallback, 4);
4398 XtRealizeWidget(commentShell);
4399 CatchDeleteWindow(commentShell, "CommentPopDown");
4401 edit = XtNameToWidget(commentShell, "*form.text");
4403 XtSetArg(args[j], XtNstring, text); j++;
4404 XtSetValues(edit, args, j);
4406 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4407 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4408 XtSetValues(commentShell, args, j);
4411 XtPopup(commentShell, XtGrabNone);
4412 XSync(xDisplay, False);
4417 void CommentCallback(w, client_data, call_data)
4419 XtPointer client_data, call_data;
4426 XtSetArg(args[j], XtNlabel, &name); j++;
4427 XtGetValues(w, args, j);
4429 if (strcmp(name, _("close")) == 0) {
4431 } else if (strcmp(name, _("edit")) == 0) {
4438 void CommentPopDown()
4443 if (!commentUp) return;
4445 XtSetArg(args[j], XtNx, &commentX); j++;
4446 XtSetArg(args[j], XtNy, &commentY); j++;
4447 XtSetArg(args[j], XtNwidth, &commentW); j++;
4448 XtSetArg(args[j], XtNheight, &commentH); j++;
4449 XtGetValues(commentShell, args, j);
4450 XtPopdown(commentShell);
4451 XSync(xDisplay, False);
4455 void PromotionPopUp()
4458 Widget dialog, layout;
4460 Dimension bw_width, pw_width;
4464 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4465 XtGetValues(boardWidget, args, j);
4468 XtSetArg(args[j], XtNresizable, True); j++;
4469 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4471 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4472 shellWidget, args, j);
4474 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4475 layoutArgs, XtNumber(layoutArgs));
4478 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4479 XtSetArg(args[j], XtNborderWidth, 0); j++;
4480 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4483 if(gameInfo.variant != VariantShogi) {
4484 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4485 (XtPointer) dialog);
4486 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4487 (XtPointer) dialog);
4488 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4489 (XtPointer) dialog);
4490 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4491 (XtPointer) dialog);
4492 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4493 gameInfo.variant == VariantGiveaway) {
4494 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4495 (XtPointer) dialog);
4497 if(gameInfo.variant == VariantCapablanca ||
4498 gameInfo.variant == VariantGothic ||
4499 gameInfo.variant == VariantCapaRandom) {
4500 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4501 (XtPointer) dialog);
4502 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4503 (XtPointer) dialog);
4505 } else // [HGM] shogi
4507 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4508 (XtPointer) dialog);
4509 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4510 (XtPointer) dialog);
4512 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4513 (XtPointer) dialog);
4515 XtRealizeWidget(promotionShell);
4516 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4519 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4520 XtGetValues(promotionShell, args, j);
4522 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4523 lineGap + squareSize/3 +
4524 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4525 0 : 6*(squareSize + lineGap)), &x, &y);
4528 XtSetArg(args[j], XtNx, x); j++;
4529 XtSetArg(args[j], XtNy, y); j++;
4530 XtSetValues(promotionShell, args, j);
4532 XtPopup(promotionShell, XtGrabNone);
4537 void PromotionPopDown()
4539 if (!promotionUp) return;
4540 XtPopdown(promotionShell);
4541 XtDestroyWidget(promotionShell);
4542 promotionUp = False;
4545 void PromotionCallback(w, client_data, call_data)
4547 XtPointer client_data, call_data;
4553 XtSetArg(args[0], XtNlabel, &name);
4554 XtGetValues(w, args, 1);
4558 if (fromX == -1) return;
4560 if (strcmp(name, _("cancel")) == 0) {
4564 } else if (strcmp(name, _("Knight")) == 0) {
4566 } else if (strcmp(name, _("Promote")) == 0) {
4568 } else if (strcmp(name, _("Defer")) == 0) {
4571 promoChar = ToLower(name[0]);
4574 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
4576 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4577 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4582 void ErrorCallback(w, client_data, call_data)
4584 XtPointer client_data, call_data;
4587 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4589 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4595 if (!errorUp) return;
4599 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4601 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4606 void ErrorPopUp(title, label, modal)
4607 char *title, *label;
4610 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4611 GTK_DIALOG_DESTROY_WITH_PARENT,
4616 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4619 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4620 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4624 g_signal_connect_swapped (GUI_Error, "response",
4625 G_CALLBACK (ErrorPopDownProc),
4628 gtk_widget_show(GTK_WIDGET(GUI_Error));
4634 /* Disable all user input other than deleting the window */
4635 static int frozen = 0;
4639 /* Grab by a widget that doesn't accept input */
4640 // XtAddGrab(messageWidget, TRUE, FALSE);
4644 /* Undo a FreezeUI */
4647 if (!frozen) return;
4648 // XtRemoveGrab(messageWidget);
4652 char *ModeToWidgetName(mode)
4656 case BeginningOfGame:
4657 if (appData.icsActive)
4658 return "menuMode.ICS Client";
4659 else if (appData.noChessProgram ||
4660 *appData.cmailGameName != NULLCHAR)
4661 return "menuMode.Edit Game";
4663 return "menuMode.Machine Black";
4664 case MachinePlaysBlack:
4665 return "menuMode.Machine Black";
4666 case MachinePlaysWhite:
4667 return "menuMode.Machine White";
4669 return "menuMode.Analysis Mode";
4671 return "menuMode.Analyze File";
4672 case TwoMachinesPlay:
4673 return "menuMode.Two Machines";
4675 return "menuMode.Edit Game";
4676 case PlayFromGameFile:
4677 return "menuFile.Load Game";
4679 return "menuMode.Edit Position";
4681 return "menuMode.Training";
4682 case IcsPlayingWhite:
4683 case IcsPlayingBlack:
4687 return "menuMode.ICS Client";
4694 void ModeHighlight()
4696 static int oldPausing = FALSE;
4697 static GameMode oldmode = (GameMode) -1;
4700 // todo this toggling of the pause button doesn't seem to work?
4701 // e.g. select pause from buttonbar doesn't activate menumode.pause
4703 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4705 if (pausing != oldPausing) {
4706 oldPausing = pausing;
4707 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4708 /* toggle background color in showbuttonbar */
4709 if (appData.showButtonBar) {
4711 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4713 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4718 wname = ModeToWidgetName(oldmode);
4720 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4724 /* Maybe all the enables should be handled here, not just this one */
4725 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4726 gameMode == Training || gameMode == PlayFromGameFile);
4731 * Button/menu procedures
4734 int LoadGamePopUp(f, gameNumber, title)
4739 cmailMsgLoaded = FALSE;
4741 if (gameNumber == 0)
4743 int error = GameListBuild(f);
4747 DisplayError(_("Cannot build game list"), error);
4749 else if (!ListEmpty(&gameList)
4750 && ((ListGame *) gameList.tailPred)->number > 1)
4752 // TODO convert to GTK
4753 // GameListPopUp(f, title);
4761 return LoadGame(f, gameNumber, title, FALSE);
4764 void ReloadCmailMsgProc(w, event, prms, nprms)
4770 ReloadCmailMsgEvent(FALSE);
4773 void MailMoveProc(w, event, prms, nprms)
4782 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4783 static char *selected_fen_position=NULL;
4786 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4787 Atom *type_return, XtPointer *value_return,
4788 unsigned long *length_return, int *format_return)
4790 char *selection_tmp;
4792 if (!selected_fen_position) return False; /* should never happen */
4793 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4794 /* note: since no XtSelectionDoneProc was registered, Xt will
4795 * automatically call XtFree on the value returned. So have to
4796 * make a copy of it allocated with XtMalloc */
4797 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4798 strcpy(selection_tmp, selected_fen_position);
4800 *value_return=selection_tmp;
4801 *length_return=strlen(selection_tmp);
4802 *type_return=*target;
4803 *format_return = 8; /* bits per byte */
4805 } else if (*target == XA_TARGETS(xDisplay)) {
4806 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4807 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4808 targets_tmp[1] = XA_STRING;
4809 *value_return = targets_tmp;
4810 *type_return = XA_ATOM;
4812 *format_return = 8 * sizeof(Atom);
4813 if (*format_return > 32) {
4814 *length_return *= *format_return / 32;
4815 *format_return = 32;
4823 /* note: when called from menu all parameters are NULL, so no clue what the
4824 * Widget which was clicked on was, or what the click event was
4826 void CopyPositionProc(w, event, prms, nprms)
4833 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4834 * have a notion of a position that is selected but not copied.
4835 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4837 if (selected_fen_position) free(selected_fen_position);
4838 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
4839 if (!selected_fen_position) return;
4840 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4842 SendPositionSelection,
4843 NULL/* lose_ownership_proc */ ,
4844 NULL/* transfer_done_proc */);
4845 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4847 SendPositionSelection,
4848 NULL/* lose_ownership_proc */ ,
4849 NULL/* transfer_done_proc */);
4852 /* function called when the data to Paste is ready */
4854 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
4855 Atom *type, XtPointer value, unsigned long *len, int *format)
4858 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
4859 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
4860 EditPositionPasteFEN(fenstr);
4864 /* called when Paste Position button is pressed,
4865 * all parameters will be NULL */
4866 void PastePositionProc(w, event, prms, nprms)
4872 XtGetSelectionValue(menuBarWidget,
4873 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
4874 /* (XtSelectionCallbackProc) */ PastePositionCB,
4875 NULL, /* client_data passed to PastePositionCB */
4877 /* better to use the time field from the event that triggered the
4878 * call to this function, but that isn't trivial to get
4886 SendGameSelection(Widget w, Atom *selection, Atom *target,
4887 Atom *type_return, XtPointer *value_return,
4888 unsigned long *length_return, int *format_return)
4890 char *selection_tmp;
4892 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4893 FILE* f = fopen(gameCopyFilename, "r");
4896 if (f == NULL) return False;
4900 selection_tmp = XtMalloc(len + 1);
4901 count = fread(selection_tmp, 1, len, f);
4903 XtFree(selection_tmp);
4906 selection_tmp[len] = NULLCHAR;
4907 *value_return = selection_tmp;
4908 *length_return = len;
4909 *type_return = *target;
4910 *format_return = 8; /* bits per byte */
4912 } else if (*target == XA_TARGETS(xDisplay)) {
4913 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4914 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4915 targets_tmp[1] = XA_STRING;
4916 *value_return = targets_tmp;
4917 *type_return = XA_ATOM;
4919 *format_return = 8 * sizeof(Atom);
4920 if (*format_return > 32) {
4921 *length_return *= *format_return / 32;
4922 *format_return = 32;
4930 /* note: when called from menu all parameters are NULL, so no clue what the
4931 * Widget which was clicked on was, or what the click event was
4933 void CopyGameProc(w, event, prms, nprms)
4941 ret = SaveGameToFile(gameCopyFilename, FALSE);
4945 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4946 * have a notion of a game that is selected but not copied.
4947 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4949 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4952 NULL/* lose_ownership_proc */ ,
4953 NULL/* transfer_done_proc */);
4954 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4957 NULL/* lose_ownership_proc */ ,
4958 NULL/* transfer_done_proc */);
4961 /* function called when the data to Paste is ready */
4963 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
4964 Atom *type, XtPointer value, unsigned long *len, int *format)
4967 if (value == NULL || *len == 0) {
4968 return; /* nothing had been selected to copy */
4970 f = fopen(gamePasteFilename, "w");
4972 DisplayError(_("Can't open temp file"), errno);
4975 fwrite(value, 1, *len, f);
4978 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
4981 /* called when Paste Game button is pressed,
4982 * all parameters will be NULL */
4983 void PasteGameProc(w, event, prms, nprms)
4989 XtGetSelectionValue(menuBarWidget,
4990 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
4991 /* (XtSelectionCallbackProc) */ PasteGameCB,
4992 NULL, /* client_data passed to PasteGameCB */
4994 /* better to use the time field from the event that triggered the
4995 * call to this function, but that isn't trivial to get
5005 SaveGameProc(NULL, NULL);
5010 void EditCommentProc(w, event, prms, nprms)
5017 EditCommentPopDown();
5023 void IcsInputBoxProc(w, event, prms, nprms)
5029 if (ICSInputBoxUp) {
5030 ICSInputBoxPopDown();
5037 void EnterKeyProc(w, event, prms, nprms)
5043 if (ICSInputBoxUp == True)
5048 void DebugProc(w, event, prms, nprms)
5054 appData.debugMode = !appData.debugMode;
5057 void AboutGameProc(w, event, prms, nprms)
5066 void NothingProc(w, event, prms, nprms)
5075 void Iconify(w, event, prms, nprms)
5084 XtSetArg(args[0], XtNiconic, True);
5085 XtSetValues(shellWidget, args, 1);
5088 void DisplayMessage(message, extMessage)
5089 gchar *message, *extMessage;
5096 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5099 message = extMessage;
5102 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5107 void DisplayTitle(text)
5110 gchar title[MSG_SIZ];
5112 if (text == NULL) text = "";
5114 if (appData.titleInWindow)
5119 if (*text != NULLCHAR)
5121 strcpy(title, text);
5123 else if (appData.icsActive)
5125 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5127 else if (appData.cmailGameName[0] != NULLCHAR)
5129 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5131 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5133 else if (gameInfo.variant == VariantGothic)
5135 strcpy(title, GOTHIC);
5139 else if (gameInfo.variant == VariantFalcon)
5141 strcpy(title, FALCON);
5144 else if (appData.noChessProgram)
5146 strcpy(title, programName);
5150 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5152 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5158 void DisplayError(message, error)
5165 if (appData.debugMode || appData.matchMode) {
5166 fprintf(stderr, "%s: %s\n", programName, message);
5169 if (appData.debugMode || appData.matchMode) {
5170 fprintf(stderr, "%s: %s: %s\n",
5171 programName, message, strerror(error));
5173 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5176 ErrorPopUp(_("Error"), message, FALSE);
5180 void DisplayMoveError(message)
5185 DrawPosition(FALSE, NULL);
5186 if (appData.debugMode || appData.matchMode) {
5187 fprintf(stderr, "%s: %s\n", programName, message);
5189 if (appData.popupMoveErrors) {
5190 ErrorPopUp(_("Error"), message, FALSE);
5192 DisplayMessage(message, "");
5197 void DisplayFatalError(message, error, status)
5203 errorExitStatus = status;
5205 fprintf(stderr, "%s: %s\n", programName, message);
5207 fprintf(stderr, "%s: %s: %s\n",
5208 programName, message, strerror(error));
5209 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5212 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5213 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5219 void DisplayInformation(message)
5223 ErrorPopUp(_("Information"), message, TRUE);
5226 void DisplayNote(message)
5230 ErrorPopUp(_("Note"), message, FALSE);
5234 NullXErrorCheck(dpy, error_event)
5236 XErrorEvent *error_event;
5241 void DisplayIcsInteractionTitle(message)
5244 if (oldICSInteractionTitle == NULL) {
5245 /* Magic to find the old window title, adapted from vim */
5246 char *wina = getenv("WINDOWID");
5248 Window win = (Window) atoi(wina);
5249 Window root, parent, *children;
5250 unsigned int nchildren;
5251 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5253 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5254 if (!XQueryTree(xDisplay, win, &root, &parent,
5255 &children, &nchildren)) break;
5256 if (children) XFree((void *)children);
5257 if (parent == root || parent == 0) break;
5260 XSetErrorHandler(oldHandler);
5262 if (oldICSInteractionTitle == NULL) {
5263 oldICSInteractionTitle = "xterm";
5266 printf("\033]0;%s\007", message);
5270 char pendingReplyPrefix[MSG_SIZ];
5271 ProcRef pendingReplyPR;
5273 void AskQuestionProc(w, event, prms, nprms)
5280 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5284 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5287 void AskQuestionPopDown()
5289 if (!askQuestionUp) return;
5290 XtPopdown(askQuestionShell);
5291 XtDestroyWidget(askQuestionShell);
5292 askQuestionUp = False;
5295 void AskQuestionReplyAction(w, event, prms, nprms)
5305 reply = XawDialogGetValueString(w = XtParent(w));
5306 strcpy(buf, pendingReplyPrefix);
5307 if (*buf) strcat(buf, " ");
5310 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5311 AskQuestionPopDown();
5313 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5316 void AskQuestionCallback(w, client_data, call_data)
5318 XtPointer client_data, call_data;
5323 XtSetArg(args[0], XtNlabel, &name);
5324 XtGetValues(w, args, 1);
5326 if (strcmp(name, _("cancel")) == 0) {
5327 AskQuestionPopDown();
5329 AskQuestionReplyAction(w, NULL, NULL, NULL);
5333 void AskQuestion(title, question, replyPrefix, pr)
5334 char *title, *question, *replyPrefix;
5338 Widget popup, layout, dialog, edit;
5344 strcpy(pendingReplyPrefix, replyPrefix);
5345 pendingReplyPR = pr;
5348 XtSetArg(args[i], XtNresizable, True); i++;
5349 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5350 askQuestionShell = popup =
5351 XtCreatePopupShell(title, transientShellWidgetClass,
5352 shellWidget, args, i);
5355 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5356 layoutArgs, XtNumber(layoutArgs));
5359 XtSetArg(args[i], XtNlabel, question); i++;
5360 XtSetArg(args[i], XtNvalue, ""); i++;
5361 XtSetArg(args[i], XtNborderWidth, 0); i++;
5362 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5365 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5366 (XtPointer) dialog);
5367 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5368 (XtPointer) dialog);
5370 XtRealizeWidget(popup);
5371 CatchDeleteWindow(popup, "AskQuestionPopDown");
5373 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5374 &x, &y, &win_x, &win_y, &mask);
5376 XtSetArg(args[0], XtNx, x - 10);
5377 XtSetArg(args[1], XtNy, y - 30);
5378 XtSetValues(popup, args, 2);
5380 XtPopup(popup, XtGrabExclusive);
5381 askQuestionUp = True;
5383 edit = XtNameToWidget(dialog, "*value");
5384 XtSetKeyboardFocus(popup, edit);
5392 if (*name == NULLCHAR) {
5394 } else if (strcmp(name, "$") == 0) {
5395 putc(BELLCHAR, stderr);
5398 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
5406 PlaySound(appData.soundMove);
5412 PlaySound(appData.soundIcsWin);
5418 PlaySound(appData.soundIcsLoss);
5424 PlaySound(appData.soundIcsDraw);
5428 PlayIcsUnfinishedSound()
5430 PlaySound(appData.soundIcsUnfinished);
5436 PlaySound(appData.soundIcsAlarm);
5442 system("stty echo");
5448 system("stty -echo");
5452 Colorize(cc, continuation)
5457 int count, outCount, error;
5459 if (textColors[(int)cc].bg > 0) {
5460 if (textColors[(int)cc].fg > 0) {
5461 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
5462 textColors[(int)cc].fg, textColors[(int)cc].bg);
5464 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5465 textColors[(int)cc].bg);
5468 if (textColors[(int)cc].fg > 0) {
5469 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5470 textColors[(int)cc].fg);
5472 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
5475 count = strlen(buf);
5476 outCount = OutputToProcess(NoProc, buf, count, &error);
5477 if (outCount < count) {
5478 DisplayFatalError(_("Error writing to display"), error, 1);
5481 if (continuation) return;
5484 PlaySound(appData.soundShout);
5487 PlaySound(appData.soundSShout);
5490 PlaySound(appData.soundChannel1);
5493 PlaySound(appData.soundChannel);
5496 PlaySound(appData.soundKibitz);
5499 PlaySound(appData.soundTell);
5501 case ColorChallenge:
5502 PlaySound(appData.soundChallenge);
5505 PlaySound(appData.soundRequest);
5508 PlaySound(appData.soundSeek);
5519 return getpwuid(getuid())->pw_name;
5522 static char *ExpandPathName(path)
5525 static char static_buf[2000];
5526 char *d, *s, buf[2000];
5532 while (*s && isspace(*s))
5541 if (*(s+1) == '/') {
5542 strcpy(d, getpwuid(getuid())->pw_dir);
5547 *strchr(buf, '/') = 0;
5548 pwd = getpwnam(buf);
5551 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
5555 strcpy(d, pwd->pw_dir);
5556 strcat(d, strchr(s+1, '/'));
5567 static char host_name[MSG_SIZ];
5569 #if HAVE_GETHOSTNAME
5570 gethostname(host_name, MSG_SIZ);
5572 #else /* not HAVE_GETHOSTNAME */
5573 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
5574 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
5576 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5578 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5579 #endif /* not HAVE_GETHOSTNAME */
5582 guint delayedEventTimerTag = 0;
5583 DelayedEventCallback delayedEventCallback = 0;
5586 FireDelayedEvent(data)
5590 g_source_remove(delayedEventTimerTag);
5591 delayedEventTimerTag = 0;
5594 delayedEventCallback();
5600 ScheduleDelayedEvent(cb, millisec)
5601 DelayedEventCallback cb; guint millisec;
5603 if(delayedEventTimerTag && delayedEventCallback == cb)
5604 // [HGM] alive: replace, rather than add or flush identical event
5605 g_source_remove(delayedEventTimerTag);
5606 delayedEventCallback = cb;
5607 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
5611 DelayedEventCallback
5614 if (delayedEventTimerTag)
5616 return delayedEventCallback;
5625 CancelDelayedEvent()
5627 if (delayedEventTimerTag)
5629 g_source_remove(delayedEventTimerTag);
5630 delayedEventTimerTag = 0;
5636 guint loadGameTimerTag = 0;
5638 int LoadGameTimerRunning()
5640 return loadGameTimerTag != 0;
5643 int StopLoadGameTimer()
5645 if (loadGameTimerTag != 0) {
5646 g_source_remove(loadGameTimerTag);
5647 loadGameTimerTag = 0;
5655 LoadGameTimerCallback(data)
5659 g_source_remove(loadGameTimerTag);
5660 loadGameTimerTag = 0;
5667 StartLoadGameTimer(millisec)
5671 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
5675 guint analysisClockTag = 0;
5678 AnalysisClockCallback(data)
5681 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
5682 || appData.icsEngineAnalyze)
5684 AnalysisPeriodicEvent(0);
5685 return 1; /* keep on going */
5687 return 0; /* stop timer */
5691 StartAnalysisClock()
5694 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
5698 guint clockTimerTag = 0;
5700 int ClockTimerRunning()
5702 return clockTimerTag != 0;
5705 int StopClockTimer()
5707 if (clockTimerTag != 0)
5709 g_source_remove(clockTimerTag);
5720 ClockTimerCallback(data)
5724 g_source_remove(clockTimerTag);
5732 StartClockTimer(millisec)
5735 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
5740 DisplayTimerLabel(w, color, timer, highlight)
5749 if (appData.clockMode) {
5750 sprintf(buf, "%s: %s", color, TimeString(timer));
5752 sprintf(buf, "%s ", color);
5754 gtk_label_set_text(GTK_LABEL(w),buf);
5756 /* check for low time warning */
5757 // Pixel foregroundOrWarningColor = timerForegroundPixel;
5760 // appData.lowTimeWarning &&
5761 // (timer / 1000) < appData.icsAlarmTime)
5762 // foregroundOrWarningColor = lowTimeWarningColor;
5764 // if (appData.clockMode) {
5765 // sprintf(buf, "%s: %s", color, TimeString(timer));
5766 // XtSetArg(args[0], XtNlabel, buf);
5768 // sprintf(buf, "%s ", color);
5769 // XtSetArg(args[0], XtNlabel, buf);
5774 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
5775 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
5777 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
5778 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
5781 // XtSetValues(w, args, 3);
5786 DisplayWhiteClock(timeRemaining, highlight)
5790 if(appData.noGUI) return;
5792 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
5793 if (highlight && WindowIcon == BlackIcon)
5795 WindowIcon = WhiteIcon;
5796 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5801 DisplayBlackClock(timeRemaining, highlight)
5805 if(appData.noGUI) return;
5807 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
5808 if (highlight && WindowIcon == WhiteIcon)
5810 WindowIcon = BlackIcon;
5811 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5829 int StartChildProcess(cmdLine, dir, pr)
5836 int to_prog[2], from_prog[2];
5840 if (appData.debugMode) {
5841 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
5844 /* We do NOT feed the cmdLine to the shell; we just
5845 parse it into blank-separated arguments in the
5846 most simple-minded way possible.
5849 strcpy(buf, cmdLine);
5854 if (p == NULL) break;
5859 SetUpChildIO(to_prog, from_prog);
5861 if ((pid = fork()) == 0) {
5863 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
5864 close(to_prog[1]); // first close the unused pipe ends
5865 close(from_prog[0]);
5866 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
5867 dup2(from_prog[1], 1);
5868 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
5869 close(from_prog[1]); // and closing again loses one of the pipes!
5870 if(fileno(stderr) >= 2) // better safe than sorry...
5871 dup2(1, fileno(stderr)); /* force stderr to the pipe */
5873 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
5878 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
5880 execvp(argv[0], argv);
5882 /* If we get here, exec failed */
5887 /* Parent process */
5889 close(from_prog[1]);
5891 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
5894 cp->fdFrom = from_prog[0];
5895 cp->fdTo = to_prog[1];
5900 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
5901 static RETSIGTYPE AlarmCallBack(int n)
5907 DestroyChildProcess(pr, signalType)
5911 ChildProc *cp = (ChildProc *) pr;
5913 if (cp->kind != CPReal) return;
5915 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
5916 signal(SIGALRM, AlarmCallBack);
5918 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
5919 kill(cp->pid, SIGKILL); // kill it forcefully
5920 wait((int *) 0); // and wait again
5924 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
5926 /* Process is exiting either because of the kill or because of
5927 a quit command sent by the backend; either way, wait for it to die.
5936 InterruptChildProcess(pr)
5939 ChildProc *cp = (ChildProc *) pr;
5941 if (cp->kind != CPReal) return;
5942 (void) kill(cp->pid, SIGINT); /* stop it thinking */
5945 int OpenTelnet(host, port, pr)
5950 char cmdLine[MSG_SIZ];
5952 if (port[0] == NULLCHAR) {
5953 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
5955 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
5957 return StartChildProcess(cmdLine, "", pr);
5960 int OpenTCP(host, port, pr)
5966 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
5967 #else /* !OMIT_SOCKETS */
5969 struct sockaddr_in sa;
5971 unsigned short uport;
5974 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
5978 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
5979 sa.sin_family = AF_INET;
5980 sa.sin_addr.s_addr = INADDR_ANY;
5981 uport = (unsigned short) 0;
5982 sa.sin_port = htons(uport);
5983 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
5987 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
5988 if (!(hp = gethostbyname(host))) {
5990 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
5991 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
5992 hp->h_addrtype = AF_INET;
5994 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
5995 hp->h_addr_list[0] = (char *) malloc(4);
5996 hp->h_addr_list[0][0] = b0;
5997 hp->h_addr_list[0][1] = b1;
5998 hp->h_addr_list[0][2] = b2;
5999 hp->h_addr_list[0][3] = b3;
6004 sa.sin_family = hp->h_addrtype;
6005 uport = (unsigned short) atoi(port);
6006 sa.sin_port = htons(uport);
6007 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6009 if (connect(s, (struct sockaddr *) &sa,
6010 sizeof(struct sockaddr_in)) < 0) {
6014 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6021 #endif /* !OMIT_SOCKETS */
6026 int OpenCommPort(name, pr)
6033 fd = open(name, 2, 0);
6034 if (fd < 0) return errno;
6036 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6046 int OpenLoopback(pr)
6052 SetUpChildIO(to, from);
6054 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6057 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6064 int OpenRcmd(host, user, cmd, pr)
6065 char *host, *user, *cmd;
6068 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6072 #define INPUT_SOURCE_BUF_SIZE 8192
6081 char buf[INPUT_SOURCE_BUF_SIZE];
6086 DoInputCallback(io,cond,data)
6091 /* read input from one of the input source (for example a chess program, ICS, etc).
6092 * and call a function that will handle the input
6095 int count; /* how many bytes did we read */
6099 /* All information (callback function, file descriptor, etc) is
6100 * saved in an InputSource structure
6102 InputSource *is = (InputSource *) data;
6106 count = read(is->fd, is->unused,
6107 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6111 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6114 is->unused += count;
6116 /* break input into lines and call the callback function on each
6119 while (p < is->unused)
6121 q = memchr(p, '\n', is->unused - p);
6122 if (q == NULL) break;
6124 (is->func)(is, is->closure, p, q - p, 0);
6127 /* remember not yet used part of the buffer */
6129 while (p < is->unused)
6137 /* read maximum length of input buffer and send the whole buffer
6138 * to the callback function
6140 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6145 (is->func)(is, is->closure, is->buf, count, error);
6151 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6158 GIOChannel *channel;
6159 ChildProc *cp = (ChildProc *) pr;
6161 is = (InputSource *) calloc(1, sizeof(InputSource));
6162 is->lineByLine = lineByLine;
6166 is->fd = fileno(stdin);
6168 is->kind = cp->kind;
6169 is->fd = cp->fdFrom;
6172 is->unused = is->buf;
6176 // is->xid = XtAppAddInput(appContext, is->fd,
6177 // (XtPointer) (XtInputReadMask),
6178 // (XtInputCallbackProc) DoInputCallback,
6182 /* TODO: will this work on windows?*/
6183 printf("DEBUG: fd=%d %d\n",is->fd,is);
6185 channel = g_io_channel_unix_new(is->fd);
6186 g_io_channel_set_close_on_unref (channel, TRUE);
6187 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6188 is->closure = closure;
6189 return (InputSourceRef) is;
6193 RemoveInputSource(isr)
6196 InputSource *is = (InputSource *) isr;
6198 if (is->sid == 0) return;
6199 g_source_remove(is->sid);
6204 int OutputToProcess(pr, message, count, outError)
6210 static int line = 0;
6211 ChildProc *cp = (ChildProc *) pr;
6216 if (appData.noJoin || !appData.useInternalWrap)
6217 outCount = fwrite(message, 1, count, stdout);
6220 int width = get_term_width();
6221 int len = wrap(NULL, message, count, width, &line);
6222 char *msg = malloc(len);
6226 outCount = fwrite(message, 1, count, stdout);
6229 dbgchk = wrap(msg, message, count, width, &line);
6230 if (dbgchk != len && appData.debugMode)
6231 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
6232 outCount = fwrite(msg, 1, dbgchk, stdout);
6238 outCount = write(cp->fdTo, message, count);
6248 /* Output message to process, with "ms" milliseconds of delay
6249 between each character. This is needed when sending the logon
6250 script to ICC, which for some reason doesn't like the
6251 instantaneous send. */
6252 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6259 ChildProc *cp = (ChildProc *) pr;
6264 r = write(cp->fdTo, message++, 1);
6277 /**** Animation code by Hugh Fisher, DCS, ANU.
6279 Known problem: if a window overlapping the board is
6280 moved away while a piece is being animated underneath,
6281 the newly exposed area won't be updated properly.
6282 I can live with this.
6284 Known problem: if you look carefully at the animation
6285 of pieces in mono mode, they are being drawn as solid
6286 shapes without interior detail while moving. Fixing
6287 this would be a major complication for minimal return.
6290 /* Masks for XPM pieces. Black and white pieces can have
6291 different shapes, but in the interest of retaining my
6292 sanity pieces must have the same outline on both light
6293 and dark squares, and all pieces must use the same
6294 background square colors/images. */
6296 static int xpmDone = 0;
6299 CreateAnimMasks (pieceDepth)
6306 unsigned long plane;
6309 /* just return for gtk at the moment */
6312 /* Need a bitmap just to get a GC with right depth */
6313 buf = XCreatePixmap(xDisplay, xBoardWindow,
6315 values.foreground = 1;
6316 values.background = 0;
6317 /* Don't use XtGetGC, not read only */
6318 maskGC = XCreateGC(xDisplay, buf,
6319 GCForeground | GCBackground, &values);
6320 XFreePixmap(xDisplay, buf);
6322 buf = XCreatePixmap(xDisplay, xBoardWindow,
6323 squareSize, squareSize, pieceDepth);
6324 values.foreground = XBlackPixel(xDisplay, xScreen);
6325 values.background = XWhitePixel(xDisplay, xScreen);
6326 bufGC = XCreateGC(xDisplay, buf,
6327 GCForeground | GCBackground, &values);
6329 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6330 /* Begin with empty mask */
6331 if(!xpmDone) // [HGM] pieces: keep using existing
6332 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6333 squareSize, squareSize, 1);
6334 XSetFunction(xDisplay, maskGC, GXclear);
6335 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6336 0, 0, squareSize, squareSize);
6338 /* Take a copy of the piece */
6343 XSetFunction(xDisplay, bufGC, GXcopy);
6344 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6346 0, 0, squareSize, squareSize, 0, 0);
6348 /* XOR the background (light) over the piece */
6349 XSetFunction(xDisplay, bufGC, GXxor);
6351 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6352 0, 0, squareSize, squareSize, 0, 0);
6354 XSetForeground(xDisplay, bufGC, lightSquareColor);
6355 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6358 /* We now have an inverted piece image with the background
6359 erased. Construct mask by just selecting all the non-zero
6360 pixels - no need to reconstruct the original image. */
6361 XSetFunction(xDisplay, maskGC, GXor);
6363 /* Might be quicker to download an XImage and create bitmap
6364 data from it rather than this N copies per piece, but it
6365 only takes a fraction of a second and there is a much
6366 longer delay for loading the pieces. */
6367 for (n = 0; n < pieceDepth; n ++) {
6368 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6369 0, 0, squareSize, squareSize,
6375 XFreePixmap(xDisplay, buf);
6376 XFreeGC(xDisplay, bufGC);
6377 XFreeGC(xDisplay, maskGC);
6381 InitAnimState (anim, info)
6383 XWindowAttributes * info;
6388 /* Each buffer is square size, same depth as window */
6389 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6390 // squareSize, squareSize, info->depth);
6391 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6392 // squareSize, squareSize, info->depth);
6394 // /* Create a plain GC for blitting */
6395 // mask = GCForeground | GCBackground | GCFunction |
6396 // GCPlaneMask | GCGraphicsExposures;
6397 // values.foreground = XBlackPixel(xDisplay, xScreen);
6398 // values.background = XWhitePixel(xDisplay, xScreen);
6399 // values.function = GXcopy;
6400 // values.plane_mask = AllPlanes;
6401 // values.graphics_exposures = False;
6402 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
6404 // /* Piece will be copied from an existing context at
6405 // the start of each new animation/drag. */
6406 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
6408 // /* Outline will be a read-only copy of an existing */
6409 // anim->outlineGC = None;
6415 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
6416 XWindowAttributes info;
6418 /* for gtk at the moment just ... */
6421 if (xpmDone && gameInfo.variant == old) return;
6422 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
6423 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
6425 // InitAnimState(&game, &info);
6426 // InitAnimState(&player, &info);
6428 /* For XPM pieces, we need bitmaps to use as masks. */
6430 // CreateAnimMasks(info.depth);
6436 static Boolean frameWaiting;
6438 static RETSIGTYPE FrameAlarm (sig)
6441 frameWaiting = False;
6442 /* In case System-V style signals. Needed?? */
6443 signal(SIGALRM, FrameAlarm);
6450 struct itimerval delay;
6452 XSync(xDisplay, False);
6455 frameWaiting = True;
6456 signal(SIGALRM, FrameAlarm);
6457 delay.it_interval.tv_sec =
6458 delay.it_value.tv_sec = time / 1000;
6459 delay.it_interval.tv_usec =
6460 delay.it_value.tv_usec = (time % 1000) * 1000;
6461 setitimer(ITIMER_REAL, &delay, NULL);
6462 while (frameWaiting) pause();
6463 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
6464 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
6465 setitimer(ITIMER_REAL, &delay, NULL);
6475 // XSync(xDisplay, False);
6477 usleep(time * 1000);
6482 /* Convert board position to corner of screen rect and color */
6485 ScreenSquare(column, row, pt, color)
6486 int column; int row; XPoint * pt; int * color;
6489 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
6490 pt->y = lineGap + row * (squareSize + lineGap);
6492 pt->x = lineGap + column * (squareSize + lineGap);
6493 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
6495 *color = SquareColor(row, column);
6498 /* Convert window coords to square */
6501 BoardSquare(x, y, column, row)
6502 int x; int y; int * column; int * row;
6504 *column = EventToSquare(x, BOARD_WIDTH);
6505 if (flipView && *column >= 0)
6506 *column = BOARD_WIDTH - 1 - *column;
6507 *row = EventToSquare(y, BOARD_HEIGHT);
6508 if (!flipView && *row >= 0)
6509 *row = BOARD_HEIGHT - 1 - *row;
6514 #undef Max /* just in case */
6516 #define Max(a, b) ((a) > (b) ? (a) : (b))
6517 #define Min(a, b) ((a) < (b) ? (a) : (b))
6520 SetRect(rect, x, y, width, height)
6521 XRectangle * rect; int x; int y; int width; int height;
6525 rect->width = width;
6526 rect->height = height;
6529 /* Test if two frames overlap. If they do, return
6530 intersection rect within old and location of
6531 that rect within new. */
6534 Intersect(old, new, size, area, pt)
6535 XPoint * old; XPoint * new;
6536 int size; XRectangle * area; XPoint * pt;
6538 if (old->x > new->x + size || new->x > old->x + size ||
6539 old->y > new->y + size || new->y > old->y + size) {
6542 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
6543 size - abs(old->x - new->x), size - abs(old->y - new->y));
6544 pt->x = Max(old->x - new->x, 0);
6545 pt->y = Max(old->y - new->y, 0);
6550 /* For two overlapping frames, return the rect(s)
6551 in the old that do not intersect with the new. */
6554 CalcUpdateRects(old, new, size, update, nUpdates)
6555 XPoint * old; XPoint * new; int size;
6556 XRectangle update[]; int * nUpdates;
6560 /* If old = new (shouldn't happen) then nothing to draw */
6561 if (old->x == new->x && old->y == new->y) {
6565 /* Work out what bits overlap. Since we know the rects
6566 are the same size we don't need a full intersect calc. */
6568 /* Top or bottom edge? */
6569 if (new->y > old->y) {
6570 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
6572 } else if (old->y > new->y) {
6573 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
6574 size, old->y - new->y);
6577 /* Left or right edge - don't overlap any update calculated above. */
6578 if (new->x > old->x) {
6579 SetRect(&(update[count]), old->x, Max(new->y, old->y),
6580 new->x - old->x, size - abs(new->y - old->y));
6582 } else if (old->x > new->x) {
6583 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
6584 old->x - new->x, size - abs(new->y - old->y));
6591 /* Generate a series of frame coords from start->mid->finish.
6592 The movement rate doubles until the half way point is
6593 reached, then halves back down to the final destination,
6594 which gives a nice slow in/out effect. The algorithmn
6595 may seem to generate too many intermediates for short
6596 moves, but remember that the purpose is to attract the
6597 viewers attention to the piece about to be moved and
6598 then to where it ends up. Too few frames would be less
6602 Tween(start, mid, finish, factor, frames, nFrames)
6603 XPoint * start; XPoint * mid;
6604 XPoint * finish; int factor;
6605 XPoint frames[]; int * nFrames;
6607 int fraction, n, count;
6611 /* Slow in, stepping 1/16th, then 1/8th, ... */
6613 for (n = 0; n < factor; n++)
6615 for (n = 0; n < factor; n++) {
6616 frames[count].x = start->x + (mid->x - start->x) / fraction;
6617 frames[count].y = start->y + (mid->y - start->y) / fraction;
6619 fraction = fraction / 2;
6623 frames[count] = *mid;
6626 /* Slow out, stepping 1/2, then 1/4, ... */
6628 for (n = 0; n < factor; n++) {
6629 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
6630 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
6632 fraction = fraction * 2;
6637 /* Draw a piece on the screen without disturbing what's there */
6640 SelectGCMask(piece, clip, outline, mask)
6641 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
6645 /* Bitmap for piece being moved. */
6646 if (appData.monoMode) {
6647 *mask = *pieceToSolid(piece);
6648 } else if (useImages) {
6650 *mask = xpmMask[piece];
6652 *mask = ximMaskPm[piece];
6655 *mask = *pieceToSolid(piece);
6658 /* GC for piece being moved. Square color doesn't matter, but
6659 since it gets modified we make a copy of the original. */
6661 if (appData.monoMode)
6666 if (appData.monoMode)
6671 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
6673 /* Outline only used in mono mode and is not modified */
6675 *outline = bwPieceGC;
6677 *outline = wbPieceGC;
6681 OverlayPiece(piece, clip, outline, dest)
6682 ChessSquare piece; GC clip; GC outline; Drawable dest;
6687 /* Draw solid rectangle which will be clipped to shape of piece */
6688 // XFillRectangle(xDisplay, dest, clip,
6689 // 0, 0, squareSize, squareSize)
6691 if (appData.monoMode)
6692 /* Also draw outline in contrasting color for black
6693 on black / white on white cases */
6694 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
6695 // 0, 0, squareSize, squareSize, 0, 0, 1)
6698 /* Copy the piece */
6703 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
6705 // 0, 0, squareSize, squareSize,
6710 /* Animate the movement of a single piece */
6713 BeginAnimation(anim, piece, startColor, start)
6721 /* The old buffer is initialised with the start square (empty) */
6722 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
6723 anim->prevFrame = *start;
6725 /* The piece will be drawn using its own bitmap as a matte */
6726 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
6727 // XSetClipMask(xDisplay, anim->pieceGC, mask);
6731 AnimationFrame(anim, frame, piece)
6736 XRectangle updates[4];
6741 /* Save what we are about to draw into the new buffer */
6742 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
6743 // frame->x, frame->y, squareSize, squareSize,
6746 /* Erase bits of the previous frame */
6747 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
6748 /* Where the new frame overlapped the previous,
6749 the contents in newBuf are wrong. */
6750 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
6751 // overlap.x, overlap.y,
6752 // overlap.width, overlap.height,
6754 /* Repaint the areas in the old that don't overlap new */
6755 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
6756 for (i = 0; i < count; i++)
6757 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6758 // updates[i].x - anim->prevFrame.x,
6759 // updates[i].y - anim->prevFrame.y,
6760 // updates[i].width, updates[i].height,
6761 // updates[i].x, updates[i].y)
6764 /* Easy when no overlap */
6765 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6766 // 0, 0, squareSize, squareSize,
6767 // anim->prevFrame.x, anim->prevFrame.y);
6770 /* Save this frame for next time round */
6771 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
6772 // 0, 0, squareSize, squareSize,
6774 anim->prevFrame = *frame;
6776 /* Draw piece over original screen contents, not current,
6777 and copy entire rect. Wipes out overlapping piece images. */
6778 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
6779 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
6780 // 0, 0, squareSize, squareSize,
6781 // frame->x, frame->y);
6785 EndAnimation (anim, finish)
6789 XRectangle updates[4];
6794 /* The main code will redraw the final square, so we
6795 only need to erase the bits that don't overlap. */
6796 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
6797 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
6798 for (i = 0; i < count; i++)
6799 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6800 // updates[i].x - anim->prevFrame.x,
6801 // updates[i].y - anim->prevFrame.y,
6802 // updates[i].width, updates[i].height,
6803 // updates[i].x, updates[i].y)
6806 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6807 // 0, 0, squareSize, squareSize,
6808 // anim->prevFrame.x, anim->prevFrame.y);
6813 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
6815 ChessSquare piece; int startColor;
6816 XPoint * start; XPoint * finish;
6817 XPoint frames[]; int nFrames;
6821 BeginAnimation(anim, piece, startColor, start);
6822 for (n = 0; n < nFrames; n++) {
6823 AnimationFrame(anim, &(frames[n]), piece);
6824 FrameDelay(appData.animSpeed);
6826 EndAnimation(anim, finish);
6829 /* Main control logic for deciding what to animate and how */
6832 AnimateMove(board, fromX, fromY, toX, toY)
6841 XPoint start, finish, mid;
6842 XPoint frames[kFactor * 2 + 1];
6843 int nFrames, startColor, endColor;
6845 /* Are we animating? */
6846 if (!appData.animate || appData.blindfold)
6849 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
6850 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
6851 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
6853 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
6854 piece = board[fromY][fromX];
6855 if (piece >= EmptySquare) return;
6860 hop = (piece == WhiteKnight || piece == BlackKnight);
6863 if (appData.debugMode) {
6864 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
6865 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
6866 piece, fromX, fromY, toX, toY); }
6868 ScreenSquare(fromX, fromY, &start, &startColor);
6869 ScreenSquare(toX, toY, &finish, &endColor);
6872 /* Knight: make diagonal movement then straight */
6873 if (abs(toY - fromY) < abs(toX - fromX)) {
6874 mid.x = start.x + (finish.x - start.x) / 2;
6878 mid.y = start.y + (finish.y - start.y) / 2;
6881 mid.x = start.x + (finish.x - start.x) / 2;
6882 mid.y = start.y + (finish.y - start.y) / 2;
6885 /* Don't use as many frames for very short moves */
6886 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
6887 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
6889 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
6890 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
6892 /* Be sure end square is redrawn */
6893 damage[toY][toX] = True;
6897 DragPieceBegin(x, y)
6900 int boardX, boardY, color;
6903 /* Are we animating? */
6904 if (!appData.animateDragging || appData.blindfold)
6907 /* Figure out which square we start in and the
6908 mouse position relative to top left corner. */
6909 BoardSquare(x, y, &boardX, &boardY);
6910 player.startBoardX = boardX;
6911 player.startBoardY = boardY;
6912 ScreenSquare(boardX, boardY, &corner, &color);
6913 player.startSquare = corner;
6914 player.startColor = color;
6915 /* As soon as we start dragging, the piece will jump slightly to
6916 be centered over the mouse pointer. */
6917 player.mouseDelta.x = squareSize/2;
6918 player.mouseDelta.y = squareSize/2;
6919 /* Initialise animation */
6920 player.dragPiece = PieceForSquare(boardX, boardY);
6922 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
6923 player.dragActive = True;
6924 BeginAnimation(&player, player.dragPiece, color, &corner);
6925 /* Mark this square as needing to be redrawn. Note that
6926 we don't remove the piece though, since logically (ie
6927 as seen by opponent) the move hasn't been made yet. */
6928 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
6929 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
6930 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
6931 // corner.x, corner.y, squareSize, squareSize,
6932 // 0, 0); // [HGM] zh: unstack in stead of grab
6933 damage[boardY][boardX] = True;
6935 player.dragActive = False;
6945 /* Are we animating? */
6946 if (!appData.animateDragging || appData.blindfold)
6950 if (! player.dragActive)
6952 /* Move piece, maintaining same relative position
6953 of mouse within square */
6954 corner.x = x - player.mouseDelta.x;
6955 corner.y = y - player.mouseDelta.y;
6956 AnimationFrame(&player, &corner, player.dragPiece);
6958 if (appData.highlightDragging) {
6960 BoardSquare(x, y, &boardX, &boardY);
6961 SetHighlights(fromX, fromY, boardX, boardY);
6970 int boardX, boardY, color;
6973 /* Are we animating? */
6974 if (!appData.animateDragging || appData.blindfold)
6978 if (! player.dragActive)
6980 /* Last frame in sequence is square piece is
6981 placed on, which may not match mouse exactly. */
6982 BoardSquare(x, y, &boardX, &boardY);
6983 ScreenSquare(boardX, boardY, &corner, &color);
6984 EndAnimation(&player, &corner);
6986 /* Be sure end square is redrawn */
6987 damage[boardY][boardX] = True;
6989 /* This prevents weird things happening with fast successive
6990 clicks which on my Sun at least can cause motion events
6991 without corresponding press/release. */
6992 player.dragActive = False;
6995 /* Handle expose event while piece being dragged */
7000 if (!player.dragActive || appData.blindfold)
7003 /* What we're doing: logically, the move hasn't been made yet,
7004 so the piece is still in it's original square. But visually
7005 it's being dragged around the board. So we erase the square
7006 that the piece is on and draw it at the last known drag point. */
7007 BlankSquare(player.startSquare.x, player.startSquare.y,
7008 player.startColor, EmptySquare, xBoardWindow);
7009 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7010 damage[player.startBoardY][player.startBoardX] = TRUE;
7013 #include <sys/ioctl.h>
7014 int get_term_width()
7016 int fd, default_width;
7019 default_width = 79; // this is FICS default anyway...
7021 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7023 if (!ioctl(fd, TIOCGSIZE, &win))
7024 default_width = win.ts_cols;
7025 #elif defined(TIOCGWINSZ)
7027 if (!ioctl(fd, TIOCGWINSZ, &win))
7028 default_width = win.ws_col;
7030 return default_width;
7033 void update_ics_width()
7035 static int old_width = 0;
7036 int new_width = get_term_width();
7038 if (old_width != new_width)
7039 ics_printf("set width %d\n", new_width);
7040 old_width = new_width;
7043 void NotifyFrontendLogin()