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 HandleUserMove P((Widget w, XEvent *event,
264 String *prms, Cardinal *nprms));
265 void AnimateUserMove P((Widget w, XEvent * event,
266 String * params, Cardinal * nParams));
267 void CommentPopUp P((char *title, char *label));
268 void CommentPopDown P((void));
269 void CommentCallback P((Widget w, XtPointer client_data,
270 XtPointer call_data));
271 void ICSInputBoxPopUp P((void));
272 void ICSInputBoxPopDown P((void));
273 void AskQuestionReplyAction P((Widget w, XEvent *event,
274 String *prms, Cardinal *nprms));
275 void AskQuestionProc P((Widget w, XEvent *event,
276 String *prms, Cardinal *nprms));
277 void AskQuestionPopDown P((void));
278 void PromotionPopDown P((void));
279 void PromotionCallback P((Widget w, XtPointer client_data,
280 XtPointer call_data));
281 void EditCommentPopDown P((void));
282 void EditCommentCallback P((Widget w, XtPointer client_data,
283 XtPointer call_data));
284 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
285 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
287 void PastePositionProc P((Widget w, XEvent *event, String *prms,
289 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
290 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
291 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
294 void AnalyzeModeProc P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
297 void EditPositionProc P((Widget w, XEvent *event,
298 String *prms, Cardinal *nprms));
299 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void EditCommentProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void IcsInputBoxProc P((Widget w, XEvent *event,
303 String *prms, Cardinal *nprms));
304 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
307 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
309 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
311 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
316 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void DisplayMove P((int moveNumber));
318 void DisplayTitle P((char *title));
319 void ICSInitScript P((void));
320 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
321 void ErrorPopUp P((char *title, char *text, int modal));
322 void ErrorPopDown P((void));
323 static char *ExpandPathName P((char *path));
324 static void CreateAnimVars P((void));
325 static void DragPieceMove P((int x, int y));
326 static void DrawDragPiece P((void));
327 char *ModeToWidgetName P((GameMode mode));
328 void EngineOutputUpdate( FrontEndProgramStats * stats );
329 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void ShufflePopDown P(());
337 void EnginePopDown P(());
338 void UciPopDown P(());
339 void TimeControlPopDown P(());
340 void NewVariantPopDown P(());
341 void SettingsPopDown P(());
342 void SetMenuEnables P((Enables *enab));
343 void update_ics_width P(());
344 int get_term_width P(());
346 * XBoard depends on Xt R4 or higher
348 int xtVersion = XtSpecificationRelease;
353 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
354 jailSquareColor, highlightSquareColor, premoveHighlightColor;
355 Pixel lowTimeWarningColor;
357 #define LINE_TYPE_NORMAL 0
358 #define LINE_TYPE_HIGHLIGHT 1
359 #define LINE_TYPE_PRE 2
362 GC lightSquareGC, darkSquareGC, jailSquareGC, wdPieceGC, wlPieceGC,
363 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC,
364 wjPieceGC, bjPieceGC;
365 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
366 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
367 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
368 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
369 menuBarWidget, editShell, errorShell, analysisShell,
370 ICSInputShell, fileNameShell, askQuestionShell;
371 Font clockFontID, coordFontID, countFontID;
372 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
373 XtAppContext appContext;
375 char *oldICSInteractionTitle;
379 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
381 Position commentX = -1, commentY = -1;
382 Dimension commentW, commentH;
384 int squareSize, smallLayout = 0, tinyLayout = 0,
385 marginW, marginH, // [HGM] for run-time resizing
386 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
387 ICSInputBoxUp = False, askQuestionUp = False,
388 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
389 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
390 Pixel timerForegroundPixel, timerBackgroundPixel;
391 Pixel buttonForegroundPixel, buttonBackgroundPixel;
392 char *chessDir, *programName, *programVersion,
393 *gameCopyFilename, *gamePasteFilename;
397 Pixmap pieceBitmap[2][(int)BlackPawn];
398 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
399 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
400 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
401 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
402 int useImages=0, useImageSqs;
403 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
404 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
405 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
406 XImage *ximLightSquare, *ximDarkSquare;
409 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
410 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
412 #define White(piece) ((int)(piece) < (int)BlackPawn)
414 /* Variables for doing smooth animation. This whole thing
415 would be much easier if the board was double-buffered,
416 but that would require a fairly major rewrite. */
421 GC blitGC, pieceGC, outlineGC;
422 XPoint startSquare, prevFrame, mouseDelta;
426 int startBoardX, startBoardY;
429 /* There can be two pieces being animated at once: a player
430 can begin dragging a piece before the remote opponent has moved. */
432 static AnimState game, player;
434 /* Bitmaps for use as masks when drawing XPM pieces.
435 Need one for each black and white piece. */
436 static Pixmap xpmMask[BlackKing + 1];
438 /* This magic number is the number of intermediate frames used
439 in each half of the animation. For short moves it's reduced
440 by 1. The total number of frames will be factor * 2 + 1. */
443 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
445 Enables icsEnables[] = {
446 { "menuFile.Mail Move", False },
447 { "menuFile.Reload CMail Message", False },
448 { "menuMode.Machine Black", False },
449 { "menuMode.Machine White", False },
450 { "menuMode.Analysis Mode", False },
451 { "menuMode.Analyze File", False },
452 { "menuMode.Two Machines", False },
454 { "menuHelp.Hint", False },
455 { "menuHelp.Book", False },
456 { "menuStep.Move Now", False },
457 { "menuOptions.Periodic Updates", False },
458 { "menuOptions.Hide Thinking", False },
459 { "menuOptions.Ponder Next Move", False },
464 Enables ncpEnables[] = {
465 { "menuFile.Mail Move", False },
466 { "menuFile.Reload CMail Message", False },
467 { "menuMode.Machine White", False },
468 { "menuMode.Machine Black", False },
469 { "menuMode.Analysis Mode", False },
470 { "menuMode.Analyze File", False },
471 { "menuMode.Two Machines", False },
472 { "menuMode.ICS Client", False },
473 { "menuMode.ICS Input Box", False },
475 { "menuStep.Revert", False },
476 { "menuStep.Move Now", False },
477 { "menuStep.Retract Move", False },
478 { "menuOptions.Auto Comment", False },
479 { "menuOptions.Auto Flag", False },
480 { "menuOptions.Auto Flip View", False },
481 { "menuOptions.Auto Observe", False },
482 { "menuOptions.Auto Raise Board", False },
483 { "menuOptions.Get Move List", False },
484 { "menuOptions.ICS Alarm", False },
485 { "menuOptions.Move Sound", False },
486 { "menuOptions.Quiet Play", False },
487 { "menuOptions.Hide Thinking", False },
488 { "menuOptions.Periodic Updates", False },
489 { "menuOptions.Ponder Next Move", False },
490 { "menuHelp.Hint", False },
491 { "menuHelp.Book", False },
495 Enables gnuEnables[] = {
496 { "menuMode.ICS Client", False },
497 { "menuMode.ICS Input Box", False },
498 { "menuAction.Accept", False },
499 { "menuAction.Decline", False },
500 { "menuAction.Rematch", False },
501 { "menuAction.Adjourn", False },
502 { "menuAction.Stop Examining", False },
503 { "menuAction.Stop Observing", False },
504 { "menuStep.Revert", False },
505 { "menuOptions.Auto Comment", False },
506 { "menuOptions.Auto Observe", False },
507 { "menuOptions.Auto Raise Board", False },
508 { "menuOptions.Get Move List", False },
509 { "menuOptions.Premove", False },
510 { "menuOptions.Quiet Play", False },
512 /* The next two options rely on SetCmailMode being called *after* */
513 /* SetGNUMode so that when GNU is being used to give hints these */
514 /* menu options are still available */
516 { "menuFile.Mail Move", False },
517 { "menuFile.Reload CMail Message", False },
521 Enables cmailEnables[] = {
523 { "menuAction.Call Flag", False },
524 { "menuAction.Draw", True },
525 { "menuAction.Adjourn", False },
526 { "menuAction.Abort", False },
527 { "menuAction.Stop Observing", False },
528 { "menuAction.Stop Examining", False },
529 { "menuFile.Mail Move", True },
530 { "menuFile.Reload CMail Message", True },
534 Enables trainingOnEnables[] = {
535 { "menuMode.Edit Comment", False },
536 { "menuMode.Pause", False },
537 { "menuStep.Forward", False },
538 { "menuStep.Backward", False },
539 { "menuStep.Forward to End", False },
540 { "menuStep.Back to Start", False },
541 { "menuStep.Move Now", False },
542 { "menuStep.Truncate Game", False },
546 Enables trainingOffEnables[] = {
547 { "menuMode.Edit Comment", True },
548 { "menuMode.Pause", True },
549 { "menuStep.Forward", True },
550 { "menuStep.Backward", True },
551 { "menuStep.Forward to End", True },
552 { "menuStep.Back to Start", True },
553 { "menuStep.Move Now", True },
554 { "menuStep.Truncate Game", True },
558 Enables machineThinkingEnables[] = {
559 { "menuFile.Load Game", False },
560 { "menuFile.Load Next Game", False },
561 { "menuFile.Load Previous Game", False },
562 { "menuFile.Reload Same Game", False },
563 { "menuFile.Paste Game", False },
564 { "menuFile.Load Position", False },
565 { "menuFile.Load Next Position", False },
566 { "menuFile.Load Previous Position", False },
567 { "menuFile.Reload Same Position", False },
568 { "menuFile.Paste Position", False },
569 { "menuMode.Machine White", False },
570 { "menuMode.Machine Black", False },
571 { "menuMode.Two Machines", False },
572 { "menuStep.Retract Move", False },
576 Enables userThinkingEnables[] = {
577 { "menuFile.Load Game", True },
578 { "menuFile.Load Next Game", True },
579 { "menuFile.Load Previous Game", True },
580 { "menuFile.Reload Same Game", True },
581 { "menuFile.Paste Game", True },
582 { "menuFile.Load Position", True },
583 { "menuFile.Load Next Position", True },
584 { "menuFile.Load Previous Position", True },
585 { "menuFile.Reload Same Position", True },
586 { "menuFile.Paste Position", True },
587 { "menuMode.Machine White", True },
588 { "menuMode.Machine Black", True },
589 { "menuMode.Two Machines", True },
590 { "menuStep.Retract Move", True },
596 MenuItem fileMenu[] = {
597 {N_("New Shuffle Game ..."), ShuffleMenuProc},
598 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
599 // {"----", NothingProc},
600 // {N_("Save Game"), SaveGameProc},
601 // {"----", NothingProc},
602 {N_("Copy Game"), CopyGameProc},
603 {N_("Paste Game"), PasteGameProc},
604 // {"----", NothingProc},
605 // {N_("Load Position"), LoadPositionProc},
606 // {N_("Load Next Position"), LoadNextPositionProc},
607 // {N_("Load Previous Position"), LoadPrevPositionProc},
608 // {N_("Reload Same Position"), ReloadPositionProc},
609 // {N_("Save Position"), SavePositionProc},
610 // {"----", NothingProc},
611 {N_("Copy Position"), CopyPositionProc},
612 {N_("Paste Position"), PastePositionProc},
613 // {"----", NothingProc},
614 {N_("Mail Move"), MailMoveProc},
615 {N_("Reload CMail Message"), ReloadCmailMsgProc},
616 // {"----", NothingProc},
620 MenuItem modeMenu[] = {
621 // {N_("Machine White"), MachineWhiteProc},
622 // {N_("Machine Black"), MachineBlackProc},
623 // {N_("Two Machines"), TwoMachinesProc},
624 {N_("Analysis Mode"), AnalyzeModeProc},
625 // {N_("Analyze File"), AnalyzeFileProc },
626 // {N_("ICS Client"), IcsClientProc},
627 {N_("Edit Game"), EditGameProc},
628 {N_("Edit Position"), EditPositionProc},
629 {N_("Training"), TrainingProc},
630 {"----", NothingProc},
631 {N_("Show Engine Output"), EngineOutputProc},
632 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
633 {N_("Show Game List"), ShowGameListProc},
634 // {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
635 {"----", NothingProc},
636 // {N_("Edit Tags"), EditTagsProc},
637 {N_("Edit Comment"), EditCommentProc},
638 {N_("ICS Input Box"), IcsInputBoxProc},
642 MenuItem optionsMenu[] = {
643 // {N_("Flip View"), FlipViewProc},
644 // {"----", NothingProc},
645 {N_("Adjudications ..."), EngineMenuProc},
646 {N_("General Settings ..."), UciMenuProc},
647 {N_("Engine #1 Settings ..."), FirstSettingsProc},
648 {N_("Engine #2 Settings ..."), SecondSettingsProc},
649 {N_("Time Control ..."), TimeControlProc},
650 {"----", NothingProc},
651 // {N_("Always Queen"), AlwaysQueenProc},
652 // {N_("Animate Dragging"), AnimateDraggingProc},
653 // {N_("Animate Moving"), AnimateMovingProc},
654 // {N_("Auto Comment"), AutocommProc},
655 // {N_("Auto Flag"), AutoflagProc},
656 // {N_("Auto Flip View"), AutoflipProc},
657 // {N_("Auto Observe"), AutobsProc},
658 // {N_("Auto Raise Board"), AutoraiseProc},
659 // {N_("Auto Save"), AutosaveProc},
660 // {N_("Blindfold"), BlindfoldProc},
661 // {N_("Flash Moves"), FlashMovesProc},
662 // {N_("Get Move List"), GetMoveListProc},
664 // {N_("Highlight Dragging"), HighlightDraggingProc},
666 // {N_("Highlight Last Move"), HighlightLastMoveProc},
667 // {N_("Move Sound"), MoveSoundProc},
668 // {N_("ICS Alarm"), IcsAlarmProc},
669 // {N_("Old Save Style"), OldSaveStyleProc},
670 // {N_("Periodic Updates"), PeriodicUpdatesProc},
671 {N_("Ponder Next Move"), PonderNextMoveProc},
672 {N_("Popup Exit Message"), PopupExitMessageProc},
673 {N_("Popup Move Errors"), PopupMoveErrorsProc},
674 {N_("Premove"), PremoveProc},
675 {N_("Quiet Play"), QuietPlayProc},
676 // {N_("Hide Thinking"), HideThinkingProc},
677 // {N_("Test Legality"), TestLegalityProc},
682 {N_("File"), fileMenu},
683 {N_("Mode"), modeMenu},
684 {N_("Options"), optionsMenu},
688 #define PIECE_MENU_SIZE 18
689 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
690 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
691 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
692 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
693 N_("Empty square"), N_("Clear board") },
694 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
695 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
696 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
697 N_("Empty square"), N_("Clear board") }
699 /* must be in same order as PieceMenuStrings! */
700 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
701 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
702 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
703 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
704 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
705 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
706 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
707 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
708 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
711 #define DROP_MENU_SIZE 6
712 String dropMenuStrings[DROP_MENU_SIZE] = {
713 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
715 /* must be in same order as PieceMenuStrings! */
716 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
717 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
718 WhiteRook, WhiteQueen
726 DropMenuEnables dmEnables[] = {
735 { XtNborderWidth, 0 },
736 { XtNdefaultDistance, 0 },
740 { XtNborderWidth, 0 },
741 { XtNresizable, (XtArgVal) True },
745 { XtNborderWidth, 0 },
750 XtResource clientResources[] = {
751 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
752 XtOffset(AppDataPtr, whitePieceColor), XtRString,
754 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
755 XtOffset(AppDataPtr, blackPieceColor), XtRString,
757 { "lightSquareColor", "lightSquareColor", XtRString,
758 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
759 XtRString, LIGHT_SQUARE_COLOR },
760 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
761 XtOffset(AppDataPtr, darkSquareColor), XtRString,
763 { "highlightSquareColor", "highlightSquareColor", XtRString,
764 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
765 XtRString, HIGHLIGHT_SQUARE_COLOR },
766 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
767 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
768 XtRString, PREMOVE_HIGHLIGHT_COLOR },
769 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
770 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
771 (XtPointer) MOVES_PER_SESSION },
772 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
773 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
774 (XtPointer) TIME_INCREMENT },
775 { "initString", "initString", XtRString, sizeof(String),
776 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
777 { "secondInitString", "secondInitString", XtRString, sizeof(String),
778 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
779 { "firstComputerString", "firstComputerString", XtRString,
780 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
782 { "secondComputerString", "secondComputerString", XtRString,
783 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
785 { "firstChessProgram", "firstChessProgram", XtRString,
786 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
787 XtRString, FIRST_CHESS_PROGRAM },
788 { "secondChessProgram", "secondChessProgram", XtRString,
789 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
790 XtRString, SECOND_CHESS_PROGRAM },
791 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
792 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
793 XtRImmediate, (XtPointer) False },
794 { "noChessProgram", "noChessProgram", XtRBoolean,
795 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
796 XtRImmediate, (XtPointer) False },
797 { "firstHost", "firstHost", XtRString, sizeof(String),
798 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
799 { "secondHost", "secondHost", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
801 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
802 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
803 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
804 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
805 { "bitmapDirectory", "bitmapDirectory", XtRString,
806 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
808 { "remoteShell", "remoteShell", XtRString, sizeof(String),
809 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
810 { "remoteUser", "remoteUser", XtRString, sizeof(String),
811 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
812 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
813 XtOffset(AppDataPtr, timeDelay), XtRString,
814 (XtPointer) TIME_DELAY_QUOTE },
815 { "timeControl", "timeControl", XtRString, sizeof(String),
816 XtOffset(AppDataPtr, timeControl), XtRString,
817 (XtPointer) TIME_CONTROL },
818 { "internetChessServerMode", "internetChessServerMode",
819 XtRBoolean, sizeof(Boolean),
820 XtOffset(AppDataPtr, icsActive), XtRImmediate,
822 { "internetChessServerHost", "internetChessServerHost",
823 XtRString, sizeof(String),
824 XtOffset(AppDataPtr, icsHost),
825 XtRString, (XtPointer) ICS_HOST },
826 { "internetChessServerPort", "internetChessServerPort",
827 XtRString, sizeof(String),
828 XtOffset(AppDataPtr, icsPort), XtRString,
829 (XtPointer) ICS_PORT },
830 { "internetChessServerCommPort", "internetChessServerCommPort",
831 XtRString, sizeof(String),
832 XtOffset(AppDataPtr, icsCommPort), XtRString,
834 { "internetChessServerLogonScript", "internetChessServerLogonScript",
835 XtRString, sizeof(String),
836 XtOffset(AppDataPtr, icsLogon), XtRString,
838 { "internetChessServerHelper", "internetChessServerHelper",
839 XtRString, sizeof(String),
840 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
841 { "internetChessServerInputBox", "internetChessServerInputBox",
842 XtRBoolean, sizeof(Boolean),
843 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
845 { "icsAlarm", "icsAlarm",
846 XtRBoolean, sizeof(Boolean),
847 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
849 { "icsAlarmTime", "icsAlarmTime",
851 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
853 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
854 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
856 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
857 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
858 { "gateway", "gateway", XtRString, sizeof(String),
859 XtOffset(AppDataPtr, gateway), XtRString, "" },
860 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
861 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
862 { "loadGameIndex", "loadGameIndex",
864 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
866 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
867 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
868 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
869 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
870 XtRImmediate, (XtPointer) True },
871 { "autoSaveGames", "autoSaveGames", XtRBoolean,
872 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
873 XtRImmediate, (XtPointer) False },
874 { "blindfold", "blindfold", XtRBoolean,
875 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
876 XtRImmediate, (XtPointer) False },
877 { "loadPositionFile", "loadPositionFile", XtRString,
878 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
880 { "loadPositionIndex", "loadPositionIndex",
882 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
884 { "savePositionFile", "savePositionFile", XtRString,
885 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
887 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
888 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
889 { "matchGames", "matchGames", XtRInt, sizeof(int),
890 XtOffset(AppDataPtr, matchGames), XtRImmediate,
892 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
893 XtOffset(AppDataPtr, monoMode), XtRImmediate,
895 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
896 XtOffset(AppDataPtr, debugMode), XtRImmediate,
898 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
899 XtOffset(AppDataPtr, clockMode), XtRImmediate,
901 { "boardSize", "boardSize", XtRString, sizeof(String),
902 XtOffset(AppDataPtr, boardSize), XtRString, "" },
903 { "searchTime", "searchTime", XtRString, sizeof(String),
904 XtOffset(AppDataPtr, searchTime), XtRString,
906 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
907 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
909 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
910 XtOffset(AppDataPtr, showCoords), XtRImmediate,
912 { "showJail", "showJail", XtRInt, sizeof(int),
913 XtOffset(AppDataPtr, showJail), XtRImmediate,
915 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
916 XtOffset(AppDataPtr, showThinking), XtRImmediate,
918 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
919 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
921 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
922 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
924 { "clockFont", "clockFont", XtRString, sizeof(String),
925 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
926 { "coordFont", "coordFont", XtRString, sizeof(String),
927 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
928 { "font", "font", XtRString, sizeof(String),
929 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
930 { "ringBellAfterMoves", "ringBellAfterMoves",
931 XtRBoolean, sizeof(Boolean),
932 XtOffset(AppDataPtr, ringBellAfterMoves),
933 XtRImmediate, (XtPointer) False },
934 { "autoCallFlag", "autoCallFlag", XtRBoolean,
935 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
936 XtRImmediate, (XtPointer) False },
937 { "autoFlipView", "autoFlipView", XtRBoolean,
938 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
939 XtRImmediate, (XtPointer) True },
940 { "autoObserve", "autoObserve", XtRBoolean,
941 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
942 XtRImmediate, (XtPointer) False },
943 { "autoComment", "autoComment", XtRBoolean,
944 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
945 XtRImmediate, (XtPointer) False },
946 { "getMoveList", "getMoveList", XtRBoolean,
947 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
948 XtRImmediate, (XtPointer) True },
950 { "highlightDragging", "highlightDragging", XtRBoolean,
951 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
952 XtRImmediate, (XtPointer) False },
954 { "highlightLastMove", "highlightLastMove", XtRBoolean,
955 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
956 XtRImmediate, (XtPointer) False },
957 { "premove", "premove", XtRBoolean,
958 sizeof(Boolean), XtOffset(AppDataPtr, premove),
959 XtRImmediate, (XtPointer) True },
960 { "testLegality", "testLegality", XtRBoolean,
961 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
962 XtRImmediate, (XtPointer) True },
963 { "flipView", "flipView", XtRBoolean,
964 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
965 XtRImmediate, (XtPointer) False },
966 { "cmail", "cmailGameName", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
968 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
969 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
970 XtRImmediate, (XtPointer) False },
971 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
973 XtRImmediate, (XtPointer) False },
974 { "quietPlay", "quietPlay", XtRBoolean,
975 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
976 XtRImmediate, (XtPointer) False },
977 { "titleInWindow", "titleInWindow", XtRBoolean,
978 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
979 XtRImmediate, (XtPointer) False },
980 { "localLineEditing", "localLineEditing", XtRBoolean,
981 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
982 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
984 { "zippyTalk", "zippyTalk", XtRBoolean,
985 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
986 XtRImmediate, (XtPointer) ZIPPY_TALK },
987 { "zippyPlay", "zippyPlay", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
989 XtRImmediate, (XtPointer) ZIPPY_PLAY },
990 { "zippyLines", "zippyLines", XtRString, sizeof(String),
991 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
992 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
993 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
994 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
995 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
996 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
997 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
998 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
999 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1000 ZIPPY_WRONG_PASSWORD },
1001 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1002 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1003 { "zippyUseI", "zippyUseI", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1005 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1006 { "zippyBughouse", "zippyBughouse", XtRInt,
1007 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1008 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1009 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1010 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1011 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1012 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1013 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1014 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1015 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1016 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1018 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1019 { "zippyAbort", "zippyAbort", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1021 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1022 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1023 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1024 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1025 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1026 (XtPointer) ZIPPY_MAX_GAMES },
1027 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1028 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1029 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1030 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1031 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1034 { "flashCount", "flashCount", XtRInt, sizeof(int),
1035 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1036 (XtPointer) FLASH_COUNT },
1037 { "flashRate", "flashRate", XtRInt, sizeof(int),
1038 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1039 (XtPointer) FLASH_RATE },
1040 { "pixmapDirectory", "pixmapDirectory", XtRString,
1041 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1043 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1044 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1045 (XtPointer) MS_LOGIN_DELAY },
1046 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1047 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1048 XtRImmediate, (XtPointer) False },
1049 { "colorShout", "colorShout", XtRString,
1050 sizeof(String), XtOffset(AppDataPtr, colorShout),
1051 XtRString, COLOR_SHOUT },
1052 { "colorSShout", "colorSShout", XtRString,
1053 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1054 XtRString, COLOR_SSHOUT },
1055 { "colorChannel1", "colorChannel1", XtRString,
1056 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1057 XtRString, COLOR_CHANNEL1 },
1058 { "colorChannel", "colorChannel", XtRString,
1059 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1060 XtRString, COLOR_CHANNEL },
1061 { "colorKibitz", "colorKibitz", XtRString,
1062 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1063 XtRString, COLOR_KIBITZ },
1064 { "colorTell", "colorTell", XtRString,
1065 sizeof(String), XtOffset(AppDataPtr, colorTell),
1066 XtRString, COLOR_TELL },
1067 { "colorChallenge", "colorChallenge", XtRString,
1068 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1069 XtRString, COLOR_CHALLENGE },
1070 { "colorRequest", "colorRequest", XtRString,
1071 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1072 XtRString, COLOR_REQUEST },
1073 { "colorSeek", "colorSeek", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1075 XtRString, COLOR_SEEK },
1076 { "colorNormal", "colorNormal", XtRString,
1077 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1078 XtRString, COLOR_NORMAL },
1079 { "soundProgram", "soundProgram", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1081 XtRString, "play" },
1082 { "soundShout", "soundShout", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, soundShout),
1085 { "soundSShout", "soundSShout", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1088 { "soundChannel1", "soundChannel1", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1091 { "soundChannel", "soundChannel", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1094 { "soundKibitz", "soundKibitz", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1097 { "soundTell", "soundTell", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, soundTell),
1100 { "soundChallenge", "soundChallenge", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1103 { "soundRequest", "soundRequest", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1106 { "soundSeek", "soundSeek", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1109 { "soundMove", "soundMove", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, soundMove),
1112 { "soundIcsWin", "soundIcsWin", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1115 { "soundIcsLoss", "soundIcsLoss", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1118 { "soundIcsDraw", "soundIcsDraw", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1121 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1124 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1127 { "reuseFirst", "reuseFirst", XtRBoolean,
1128 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1129 XtRImmediate, (XtPointer) True },
1130 { "reuseSecond", "reuseSecond", XtRBoolean,
1131 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1132 XtRImmediate, (XtPointer) True },
1133 { "animateDragging", "animateDragging", XtRBoolean,
1134 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1135 XtRImmediate, (XtPointer) True },
1136 { "animateMoving", "animateMoving", XtRBoolean,
1137 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1138 XtRImmediate, (XtPointer) True },
1139 { "animateSpeed", "animateSpeed", XtRInt,
1140 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1141 XtRImmediate, (XtPointer)10 },
1142 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1143 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1144 XtRImmediate, (XtPointer) True },
1145 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1146 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1147 XtRImmediate, (XtPointer) False },
1148 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1149 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1150 XtRImmediate, (XtPointer)4 },
1151 { "initialMode", "initialMode", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, initialMode),
1153 XtRImmediate, (XtPointer) "" },
1154 { "variant", "variant", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, variant),
1156 XtRImmediate, (XtPointer) "normal" },
1157 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1158 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1159 XtRImmediate, (XtPointer)PROTOVER },
1160 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1161 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1162 XtRImmediate, (XtPointer)PROTOVER },
1163 { "showButtonBar", "showButtonBar", XtRBoolean,
1164 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1165 XtRImmediate, (XtPointer) True },
1166 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1168 XtRString, COLOR_LOWTIMEWARNING },
1169 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1170 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1171 XtRImmediate, (XtPointer) False },
1172 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1173 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1174 XtRImmediate, (XtPointer) False },
1175 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1177 XtRImmediate, (XtPointer) False },
1178 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1180 XtRImmediate, (XtPointer) False },
1181 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1182 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1183 XtRImmediate, (XtPointer) False },
1184 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1185 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1186 XtRImmediate, (XtPointer) True },
1187 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1188 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1189 XtRImmediate, (XtPointer) 0},
1190 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1191 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1192 XtRImmediate, (XtPointer) 0},
1193 { "pgnEventHeader", "pgnEventHeader", XtRString,
1194 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1195 XtRImmediate, (XtPointer) "Computer Chess Game" },
1196 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1197 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1198 XtRImmediate, (XtPointer) -1},
1199 { "gameListTags", "gameListTags", XtRString,
1200 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1201 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1203 // [HGM] 4.3.xx options
1204 { "boardWidth", "boardWidth", XtRInt,
1205 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1206 XtRImmediate, (XtPointer) -1},
1207 { "boardHeight", "boardHeight", XtRInt,
1208 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1209 XtRImmediate, (XtPointer) -1},
1210 { "matchPause", "matchPause", XtRInt,
1211 sizeof(int), XtOffset(AppDataPtr, matchPause),
1212 XtRImmediate, (XtPointer) 10000},
1213 { "holdingsSize", "holdingsSize", XtRInt,
1214 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1215 XtRImmediate, (XtPointer) -1},
1216 { "flipBlack", "flipBlack", XtRBoolean,
1217 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1218 XtRImmediate, (XtPointer) False},
1219 { "allWhite", "allWhite", XtRBoolean,
1220 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1221 XtRImmediate, (XtPointer) False},
1222 { "pieceToCharTable", "pieceToCharTable", XtRString,
1223 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1224 XtRImmediate, (XtPointer) 0},
1225 { "alphaRank", "alphaRank", XtRBoolean,
1226 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1227 XtRImmediate, (XtPointer) False},
1228 { "testClaims", "testClaims", XtRBoolean,
1229 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1230 XtRImmediate, (XtPointer) True},
1231 { "checkMates", "checkMates", XtRBoolean,
1232 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1233 XtRImmediate, (XtPointer) True},
1234 { "materialDraws", "materialDraws", XtRBoolean,
1235 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1236 XtRImmediate, (XtPointer) True},
1237 { "trivialDraws", "trivialDraws", XtRBoolean,
1238 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1239 XtRImmediate, (XtPointer) False},
1240 { "ruleMoves", "ruleMoves", XtRInt,
1241 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1242 XtRImmediate, (XtPointer) 51},
1243 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1244 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1245 XtRImmediate, (XtPointer) 6},
1246 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1247 sizeof(int), XtOffset(AppDataPtr, engineComments),
1248 XtRImmediate, (XtPointer) 1},
1249 { "userName", "userName", XtRString,
1250 sizeof(int), XtOffset(AppDataPtr, userName),
1251 XtRImmediate, (XtPointer) 0},
1252 { "autoKibitz", "autoKibitz", XtRBoolean,
1253 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1254 XtRImmediate, (XtPointer) False},
1255 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1257 XtRImmediate, (XtPointer) 1},
1258 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1260 XtRImmediate, (XtPointer) 1},
1261 { "timeOddsMode", "timeOddsMode", XtRInt,
1262 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1263 XtRImmediate, (XtPointer) 0},
1264 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1265 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1266 XtRImmediate, (XtPointer) 1},
1267 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1268 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1269 XtRImmediate, (XtPointer) 1},
1270 { "firstNPS", "firstNPS", XtRInt,
1271 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1272 XtRImmediate, (XtPointer) -1},
1273 { "secondNPS", "secondNPS", XtRInt,
1274 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1275 XtRImmediate, (XtPointer) -1},
1276 { "serverMoves", "serverMoves", XtRString,
1277 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1278 XtRImmediate, (XtPointer) 0},
1279 { "serverPause", "serverPause", XtRInt,
1280 sizeof(int), XtOffset(AppDataPtr, serverPause),
1281 XtRImmediate, (XtPointer) 0},
1282 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1283 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1284 XtRImmediate, (XtPointer) False},
1285 { "userName", "userName", XtRString,
1286 sizeof(String), XtOffset(AppDataPtr, userName),
1287 XtRImmediate, (XtPointer) 0},
1288 { "egtFormats", "egtFormats", XtRString,
1289 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1290 XtRImmediate, (XtPointer) 0},
1291 { "rewindIndex", "rewindIndex", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1293 XtRImmediate, (XtPointer) 0},
1294 { "sameColorGames", "sameColorGames", XtRInt,
1295 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1296 XtRImmediate, (XtPointer) 0},
1297 { "smpCores", "smpCores", XtRInt,
1298 sizeof(int), XtOffset(AppDataPtr, smpCores),
1299 XtRImmediate, (XtPointer) 1},
1300 { "niceEngines", "niceEngines", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1302 XtRImmediate, (XtPointer) 0},
1303 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1304 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1305 XtRImmediate, (XtPointer) "xboard.debug"},
1306 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, engineComments),
1308 XtRImmediate, (XtPointer) 1},
1309 { "noGUI", "noGUI", XtRBoolean,
1310 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1311 XtRImmediate, (XtPointer) 0},
1312 { "firstOptions", "firstOptions", XtRString,
1313 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1314 XtRImmediate, (XtPointer) "" },
1315 { "secondOptions", "secondOptions", XtRString,
1316 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1317 XtRImmediate, (XtPointer) "" },
1318 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1319 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1320 XtRImmediate, (XtPointer) 0 },
1321 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1322 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1323 XtRImmediate, (XtPointer) 0 },
1325 // [HGM] Winboard_x UCI options
1326 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1327 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1328 XtRImmediate, (XtPointer) False},
1329 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1330 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1331 XtRImmediate, (XtPointer) False},
1332 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1333 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1334 XtRImmediate, (XtPointer) True},
1335 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1336 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1337 XtRImmediate, (XtPointer) True},
1338 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1339 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1340 XtRImmediate, (XtPointer) False},
1341 { "defaultHashSize", "defaultHashSize", XtRInt,
1342 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1343 XtRImmediate, (XtPointer) 64},
1344 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1345 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1346 XtRImmediate, (XtPointer) 4},
1347 { "polyglotDir", "polyglotDir", XtRString,
1348 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1349 XtRImmediate, (XtPointer) "." },
1350 { "polyglotBook", "polyglotBook", XtRString,
1351 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1352 XtRImmediate, (XtPointer) "" },
1353 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1354 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1355 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1356 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1357 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1358 XtRImmediate, (XtPointer) 0},
1359 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1360 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1361 XtRImmediate, (XtPointer) 0},
1362 { "keepAlive", "keepAlive", XtRInt,
1363 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1364 XtRImmediate, (XtPointer) 0},
1365 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1366 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1367 XtRImmediate, (XtPointer) False},
1368 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1369 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1370 XtRImmediate, (XtPointer) False},
1371 { "wrapContinuationSequence", "wrapContinuationSequence", XtRString,
1372 sizeof(String), XtOffset(AppDataPtr, wrapContSeq),
1374 { "useInternalWrap", "useInternalWrap", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, useInternalWrap),
1376 XtRImmediate, (XtPointer) True},
1377 { "autoDisplayTags", "autoDisplayTags", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayTags),
1379 XtRImmediate, (XtPointer) True},
1380 { "autoDisplayComment", "autoDisplayComment", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, autoDisplayComment),
1382 XtRImmediate, (XtPointer) True},
1383 { "pasteSelection", "pasteSelection", XtRBoolean,
1384 sizeof(Boolean), XtOffset(AppDataPtr, pasteSelection),
1385 XtRImmediate, (XtPointer) False},
1388 XrmOptionDescRec shellOptions[] = {
1389 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1390 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1391 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1392 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1393 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1394 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1395 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1396 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1397 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1398 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1399 { "-initString", "initString", XrmoptionSepArg, NULL },
1400 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1401 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1402 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1403 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1404 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1405 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1406 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1407 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1408 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1409 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1410 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1411 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1412 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1413 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1414 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1415 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1416 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1417 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1418 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1419 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1420 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1421 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1422 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1423 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1424 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1425 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1426 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1427 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1428 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1429 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1430 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1431 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1432 { "-internetChessServerMode", "internetChessServerMode",
1433 XrmoptionSepArg, NULL },
1434 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1435 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1436 { "-internetChessServerHost", "internetChessServerHost",
1437 XrmoptionSepArg, NULL },
1438 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1439 { "-internetChessServerPort", "internetChessServerPort",
1440 XrmoptionSepArg, NULL },
1441 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1442 { "-internetChessServerCommPort", "internetChessServerCommPort",
1443 XrmoptionSepArg, NULL },
1444 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1445 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1446 XrmoptionSepArg, NULL },
1447 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1448 { "-internetChessServerHelper", "internetChessServerHelper",
1449 XrmoptionSepArg, NULL },
1450 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1451 { "-internetChessServerInputBox", "internetChessServerInputBox",
1452 XrmoptionSepArg, NULL },
1453 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1454 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1455 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1456 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1457 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1458 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1459 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1460 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1461 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1462 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1463 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1464 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1465 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1466 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1467 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1468 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1469 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1470 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1471 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1472 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1473 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1474 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1475 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1476 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1477 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1478 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1479 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1480 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1481 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1482 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1483 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1484 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1485 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1486 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1487 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1488 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1489 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1490 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1491 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1492 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1493 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1494 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1495 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1496 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1497 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1498 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1499 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1500 { "-size", "boardSize", XrmoptionSepArg, NULL },
1501 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1502 { "-st", "searchTime", XrmoptionSepArg, NULL },
1503 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1504 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1505 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1506 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1507 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1509 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1510 { "-jail", "showJail", XrmoptionNoArg, "1" },
1511 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1512 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1514 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1515 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1516 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1517 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1518 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1519 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1520 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1521 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1522 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1523 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1524 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1525 { "-font", "font", XrmoptionSepArg, NULL },
1526 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1527 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1528 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1529 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1530 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1531 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1532 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1533 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1534 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1535 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1536 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1537 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1538 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1539 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1540 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1541 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1542 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1543 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1544 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1545 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1547 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1548 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1549 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1551 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1552 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1553 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1554 { "-premove", "premove", XrmoptionSepArg, NULL },
1555 { "-pre", "premove", XrmoptionNoArg, "True" },
1556 { "-xpre", "premove", XrmoptionNoArg, "False" },
1557 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1558 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1559 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1560 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1561 { "-flip", "flipView", XrmoptionNoArg, "True" },
1562 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1563 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1564 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1565 XrmoptionSepArg, NULL },
1566 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1567 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1568 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1569 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1570 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1571 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1572 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1573 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1574 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1575 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1576 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1578 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1579 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1580 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1581 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1582 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1583 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1584 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1585 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1586 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1587 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1588 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1589 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1590 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1591 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1592 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1593 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1594 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1595 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1596 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1597 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1598 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1599 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1600 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1601 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1602 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1603 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1604 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1605 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1606 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1607 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1608 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1610 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1611 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1612 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1613 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1614 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1615 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1616 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1617 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1618 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1619 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1620 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1621 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1622 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1623 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1624 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1625 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1626 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1627 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1628 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1629 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1630 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1631 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1632 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1633 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1634 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1635 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1636 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1637 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1638 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1639 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1640 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1641 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1642 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1643 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1644 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1645 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1646 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1647 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1648 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1649 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1650 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1651 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1652 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1653 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1654 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1655 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1656 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1657 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1658 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1659 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1660 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1661 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1662 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1663 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1664 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1665 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1666 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1667 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1668 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1669 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1670 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1671 { "-variant", "variant", XrmoptionSepArg, NULL },
1672 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1673 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1674 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1675 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1676 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1677 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1678 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1679 /* [AS,HR] New features */
1680 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1681 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1682 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1683 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1684 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1685 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1686 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1687 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1688 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1689 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1690 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1691 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1692 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1693 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1694 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1695 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1696 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1697 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1698 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1699 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1700 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1701 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1702 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1703 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1704 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1705 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1707 /* [HGM,HR] User-selectable board size */
1708 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1709 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1710 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1712 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1713 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1714 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1715 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1716 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1717 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1718 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1719 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1720 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1721 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1722 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1723 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1724 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1725 { "-userName", "userName", XrmoptionSepArg, NULL },
1726 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1727 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1728 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1729 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1730 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1731 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1732 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1733 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1734 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1735 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1736 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1737 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1738 { "-userName", "userName", XrmoptionSepArg, NULL },
1739 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1740 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1741 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1742 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1743 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1744 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1745 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1746 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1747 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1748 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1749 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1750 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1751 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1752 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1753 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1754 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1755 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1756 { "-wrapContinuationSequence", "wrapContinuationSequence", XrmoptionSepArg, NULL },
1757 { "-useInternalWrap", "useInternalWrap", XrmoptionSepArg, NULL },
1758 { "-autoDisplayTags", "autoDisplayTags", XrmoptionSepArg, NULL },
1759 { "-autoDisplayComment", "autoDisplayComment", XrmoptionSepArg, NULL },
1760 { "-pasteSelection", "pasteSelection", XrmoptionSepArg, NULL },
1763 XtActionsRec boardActions[] = {
1764 { "HandleUserMove", HandleUserMove },
1765 { "AnimateUserMove", AnimateUserMove },
1766 // { "FileNameAction", FileNameAction },
1767 { "AskQuestionProc", AskQuestionProc },
1768 { "AskQuestionReplyAction", AskQuestionReplyAction },
1769 { "PieceMenuPopup", PieceMenuPopup },
1770 // { "WhiteClock", WhiteClock },
1771 // { "BlackClock", BlackClock },
1772 { "Iconify", Iconify },
1773 { "LoadSelectedProc", LoadSelectedProc },
1774 // { "LoadPositionProc", LoadPositionProc },
1775 // { "LoadNextPositionProc", LoadNextPositionProc },
1776 // { "LoadPrevPositionProc", LoadPrevPositionProc },
1777 // { "ReloadPositionProc", ReloadPositionProc },
1778 { "CopyPositionProc", CopyPositionProc },
1779 { "PastePositionProc", PastePositionProc },
1780 { "CopyGameProc", CopyGameProc },
1781 { "PasteGameProc", PasteGameProc },
1782 // { "SaveGameProc", SaveGameProc },
1783 // { "SavePositionProc", SavePositionProc },
1784 { "MailMoveProc", MailMoveProc },
1785 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1786 // { "MachineWhiteProc", MachineWhiteProc },
1787 // { "MachineBlackProc", MachineBlackProc },
1788 { "AnalysisModeProc", AnalyzeModeProc },
1789 // { "AnalyzeFileProc", AnalyzeFileProc },
1790 // { "TwoMachinesProc", TwoMachinesProc },
1791 // { "IcsClientProc", IcsClientProc },
1792 { "EditGameProc", EditGameProc },
1793 { "EditPositionProc", EditPositionProc },
1794 { "TrainingProc", EditPositionProc },
1795 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1796 { "ShowGameListProc", ShowGameListProc },
1797 // { "ShowMoveListProc", HistoryShowProc},
1798 // { "EditTagsProc", EditCommentProc },
1799 { "EditCommentProc", EditCommentProc },
1800 // { "IcsAlarmProc", IcsAlarmProc },
1801 { "IcsInputBoxProc", IcsInputBoxProc },
1802 // { "AcceptProc", AcceptProc },
1803 // { "DeclineProc", DeclineProc },
1804 // { "RematchProc", RematchProc },
1805 // { "CallFlagProc", CallFlagProc },
1806 // { "DrawProc", DrawProc },
1807 // { "AdjournProc", AdjournProc },
1808 // { "AbortProc", AbortProc },
1809 // { "ResignProc", ResignProc },
1810 // { "AdjuWhiteProc", AdjuWhiteProc },
1811 // { "AdjuBlackProc", AdjuBlackProc },
1812 // { "AdjuDrawProc", AdjuDrawProc },
1813 { "EnterKeyProc", EnterKeyProc },
1814 // { "StopObservingProc", StopObservingProc },
1815 // { "StopExaminingProc", StopExaminingProc },
1816 // { "BackwardProc", BackwardProc },
1817 // { "ForwardProc", ForwardProc },
1818 // { "ToStartProc", ToStartProc },
1819 // { "ToEndProc", ToEndProc },
1820 // { "RevertProc", RevertProc },
1821 // { "TruncateGameProc", TruncateGameProc },
1822 // { "MoveNowProc", MoveNowProc },
1823 // { "RetractMoveProc", RetractMoveProc },
1824 // { "AlwaysQueenProc", AlwaysQueenProc },
1825 // { "AnimateDraggingProc", AnimateDraggingProc },
1826 // { "AnimateMovingProc", AnimateMovingProc },
1827 // { "AutoflagProc", AutoflagProc },
1828 // { "AutoflipProc", AutoflipProc },
1829 // { "AutobsProc", AutobsProc },
1830 // { "AutoraiseProc", AutoraiseProc },
1831 // { "AutosaveProc", AutosaveProc },
1832 // { "BlindfoldProc", BlindfoldProc },
1833 // { "FlashMovesProc", FlashMovesProc },
1834 // { "FlipViewProc", FlipViewProc },
1835 // { "GetMoveListProc", GetMoveListProc },
1837 // { "HighlightDraggingProc", HighlightDraggingProc },
1839 // { "HighlightLastMoveProc", HighlightLastMoveProc },
1840 // { "IcsAlarmProc", IcsAlarmProc },
1841 // { "MoveSoundProc", MoveSoundProc },
1842 // { "OldSaveStyleProc", OldSaveStyleProc },
1843 // { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1844 { "PonderNextMoveProc", PonderNextMoveProc },
1845 { "PopupExitMessageProc", PopupExitMessageProc },
1846 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1847 { "PremoveProc", PremoveProc },
1848 { "QuietPlayProc", QuietPlayProc },
1849 // { "ShowThinkingProc", ShowThinkingProc },
1850 // { "HideThinkingProc", HideThinkingProc },
1851 { "TestLegalityProc", TestLegalityProc },
1852 // { "InfoProc", InfoProc },
1853 // { "ManProc", ManProc },
1854 // { "HintProc", HintProc },
1855 // { "BookProc", BookProc },
1856 { "AboutGameProc", AboutGameProc },
1857 { "DebugProc", DebugProc },
1858 { "NothingProc", NothingProc },
1859 { "CommentPopDown", (XtActionProc) CommentPopDown },
1860 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1861 { "TagsPopDown", (XtActionProc) TagsPopDown },
1862 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1863 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1864 // { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1865 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1866 { "GameListPopDown", (XtActionProc) GameListPopDown },
1867 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1868 // { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1869 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1870 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1871 { "EnginePopDown", (XtActionProc) EnginePopDown },
1872 { "UciPopDown", (XtActionProc) UciPopDown },
1873 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1874 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1875 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1879 char ICSInputTranslations[] =
1880 "<Key>Return: EnterKeyProc() \n";
1882 String xboardResources[] = {
1883 // "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1884 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1885 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1889 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1890 "magenta", "cyan", "white" };
1894 TextColors textColors[(int)NColorClasses];
1896 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1898 parse_color(str, which)
1902 char *p, buf[100], *d;
1905 if (strlen(str) > 99) /* watch bounds on buf */
1910 for (i=0; i<which; ++i) {
1917 /* Could be looking at something like:
1919 .. in which case we want to stop on a comma also */
1920 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1924 return -1; /* Use default for empty field */
1927 if (which == 2 || isdigit(*p))
1930 while (*p && isalpha(*p))
1935 for (i=0; i<8; ++i) {
1936 if (!StrCaseCmp(buf, cnames[i]))
1937 return which? (i+40) : (i+30);
1939 if (!StrCaseCmp(buf, "default")) return -1;
1941 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1946 parse_cpair(cc, str)
1950 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1951 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1956 /* bg and attr are optional */
1957 textColors[(int)cc].bg = parse_color(str, 1);
1958 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1959 textColors[(int)cc].attr = 0;
1965 /* Arrange to catch delete-window events */
1966 Atom wm_delete_window;
1968 CatchDeleteWindow(Widget w, String procname)
1971 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1972 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
1973 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1979 /* this should raise the board to the top */
1980 gtk_window_present(GTK_WINDOW(GUI_Window));
1984 #define BoardSize int
1985 void InitDrawingSizes(BoardSize boardSize, int flags)
1986 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
1987 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
1989 XtGeometryResult gres;
1992 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
1993 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
1995 timerWidth = (boardWidth - sep) / 2;
1997 if (appData.titleInWindow)
2002 w = boardWidth - 2*bor;
2006 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2010 if(!formWidget) return;
2013 * Inhibit shell resizing.
2016 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2019 for(i=0; i<4; i++) {
2021 for(p=0; p<=(int)WhiteKing; p++)
2022 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2023 if(gameInfo.variant == VariantShogi) {
2024 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2025 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2026 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2027 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2028 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2031 if(gameInfo.variant == VariantGothic) {
2032 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2036 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2037 for(p=0; p<=(int)WhiteKing; p++)
2038 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2039 if(gameInfo.variant == VariantShogi) {
2040 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2041 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2042 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2043 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2044 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2047 if(gameInfo.variant == VariantGothic) {
2048 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2054 for(i=0; i<2; i++) {
2056 for(p=0; p<=(int)WhiteKing; p++)
2057 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2058 if(gameInfo.variant == VariantShogi) {
2059 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2060 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2061 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2062 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2063 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2066 if(gameInfo.variant == VariantGothic) {
2067 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2077 void EscapeExpand(char *p, char *q)
2078 { // [HGM] initstring: routine to shape up string arguments
2079 while(*p++ = *q++) if(p[-1] == '\\')
2081 case 'n': p[-1] = '\n'; break;
2082 case 'r': p[-1] = '\r'; break;
2083 case 't': p[-1] = '\t'; break;
2084 case '\\': p[-1] = '\\'; break;
2085 case 0: *p = 0; return;
2086 default: p[-1] = q[-1]; break;
2095 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2096 XSetWindowAttributes window_attributes;
2098 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2099 XrmValue vFrom, vTo;
2100 XtGeometryResult gres;
2103 int forceMono = False;
2107 // [HGM] before anything else, expand any indirection files amongst options
2108 char *argvCopy[1000]; // 1000 seems enough
2109 char newArgs[10000]; // holds actual characters
2112 srandom(time(0)); // [HGM] book: make random truly random
2115 for(i=0; i<argc; i++) {
2116 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2117 //fprintf(stderr, "arg %s\n", argv[i]);
2118 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2120 FILE *f = fopen(argv[i]+1, "rb");
2121 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2122 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2123 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2125 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2126 newArgs[k++] = 0; // terminate current arg
2127 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2128 argvCopy[j++] = newArgs + k; // get ready for next
2130 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2144 setbuf(stdout, NULL);
2145 setbuf(stderr, NULL);
2148 programName = strrchr(argv[0], '/');
2149 if (programName == NULL)
2150 programName = argv[0];
2155 XtSetLanguageProc(NULL, NULL, NULL);
2156 bindtextdomain(PACKAGE, LOCALEDIR);
2157 textdomain(PACKAGE);
2161 XtAppInitialize(&appContext, "XBoard", shellOptions,
2162 XtNumber(shellOptions),
2163 &argc, argv, xboardResources, NULL, 0);
2166 gtk_init (&argc, &argv);
2168 /* parse glade file to build widgets */
2170 builder = gtk_builder_new ();
2171 gtk_builder_add_from_file (builder, "gtk-interface.xml", NULL);
2173 /* test if everything worked ok */
2175 GUI_Window = GTK_WIDGET (gtk_builder_get_object (builder, "MainWindow"));
2176 if(!GUI_Window) printf("Error: gtk_builder didn't work!\n");
2178 GUI_Aspect = GTK_WIDGET (gtk_builder_get_object (builder, "Aspectframe"));
2179 if(!GUI_Aspect) printf("Error: gtk_builder didn't work!\n");
2181 GUI_History = GTK_WIDGET (gtk_builder_get_object (builder, "MoveHistory"));
2182 if(!GUI_History) printf("Error: gtk_builder didn't work!\n");
2184 GUI_Menubar = GTK_WIDGET (gtk_builder_get_object (builder, "MenuBar"));
2185 if(!GUI_Menubar) printf("Error: gtk_builder didn't work!\n");
2186 GUI_Timer = GTK_WIDGET (gtk_builder_get_object (builder, "Timer"));
2187 if(!GUI_Timer) printf("Error: gtk_builder didn't work!\n");
2188 GUI_Buttonbar = GTK_WIDGET (gtk_builder_get_object (builder, "ButtonBar"));
2189 if(!GUI_Buttonbar) printf("Error: gtk_builder didn't work!\n");
2190 GUI_Board = GTK_WIDGET (gtk_builder_get_object (builder, "Board"));
2191 if(!GUI_Board) printf("Error: gtk_builder didn't work!\n");
2193 GUI_Whiteclock = GTK_WIDGET (gtk_builder_get_object (builder, "WhiteClock"));
2194 if(!GUI_Whiteclock) printf("Error: gtk_builder didn't work!\n");
2196 GUI_Blackclock = GTK_WIDGET (gtk_builder_get_object (builder, "BlackClock"));
2197 if(!GUI_Blackclock) printf("Error: gtk_builder didn't work!\n");
2199 LIST_MoveHistory = GTK_LIST_STORE (gtk_builder_get_object (builder, "MoveHistoryStore"));
2200 if(!LIST_MoveHistory) printf("Error: gtk_builder didn't work!\n");
2202 /* EditTags window */
2203 GUI_EditTags = GTK_WIDGET (gtk_builder_get_object (builder, "EditTags"));
2204 if(!GUI_EditTags) printf("Error: gtk_builder didn't work!\n");
2206 GUI_EditTagsTextArea = GTK_WIDGET (gtk_builder_get_object (builder, "EditTagsTextArea"));
2207 if(!GUI_EditTagsTextArea) printf("Error: gtk_builder didn't work!\n");
2210 gtk_builder_connect_signals (builder, NULL);
2212 // don't unref the builder, since we use it to get references to widgets
2213 // g_object_unref (G_OBJECT (builder));
2215 /* end parse glade file */
2219 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2220 programName, argv[1]);
2222 fprintf(stderr, "Recognized options:\n");
2223 for(i = 0; i < XtNumber(shellOptions); i++)
2225 /* print first column */
2226 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2227 (shellOptions[i].argKind == XrmoptionSepArg
2229 /* print second column and end line */
2230 if (++i < XtNumber(shellOptions))
2232 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2233 shellOptions[i].option,
2234 (shellOptions[i].argKind == XrmoptionSepArg
2239 fprintf(stderr, "\n");
2246 if (p == NULL) p = "/tmp";
2247 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2248 gameCopyFilename = (char*) malloc(i);
2249 gamePasteFilename = (char*) malloc(i);
2250 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2251 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2253 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2254 clientResources, XtNumber(clientResources),
2257 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2258 static char buf[MSG_SIZ];
2259 EscapeExpand(buf, appData.initString);
2260 appData.initString = strdup(buf);
2261 EscapeExpand(buf, appData.secondInitString);
2262 appData.secondInitString = strdup(buf);
2263 EscapeExpand(buf, appData.firstComputerString);
2264 appData.firstComputerString = strdup(buf);
2265 EscapeExpand(buf, appData.secondComputerString);
2266 appData.secondComputerString = strdup(buf);
2269 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2272 if (chdir(chessDir) != 0) {
2273 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2279 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2280 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2281 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2282 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2285 setbuf(debugFP, NULL);
2288 /* [HGM,HR] make sure board size is acceptable */
2289 if(appData.NrFiles > BOARD_SIZE ||
2290 appData.NrRanks > BOARD_SIZE )
2291 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2294 /* This feature does not work; animation needs a rewrite */
2295 appData.highlightDragging = FALSE;
2299 xDisplay = XtDisplay(shellWidget);
2300 xScreen = DefaultScreen(xDisplay);
2301 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2303 gameInfo.variant = StringToVariant(appData.variant);
2304 InitPosition(FALSE);
2306 /* calc board size */
2307 if (isdigit(appData.boardSize[0]))
2309 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2310 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2311 &fontPxlSize, &smallLayout, &tinyLayout);
2314 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2315 programName, appData.boardSize);
2320 /* Find some defaults; use the nearest known size */
2321 SizeDefaults *szd, *nearest;
2322 int distance = 99999;
2323 nearest = szd = sizeDefaults;
2324 while (szd->name != NULL)
2326 if (abs(szd->squareSize - squareSize) < distance)
2329 distance = abs(szd->squareSize - squareSize);
2330 if (distance == 0) break;
2334 if (i < 2) lineGap = nearest->lineGap;
2335 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2336 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2337 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2338 if (i < 6) smallLayout = nearest->smallLayout;
2339 if (i < 7) tinyLayout = nearest->tinyLayout;
2344 SizeDefaults *szd = sizeDefaults;
2345 if (*appData.boardSize == NULLCHAR)
2347 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize
2348 || DisplayHeight(xDisplay, xScreen) < szd->minScreenSize)
2352 if (szd->name == NULL) szd--;
2356 while (szd->name != NULL
2357 && StrCaseCmp(szd->name, appData.boardSize) != 0)
2359 if (szd->name == NULL)
2361 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2362 programName, appData.boardSize);
2366 squareSize = szd->squareSize;
2367 lineGap = szd->lineGap;
2368 clockFontPxlSize = szd->clockFontPxlSize;
2369 coordFontPxlSize = szd->coordFontPxlSize;
2370 fontPxlSize = szd->fontPxlSize;
2371 smallLayout = szd->smallLayout;
2372 tinyLayout = szd->tinyLayout;
2374 /* end figuring out what size to use */
2376 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2377 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2380 * Determine what fonts to use.
2382 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2383 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2384 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2385 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2386 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2387 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2388 appData.font = FindFont(appData.font, fontPxlSize);
2389 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2390 countFontStruct = XQueryFont(xDisplay, countFontID);
2391 // appData.font = FindFont(appData.font, fontPxlSize);
2393 xdb = XtDatabase(xDisplay);
2394 XrmPutStringResource(&xdb, "*font", appData.font);
2397 * Detect if there are not enough colors available and adapt.
2399 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2400 appData.monoMode = True;
2403 if (!appData.monoMode) {
2404 vFrom.addr = (caddr_t) appData.lightSquareColor;
2405 vFrom.size = strlen(appData.lightSquareColor);
2406 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2407 if (vTo.addr == NULL) {
2408 appData.monoMode = True;
2411 lightSquareColor = *(Pixel *) vTo.addr;
2414 if (!appData.monoMode) {
2415 vFrom.addr = (caddr_t) appData.darkSquareColor;
2416 vFrom.size = strlen(appData.darkSquareColor);
2417 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2418 if (vTo.addr == NULL) {
2419 appData.monoMode = True;
2422 darkSquareColor = *(Pixel *) vTo.addr;
2425 if (!appData.monoMode) {
2426 vFrom.addr = (caddr_t) appData.whitePieceColor;
2427 vFrom.size = strlen(appData.whitePieceColor);
2428 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2429 if (vTo.addr == NULL) {
2430 appData.monoMode = True;
2433 whitePieceColor = *(Pixel *) vTo.addr;
2436 if (!appData.monoMode) {
2437 vFrom.addr = (caddr_t) appData.blackPieceColor;
2438 vFrom.size = strlen(appData.blackPieceColor);
2439 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2440 if (vTo.addr == NULL) {
2441 appData.monoMode = True;
2444 blackPieceColor = *(Pixel *) vTo.addr;
2448 if (!appData.monoMode) {
2449 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2450 vFrom.size = strlen(appData.highlightSquareColor);
2451 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2452 if (vTo.addr == NULL) {
2453 appData.monoMode = True;
2456 highlightSquareColor = *(Pixel *) vTo.addr;
2460 if (!appData.monoMode) {
2461 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2462 vFrom.size = strlen(appData.premoveHighlightColor);
2463 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2464 if (vTo.addr == NULL) {
2465 appData.monoMode = True;
2468 premoveHighlightColor = *(Pixel *) vTo.addr;
2473 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2476 if (appData.bitmapDirectory == NULL ||
2477 appData.bitmapDirectory[0] == NULLCHAR)
2478 appData.bitmapDirectory = DEF_BITMAP_DIR;
2481 if (appData.lowTimeWarning && !appData.monoMode) {
2482 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2483 vFrom.size = strlen(appData.lowTimeWarningColor);
2484 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2485 if (vTo.addr == NULL)
2486 appData.monoMode = True;
2488 lowTimeWarningColor = *(Pixel *) vTo.addr;
2491 if (appData.monoMode && appData.debugMode) {
2492 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2493 (unsigned long) XWhitePixel(xDisplay, xScreen),
2494 (unsigned long) XBlackPixel(xDisplay, xScreen));
2497 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2498 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2499 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2500 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2501 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2502 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2503 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2504 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2505 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2506 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2508 if (appData.colorize) {
2510 _("%s: can't parse color names; disabling colorization\n"),
2513 appData.colorize = FALSE;
2515 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2516 textColors[ColorNone].attr = 0;
2518 // XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2524 layoutName = "tinyLayout";
2525 } else if (smallLayout) {
2526 layoutName = "smallLayout";
2528 layoutName = "normalLayout";
2531 if (appData.titleInWindow) {
2532 /* todo check what this appdata does */
2535 if (appData.showButtonBar) {
2536 /* TODO hide button bar if requested */
2540 if (appData.titleInWindow)
2545 if (appData.showButtonBar)
2552 if (appData.showButtonBar)
2562 /* set some checkboxes in the menu according to appData */
2564 if (appData.alwaysPromoteToQueen)
2565 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Always Queen")),TRUE);
2567 if (appData.animateDragging)
2568 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Dragging")),TRUE);
2570 if (appData.animate)
2571 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Animate Moving")),TRUE);
2573 if (appData.autoComment)
2574 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Comment")),TRUE);
2576 if (appData.autoCallFlag)
2577 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flag")),TRUE);
2579 if (appData.autoFlipView)
2580 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Flip View")),TRUE);
2582 if (appData.autoObserve)
2583 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Observe")),TRUE);
2585 if (appData.autoRaiseBoard)
2586 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Raise Board")),TRUE);
2588 if (appData.autoSaveGames)
2589 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2591 if (appData.saveGameFile[0] != NULLCHAR)
2593 /* Can't turn this off from menu */
2594 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Auto Save")),TRUE);
2595 gtk_action_set_sensitive(GTK_ACTION (gtk_builder_get_object (builder, "menuOptions.Auto Save")),FALSE);
2598 if (appData.blindfold)
2599 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Blindfold")),TRUE);
2601 if (appData.flashCount > 0)
2602 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Flash Moves")),TRUE);
2604 if (appData.getMoveList)
2605 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Get Move List")),TRUE);
2608 if (appData.highlightDragging)
2609 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Dragging")),TRUE);
2612 if (appData.highlightLastMove)
2613 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Highlight Last Move")),TRUE);
2615 if (appData.icsAlarm)
2616 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.ICS Alarm")),TRUE);
2618 if (appData.ringBellAfterMoves)
2619 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Move Sound")),TRUE);
2621 if (appData.oldSaveStyle)
2622 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Old Save Style")),TRUE);
2624 if (appData.periodicUpdates)
2625 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Periodic Updates")),TRUE);
2627 if (appData.ponderNextMove)
2628 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Ponder Next Move")),TRUE);
2630 if (appData.popupExitMessage)
2631 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Exit Message")),TRUE);
2633 if (appData.popupMoveErrors)
2634 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Popup Move Errors")),TRUE);
2636 if (appData.premove)
2637 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Premove")),TRUE);
2639 if (appData.quietPlay)
2640 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Quit Play")),TRUE);
2642 if (appData.showCoords)
2643 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Coords")),TRUE);
2645 if (appData.showThinking)
2646 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Show Thinking")),TRUE);
2648 if (appData.testLegality)
2649 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuOptions.Test Legality")),TRUE);
2651 /* end setting check boxes */
2653 /* load square colors */
2654 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
2655 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
2656 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
2658 /* use two icons to indicate if it is white's or black's turn */
2659 WhiteIcon = load_pixbuf("svg/icon_white.svg",0);
2660 BlackIcon = load_pixbuf("svg/icon_black.svg",0);
2661 WindowIcon = WhiteIcon;
2662 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
2665 /* realize window */
2666 gtk_widget_show (GUI_Window);
2668 /* recalc boardsize */
2673 if (appData.animate || appData.animateDragging)
2678 if (errorExitStatus == -1) {
2679 if (appData.icsActive) {
2680 /* We now wait until we see "login:" from the ICS before
2681 sending the logon script (problems with timestamp otherwise) */
2682 /*ICSInitScript();*/
2683 if (appData.icsInputBox) ICSInputBoxPopUp();
2687 signal(SIGWINCH, TermSizeSigHandler);
2689 signal(SIGINT, IntSigHandler);
2690 signal(SIGTERM, IntSigHandler);
2691 if (*appData.cmailGameName != NULLCHAR) {
2692 signal(SIGUSR1, CmailSigHandler);
2695 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
2699 * Create a cursor for the board widget.
2700 * (This needs to be called after the window has been created to have access to board-window)
2703 BoardCursor = gdk_cursor_new(GDK_HAND2);
2704 gdk_window_set_cursor(GUI_Board->window, BoardCursor);
2705 gdk_cursor_destroy(BoardCursor);
2710 if (appData.debugMode) fclose(debugFP); // [DM] debug
2717 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2718 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2720 unlink(gameCopyFilename);
2721 unlink(gamePasteFilename);
2724 RETSIGTYPE TermSizeSigHandler(int sig)
2737 CmailSigHandler(sig)
2743 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2745 /* Activate call-back function CmailSigHandlerCallBack() */
2746 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2748 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2752 CmailSigHandlerCallBack(isr, closure, message, count, error)
2760 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2762 /**** end signal code ****/
2772 f = fopen(appData.icsLogon, "r");
2778 strcat(buf, appData.icsLogon);
2779 f = fopen(buf, "r");
2783 ProcessICSInitScript(f);
2790 EditCommentPopDown();
2796 SetMenuEnables(enab)
2801 if (!builder) return;
2802 while (enab->name != NULL) {
2803 o = gtk_builder_get_object(builder, enab->name);
2804 if(GTK_IS_WIDGET(o))
2805 gtk_widget_set_sensitive(GTK_WIDGET (o),enab->value);
2808 if(GTK_IS_ACTION(o))
2809 gtk_action_set_sensitive(GTK_ACTION (o),enab->value);
2811 DisplayError(enab->name, 0);
2819 SetMenuEnables(icsEnables);
2822 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
2823 {}; // XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2830 SetMenuEnables(ncpEnables);
2836 SetMenuEnables(gnuEnables);
2842 SetMenuEnables(cmailEnables);
2848 SetMenuEnables(trainingOnEnables);
2849 if (appData.showButtonBar) {
2850 // XtSetSensitive(buttonBarWidget, False);
2856 SetTrainingModeOff()
2858 SetMenuEnables(trainingOffEnables);
2859 if (appData.showButtonBar) {
2860 // XtSetSensitive(buttonBarWidget, True);
2865 SetUserThinkingEnables()
2867 if (appData.noChessProgram) return;
2868 SetMenuEnables(userThinkingEnables);
2872 SetMachineThinkingEnables()
2874 if (appData.noChessProgram) return;
2875 SetMenuEnables(machineThinkingEnables);
2877 case MachinePlaysBlack:
2878 case MachinePlaysWhite:
2879 case TwoMachinesPlay:
2880 // XtSetSensitive(XtNameToWidget(menuBarWidget,
2881 // ModeToWidgetName(gameMode)), True);
2888 #define Abs(n) ((n)<0 ? -(n) : (n))
2891 * Find a font that matches "pattern" that is as close as
2892 * possible to the targetPxlSize. Prefer fonts that are k
2893 * pixels smaller to fonts that are k pixels larger. The
2894 * pattern must be in the X Consortium standard format,
2895 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2896 * The return value should be freed with XtFree when no
2899 char *FindFont(pattern, targetPxlSize)
2903 char **fonts, *p, *best, *scalable, *scalableTail;
2904 int i, j, nfonts, minerr, err, pxlSize;
2907 char **missing_list;
2909 char *def_string, *base_fnt_lst, strInt[3];
2911 XFontStruct **fnt_list;
2913 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2914 sprintf(strInt, "%d", targetPxlSize);
2915 p = strstr(pattern, "--");
2916 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2917 strcat(base_fnt_lst, strInt);
2918 strcat(base_fnt_lst, strchr(p + 2, '-'));
2920 if ((fntSet = XCreateFontSet(xDisplay,
2924 &def_string)) == NULL) {
2926 fprintf(stderr, _("Unable to create font set.\n"));
2930 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2932 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2934 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2935 programName, pattern);
2943 for (i=0; i<nfonts; i++) {
2946 if (*p != '-') continue;
2948 if (*p == NULLCHAR) break;
2949 if (*p++ == '-') j++;
2951 if (j < 7) continue;
2954 scalable = fonts[i];
2957 err = pxlSize - targetPxlSize;
2958 if (Abs(err) < Abs(minerr) ||
2959 (minerr > 0 && err < 0 && -err == minerr)) {
2965 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2966 /* If the error is too big and there is a scalable font,
2967 use the scalable font. */
2968 int headlen = scalableTail - scalable;
2969 p = (char *) XtMalloc(strlen(scalable) + 10);
2970 while (isdigit(*scalableTail)) scalableTail++;
2971 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2973 p = (char *) XtMalloc(strlen(best) + 1);
2976 if (appData.debugMode) {
2977 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2978 pattern, targetPxlSize, p);
2981 if (missing_count > 0)
2982 XFreeStringList(missing_list);
2983 XFreeFontSet(xDisplay, fntSet);
2985 XFreeFontNames(fonts);
2992 /* 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*/
2994 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2995 | GCBackground | GCFunction | GCPlaneMask;
2996 XGCValues gc_values;
2999 gc_values.plane_mask = AllPlanes;
3000 gc_values.line_width = lineGap;
3001 gc_values.line_style = LineSolid;
3002 gc_values.function = GXcopy;
3004 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3005 gc_values.background = XWhitePixel(xDisplay, xScreen);
3006 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3007 XSetFont(xDisplay, coordGC, coordFontID);
3009 if (appData.monoMode) {
3010 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3011 gc_values.background = XBlackPixel(xDisplay, xScreen);
3012 lightSquareGC = wbPieceGC
3013 = XtGetGC(shellWidget, value_mask, &gc_values);
3015 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3016 gc_values.background = XWhitePixel(xDisplay, xScreen);
3017 darkSquareGC = bwPieceGC
3018 = XtGetGC(shellWidget, value_mask, &gc_values);
3020 if (DefaultDepth(xDisplay, xScreen) == 1) {
3021 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3022 gc_values.function = GXcopyInverted;
3023 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3024 gc_values.function = GXcopy;
3025 if (XBlackPixel(xDisplay, xScreen) == 1) {
3026 bwPieceGC = darkSquareGC;
3027 wbPieceGC = copyInvertedGC;
3029 bwPieceGC = copyInvertedGC;
3030 wbPieceGC = lightSquareGC;
3034 gc_values.foreground = lightSquareColor;
3035 gc_values.background = darkSquareColor;
3036 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3038 gc_values.foreground = darkSquareColor;
3039 gc_values.background = lightSquareColor;
3040 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3042 gc_values.foreground = jailSquareColor;
3043 gc_values.background = jailSquareColor;
3044 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3046 gc_values.foreground = whitePieceColor;
3047 gc_values.background = darkSquareColor;
3048 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3050 gc_values.foreground = whitePieceColor;
3051 gc_values.background = lightSquareColor;
3052 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3054 gc_values.foreground = whitePieceColor;
3055 gc_values.background = jailSquareColor;
3056 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3058 gc_values.foreground = blackPieceColor;
3059 gc_values.background = darkSquareColor;
3060 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3062 gc_values.foreground = blackPieceColor;
3063 gc_values.background = lightSquareColor;
3064 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3066 gc_values.foreground = blackPieceColor;
3067 gc_values.background = jailSquareColor;
3068 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3077 for(i=0;i<MAXPIECES;i++)
3081 g_free(SVGpieces[i]);
3088 SVGLightSquare = load_pixbuf("svg/LightSquare.svg",squareSize);
3089 SVGDarkSquare = load_pixbuf("svg/DarkSquare.svg",squareSize);
3090 SVGNeutralSquare = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3093 /* get some defaults going */
3094 for(i=WhitePawn; i<DemotePiece+1; i++)
3095 SVGpieces[i] = load_pixbuf("svg/NeutralSquare.svg",squareSize);
3097 SVGpieces[WhitePawn] = load_pixbuf("svg/WhitePawn.svg",squareSize);
3098 SVGpieces[WhiteKnight] = load_pixbuf("svg/WhiteKnight.svg",squareSize);
3099 SVGpieces[WhiteBishop] = load_pixbuf("svg/WhiteBishop.svg",squareSize);
3100 SVGpieces[WhiteRook] = load_pixbuf("svg/WhiteRook.svg",squareSize);
3101 SVGpieces[WhiteQueen] = load_pixbuf("svg/WhiteQueen.svg",squareSize);
3102 SVGpieces[WhiteKing] = load_pixbuf("svg/WhiteKing.svg",squareSize);
3104 SVGpieces[BlackPawn] = load_pixbuf("svg/BlackPawn.svg",squareSize);
3105 SVGpieces[BlackKnight] = load_pixbuf("svg/BlackKnight.svg",squareSize);
3106 SVGpieces[BlackBishop] = load_pixbuf("svg/BlackBishop.svg",squareSize);
3107 SVGpieces[BlackRook] = load_pixbuf("svg/BlackRook.svg",squareSize);
3108 SVGpieces[BlackQueen] = load_pixbuf("svg/BlackQueen.svg",squareSize);
3109 SVGpieces[BlackKing] = load_pixbuf("svg/BlackKing.svg",squareSize);
3115 static void MenuBarSelect(w, addr, index)
3120 XtActionProc proc = (XtActionProc) addr;
3122 (proc)(NULL, NULL, NULL, NULL);
3125 void CreateMenuBarPopup(parent, name, mb)
3135 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3138 XtSetArg(args[j], XtNleftMargin, 20); j++;
3139 XtSetArg(args[j], XtNrightMargin, 20); j++;
3141 while (mi->string != NULL) {
3142 if (strcmp(mi->string, "----") == 0) {
3143 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3146 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3147 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3149 XtAddCallback(entry, XtNcallback,
3150 (XtCallbackProc) MenuBarSelect,
3151 (caddr_t) mi->proc);
3157 Widget CreateMenuBar(mb)
3161 Widget anchor, menuBar;
3163 char menuName[MSG_SIZ];
3166 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3167 XtSetArg(args[j], XtNvSpace, 0); j++;
3168 XtSetArg(args[j], XtNborderWidth, 0); j++;
3169 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3170 formWidget, args, j);
3172 while (mb->name != NULL) {
3173 strcpy(menuName, "menu");
3174 strcat(menuName, mb->name);
3176 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3179 shortName[0] = _(mb->name)[0];
3180 shortName[1] = NULLCHAR;
3181 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3184 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3187 XtSetArg(args[j], XtNborderWidth, 0); j++;
3188 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3190 CreateMenuBarPopup(menuBar, menuName, mb);
3198 CreatePieceMenu(name, color)
3205 ChessSquare selection;
3207 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3208 boardWidget, args, 0);
3210 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3211 String item = pieceMenuStrings[color][i];
3213 if (strcmp(item, "----") == 0) {
3214 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3217 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3218 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3220 selection = pieceMenuTranslation[color][i];
3221 XtAddCallback(entry, XtNcallback,
3222 (XtCallbackProc) PieceMenuSelect,
3223 (caddr_t) selection);
3224 if (selection == WhitePawn || selection == BlackPawn) {
3225 XtSetArg(args[0], XtNpopupOnEntry, entry);
3226 XtSetValues(menu, args, 1);
3239 ChessSquare selection;
3241 // whitePieceMenu = CreatePieceMenu("menuW", 0);
3242 // blackPieceMenu = CreatePieceMenu("menuB", 1);
3244 // XtRegisterGrabAction(PieceMenuPopup, True,
3245 // (unsigned)(ButtonPressMask|ButtonReleaseMask),
3246 // GrabModeAsync, GrabModeAsync);
3248 // XtSetArg(args[0], XtNlabel, _("Drop"));
3249 // dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3250 // boardWidget, args, 1);
3251 // for (i = 0; i < DROP_MENU_SIZE; i++) {
3252 // String item = dropMenuStrings[i];
3254 // if (strcmp(item, "----") == 0) {
3255 // entry = XtCreateManagedWidget(item, smeLineObjectClass,
3256 // dropMenu, NULL, 0);
3258 // XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3259 // entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3260 // dropMenu, args, 1);
3261 // selection = dropMenuTranslation[i];
3262 // XtAddCallback(entry, XtNcallback,
3263 // (XtCallbackProc) DropMenuSelect,
3264 // (caddr_t) selection);
3269 void SetupDropMenu()
3277 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3278 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3279 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3280 dmEnables[i].piece);
3281 XtSetSensitive(entry, p != NULL || !appData.testLegality
3282 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3283 && !appData.icsActive));
3285 while (p && *p++ == dmEnables[i].piece) count++;
3286 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
3288 XtSetArg(args[j], XtNlabel, label); j++;
3289 XtSetValues(entry, args, j);
3293 void PieceMenuPopup(w, event, params, num_params)
3297 Cardinal *num_params;
3300 if (event->type != ButtonPress) return;
3301 if (errorUp) ErrorPopDown();
3305 whichMenu = params[0];
3307 case IcsPlayingWhite:
3308 case IcsPlayingBlack:
3310 case MachinePlaysWhite:
3311 case MachinePlaysBlack:
3312 if (appData.testLegality &&
3313 gameInfo.variant != VariantBughouse &&
3314 gameInfo.variant != VariantCrazyhouse) return;
3316 whichMenu = "menuD";
3322 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
3323 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
3324 pmFromX = pmFromY = -1;
3328 pmFromX = BOARD_WIDTH - 1 - pmFromX;
3330 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
3332 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3335 static void PieceMenuSelect(w, piece, junk)
3340 if (pmFromX < 0 || pmFromY < 0) return;
3341 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3344 static void DropMenuSelect(w, piece, junk)
3349 if (pmFromX < 0 || pmFromY < 0) return;
3350 DropMenuEvent(piece, pmFromX, pmFromY);
3354 * If the user selects on a border boundary, return -1; if off the board,
3355 * return -2. Otherwise map the event coordinate to the square.
3357 int EventToSquare(x, limit)
3365 if ((x % (squareSize + lineGap)) >= squareSize)
3367 x /= (squareSize + lineGap);
3373 static void do_flash_delay(msec)
3379 static void drawHighlight(file, rank, line_type)
3380 int file, rank, line_type;
3385 if (lineGap == 0 || appData.blindfold) return;
3389 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
3390 (squareSize + lineGap);
3391 y = lineGap/2 + rank * (squareSize + lineGap);
3395 x = lineGap/2 + file * (squareSize + lineGap);
3396 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
3397 (squareSize + lineGap);
3401 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3403 /* draw the highlight */
3404 cairo_move_to (cr, x, y);
3405 cairo_rel_line_to (cr, 0,squareSize+lineGap);
3406 cairo_rel_line_to (cr, squareSize+lineGap,0);
3407 cairo_rel_line_to (cr, 0,-squareSize-lineGap);
3408 cairo_close_path (cr);
3410 cairo_set_line_width (cr, lineGap);
3413 /* TODO: use appdata colors */
3414 case LINE_TYPE_HIGHLIGHT:
3415 cairo_set_source_rgba (cr, 1, 1, 0, 1.0);
3418 cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
3420 case LINE_TYPE_NORMAL:
3422 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3433 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3434 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3437 SetHighlights(fromX, fromY, toX, toY)
3438 int fromX, fromY, toX, toY;
3440 if (hi1X != fromX || hi1Y != fromY)
3442 if (hi1X >= 0 && hi1Y >= 0)
3444 drawHighlight(hi1X, hi1Y, LINE_TYPE_NORMAL);
3446 if (fromX >= 0 && fromY >= 0)
3448 drawHighlight(fromX, fromY, LINE_TYPE_HIGHLIGHT);
3451 if (hi2X != toX || hi2Y != toY)
3453 if (hi2X >= 0 && hi2Y >= 0)
3455 drawHighlight(hi2X, hi2Y, LINE_TYPE_NORMAL);
3457 if (toX >= 0 && toY >= 0)
3459 drawHighlight(toX, toY, LINE_TYPE_HIGHLIGHT);
3473 SetHighlights(-1, -1, -1, -1);
3478 SetPremoveHighlights(fromX, fromY, toX, toY)
3479 int fromX, fromY, toX, toY;
3481 if (pm1X != fromX || pm1Y != fromY)
3483 if (pm1X >= 0 && pm1Y >= 0)
3485 drawHighlight(pm1X, pm1Y, LINE_TYPE_NORMAL);
3487 if (fromX >= 0 && fromY >= 0)
3489 drawHighlight(fromX, fromY, LINE_TYPE_PRE);
3492 if (pm2X != toX || pm2Y != toY)
3494 if (pm2X >= 0 && pm2Y >= 0)
3496 drawHighlight(pm2X, pm2Y, LINE_TYPE_NORMAL);
3498 if (toX >= 0 && toY >= 0)
3500 drawHighlight(toX, toY, LINE_TYPE_PRE);
3513 ClearPremoveHighlights()
3515 SetPremoveHighlights(-1, -1, -1, -1);
3518 static void BlankSquare(x, y, color, piece, dest)
3531 pb = SVGLightSquare;
3533 case 2: /* neutral */
3535 pb = SVGNeutralSquare;
3538 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,pb,0,0,x,y,-1,-1, GDK_RGB_DITHER_NORMAL, 0, 0);
3542 static void DrawPiece(piece, square_color, x, y, dest)
3544 int square_color, x, y;
3547 /* redraw background, since piece might be transparent in some areas */
3548 BlankSquare(x,y,square_color,piece,dest);
3551 gdk_draw_pixbuf(GDK_WINDOW(GUI_Board->window),NULL,
3552 GDK_PIXBUF(SVGpieces[piece]),0,0,x,y,-1,-1,
3553 GDK_RGB_DITHER_NORMAL, 0, 0);
3557 /* [HR] determine square color depending on chess variant. */
3558 static int SquareColor(row, column)
3563 if (gameInfo.variant == VariantXiangqi) {
3564 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
3566 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
3568 } else if (row <= 4) {
3574 square_color = ((column + row) % 2) == 1;
3577 /* [hgm] holdings: next line makes all holdings squares light */
3578 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
3580 return square_color;
3583 void DrawSquare(row, column, piece, do_flash)
3584 int row, column, do_flash;
3587 int square_color, x, y;
3592 /* Calculate delay in milliseconds (2-delays per complete flash) */
3593 flash_delay = 500 / appData.flashRate;
3595 /* calculate x and y coordinates from row and column */
3598 x = lineGap + ((BOARD_WIDTH-1)-column) *
3599 (squareSize + lineGap);
3600 y = lineGap + row * (squareSize + lineGap);
3604 x = lineGap + column * (squareSize + lineGap);
3605 y = lineGap + ((BOARD_HEIGHT-1)-row) *
3606 (squareSize + lineGap);
3609 square_color = SquareColor(row, column);
3611 // [HGM] holdings: blank out area between board and holdings
3612 if ( column == BOARD_LEFT-1 || column == BOARD_RGHT
3613 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
3614 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) )
3616 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
3618 // [HGM] print piece counts next to holdings
3619 string[1] = NULLCHAR;
3622 cairo_text_extents_t extents;
3627 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3629 string[0] = '0' + piece;
3631 /* TODO this has to go into the font-selection */
3632 cairo_select_font_face (cr, "Sans",
3633 CAIRO_FONT_SLANT_NORMAL,
3634 CAIRO_FONT_WEIGHT_NORMAL);
3636 cairo_set_font_size (cr, 12.0);
3637 cairo_text_extents (cr, string, &extents);
3639 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) )
3641 xpos= x + squareSize - extents.width - 2;
3642 ypos= y + extents.y_bearing + 1;
3644 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1)
3647 ypos = y + extents.y_bearing + 1;
3650 /* TODO mono mode? */
3651 cairo_move_to (cr, xpos, ypos);
3652 cairo_text_path (cr, string);
3653 cairo_set_source_rgb (cr, 1.0, 1.0, 1);
3654 cairo_fill_preserve (cr);
3655 cairo_set_source_rgb (cr, 0, 0, 0);
3656 cairo_set_line_width (cr, 0.1);
3665 /* square on the board */
3666 if (piece == EmptySquare || appData.blindfold)
3668 BlankSquare(x, y, square_color, piece, xBoardWindow);
3672 if (do_flash && appData.flashCount > 0)
3674 for (i=0; i<appData.flashCount; ++i)
3677 DrawPiece(piece, square_color, x, y, xBoardWindow);
3678 do_flash_delay(flash_delay);
3680 BlankSquare(x, y, square_color, piece, xBoardWindow);
3681 do_flash_delay(flash_delay);
3684 DrawPiece(piece, square_color, x, y, xBoardWindow);
3688 /* show coordinates if necessary */
3689 if(appData.showCoords)
3691 cairo_text_extents_t extents;
3695 /* TODO this has to go into the font-selection */
3696 cairo_select_font_face (cr, "Sans",
3697 CAIRO_FONT_SLANT_NORMAL,
3698 CAIRO_FONT_WEIGHT_NORMAL);
3699 cairo_set_font_size (cr, 12.0);
3701 string[1] = NULLCHAR;
3704 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3706 if (row == (flipView ? BOARD_HEIGHT-1 : 0) &&
3707 column >= BOARD_LEFT && column < BOARD_RGHT)
3709 string[0] = 'a' + column - BOARD_LEFT;
3710 cairo_text_extents (cr, string, &extents);
3712 xpos = x + squareSize - extents.width - 2;
3713 ypos = y + squareSize - extents.height - extents.y_bearing - 1;
3715 if (appData.monoMode)
3722 cairo_move_to (cr, xpos, ypos);
3723 cairo_text_path (cr, string);
3724 cairo_set_source_rgb (cr, 0.0, 0.0, 0);
3725 cairo_fill_preserve (cr);
3726 cairo_set_source_rgb (cr, 0, 1.0, 0);
3727 cairo_set_line_width (cr, 0.1);
3730 if ( column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT))
3733 string[0] = ONE + row;
3734 cairo_text_extents (cr, string, &extents);
3737 ypos = y + extents.height + 1;
3739 if (appData.monoMode)
3746 cairo_move_to (cr, xpos, ypos);
3747 cairo_text_path (cr, string);
3748 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
3749 cairo_fill_preserve (cr);
3750 cairo_set_source_rgb (cr, 0, 0, 1.0);
3751 cairo_set_line_width (cr, 0.1);
3763 /* Returns 1 if there are "too many" differences between b1 and b2
3764 (i.e. more than 1 move was made) */
3765 static int too_many_diffs(b1, b2)
3771 for (i=0; i<BOARD_HEIGHT; ++i) {
3772 for (j=0; j<BOARD_WIDTH; ++j) {
3773 if (b1[i][j] != b2[i][j]) {
3774 if (++c > 4) /* Castling causes 4 diffs */
3783 /* Matrix describing castling maneuvers */
3784 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
3785 static int castling_matrix[4][5] = {
3786 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
3787 { 0, 7, 4, 5, 6 }, /* 0-0, white */
3788 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
3789 { 7, 7, 4, 5, 6 } /* 0-0, black */
3792 /* Checks whether castling occurred. If it did, *rrow and *rcol
3793 are set to the destination (row,col) of the rook that moved.
3795 Returns 1 if castling occurred, 0 if not.
3797 Note: Only handles a max of 1 castling move, so be sure
3798 to call too_many_diffs() first.
3800 static int check_castle_draw(newb, oldb, rrow, rcol)
3807 /* For each type of castling... */
3808 for (i=0; i<4; ++i) {
3809 r = castling_matrix[i];
3811 /* Check the 4 squares involved in the castling move */
3813 for (j=1; j<=4; ++j) {
3814 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
3821 /* All 4 changed, so it must be a castling move */
3830 static int damage[BOARD_SIZE][BOARD_SIZE];
3833 * event handler for redrawing the board
3835 void DrawPosition( repaint, board)
3836 /*Boolean*/int repaint;
3840 static int lastFlipView = 0;
3841 static int lastBoardValid = 0;
3842 static Board lastBoard;
3845 if (board == NULL) {
3846 if (!lastBoardValid) return;
3849 if (!lastBoardValid || lastFlipView != flipView) {
3850 // XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
3851 // XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
3856 * It would be simpler to clear the window with XClearWindow()
3857 * but this causes a very distracting flicker.
3860 if (!repaint && lastBoardValid && lastFlipView == flipView)
3862 /* If too much changes (begin observing new game, etc.), don't
3864 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
3866 /* Special check for castling so we don't flash both the king
3867 and the rook (just flash the king). */
3870 if (check_castle_draw(board, lastBoard, &rrow, &rcol))
3872 /* Draw rook with NO flashing. King will be drawn flashing later */
3873 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
3874 lastBoard[rrow][rcol] = board[rrow][rcol];
3878 /* First pass -- Draw (newly) empty squares and repair damage.
3879 This prevents you from having a piece show up twice while it
3880 is flashing on its new square */
3881 for (i = 0; i < BOARD_HEIGHT; i++)
3882 for (j = 0; j < BOARD_WIDTH; j++)
3883 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
3886 DrawSquare(i, j, board[i][j], 0);
3887 damage[i][j] = False;
3890 /* Second pass -- Draw piece(s) in new position and flash them */
3891 for (i = 0; i < BOARD_HEIGHT; i++)
3892 for (j = 0; j < BOARD_WIDTH; j++)
3893 if (board[i][j] != lastBoard[i][j])
3895 DrawSquare(i, j, board[i][j], do_flash);
3907 cr = gdk_cairo_create (GDK_WINDOW(GUI_Board->window));
3909 cairo_set_line_width (cr, lineGap);
3911 /* TODO: use appdata colors */
3912 cairo_set_source_rgba (cr, 0, 1, 0, 1.0);
3916 for (i = 0; i < BOARD_HEIGHT + 1; i++)
3919 x2 = lineGap + BOARD_WIDTH * (squareSize + lineGap);
3920 y1 = y2 = lineGap / 2 + (i * (squareSize + lineGap));
3922 cairo_move_to (cr, x1, y1);
3923 cairo_rel_line_to (cr, x2,0);
3927 for (j = 0; j < BOARD_WIDTH + 1; j++)
3930 y2 = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
3931 x1 = x2 = lineGap / 2 + (j * (squareSize + lineGap));
3933 cairo_move_to (cr, x1, y1);
3934 cairo_rel_line_to (cr, 0, y2);
3943 for (i = 0; i < BOARD_HEIGHT; i++)
3944 for (j = 0; j < BOARD_WIDTH; j++)
3946 DrawSquare(i, j, board[i][j], 0);
3947 damage[i][j] = False;
3951 CopyBoard(lastBoard, board);
3953 lastFlipView = flipView;
3955 /* Draw highlights */
3956 if (pm1X >= 0 && pm1Y >= 0)
3958 drawHighlight(pm1X, pm1Y, LINE_TYPE_PRE);
3960 if (pm2X >= 0 && pm2Y >= 0)
3962 drawHighlight(pm2X, pm2Y, LINE_TYPE_PRE);
3964 if (hi1X >= 0 && hi1Y >= 0)
3966 drawHighlight(hi1X, hi1Y, LINE_TYPE_HIGHLIGHT);
3968 if (hi2X >= 0 && hi2Y >= 0)
3970 drawHighlight(hi2X, hi2Y, LINE_TYPE_HIGHLIGHT);
3973 /* If piece being dragged around board, must redraw that too */
3980 * event handler for parsing user moves
3982 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
3983 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
3984 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
3985 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
3986 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
3987 // and at the end FinishMove() to perform the move after optional promotion popups.
3988 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
3989 void HandleUserMove(w, event, prms, nprms)
3995 if (w != boardWidget || errorExitStatus != -1) return;
3998 if (event->type == ButtonPress) {
3999 // XtPopdown(promotionShell);
4000 // XtDestroyWidget(promotionShell);
4001 promotionUp = False;
4009 // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
4010 if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
4011 if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
4014 void AnimateUserMove (Widget w, XEvent * event,
4015 String * params, Cardinal * nParams)
4017 DragPieceMove(event->xmotion.x, event->xmotion.y);
4020 Widget CommentCreate(name, text, mutable, callback, lines)
4022 int /*Boolean*/ mutable;
4023 XtCallbackProc callback;
4027 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4032 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4033 XtGetValues(boardWidget, args, j);
4036 XtSetArg(args[j], XtNresizable, True); j++;
4039 XtCreatePopupShell(name, topLevelShellWidgetClass,
4040 shellWidget, args, j);
4043 XtCreatePopupShell(name, transientShellWidgetClass,
4044 shellWidget, args, j);
4047 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4048 layoutArgs, XtNumber(layoutArgs));
4050 XtCreateManagedWidget("form", formWidgetClass, layout,
4051 formArgs, XtNumber(formArgs));
4055 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4056 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4058 XtSetArg(args[j], XtNstring, text); j++;
4059 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4060 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4061 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4062 XtSetArg(args[j], XtNright, XtChainRight); j++;
4063 XtSetArg(args[j], XtNresizable, True); j++;
4064 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4065 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4066 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4067 XtSetArg(args[j], XtNautoFill, True); j++;
4068 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4070 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4074 XtSetArg(args[j], XtNfromVert, edit); j++;
4075 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4076 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4077 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4078 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4080 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4081 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4084 XtSetArg(args[j], XtNfromVert, edit); j++;
4085 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4086 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4087 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4088 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4089 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4091 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4092 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4095 XtSetArg(args[j], XtNfromVert, edit); j++;
4096 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4097 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4098 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4099 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4100 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4102 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4103 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4106 XtSetArg(args[j], XtNfromVert, edit); j++;
4107 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4108 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4109 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4110 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4112 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4113 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4116 XtSetArg(args[j], XtNfromVert, edit); j++;
4117 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4118 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4119 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4120 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4121 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4123 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4124 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4127 XtRealizeWidget(shell);
4129 if (commentX == -1) {
4132 Dimension pw_height;
4133 Dimension ew_height;
4136 XtSetArg(args[j], XtNheight, &ew_height); j++;
4137 XtGetValues(edit, args, j);
4140 XtSetArg(args[j], XtNheight, &pw_height); j++;
4141 XtGetValues(shell, args, j);
4142 commentH = pw_height + (lines - 1) * ew_height;
4143 commentW = bw_width - 16;
4145 XSync(xDisplay, False);
4147 /* This code seems to tickle an X bug if it is executed too soon
4148 after xboard starts up. The coordinates get transformed as if
4149 the main window was positioned at (0, 0).
4151 XtTranslateCoords(shellWidget,
4152 (bw_width - commentW) / 2, 0 - commentH / 2,
4153 &commentX, &commentY);
4155 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4156 RootWindowOfScreen(XtScreen(shellWidget)),
4157 (bw_width - commentW) / 2, 0 - commentH / 2,
4162 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4165 XtSetArg(args[j], XtNheight, commentH); j++;
4166 XtSetArg(args[j], XtNwidth, commentW); j++;
4167 XtSetArg(args[j], XtNx, commentX); j++;
4168 XtSetArg(args[j], XtNy, commentY); j++;
4169 XtSetValues(shell, args, j);
4170 XtSetKeyboardFocus(shell, edit);
4175 /* Used for analysis window and ICS input window */
4176 Widget MiscCreate(name, text, mutable, callback, lines)
4178 int /*Boolean*/ mutable;
4179 XtCallbackProc callback;
4183 Widget shell, layout, form, edit;
4185 Dimension bw_width, pw_height, ew_height, w, h;
4191 XtSetArg(args[j], XtNresizable, True); j++;
4194 XtCreatePopupShell(name, topLevelShellWidgetClass,
4195 shellWidget, args, j);
4198 XtCreatePopupShell(name, transientShellWidgetClass,
4199 shellWidget, args, j);
4202 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4203 layoutArgs, XtNumber(layoutArgs));
4205 XtCreateManagedWidget("form", formWidgetClass, layout,
4206 formArgs, XtNumber(formArgs));
4210 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4211 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4213 XtSetArg(args[j], XtNstring, text); j++;
4214 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4215 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4216 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4217 XtSetArg(args[j], XtNright, XtChainRight); j++;
4218 XtSetArg(args[j], XtNresizable, True); j++;
4219 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4220 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4221 XtSetArg(args[j], XtNautoFill, True); j++;
4222 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4224 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4226 XtRealizeWidget(shell);
4229 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4230 XtGetValues(boardWidget, args, j);
4233 XtSetArg(args[j], XtNheight, &ew_height); j++;
4234 XtGetValues(edit, args, j);
4237 XtSetArg(args[j], XtNheight, &pw_height); j++;
4238 XtGetValues(shell, args, j);
4239 h = pw_height + (lines - 1) * ew_height;
4242 XSync(xDisplay, False);
4244 /* This code seems to tickle an X bug if it is executed too soon
4245 after xboard starts up. The coordinates get transformed as if
4246 the main window was positioned at (0, 0).
4248 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4250 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4251 RootWindowOfScreen(XtScreen(shellWidget)),
4252 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4256 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4259 XtSetArg(args[j], XtNheight, h); j++;
4260 XtSetArg(args[j], XtNwidth, w); j++;
4261 XtSetArg(args[j], XtNx, x); j++;
4262 XtSetArg(args[j], XtNy, y); j++;
4263 XtSetValues(shell, args, j);
4269 static int savedIndex; /* gross that this is global */
4271 void EditCommentPopUp(index, title, text)
4280 if (text == NULL) text = "";
4282 if (editShell == NULL) {
4284 CommentCreate(title, text, True, EditCommentCallback, 4);
4285 XtRealizeWidget(editShell);
4286 CatchDeleteWindow(editShell, "EditCommentPopDown");
4288 edit = XtNameToWidget(editShell, "*form.text");
4290 XtSetArg(args[j], XtNstring, text); j++;
4291 XtSetValues(edit, args, j);
4293 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4294 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4295 XtSetValues(editShell, args, j);
4298 XtPopup(editShell, XtGrabNone);
4302 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4303 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4307 void EditCommentCallback(w, client_data, call_data)
4309 XtPointer client_data, call_data;
4317 XtSetArg(args[j], XtNlabel, &name); j++;
4318 XtGetValues(w, args, j);
4320 if (strcmp(name, _("ok")) == 0) {
4321 edit = XtNameToWidget(editShell, "*form.text");
4323 XtSetArg(args[j], XtNstring, &val); j++;
4324 XtGetValues(edit, args, j);
4325 ReplaceComment(savedIndex, val);
4326 EditCommentPopDown();
4327 } else if (strcmp(name, _("cancel")) == 0) {
4328 EditCommentPopDown();
4329 } else if (strcmp(name, _("clear")) == 0) {
4330 edit = XtNameToWidget(editShell, "*form.text");
4331 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4332 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4336 void EditCommentPopDown()
4341 if (!editUp) return;
4343 XtSetArg(args[j], XtNx, &commentX); j++;
4344 XtSetArg(args[j], XtNy, &commentY); j++;
4345 XtSetArg(args[j], XtNheight, &commentH); j++;
4346 XtSetArg(args[j], XtNwidth, &commentW); j++;
4347 XtGetValues(editShell, args, j);
4348 XtPopdown(editShell);
4351 XtSetArg(args[j], XtNleftBitmap, None); j++;
4352 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4356 void ICSInputBoxPopUp()
4361 char *title = _("ICS Input");
4364 if (ICSInputShell == NULL) {
4365 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4366 tr = XtParseTranslationTable(ICSInputTranslations);
4367 edit = XtNameToWidget(ICSInputShell, "*form.text");
4368 XtOverrideTranslations(edit, tr);
4369 XtRealizeWidget(ICSInputShell);
4370 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4373 edit = XtNameToWidget(ICSInputShell, "*form.text");
4375 XtSetArg(args[j], XtNstring, ""); j++;
4376 XtSetValues(edit, args, j);
4378 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4379 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4380 XtSetValues(ICSInputShell, args, j);
4383 XtPopup(ICSInputShell, XtGrabNone);
4384 XtSetKeyboardFocus(ICSInputShell, edit);
4386 ICSInputBoxUp = True;
4388 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4389 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4393 void ICSInputSendText()
4400 edit = XtNameToWidget(ICSInputShell, "*form.text");
4402 XtSetArg(args[j], XtNstring, &val); j++;
4403 XtGetValues(edit, args, j);
4404 SendMultiLineToICS(val);
4405 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4406 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4409 void ICSInputBoxPopDown()
4414 if (!ICSInputBoxUp) return;
4416 XtPopdown(ICSInputShell);
4417 ICSInputBoxUp = False;
4419 XtSetArg(args[j], XtNleftBitmap, None); j++;
4420 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4424 void CommentPopUp(title, text)
4431 if (commentShell == NULL) {
4433 CommentCreate(title, text, False, CommentCallback, 4);
4434 XtRealizeWidget(commentShell);
4435 CatchDeleteWindow(commentShell, "CommentPopDown");
4437 edit = XtNameToWidget(commentShell, "*form.text");
4439 XtSetArg(args[j], XtNstring, text); j++;
4440 XtSetValues(edit, args, j);
4442 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4443 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4444 XtSetValues(commentShell, args, j);
4447 XtPopup(commentShell, XtGrabNone);
4448 XSync(xDisplay, False);
4453 void CommentCallback(w, client_data, call_data)
4455 XtPointer client_data, call_data;
4462 XtSetArg(args[j], XtNlabel, &name); j++;
4463 XtGetValues(w, args, j);
4465 if (strcmp(name, _("close")) == 0) {
4467 } else if (strcmp(name, _("edit")) == 0) {
4474 void CommentPopDown()
4479 if (!commentUp) return;
4481 XtSetArg(args[j], XtNx, &commentX); j++;
4482 XtSetArg(args[j], XtNy, &commentY); j++;
4483 XtSetArg(args[j], XtNwidth, &commentW); j++;
4484 XtSetArg(args[j], XtNheight, &commentH); j++;
4485 XtGetValues(commentShell, args, j);
4486 XtPopdown(commentShell);
4487 XSync(xDisplay, False);
4491 void PromotionPopUp()
4494 Widget dialog, layout;
4496 Dimension bw_width, pw_width;
4500 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4501 XtGetValues(boardWidget, args, j);
4504 XtSetArg(args[j], XtNresizable, True); j++;
4505 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
4507 XtCreatePopupShell("Promotion", transientShellWidgetClass,
4508 shellWidget, args, j);
4510 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
4511 layoutArgs, XtNumber(layoutArgs));
4514 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
4515 XtSetArg(args[j], XtNborderWidth, 0); j++;
4516 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
4519 if(gameInfo.variant != VariantShogi) {
4520 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
4521 (XtPointer) dialog);
4522 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
4523 (XtPointer) dialog);
4524 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
4525 (XtPointer) dialog);
4526 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
4527 (XtPointer) dialog);
4528 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
4529 gameInfo.variant == VariantGiveaway) {
4530 XawDialogAddButton(dialog, _("King"), PromotionCallback,
4531 (XtPointer) dialog);
4533 if(gameInfo.variant == VariantCapablanca ||
4534 gameInfo.variant == VariantGothic ||
4535 gameInfo.variant == VariantCapaRandom) {
4536 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
4537 (XtPointer) dialog);
4538 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
4539 (XtPointer) dialog);
4541 } else // [HGM] shogi
4543 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
4544 (XtPointer) dialog);
4545 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
4546 (XtPointer) dialog);
4548 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
4549 (XtPointer) dialog);
4551 XtRealizeWidget(promotionShell);
4552 CatchDeleteWindow(promotionShell, "PromotionPopDown");
4555 XtSetArg(args[j], XtNwidth, &pw_width); j++;
4556 XtGetValues(promotionShell, args, j);
4558 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
4559 lineGap + squareSize/3 +
4560 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
4561 0 : 6*(squareSize + lineGap)), &x, &y);
4564 XtSetArg(args[j], XtNx, x); j++;
4565 XtSetArg(args[j], XtNy, y); j++;
4566 XtSetValues(promotionShell, args, j);
4568 XtPopup(promotionShell, XtGrabNone);
4573 void PromotionPopDown()
4575 if (!promotionUp) return;
4576 XtPopdown(promotionShell);
4577 XtDestroyWidget(promotionShell);
4578 promotionUp = False;
4581 void PromotionCallback(w, client_data, call_data)
4583 XtPointer client_data, call_data;
4589 XtSetArg(args[0], XtNlabel, &name);
4590 XtGetValues(w, args, 1);
4594 if (fromX == -1) return;
4596 if (strcmp(name, _("cancel")) == 0) {
4600 } else if (strcmp(name, _("Knight")) == 0) {
4602 } else if (strcmp(name, _("Promote")) == 0) {
4604 } else if (strcmp(name, _("Defer")) == 0) {
4607 promoChar = ToLower(name[0]);
4610 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
4612 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4613 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4618 void ErrorCallback(w, client_data, call_data)
4620 XtPointer client_data, call_data;
4623 XtPopdown(w = XtParent(XtParent(XtParent(w))));
4625 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4631 if (!errorUp) return;
4635 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4637 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
4642 void ErrorPopUp(title, label, modal)
4643 char *title, *label;
4646 GUI_Error = gtk_message_dialog_new(GTK_WINDOW(GUI_Window),
4647 GTK_DIALOG_DESTROY_WITH_PARENT,
4652 gtk_window_set_title(GTK_WINDOW(GUI_Error),(gchar *) title);
4655 gtk_dialog_run(GTK_DIALOG(GUI_Error));
4656 gtk_widget_destroy(GTK_WIDGET(GUI_Error));
4660 g_signal_connect_swapped (GUI_Error, "response",
4661 G_CALLBACK (ErrorPopDownProc),
4664 gtk_widget_show(GTK_WIDGET(GUI_Error));
4670 /* Disable all user input other than deleting the window */
4671 static int frozen = 0;
4675 /* Grab by a widget that doesn't accept input */
4676 // XtAddGrab(messageWidget, TRUE, FALSE);
4680 /* Undo a FreezeUI */
4683 if (!frozen) return;
4684 // XtRemoveGrab(messageWidget);
4688 char *ModeToWidgetName(mode)
4692 case BeginningOfGame:
4693 if (appData.icsActive)
4694 return "menuMode.ICS Client";
4695 else if (appData.noChessProgram ||
4696 *appData.cmailGameName != NULLCHAR)
4697 return "menuMode.Edit Game";
4699 return "menuMode.Machine Black";
4700 case MachinePlaysBlack:
4701 return "menuMode.Machine Black";
4702 case MachinePlaysWhite:
4703 return "menuMode.Machine White";
4705 return "menuMode.Analysis Mode";
4707 return "menuMode.Analyze File";
4708 case TwoMachinesPlay:
4709 return "menuMode.Two Machines";
4711 return "menuMode.Edit Game";
4712 case PlayFromGameFile:
4713 return "menuFile.Load Game";
4715 return "menuMode.Edit Position";
4717 return "menuMode.Training";
4718 case IcsPlayingWhite:
4719 case IcsPlayingBlack:
4723 return "menuMode.ICS Client";
4730 void ModeHighlight()
4732 static int oldPausing = FALSE;
4733 static GameMode oldmode = (GameMode) -1;
4736 // todo this toggling of the pause button doesn't seem to work?
4737 // e.g. select pause from buttonbar doesn't activate menumode.pause
4739 // if (!boardWidget || !XtIsRealized(boardWidget)) return;
4741 if (pausing != oldPausing) {
4742 oldPausing = pausing;
4743 gtk_button_set_relief(GTK_BUTTON (gtk_builder_get_object (builder, "menuMode.Pause")),pausing?GTK_RELIEF_NORMAL:GTK_RELIEF_NONE);
4744 /* toggle background color in showbuttonbar */
4745 if (appData.showButtonBar) {
4747 gtk_button_pressed(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4749 gtk_button_released(GTK_BUTTON (gtk_builder_get_object (builder, "buttonbar.Pause")));
4754 wname = ModeToWidgetName(oldmode);
4756 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, wname)),True);
4760 /* Maybe all the enables should be handled here, not just this one */
4761 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (gtk_builder_get_object (builder, "menuMode.Training")),
4762 gameMode == Training || gameMode == PlayFromGameFile);
4767 * Button/menu procedures
4770 int LoadGamePopUp(f, gameNumber, title)
4775 cmailMsgLoaded = FALSE;
4777 if (gameNumber == 0)
4779 int error = GameListBuild(f);
4783 DisplayError(_("Cannot build game list"), error);
4785 else if (!ListEmpty(&gameList)
4786 && ((ListGame *) gameList.tailPred)->number > 1)
4788 // TODO convert to GTK
4789 // GameListPopUp(f, title);
4797 return LoadGame(f, gameNumber, title, FALSE);
4800 void ReloadCmailMsgProc(w, event, prms, nprms)
4806 ReloadCmailMsgEvent(FALSE);
4809 void MailMoveProc(w, event, prms, nprms)
4818 /* this variable is shared between CopyPositionProc and SendPositionSelection */
4819 static char *selected_fen_position=NULL;
4822 SendPositionSelection(Widget w, Atom *selection, Atom *target,
4823 Atom *type_return, XtPointer *value_return,
4824 unsigned long *length_return, int *format_return)
4826 char *selection_tmp;
4828 if (!selected_fen_position) return False; /* should never happen */
4829 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4830 /* note: since no XtSelectionDoneProc was registered, Xt will
4831 * automatically call XtFree on the value returned. So have to
4832 * make a copy of it allocated with XtMalloc */
4833 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
4834 strcpy(selection_tmp, selected_fen_position);
4836 *value_return=selection_tmp;
4837 *length_return=strlen(selection_tmp);
4838 *type_return=*target;
4839 *format_return = 8; /* bits per byte */
4841 } else if (*target == XA_TARGETS(xDisplay)) {
4842 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4843 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4844 targets_tmp[1] = XA_STRING;
4845 *value_return = targets_tmp;
4846 *type_return = XA_ATOM;
4848 *format_return = 8 * sizeof(Atom);
4849 if (*format_return > 32) {
4850 *length_return *= *format_return / 32;
4851 *format_return = 32;
4859 /* note: when called from menu all parameters are NULL, so no clue what the
4860 * Widget which was clicked on was, or what the click event was
4862 void CopyPositionProc(w, event, prms, nprms)
4869 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4870 * have a notion of a position that is selected but not copied.
4871 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4873 if (selected_fen_position) free(selected_fen_position);
4874 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
4875 if (!selected_fen_position) return;
4876 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4878 SendPositionSelection,
4879 NULL/* lose_ownership_proc */ ,
4880 NULL/* transfer_done_proc */);
4881 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4883 SendPositionSelection,
4884 NULL/* lose_ownership_proc */ ,
4885 NULL/* transfer_done_proc */);
4888 /* function called when the data to Paste is ready */
4890 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
4891 Atom *type, XtPointer value, unsigned long *len, int *format)
4894 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
4895 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
4896 EditPositionPasteFEN(fenstr);
4900 /* called when Paste Position button is pressed,
4901 * all parameters will be NULL */
4902 void PastePositionProc(w, event, prms, nprms)
4908 XtGetSelectionValue(menuBarWidget,
4909 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
4910 /* (XtSelectionCallbackProc) */ PastePositionCB,
4911 NULL, /* client_data passed to PastePositionCB */
4913 /* better to use the time field from the event that triggered the
4914 * call to this function, but that isn't trivial to get
4922 SendGameSelection(Widget w, Atom *selection, Atom *target,
4923 Atom *type_return, XtPointer *value_return,
4924 unsigned long *length_return, int *format_return)
4926 char *selection_tmp;
4928 if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){
4929 FILE* f = fopen(gameCopyFilename, "r");
4932 if (f == NULL) return False;
4936 selection_tmp = XtMalloc(len + 1);
4937 count = fread(selection_tmp, 1, len, f);
4939 XtFree(selection_tmp);
4942 selection_tmp[len] = NULLCHAR;
4943 *value_return = selection_tmp;
4944 *length_return = len;
4945 *type_return = *target;
4946 *format_return = 8; /* bits per byte */
4948 } else if (*target == XA_TARGETS(xDisplay)) {
4949 Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom));
4950 targets_tmp[0] = XA_UTF8_STRING(xDisplay);
4951 targets_tmp[1] = XA_STRING;
4952 *value_return = targets_tmp;
4953 *type_return = XA_ATOM;
4955 *format_return = 8 * sizeof(Atom);
4956 if (*format_return > 32) {
4957 *length_return *= *format_return / 32;
4958 *format_return = 32;
4966 /* note: when called from menu all parameters are NULL, so no clue what the
4967 * Widget which was clicked on was, or what the click event was
4969 void CopyGameProc(w, event, prms, nprms)
4977 ret = SaveGameToFile(gameCopyFilename, FALSE);
4981 * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
4982 * have a notion of a game that is selected but not copied.
4983 * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki
4985 XtOwnSelection(menuBarWidget, XA_PRIMARY,
4988 NULL/* lose_ownership_proc */ ,
4989 NULL/* transfer_done_proc */);
4990 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
4993 NULL/* lose_ownership_proc */ ,
4994 NULL/* transfer_done_proc */);
4997 /* function called when the data to Paste is ready */
4999 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5000 Atom *type, XtPointer value, unsigned long *len, int *format)
5003 if (value == NULL || *len == 0) {
5004 return; /* nothing had been selected to copy */
5006 f = fopen(gamePasteFilename, "w");
5008 DisplayError(_("Can't open temp file"), errno);
5011 fwrite(value, 1, *len, f);
5014 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5017 /* called when Paste Game button is pressed,
5018 * all parameters will be NULL */
5019 void PasteGameProc(w, event, prms, nprms)
5025 XtGetSelectionValue(menuBarWidget,
5026 appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
5027 /* (XtSelectionCallbackProc) */ PasteGameCB,
5028 NULL, /* client_data passed to PasteGameCB */
5030 /* better to use the time field from the event that triggered the
5031 * call to this function, but that isn't trivial to get
5041 SaveGameProc(NULL, NULL);
5045 void AnalyzeModeProc(w, event, prms, nprms)
5053 if (!first.analysisSupport) {
5054 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
5055 DisplayError(buf, 0);
5058 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
5059 if (appData.icsActive) {
5060 if (gameMode != IcsObserving) {
5061 sprintf(buf,_("You are not observing a game"));
5062 DisplayError(buf, 0);
5064 if (appData.icsEngineAnalyze) {
5065 if (appData.debugMode)
5066 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5072 /* if enable, use want disable icsEngineAnalyze */
5073 if (appData.icsEngineAnalyze) {
5078 appData.icsEngineAnalyze = TRUE;
5079 if (appData.debugMode)
5080 fprintf(debugFP, _("ICS engine analyze starting... \n"));
5082 if (!appData.showThinking)
5083 ShowThinkingProc(NULL,NULL);
5088 void EditGameProc(w, event, prms, nprms)
5097 void EditPositionProc(w, event, prms, nprms)
5103 EditPositionEvent();
5106 void TrainingProc(w, event, prms, nprms)
5115 void EditCommentProc(w, event, prms, nprms)
5122 EditCommentPopDown();
5128 void IcsInputBoxProc(w, event, prms, nprms)
5134 if (ICSInputBoxUp) {
5135 ICSInputBoxPopDown();
5142 void EnterKeyProc(w, event, prms, nprms)
5148 if (ICSInputBoxUp == True)
5153 void PonderNextMoveProc(w, event, prms, nprms)
5161 PonderNextMoveEvent(!appData.ponderNextMove);
5163 if (appData.ponderNextMove) {
5164 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5166 XtSetArg(args[0], XtNleftBitmap, None);
5168 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
5172 void PopupExitMessageProc(w, event, prms, nprms)
5180 appData.popupExitMessage = !appData.popupExitMessage;
5182 if (appData.popupExitMessage) {
5183 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5185 XtSetArg(args[0], XtNleftBitmap, None);
5187 XtSetValues(XtNameToWidget(menuBarWidget,
5188 "menuOptions.Popup Exit Message"), args, 1);
5191 void PopupMoveErrorsProc(w, event, prms, nprms)
5199 appData.popupMoveErrors = !appData.popupMoveErrors;
5201 if (appData.popupMoveErrors) {
5202 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5204 XtSetArg(args[0], XtNleftBitmap, None);
5206 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
5210 void PremoveProc(w, event, prms, nprms)
5218 appData.premove = !appData.premove;
5220 if (appData.premove) {
5221 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5223 XtSetArg(args[0], XtNleftBitmap, None);
5225 XtSetValues(XtNameToWidget(menuBarWidget,
5226 "menuOptions.Premove"), args, 1);
5229 void QuietPlayProc(w, event, prms, nprms)
5237 appData.quietPlay = !appData.quietPlay;
5239 if (appData.quietPlay) {
5240 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5242 XtSetArg(args[0], XtNleftBitmap, None);
5244 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
5248 void DebugProc(w, event, prms, nprms)
5254 appData.debugMode = !appData.debugMode;
5257 void AboutGameProc(w, event, prms, nprms)
5266 void NothingProc(w, event, prms, nprms)
5275 void Iconify(w, event, prms, nprms)
5284 XtSetArg(args[0], XtNiconic, True);
5285 XtSetValues(shellWidget, args, 1);
5288 void DisplayMessage(message, extMessage)
5289 gchar *message, *extMessage;
5296 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
5299 message = extMessage;
5302 gtk_label_set_text( GTK_LABEL(gtk_builder_get_object (builder, "Messages")),message);
5307 void DisplayTitle(text)
5310 gchar title[MSG_SIZ];
5312 if (text == NULL) text = "";
5314 if (appData.titleInWindow)
5319 if (*text != NULLCHAR)
5321 strcpy(title, text);
5323 else if (appData.icsActive)
5325 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
5327 else if (appData.cmailGameName[0] != NULLCHAR)
5329 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
5331 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
5333 else if (gameInfo.variant == VariantGothic)
5335 strcpy(title, GOTHIC);
5339 else if (gameInfo.variant == VariantFalcon)
5341 strcpy(title, FALCON);
5344 else if (appData.noChessProgram)
5346 strcpy(title, programName);
5350 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
5352 gtk_window_set_title(GTK_WINDOW(GUI_Window),title);
5358 void DisplayError(message, error)
5365 if (appData.debugMode || appData.matchMode) {
5366 fprintf(stderr, "%s: %s\n", programName, message);
5369 if (appData.debugMode || appData.matchMode) {
5370 fprintf(stderr, "%s: %s: %s\n",
5371 programName, message, strerror(error));
5373 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5376 ErrorPopUp(_("Error"), message, FALSE);
5380 void DisplayMoveError(message)
5385 DrawPosition(FALSE, NULL);
5386 if (appData.debugMode || appData.matchMode) {
5387 fprintf(stderr, "%s: %s\n", programName, message);
5389 if (appData.popupMoveErrors) {
5390 ErrorPopUp(_("Error"), message, FALSE);
5392 DisplayMessage(message, "");
5397 void DisplayFatalError(message, error, status)
5403 errorExitStatus = status;
5405 fprintf(stderr, "%s: %s\n", programName, message);
5407 fprintf(stderr, "%s: %s: %s\n",
5408 programName, message, strerror(error));
5409 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
5412 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
5413 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
5419 void DisplayInformation(message)
5423 ErrorPopUp(_("Information"), message, TRUE);
5426 void DisplayNote(message)
5430 ErrorPopUp(_("Note"), message, FALSE);
5434 NullXErrorCheck(dpy, error_event)
5436 XErrorEvent *error_event;
5441 void DisplayIcsInteractionTitle(message)
5444 if (oldICSInteractionTitle == NULL) {
5445 /* Magic to find the old window title, adapted from vim */
5446 char *wina = getenv("WINDOWID");
5448 Window win = (Window) atoi(wina);
5449 Window root, parent, *children;
5450 unsigned int nchildren;
5451 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
5453 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
5454 if (!XQueryTree(xDisplay, win, &root, &parent,
5455 &children, &nchildren)) break;
5456 if (children) XFree((void *)children);
5457 if (parent == root || parent == 0) break;
5460 XSetErrorHandler(oldHandler);
5462 if (oldICSInteractionTitle == NULL) {
5463 oldICSInteractionTitle = "xterm";
5466 printf("\033]0;%s\007", message);
5470 char pendingReplyPrefix[MSG_SIZ];
5471 ProcRef pendingReplyPR;
5473 void AskQuestionProc(w, event, prms, nprms)
5480 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
5484 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
5487 void AskQuestionPopDown()
5489 if (!askQuestionUp) return;
5490 XtPopdown(askQuestionShell);
5491 XtDestroyWidget(askQuestionShell);
5492 askQuestionUp = False;
5495 void AskQuestionReplyAction(w, event, prms, nprms)
5505 reply = XawDialogGetValueString(w = XtParent(w));
5506 strcpy(buf, pendingReplyPrefix);
5507 if (*buf) strcat(buf, " ");
5510 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
5511 AskQuestionPopDown();
5513 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
5516 void AskQuestionCallback(w, client_data, call_data)
5518 XtPointer client_data, call_data;
5523 XtSetArg(args[0], XtNlabel, &name);
5524 XtGetValues(w, args, 1);
5526 if (strcmp(name, _("cancel")) == 0) {
5527 AskQuestionPopDown();
5529 AskQuestionReplyAction(w, NULL, NULL, NULL);
5533 void AskQuestion(title, question, replyPrefix, pr)
5534 char *title, *question, *replyPrefix;
5538 Widget popup, layout, dialog, edit;
5544 strcpy(pendingReplyPrefix, replyPrefix);
5545 pendingReplyPR = pr;
5548 XtSetArg(args[i], XtNresizable, True); i++;
5549 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5550 askQuestionShell = popup =
5551 XtCreatePopupShell(title, transientShellWidgetClass,
5552 shellWidget, args, i);
5555 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5556 layoutArgs, XtNumber(layoutArgs));
5559 XtSetArg(args[i], XtNlabel, question); i++;
5560 XtSetArg(args[i], XtNvalue, ""); i++;
5561 XtSetArg(args[i], XtNborderWidth, 0); i++;
5562 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
5565 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
5566 (XtPointer) dialog);
5567 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
5568 (XtPointer) dialog);
5570 XtRealizeWidget(popup);
5571 CatchDeleteWindow(popup, "AskQuestionPopDown");
5573 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5574 &x, &y, &win_x, &win_y, &mask);
5576 XtSetArg(args[0], XtNx, x - 10);
5577 XtSetArg(args[1], XtNy, y - 30);
5578 XtSetValues(popup, args, 2);
5580 XtPopup(popup, XtGrabExclusive);
5581 askQuestionUp = True;
5583 edit = XtNameToWidget(dialog, "*value");
5584 XtSetKeyboardFocus(popup, edit);
5592 if (*name == NULLCHAR) {
5594 } else if (strcmp(name, "$") == 0) {
5595 putc(BELLCHAR, stderr);
5598 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
5606 PlaySound(appData.soundMove);
5612 PlaySound(appData.soundIcsWin);
5618 PlaySound(appData.soundIcsLoss);
5624 PlaySound(appData.soundIcsDraw);
5628 PlayIcsUnfinishedSound()
5630 PlaySound(appData.soundIcsUnfinished);
5636 PlaySound(appData.soundIcsAlarm);
5642 system("stty echo");
5648 system("stty -echo");
5652 Colorize(cc, continuation)
5657 int count, outCount, error;
5659 if (textColors[(int)cc].bg > 0) {
5660 if (textColors[(int)cc].fg > 0) {
5661 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
5662 textColors[(int)cc].fg, textColors[(int)cc].bg);
5664 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5665 textColors[(int)cc].bg);
5668 if (textColors[(int)cc].fg > 0) {
5669 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
5670 textColors[(int)cc].fg);
5672 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
5675 count = strlen(buf);
5676 outCount = OutputToProcess(NoProc, buf, count, &error);
5677 if (outCount < count) {
5678 DisplayFatalError(_("Error writing to display"), error, 1);
5681 if (continuation) return;
5684 PlaySound(appData.soundShout);
5687 PlaySound(appData.soundSShout);
5690 PlaySound(appData.soundChannel1);
5693 PlaySound(appData.soundChannel);
5696 PlaySound(appData.soundKibitz);
5699 PlaySound(appData.soundTell);
5701 case ColorChallenge:
5702 PlaySound(appData.soundChallenge);
5705 PlaySound(appData.soundRequest);
5708 PlaySound(appData.soundSeek);
5719 return getpwuid(getuid())->pw_name;
5722 static char *ExpandPathName(path)
5725 static char static_buf[2000];
5726 char *d, *s, buf[2000];
5732 while (*s && isspace(*s))
5741 if (*(s+1) == '/') {
5742 strcpy(d, getpwuid(getuid())->pw_dir);
5747 *strchr(buf, '/') = 0;
5748 pwd = getpwnam(buf);
5751 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
5755 strcpy(d, pwd->pw_dir);
5756 strcat(d, strchr(s+1, '/'));
5767 static char host_name[MSG_SIZ];
5769 #if HAVE_GETHOSTNAME
5770 gethostname(host_name, MSG_SIZ);
5772 #else /* not HAVE_GETHOSTNAME */
5773 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
5774 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
5776 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5778 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
5779 #endif /* not HAVE_GETHOSTNAME */
5782 guint delayedEventTimerTag = 0;
5783 DelayedEventCallback delayedEventCallback = 0;
5786 FireDelayedEvent(data)
5790 g_source_remove(delayedEventTimerTag);
5791 delayedEventTimerTag = 0;
5794 delayedEventCallback();
5800 ScheduleDelayedEvent(cb, millisec)
5801 DelayedEventCallback cb; guint millisec;
5803 if(delayedEventTimerTag && delayedEventCallback == cb)
5804 // [HGM] alive: replace, rather than add or flush identical event
5805 g_source_remove(delayedEventTimerTag);
5806 delayedEventCallback = cb;
5807 delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL);
5811 DelayedEventCallback
5814 if (delayedEventTimerTag)
5816 return delayedEventCallback;
5825 CancelDelayedEvent()
5827 if (delayedEventTimerTag)
5829 g_source_remove(delayedEventTimerTag);
5830 delayedEventTimerTag = 0;
5836 guint loadGameTimerTag = 0;
5838 int LoadGameTimerRunning()
5840 return loadGameTimerTag != 0;
5843 int StopLoadGameTimer()
5845 if (loadGameTimerTag != 0) {
5846 g_source_remove(loadGameTimerTag);
5847 loadGameTimerTag = 0;
5855 LoadGameTimerCallback(data)
5859 g_source_remove(loadGameTimerTag);
5860 loadGameTimerTag = 0;
5867 StartLoadGameTimer(millisec)
5871 g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL);
5875 guint analysisClockTag = 0;
5878 AnalysisClockCallback(data)
5881 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
5882 || appData.icsEngineAnalyze)
5884 AnalysisPeriodicEvent(0);
5885 return 1; /* keep on going */
5887 return 0; /* stop timer */
5891 StartAnalysisClock()
5894 g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL);
5898 guint clockTimerTag = 0;
5900 int ClockTimerRunning()
5902 return clockTimerTag != 0;
5905 int StopClockTimer()
5907 if (clockTimerTag != 0)
5909 g_source_remove(clockTimerTag);
5920 ClockTimerCallback(data)
5924 g_source_remove(clockTimerTag);
5932 StartClockTimer(millisec)
5935 clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL);
5940 DisplayTimerLabel(w, color, timer, highlight)
5949 if (appData.clockMode) {
5950 sprintf(buf, "%s: %s", color, TimeString(timer));
5952 sprintf(buf, "%s ", color);
5954 gtk_label_set_text(GTK_LABEL(w),buf);
5956 /* check for low time warning */
5957 // Pixel foregroundOrWarningColor = timerForegroundPixel;
5960 // appData.lowTimeWarning &&
5961 // (timer / 1000) < appData.icsAlarmTime)
5962 // foregroundOrWarningColor = lowTimeWarningColor;
5964 // if (appData.clockMode) {
5965 // sprintf(buf, "%s: %s", color, TimeString(timer));
5966 // XtSetArg(args[0], XtNlabel, buf);
5968 // sprintf(buf, "%s ", color);
5969 // XtSetArg(args[0], XtNlabel, buf);
5974 // XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
5975 // XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
5977 // XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
5978 // XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
5981 // XtSetValues(w, args, 3);
5986 DisplayWhiteClock(timeRemaining, highlight)
5990 if(appData.noGUI) return;
5992 DisplayTimerLabel(GUI_Whiteclock, _("White"), timeRemaining, highlight);
5993 if (highlight && WindowIcon == BlackIcon)
5995 WindowIcon = WhiteIcon;
5996 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6001 DisplayBlackClock(timeRemaining, highlight)
6005 if(appData.noGUI) return;
6007 DisplayTimerLabel(GUI_Blackclock, _("Black"), timeRemaining, highlight);
6008 if (highlight && WindowIcon == WhiteIcon)
6010 WindowIcon = BlackIcon;
6011 gtk_window_set_icon(GTK_WINDOW(GUI_Window),WindowIcon);
6029 int StartChildProcess(cmdLine, dir, pr)
6036 int to_prog[2], from_prog[2];
6040 if (appData.debugMode) {
6041 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
6044 /* We do NOT feed the cmdLine to the shell; we just
6045 parse it into blank-separated arguments in the
6046 most simple-minded way possible.
6049 strcpy(buf, cmdLine);
6054 if (p == NULL) break;
6059 SetUpChildIO(to_prog, from_prog);
6061 if ((pid = fork()) == 0) {
6063 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
6064 close(to_prog[1]); // first close the unused pipe ends
6065 close(from_prog[0]);
6066 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
6067 dup2(from_prog[1], 1);
6068 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
6069 close(from_prog[1]); // and closing again loses one of the pipes!
6070 if(fileno(stderr) >= 2) // better safe than sorry...
6071 dup2(1, fileno(stderr)); /* force stderr to the pipe */
6073 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
6078 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
6080 execvp(argv[0], argv);
6082 /* If we get here, exec failed */
6087 /* Parent process */
6089 close(from_prog[1]);
6091 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6094 cp->fdFrom = from_prog[0];
6095 cp->fdTo = to_prog[1];
6100 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
6101 static RETSIGTYPE AlarmCallBack(int n)
6107 DestroyChildProcess(pr, signalType)
6111 ChildProc *cp = (ChildProc *) pr;
6113 if (cp->kind != CPReal) return;
6115 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
6116 signal(SIGALRM, AlarmCallBack);
6118 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
6119 kill(cp->pid, SIGKILL); // kill it forcefully
6120 wait((int *) 0); // and wait again
6124 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
6126 /* Process is exiting either because of the kill or because of
6127 a quit command sent by the backend; either way, wait for it to die.
6136 InterruptChildProcess(pr)
6139 ChildProc *cp = (ChildProc *) pr;
6141 if (cp->kind != CPReal) return;
6142 (void) kill(cp->pid, SIGINT); /* stop it thinking */
6145 int OpenTelnet(host, port, pr)
6150 char cmdLine[MSG_SIZ];
6152 if (port[0] == NULLCHAR) {
6153 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
6155 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
6157 return StartChildProcess(cmdLine, "", pr);
6160 int OpenTCP(host, port, pr)
6166 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
6167 #else /* !OMIT_SOCKETS */
6169 struct sockaddr_in sa;
6171 unsigned short uport;
6174 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
6178 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6179 sa.sin_family = AF_INET;
6180 sa.sin_addr.s_addr = INADDR_ANY;
6181 uport = (unsigned short) 0;
6182 sa.sin_port = htons(uport);
6183 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
6187 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
6188 if (!(hp = gethostbyname(host))) {
6190 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
6191 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
6192 hp->h_addrtype = AF_INET;
6194 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
6195 hp->h_addr_list[0] = (char *) malloc(4);
6196 hp->h_addr_list[0][0] = b0;
6197 hp->h_addr_list[0][1] = b1;
6198 hp->h_addr_list[0][2] = b2;
6199 hp->h_addr_list[0][3] = b3;
6204 sa.sin_family = hp->h_addrtype;
6205 uport = (unsigned short) atoi(port);
6206 sa.sin_port = htons(uport);
6207 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
6209 if (connect(s, (struct sockaddr *) &sa,
6210 sizeof(struct sockaddr_in)) < 0) {
6214 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6221 #endif /* !OMIT_SOCKETS */
6226 int OpenCommPort(name, pr)
6233 fd = open(name, 2, 0);
6234 if (fd < 0) return errno;
6236 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6246 int OpenLoopback(pr)
6252 SetUpChildIO(to, from);
6254 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
6257 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
6264 int OpenRcmd(host, user, cmd, pr)
6265 char *host, *user, *cmd;
6268 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
6272 #define INPUT_SOURCE_BUF_SIZE 8192
6281 char buf[INPUT_SOURCE_BUF_SIZE];
6286 DoInputCallback(io,cond,data)
6291 /* read input from one of the input source (for example a chess program, ICS, etc).
6292 * and call a function that will handle the input
6295 int count; /* how many bytes did we read */
6299 /* All information (callback function, file descriptor, etc) is
6300 * saved in an InputSource structure
6302 InputSource *is = (InputSource *) data;
6306 count = read(is->fd, is->unused,
6307 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
6311 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
6314 is->unused += count;
6316 /* break input into lines and call the callback function on each
6319 while (p < is->unused)
6321 q = memchr(p, '\n', is->unused - p);
6322 if (q == NULL) break;
6324 (is->func)(is, is->closure, p, q - p, 0);
6327 /* remember not yet used part of the buffer */
6329 while (p < is->unused)
6337 /* read maximum length of input buffer and send the whole buffer
6338 * to the callback function
6340 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
6345 (is->func)(is, is->closure, is->buf, count, error);
6351 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
6358 GIOChannel *channel;
6359 ChildProc *cp = (ChildProc *) pr;
6361 is = (InputSource *) calloc(1, sizeof(InputSource));
6362 is->lineByLine = lineByLine;
6366 is->fd = fileno(stdin);
6368 is->kind = cp->kind;
6369 is->fd = cp->fdFrom;
6372 is->unused = is->buf;
6376 // is->xid = XtAppAddInput(appContext, is->fd,
6377 // (XtPointer) (XtInputReadMask),
6378 // (XtInputCallbackProc) DoInputCallback,
6382 /* TODO: will this work on windows?*/
6383 printf("DEBUG: fd=%d %d\n",is->fd,is);
6385 channel = g_io_channel_unix_new(is->fd);
6386 g_io_channel_set_close_on_unref (channel, TRUE);
6387 is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
6388 is->closure = closure;
6389 return (InputSourceRef) is;
6393 RemoveInputSource(isr)
6396 InputSource *is = (InputSource *) isr;
6398 if (is->sid == 0) return;
6399 g_source_remove(is->sid);
6404 int OutputToProcess(pr, message, count, outError)
6410 static int line = 0;
6411 ChildProc *cp = (ChildProc *) pr;
6416 if (appData.noJoin || !appData.useInternalWrap)
6417 outCount = fwrite(message, 1, count, stdout);
6420 int width = get_term_width();
6421 int len = wrap(NULL, message, count, width, &line);
6422 char *msg = malloc(len);
6426 outCount = fwrite(message, 1, count, stdout);
6429 dbgchk = wrap(msg, message, count, width, &line);
6430 if (dbgchk != len && appData.debugMode)
6431 fprintf(debugFP, "wrap(): dbgchk(%d) != len(%d)\n", dbgchk, len);
6432 outCount = fwrite(msg, 1, dbgchk, stdout);
6438 outCount = write(cp->fdTo, message, count);
6448 /* Output message to process, with "ms" milliseconds of delay
6449 between each character. This is needed when sending the logon
6450 script to ICC, which for some reason doesn't like the
6451 instantaneous send. */
6452 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
6459 ChildProc *cp = (ChildProc *) pr;
6464 r = write(cp->fdTo, message++, 1);
6477 /**** Animation code by Hugh Fisher, DCS, ANU.
6479 Known problem: if a window overlapping the board is
6480 moved away while a piece is being animated underneath,
6481 the newly exposed area won't be updated properly.
6482 I can live with this.
6484 Known problem: if you look carefully at the animation
6485 of pieces in mono mode, they are being drawn as solid
6486 shapes without interior detail while moving. Fixing
6487 this would be a major complication for minimal return.
6490 /* Masks for XPM pieces. Black and white pieces can have
6491 different shapes, but in the interest of retaining my
6492 sanity pieces must have the same outline on both light
6493 and dark squares, and all pieces must use the same
6494 background square colors/images. */
6496 static int xpmDone = 0;
6499 CreateAnimMasks (pieceDepth)
6506 unsigned long plane;
6509 /* just return for gtk at the moment */
6512 /* Need a bitmap just to get a GC with right depth */
6513 buf = XCreatePixmap(xDisplay, xBoardWindow,
6515 values.foreground = 1;
6516 values.background = 0;
6517 /* Don't use XtGetGC, not read only */
6518 maskGC = XCreateGC(xDisplay, buf,
6519 GCForeground | GCBackground, &values);
6520 XFreePixmap(xDisplay, buf);
6522 buf = XCreatePixmap(xDisplay, xBoardWindow,
6523 squareSize, squareSize, pieceDepth);
6524 values.foreground = XBlackPixel(xDisplay, xScreen);
6525 values.background = XWhitePixel(xDisplay, xScreen);
6526 bufGC = XCreateGC(xDisplay, buf,
6527 GCForeground | GCBackground, &values);
6529 for (piece = WhitePawn; piece <= BlackKing; piece++) {
6530 /* Begin with empty mask */
6531 if(!xpmDone) // [HGM] pieces: keep using existing
6532 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
6533 squareSize, squareSize, 1);
6534 XSetFunction(xDisplay, maskGC, GXclear);
6535 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
6536 0, 0, squareSize, squareSize);
6538 /* Take a copy of the piece */
6543 XSetFunction(xDisplay, bufGC, GXcopy);
6544 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
6546 0, 0, squareSize, squareSize, 0, 0);
6548 /* XOR the background (light) over the piece */
6549 XSetFunction(xDisplay, bufGC, GXxor);
6551 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
6552 0, 0, squareSize, squareSize, 0, 0);
6554 XSetForeground(xDisplay, bufGC, lightSquareColor);
6555 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
6558 /* We now have an inverted piece image with the background
6559 erased. Construct mask by just selecting all the non-zero
6560 pixels - no need to reconstruct the original image. */
6561 XSetFunction(xDisplay, maskGC, GXor);
6563 /* Might be quicker to download an XImage and create bitmap
6564 data from it rather than this N copies per piece, but it
6565 only takes a fraction of a second and there is a much
6566 longer delay for loading the pieces. */
6567 for (n = 0; n < pieceDepth; n ++) {
6568 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
6569 0, 0, squareSize, squareSize,
6575 XFreePixmap(xDisplay, buf);
6576 XFreeGC(xDisplay, bufGC);
6577 XFreeGC(xDisplay, maskGC);
6581 InitAnimState (anim, info)
6583 XWindowAttributes * info;
6588 /* Each buffer is square size, same depth as window */
6589 // anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
6590 // squareSize, squareSize, info->depth);
6591 // anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
6592 // squareSize, squareSize, info->depth);
6594 // /* Create a plain GC for blitting */
6595 // mask = GCForeground | GCBackground | GCFunction |
6596 // GCPlaneMask | GCGraphicsExposures;
6597 // values.foreground = XBlackPixel(xDisplay, xScreen);
6598 // values.background = XWhitePixel(xDisplay, xScreen);
6599 // values.function = GXcopy;
6600 // values.plane_mask = AllPlanes;
6601 // values.graphics_exposures = False;
6602 // anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
6604 // /* Piece will be copied from an existing context at
6605 // the start of each new animation/drag. */
6606 // anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
6608 // /* Outline will be a read-only copy of an existing */
6609 // anim->outlineGC = None;
6615 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
6616 XWindowAttributes info;
6618 /* for gtk at the moment just ... */
6621 if (xpmDone && gameInfo.variant == old) return;
6622 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
6623 // XGetWindowAttributes(xDisplay, xBoardWindow, &info);
6625 // InitAnimState(&game, &info);
6626 // InitAnimState(&player, &info);
6628 /* For XPM pieces, we need bitmaps to use as masks. */
6630 // CreateAnimMasks(info.depth);
6636 static Boolean frameWaiting;
6638 static RETSIGTYPE FrameAlarm (sig)
6641 frameWaiting = False;
6642 /* In case System-V style signals. Needed?? */
6643 signal(SIGALRM, FrameAlarm);
6650 struct itimerval delay;
6652 XSync(xDisplay, False);
6655 frameWaiting = True;
6656 signal(SIGALRM, FrameAlarm);
6657 delay.it_interval.tv_sec =
6658 delay.it_value.tv_sec = time / 1000;
6659 delay.it_interval.tv_usec =
6660 delay.it_value.tv_usec = (time % 1000) * 1000;
6661 setitimer(ITIMER_REAL, &delay, NULL);
6662 while (frameWaiting) pause();
6663 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
6664 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
6665 setitimer(ITIMER_REAL, &delay, NULL);
6675 // XSync(xDisplay, False);
6677 usleep(time * 1000);
6682 /* Convert board position to corner of screen rect and color */
6685 ScreenSquare(column, row, pt, color)
6686 int column; int row; XPoint * pt; int * color;
6689 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
6690 pt->y = lineGap + row * (squareSize + lineGap);
6692 pt->x = lineGap + column * (squareSize + lineGap);
6693 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
6695 *color = SquareColor(row, column);
6698 /* Convert window coords to square */
6701 BoardSquare(x, y, column, row)
6702 int x; int y; int * column; int * row;
6704 *column = EventToSquare(x, BOARD_WIDTH);
6705 if (flipView && *column >= 0)
6706 *column = BOARD_WIDTH - 1 - *column;
6707 *row = EventToSquare(y, BOARD_HEIGHT);
6708 if (!flipView && *row >= 0)
6709 *row = BOARD_HEIGHT - 1 - *row;
6714 #undef Max /* just in case */
6716 #define Max(a, b) ((a) > (b) ? (a) : (b))
6717 #define Min(a, b) ((a) < (b) ? (a) : (b))
6720 SetRect(rect, x, y, width, height)
6721 XRectangle * rect; int x; int y; int width; int height;
6725 rect->width = width;
6726 rect->height = height;
6729 /* Test if two frames overlap. If they do, return
6730 intersection rect within old and location of
6731 that rect within new. */
6734 Intersect(old, new, size, area, pt)
6735 XPoint * old; XPoint * new;
6736 int size; XRectangle * area; XPoint * pt;
6738 if (old->x > new->x + size || new->x > old->x + size ||
6739 old->y > new->y + size || new->y > old->y + size) {
6742 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
6743 size - abs(old->x - new->x), size - abs(old->y - new->y));
6744 pt->x = Max(old->x - new->x, 0);
6745 pt->y = Max(old->y - new->y, 0);
6750 /* For two overlapping frames, return the rect(s)
6751 in the old that do not intersect with the new. */
6754 CalcUpdateRects(old, new, size, update, nUpdates)
6755 XPoint * old; XPoint * new; int size;
6756 XRectangle update[]; int * nUpdates;
6760 /* If old = new (shouldn't happen) then nothing to draw */
6761 if (old->x == new->x && old->y == new->y) {
6765 /* Work out what bits overlap. Since we know the rects
6766 are the same size we don't need a full intersect calc. */
6768 /* Top or bottom edge? */
6769 if (new->y > old->y) {
6770 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
6772 } else if (old->y > new->y) {
6773 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
6774 size, old->y - new->y);
6777 /* Left or right edge - don't overlap any update calculated above. */
6778 if (new->x > old->x) {
6779 SetRect(&(update[count]), old->x, Max(new->y, old->y),
6780 new->x - old->x, size - abs(new->y - old->y));
6782 } else if (old->x > new->x) {
6783 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
6784 old->x - new->x, size - abs(new->y - old->y));
6791 /* Generate a series of frame coords from start->mid->finish.
6792 The movement rate doubles until the half way point is
6793 reached, then halves back down to the final destination,
6794 which gives a nice slow in/out effect. The algorithmn
6795 may seem to generate too many intermediates for short
6796 moves, but remember that the purpose is to attract the
6797 viewers attention to the piece about to be moved and
6798 then to where it ends up. Too few frames would be less
6802 Tween(start, mid, finish, factor, frames, nFrames)
6803 XPoint * start; XPoint * mid;
6804 XPoint * finish; int factor;
6805 XPoint frames[]; int * nFrames;
6807 int fraction, n, count;
6811 /* Slow in, stepping 1/16th, then 1/8th, ... */
6813 for (n = 0; n < factor; n++)
6815 for (n = 0; n < factor; n++) {
6816 frames[count].x = start->x + (mid->x - start->x) / fraction;
6817 frames[count].y = start->y + (mid->y - start->y) / fraction;
6819 fraction = fraction / 2;
6823 frames[count] = *mid;
6826 /* Slow out, stepping 1/2, then 1/4, ... */
6828 for (n = 0; n < factor; n++) {
6829 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
6830 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
6832 fraction = fraction * 2;
6837 /* Draw a piece on the screen without disturbing what's there */
6840 SelectGCMask(piece, clip, outline, mask)
6841 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
6845 /* Bitmap for piece being moved. */
6846 if (appData.monoMode) {
6847 *mask = *pieceToSolid(piece);
6848 } else if (useImages) {
6850 *mask = xpmMask[piece];
6852 *mask = ximMaskPm[piece];
6855 *mask = *pieceToSolid(piece);
6858 /* GC for piece being moved. Square color doesn't matter, but
6859 since it gets modified we make a copy of the original. */
6861 if (appData.monoMode)
6866 if (appData.monoMode)
6871 // XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
6873 /* Outline only used in mono mode and is not modified */
6875 *outline = bwPieceGC;
6877 *outline = wbPieceGC;
6881 OverlayPiece(piece, clip, outline, dest)
6882 ChessSquare piece; GC clip; GC outline; Drawable dest;
6887 /* Draw solid rectangle which will be clipped to shape of piece */
6888 // XFillRectangle(xDisplay, dest, clip,
6889 // 0, 0, squareSize, squareSize)
6891 if (appData.monoMode)
6892 /* Also draw outline in contrasting color for black
6893 on black / white on white cases */
6894 // XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
6895 // 0, 0, squareSize, squareSize, 0, 0, 1)
6898 /* Copy the piece */
6903 // XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
6905 // 0, 0, squareSize, squareSize,
6910 /* Animate the movement of a single piece */
6913 BeginAnimation(anim, piece, startColor, start)
6921 /* The old buffer is initialised with the start square (empty) */
6922 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
6923 anim->prevFrame = *start;
6925 /* The piece will be drawn using its own bitmap as a matte */
6926 // SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
6927 // XSetClipMask(xDisplay, anim->pieceGC, mask);
6931 AnimationFrame(anim, frame, piece)
6936 XRectangle updates[4];
6941 /* Save what we are about to draw into the new buffer */
6942 // XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
6943 // frame->x, frame->y, squareSize, squareSize,
6946 /* Erase bits of the previous frame */
6947 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
6948 /* Where the new frame overlapped the previous,
6949 the contents in newBuf are wrong. */
6950 // XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
6951 // overlap.x, overlap.y,
6952 // overlap.width, overlap.height,
6954 /* Repaint the areas in the old that don't overlap new */
6955 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
6956 for (i = 0; i < count; i++)
6957 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6958 // updates[i].x - anim->prevFrame.x,
6959 // updates[i].y - anim->prevFrame.y,
6960 // updates[i].width, updates[i].height,
6961 // updates[i].x, updates[i].y)
6964 /* Easy when no overlap */
6965 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
6966 // 0, 0, squareSize, squareSize,
6967 // anim->prevFrame.x, anim->prevFrame.y);
6970 /* Save this frame for next time round */
6971 // XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
6972 // 0, 0, squareSize, squareSize,
6974 anim->prevFrame = *frame;
6976 /* Draw piece over original screen contents, not current,
6977 and copy entire rect. Wipes out overlapping piece images. */
6978 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
6979 // XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
6980 // 0, 0, squareSize, squareSize,
6981 // frame->x, frame->y);
6985 EndAnimation (anim, finish)
6989 XRectangle updates[4];
6994 /* The main code will redraw the final square, so we
6995 only need to erase the bits that don't overlap. */
6996 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
6997 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
6998 for (i = 0; i < count; i++)
6999 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7000 // updates[i].x - anim->prevFrame.x,
7001 // updates[i].y - anim->prevFrame.y,
7002 // updates[i].width, updates[i].height,
7003 // updates[i].x, updates[i].y)
7006 // XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
7007 // 0, 0, squareSize, squareSize,
7008 // anim->prevFrame.x, anim->prevFrame.y);
7013 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
7015 ChessSquare piece; int startColor;
7016 XPoint * start; XPoint * finish;
7017 XPoint frames[]; int nFrames;
7021 BeginAnimation(anim, piece, startColor, start);
7022 for (n = 0; n < nFrames; n++) {
7023 AnimationFrame(anim, &(frames[n]), piece);
7024 FrameDelay(appData.animSpeed);
7026 EndAnimation(anim, finish);
7029 /* Main control logic for deciding what to animate and how */
7032 AnimateMove(board, fromX, fromY, toX, toY)
7041 XPoint start, finish, mid;
7042 XPoint frames[kFactor * 2 + 1];
7043 int nFrames, startColor, endColor;
7045 /* Are we animating? */
7046 if (!appData.animate || appData.blindfold)
7049 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
7050 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
7051 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
7053 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
7054 piece = board[fromY][fromX];
7055 if (piece >= EmptySquare) return;
7060 hop = (piece == WhiteKnight || piece == BlackKnight);
7063 if (appData.debugMode) {
7064 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
7065 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
7066 piece, fromX, fromY, toX, toY); }
7068 ScreenSquare(fromX, fromY, &start, &startColor);
7069 ScreenSquare(toX, toY, &finish, &endColor);
7072 /* Knight: make diagonal movement then straight */
7073 if (abs(toY - fromY) < abs(toX - fromX)) {
7074 mid.x = start.x + (finish.x - start.x) / 2;
7078 mid.y = start.y + (finish.y - start.y) / 2;
7081 mid.x = start.x + (finish.x - start.x) / 2;
7082 mid.y = start.y + (finish.y - start.y) / 2;
7085 /* Don't use as many frames for very short moves */
7086 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
7087 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
7089 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
7090 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
7092 /* Be sure end square is redrawn */
7093 damage[toY][toX] = True;
7097 DragPieceBegin(x, y)
7100 int boardX, boardY, color;
7103 /* Are we animating? */
7104 if (!appData.animateDragging || appData.blindfold)
7107 /* Figure out which square we start in and the
7108 mouse position relative to top left corner. */
7109 BoardSquare(x, y, &boardX, &boardY);
7110 player.startBoardX = boardX;
7111 player.startBoardY = boardY;
7112 ScreenSquare(boardX, boardY, &corner, &color);
7113 player.startSquare = corner;
7114 player.startColor = color;
7115 /* As soon as we start dragging, the piece will jump slightly to
7116 be centered over the mouse pointer. */
7117 player.mouseDelta.x = squareSize/2;
7118 player.mouseDelta.y = squareSize/2;
7119 /* Initialise animation */
7120 player.dragPiece = PieceForSquare(boardX, boardY);
7122 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
7123 player.dragActive = True;
7124 BeginAnimation(&player, player.dragPiece, color, &corner);
7125 /* Mark this square as needing to be redrawn. Note that
7126 we don't remove the piece though, since logically (ie
7127 as seen by opponent) the move hasn't been made yet. */
7128 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
7129 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
7130 // XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
7131 // corner.x, corner.y, squareSize, squareSize,
7132 // 0, 0); // [HGM] zh: unstack in stead of grab
7133 damage[boardY][boardX] = True;
7135 player.dragActive = False;
7145 /* Are we animating? */
7146 if (!appData.animateDragging || appData.blindfold)
7150 if (! player.dragActive)
7152 /* Move piece, maintaining same relative position
7153 of mouse within square */
7154 corner.x = x - player.mouseDelta.x;
7155 corner.y = y - player.mouseDelta.y;
7156 AnimationFrame(&player, &corner, player.dragPiece);
7158 if (appData.highlightDragging) {
7160 BoardSquare(x, y, &boardX, &boardY);
7161 SetHighlights(fromX, fromY, boardX, boardY);
7170 int boardX, boardY, color;
7173 /* Are we animating? */
7174 if (!appData.animateDragging || appData.blindfold)
7178 if (! player.dragActive)
7180 /* Last frame in sequence is square piece is
7181 placed on, which may not match mouse exactly. */
7182 BoardSquare(x, y, &boardX, &boardY);
7183 ScreenSquare(boardX, boardY, &corner, &color);
7184 EndAnimation(&player, &corner);
7186 /* Be sure end square is redrawn */
7187 damage[boardY][boardX] = True;
7189 /* This prevents weird things happening with fast successive
7190 clicks which on my Sun at least can cause motion events
7191 without corresponding press/release. */
7192 player.dragActive = False;
7195 /* Handle expose event while piece being dragged */
7200 if (!player.dragActive || appData.blindfold)
7203 /* What we're doing: logically, the move hasn't been made yet,
7204 so the piece is still in it's original square. But visually
7205 it's being dragged around the board. So we erase the square
7206 that the piece is on and draw it at the last known drag point. */
7207 BlankSquare(player.startSquare.x, player.startSquare.y,
7208 player.startColor, EmptySquare, xBoardWindow);
7209 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
7210 damage[player.startBoardY][player.startBoardX] = TRUE;
7214 SetProgramStats( FrontEndProgramStats * stats )
7217 // [HGM] done, but perhaps backend should call this directly?
7218 EngineOutputUpdate( stats );
7221 #include <sys/ioctl.h>
7222 int get_term_width()
7224 int fd, default_width;
7227 default_width = 79; // this is FICS default anyway...
7229 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
7231 if (!ioctl(fd, TIOCGSIZE, &win))
7232 default_width = win.ts_cols;
7233 #elif defined(TIOCGWINSZ)
7235 if (!ioctl(fd, TIOCGWINSZ, &win))
7236 default_width = win.ws_col;
7238 return default_width;
7241 void update_ics_width()
7243 static int old_width = 0;
7244 int new_width = get_term_width();
7246 if (old_width != new_width)
7247 ics_printf("set width %d\n", new_width);
7248 old_width = new_width;
7251 void NotifyFrontendLogin()