2 * xboard.c -- X front end for XBoard
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009 Free Software Foundation, Inc.
10 * The following terms apply to Digital Equipment Corporation's copyright
12 * ------------------------------------------------------------------------
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 * ------------------------------------------------------------------------
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
58 #include <sys/types.h>
63 # if HAVE_SYS_SOCKET_H
64 # include <sys/socket.h>
65 # include <netinet/in.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 # if HAVE_LAN_SOCKET_H
69 # include <lan/socket.h>
71 # include <lan/netdb.h>
72 # else /* not HAVE_LAN_SOCKET_H */
73 # define OMIT_SOCKETS 1
74 # endif /* not HAVE_LAN_SOCKET_H */
75 # endif /* not HAVE_SYS_SOCKET_H */
76 #endif /* !OMIT_SOCKETS */
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
85 # else /* not HAVE_STRING_H */
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
107 # include <sys/time.h>
118 # include <sys/wait.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
129 # include <sys/ndir.h>
130 # define HAVE_DIR_STRUCT
133 # include <sys/dir.h>
134 # define HAVE_DIR_STRUCT
138 # define HAVE_DIR_STRUCT
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
147 #include <X11/Xmu/Atoms.h>
149 #include <X11/Xaw3d/Dialog.h>
150 #include <X11/Xaw3d/Form.h>
151 #include <X11/Xaw3d/List.h>
152 #include <X11/Xaw3d/Label.h>
153 #include <X11/Xaw3d/SimpleMenu.h>
154 #include <X11/Xaw3d/SmeBSB.h>
155 #include <X11/Xaw3d/SmeLine.h>
156 #include <X11/Xaw3d/Box.h>
157 #include <X11/Xaw3d/MenuButton.h>
158 #include <X11/Xaw3d/Text.h>
159 #include <X11/Xaw3d/AsciiText.h>
161 #include <X11/Xaw/Dialog.h>
162 #include <X11/Xaw/Form.h>
163 #include <X11/Xaw/List.h>
164 #include <X11/Xaw/Label.h>
165 #include <X11/Xaw/SimpleMenu.h>
166 #include <X11/Xaw/SmeBSB.h>
167 #include <X11/Xaw/SmeLine.h>
168 #include <X11/Xaw/Box.h>
169 #include <X11/Xaw/MenuButton.h>
170 #include <X11/Xaw/Text.h>
171 #include <X11/Xaw/AsciiText.h>
174 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
179 #include "pixmaps/pixmaps.h"
180 #define IMAGE_EXT "xpm"
182 #define IMAGE_EXT "xim"
183 #include "bitmaps/bitmaps.h"
188 #include <gdk-pixbuf/gdk-pixbuf.h>
190 #include "bitmaps/icon_white.bm"
191 #include "bitmaps/icon_black.bm"
192 #include "bitmaps/checkmark.bm"
194 #include "frontend.h"
199 #include "xgamelist.h"
200 #include "xhistory.h"
201 #include "xedittags.h"
203 #include "callback.h"
204 #include "interface.h"
206 // must be moved to xengineoutput.h
208 void EngineOutputProc P((Widget w, XEvent *event,
209 String *prms, Cardinal *nprms));
211 void EngineOutputPopDown();
218 #define usleep(t) _sleep2(((t)+500)/1000)
222 # define _(s) gettext (s)
223 # define N_(s) gettext_noop (s)
246 int main P((int argc, char **argv));
247 RETSIGTYPE CmailSigHandler P((int sig));
248 RETSIGTYPE IntSigHandler P((int sig));
249 RETSIGTYPE TermSizeSigHandler P((int sig));
250 void CreateGCs P((void));
251 void CreateXIMPieces P((void));
252 void CreateXPMPieces P((void));
253 void CreatePieces P((void));
254 void CreatePieceMenus P((void));
255 Widget CreateMenuBar P((Menu *mb));
256 char *FindFont P((char *pattern, int targetPxlSize));
257 void PieceMenuPopup P((Widget w, XEvent *event,
258 String *params, Cardinal *num_params));
259 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
260 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
261 int EventToSquare P((int x, int limit));
262 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
263 void AnimateUserMove P((Widget w, XEvent * event,
264 String * params, Cardinal * nParams));
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268 XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void AskQuestionReplyAction P((Widget w, XEvent *event,
272 String *prms, Cardinal *nprms));
273 void AskQuestionProc P((Widget w, XEvent *event,
274 String *prms, Cardinal *nprms));
275 void AskQuestionPopDown P((void));
276 void PromotionPopDown P((void));
277 void PromotionCallback P((Widget w, XtPointer client_data,
278 XtPointer call_data));
279 void EditCommentPopDown P((void));
280 void EditCommentCallback P((Widget w, XtPointer client_data,
281 XtPointer call_data));
282 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
283 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
285 void PastePositionProc P((Widget w, XEvent *event, String *prms,
287 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
288 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
289 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
290 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
292 void AnalyzeModeProc P((Widget w, XEvent *event,
293 String *prms, Cardinal *nprms));
294 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
295 void EditPositionProc P((Widget w, XEvent *event,
296 String *prms, Cardinal *nprms));
297 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
298 void EditCommentProc P((Widget w, XEvent *event,
299 String *prms, Cardinal *nprms));
300 void IcsInputBoxProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
304 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
307 void DisplayMove P((int moveNumber));
308 void DisplayTitle P((char *title));
309 void ICSInitScript P((void));
310 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
311 void ErrorPopUp P((char *title, char *text, int modal));
312 void ErrorPopDown P((void));
313 static char *ExpandPathName P((char *path));
314 static void CreateAnimVars P((void));
315 static void DragPieceMove P((int x, int y));
316 static void DrawDragPiece P((void));
317 char *ModeToWidgetName P((GameMode mode));
318 void EngineOutputUpdate( FrontEndProgramStats * stats );
319 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
322 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void ShufflePopDown P(());
327 void EnginePopDown P(());
328 void UciPopDown P(());
329 void TimeControlPopDown P(());
330 void NewVariantPopDown P(());
331 void SettingsPopDown P(());
332 void SetMenuEnables P((Enables *enab));
333 void update_ics_width P(());
334 int get_term_width P(());
336 * XBoard depends on Xt R4 or higher
338 int xtVersion = XtSpecificationRelease;
343 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
344 jailSquareColor, highlightSquareColor, premoveHighlightColor;
345 Pixel lowTimeWarningColor;
347 #define LINE_TYPE_NORMAL 0
348 #define LINE_TYPE_HIGHLIGHT 1
349 #define LINE_TYPE_PRE 2
352 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
353 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
354 wjPieceGC, bjPieceGC;
355 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
356 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
357 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
358 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
359 menuBarWidget, editShell, errorShell, analysisShell,
360 ICSInputShell, fileNameShell, askQuestionShell;
361 Font clockFontID, coordFontID, countFontID;
362 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
363 XtAppContext appContext;
365 char *oldICSInteractionTitle;
369 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
371 Position commentX = -1, commentY = -1;
372 Dimension commentW, commentH;
374 int squareSize, smallLayout = 0, tinyLayout = 0,
375 marginW, marginH, // [HGM] for run-time resizing
376 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
377 ICSInputBoxUp = False, askQuestionUp = False,
378 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
379 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
380 Pixel timerForegroundPixel, timerBackgroundPixel;
381 Pixel buttonForegroundPixel, buttonBackgroundPixel;
382 char *chessDir, *programName, *programVersion,
383 *gameCopyFilename, *gamePasteFilename;
387 Pixmap pieceBitmap[2][(int)BlackPawn];
388 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
389 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
390 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
391 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
392 int useImages=0, useImageSqs;
393 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
394 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
395 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
396 XImage *ximLightSquare, *ximDarkSquare;
399 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
400 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
402 #define White(piece) ((int)(piece) < (int)BlackPawn)
404 /* Variables for doing smooth animation. This whole thing
405 would be much easier if the board was double-buffered,
406 but that would require a fairly major rewrite. */
411 GC blitGC, pieceGC, outlineGC;
412 XPoint startSquare, prevFrame, mouseDelta;
416 int startBoardX, startBoardY;
419 /* There can be two pieces being animated at once: a player
420 can begin dragging a piece before the remote opponent has moved. */
422 static AnimState game, player;
424 /* Bitmaps for use as masks when drawing XPM pieces.
425 Need one for each black and white piece. */
426 static Pixmap xpmMask[BlackKing + 1];
428 /* This magic number is the number of intermediate frames used
429 in each half of the animation. For short moves it's reduced
430 by 1. The total number of frames will be factor * 2 + 1. */
433 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
435 Enables icsEnables[] = {
436 { "menuFile.Mail Move", False },
437 { "menuFile.Reload CMail Message", False },
438 { "menuMode.Machine Black", False },
439 { "menuMode.Machine White", False },
440 { "menuMode.Analysis Mode", False },
441 { "menuMode.Analyze File", False },
442 { "menuMode.Two Machines", False },
444 { "menuHelp.Hint", False },
445 { "menuHelp.Book", False },
446 { "menuStep.Move Now", False },
447 { "menuOptions.Periodic Updates", False },
448 { "menuOptions.Hide Thinking", False },
449 { "menuOptions.Ponder Next Move", False },
454 Enables ncpEnables[] = {
455 { "menuFile.Mail Move", False },
456 { "menuFile.Reload CMail Message", False },
457 { "menuMode.Machine White", False },
458 { "menuMode.Machine Black", False },
459 { "menuMode.Analysis Mode", False },
460 { "menuMode.Analyze File", False },
461 { "menuMode.Two Machines", False },
462 { "menuMode.ICS Client", False },
463 { "menuMode.ICS Input Box", False },
465 { "menuStep.Revert", False },
466 { "menuStep.Move Now", False },
467 { "menuStep.Retract Move", False },
468 { "menuOptions.Auto Comment", False },
469 { "menuOptions.Auto Flag", False },
470 { "menuOptions.Auto Flip View", False },
471 { "menuOptions.Auto Observe", False },
472 { "menuOptions.Auto Raise Board", False },
473 { "menuOptions.Get Move List", False },
474 { "menuOptions.ICS Alarm", False },
475 { "menuOptions.Move Sound", False },
476 { "menuOptions.Quiet Play", False },
477 { "menuOptions.Hide Thinking", False },
478 { "menuOptions.Periodic Updates", False },
479 { "menuOptions.Ponder Next Move", False },
480 { "menuHelp.Hint", False },
481 { "menuHelp.Book", False },
485 Enables gnuEnables[] = {
486 { "menuMode.ICS Client", False },
487 { "menuMode.ICS Input Box", False },
488 { "menuAction.Accept", False },
489 { "menuAction.Decline", False },
490 { "menuAction.Rematch", False },
491 { "menuAction.Adjourn", False },
492 { "menuAction.Stop Examining", False },
493 { "menuAction.Stop Observing", False },
494 { "menuStep.Revert", False },
495 { "menuOptions.Auto Comment", False },
496 { "menuOptions.Auto Observe", False },
497 { "menuOptions.Auto Raise Board", False },
498 { "menuOptions.Get Move List", False },
499 { "menuOptions.Premove", False },
500 { "menuOptions.Quiet Play", False },
502 /* The next two options rely on SetCmailMode being called *after* */
503 /* SetGNUMode so that when GNU is being used to give hints these */
504 /* menu options are still available */
506 { "menuFile.Mail Move", False },
507 { "menuFile.Reload CMail Message", False },
511 Enables cmailEnables[] = {
513 { "menuAction.Call Flag", False },
514 { "menuAction.Draw", True },
515 { "menuAction.Adjourn", False },
516 { "menuAction.Abort", False },
517 { "menuAction.Stop Observing", False },
518 { "menuAction.Stop Examining", False },
519 { "menuFile.Mail Move", True },
520 { "menuFile.Reload CMail Message", True },
524 Enables trainingOnEnables[] = {
525 { "menuMode.Edit Comment", False },
526 { "menuMode.Pause", False },
527 { "menuStep.Forward", False },
528 { "menuStep.Backward", False },
529 { "menuStep.Forward to End", False },
530 { "menuStep.Back to Start", False },
531 { "menuStep.Move Now", False },
532 { "menuStep.Truncate Game", False },
536 Enables trainingOffEnables[] = {
537 { "menuMode.Edit Comment", True },
538 { "menuMode.Pause", True },
539 { "menuStep.Forward", True },
540 { "menuStep.Backward", True },
541 { "menuStep.Forward to End", True },
542 { "menuStep.Back to Start", True },
543 { "menuStep.Move Now", True },
544 { "menuStep.Truncate Game", True },
548 Enables machineThinkingEnables[] = {
549 { "menuFile.Load Game", False },
550 { "menuFile.Load Next Game", False },
551 { "menuFile.Load Previous Game", False },
552 { "menuFile.Reload Same Game", False },
553 { "menuFile.Paste Game", False },
554 { "menuFile.Load Position", False },
555 { "menuFile.Load Next Position", False },
556 { "menuFile.Load Previous Position", False },
557 { "menuFile.Reload Same Position", False },
558 { "menuFile.Paste Position", False },
559 { "menuMode.Machine White", False },
560 { "menuMode.Machine Black", False },
561 { "menuMode.Two Machines", False },
562 { "menuStep.Retract Move", False },
566 Enables userThinkingEnables[] = {
567 { "menuFile.Load Game", True },
568 { "menuFile.Load Next Game", True },
569 { "menuFile.Load Previous Game", True },
570 { "menuFile.Reload Same Game", True },
571 { "menuFile.Paste Game", True },
572 { "menuFile.Load Position", True },
573 { "menuFile.Load Next Position", True },
574 { "menuFile.Load Previous Position", True },
575 { "menuFile.Reload Same Position", True },
576 { "menuFile.Paste Position", True },
577 { "menuMode.Machine White", True },
578 { "menuMode.Machine Black", True },
579 { "menuMode.Two Machines", True },
580 { "menuStep.Retract Move", True },
586 MenuItem fileMenu[] = {
587 {N_("New Shuffle Game ..."), ShuffleMenuProc},
588 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
589 // {"----", NothingProc},
590 // {N_("Save Game"), SaveGameProc},
591 // {"----", NothingProc},
592 {N_("Copy Game"), CopyGameProc},
593 {N_("Paste Game"), PasteGameProc},
594 // {"----", NothingProc},
595 // {N_("Load Position"), LoadPositionProc},
596 // {N_("Load Next Position"), LoadNextPositionProc},
597 // {N_("Load Previous Position"), LoadPrevPositionProc},
598 // {N_("Reload Same Position"), ReloadPositionProc},
599 // {N_("Save Position"), SavePositionProc},
600 // {"----", NothingProc},
601 {N_("Copy Position"), CopyPositionProc},
602 {N_("Paste Position"), PastePositionProc},
603 // {"----", NothingProc},
604 {N_("Mail Move"), MailMoveProc},
605 {N_("Reload CMail Message"), ReloadCmailMsgProc},
606 // {"----", NothingProc},
610 MenuItem modeMenu[] = {
611 // {N_("Machine White"), MachineWhiteProc},
612 // {N_("Machine Black"), MachineBlackProc},
613 // {N_("Two Machines"), TwoMachinesProc},
614 {N_("Analysis Mode"), AnalyzeModeProc},
615 // {N_("Analyze File"), AnalyzeFileProc },
616 // {N_("ICS Client"), IcsClientProc},
617 {N_("Edit Game"), EditGameProc},
618 {N_("Edit Position"), EditPositionProc},
619 {N_("Training"), TrainingProc},
620 {"----", NothingProc},
621 {N_("Show Engine Output"), EngineOutputProc},
622 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
623 {N_("Show Game List"), ShowGameListProc},
624 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
625 {"----", NothingProc},
626 // {N_("Edit Tags"), EditTagsProc},
627 {N_("Edit Comment"), EditCommentProc},
628 {N_("ICS Input Box"), IcsInputBoxProc},
632 MenuItem optionsMenu[] = {
633 // {N_("Flip View"), FlipViewProc},
634 // {"----", NothingProc},
635 {N_("Adjudications ..."), EngineMenuProc},
636 {N_("General Settings ..."), UciMenuProc},
637 {N_("Engine #1 Settings ..."), FirstSettingsProc},
638 {N_("Engine #2 Settings ..."), SecondSettingsProc},
639 {N_("Time Control ..."), TimeControlProc},
640 {"----", NothingProc},
641 // {N_("Always Queen"), AlwaysQueenProc},
642 // {N_("Animate Dragging"), AnimateDraggingProc},
643 // {N_("Animate Moving"), AnimateMovingProc},
644 // {N_("Auto Comment"), AutocommProc},
645 // {N_("Auto Flag"), AutoflagProc},
646 // {N_("Auto Flip View"), AutoflipProc},
647 // {N_("Auto Observe"), AutobsProc},
648 // {N_("Auto Raise Board"), AutoraiseProc},
649 // {N_("Auto Save"), AutosaveProc},
650 // {N_("Blindfold"), BlindfoldProc},
651 // {N_("Flash Moves"), FlashMovesProc},
652 // {N_("Get Move List"), GetMoveListProc},
654 // {N_("Highlight Dragging"), HighlightDraggingProc},
656 // {N_("Highlight Last Move"), HighlightLastMoveProc},
657 // {N_("Move Sound"), MoveSoundProc},
658 // {N_("ICS Alarm"), IcsAlarmProc},
659 // {N_("Old Save Style"), OldSaveStyleProc},
660 // {N_("Periodic Updates"), PeriodicUpdatesProc},
661 // {N_("Ponder Next Move"), PonderNextMoveProc},
662 // {N_("Popup Exit Message"), PopupExitMessageProc},
663 // {N_("Popup Move Errors"), PopupMoveErrorsProc},
664 // {N_("Premove"), PremoveProc},
665 // {N_("Quiet Play"), QuietPlayProc},
666 // {N_("Hide Thinking"), HideThinkingProc},
667 // {N_("Test Legality"), TestLegalityProc},
672 {N_("File"), fileMenu},
673 {N_("Mode"), modeMenu},
674 {N_("Options"), optionsMenu},
678 #define PIECE_MENU_SIZE 18
679 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
680 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
681 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
682 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
683 N_("Empty square"), N_("Clear board") },
684 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
685 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
686 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
687 N_("Empty square"), N_("Clear board") }
689 /* must be in same order as PieceMenuStrings! */
690 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
691 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
692 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
693 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
694 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
695 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
696 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
697 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
698 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
701 #define DROP_MENU_SIZE 6
702 String dropMenuStrings[DROP_MENU_SIZE] = {
703 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
705 /* must be in same order as PieceMenuStrings! */
706 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
707 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
708 WhiteRook, WhiteQueen
716 DropMenuEnables dmEnables[] = {
725 { XtNborderWidth, 0 },
726 { XtNdefaultDistance, 0 },
730 { XtNborderWidth, 0 },
731 { XtNresizable, (XtArgVal) True },
735 { XtNborderWidth, 0 },
740 XtResource clientResources[] = {
741 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
742 XtOffset(AppDataPtr, whitePieceColor), XtRString,
744 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
745 XtOffset(AppDataPtr, blackPieceColor), XtRString,
747 { "lightSquareColor", "lightSquareColor", XtRString,
748 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
749 XtRString, LIGHT_SQUARE_COLOR },
750 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
751 XtOffset(AppDataPtr, darkSquareColor), XtRString,
753 { "highlightSquareColor", "highlightSquareColor", XtRString,
754 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
755 XtRString, HIGHLIGHT_SQUARE_COLOR },
756 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
757 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
758 XtRString, PREMOVE_HIGHLIGHT_COLOR },
759 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
760 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
761 (XtPointer) MOVES_PER_SESSION },
762 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
763 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
764 (XtPointer) TIME_INCREMENT },
765 { "initString", "initString", XtRString, sizeof(String),
766 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
767 { "secondInitString", "secondInitString", XtRString, sizeof(String),
768 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
769 { "firstComputerString", "firstComputerString", XtRString,
770 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
772 { "secondComputerString", "secondComputerString", XtRString,
773 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
775 { "firstChessProgram", "firstChessProgram", XtRString,
776 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
777 XtRString, FIRST_CHESS_PROGRAM },
778 { "secondChessProgram", "secondChessProgram", XtRString,
779 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
780 XtRString, SECOND_CHESS_PROGRAM },
781 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
782 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
783 XtRImmediate, (XtPointer) False },
784 { "noChessProgram", "noChessProgram", XtRBoolean,
785 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
786 XtRImmediate, (XtPointer) False },
787 { "firstHost", "firstHost", XtRString, sizeof(String),
788 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
789 { "secondHost", "secondHost", XtRString, sizeof(String),
790 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
791 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
792 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
793 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
794 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
795 { "bitmapDirectory", "bitmapDirectory", XtRString,
796 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
798 { "remoteShell", "remoteShell", XtRString, sizeof(String),
799 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
800 { "remoteUser", "remoteUser", XtRString, sizeof(String),
801 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
802 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
803 XtOffset(AppDataPtr, timeDelay), XtRString,
804 (XtPointer) TIME_DELAY_QUOTE },
805 { "timeControl", "timeControl", XtRString, sizeof(String),
806 XtOffset(AppDataPtr, timeControl), XtRString,
807 (XtPointer) TIME_CONTROL },
808 { "internetChessServerMode", "internetChessServerMode",
809 XtRBoolean, sizeof(Boolean),
810 XtOffset(AppDataPtr, icsActive), XtRImmediate,
812 { "internetChessServerHost", "internetChessServerHost",
813 XtRString, sizeof(String),
814 XtOffset(AppDataPtr, icsHost),
815 XtRString, (XtPointer) ICS_HOST },
816 { "internetChessServerPort", "internetChessServerPort",
817 XtRString, sizeof(String),
818 XtOffset(AppDataPtr, icsPort), XtRString,
819 (XtPointer) ICS_PORT },
820 { "internetChessServerCommPort", "internetChessServerCommPort",
821 XtRString, sizeof(String),
822 XtOffset(AppDataPtr, icsCommPort), XtRString,
824 { "internetChessServerLogonScript", "internetChessServerLogonScript",
825 XtRString, sizeof(String),
826 XtOffset(AppDataPtr, icsLogon), XtRString,
828 { "internetChessServerHelper", "internetChessServerHelper",
829 XtRString, sizeof(String),
830 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
831 { "internetChessServerInputBox", "internetChessServerInputBox",
832 XtRBoolean, sizeof(Boolean),
833 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
835 { "icsAlarm", "icsAlarm",
836 XtRBoolean, sizeof(Boolean),
837 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
839 { "icsAlarmTime", "icsAlarmTime",
841 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
843 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
844 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
846 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
847 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
848 { "gateway", "gateway", XtRString, sizeof(String),
849 XtOffset(AppDataPtr, gateway), XtRString, "" },
850 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
852 { "loadGameIndex", "loadGameIndex",
854 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
856 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
857 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
858 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
860 XtRImmediate, (XtPointer) True },
861 { "autoSaveGames", "autoSaveGames", XtRBoolean,
862 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
863 XtRImmediate, (XtPointer) False },
864 { "blindfold", "blindfold", XtRBoolean,
865 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
866 XtRImmediate, (XtPointer) False },
867 { "loadPositionFile", "loadPositionFile", XtRString,
868 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
870 { "loadPositionIndex", "loadPositionIndex",
872 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
874 { "savePositionFile", "savePositionFile", XtRString,
875 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
877 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
878 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
879 { "matchGames", "matchGames", XtRInt, sizeof(int),
880 XtOffset(AppDataPtr, matchGames), XtRImmediate,
882 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
883 XtOffset(AppDataPtr, monoMode), XtRImmediate,
885 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, debugMode), XtRImmediate,
888 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
889 XtOffset(AppDataPtr, clockMode), XtRImmediate,
891 { "boardSize", "boardSize", XtRString, sizeof(String),
892 XtOffset(AppDataPtr, boardSize), XtRString, "" },
893 { "searchTime", "searchTime", XtRString, sizeof(String),
894 XtOffset(AppDataPtr, searchTime), XtRString,
896 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
897 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
899 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
900 XtOffset(AppDataPtr, showCoords), XtRImmediate,
902 { "showJail", "showJail", XtRInt, sizeof(int),
903 XtOffset(AppDataPtr, showJail), XtRImmediate,
905 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
906 XtOffset(AppDataPtr, showThinking), XtRImmediate,
908 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
909 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
911 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
912 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
914 { "clockFont", "clockFont", XtRString, sizeof(String),
915 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
916 { "coordFont", "coordFont", XtRString, sizeof(String),
917 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
918 { "font", "font", XtRString, sizeof(String),
919 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
920 { "ringBellAfterMoves", "ringBellAfterMoves",
921 XtRBoolean, sizeof(Boolean),
922 XtOffset(AppDataPtr, ringBellAfterMoves),
923 XtRImmediate, (XtPointer) False },
924 { "autoCallFlag", "autoCallFlag", XtRBoolean,
925 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
926 XtRImmediate, (XtPointer) False },
927 { "autoFlipView", "autoFlipView", XtRBoolean,
928 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
929 XtRImmediate, (XtPointer) True },
930 { "autoObserve", "autoObserve", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
932 XtRImmediate, (XtPointer) False },
933 { "autoComment", "autoComment", XtRBoolean,
934 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
935 XtRImmediate, (XtPointer) False },
936 { "getMoveList", "getMoveList", XtRBoolean,
937 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
938 XtRImmediate, (XtPointer) True },
940 { "highlightDragging", "highlightDragging", XtRBoolean,
941 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
942 XtRImmediate, (XtPointer) False },
944 { "highlightLastMove", "highlightLastMove", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
946 XtRImmediate, (XtPointer) False },
947 { "premove", "premove", XtRBoolean,
948 sizeof(Boolean), XtOffset(AppDataPtr, premove),
949 XtRImmediate, (XtPointer) True },
950 { "testLegality", "testLegality", XtRBoolean,
951 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
952 XtRImmediate, (XtPointer) True },
953 { "flipView", "flipView", XtRBoolean,
954 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
955 XtRImmediate, (XtPointer) False },
956 { "cmail", "cmailGameName", XtRString, sizeof(String),
957 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
958 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
960 XtRImmediate, (XtPointer) False },
961 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
963 XtRImmediate, (XtPointer) False },
964 { "quietPlay", "quietPlay", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
966 XtRImmediate, (XtPointer) False },
967 { "titleInWindow", "titleInWindow", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
969 XtRImmediate, (XtPointer) False },
970 { "localLineEditing", "localLineEditing", XtRBoolean,
971 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
972 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
974 { "zippyTalk", "zippyTalk", XtRBoolean,
975 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
976 XtRImmediate, (XtPointer) ZIPPY_TALK },
977 { "zippyPlay", "zippyPlay", XtRBoolean,
978 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
979 XtRImmediate, (XtPointer) ZIPPY_PLAY },
980 { "zippyLines", "zippyLines", XtRString, sizeof(String),
981 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
982 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
983 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
984 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
985 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
986 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
987 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
988 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
990 ZIPPY_WRONG_PASSWORD },
991 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
992 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
993 { "zippyUseI", "zippyUseI", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
995 XtRImmediate, (XtPointer) ZIPPY_USE_I },
996 { "zippyBughouse", "zippyBughouse", XtRInt,
997 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
998 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
999 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1001 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1002 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1003 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1004 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1005 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1006 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1008 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1009 { "zippyAbort", "zippyAbort", XtRBoolean,
1010 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1011 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1012 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1013 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1014 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1015 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1016 (XtPointer) ZIPPY_MAX_GAMES },
1017 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1018 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1019 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1020 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1021 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1024 { "flashCount", "flashCount", XtRInt, sizeof(int),
1025 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1026 (XtPointer) FLASH_COUNT },
1027 { "flashRate", "flashRate", XtRInt, sizeof(int),
1028 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1029 (XtPointer) FLASH_RATE },
1030 { "pixmapDirectory", "pixmapDirectory", XtRString,
1031 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1033 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1034 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1035 (XtPointer) MS_LOGIN_DELAY },
1036 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1037 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1038 XtRImmediate, (XtPointer) False },
1039 { "colorShout", "colorShout", XtRString,
1040 sizeof(String), XtOffset(AppDataPtr, colorShout),
1041 XtRString, COLOR_SHOUT },
1042 { "colorSShout", "colorSShout", XtRString,
1043 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1044 XtRString, COLOR_SSHOUT },
1045 { "colorChannel1", "colorChannel1", XtRString,
1046 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1047 XtRString, COLOR_CHANNEL1 },
1048 { "colorChannel", "colorChannel", XtRString,
1049 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1050 XtRString, COLOR_CHANNEL },
1051 { "colorKibitz", "colorKibitz", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1053 XtRString, COLOR_KIBITZ },
1054 { "colorTell", "colorTell", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorTell),
1056 XtRString, COLOR_TELL },
1057 { "colorChallenge", "colorChallenge", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1059 XtRString, COLOR_CHALLENGE },
1060 { "colorRequest", "colorRequest", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1062 XtRString, COLOR_REQUEST },
1063 { "colorSeek", "colorSeek", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1065 XtRString, COLOR_SEEK },
1066 { "colorNormal", "colorNormal", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1068 XtRString, COLOR_NORMAL },
1069 { "soundProgram", "soundProgram", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1071 XtRString, "play" },
1072 { "soundShout", "soundShout", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, soundShout),
1075 { "soundSShout", "soundSShout", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1078 { "soundChannel1", "soundChannel1", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1081 { "soundChannel", "soundChannel", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1084 { "soundKibitz", "soundKibitz", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1087 { "soundTell", "soundTell", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundTell),
1090 { "soundChallenge", "soundChallenge", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1093 { "soundRequest", "soundRequest", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1096 { "soundSeek", "soundSeek", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1099 { "soundMove", "soundMove", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundMove),
1102 { "soundIcsWin", "soundIcsWin", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1105 { "soundIcsLoss", "soundIcsLoss", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1108 { "soundIcsDraw", "soundIcsDraw", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1111 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1112 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1114 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1115 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1117 { "reuseFirst", "reuseFirst", XtRBoolean,
1118 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1119 XtRImmediate, (XtPointer) True },
1120 { "reuseSecond", "reuseSecond", XtRBoolean,
1121 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1122 XtRImmediate, (XtPointer) True },
1123 { "animateDragging", "animateDragging", XtRBoolean,
1124 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1125 XtRImmediate, (XtPointer) True },
1126 { "animateMoving", "animateMoving", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1128 XtRImmediate, (XtPointer) True },
1129 { "animateSpeed", "animateSpeed", XtRInt,
1130 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1131 XtRImmediate, (XtPointer)10 },
1132 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1133 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1134 XtRImmediate, (XtPointer) True },
1135 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1136 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1137 XtRImmediate, (XtPointer) False },
1138 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1139 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1140 XtRImmediate, (XtPointer)4 },
1141 { "initialMode", "initialMode", XtRString,
1142 sizeof(String), XtOffset(AppDataPtr, initialMode),
1143 XtRImmediate, (XtPointer) "" },
1144 { "variant", "variant", XtRString,
1145 sizeof(String), XtOffset(AppDataPtr, variant),
1146 XtRImmediate, (XtPointer) "normal" },
1147 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1148 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1149 XtRImmediate, (XtPointer)PROTOVER },
1150 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1151 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1152 XtRImmediate, (XtPointer)PROTOVER },
1153 { "showButtonBar", "showButtonBar", XtRBoolean,
1154 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1155 XtRImmediate, (XtPointer) True },
1156 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1157 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1158 XtRString, COLOR_LOWTIMEWARNING },
1159 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1160 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1161 XtRImmediate, (XtPointer) False },
1162 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1163 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1164 XtRImmediate, (XtPointer) False },
1165 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1166 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1167 XtRImmediate, (XtPointer) False },
1168 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1169 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1170 XtRImmediate, (XtPointer) False },
1171 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1172 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1173 XtRImmediate, (XtPointer) False },
1174 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1175 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1176 XtRImmediate, (XtPointer) True },
1177 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1178 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1179 XtRImmediate, (XtPointer) 0},
1180 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1181 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1182 XtRImmediate, (XtPointer) 0},
1183 { "pgnEventHeader", "pgnEventHeader", XtRString,
1184 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1185 XtRImmediate, (XtPointer) "Computer Chess Game" },
1186 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1187 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1188 XtRImmediate, (XtPointer) -1},
1189 { "gameListTags", "gameListTags", XtRString,
1190 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1191 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1193 // [HGM] 4.3.xx options
1194 { "boardWidth", "boardWidth", XtRInt,
1195 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1196 XtRImmediate, (XtPointer) -1},
1197 { "boardHeight", "boardHeight", XtRInt,
1198 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1199 XtRImmediate, (XtPointer) -1},
1200 { "matchPause", "matchPause", XtRInt,
1201 sizeof(int), XtOffset(AppDataPtr, matchPause),
1202 XtRImmediate, (XtPointer) 10000},
1203 { "holdingsSize", "holdingsSize", XtRInt,
1204 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1205 XtRImmediate, (XtPointer) -1},
1206 { "flipBlack", "flipBlack", XtRBoolean,
1207 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1208 XtRImmediate, (XtPointer) False},
1209 { "allWhite", "allWhite", XtRBoolean,
1210 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1211 XtRImmediate, (XtPointer) False},
1212 { "pieceToCharTable", "pieceToCharTable", XtRString,
1213 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1214 XtRImmediate, (XtPointer) 0},
1215 { "alphaRank", "alphaRank", XtRBoolean,
1216 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1217 XtRImmediate, (XtPointer) False},
1218 { "testClaims", "testClaims", XtRBoolean,
1219 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1220 XtRImmediate, (XtPointer) True},
1221 { "checkMates", "checkMates", XtRBoolean,
1222 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1223 XtRImmediate, (XtPointer) True},
1224 { "materialDraws", "materialDraws", XtRBoolean,
1225 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1226 XtRImmediate, (XtPointer) True},
1227 { "trivialDraws", "trivialDraws", XtRBoolean,
1228 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1229 XtRImmediate, (XtPointer) False},
1230 { "ruleMoves", "ruleMoves", XtRInt,
1231 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1232 XtRImmediate, (XtPointer) 51},
1233 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1234 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1235 XtRImmediate, (XtPointer) 6},
1236 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1237 sizeof(int), XtOffset(AppDataPtr, engineComments),
1238 XtRImmediate, (XtPointer) 1},
1239 { "userName", "userName", XtRString,
1240 sizeof(int), XtOffset(AppDataPtr, userName),
1241 XtRImmediate, (XtPointer) 0},
1242 { "autoKibitz", "autoKibitz", XtRBoolean,
1243 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1244 XtRImmediate, (XtPointer) False},
1245 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1246 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1247 XtRImmediate, (XtPointer) 1},
1248 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1249 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1250 XtRImmediate, (XtPointer) 1},
1251 { "timeOddsMode", "timeOddsMode", XtRInt,
1252 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1253 XtRImmediate, (XtPointer) 0},
1254 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1255 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1256 XtRImmediate, (XtPointer) 1},
1257 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1258 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1259 XtRImmediate, (XtPointer) 1},
1260 { "firstNPS", "firstNPS", XtRInt,
1261 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1262 XtRImmediate, (XtPointer) -1},
1263 { "secondNPS", "secondNPS", XtRInt,
1264 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1265 XtRImmediate, (XtPointer) -1},
1266 { "serverMoves", "serverMoves", XtRString,
1267 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1268 XtRImmediate, (XtPointer) 0},
1269 { "serverPause", "serverPause", XtRInt,
1270 sizeof(int), XtOffset(AppDataPtr, serverPause),
1271 XtRImmediate, (XtPointer) 0},
1272 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1273 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1274 XtRImmediate, (XtPointer) False},
1275 { "userName", "userName", XtRString,
1276 sizeof(String), XtOffset(AppDataPtr, userName),
1277 XtRImmediate, (XtPointer) 0},
1278 { "egtFormats", "egtFormats", XtRString,
1279 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1280 XtRImmediate, (XtPointer) 0},
1281 { "rewindIndex", "rewindIndex", XtRInt,
1282 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1283 XtRImmediate, (XtPointer) 0},
1284 { "sameColorGames", "sameColorGames", XtRInt,
1285 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1286 XtRImmediate, (XtPointer) 0},
1287 { "smpCores", "smpCores", XtRInt,
1288 sizeof(int), XtOffset(AppDataPtr, smpCores),
1289 XtRImmediate, (XtPointer) 1},
1290 { "niceEngines", "niceEngines", XtRInt,
1291 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1292 XtRImmediate, (XtPointer) 0},
1293 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1294 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1295 XtRImmediate, (XtPointer) "xboard.debug"},
1296 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1297 sizeof(int), XtOffset(AppDataPtr, engineComments),
1298 XtRImmediate, (XtPointer) 1},
1299 { "noGUI", "noGUI", XtRBoolean,
1300 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1301 XtRImmediate, (XtPointer) 0},
1302 { "firstOptions", "firstOptions", XtRString,
1303 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1304 XtRImmediate, (XtPointer) "" },
1305 { "secondOptions", "secondOptions", XtRString,
1306 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1307 XtRImmediate, (XtPointer) "" },
1308 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1309 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1310 XtRImmediate, (XtPointer) 0 },
1311 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1312 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1313 XtRImmediate, (XtPointer) 0 },
1315 // [HGM] Winboard_x UCI options
1316 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1317 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1318 XtRImmediate, (XtPointer) False},
1319 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1320 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1321 XtRImmediate, (XtPointer) False},
1322 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1323 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1324 XtRImmediate, (XtPointer) True},
1325 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1326 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1327 XtRImmediate, (XtPointer) True},
1328 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1329 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1330 XtRImmediate, (XtPointer) False},
1331 { "defaultHashSize", "defaultHashSize", XtRInt,
1332 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1333 XtRImmediate, (XtPointer) 64},
1334 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1335 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1336 XtRImmediate, (XtPointer) 4},
1337 { "polyglotDir", "polyglotDir", XtRString,
1338 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1339 XtRImmediate, (XtPointer) "." },
1340 { "polyglotBook", "polyglotBook", XtRString,
1341 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1342 XtRImmediate, (XtPointer) "" },
1343 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1344 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1345 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1346 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1347 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1348 XtRImmediate, (XtPointer) 0},
1349 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1350 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1351 XtRImmediate, (XtPointer) 0},
1352 { "keepAlive", "keepAlive", XtRInt,
1353 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1354 XtRImmediate, (XtPointer) 0},
1355 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1356 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1357 XtRImmediate, (XtPointer) False},
1358 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1359 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1360 XtRImmediate, (XtPointer) False},
1361 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1362 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1364 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1365 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1366 XtRImmediate, (XtPointer) True},
1367 { "autoDisplayTags", "autoDisplayTags", XtRBoolean,
1368 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayTags),
1369 XtRImmediate, (XtPointer) True},
1370 { "autoDisplayComment", "autoDisplayComment", XtRBoolean,
1371 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayComment),
1372 XtRImmediate, (XtPointer) True},
1373 { "pasteSelection", "pasteSelection", XtRBoolean,
1374 sizeof(Boolean), XtOffset(AppDataPtr, pasteSelection),
1375 XtRImmediate, (XtPointer) False},
1378 XrmOptionDescRec shellOptions[] = {
1379 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1380 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1381 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1382 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1383 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1384 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1385 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1386 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1387 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1388 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1389 { "-initString", "initString", XrmoptionSepArg, NULL },
1390 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1391 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1392 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1393 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1394 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1395 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1396 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1397 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1398 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1399 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1400 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1401 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1402 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1403 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1404 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1405 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1406 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1407 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1408 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1409 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1410 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1411 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1412 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1413 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1414 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1415 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1416 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1417 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1418 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1419 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1420 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1421 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1422 { "-internetChessServerMode", "internetChessServerMode",
1423 XrmoptionSepArg, NULL },
1424 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1425 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1426 { "-internetChessServerHost", "internetChessServerHost",
1427 XrmoptionSepArg, NULL },
1428 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1429 { "-internetChessServerPort", "internetChessServerPort",
1430 XrmoptionSepArg, NULL },
1431 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1432 { "-internetChessServerCommPort", "internetChessServerCommPort",
1433 XrmoptionSepArg, NULL },
1434 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1435 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1436 XrmoptionSepArg, NULL },
1437 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1438 { "-internetChessServerHelper", "internetChessServerHelper",
1439 XrmoptionSepArg, NULL },
1440 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1441 { "-internetChessServerInputBox", "internetChessServerInputBox",
1442 XrmoptionSepArg, NULL },
1443 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1444 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1445 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1446 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1447 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1448 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1449 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1450 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1451 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1452 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1453 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1454 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1455 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1456 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1457 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1458 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1459 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1460 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1461 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1462 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1463 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1464 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1465 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1466 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1467 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1468 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1469 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1470 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1471 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1472 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1473 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1474 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1475 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1476 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1477 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1478 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1479 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1480 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1481 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1482 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1483 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1484 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1485 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1486 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1487 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1488 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1489 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1490 { "-size", "boardSize", XrmoptionSepArg, NULL },
1491 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1492 { "-st", "searchTime", XrmoptionSepArg, NULL },
1493 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1494 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1495 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1496 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1497 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1499 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1500 { "-jail", "showJail", XrmoptionNoArg, "1" },
1501 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1502 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1504 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1505 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1506 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1507 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1508 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1509 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1510 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1511 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1512 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1513 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1514 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1515 { "-font", "font", XrmoptionSepArg, NULL },
1516 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1517 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1518 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1519 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1520 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1521 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1522 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1523 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1524 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1525 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1526 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1527 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1528 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1529 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1530 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1531 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1532 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1533 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1534 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1535 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1537 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1538 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1539 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1541 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1542 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1543 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1544 { "-premove", "premove", XrmoptionSepArg, NULL },
1545 { "-pre", "premove", XrmoptionNoArg, "True" },
1546 { "-xpre", "premove", XrmoptionNoArg, "False" },
1547 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1548 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1549 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1550 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1551 { "-flip", "flipView", XrmoptionNoArg, "True" },
1552 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1553 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1554 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1555 XrmoptionSepArg, NULL },
1556 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1557 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1558 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1559 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1560 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1561 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1562 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1563 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1564 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1565 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1566 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1568 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1569 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1570 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1571 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1572 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1573 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1574 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1575 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1576 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1577 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1578 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1579 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1580 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1581 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1582 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1583 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1584 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1585 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1586 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1587 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1588 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1589 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1590 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1591 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1592 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1593 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1594 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1595 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1596 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1597 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1598 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1600 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1601 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1602 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1603 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1604 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1605 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1606 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1607 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1608 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1609 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1610 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1611 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1612 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1613 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1614 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1615 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1616 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1617 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1618 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1619 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1620 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1621 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1622 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1623 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1624 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1625 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1626 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1627 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1628 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1629 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1630 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1631 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1632 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1633 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1634 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1635 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1636 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1637 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1638 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1639 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1640 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1641 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1642 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1643 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1644 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1645 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1646 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1647 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1648 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1649 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1650 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1651 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1652 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1653 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1654 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1655 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1656 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1657 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1658 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1659 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1660 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1661 { "-variant", "variant", XrmoptionSepArg, NULL },
1662 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1663 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1664 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1665 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1666 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1667 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1668 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1669 /* [AS,HR] New features */
1670 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1671 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1672 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1673 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1674 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1675 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1676 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1677 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1678 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1679 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1680 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1681 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1682 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1683 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1684 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1685 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1686 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1687 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1688 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1689 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1690 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1691 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1692 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1693 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1694 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1695 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1697 /* [HGM,HR] User-selectable board size */
1698 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1699 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1700 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1702 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1703 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1704 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1705 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1706 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1707 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1708 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1709 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1710 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1711 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1712 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1713 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1714 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1715 { "-userName", "userName", XrmoptionSepArg, NULL },
1716 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1717 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1718 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1719 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1720 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1721 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1722 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1723 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1724 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1725 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1726 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1727 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1728 { "-userName", "userName", XrmoptionSepArg, NULL },
1729 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1730 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1731 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1732 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1733 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1734 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1735 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1736 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1737 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1738 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1739 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1740 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1741 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1742 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1743 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1744 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1745 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1746 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1747 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1748 { "-autoDisplayTags", "autoDisplayTags", XrmoptionSepArg, NULL },
1749 { "-autoDisplayComment", "autoDisplayComment", XrmoptionSepArg, NULL },
1750 { "-pasteSelection", "pasteSelection", XrmoptionSepArg, NULL },
1753 XtActionsRec boardActions[] = {
1754 // { "HandleUserMove", HandleUserMove },
1755 { "AnimateUserMove", AnimateUserMove },
1756 // { "FileNameAction", FileNameAction },
1757 { "AskQuestionProc", AskQuestionProc },
1758 { "AskQuestionReplyAction", AskQuestionReplyAction },
1759 { "PieceMenuPopup", PieceMenuPopup },
1760 // { "WhiteClock", WhiteClock },
1761 // { "BlackClock", BlackClock },
1762 { "Iconify", Iconify },
1763 { "LoadSelectedProc", LoadSelectedProc },
1764 // { "LoadPositionProc", LoadPositionProc },
1765 // { "LoadNextPositionProc", LoadNextPositionProc },
1766 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1767 // { "ReloadPositionProc", ReloadPositionProc },
1768 { "CopyPositionProc", CopyPositionProc },
1769 { "PastePositionProc", PastePositionProc },
1770 { "CopyGameProc", CopyGameProc },
1771 { "PasteGameProc", PasteGameProc },
1772 // { "SaveGameProc", SaveGameProc },
1773 // { "SavePositionProc", SavePositionProc },
1774 { "MailMoveProc", MailMoveProc },
1775 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1776 // { "MachineWhiteProc", MachineWhiteProc },
1777 // { "MachineBlackProc", MachineBlackProc },
1778 { "AnalysisModeProc", AnalyzeModeProc },
1779 // { "AnalyzeFileProc", AnalyzeFileProc },
1780 // { "TwoMachinesProc", TwoMachinesProc },
1781 // { "IcsClientProc", IcsClientProc },
1782 { "EditGameProc", EditGameProc },
1783 { "EditPositionProc", EditPositionProc },
1784 { "TrainingProc", EditPositionProc },
1785 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1786 { "ShowGameListProc", ShowGameListProc },
1787 // { "ShowMoveListProc", HistoryShowProc},
1788 // { "EditTagsProc", EditCommentProc },
1789 { "EditCommentProc", EditCommentProc },
1790 // { "IcsAlarmProc", IcsAlarmProc },
1791 { "IcsInputBoxProc", IcsInputBoxProc },
1792 // { "AcceptProc", AcceptProc },
1793 // { "DeclineProc", DeclineProc },
1794 // { "RematchProc", RematchProc },
1795 // { "CallFlagProc", CallFlagProc },
1796 // { "DrawProc", DrawProc },
1797 // { "AdjournProc", AdjournProc },
1798 // { "AbortProc", AbortProc },
1799 // { "ResignProc", ResignProc },
1800 // { "AdjuWhiteProc", AdjuWhiteProc },
1801 // { "AdjuBlackProc", AdjuBlackProc },
1802 // { "AdjuDrawProc", AdjuDrawProc },
1803 { "EnterKeyProc", EnterKeyProc },
1804 // { "StopObservingProc", StopObservingProc },
1805 // { "StopExaminingProc", StopExaminingProc },
1806 // { "BackwardProc", BackwardProc },
1807 // { "ForwardProc", ForwardProc },
1808 // { "ToStartProc", ToStartProc },
1809 // { "ToEndProc", ToEndProc },
1810 // { "RevertProc", RevertProc },
1811 // { "TruncateGameProc", TruncateGameProc },
1812 // { "MoveNowProc", MoveNowProc },
1813 // { "RetractMoveProc", RetractMoveProc },
1814 // { "AlwaysQueenProc", AlwaysQueenProc },
1815 // { "AnimateDraggingProc", AnimateDraggingProc },
1816 // { "AnimateMovingProc", AnimateMovingProc },
1817 // { "AutoflagProc", AutoflagProc },
1818 // { "AutoflipProc", AutoflipProc },
1819 // { "AutobsProc", AutobsProc },
1820 // { "AutoraiseProc", AutoraiseProc },
1821 // { "AutosaveProc", AutosaveProc },
1822 // { "BlindfoldProc", BlindfoldProc },
1823 // { "FlashMovesProc", FlashMovesProc },
1824 // { "FlipViewProc", FlipViewProc },
1825 // { "GetMoveListProc", GetMoveListProc },
1827 // { "HighlightDraggingProc", HighlightDraggingProc },
1829 // { "HighlightLastMoveProc", HighlightLastMoveProc },
1830 // { "IcsAlarmProc", IcsAlarmProc },
1831 // { "MoveSoundProc", MoveSoundProc },
1832 // { "OldSaveStyleProc", OldSaveStyleProc },
1833 // { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1834 // { "PonderNextMoveProc", PonderNextMoveProc },
1835 // { "PopupExitMessageProc", PopupExitMessageProc },
1836 // { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1837 // { "PremoveProc", PremoveProc },
1838 // { "QuietPlayProc", QuietPlayProc },
1839 // { "ShowThinkingProc", ShowThinkingProc },
1840 // { "HideThinkingProc", HideThinkingProc },
1841 { "TestLegalityProc", TestLegalityProc },
1842 // { "InfoProc", InfoProc },
1843 // { "ManProc", ManProc },
1844 // { "HintProc", HintProc },
1845 // { "BookProc", BookProc },
1846 { "AboutGameProc", AboutGameProc },
1847 { "DebugProc", DebugProc },
1848 { "NothingProc", NothingProc },
1849 { "CommentPopDown", (XtActionProc) CommentPopDown },
1850 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1851 { "TagsPopDown", (XtActionProc) TagsPopDown },
1852 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1853 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1854 // { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1855 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1856 { "GameListPopDown", (XtActionProc) GameListPopDown },
1857 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1858 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1859 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1860 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1861 { "EnginePopDown", (XtActionProc) EnginePopDown },
1862 { "UciPopDown", (XtActionProc) UciPopDown },
1863 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1864 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1865 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1869 char ICSInputTranslations[] =
1870 "<Key>Return: EnterKeyProc() \n";
1872 String xboardResources[] = {
1873 // "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1874 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1875 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1879 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1880 "magenta", "cyan", "white" };
1884 TextColors textColors[(int)NColorClasses];
1886 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1888 parse_color(str, which)
1892 char *p, buf[100], *d;
1895 if (strlen(str) > 99) /* watch bounds on buf */
1900 for (i=0; i<which; ++i) {
1907 /* Could be looking at something like:
1909 .. in which case we want to stop on a comma also */
1910 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1914 return -1; /* Use default for empty field */
1917 if (which == 2 || isdigit(*p))
1920 while (*p && isalpha(*p))
1925 for (i=0; i<8; ++i) {
1926 if (!StrCaseCmp(buf, cnames[i]))
1927 return which? (i+40) : (i+30);
1929 if (!StrCaseCmp(buf, "default")) return -1;
1931 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1936 parse_cpair(cc, str)
1940 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1941 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1946 /* bg and attr are optional */
1947 textColors[(int)cc].bg = parse_color(str, 1);
1948 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1949 textColors[(int)cc].attr = 0;
1955 /* Arrange to catch delete-window events */
1956 Atom wm_delete_window;
1958 CatchDeleteWindow(Widget w, String procname)
1961 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1962 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1963 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1969 /* this should raise the board to the top */
1970 gtk_window_present(GTK_WINDOW(GUI_Window));
1974 #define BoardSize int
1975 void InitDrawingSizes(BoardSize boardSize, int flags)
1976 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1977 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1979 XtGeometryResult gres;
1982 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1983 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1985 timerWidth = (boardWidth - sep) / 2;
1987 if (appData.titleInWindow)
1992 w = boardWidth - 2*bor;
1996 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2000 if(!formWidget) return;
2003 * Inhibit shell resizing.
2006 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2009 for(i=0; i<4; i++) {
2011 for(p=0; p<=(int)WhiteKing; p++)
2012 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2013 if(gameInfo.variant == VariantShogi) {
2014 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2015 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2016 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2017 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2018 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2021 if(gameInfo.variant == VariantGothic) {
2022 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2026 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2027 for(p=0; p<=(int)WhiteKing; p++)
2028 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2029 if(gameInfo.variant == VariantShogi) {
2030 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2031 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2032 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2033 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2034 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2037 if(gameInfo.variant == VariantGothic) {
2038 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2044 for(i=0; i<2; i++) {
2046 for(p=0; p<=(int)WhiteKing; p++)
2047 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2048 if(gameInfo.variant == VariantShogi) {
2049 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2050 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2051 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2052 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2053 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2056 if(gameInfo.variant == VariantGothic) {
2057 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2067 void EscapeExpand(char *p, char *q)
2068 { // [HGM] initstring: routine to shape up string arguments
2069 while(*p++ = *q++) if(p[-1] == '\\')
2071 case 'n': p[-1] = '\n'; break;
2072 case 'r': p[-1] = '\r'; break;
2073 case 't': p[-1] = '\t'; break;
2074 case '\\': p[-1] = '\\'; break;
2075 case 0: *p = 0; return;
2076 default: p[-1] = q[-1]; break;
2085 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2086 XSetWindowAttributes window_attributes;
2088 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2089 XrmValue vFrom, vTo;
2090 XtGeometryResult gres;
2093 int forceMono = False;
2097 // [HGM] before anything else, expand any indirection files amongst options
2098 char *argvCopy[1000]; // 1000 seems enough
2099 char newArgs[10000]; // holds actual characters
2102 srandom(time(0)); // [HGM] book: make random truly random
2105 for(i=0; i<argc; i++) {
2106 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2107 //fprintf(stderr, "arg %s\n", argv[i]);
2108 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2110 FILE *f = fopen(argv[i]+1, "rb");
2111 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2112 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2113 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2115 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2116 newArgs[k++] = 0; // terminate current arg
2117 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2118 argvCopy[j++] = newArgs + k; // get ready for next
2120 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2134 setbuf(stdout, NULL);
2135 setbuf(stderr, NULL);
2138 programName = strrchr(argv[0], '/');
2139 if (programName == NULL)
2140 programName = argv[0];
2145 XtSetLanguageProc(NULL, NULL, NULL);
2146 bindtextdomain(PACKAGE, LOCALEDIR);
2147 textdomain(PACKAGE);
2151 XtAppInitialize(&appContext, "XBoard", shellOptions,
2152 XtNumber(shellOptions),
2153 &argc, argv, xboardResources, NULL, 0);
2156 gtk_init (&argc, &argv);
2158 /* parse glade file to build widgets */
2160 builder = gtk_builder_new ();
2161 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2163 /* test if everything worked ok */
2165 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2166 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2168 GUI_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2169 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2171 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2172 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2174 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2175 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2176 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2177 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2178 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2179 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2180 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2181 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2183 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2184 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2186 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2187 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2189 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2190 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2192 /* EditTags window */
2193 GUI_EditTags = GTK_WIDGET (gtk_builder_get_object (builder, "EditTags"));
2194 if(!GUI_EditTags) printf("Error: gtk_builder didn't work!\n");
2196 GUI_EditTagsTextArea = GTK_WIDGET (gtk_builder_get_object (builder, "EditTagsTextArea"));
2197 if(!GUI_EditTagsTextArea) printf("Error: gtk_builder didn't work!\n");
2200 gtk_builder_connect_signals (builder, NULL);
2202 // don't unref the builder, since we use it to get references to widgets
2203 // g_object_unref (G_OBJECT (builder));
2205 /* end parse glade file */
2209 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2210 programName, argv[1]);
2212 fprintf(stderr, "Recognized options:\n");
2213 for(i = 0; i < XtNumber(shellOptions); i++)
2215 /* print first column */
2216 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2217 (shellOptions[i].argKind == XrmoptionSepArg
2219 /* print second column and end line */
2220 if (++i < XtNumber(shellOptions))
2222 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2223 shellOptions[i].option,
2224 (shellOptions[i].argKind == XrmoptionSepArg
2229 fprintf(stderr, "\n");
2236 if (p == NULL) p = "/tmp";
2237 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2238 gameCopyFilename = (char*) malloc(i);
2239 gamePasteFilename = (char*) malloc(i);
2240 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2241 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2243 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2244 clientResources, XtNumber(clientResources),
2247 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2248 static char buf[MSG_SIZ];
2249 EscapeExpand(buf, appData.initString);
2250 appData.initString = strdup(buf);
2251 EscapeExpand(buf, appData.secondInitString);
2252 appData.secondInitString = strdup(buf);
2253 EscapeExpand(buf, appData.firstComputerString);
2254 appData.firstComputerString = strdup(buf);
2255 EscapeExpand(buf, appData.secondComputerString);
2256 appData.secondComputerString = strdup(buf);
2259 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2262 if (chdir(chessDir) != 0) {
2263 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2269 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2270 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2271 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2272 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2275 setbuf(debugFP, NULL);
2278 /* [HGM,HR] make sure board size is acceptable */
2279 if(appData.NrFiles > BOARD_SIZE ||
2280 appData.NrRanks > BOARD_SIZE )
2281 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2284 /* This feature does not work; animation needs a rewrite */
2285 appData.highlightDragging = FALSE;
2289 xDisplay = XtDisplay(shellWidget);
2290 xScreen = DefaultScreen(xDisplay);
2291 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2293 gameInfo.variant = StringToVariant(appData.variant);
2294 InitPosition(FALSE);
2296 /* calc board size */
2297 if (isdigit(appData.boardSize[0]))
2299 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2300 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2301 &fontPxlSize, &smallLayout, &tinyLayout);
2304 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2305 programName, appData.boardSize);
2310 /* Find some defaults; use the nearest known size */
2311 SizeDefaults *szd, *nearest;
2312 int distance = 99999;
2313 nearest = szd = sizeDefaults;
2314 while (szd->name != NULL)
2316 if (abs(szd->squareSize - squareSize) < distance)
2319 distance = abs(szd->squareSize - squareSize);
2320 if (distance == 0) break;
2324 if (i < 2) lineGap = nearest->lineGap;
2325 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2326 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2327 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2328 if (i < 6) smallLayout = nearest->smallLayout;
2329 if (i < 7) tinyLayout = nearest->tinyLayout;
2334 SizeDefaults *szd = sizeDefaults;
2335 if (*appData.boardSize == NULLCHAR)
2337 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2338 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2342 if (szd->name == NULL) szd--;
2346 while (szd->name != NULL
2347 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2349 if (szd->name == NULL)
2351 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2352 programName, appData.boardSize);
2356 squareSize = szd->squareSize;
2357 lineGap = szd->lineGap;
2358 clockFontPxlSize = szd->clockFontPxlSize;
2359 coordFontPxlSize = szd->coordFontPxlSize;
2360 fontPxlSize = szd->fontPxlSize;
2361 smallLayout = szd->smallLayout;
2362 tinyLayout = szd->tinyLayout;
2364 /* end figuring out what size to use */
2366 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2367 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2370 * Determine what fonts to use.
2372 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2373 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2374 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2375 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2376 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2377 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2378 appData.font = FindFont(appData.font, fontPxlSize);
2379 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2380 countFontStruct = XQueryFont(xDisplay, countFontID);
2381 // appData.font = FindFont(appData.font, fontPxlSize);
2383 xdb = XtDatabase(xDisplay);
2384 XrmPutStringResource(&xdb, "*font", appData.font);
2387 * Detect if there are not enough colors available and adapt.
2389 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2390 appData.monoMode = True;
2393 if (!appData.monoMode) {
2394 vFrom.addr = (caddr_t) appData.lightSquareColor;
2395 vFrom.size = strlen(appData.lightSquareColor);
2396 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2397 if (vTo.addr == NULL) {
2398 appData.monoMode = True;
2401 lightSquareColor = *(Pixel *) vTo.addr;
2404 if (!appData.monoMode) {
2405 vFrom.addr = (caddr_t) appData.darkSquareColor;
2406 vFrom.size = strlen(appData.darkSquareColor);
2407 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2408 if (vTo.addr == NULL) {
2409 appData.monoMode = True;
2412 darkSquareColor = *(Pixel *) vTo.addr;
2415 if (!appData.monoMode) {
2416 vFrom.addr = (caddr_t) appData.whitePieceColor;
2417 vFrom.size = strlen(appData.whitePieceColor);
2418 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2419 if (vTo.addr == NULL) {
2420 appData.monoMode = True;
2423 whitePieceColor = *(Pixel *) vTo.addr;
2426 if (!appData.monoMode) {
2427 vFrom.addr = (caddr_t) appData.blackPieceColor;
2428 vFrom.size = strlen(appData.blackPieceColor);
2429 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2430 if (vTo.addr == NULL) {
2431 appData.monoMode = True;
2434 blackPieceColor = *(Pixel *) vTo.addr;
2438 if (!appData.monoMode) {
2439 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2440 vFrom.size = strlen(appData.highlightSquareColor);
2441 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2442 if (vTo.addr == NULL) {
2443 appData.monoMode = True;
2446 highlightSquareColor = *(Pixel *) vTo.addr;
2450 if (!appData.monoMode) {
2451 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2452 vFrom.size = strlen(appData.premoveHighlightColor);
2453 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2454 if (vTo.addr == NULL) {
2455 appData.monoMode = True;
2458 premoveHighlightColor = *(Pixel *) vTo.addr;
2463 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2466 if (appData.bitmapDirectory == NULL ||
2467 appData.bitmapDirectory[0] == NULLCHAR)
2468 appData.bitmapDirectory = DEF_BITMAP_DIR;
2471 if (appData.lowTimeWarning && !appData.monoMode) {
2472 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2473 vFrom.size = strlen(appData.lowTimeWarningColor);
2474 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2475 if (vTo.addr == NULL)
2476 appData.monoMode = True;
2478 lowTimeWarningColor = *(Pixel *) vTo.addr;
2481 if (appData.monoMode && appData.debugMode) {
2482 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2483 (unsigned long) XWhitePixel(xDisplay, xScreen),
2484 (unsigned long) XBlackPixel(xDisplay, xScreen));
2487 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2488 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2489 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2490 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2491 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2492 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2493 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2494 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2495 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2496 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2498 if (appData.colorize) {
2500 _("%s: can't parse color names; disabling colorization\n"),
2503 appData.colorize = FALSE;
2505 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2506 textColors[ColorNone].attr = 0;
2508 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2514 layoutName = "tinyLayout";
2515 } else if (smallLayout) {
2516 layoutName = "smallLayout";
2518 layoutName = "normalLayout";
2521 if (appData.titleInWindow) {
2522 /* todo check what this appdata does */
2525 if (appData.showButtonBar) {
2526 /* TODO hide button bar if requested */
2530 if (appData.titleInWindow)
2535 if (appData.showButtonBar)
2542 if (appData.showButtonBar)
2552 /* set some checkboxes in the menu according to appData */
2554 if (appData.alwaysPromoteToQueen)
2555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2557 if (appData.animateDragging)
2558 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2560 if (appData.animate)
2561 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2563 if (appData.autoComment)
2564 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2566 if (appData.autoCallFlag)
2567 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2569 if (appData.autoFlipView)
2570 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2572 if (appData.autoObserve)
2573 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2575 if (appData.autoRaiseBoard)
2576 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2578 if (appData.autoSaveGames)
2579 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2581 if (appData.saveGameFile[0] != NULLCHAR)
2583 /* Can't turn this off from menu */
2584 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2585 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2588 if (appData.blindfold)
2589 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2591 if (appData.flashCount > 0)
2592 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2594 if (appData.getMoveList)
2595 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2598 if (appData.highlightDragging)
2599 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2602 if (appData.highlightLastMove)
2603 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2605 if (appData.icsAlarm)
2606 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2608 if (appData.ringBellAfterMoves)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2611 if (appData.oldSaveStyle)
2612 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2614 if (appData.periodicUpdates)
2615 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2617 if (appData.ponderNextMove)
2618 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2620 if (appData.popupExitMessage)
2621 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2623 if (appData.popupMoveErrors)
2624 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2626 if (appData.premove)
2627 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2629 if (appData.quietPlay)
2630 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2632 if (appData.showCoords)
2633 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2635 if (appData.showThinking)
2636 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2638 if (appData.testLegality)
2639 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2641 /* end setting check boxes */
2643 /* load square colors */
2644 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2645 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2646 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2648 /* use two icons to indicate if it is white's or black's turn */
2649 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2650 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2651 WindowIcon = WhiteIcon;
2652 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2655 /* realize window */
2656 gtk_widget_show (GUI_Window);
2658 /* recalc boardsize */
2663 if (appData.animate || appData.animateDragging)
2668 if (errorExitStatus == -1) {
2669 if (appData.icsActive) {
2670 /* We now wait until we see "login:" from the ICS before
2671 sending the logon script (problems with timestamp otherwise) */
2672 /*ICSInitScript();*/
2673 if (appData.icsInputBox) ICSInputBoxPopUp();
2677 signal(SIGWINCH, TermSizeSigHandler);
2679 signal(SIGINT, IntSigHandler);
2680 signal(SIGTERM, IntSigHandler);
2681 if (*appData.cmailGameName != NULLCHAR) {
2682 signal(SIGUSR1, CmailSigHandler);
2685 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2689 * Create a cursor for the board widget.
2690 * (This needs to be called after the window has been created to have access to board-window)
2693 BoardCursor = gdk_cursor_new(GDK_HAND2);
2694 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2695 gdk_cursor_destroy(BoardCursor);
2700 if (appData.debugMode) fclose(debugFP); // [DM] debug
2707 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2708 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2710 unlink(gameCopyFilename);
2711 unlink(gamePasteFilename);
2714 RETSIGTYPE TermSizeSigHandler(int sig)
2727 CmailSigHandler(sig)
2733 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2735 /* Activate call-back function CmailSigHandlerCallBack() */
2736 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2738 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2742 CmailSigHandlerCallBack(isr, closure, message, count, error)
2750 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2752 /**** end signal code ****/
2762 f = fopen(appData.icsLogon, "r");
2768 strcat(buf, appData.icsLogon);
2769 f = fopen(buf, "r");
2773 ProcessICSInitScript(f);
2780 EditCommentPopDown();
2786 SetMenuEnables(enab)
2791 if (!builder) return;
2792 while (enab->name != NULL) {
2793 o = gtk_builder_get_object(builder, enab->name);
2794 if(GTK_IS_WIDGET(o))
2795 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2798 if(GTK_IS_ACTION(o))
2799 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2801 DisplayError(enab->name, 0);
2809 SetMenuEnables(icsEnables);
2812 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2813 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2820 SetMenuEnables(ncpEnables);
2826 SetMenuEnables(gnuEnables);
2832 SetMenuEnables(cmailEnables);
2838 SetMenuEnables(trainingOnEnables);
2839 if (appData.showButtonBar) {
2840 // XtSetSensitive(buttonBarWidget, False);
2846 SetTrainingModeOff()
2848 SetMenuEnables(trainingOffEnables);
2849 if (appData.showButtonBar) {
2850 // XtSetSensitive(buttonBarWidget, True);
2855 SetUserThinkingEnables()
2857 if (appData.noChessProgram) return;
2858 SetMenuEnables(userThinkingEnables);
2862 SetMachineThinkingEnables()
2864 if (appData.noChessProgram) return;
2865 SetMenuEnables(machineThinkingEnables);
2867 case MachinePlaysBlack:
2868 case MachinePlaysWhite:
2869 case TwoMachinesPlay:
2870 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2871 // ModeToWidgetName(gameMode)), True);
2878 #define Abs(n) ((n)<0 ? -(n) : (n))
2881 * Find a font that matches "pattern" that is as close as
2882 * possible to the targetPxlSize. Prefer fonts that are k
2883 * pixels smaller to fonts that are k pixels larger. The
2884 * pattern must be in the X Consortium standard format,
2885 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2886 * The return value should be freed with XtFree when no
2889 char *FindFont(pattern, targetPxlSize)
2893 char **fonts, *p, *best, *scalable, *scalableTail;
2894 int i, j, nfonts, minerr, err, pxlSize;
2897 char **missing_list;
2899 char *def_string, *base_fnt_lst, strInt[3];
2901 XFontStruct **fnt_list;
2903 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2904 sprintf(strInt, "%d", targetPxlSize);
2905 p = strstr(pattern, "--");
2906 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2907 strcat(base_fnt_lst, strInt);
2908 strcat(base_fnt_lst, strchr(p + 2, '-'));
2910 if ((fntSet = XCreateFontSet(xDisplay,
2914 &def_string)) == NULL) {
2916 fprintf(stderr, _("Unable to create font set.\n"));
2920 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2922 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2924 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2925 programName, pattern);
2933 for (i=0; i<nfonts; i++) {
2936 if (*p != '-') continue;
2938 if (*p == NULLCHAR) break;
2939 if (*p++ == '-') j++;
2941 if (j < 7) continue;
2944 scalable = fonts[i];
2947 err = pxlSize - targetPxlSize;
2948 if (Abs(err) < Abs(minerr) ||
2949 (minerr > 0 && err < 0 && -err == minerr)) {
2955 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2956 /* If the error is too big and there is a scalable font,
2957 use the scalable font. */
2958 int headlen = scalableTail - scalable;
2959 p = (char *) XtMalloc(strlen(scalable) + 10);
2960 while (isdigit(*scalableTail)) scalableTail++;
2961 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2963 p = (char *) XtMalloc(strlen(best) + 1);
2966 if (appData.debugMode) {
2967 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2968 pattern, targetPxlSize, p);
2971 if (missing_count > 0)
2972 XFreeStringList(missing_list);
2973 XFreeFontSet(xDisplay, fntSet);
2975 XFreeFontNames(fonts);
2982 /* 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*/
2984 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2985 | GCBackground | GCFunction | GCPlaneMask;
2986 XGCValues gc_values;
2989 gc_values.plane_mask = AllPlanes;
2990 gc_values.line_width = lineGap;
2991 gc_values.line_style = LineSolid;
2992 gc_values.function = GXcopy;
2994 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2995 gc_values.background = XWhitePixel(xDisplay, xScreen);
2996 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2997 XSetFont(xDisplay, coordGC, coordFontID);
2999 if (appData.monoMode) {
3000 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3001 gc_values.background = XBlackPixel(xDisplay, xScreen);
3002 lightSquareGC = wbPieceGC
3003 = XtGetGC(shellWidget, value_mask, &gc_values);
3005 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3006 gc_values.background = XWhitePixel(xDisplay, xScreen);
3007 darkSquareGC = bwPieceGC
3008 = XtGetGC(shellWidget, value_mask, &gc_values);
3010 if (DefaultDepth(xDisplay, xScreen) == 1) {
3011 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3012 gc_values.function = GXcopyInverted;
3013 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3014 gc_values.function = GXcopy;
3015 if (XBlackPixel(xDisplay, xScreen) == 1) {
3016 bwPieceGC = darkSquareGC;
3017 wbPieceGC = copyInvertedGC;
3019 bwPieceGC = copyInvertedGC;
3020 wbPieceGC = lightSquareGC;
3024 gc_values.foreground = lightSquareColor;
3025 gc_values.background = darkSquareColor;
3026 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3028 gc_values.foreground = darkSquareColor;
3029 gc_values.background = lightSquareColor;
3030 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3032 gc_values.foreground = jailSquareColor;
3033 gc_values.background = jailSquareColor;
3034 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3036 gc_values.foreground = whitePieceColor;
3037 gc_values.background = darkSquareColor;
3038 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3040 gc_values.foreground = whitePieceColor;
3041 gc_values.background = lightSquareColor;
3042 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3044 gc_values.foreground = whitePieceColor;
3045 gc_values.background = jailSquareColor;
3046 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3048 gc_values.foreground = blackPieceColor;
3049 gc_values.background = darkSquareColor;
3050 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3052 gc_values.foreground = blackPieceColor;
3053 gc_values.background = lightSquareColor;
3054 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3056 gc_values.foreground = blackPieceColor;
3057 gc_values.background = jailSquareColor;
3058 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3067 for(i=0;i<MAXPIECES;i++)
3071 g_free(SVGpieces[i]);
3078 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3079 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3080 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3083 /* get some defaults going */
3084 for(i=WhitePawn; i<DemotePiece+1; i++)
3085 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3087 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3088 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3089 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3090 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3091 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3092 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3094 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3095 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3096 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3097 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3098 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3099 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3105 static void MenuBarSelect(w, addr, index)
3110 XtActionProc proc = (XtActionProc) addr;
3112 (proc)(NULL, NULL, NULL, NULL);
3115 void CreateMenuBarPopup(parent, name, mb)
3125 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3128 XtSetArg(args[j], XtNleftMargin, 20); j++;
3129 XtSetArg(args[j], XtNrightMargin, 20); j++;
3131 while (mi->string != NULL) {
3132 if (strcmp(mi->string, "----") == 0) {
3133 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3136 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3137 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3139 XtAddCallback(entry, XtNcallback,
3140 (XtCallbackProc) MenuBarSelect,
3141 (caddr_t) mi->proc);
3147 Widget CreateMenuBar(mb)
3151 Widget anchor, menuBar;
3153 char menuName[MSG_SIZ];
3156 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3157 XtSetArg(args[j], XtNvSpace, 0); j++;
3158 XtSetArg(args[j], XtNborderWidth, 0); j++;
3159 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3160 formWidget, args, j);
3162 while (mb->name != NULL) {
3163 strcpy(menuName, "menu");
3164 strcat(menuName, mb->name);
3166 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3169 shortName[0] = _(mb->name)[0];
3170 shortName[1] = NULLCHAR;
3171 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3174 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3177 XtSetArg(args[j], XtNborderWidth, 0); j++;
3178 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3180 CreateMenuBarPopup(menuBar, menuName, mb);
3188 CreatePieceMenu(name, color)
3195 ChessSquare selection;
3197 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3198 boardWidget, args, 0);
3200 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3201 String item = pieceMenuStrings[color][i];
3203 if (strcmp(item, "----") == 0) {
3204 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3207 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3208 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3210 selection = pieceMenuTranslation[color][i];
3211 XtAddCallback(entry, XtNcallback,
3212 (XtCallbackProc) PieceMenuSelect,
3213 (caddr_t) selection);
3214 if (selection == WhitePawn || selection == BlackPawn) {
3215 XtSetArg(args[0], XtNpopupOnEntry, entry);
3216 XtSetValues(menu, args, 1);
3229 ChessSquare selection;
3231 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3232 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3234 // XtRegisterGrabAction(PieceMenuPopup, True,
3235 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3236 // GrabModeAsync, GrabModeAsync);
3238 // XtSetArg(args[0], XtNlabel, _("Drop"));
3239 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3240 // boardWidget, args, 1);
3241 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3242 // String item = dropMenuStrings[i];
3244 // if (strcmp(item, "----") == 0) {
3245 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3246 // dropMenu, NULL, 0);
3248 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3249 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3250 // dropMenu, args, 1);
3251 // selection = dropMenuTranslation[i];
3252 // XtAddCallback(entry, XtNcallback,
3253 // (XtCallbackProc) DropMenuSelect,
3254 // (caddr_t) selection);
3259 void SetupDropMenu()
3267 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3268 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3269 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3270 dmEnables[i].piece);
3271 XtSetSensitive(entry, p != NULL || !appData.testLegality
3272 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3273 && !appData.icsActive));
3275 while (p && *p++ == dmEnables[i].piece) count++;
3276 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3278 XtSetArg(args[j], XtNlabel, label); j++;
3279 XtSetValues(entry, args, j);
3283 void PieceMenuPopup(w, event, params, num_params)
3287 Cardinal *num_params;
3290 if (event->type != ButtonPress) return;
3291 if (errorUp) ErrorPopDown();
3295 whichMenu = params[0];
3297 case IcsPlayingWhite:
3298 case IcsPlayingBlack:
3300 case MachinePlaysWhite:
3301 case MachinePlaysBlack:
3302 if (appData.testLegality &&
3303 gameInfo.variant != VariantBughouse &&
3304 gameInfo.variant != VariantCrazyhouse) return;
3306 whichMenu = "menuD";
3312 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3313 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3314 pmFromX = pmFromY = -1;
3318 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3320 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3322 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3325 static void PieceMenuSelect(w, piece, junk)
3330 if (pmFromX < 0 || pmFromY < 0) return;
3331 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3334 static void DropMenuSelect(w, piece, junk)
3339 if (pmFromX < 0 || pmFromY < 0) return;
3340 DropMenuEvent(piece, pmFromX, pmFromY);
3344 * If the user selects on a border boundary, return -1; if off the board,
3345 * return -2. Otherwise map the event coordinate to the square.
3347 int EventToSquare(x, limit)
3355 if ((x % (squareSize + lineGap)) >= squareSize)
3357 x /= (squareSize + lineGap);
3363 static void do_flash_delay(msec)
3369 static void drawHighlight(file, rank, line_type)
3370 int file, rank, line_type;
3375 if (lineGap == 0 || appData.blindfold) return;
3379 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3380 (squareSize + lineGap);
3381 y = lineGap/2 + rank * (squareSize + lineGap);
3385 x = lineGap/2 + file * (squareSize + lineGap);
3386 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3387 (squareSize + lineGap);
3391 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3393 /* draw the highlight */
3394 cairo_move_to (cr, x, y);
3395 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3396 cairo_rel_line_to (cr, squareSize+lineGap,0);
3397 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3398 cairo_close_path (cr);
3400 cairo_set_line_width (cr, lineGap);
3403 /* TODO: use appdata colors */
3404 case LINE_TYPE_HIGHLIGHT:
3405 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3408 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3410 case LINE_TYPE_NORMAL:
3412 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3423 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3424 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3427 SetHighlights(fromX, fromY, toX, toY)
3428 int fromX, fromY, toX, toY;
3430 if (hi1X != fromX || hi1Y != fromY)
3432 if (hi1X >= 0 && hi1Y >= 0)
3434 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3436 if (fromX >= 0 && fromY >= 0)
3438 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3441 if (hi2X != toX || hi2Y != toY)
3443 if (hi2X >= 0 && hi2Y >= 0)
3445 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3447 if (toX >= 0 && toY >= 0)
3449 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3463 SetHighlights(-1, -1, -1, -1);
3468 SetPremoveHighlights(fromX, fromY, toX, toY)
3469 int fromX, fromY, toX, toY;
3471 if (pm1X != fromX || pm1Y != fromY)
3473 if (pm1X >= 0 && pm1Y >= 0)
3475 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3477 if (fromX >= 0 && fromY >= 0)
3479 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3482 if (pm2X != toX || pm2Y != toY)
3484 if (pm2X >= 0 && pm2Y >= 0)
3486 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3488 if (toX >= 0 && toY >= 0)
3490 drawHighlight(toX, toY, LINE_TYPE_PRE);
3503 ClearPremoveHighlights()
3505 SetPremoveHighlights(-1, -1, -1, -1);
3508 static void BlankSquare(x, y, color, piece, dest)
3521 pb = SVGLightSquare;
3523 case 2: /* neutral */
3525 pb = SVGNeutralSquare;
3528 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3532 static void DrawPiece(piece, square_color, x, y, dest)
3534 int square_color, x, y;
3537 /* redraw background, since piece might be transparent in some areas */
3538 BlankSquare(x,y,square_color,piece,dest);
3541 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3542 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3543 GDK_RGB_DITHER_NORMAL, 0, 0);
3547 /* [HR] determine square color depending on chess variant. */
3548 static int SquareColor(row, column)
3553 if (gameInfo.variant == VariantXiangqi) {
3554 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3556 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3558 } else if (row <= 4) {
3564 square_color = ((column + row) % 2) == 1;
3567 /* [hgm] holdings: next line makes all holdings squares light */
3568 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3570 return square_color;
3573 void DrawSquare(row, column, piece, do_flash)
3574 int row, column, do_flash;
3577 int square_color, x, y;
3582 /* Calculate delay in milliseconds (2-delays per complete flash) */
3583 flash_delay = 500 / appData.flashRate;
3585 /* calculate x and y coordinates from row and column */
3588 x = lineGap + ((BOARD_WIDTH-1)-column) *
3589 (squareSize + lineGap);
3590 y = lineGap + row * (squareSize + lineGap);
3594 x = lineGap + column * (squareSize + lineGap);
3595 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3596 (squareSize + lineGap);
3599 square_color = SquareColor(row, column);
3601 // [HGM] holdings: blank out area between board and holdings
3602 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3603 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3604 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3606 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3608 // [HGM] print piece counts next to holdings
3609 string[1] = NULLCHAR;
3612 cairo_text_extents_t extents;
3617 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3619 string[0] = '0' + piece;
3621 /* TODO this has to go into the font-selection */
3622 cairo_select_font_face (cr, "Sans",
3623 CAIRO_FONT_SLANT_NORMAL,
3624 CAIRO_FONT_WEIGHT_NORMAL);
3626 cairo_set_font_size (cr, 12.0);
3627 cairo_text_extents (cr, string, &extents);
3629 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3631 xpos= x + squareSize - extents.width - 2;
3632 ypos= y + extents.y_bearing + 1;
3634 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3637 ypos = y + extents.y_bearing + 1;
3640 /* TODO mono mode? */
3641 cairo_move_to (cr, xpos, ypos);
3642 cairo_text_path (cr, string);
3643 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3644 cairo_fill_preserve (cr);
3645 cairo_set_source_rgb (cr, 0, 0, 0);
3646 cairo_set_line_width (cr, 0.1);
3655 /* square on the board */
3656 if (piece == EmptySquare || appData.blindfold)
3658 BlankSquare(x, y, square_color, piece, xBoardWindow);
3662 if (do_flash && appData.flashCount > 0)
3664 for (i=0; i<appData.flashCount; ++i)
3667 DrawPiece(piece, square_color, x, y, xBoardWindow);
3668 do_flash_delay(flash_delay);
3670 BlankSquare(x, y, square_color, piece, xBoardWindow);
3671 do_flash_delay(flash_delay);
3674 DrawPiece(piece, square_color, x, y, xBoardWindow);
3678 /* show coordinates if necessary */
3679 if(appData.showCoords)
3681 cairo_text_extents_t extents;
3685 /* TODO this has to go into the font-selection */
3686 cairo_select_font_face (cr, "Sans",
3687 CAIRO_FONT_SLANT_NORMAL,
3688 CAIRO_FONT_WEIGHT_NORMAL);
3689 cairo_set_font_size (cr, 12.0);
3691 string[1] = NULLCHAR;
3694 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3696 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3697 column >= BOARD_LEFT && column < BOARD_RGHT)
3699 string[0] = 'a' + column - BOARD_LEFT;
3700 cairo_text_extents (cr, string, &extents);
3702 xpos = x + squareSize - extents.width - 2;
3703 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3705 if (appData.monoMode)
3712 cairo_move_to (cr, xpos, ypos);
3713 cairo_text_path (cr, string);
3714 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3715 cairo_fill_preserve (cr);
3716 cairo_set_source_rgb (cr, 0, 1.0, 0);
3717 cairo_set_line_width (cr, 0.1);
3720 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3723 string[0] = ONE + row;
3724 cairo_text_extents (cr, string, &extents);
3727 ypos = y + extents.height + 1;
3729 if (appData.monoMode)
3736 cairo_move_to (cr, xpos, ypos);
3737 cairo_text_path (cr, string);
3738 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3739 cairo_fill_preserve (cr);
3740 cairo_set_source_rgb (cr, 0, 0, 1.0);
3741 cairo_set_line_width (cr, 0.1);
3753 /* Returns 1 if there are "too many" differences between b1 and b2
3754 (i.e. more than 1 move was made) */
3755 static int too_many_diffs(b1, b2)
3761 for (i=0; i<BOARD_HEIGHT; ++i) {
3762 for (j=0; j<BOARD_WIDTH; ++j) {
3763 if (b1[i][j] != b2[i][j]) {
3764 if (++c > 4) /* Castling causes 4 diffs */
3773 /* Matrix describing castling maneuvers */
3774 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3775 static int castling_matrix[4][5] = {
3776 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3777 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3778 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3779 { 7, 7, 4, 5, 6 } /* 0-0, black */
3782 /* Checks whether castling occurred. If it did, *rrow and *rcol
3783 are set to the destination (row,col) of the rook that moved.
3785 Returns 1 if castling occurred, 0 if not.
3787 Note: Only handles a max of 1 castling move, so be sure
3788 to call too_many_diffs() first.
3790 static int check_castle_draw(newb, oldb, rrow, rcol)
3797 /* For each type of castling... */
3798 for (i=0; i<4; ++i) {
3799 r = castling_matrix[i];
3801 /* Check the 4 squares involved in the castling move */
3803 for (j=1; j<=4; ++j) {
3804 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3811 /* All 4 changed, so it must be a castling move */
3820 static int damage[BOARD_SIZE][BOARD_SIZE];
3823 * event handler for redrawing the board
3825 void DrawPosition( repaint, board)
3826 /*Boolean*/int repaint;
3830 static int lastFlipView = 0;
3831 static int lastBoardValid = 0;
3832 static Board lastBoard;
3835 if (board == NULL) {
3836 if (!lastBoardValid) return;
3839 if (!lastBoardValid || lastFlipView != flipView) {
3840 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3841 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3846 * It would be simpler to clear the window with XClearWindow()
3847 * but this causes a very distracting flicker.
3850 if (!repaint && lastBoardValid && lastFlipView == flipView)
3852 /* If too much changes (begin observing new game, etc.), don't
3854 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3856 /* Special check for castling so we don't flash both the king
3857 and the rook (just flash the king). */
3860 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3862 /* Draw rook with NO flashing. King will be drawn flashing later */
3863 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3864 lastBoard[rrow][rcol] = board[rrow][rcol];
3868 /* First pass -- Draw (newly) empty squares and repair damage.
3869 This prevents you from having a piece show up twice while it
3870 is flashing on its new square */
3871 for (i = 0; i < BOARD_HEIGHT; i++)
3872 for (j = 0; j < BOARD_WIDTH; j++)
3873 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3876 DrawSquare(i, j, board[i][j], 0);
3877 damage[i][j] = False;
3880 /* Second pass -- Draw piece(s) in new position and flash them */
3881 for (i = 0; i < BOARD_HEIGHT; i++)
3882 for (j = 0; j < BOARD_WIDTH; j++)
3883 if (board[i][j] != lastBoard[i][j])
3885 DrawSquare(i, j, board[i][j], do_flash);
3897 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3899 cairo_set_line_width (cr, lineGap);
3901 /* TODO: use appdata colors */
3902 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3906 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3909 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3910 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3912 cairo_move_to (cr, x1, y1);
3913 cairo_rel_line_to (cr, x2,0);
3917 for (j = 0; j < BOARD_WIDTH + 1; j++)
3920 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3921 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3923 cairo_move_to (cr, x1, y1);
3924 cairo_rel_line_to (cr, 0, y2);
3933 for (i = 0; i < BOARD_HEIGHT; i++)
3934 for (j = 0; j < BOARD_WIDTH; j++)
3936 DrawSquare(i, j, board[i][j], 0);
3937 damage[i][j] = False;
3941 CopyBoard(lastBoard, board);
3943 lastFlipView = flipView;
3945 /* Draw highlights */
3946 if (pm1X >= 0 && pm1Y >= 0)
3948 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3950 if (pm2X >= 0 && pm2Y >= 0)
3952 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3954 if (hi1X >= 0 && hi1Y >= 0)
3956 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3958 if (hi2X >= 0 && hi2Y >= 0)
3960 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3963 /* If piece being dragged around board, must redraw that too */
3969 void AnimateUserMove (Widget w, XEvent * event,
3970 String * params, Cardinal * nParams)
3972 DragPieceMove(event->xmotion.x, event->xmotion.y);
3975 Widget CommentCreate(name, text, mutable, callback, lines)
3977 int /*Boolean*/ mutable;
3978 XtCallbackProc callback;
3982 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
3987 XtSetArg(args[j], XtNwidth, &bw_width); j++;
3988 XtGetValues(boardWidget, args, j);
3991 XtSetArg(args[j], XtNresizable, True); j++;
3994 XtCreatePopupShell(name, topLevelShellWidgetClass,
3995 shellWidget, args, j);
3998 XtCreatePopupShell(name, transientShellWidgetClass,
3999 shellWidget, args, j);
4002 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4003 layoutArgs, XtNumber(layoutArgs));
4005 XtCreateManagedWidget("form", formWidgetClass, layout,
4006 formArgs, XtNumber(formArgs));
4010 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4011 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4013 XtSetArg(args[j], XtNstring, text); j++;
4014 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4015 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4016 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4017 XtSetArg(args[j], XtNright, XtChainRight); j++;
4018 XtSetArg(args[j], XtNresizable, True); j++;
4019 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4020 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4021 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4022 XtSetArg(args[j], XtNautoFill, True); j++;
4023 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4025 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4029 XtSetArg(args[j], XtNfromVert, edit); j++;
4030 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4031 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4032 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4033 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4035 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4036 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4039 XtSetArg(args[j], XtNfromVert, edit); j++;
4040 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4041 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4042 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4043 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4044 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4046 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4047 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4050 XtSetArg(args[j], XtNfromVert, edit); j++;
4051 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4052 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4053 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4054 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4055 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4057 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4058 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4061 XtSetArg(args[j], XtNfromVert, edit); j++;
4062 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4063 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4064 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4065 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4067 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4068 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4071 XtSetArg(args[j], XtNfromVert, edit); j++;
4072 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4073 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4074 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4075 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4076 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4078 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4079 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4082 XtRealizeWidget(shell);
4084 if (commentX == -1) {
4087 Dimension pw_height;
4088 Dimension ew_height;
4091 XtSetArg(args[j], XtNheight, &ew_height); j++;
4092 XtGetValues(edit, args, j);
4095 XtSetArg(args[j], XtNheight, &pw_height); j++;
4096 XtGetValues(shell, args, j);
4097 commentH = pw_height + (lines - 1) * ew_height;
4098 commentW = bw_width - 16;
4100 XSync(xDisplay, False);
4102 /* This code seems to tickle an X bug if it is executed too soon
4103 after xboard starts up. The coordinates get transformed as if
4104 the main window was positioned at (0, 0).
4106 XtTranslateCoords(shellWidget,
4107 (bw_width - commentW) / 2, 0 - commentH / 2,
4108 &commentX, &commentY);
4110 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4111 RootWindowOfScreen(XtScreen(shellWidget)),
4112 (bw_width - commentW) / 2, 0 - commentH / 2,
4117 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4120 XtSetArg(args[j], XtNheight, commentH); j++;
4121 XtSetArg(args[j], XtNwidth, commentW); j++;
4122 XtSetArg(args[j], XtNx, commentX); j++;
4123 XtSetArg(args[j], XtNy, commentY); j++;
4124 XtSetValues(shell, args, j);
4125 XtSetKeyboardFocus(shell, edit);
4130 /* Used for analysis window and ICS input window */
4131 Widget MiscCreate(name, text, mutable, callback, lines)
4133 int /*Boolean*/ mutable;
4134 XtCallbackProc callback;
4138 Widget shell, layout, form, edit;
4140 Dimension bw_width, pw_height, ew_height, w, h;
4146 XtSetArg(args[j], XtNresizable, True); j++;
4149 XtCreatePopupShell(name, topLevelShellWidgetClass,
4150 shellWidget, args, j);
4153 XtCreatePopupShell(name, transientShellWidgetClass,
4154 shellWidget, args, j);
4157 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4158 layoutArgs, XtNumber(layoutArgs));
4160 XtCreateManagedWidget("form", formWidgetClass, layout,
4161 formArgs, XtNumber(formArgs));
4165 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4166 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4168 XtSetArg(args[j], XtNstring, text); j++;
4169 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4170 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4171 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4172 XtSetArg(args[j], XtNright, XtChainRight); j++;
4173 XtSetArg(args[j], XtNresizable, True); j++;
4174 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4175 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4176 XtSetArg(args[j], XtNautoFill, True); j++;
4177 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4179 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4181 XtRealizeWidget(shell);
4184 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4185 XtGetValues(boardWidget, args, j);
4188 XtSetArg(args[j], XtNheight, &ew_height); j++;
4189 XtGetValues(edit, args, j);
4192 XtSetArg(args[j], XtNheight, &pw_height); j++;
4193 XtGetValues(shell, args, j);
4194 h = pw_height + (lines - 1) * ew_height;
4197 XSync(xDisplay, False);
4199 /* This code seems to tickle an X bug if it is executed too soon
4200 after xboard starts up. The coordinates get transformed as if
4201 the main window was positioned at (0, 0).
4203 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4205 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4206 RootWindowOfScreen(XtScreen(shellWidget)),
4207 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4211 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4214 XtSetArg(args[j], XtNheight, h); j++;
4215 XtSetArg(args[j], XtNwidth, w); j++;
4216 XtSetArg(args[j], XtNx, x); j++;
4217 XtSetArg(args[j], XtNy, y); j++;
4218 XtSetValues(shell, args, j);
4224 static int savedIndex; /* gross that this is global */
4226 void EditCommentPopUp(index, title, text)
4235 if (text == NULL) text = "";
4237 if (editShell == NULL) {
4239 CommentCreate(title, text, True, EditCommentCallback, 4);
4240 XtRealizeWidget(editShell);
4241 CatchDeleteWindow(editShell, "EditCommentPopDown");
4243 edit = XtNameToWidget(editShell, "*form.text");
4245 XtSetArg(args[j], XtNstring, text); j++;
4246 XtSetValues(edit, args, j);
4248 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4249 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4250 XtSetValues(editShell, args, j);
4253 XtPopup(editShell, XtGrabNone);
4257 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4258 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4262 void EditCommentCallback(w, client_data, call_data)
4264 XtPointer client_data, call_data;
4272 XtSetArg(args[j], XtNlabel, &name); j++;
4273 XtGetValues(w, args, j);
4275 if (strcmp(name, _("ok")) == 0) {
4276 edit = XtNameToWidget(editShell, "*form.text");
4278 XtSetArg(args[j], XtNstring, &val); j++;
4279 XtGetValues(edit, args, j);
4280 ReplaceComment(savedIndex, val);
4281 EditCommentPopDown();
4282 } else if (strcmp(name, _("cancel")) == 0) {
4283 EditCommentPopDown();
4284 } else if (strcmp(name, _("clear")) == 0) {
4285 edit = XtNameToWidget(editShell, "*form.text");
4286 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4287 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4291 void EditCommentPopDown()
4296 if (!editUp) return;
4298 XtSetArg(args[j], XtNx, &commentX); j++;
4299 XtSetArg(args[j], XtNy, &commentY); j++;
4300 XtSetArg(args[j], XtNheight, &commentH); j++;
4301 XtSetArg(args[j], XtNwidth, &commentW); j++;
4302 XtGetValues(editShell, args, j);
4303 XtPopdown(editShell);
4306 XtSetArg(args[j], XtNleftBitmap, None); j++;
4307 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4311 void ICSInputBoxPopUp()
4316 char *title = _("ICS Input");
4319 if (ICSInputShell == NULL) {
4320 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4321 tr = XtParseTranslationTable(ICSInputTranslations);
4322 edit = XtNameToWidget(ICSInputShell, "*form.text");
4323 XtOverrideTranslations(edit, tr);
4324 XtRealizeWidget(ICSInputShell);
4325 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4328 edit = XtNameToWidget(ICSInputShell, "*form.text");
4330 XtSetArg(args[j], XtNstring, ""); j++;
4331 XtSetValues(edit, args, j);
4333 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4334 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4335 XtSetValues(ICSInputShell, args, j);
4338 XtPopup(ICSInputShell, XtGrabNone);
4339 XtSetKeyboardFocus(ICSInputShell, edit);
4341 ICSInputBoxUp = True;
4343 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4344 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4348 void ICSInputSendText()
4355 edit = XtNameToWidget(ICSInputShell, "*form.text");
4357 XtSetArg(args[j], XtNstring, &val); j++;
4358 XtGetValues(edit, args, j);
4359 SendMultiLineToICS(val);
4360 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4361 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4364 void ICSInputBoxPopDown()
4369 if (!ICSInputBoxUp) return;
4371 XtPopdown(ICSInputShell);
4372 ICSInputBoxUp = False;
4374 XtSetArg(args[j], XtNleftBitmap, None); j++;
4375 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4379 void CommentPopUp(title, text)
4386 if (commentShell == NULL) {
4388 CommentCreate(title, text, False, CommentCallback, 4);
4389 XtRealizeWidget(commentShell);
4390 CatchDeleteWindow(commentShell, "CommentPopDown");
4392 edit = XtNameToWidget(commentShell, "*form.text");
4394 XtSetArg(args[j], XtNstring, text); j++;
4395 XtSetValues(edit, args, j);
4397 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4398 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4399 XtSetValues(commentShell, args, j);
4402 XtPopup(commentShell, XtGrabNone);
4403 XSync(xDisplay, False);
4408 void CommentCallback(w, client_data, call_data)
4410 XtPointer client_data, call_data;
4417 XtSetArg(args[j], XtNlabel, &name); j++;
4418 XtGetValues(w, args, j);
4420 if (strcmp(name, _("close")) == 0) {
4422 } else if (strcmp(name, _("edit")) == 0) {
4429 void CommentPopDown()
4434 if (!commentUp) return;
4436 XtSetArg(args[j], XtNx, &commentX); j++;
4437 XtSetArg(args[j], XtNy, &commentY); j++;
4438 XtSetArg(args[j], XtNwidth, &commentW); j++;
4439 XtSetArg(args[j], XtNheight, &commentH); j++;
4440 XtGetValues(commentShell, args, j);
4441 XtPopdown(commentShell);
4442 XSync(xDisplay, False);
4446 void PromotionPopUp()
4449 Widget dialog, layout;
4451 Dimension bw_width, pw_width;
4455 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4456 XtGetValues(boardWidget, args, j);
4459 XtSetArg(args[j], XtNresizable, True); j++;
4460 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4462 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4463 shellWidget, args, j);
4465 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4466 layoutArgs, XtNumber(layoutArgs));
4469 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4470 XtSetArg(args[j], XtNborderWidth, 0); j++;
4471 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4474 if(gameInfo.variant != VariantShogi) {
4475 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4476 (XtPointer) dialog);
4477 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4478 (XtPointer) dialog);
4479 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4480 (XtPointer) dialog);
4481 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4482 (XtPointer) dialog);
4483 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4484 gameInfo.variant == VariantGiveaway) {
4485 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4486 (XtPointer) dialog);
4488 if(gameInfo.variant == VariantCapablanca ||
4489 gameInfo.variant == VariantGothic ||
4490 gameInfo.variant == VariantCapaRandom) {
4491 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4492 (XtPointer) dialog);
4493 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4494 (XtPointer) dialog);
4496 } else // [HGM] shogi
4498 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4499 (XtPointer) dialog);
4500 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4501 (XtPointer) dialog);
4503 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4504 (XtPointer) dialog);
4506 XtRealizeWidget(promotionShell);
4507 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4510 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4511 XtGetValues(promotionShell, args, j);
4513 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4514 lineGap + squareSize/3 +
4515 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4516 0 : 6*(squareSize + lineGap)), &x, &y);
4519 XtSetArg(args[j], XtNx, x); j++;
4520 XtSetArg(args[j], XtNy, y); j++;
4521 XtSetValues(promotionShell, args, j);
4523 XtPopup(promotionShell, XtGrabNone);
4528 void PromotionPopDown()
4530 if (!promotionUp) return;
4531 XtPopdown(promotionShell);
4532 XtDestroyWidget(promotionShell);
4533 promotionUp = False;
4536 void PromotionCallback(w, client_data, call_data)
4538 XtPointer client_data, call_data;
4544 XtSetArg(args[0], XtNlabel, &name);
4545 XtGetValues(w, args, 1);
4549 if (fromX == -1) return;
4551 if (strcmp(name, _("cancel")) == 0) {
4555 } else if (strcmp(name, _("Knight")) == 0) {
4557 } else if (strcmp(name, _("Promote")) == 0) {
4559 } else if (strcmp(name, _("Defer")) == 0) {
4562 promoChar = ToLower(name[0]);
4565 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
4567 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4568 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4573 void ErrorCallback(w, client_data, call_data)
4575 XtPointer client_data, call_data;
4578 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4580 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4586 if (!errorUp) return;
4590 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4592 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4597 void ErrorPopUp(title, label, modal)
4598 char *title, *label;
4601 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4602 GTK_DIALOG_DESTROY_WITH_PARENT,
4607 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4610 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4611 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4615 g_signal_connect_swapped (GUI_Error, "response",
4616 G_CALLBACK (ErrorPopDownProc),
4619 gtk_widget_show(GTK_WIDGET(GUI_Error));
4625 /* Disable all user input other than deleting the window */
4626 static int frozen = 0;
4630 /* Grab by a widget that doesn't accept input */
4631 // XtAddGrab(messageWidget, TRUE, FALSE);
4635 /* Undo a FreezeUI */
4638 if (!frozen) return;
4639 // XtRemoveGrab(messageWidget);
4643 char *ModeToWidgetName(mode)
4647 case BeginningOfGame:
4648 if (appData.icsActive)
4649 return "menuMode.ICS Client";
4650 else if (appData.noChessProgram ||
4651 *appData.cmailGameName != NULLCHAR)
4652 return "menuMode.Edit Game";
4654 return "menuMode.Machine Black";
4655 case MachinePlaysBlack:
4656 return "menuMode.Machine Black";
4657 case MachinePlaysWhite:
4658 return "menuMode.Machine White";
4660 return "menuMode.Analysis Mode";
4662 return "menuMode.Analyze File";
4663 case TwoMachinesPlay:
4664 return "menuMode.Two Machines";
4666 return "menuMode.Edit Game";
4667 case PlayFromGameFile:
4668 return "menuFile.Load Game";
4670 return "menuMode.Edit Position";
4672 return "menuMode.Training";
4673 case IcsPlayingWhite:
4674 case IcsPlayingBlack:
4678 return "menuMode.ICS Client";
4685 void ModeHighlight()
4687 static int oldPausing = FALSE;
4688 static GameMode oldmode = (GameMode) -1;
4691 // todo this toggling of the pause button doesn't seem to work?
4692 // e.g. select pause from buttonbar doesn't activate menumode.pause
4694 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4696 if (pausing != oldPausing) {
4697 oldPausing = pausing;
4698 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4699 /* toggle background color in showbuttonbar */
4700 if (appData.showButtonBar) {
4702 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4704 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4709 wname = ModeToWidgetName(oldmode);
4711 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4715 /* Maybe all the enables should be handled here, not just this one */
4716 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4717 gameMode == Training || gameMode == PlayFromGameFile);
4722 * Button/menu procedures
4725 int LoadGamePopUp(f, gameNumber, title)
4730 cmailMsgLoaded = FALSE;
4732 if (gameNumber == 0)
4734 int error = GameListBuild(f);
4738 DisplayError(_("Cannot build game list"), error);
4740 else if (!ListEmpty(&gameList)
4741 && ((ListGame *) gameList.tailPred)->number > 1)
4743 // TODO convert to GTK
4744 // GameListPopUp(f, title);
4752 return LoadGame(f, gameNumber, title, FALSE);
4755 void ReloadCmailMsgProc(w, event, prms, nprms)
4761 ReloadCmailMsgEvent(FALSE);
4764 void MailMoveProc(w, event, prms, nprms)
4773 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4774 static char *selected_fen_position=NULL;
4777 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4778 Atom *type_return, XtPointer *value_return,
4779 unsigned long *length_return, int *format_return)
4781 char *selection_tmp;
4783 if (!selected_fen_position) return False; /* should never happen */
4784 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4785 /* note: since no XtSelectionDoneProc was registered, Xt will
4786 * automatically call XtFree on the value returned. So have to
4787 * make a copy of it allocated with XtMalloc */
4788 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4789 strcpy(selection_tmp, selected_fen_position);
4791 *value_return=selection_tmp;
4792 *length_return=strlen(selection_tmp);
4793 *type_return=*target;
4794 *format_return = 8; /* bits per byte */
4796 } else if (*target == XA_TARGETS(xDisplay)) {
4797 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4798 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4799 targets_tmp[1] = XA_STRING;
4800 *value_return = targets_tmp;
4801 *type_return = XA_ATOM;
4803 *format_return = 8 * sizeof(Atom);
4804 if (*format_return > 32) {
4805 *length_return *= *format_return / 32;
4806 *format_return = 32;
4814 /* note: when called from menu all parameters are NULL, so no clue what the
4815 * Widget which was clicked on was, or what the click event was
4817 void CopyPositionProc(w, event, prms, nprms)
4824 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4825 * have a notion of a position that is selected but not copied.
4826 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4828 if (selected_fen_position) free(selected_fen_position);
4829 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
4830 if (!selected_fen_position) return;
4831 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4833 SendPositionSelection,
4834 NULL/* lose_ownership_proc */ ,
4835 NULL/* transfer_done_proc */);
4836 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4838 SendPositionSelection,
4839 NULL/* lose_ownership_proc */ ,
4840 NULL/* transfer_done_proc */);
4843 /* function called when the data to Paste is ready */
4845 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
4846 Atom *type, XtPointer value, unsigned long *len, int *format)
4849 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
4850 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
4851 EditPositionPasteFEN(fenstr);
4855 /* called when Paste Position button is pressed,
4856 * all parameters will be NULL */
4857 void PastePositionProc(w, event, prms, nprms)
4863 XtGetSelectionValue(menuBarWidget,
4864 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
4865 /* (XtSelectionCallbackProc) */ PastePositionCB,
4866 NULL, /* client_data passed to PastePositionCB */
4868 /* better to use the time field from the event that triggered the
4869 * call to this function, but that isn't trivial to get
4877 SendGameSelection(Widget w, Atom *selection, Atom *target,
4878 Atom *type_return, XtPointer *value_return,
4879 unsigned long *length_return, int *format_return)
4881 char *selection_tmp;
4883 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4884 FILE* f = fopen(gameCopyFilename, "r");
4887 if (f == NULL) return False;
4891 selection_tmp = XtMalloc(len + 1);
4892 count = fread(selection_tmp, 1, len, f);
4894 XtFree(selection_tmp);
4897 selection_tmp[len] = NULLCHAR;
4898 *value_return = selection_tmp;
4899 *length_return = len;
4900 *type_return = *target;
4901 *format_return = 8; /* bits per byte */
4903 } else if (*target == XA_TARGETS(xDisplay)) {
4904 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4905 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4906 targets_tmp[1] = XA_STRING;
4907 *value_return = targets_tmp;
4908 *type_return = XA_ATOM;
4910 *format_return = 8 * sizeof(Atom);
4911 if (*format_return > 32) {
4912 *length_return *= *format_return / 32;
4913 *format_return = 32;
4921 /* note: when called from menu all parameters are NULL, so no clue what the
4922 * Widget which was clicked on was, or what the click event was
4924 void CopyGameProc(w, event, prms, nprms)
4932 ret = SaveGameToFile(gameCopyFilename, FALSE);
4936 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4937 * have a notion of a game that is selected but not copied.
4938 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4940 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4943 NULL/* lose_ownership_proc */ ,
4944 NULL/* transfer_done_proc */);
4945 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4948 NULL/* lose_ownership_proc */ ,
4949 NULL/* transfer_done_proc */);
4952 /* function called when the data to Paste is ready */
4954 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
4955 Atom *type, XtPointer value, unsigned long *len, int *format)
4958 if (value == NULL || *len == 0) {
4959 return; /* nothing had been selected to copy */
4961 f = fopen(gamePasteFilename, "w");
4963 DisplayError(_("Can't open temp file"), errno);
4966 fwrite(value, 1, *len, f);
4969 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
4972 /* called when Paste Game button is pressed,
4973 * all parameters will be NULL */
4974 void PasteGameProc(w, event, prms, nprms)
4980 XtGetSelectionValue(menuBarWidget,
4981 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
4982 /* (XtSelectionCallbackProc) */ PasteGameCB,
4983 NULL, /* client_data passed to PasteGameCB */
4985 /* better to use the time field from the event that triggered the
4986 * call to this function, but that isn't trivial to get
4996 SaveGameProc(NULL, NULL);
5000 void AnalyzeModeProc(w, event, prms, nprms)
5008 if (!first.analysisSupport) {
5009 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5010 DisplayError(buf, 0);
5013 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5014 if (appData.icsActive) {
5015 if (gameMode != IcsObserving) {
5016 sprintf(buf,_("You are not observing a game"));
5017 DisplayError(buf, 0);
5019 if (appData.icsEngineAnalyze) {
5020 if (appData.debugMode)
5021 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5027 /* if enable, use want disable icsEngineAnalyze */
5028 if (appData.icsEngineAnalyze) {
5033 appData.icsEngineAnalyze = TRUE;
5034 if (appData.debugMode)
5035 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5037 if (!appData.showThinking)
5038 ShowThinkingProc(NULL,NULL);
5043 void EditGameProc(w, event, prms, nprms)
5052 void EditPositionProc(w, event, prms, nprms)
5058 EditPositionEvent();
5061 void TrainingProc(w, event, prms, nprms)
5070 void EditCommentProc(w, event, prms, nprms)
5077 EditCommentPopDown();
5083 void IcsInputBoxProc(w, event, prms, nprms)
5089 if (ICSInputBoxUp) {
5090 ICSInputBoxPopDown();
5097 void EnterKeyProc(w, event, prms, nprms)
5103 if (ICSInputBoxUp == True)
5108 void DebugProc(w, event, prms, nprms)
5114 appData.debugMode = !appData.debugMode;
5117 void AboutGameProc(w, event, prms, nprms)
5126 void NothingProc(w, event, prms, nprms)
5135 void Iconify(w, event, prms, nprms)
5144 XtSetArg(args[0], XtNiconic, True);
5145 XtSetValues(shellWidget, args, 1);
5148 void DisplayMessage(message, extMessage)
5149 gchar *message, *extMessage;
5156 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5159 message = extMessage;
5162 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5167 void DisplayTitle(text)
5170 gchar title[MSG_SIZ];
5172 if (text == NULL) text = "";
5174 if (appData.titleInWindow)
5179 if (*text != NULLCHAR)
5181 strcpy(title, text);
5183 else if (appData.icsActive)
5185 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5187 else if (appData.cmailGameName[0] != NULLCHAR)
5189 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5191 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5193 else if (gameInfo.variant == VariantGothic)
5195 strcpy(title, GOTHIC);
5199 else if (gameInfo.variant == VariantFalcon)
5201 strcpy(title, FALCON);
5204 else if (appData.noChessProgram)
5206 strcpy(title, programName);
5210 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5212 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5218 void DisplayError(message, error)
5225 if (appData.debugMode || appData.matchMode) {
5226 fprintf(stderr, "%s: %s\n", programName, message);
5229 if (appData.debugMode || appData.matchMode) {
5230 fprintf(stderr, "%s: %s: %s\n",
5231 programName, message, strerror(error));
5233 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5236 ErrorPopUp(_("Error"), message, FALSE);
5240 void DisplayMoveError(message)
5245 DrawPosition(FALSE, NULL);
5246 if (appData.debugMode || appData.matchMode) {
5247 fprintf(stderr, "%s: %s\n", programName, message);
5249 if (appData.popupMoveErrors) {
5250 ErrorPopUp(_("Error"), message, FALSE);
5252 DisplayMessage(message, "");
5257 void DisplayFatalError(message, error, status)
5263 errorExitStatus = status;
5265 fprintf(stderr, "%s: %s\n", programName, message);
5267 fprintf(stderr, "%s: %s: %s\n",
5268 programName, message, strerror(error));
5269 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5272 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5273 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5279 void DisplayInformation(message)
5283 ErrorPopUp(_("Information"), message, TRUE);
5286 void DisplayNote(message)
5290 ErrorPopUp(_("Note"), message, FALSE);
5294 NullXErrorCheck(dpy, error_event)
5296 XErrorEvent *error_event;
5301 void DisplayIcsInteractionTitle(message)
5304 if (oldICSInteractionTitle == NULL) {
5305 /* Magic to find the old window title, adapted from vim */
5306 char *wina = getenv("WINDOWID");
5308 Window win = (Window) atoi(wina);
5309 Window root, parent, *children;
5310 unsigned int nchildren;
5311 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5313 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5314 if (!XQueryTree(xDisplay, win, &root, &parent,
5315 &children, &nchildren)) break;
5316 if (children) XFree((void *)children);
5317 if (parent == root || parent == 0) break;
5320 XSetErrorHandler(oldHandler);
5322 if (oldICSInteractionTitle == NULL) {
5323 oldICSInteractionTitle = "xterm";
5326 printf("\033]0;%s\007", message);
5330 char pendingReplyPrefix[MSG_SIZ];
5331 ProcRef pendingReplyPR;
5333 void AskQuestionProc(w, event, prms, nprms)
5340 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5344 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5347 void AskQuestionPopDown()
5349 if (!askQuestionUp) return;
5350 XtPopdown(askQuestionShell);
5351 XtDestroyWidget(askQuestionShell);
5352 askQuestionUp = False;
5355 void AskQuestionReplyAction(w, event, prms, nprms)
5365 reply = XawDialogGetValueString(w = XtParent(w));
5366 strcpy(buf, pendingReplyPrefix);
5367 if (*buf) strcat(buf, " ");
5370 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5371 AskQuestionPopDown();
5373 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5376 void AskQuestionCallback(w, client_data, call_data)
5378 XtPointer client_data, call_data;
5383 XtSetArg(args[0], XtNlabel, &name);
5384 XtGetValues(w, args, 1);
5386 if (strcmp(name, _("cancel")) == 0) {
5387 AskQuestionPopDown();
5389 AskQuestionReplyAction(w, NULL, NULL, NULL);
5393 void AskQuestion(title, question, replyPrefix, pr)
5394 char *title, *question, *replyPrefix;
5398 Widget popup, layout, dialog, edit;
5404 strcpy(pendingReplyPrefix, replyPrefix);
5405 pendingReplyPR = pr;
5408 XtSetArg(args[i], XtNresizable, True); i++;
5409 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5410 askQuestionShell = popup =
5411 XtCreatePopupShell(title, transientShellWidgetClass,
5412 shellWidget, args, i);
5415 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5416 layoutArgs, XtNumber(layoutArgs));
5419 XtSetArg(args[i], XtNlabel, question); i++;
5420 XtSetArg(args[i], XtNvalue, ""); i++;
5421 XtSetArg(args[i], XtNborderWidth, 0); i++;
5422 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5425 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5426 (XtPointer) dialog);
5427 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5428 (XtPointer) dialog);
5430 XtRealizeWidget(popup);
5431 CatchDeleteWindow(popup, "AskQuestionPopDown");
5433 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5434 &x, &y, &win_x, &win_y, &mask);
5436 XtSetArg(args[0], XtNx, x - 10);
5437 XtSetArg(args[1], XtNy, y - 30);
5438 XtSetValues(popup, args, 2);
5440 XtPopup(popup, XtGrabExclusive);
5441 askQuestionUp = True;
5443 edit = XtNameToWidget(dialog, "*value");
5444 XtSetKeyboardFocus(popup, edit);
5452 if (*name == NULLCHAR) {
5454 } else if (strcmp(name, "$") == 0) {
5455 putc(BELLCHAR, stderr);
5458 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
5466 PlaySound(appData.soundMove);
5472 PlaySound(appData.soundIcsWin);
5478 PlaySound(appData.soundIcsLoss);
5484 PlaySound(appData.soundIcsDraw);
5488 PlayIcsUnfinishedSound()
5490 PlaySound(appData.soundIcsUnfinished);
5496 PlaySound(appData.soundIcsAlarm);
5502 system("stty echo");
5508 system("stty -echo");
5512 Colorize(cc, continuation)
5517 int count, outCount, error;
5519 if (textColors[(int)cc].bg > 0) {
5520 if (textColors[(int)cc].fg > 0) {
5521 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
5522 textColors[(int)cc].fg, textColors[(int)cc].bg);
5524 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5525 textColors[(int)cc].bg);
5528 if (textColors[(int)cc].fg > 0) {
5529 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5530 textColors[(int)cc].fg);
5532 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
5535 count = strlen(buf);
5536 outCount = OutputToProcess(NoProc, buf, count, &error);
5537 if (outCount < count) {
5538 DisplayFatalError(_("Error writing to display"), error, 1);
5541 if (continuation) return;
5544 PlaySound(appData.soundShout);
5547 PlaySound(appData.soundSShout);
5550 PlaySound(appData.soundChannel1);
5553 PlaySound(appData.soundChannel);
5556 PlaySound(appData.soundKibitz);
5559 PlaySound(appData.soundTell);
5561 case ColorChallenge:
5562 PlaySound(appData.soundChallenge);
5565 PlaySound(appData.soundRequest);
5568 PlaySound(appData.soundSeek);
5579 return getpwuid(getuid())->pw_name;
5582 static char *ExpandPathName(path)
5585 static char static_buf[2000];
5586 char *d, *s, buf[2000];
5592 while (*s && isspace(*s))
5601 if (*(s+1) == '/') {
5602 strcpy(d, getpwuid(getuid())->pw_dir);
5607 *strchr(buf, '/') = 0;
5608 pwd = getpwnam(buf);
5611 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
5615 strcpy(d, pwd->pw_dir);
5616 strcat(d, strchr(s+1, '/'));
5627 static char host_name[MSG_SIZ];
5629 #if HAVE_GETHOSTNAME
5630 gethostname(host_name, MSG_SIZ);
5632 #else /* not HAVE_GETHOSTNAME */
5633 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
5634 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
5636 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5638 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5639 #endif /* not HAVE_GETHOSTNAME */
5642 guint delayedEventTimerTag = 0;
5643 DelayedEventCallback delayedEventCallback = 0;
5646 FireDelayedEvent(data)
5650 g_source_remove(delayedEventTimerTag);
5651 delayedEventTimerTag = 0;
5654 delayedEventCallback();
5660 ScheduleDelayedEvent(cb, millisec)
5661 DelayedEventCallback cb; guint millisec;
5663 if(delayedEventTimerTag && delayedEventCallback == cb)
5664 // [HGM] alive: replace, rather than add or flush identical event
5665 g_source_remove(delayedEventTimerTag);
5666 delayedEventCallback = cb;
5667 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
5671 DelayedEventCallback
5674 if (delayedEventTimerTag)
5676 return delayedEventCallback;
5685 CancelDelayedEvent()
5687 if (delayedEventTimerTag)
5689 g_source_remove(delayedEventTimerTag);
5690 delayedEventTimerTag = 0;
5696 guint loadGameTimerTag = 0;
5698 int LoadGameTimerRunning()
5700 return loadGameTimerTag != 0;
5703 int StopLoadGameTimer()
5705 if (loadGameTimerTag != 0) {
5706 g_source_remove(loadGameTimerTag);
5707 loadGameTimerTag = 0;
5715 LoadGameTimerCallback(data)
5719 g_source_remove(loadGameTimerTag);
5720 loadGameTimerTag = 0;
5727 StartLoadGameTimer(millisec)
5731 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
5735 guint analysisClockTag = 0;
5738 AnalysisClockCallback(data)
5741 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
5742 || appData.icsEngineAnalyze)
5744 AnalysisPeriodicEvent(0);
5745 return 1; /* keep on going */
5747 return 0; /* stop timer */
5751 StartAnalysisClock()
5754 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
5758 guint clockTimerTag = 0;
5760 int ClockTimerRunning()
5762 return clockTimerTag != 0;
5765 int StopClockTimer()
5767 if (clockTimerTag != 0)
5769 g_source_remove(clockTimerTag);
5780 ClockTimerCallback(data)
5784 g_source_remove(clockTimerTag);
5792 StartClockTimer(millisec)
5795 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
5800 DisplayTimerLabel(w, color, timer, highlight)
5809 if (appData.clockMode) {
5810 sprintf(buf, "%s: %s", color, TimeString(timer));
5812 sprintf(buf, "%s ", color);
5814 gtk_label_set_text(GTK_LABEL(w),buf);
5816 /* check for low time warning */
5817 // Pixel foregroundOrWarningColor = timerForegroundPixel;
5820 // appData.lowTimeWarning &&
5821 // (timer / 1000) < appData.icsAlarmTime)
5822 // foregroundOrWarningColor = lowTimeWarningColor;
5824 // if (appData.clockMode) {
5825 // sprintf(buf, "%s: %s", color, TimeString(timer));
5826 // XtSetArg(args[0], XtNlabel, buf);
5828 // sprintf(buf, "%s ", color);
5829 // XtSetArg(args[0], XtNlabel, buf);
5834 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
5835 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
5837 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
5838 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
5841 // XtSetValues(w, args, 3);
5846 DisplayWhiteClock(timeRemaining, highlight)
5850 if(appData.noGUI) return;
5852 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
5853 if (highlight && WindowIcon == BlackIcon)
5855 WindowIcon = WhiteIcon;
5856 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5861 DisplayBlackClock(timeRemaining, highlight)
5865 if(appData.noGUI) return;
5867 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
5868 if (highlight && WindowIcon == WhiteIcon)
5870 WindowIcon = BlackIcon;
5871 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
5889 int StartChildProcess(cmdLine, dir, pr)
5896 int to_prog[2], from_prog[2];
5900 if (appData.debugMode) {
5901 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
5904 /* We do NOT feed the cmdLine to the shell; we just
5905 parse it into blank-separated arguments in the
5906 most simple-minded way possible.
5909 strcpy(buf, cmdLine);
5914 if (p == NULL) break;
5919 SetUpChildIO(to_prog, from_prog);
5921 if ((pid = fork()) == 0) {
5923 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
5924 close(to_prog[1]); // first close the unused pipe ends
5925 close(from_prog[0]);
5926 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
5927 dup2(from_prog[1], 1);
5928 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
5929 close(from_prog[1]); // and closing again loses one of the pipes!
5930 if(fileno(stderr) >= 2) // better safe than sorry...
5931 dup2(1, fileno(stderr)); /* force stderr to the pipe */
5933 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
5938 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
5940 execvp(argv[0], argv);
5942 /* If we get here, exec failed */
5947 /* Parent process */
5949 close(from_prog[1]);
5951 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
5954 cp->fdFrom = from_prog[0];
5955 cp->fdTo = to_prog[1];
5960 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
5961 static RETSIGTYPE AlarmCallBack(int n)
5967 DestroyChildProcess(pr, signalType)
5971 ChildProc *cp = (ChildProc *) pr;
5973 if (cp->kind != CPReal) return;
5975 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
5976 signal(SIGALRM, AlarmCallBack);
5978 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
5979 kill(cp->pid, SIGKILL); // kill it forcefully
5980 wait((int *) 0); // and wait again
5984 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
5986 /* Process is exiting either because of the kill or because of
5987 a quit command sent by the backend; either way, wait for it to die.
5996 InterruptChildProcess(pr)
5999 ChildProc *cp = (ChildProc *) pr;
6001 if (cp->kind != CPReal) return;
6002 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6005 int OpenTelnet(host, port, pr)
6010 char cmdLine[MSG_SIZ];
6012 if (port[0] == NULLCHAR) {
6013 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6015 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6017 return StartChildProcess(cmdLine, "", pr);
6020 int OpenTCP(host, port, pr)
6026 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6027 #else /* !OMIT_SOCKETS */
6029 struct sockaddr_in sa;
6031 unsigned short uport;
6034 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6038 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6039 sa.sin_family = AF_INET;
6040 sa.sin_addr.s_addr = INADDR_ANY;
6041 uport = (unsigned short) 0;
6042 sa.sin_port = htons(uport);
6043 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6047 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6048 if (!(hp = gethostbyname(host))) {
6050 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6051 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6052 hp->h_addrtype = AF_INET;
6054 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6055 hp->h_addr_list[0] = (char *) malloc(4);
6056 hp->h_addr_list[0][0] = b0;
6057 hp->h_addr_list[0][1] = b1;
6058 hp->h_addr_list[0][2] = b2;
6059 hp->h_addr_list[0][3] = b3;
6064 sa.sin_family = hp->h_addrtype;
6065 uport = (unsigned short) atoi(port);
6066 sa.sin_port = htons(uport);
6067 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6069 if (connect(s, (struct sockaddr *) &sa,
6070 sizeof(struct sockaddr_in)) < 0) {
6074 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6081 #endif /* !OMIT_SOCKETS */
6086 int OpenCommPort(name, pr)
6093 fd = open(name, 2, 0);
6094 if (fd < 0) return errno;
6096 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6106 int OpenLoopback(pr)
6112 SetUpChildIO(to, from);
6114 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6117 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6124 int OpenRcmd(host, user, cmd, pr)
6125 char *host, *user, *cmd;
6128 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6132 #define INPUT_SOURCE_BUF_SIZE 8192
6141 char buf[INPUT_SOURCE_BUF_SIZE];
6146 DoInputCallback(io,cond,data)
6151 /* read input from one of the input source (for example a chess program, ICS, etc).
6152 * and call a function that will handle the input
6155 int count; /* how many bytes did we read */
6159 /* All information (callback function, file descriptor, etc) is
6160 * saved in an InputSource structure
6162 InputSource *is = (InputSource *) data;
6166 count = read(is->fd, is->unused,
6167 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6171 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6174 is->unused += count;
6176 /* break input into lines and call the callback function on each
6179 while (p < is->unused)
6181 q = memchr(p, '\n', is->unused - p);
6182 if (q == NULL) break;
6184 (is->func)(is, is->closure, p, q - p, 0);
6187 /* remember not yet used part of the buffer */
6189 while (p < is->unused)
6197 /* read maximum length of input buffer and send the whole buffer
6198 * to the callback function
6200 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6205 (is->func)(is, is->closure, is->buf, count, error);
6211 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6218 GIOChannel *channel;
6219 ChildProc *cp = (ChildProc *) pr;
6221 is = (InputSource *) calloc(1, sizeof(InputSource));
6222 is->lineByLine = lineByLine;
6226 is->fd = fileno(stdin);
6228 is->kind = cp->kind;
6229 is->fd = cp->fdFrom;
6232 is->unused = is->buf;
6236 // is->xid = XtAppAddInput(appContext, is->fd,
6237 // (XtPointer) (XtInputReadMask),
6238 // (XtInputCallbackProc) DoInputCallback,
6242 /* TODO: will this work on windows?*/
6243 printf("DEBUG: fd=%d %d\n",is->fd,is);
6245 channel = g_io_channel_unix_new(is->fd);
6246 g_io_channel_set_close_on_unref (channel, TRUE);
6247 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6248 is->closure = closure;
6249 return (InputSourceRef) is;
6253 RemoveInputSource(isr)
6256 InputSource *is = (InputSource *) isr;
6258 if (is->sid == 0) return;
6259 g_source_remove(is->sid);
6264 int OutputToProcess(pr, message, count, outError)
6270 static int line = 0;
6271 ChildProc *cp = (ChildProc *) pr;
6276 if (appData.noJoin || !appData.useInternalWrap)
6277 outCount = fwrite(message, 1, count, stdout);
6280 int width = get_term_width();
6281 int len = wrap(NULL, message, count, width, &line);
6282 char *msg = malloc(len);
6286 outCount = fwrite(message, 1, count, stdout);
6289 dbgchk = wrap(msg, message, count, width, &line);
6290 if (dbgchk != len && appData.debugMode)
6291 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
6292 outCount = fwrite(msg, 1, dbgchk, stdout);
6298 outCount = write(cp->fdTo, message, count);
6308 /* Output message to process, with "ms" milliseconds of delay
6309 between each character. This is needed when sending the logon
6310 script to ICC, which for some reason doesn't like the
6311 instantaneous send. */
6312 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6319 ChildProc *cp = (ChildProc *) pr;
6324 r = write(cp->fdTo, message++, 1);
6337 /**** Animation code by Hugh Fisher, DCS, ANU.
6339 Known problem: if a window overlapping the board is
6340 moved away while a piece is being animated underneath,
6341 the newly exposed area won't be updated properly.
6342 I can live with this.
6344 Known problem: if you look carefully at the animation
6345 of pieces in mono mode, they are being drawn as solid
6346 shapes without interior detail while moving. Fixing
6347 this would be a major complication for minimal return.
6350 /* Masks for XPM pieces. Black and white pieces can have
6351 different shapes, but in the interest of retaining my
6352 sanity pieces must have the same outline on both light
6353 and dark squares, and all pieces must use the same
6354 background square colors/images. */
6356 static int xpmDone = 0;
6359 CreateAnimMasks (pieceDepth)
6366 unsigned long plane;
6369 /* just return for gtk at the moment */
6372 /* Need a bitmap just to get a GC with right depth */
6373 buf = XCreatePixmap(xDisplay, xBoardWindow,
6375 values.foreground = 1;
6376 values.background = 0;
6377 /* Don't use XtGetGC, not read only */
6378 maskGC = XCreateGC(xDisplay, buf,
6379 GCForeground | GCBackground, &values);
6380 XFreePixmap(xDisplay, buf);
6382 buf = XCreatePixmap(xDisplay, xBoardWindow,
6383 squareSize, squareSize, pieceDepth);
6384 values.foreground = XBlackPixel(xDisplay, xScreen);
6385 values.background = XWhitePixel(xDisplay, xScreen);
6386 bufGC = XCreateGC(xDisplay, buf,
6387 GCForeground | GCBackground, &values);
6389 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6390 /* Begin with empty mask */
6391 if(!xpmDone) // [HGM] pieces: keep using existing
6392 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6393 squareSize, squareSize, 1);
6394 XSetFunction(xDisplay, maskGC, GXclear);
6395 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6396 0, 0, squareSize, squareSize);
6398 /* Take a copy of the piece */
6403 XSetFunction(xDisplay, bufGC, GXcopy);
6404 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6406 0, 0, squareSize, squareSize, 0, 0);
6408 /* XOR the background (light) over the piece */
6409 XSetFunction(xDisplay, bufGC, GXxor);
6411 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6412 0, 0, squareSize, squareSize, 0, 0);
6414 XSetForeground(xDisplay, bufGC, lightSquareColor);
6415 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6418 /* We now have an inverted piece image with the background
6419 erased. Construct mask by just selecting all the non-zero
6420 pixels - no need to reconstruct the original image. */
6421 XSetFunction(xDisplay, maskGC, GXor);
6423 /* Might be quicker to download an XImage and create bitmap
6424 data from it rather than this N copies per piece, but it
6425 only takes a fraction of a second and there is a much
6426 longer delay for loading the pieces. */
6427 for (n = 0; n < pieceDepth; n ++) {
6428 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6429 0, 0, squareSize, squareSize,
6435 XFreePixmap(xDisplay, buf);
6436 XFreeGC(xDisplay, bufGC);
6437 XFreeGC(xDisplay, maskGC);
6441 InitAnimState (anim, info)
6443 XWindowAttributes * info;
6448 /* Each buffer is square size, same depth as window */
6449 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6450 // squareSize, squareSize, info->depth);
6451 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6452 // squareSize, squareSize, info->depth);
6454 // /* Create a plain GC for blitting */
6455 // mask = GCForeground | GCBackground | GCFunction |
6456 // GCPlaneMask | GCGraphicsExposures;
6457 // values.foreground = XBlackPixel(xDisplay, xScreen);
6458 // values.background = XWhitePixel(xDisplay, xScreen);
6459 // values.function = GXcopy;
6460 // values.plane_mask = AllPlanes;
6461 // values.graphics_exposures = False;
6462 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
6464 // /* Piece will be copied from an existing context at
6465 // the start of each new animation/drag. */
6466 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
6468 // /* Outline will be a read-only copy of an existing */
6469 // anim->outlineGC = None;
6475 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
6476 XWindowAttributes info;
6478 /* for gtk at the moment just ... */
6481 if (xpmDone && gameInfo.variant == old) return;
6482 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
6483 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
6485 // InitAnimState(&game, &info);
6486 // InitAnimState(&player, &info);
6488 /* For XPM pieces, we need bitmaps to use as masks. */
6490 // CreateAnimMasks(info.depth);
6496 static Boolean frameWaiting;
6498 static RETSIGTYPE FrameAlarm (sig)
6501 frameWaiting = False;
6502 /* In case System-V style signals. Needed?? */
6503 signal(SIGALRM, FrameAlarm);
6510 struct itimerval delay;
6512 XSync(xDisplay, False);
6515 frameWaiting = True;
6516 signal(SIGALRM, FrameAlarm);
6517 delay.it_interval.tv_sec =
6518 delay.it_value.tv_sec = time / 1000;
6519 delay.it_interval.tv_usec =
6520 delay.it_value.tv_usec = (time % 1000) * 1000;
6521 setitimer(ITIMER_REAL, &delay, NULL);
6522 while (frameWaiting) pause();
6523 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
6524 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
6525 setitimer(ITIMER_REAL, &delay, NULL);
6535 // XSync(xDisplay, False);
6537 usleep(time * 1000);
6542 /* Convert board position to corner of screen rect and color */
6545 ScreenSquare(column, row, pt, color)
6546 int column; int row; XPoint * pt; int * color;
6549 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
6550 pt->y = lineGap + row * (squareSize + lineGap);
6552 pt->x = lineGap + column * (squareSize + lineGap);
6553 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
6555 *color = SquareColor(row, column);
6558 /* Convert window coords to square */
6561 BoardSquare(x, y, column, row)
6562 int x; int y; int * column; int * row;
6564 *column = EventToSquare(x, BOARD_WIDTH);
6565 if (flipView && *column >= 0)
6566 *column = BOARD_WIDTH - 1 - *column;
6567 *row = EventToSquare(y, BOARD_HEIGHT);
6568 if (!flipView && *row >= 0)
6569 *row = BOARD_HEIGHT - 1 - *row;
6574 #undef Max /* just in case */
6576 #define Max(a, b) ((a) > (b) ? (a) : (b))
6577 #define Min(a, b) ((a) < (b) ? (a) : (b))
6580 SetRect(rect, x, y, width, height)
6581 XRectangle * rect; int x; int y; int width; int height;
6585 rect->width = width;
6586 rect->height = height;
6589 /* Test if two frames overlap. If they do, return
6590 intersection rect within old and location of
6591 that rect within new. */
6594 Intersect(old, new, size, area, pt)
6595 XPoint * old; XPoint * new;
6596 int size; XRectangle * area; XPoint * pt;
6598 if (old->x > new->x + size || new->x > old->x + size ||
6599 old->y > new->y + size || new->y > old->y + size) {
6602 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
6603 size - abs(old->x - new->x), size - abs(old->y - new->y));
6604 pt->x = Max(old->x - new->x, 0);
6605 pt->y = Max(old->y - new->y, 0);
6610 /* For two overlapping frames, return the rect(s)
6611 in the old that do not intersect with the new. */
6614 CalcUpdateRects(old, new, size, update, nUpdates)
6615 XPoint * old; XPoint * new; int size;
6616 XRectangle update[]; int * nUpdates;
6620 /* If old = new (shouldn't happen) then nothing to draw */
6621 if (old->x == new->x && old->y == new->y) {
6625 /* Work out what bits overlap. Since we know the rects
6626 are the same size we don't need a full intersect calc. */
6628 /* Top or bottom edge? */
6629 if (new->y > old->y) {
6630 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
6632 } else if (old->y > new->y) {
6633 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
6634 size, old->y - new->y);
6637 /* Left or right edge - don't overlap any update calculated above. */
6638 if (new->x > old->x) {
6639 SetRect(&(update[count]), old->x, Max(new->y, old->y),
6640 new->x - old->x, size - abs(new->y - old->y));
6642 } else if (old->x > new->x) {
6643 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
6644 old->x - new->x, size - abs(new->y - old->y));
6651 /* Generate a series of frame coords from start->mid->finish.
6652 The movement rate doubles until the half way point is
6653 reached, then halves back down to the final destination,
6654 which gives a nice slow in/out effect. The algorithmn
6655 may seem to generate too many intermediates for short
6656 moves, but remember that the purpose is to attract the
6657 viewers attention to the piece about to be moved and
6658 then to where it ends up. Too few frames would be less
6662 Tween(start, mid, finish, factor, frames, nFrames)
6663 XPoint * start; XPoint * mid;
6664 XPoint * finish; int factor;
6665 XPoint frames[]; int * nFrames;
6667 int fraction, n, count;
6671 /* Slow in, stepping 1/16th, then 1/8th, ... */
6673 for (n = 0; n < factor; n++)
6675 for (n = 0; n < factor; n++) {
6676 frames[count].x = start->x + (mid->x - start->x) / fraction;
6677 frames[count].y = start->y + (mid->y - start->y) / fraction;
6679 fraction = fraction / 2;
6683 frames[count] = *mid;
6686 /* Slow out, stepping 1/2, then 1/4, ... */
6688 for (n = 0; n < factor; n++) {
6689 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
6690 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
6692 fraction = fraction * 2;
6697 /* Draw a piece on the screen without disturbing what's there */
6700 SelectGCMask(piece, clip, outline, mask)
6701 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
6705 /* Bitmap for piece being moved. */
6706 if (appData.monoMode) {
6707 *mask = *pieceToSolid(piece);
6708 } else if (useImages) {
6710 *mask = xpmMask[piece];
6712 *mask = ximMaskPm[piece];
6715 *mask = *pieceToSolid(piece);
6718 /* GC for piece being moved. Square color doesn't matter, but
6719 since it gets modified we make a copy of the original. */
6721 if (appData.monoMode)
6726 if (appData.monoMode)
6731 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
6733 /* Outline only used in mono mode and is not modified */
6735 *outline = bwPieceGC;
6737 *outline = wbPieceGC;
6741 OverlayPiece(piece, clip, outline, dest)
6742 ChessSquare piece; GC clip; GC outline; Drawable dest;
6747 /* Draw solid rectangle which will be clipped to shape of piece */
6748 // XFillRectangle(xDisplay, dest, clip,
6749 // 0, 0, squareSize, squareSize)
6751 if (appData.monoMode)
6752 /* Also draw outline in contrasting color for black
6753 on black / white on white cases */
6754 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
6755 // 0, 0, squareSize, squareSize, 0, 0, 1)
6758 /* Copy the piece */
6763 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
6765 // 0, 0, squareSize, squareSize,
6770 /* Animate the movement of a single piece */
6773 BeginAnimation(anim, piece, startColor, start)
6781 /* The old buffer is initialised with the start square (empty) */
6782 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
6783 anim->prevFrame = *start;
6785 /* The piece will be drawn using its own bitmap as a matte */
6786 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
6787 // XSetClipMask(xDisplay, anim->pieceGC, mask);
6791 AnimationFrame(anim, frame, piece)
6796 XRectangle updates[4];
6801 /* Save what we are about to draw into the new buffer */
6802 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
6803 // frame->x, frame->y, squareSize, squareSize,
6806 /* Erase bits of the previous frame */
6807 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
6808 /* Where the new frame overlapped the previous,
6809 the contents in newBuf are wrong. */
6810 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
6811 // overlap.x, overlap.y,
6812 // overlap.width, overlap.height,
6814 /* Repaint the areas in the old that don't overlap new */
6815 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
6816 for (i = 0; i < count; i++)
6817 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6818 // updates[i].x - anim->prevFrame.x,
6819 // updates[i].y - anim->prevFrame.y,
6820 // updates[i].width, updates[i].height,
6821 // updates[i].x, updates[i].y)
6824 /* Easy when no overlap */
6825 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6826 // 0, 0, squareSize, squareSize,
6827 // anim->prevFrame.x, anim->prevFrame.y);
6830 /* Save this frame for next time round */
6831 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
6832 // 0, 0, squareSize, squareSize,
6834 anim->prevFrame = *frame;
6836 /* Draw piece over original screen contents, not current,
6837 and copy entire rect. Wipes out overlapping piece images. */
6838 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
6839 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
6840 // 0, 0, squareSize, squareSize,
6841 // frame->x, frame->y);
6845 EndAnimation (anim, finish)
6849 XRectangle updates[4];
6854 /* The main code will redraw the final square, so we
6855 only need to erase the bits that don't overlap. */
6856 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
6857 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
6858 for (i = 0; i < count; i++)
6859 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6860 // updates[i].x - anim->prevFrame.x,
6861 // updates[i].y - anim->prevFrame.y,
6862 // updates[i].width, updates[i].height,
6863 // updates[i].x, updates[i].y)
6866 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6867 // 0, 0, squareSize, squareSize,
6868 // anim->prevFrame.x, anim->prevFrame.y);
6873 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
6875 ChessSquare piece; int startColor;
6876 XPoint * start; XPoint * finish;
6877 XPoint frames[]; int nFrames;
6881 BeginAnimation(anim, piece, startColor, start);
6882 for (n = 0; n < nFrames; n++) {
6883 AnimationFrame(anim, &(frames[n]), piece);
6884 FrameDelay(appData.animSpeed);
6886 EndAnimation(anim, finish);
6889 /* Main control logic for deciding what to animate and how */
6892 AnimateMove(board, fromX, fromY, toX, toY)
6901 XPoint start, finish, mid;
6902 XPoint frames[kFactor * 2 + 1];
6903 int nFrames, startColor, endColor;
6905 /* Are we animating? */
6906 if (!appData.animate || appData.blindfold)
6909 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
6910 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
6911 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
6913 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
6914 piece = board[fromY][fromX];
6915 if (piece >= EmptySquare) return;
6920 hop = (piece == WhiteKnight || piece == BlackKnight);
6923 if (appData.debugMode) {
6924 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
6925 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
6926 piece, fromX, fromY, toX, toY); }
6928 ScreenSquare(fromX, fromY, &start, &startColor);
6929 ScreenSquare(toX, toY, &finish, &endColor);
6932 /* Knight: make diagonal movement then straight */
6933 if (abs(toY - fromY) < abs(toX - fromX)) {
6934 mid.x = start.x + (finish.x - start.x) / 2;
6938 mid.y = start.y + (finish.y - start.y) / 2;
6941 mid.x = start.x + (finish.x - start.x) / 2;
6942 mid.y = start.y + (finish.y - start.y) / 2;
6945 /* Don't use as many frames for very short moves */
6946 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
6947 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
6949 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
6950 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
6952 /* Be sure end square is redrawn */
6953 damage[toY][toX] = True;
6957 DragPieceBegin(x, y)
6960 int boardX, boardY, color;
6963 /* Are we animating? */
6964 if (!appData.animateDragging || appData.blindfold)
6967 /* Figure out which square we start in and the
6968 mouse position relative to top left corner. */
6969 BoardSquare(x, y, &boardX, &boardY);
6970 player.startBoardX = boardX;
6971 player.startBoardY = boardY;
6972 ScreenSquare(boardX, boardY, &corner, &color);
6973 player.startSquare = corner;
6974 player.startColor = color;
6975 /* As soon as we start dragging, the piece will jump slightly to
6976 be centered over the mouse pointer. */
6977 player.mouseDelta.x = squareSize/2;
6978 player.mouseDelta.y = squareSize/2;
6979 /* Initialise animation */
6980 player.dragPiece = PieceForSquare(boardX, boardY);
6982 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
6983 player.dragActive = True;
6984 BeginAnimation(&player, player.dragPiece, color, &corner);
6985 /* Mark this square as needing to be redrawn. Note that
6986 we don't remove the piece though, since logically (ie
6987 as seen by opponent) the move hasn't been made yet. */
6988 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
6989 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
6990 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
6991 // corner.x, corner.y, squareSize, squareSize,
6992 // 0, 0); // [HGM] zh: unstack in stead of grab
6993 damage[boardY][boardX] = True;
6995 player.dragActive = False;
7005 /* Are we animating? */
7006 if (!appData.animateDragging || appData.blindfold)
7010 if (! player.dragActive)
7012 /* Move piece, maintaining same relative position
7013 of mouse within square */
7014 corner.x = x - player.mouseDelta.x;
7015 corner.y = y - player.mouseDelta.y;
7016 AnimationFrame(&player, &corner, player.dragPiece);
7018 if (appData.highlightDragging) {
7020 BoardSquare(x, y, &boardX, &boardY);
7021 SetHighlights(fromX, fromY, boardX, boardY);
7030 int boardX, boardY, color;
7033 /* Are we animating? */
7034 if (!appData.animateDragging || appData.blindfold)
7038 if (! player.dragActive)
7040 /* Last frame in sequence is square piece is
7041 placed on, which may not match mouse exactly. */
7042 BoardSquare(x, y, &boardX, &boardY);
7043 ScreenSquare(boardX, boardY, &corner, &color);
7044 EndAnimation(&player, &corner);
7046 /* Be sure end square is redrawn */
7047 damage[boardY][boardX] = True;
7049 /* This prevents weird things happening with fast successive
7050 clicks which on my Sun at least can cause motion events
7051 without corresponding press/release. */
7052 player.dragActive = False;
7055 /* Handle expose event while piece being dragged */
7060 if (!player.dragActive || appData.blindfold)
7063 /* What we're doing: logically, the move hasn't been made yet,
7064 so the piece is still in it's original square. But visually
7065 it's being dragged around the board. So we erase the square
7066 that the piece is on and draw it at the last known drag point. */
7067 BlankSquare(player.startSquare.x, player.startSquare.y,
7068 player.startColor, EmptySquare, xBoardWindow);
7069 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7070 damage[player.startBoardY][player.startBoardX] = TRUE;
7074 SetProgramStats( FrontEndProgramStats * stats )
7077 // [HGM] done, but perhaps backend should call this directly?
7078 EngineOutputUpdate( stats );
7081 #include <sys/ioctl.h>
7082 int get_term_width()
7084 int fd, default_width;
7087 default_width = 79; // this is FICS default anyway...
7089 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7091 if (!ioctl(fd, TIOCGSIZE, &win))
7092 default_width = win.ts_cols;
7093 #elif defined(TIOCGWINSZ)
7095 if (!ioctl(fd, TIOCGWINSZ, &win))
7096 default_width = win.ws_col;
7098 return default_width;
7101 void update_ics_width()
7103 static int old_width = 0;
7104 int new_width = get_term_width();
7106 if (old_width != new_width)
7107 ics_printf("set width %d\n", new_width);
7108 old_width = new_width;
7111 void NotifyFrontendLogin()