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>
148 #include <X11/Xaw3d/Dialog.h>
149 #include <X11/Xaw3d/Form.h>
150 #include <X11/Xaw3d/List.h>
151 #include <X11/Xaw3d/Label.h>
152 #include <X11/Xaw3d/SimpleMenu.h>
153 #include <X11/Xaw3d/SmeBSB.h>
154 #include <X11/Xaw3d/SmeLine.h>
155 #include <X11/Xaw3d/Box.h>
156 #include <X11/Xaw3d/MenuButton.h>
157 #include <X11/Xaw3d/Text.h>
158 #include <X11/Xaw3d/AsciiText.h>
160 #include <X11/Xaw/Dialog.h>
161 #include <X11/Xaw/Form.h>
162 #include <X11/Xaw/List.h>
163 #include <X11/Xaw/Label.h>
164 #include <X11/Xaw/SimpleMenu.h>
165 #include <X11/Xaw/SmeBSB.h>
166 #include <X11/Xaw/SmeLine.h>
167 #include <X11/Xaw/Box.h>
168 #include <X11/Xaw/MenuButton.h>
169 #include <X11/Xaw/Text.h>
170 #include <X11/Xaw/AsciiText.h>
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
189 #include "frontend.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
199 // must be moved to xengineoutput.h
201 void EngineOutputProc P((Widget w, XEvent *event,
202 String *prms, Cardinal *nprms));
204 void EngineOutputPopDown();
211 #define usleep(t) _sleep2(((t)+500)/1000)
215 # define _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 RETSIGTYPE TermSizeSigHandler P((int sig));
236 void CreateGCs P((void));
237 void CreateXIMPieces P((void));
238 void CreateXPMPieces P((void));
239 void CreatePieces P((void));
240 void CreatePieceMenus P((void));
241 Widget CreateMenuBar P((Menu *mb));
242 Widget CreateButtonBar P ((MenuItem *mi));
243 char *FindFont P((char *pattern, int targetPxlSize));
244 void PieceMenuPopup P((Widget w, XEvent *event,
245 String *params, Cardinal *num_params));
246 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
248 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
249 u_int wreq, u_int hreq));
250 void CreateGrid P((void));
251 int EventToSquare P((int x, int limit));
252 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
253 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
254 void HandleUserMove P((Widget w, XEvent *event,
255 String *prms, Cardinal *nprms));
256 void AnimateUserMove P((Widget w, XEvent * event,
257 String * params, Cardinal * nParams));
258 void WhiteClock P((Widget w, XEvent *event,
259 String *prms, Cardinal *nprms));
260 void BlackClock P((Widget w, XEvent *event,
261 String *prms, Cardinal *nprms));
262 void DrawPositionProc P((Widget w, XEvent *event,
263 String *prms, Cardinal *nprms));
264 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
266 void CommentPopUp P((char *title, char *label));
267 void CommentPopDown P((void));
268 void CommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void ICSInputBoxPopUp P((void));
271 void ICSInputBoxPopDown P((void));
272 void FileNamePopUp P((char *label, char *def,
273 FileProc proc, char *openMode));
274 void FileNamePopDown P((void));
275 void FileNameCallback P((Widget w, XtPointer client_data,
276 XtPointer call_data));
277 void FileNameAction P((Widget w, XEvent *event,
278 String *prms, Cardinal *nprms));
279 void AskQuestionReplyAction P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void AskQuestionProc P((Widget w, XEvent *event,
282 String *prms, Cardinal *nprms));
283 void AskQuestionPopDown P((void));
284 void PromotionPopUp P((void));
285 void PromotionPopDown P((void));
286 void PromotionCallback P((Widget w, XtPointer client_data,
287 XtPointer call_data));
288 void EditCommentPopDown P((void));
289 void EditCommentCallback P((Widget w, XtPointer client_data,
290 XtPointer call_data));
291 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
292 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
294 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
296 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
298 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
300 void LoadPositionProc P((Widget w, XEvent *event,
301 String *prms, Cardinal *nprms));
302 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
304 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
306 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
308 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
310 void PastePositionProc P((Widget w, XEvent *event, String *prms,
312 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
315 void SavePositionProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
318 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
320 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
322 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
324 void MachineWhiteProc P((Widget w, XEvent *event,
325 String *prms, Cardinal *nprms));
326 void AnalyzeModeProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void AnalyzeFileProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
332 void IcsClientProc P((Widget w, XEvent *event, String *prms,
334 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void EditPositionProc P((Widget w, XEvent *event,
336 String *prms, Cardinal *nprms));
337 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void EditCommentProc P((Widget w, XEvent *event,
339 String *prms, Cardinal *nprms));
340 void IcsInputBoxProc P((Widget w, XEvent *event,
341 String *prms, Cardinal *nprms));
342 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void StopObservingProc P((Widget w, XEvent *event, String *prms,
356 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
358 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
365 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
367 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
370 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
372 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
374 void AutocommProc P((Widget w, XEvent *event, String *prms,
376 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void AutobsProc P((Widget w, XEvent *event, String *prms,
380 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
383 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
385 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
386 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
388 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
390 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
392 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
396 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
398 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
400 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
402 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
404 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
408 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
410 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
412 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
414 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
423 void DisplayMove P((int moveNumber));
424 void DisplayTitle P((char *title));
425 void ICSInitScript P((void));
426 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
427 void ErrorPopUp P((char *title, char *text, int modal));
428 void ErrorPopDown P((void));
429 static char *ExpandPathName P((char *path));
430 static void CreateAnimVars P((void));
431 static void DragPieceBegin P((int x, int y));
432 static void DragPieceMove P((int x, int y));
433 static void DragPieceEnd P((int x, int y));
434 static void DrawDragPiece P((void));
435 char *ModeToWidgetName P((GameMode mode));
436 void EngineOutputUpdate( FrontEndProgramStats * stats );
437 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
444 void ShufflePopDown P(());
445 void EnginePopDown P(());
446 void UciPopDown P(());
447 void TimeControlPopDown P(());
448 void NewVariantPopDown P(());
449 void SettingsPopDown P(());
450 void update_ics_width P(());
451 int get_term_width P(());
453 * XBoard depends on Xt R4 or higher
455 int xtVersion = XtSpecificationRelease;
460 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
461 jailSquareColor, highlightSquareColor, premoveHighlightColor;
462 Pixel lowTimeWarningColor;
463 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
464 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
465 wjPieceGC, bjPieceGC, prelineGC, countGC;
466 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
467 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
468 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
469 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
470 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
471 ICSInputShell, fileNameShell, askQuestionShell;
472 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
473 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
474 Font clockFontID, coordFontID, countFontID;
475 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
476 XtAppContext appContext;
478 char *oldICSInteractionTitle;
482 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
484 Position commentX = -1, commentY = -1;
485 Dimension commentW, commentH;
487 int squareSize, smallLayout = 0, tinyLayout = 0,
488 marginW, marginH, // [HGM] for run-time resizing
489 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
490 ICSInputBoxUp = False, askQuestionUp = False,
491 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
492 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
493 Pixel timerForegroundPixel, timerBackgroundPixel;
494 Pixel buttonForegroundPixel, buttonBackgroundPixel;
495 char *chessDir, *programName, *programVersion,
496 *gameCopyFilename, *gamePasteFilename;
500 Pixmap pieceBitmap[2][(int)BlackPawn];
501 Pixmap pieceBitmap2[2][(int)BlackPawn+4]; /* [HGM] pieces */
502 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD actually used*/
503 Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4]; /* LL, LD, DL, DD set to select from */
504 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
505 int useImages, useImageSqs;
506 XImage *ximPieceBitmap[4][(int)BlackPawn+4]; /* LL, LD, DL, DD */
507 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
508 Pixmap ximMaskPm2[(int)BlackPawn+4]; /* clipmasks, used for XIM pieces */
509 XImage *ximLightSquare, *ximDarkSquare;
512 #define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
513 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
515 #define White(piece) ((int)(piece) < (int)BlackPawn)
517 /* Variables for doing smooth animation. This whole thing
518 would be much easier if the board was double-buffered,
519 but that would require a fairly major rewrite. */
524 GC blitGC, pieceGC, outlineGC;
525 XPoint startSquare, prevFrame, mouseDelta;
529 int startBoardX, startBoardY;
532 /* There can be two pieces being animated at once: a player
533 can begin dragging a piece before the remote opponent has moved. */
535 static AnimState game, player;
537 /* Bitmaps for use as masks when drawing XPM pieces.
538 Need one for each black and white piece. */
539 static Pixmap xpmMask[BlackKing + 1];
541 /* This magic number is the number of intermediate frames used
542 in each half of the animation. For short moves it's reduced
543 by 1. The total number of frames will be factor * 2 + 1. */
546 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
548 MenuItem fileMenu[] = {
549 {N_("New Game"), ResetProc},
550 {N_("New Shuffle Game ..."), ShuffleMenuProc},
551 {N_("New Variant ..."), NewVariantProc}, // [HGM] variant: not functional yet
552 {"----", NothingProc},
553 {N_("Load Game"), LoadGameProc},
554 {N_("Load Next Game"), LoadNextGameProc},
555 {N_("Load Previous Game"), LoadPrevGameProc},
556 {N_("Reload Same Game"), ReloadGameProc},
557 {N_("Save Game"), SaveGameProc},
558 {"----", NothingProc},
559 {N_("Copy Game"), CopyGameProc},
560 {N_("Paste Game"), PasteGameProc},
561 {"----", NothingProc},
562 {N_("Load Position"), LoadPositionProc},
563 {N_("Load Next Position"), LoadNextPositionProc},
564 {N_("Load Previous Position"), LoadPrevPositionProc},
565 {N_("Reload Same Position"), ReloadPositionProc},
566 {N_("Save Position"), SavePositionProc},
567 {"----", NothingProc},
568 {N_("Copy Position"), CopyPositionProc},
569 {N_("Paste Position"), PastePositionProc},
570 {"----", NothingProc},
571 {N_("Mail Move"), MailMoveProc},
572 {N_("Reload CMail Message"), ReloadCmailMsgProc},
573 {"----", NothingProc},
574 {N_("Exit"), QuitProc},
578 MenuItem modeMenu[] = {
579 {N_("Machine White"), MachineWhiteProc},
580 {N_("Machine Black"), MachineBlackProc},
581 {N_("Two Machines"), TwoMachinesProc},
582 {N_("Analysis Mode"), AnalyzeModeProc},
583 {N_("Analyze File"), AnalyzeFileProc },
584 {N_("ICS Client"), IcsClientProc},
585 {N_("Edit Game"), EditGameProc},
586 {N_("Edit Position"), EditPositionProc},
587 {N_("Training"), TrainingProc},
588 {"----", NothingProc},
589 {N_("Show Engine Output"), EngineOutputProc},
590 {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
591 {N_("Show Game List"), ShowGameListProc},
592 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
593 {"----", NothingProc},
594 {N_("Edit Tags"), EditTagsProc},
595 {N_("Edit Comment"), EditCommentProc},
596 {N_("ICS Input Box"), IcsInputBoxProc},
597 {N_("Pause"), PauseProc},
601 MenuItem actionMenu[] = {
602 {N_("Accept"), AcceptProc},
603 {N_("Decline"), DeclineProc},
604 {N_("Rematch"), RematchProc},
605 {"----", NothingProc},
606 {N_("Call Flag"), CallFlagProc},
607 {N_("Draw"), DrawProc},
608 {N_("Adjourn"), AdjournProc},
609 {N_("Abort"), AbortProc},
610 {N_("Resign"), ResignProc},
611 {"----", NothingProc},
612 {N_("Stop Observing"), StopObservingProc},
613 {N_("Stop Examining"), StopExaminingProc},
614 {"----", NothingProc},
615 {N_("Adjudicate to White"), AdjuWhiteProc},
616 {N_("Adjudicate to Black"), AdjuBlackProc},
617 {N_("Adjudicate Draw"), AdjuDrawProc},
621 MenuItem stepMenu[] = {
622 {N_("Backward"), BackwardProc},
623 {N_("Forward"), ForwardProc},
624 {N_("Back to Start"), ToStartProc},
625 {N_("Forward to End"), ToEndProc},
626 {N_("Revert"), RevertProc},
627 {N_("Truncate Game"), TruncateGameProc},
628 {"----", NothingProc},
629 {N_("Move Now"), MoveNowProc},
630 {N_("Retract Move"), RetractMoveProc},
634 MenuItem optionsMenu[] = {
635 {N_("Flip View"), FlipViewProc},
636 {"----", NothingProc},
637 {N_("Adjudications ..."), EngineMenuProc},
638 {N_("General Settings ..."), UciMenuProc},
639 {N_("Engine #1 Settings ..."), FirstSettingsProc},
640 {N_("Engine #2 Settings ..."), SecondSettingsProc},
641 {N_("Time Control ..."), TimeControlProc},
642 {"----", NothingProc},
643 {N_("Always Queen"), AlwaysQueenProc},
644 {N_("Animate Dragging"), AnimateDraggingProc},
645 {N_("Animate Moving"), AnimateMovingProc},
646 {N_("Auto Comment"), AutocommProc},
647 {N_("Auto Flag"), AutoflagProc},
648 {N_("Auto Flip View"), AutoflipProc},
649 {N_("Auto Observe"), AutobsProc},
650 {N_("Auto Raise Board"), AutoraiseProc},
651 {N_("Auto Save"), AutosaveProc},
652 {N_("Blindfold"), BlindfoldProc},
653 {N_("Flash Moves"), FlashMovesProc},
654 {N_("Get Move List"), GetMoveListProc},
656 {N_("Highlight Dragging"), HighlightDraggingProc},
658 {N_("Highlight Last Move"), HighlightLastMoveProc},
659 {N_("Move Sound"), MoveSoundProc},
660 {N_("ICS Alarm"), IcsAlarmProc},
661 {N_("Old Save Style"), OldSaveStyleProc},
662 {N_("Periodic Updates"), PeriodicUpdatesProc},
663 {N_("Ponder Next Move"), PonderNextMoveProc},
664 {N_("Popup Exit Message"), PopupExitMessageProc},
665 {N_("Popup Move Errors"), PopupMoveErrorsProc},
666 {N_("Premove"), PremoveProc},
667 {N_("Quiet Play"), QuietPlayProc},
668 {N_("Show Coords"), ShowCoordsProc},
669 {N_("Hide Thinking"), HideThinkingProc},
670 {N_("Test Legality"), TestLegalityProc},
674 MenuItem helpMenu[] = {
675 {N_("Info XBoard"), InfoProc},
676 {N_("Man XBoard"), ManProc},
677 {"----", NothingProc},
678 {N_("Hint"), HintProc},
679 {N_("Book"), BookProc},
680 {"----", NothingProc},
681 {N_("About XBoard"), AboutProc},
686 {N_("File"), fileMenu},
687 {N_("Mode"), modeMenu},
688 {N_("Action"), actionMenu},
689 {N_("Step"), stepMenu},
690 {N_("Options"), optionsMenu},
691 {N_("Help"), helpMenu},
695 #define PAUSE_BUTTON N_("P")
696 MenuItem buttonBar[] = {
699 {PAUSE_BUTTON, PauseProc},
705 #define PIECE_MENU_SIZE 18
706 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
707 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
708 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
709 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
710 N_("Empty square"), N_("Clear board") },
711 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
712 N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"),
713 N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"),
714 N_("Empty square"), N_("Clear board") }
716 /* must be in same order as PieceMenuStrings! */
717 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
718 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
719 WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
720 WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0,
721 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
722 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
723 BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
724 BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0,
725 PromotePiece, DemotePiece, EmptySquare, ClearBoard },
728 #define DROP_MENU_SIZE 6
729 String dropMenuStrings[DROP_MENU_SIZE] = {
730 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
732 /* must be in same order as PieceMenuStrings! */
733 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
734 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
735 WhiteRook, WhiteQueen
743 DropMenuEnables dmEnables[] = {
761 { XtNborderWidth, 0 },
762 { XtNdefaultDistance, 0 },
766 { XtNborderWidth, 0 },
767 { XtNresizable, (XtArgVal) True },
771 { XtNborderWidth, 0 },
777 { XtNjustify, (XtArgVal) XtJustifyRight },
778 { XtNlabel, (XtArgVal) "..." },
779 { XtNresizable, (XtArgVal) True },
780 { XtNresize, (XtArgVal) False }
783 Arg messageArgs[] = {
784 { XtNjustify, (XtArgVal) XtJustifyLeft },
785 { XtNlabel, (XtArgVal) "..." },
786 { XtNresizable, (XtArgVal) True },
787 { XtNresize, (XtArgVal) False }
791 { XtNborderWidth, 0 },
792 { XtNjustify, (XtArgVal) XtJustifyLeft }
795 XtResource clientResources[] = {
796 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
797 XtOffset(AppDataPtr, whitePieceColor), XtRString,
799 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, blackPieceColor), XtRString,
802 { "lightSquareColor", "lightSquareColor", XtRString,
803 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
804 XtRString, LIGHT_SQUARE_COLOR },
805 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
806 XtOffset(AppDataPtr, darkSquareColor), XtRString,
808 { "highlightSquareColor", "highlightSquareColor", XtRString,
809 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
810 XtRString, HIGHLIGHT_SQUARE_COLOR },
811 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
812 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
813 XtRString, PREMOVE_HIGHLIGHT_COLOR },
814 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
815 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
816 (XtPointer) MOVES_PER_SESSION },
817 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
818 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
819 (XtPointer) TIME_INCREMENT },
820 { "initString", "initString", XtRString, sizeof(String),
821 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
822 { "secondInitString", "secondInitString", XtRString, sizeof(String),
823 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
824 { "firstComputerString", "firstComputerString", XtRString,
825 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
827 { "secondComputerString", "secondComputerString", XtRString,
828 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
830 { "firstChessProgram", "firstChessProgram", XtRString,
831 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
832 XtRString, FIRST_CHESS_PROGRAM },
833 { "secondChessProgram", "secondChessProgram", XtRString,
834 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
835 XtRString, SECOND_CHESS_PROGRAM },
836 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
837 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
838 XtRImmediate, (XtPointer) False },
839 { "noChessProgram", "noChessProgram", XtRBoolean,
840 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
841 XtRImmediate, (XtPointer) False },
842 { "firstHost", "firstHost", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
844 { "secondHost", "secondHost", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
846 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
847 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
848 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
849 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
850 { "bitmapDirectory", "bitmapDirectory", XtRString,
851 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
853 { "remoteShell", "remoteShell", XtRString, sizeof(String),
854 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
855 { "remoteUser", "remoteUser", XtRString, sizeof(String),
856 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
857 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
858 XtOffset(AppDataPtr, timeDelay), XtRString,
859 (XtPointer) TIME_DELAY_QUOTE },
860 { "timeControl", "timeControl", XtRString, sizeof(String),
861 XtOffset(AppDataPtr, timeControl), XtRString,
862 (XtPointer) TIME_CONTROL },
863 { "internetChessServerMode", "internetChessServerMode",
864 XtRBoolean, sizeof(Boolean),
865 XtOffset(AppDataPtr, icsActive), XtRImmediate,
867 { "internetChessServerHost", "internetChessServerHost",
868 XtRString, sizeof(String),
869 XtOffset(AppDataPtr, icsHost),
870 XtRString, (XtPointer) ICS_HOST },
871 { "internetChessServerPort", "internetChessServerPort",
872 XtRString, sizeof(String),
873 XtOffset(AppDataPtr, icsPort), XtRString,
874 (XtPointer) ICS_PORT },
875 { "internetChessServerCommPort", "internetChessServerCommPort",
876 XtRString, sizeof(String),
877 XtOffset(AppDataPtr, icsCommPort), XtRString,
879 { "internetChessServerLogonScript", "internetChessServerLogonScript",
880 XtRString, sizeof(String),
881 XtOffset(AppDataPtr, icsLogon), XtRString,
883 { "internetChessServerHelper", "internetChessServerHelper",
884 XtRString, sizeof(String),
885 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
886 { "internetChessServerInputBox", "internetChessServerInputBox",
887 XtRBoolean, sizeof(Boolean),
888 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
890 { "icsAlarm", "icsAlarm",
891 XtRBoolean, sizeof(Boolean),
892 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
894 { "icsAlarmTime", "icsAlarmTime",
896 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
898 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
899 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
901 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
902 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
903 { "gateway", "gateway", XtRString, sizeof(String),
904 XtOffset(AppDataPtr, gateway), XtRString, "" },
905 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
906 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
907 { "loadGameIndex", "loadGameIndex",
909 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
911 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
912 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
913 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
915 XtRImmediate, (XtPointer) True },
916 { "autoSaveGames", "autoSaveGames", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
918 XtRImmediate, (XtPointer) False },
919 { "blindfold", "blindfold", XtRBoolean,
920 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
921 XtRImmediate, (XtPointer) False },
922 { "loadPositionFile", "loadPositionFile", XtRString,
923 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
925 { "loadPositionIndex", "loadPositionIndex",
927 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
929 { "savePositionFile", "savePositionFile", XtRString,
930 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
932 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
933 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
934 { "matchGames", "matchGames", XtRInt, sizeof(int),
935 XtOffset(AppDataPtr, matchGames), XtRImmediate,
937 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
938 XtOffset(AppDataPtr, monoMode), XtRImmediate,
940 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
941 XtOffset(AppDataPtr, debugMode), XtRImmediate,
943 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
944 XtOffset(AppDataPtr, clockMode), XtRImmediate,
946 { "boardSize", "boardSize", XtRString, sizeof(String),
947 XtOffset(AppDataPtr, boardSize), XtRString, "" },
948 { "searchTime", "searchTime", XtRString, sizeof(String),
949 XtOffset(AppDataPtr, searchTime), XtRString,
951 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
952 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
954 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
955 XtOffset(AppDataPtr, showCoords), XtRImmediate,
957 { "showJail", "showJail", XtRInt, sizeof(int),
958 XtOffset(AppDataPtr, showJail), XtRImmediate,
960 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
961 XtOffset(AppDataPtr, showThinking), XtRImmediate,
963 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
964 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
966 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
967 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
969 { "clockFont", "clockFont", XtRString, sizeof(String),
970 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
971 { "coordFont", "coordFont", XtRString, sizeof(String),
972 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
973 { "font", "font", XtRString, sizeof(String),
974 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
975 { "ringBellAfterMoves", "ringBellAfterMoves",
976 XtRBoolean, sizeof(Boolean),
977 XtOffset(AppDataPtr, ringBellAfterMoves),
978 XtRImmediate, (XtPointer) False },
979 { "autoCallFlag", "autoCallFlag", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
981 XtRImmediate, (XtPointer) False },
982 { "autoFlipView", "autoFlipView", XtRBoolean,
983 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
984 XtRImmediate, (XtPointer) True },
985 { "autoObserve", "autoObserve", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
987 XtRImmediate, (XtPointer) False },
988 { "autoComment", "autoComment", XtRBoolean,
989 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
990 XtRImmediate, (XtPointer) False },
991 { "getMoveList", "getMoveList", XtRBoolean,
992 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
993 XtRImmediate, (XtPointer) True },
995 { "highlightDragging", "highlightDragging", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
997 XtRImmediate, (XtPointer) False },
999 { "highlightLastMove", "highlightLastMove", XtRBoolean,
1000 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
1001 XtRImmediate, (XtPointer) False },
1002 { "premove", "premove", XtRBoolean,
1003 sizeof(Boolean), XtOffset(AppDataPtr, premove),
1004 XtRImmediate, (XtPointer) True },
1005 { "testLegality", "testLegality", XtRBoolean,
1006 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1007 XtRImmediate, (XtPointer) True },
1008 { "flipView", "flipView", XtRBoolean,
1009 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1010 XtRImmediate, (XtPointer) False },
1011 { "cmail", "cmailGameName", XtRString, sizeof(String),
1012 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1013 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1014 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1015 XtRImmediate, (XtPointer) False },
1016 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1017 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1018 XtRImmediate, (XtPointer) False },
1019 { "quietPlay", "quietPlay", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1021 XtRImmediate, (XtPointer) False },
1022 { "titleInWindow", "titleInWindow", XtRBoolean,
1023 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1024 XtRImmediate, (XtPointer) False },
1025 { "localLineEditing", "localLineEditing", XtRBoolean,
1026 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1027 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1029 { "zippyTalk", "zippyTalk", XtRBoolean,
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1031 XtRImmediate, (XtPointer) ZIPPY_TALK },
1032 { "zippyPlay", "zippyPlay", XtRBoolean,
1033 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1034 XtRImmediate, (XtPointer) ZIPPY_PLAY },
1035 { "zippyLines", "zippyLines", XtRString, sizeof(String),
1036 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1037 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1038 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1039 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1040 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1041 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1042 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1043 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1044 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1045 ZIPPY_WRONG_PASSWORD },
1046 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1047 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1048 { "zippyUseI", "zippyUseI", XtRBoolean,
1049 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1050 XtRImmediate, (XtPointer) ZIPPY_USE_I },
1051 { "zippyBughouse", "zippyBughouse", XtRInt,
1052 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1053 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1054 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1055 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1056 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1057 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1058 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1059 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1060 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1061 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1062 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1063 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1064 { "zippyAbort", "zippyAbort", XtRBoolean,
1065 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1066 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1067 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1068 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1069 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1070 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1071 (XtPointer) ZIPPY_MAX_GAMES },
1072 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1073 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1074 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1075 { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1076 XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1079 { "flashCount", "flashCount", XtRInt, sizeof(int),
1080 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1081 (XtPointer) FLASH_COUNT },
1082 { "flashRate", "flashRate", XtRInt, sizeof(int),
1083 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1084 (XtPointer) FLASH_RATE },
1085 { "pixmapDirectory", "pixmapDirectory", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1088 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1089 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1090 (XtPointer) MS_LOGIN_DELAY },
1091 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1092 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1093 XtRImmediate, (XtPointer) False },
1094 { "colorShout", "colorShout", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, colorShout),
1096 XtRString, COLOR_SHOUT },
1097 { "colorSShout", "colorSShout", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1099 XtRString, COLOR_SSHOUT },
1100 { "colorChannel1", "colorChannel1", XtRString,
1101 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1102 XtRString, COLOR_CHANNEL1 },
1103 { "colorChannel", "colorChannel", XtRString,
1104 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1105 XtRString, COLOR_CHANNEL },
1106 { "colorKibitz", "colorKibitz", XtRString,
1107 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1108 XtRString, COLOR_KIBITZ },
1109 { "colorTell", "colorTell", XtRString,
1110 sizeof(String), XtOffset(AppDataPtr, colorTell),
1111 XtRString, COLOR_TELL },
1112 { "colorChallenge", "colorChallenge", XtRString,
1113 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1114 XtRString, COLOR_CHALLENGE },
1115 { "colorRequest", "colorRequest", XtRString,
1116 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1117 XtRString, COLOR_REQUEST },
1118 { "colorSeek", "colorSeek", XtRString,
1119 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1120 XtRString, COLOR_SEEK },
1121 { "colorNormal", "colorNormal", XtRString,
1122 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1123 XtRString, COLOR_NORMAL },
1124 { "soundProgram", "soundProgram", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1126 XtRString, "play" },
1127 { "soundShout", "soundShout", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, soundShout),
1130 { "soundSShout", "soundSShout", XtRString,
1131 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1133 { "soundChannel1", "soundChannel1", XtRString,
1134 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1136 { "soundChannel", "soundChannel", XtRString,
1137 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1139 { "soundKibitz", "soundKibitz", XtRString,
1140 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1142 { "soundTell", "soundTell", XtRString,
1143 sizeof(String), XtOffset(AppDataPtr, soundTell),
1145 { "soundChallenge", "soundChallenge", XtRString,
1146 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1148 { "soundRequest", "soundRequest", XtRString,
1149 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1151 { "soundSeek", "soundSeek", XtRString,
1152 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1154 { "soundMove", "soundMove", XtRString,
1155 sizeof(String), XtOffset(AppDataPtr, soundMove),
1157 { "soundIcsWin", "soundIcsWin", XtRString,
1158 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1160 { "soundIcsLoss", "soundIcsLoss", XtRString,
1161 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1163 { "soundIcsDraw", "soundIcsDraw", XtRString,
1164 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1166 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1167 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1169 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1170 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1172 { "reuseFirst", "reuseFirst", XtRBoolean,
1173 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1174 XtRImmediate, (XtPointer) True },
1175 { "reuseSecond", "reuseSecond", XtRBoolean,
1176 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1177 XtRImmediate, (XtPointer) True },
1178 { "animateDragging", "animateDragging", XtRBoolean,
1179 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1180 XtRImmediate, (XtPointer) True },
1181 { "animateMoving", "animateMoving", XtRBoolean,
1182 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1183 XtRImmediate, (XtPointer) True },
1184 { "animateSpeed", "animateSpeed", XtRInt,
1185 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1186 XtRImmediate, (XtPointer)10 },
1187 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1188 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1189 XtRImmediate, (XtPointer) True },
1190 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1191 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1192 XtRImmediate, (XtPointer) False },
1193 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1194 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1195 XtRImmediate, (XtPointer)4 },
1196 { "initialMode", "initialMode", XtRString,
1197 sizeof(String), XtOffset(AppDataPtr, initialMode),
1198 XtRImmediate, (XtPointer) "" },
1199 { "variant", "variant", XtRString,
1200 sizeof(String), XtOffset(AppDataPtr, variant),
1201 XtRImmediate, (XtPointer) "normal" },
1202 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1203 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1204 XtRImmediate, (XtPointer)PROTOVER },
1205 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1206 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1207 XtRImmediate, (XtPointer)PROTOVER },
1208 { "showButtonBar", "showButtonBar", XtRBoolean,
1209 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1210 XtRImmediate, (XtPointer) True },
1211 { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1212 sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1213 XtRString, COLOR_LOWTIMEWARNING },
1214 { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1215 sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1216 XtRImmediate, (XtPointer) False },
1217 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean, /* [DM] icsEngineAnalyze */
1218 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1219 XtRImmediate, (XtPointer) False },
1220 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1221 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1222 XtRImmediate, (XtPointer) False },
1223 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1224 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1225 XtRImmediate, (XtPointer) False },
1226 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1227 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1228 XtRImmediate, (XtPointer) False },
1229 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1230 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1231 XtRImmediate, (XtPointer) True },
1232 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1233 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1234 XtRImmediate, (XtPointer) 0},
1235 { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt,
1236 sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves),
1237 XtRImmediate, (XtPointer) 0},
1238 { "pgnEventHeader", "pgnEventHeader", XtRString,
1239 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1240 XtRImmediate, (XtPointer) "Computer Chess Game" },
1241 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1242 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1243 XtRImmediate, (XtPointer) -1},
1244 { "gameListTags", "gameListTags", XtRString,
1245 sizeof(String), XtOffset(AppDataPtr, gameListTags),
1246 XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1248 // [HGM] 4.3.xx options
1249 { "boardWidth", "boardWidth", XtRInt,
1250 sizeof(int), XtOffset(AppDataPtr, NrFiles),
1251 XtRImmediate, (XtPointer) -1},
1252 { "boardHeight", "boardHeight", XtRInt,
1253 sizeof(int), XtOffset(AppDataPtr, NrRanks),
1254 XtRImmediate, (XtPointer) -1},
1255 { "matchPause", "matchPause", XtRInt,
1256 sizeof(int), XtOffset(AppDataPtr, matchPause),
1257 XtRImmediate, (XtPointer) 10000},
1258 { "holdingsSize", "holdingsSize", XtRInt,
1259 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1260 XtRImmediate, (XtPointer) -1},
1261 { "flipBlack", "flipBlack", XtRBoolean,
1262 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1263 XtRImmediate, (XtPointer) False},
1264 { "allWhite", "allWhite", XtRBoolean,
1265 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1266 XtRImmediate, (XtPointer) False},
1267 { "pieceToCharTable", "pieceToCharTable", XtRString,
1268 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1269 XtRImmediate, (XtPointer) 0},
1270 { "alphaRank", "alphaRank", XtRBoolean,
1271 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1272 XtRImmediate, (XtPointer) False},
1273 { "testClaims", "testClaims", XtRBoolean,
1274 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1275 XtRImmediate, (XtPointer) True},
1276 { "checkMates", "checkMates", XtRBoolean,
1277 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1278 XtRImmediate, (XtPointer) True},
1279 { "materialDraws", "materialDraws", XtRBoolean,
1280 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1281 XtRImmediate, (XtPointer) True},
1282 { "trivialDraws", "trivialDraws", XtRBoolean,
1283 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1284 XtRImmediate, (XtPointer) False},
1285 { "ruleMoves", "ruleMoves", XtRInt,
1286 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1287 XtRImmediate, (XtPointer) 51},
1288 { "repeatsToDraw", "repeatsToDraw", XtRInt,
1289 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1290 XtRImmediate, (XtPointer) 6},
1291 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1292 sizeof(int), XtOffset(AppDataPtr, engineComments),
1293 XtRImmediate, (XtPointer) 1},
1294 { "userName", "userName", XtRString,
1295 sizeof(int), XtOffset(AppDataPtr, userName),
1296 XtRImmediate, (XtPointer) 0},
1297 { "autoKibitz", "autoKibitz", XtRBoolean,
1298 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1299 XtRImmediate, (XtPointer) False},
1300 { "firstTimeOdds", "firstTimeOdds", XtRInt,
1301 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1302 XtRImmediate, (XtPointer) 1},
1303 { "secondTimeOdds", "secondTimeOdds", XtRInt,
1304 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1305 XtRImmediate, (XtPointer) 1},
1306 { "timeOddsMode", "timeOddsMode", XtRInt,
1307 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1308 XtRImmediate, (XtPointer) 0},
1309 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1310 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1311 XtRImmediate, (XtPointer) 1},
1312 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1313 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1314 XtRImmediate, (XtPointer) 1},
1315 { "firstNPS", "firstNPS", XtRInt,
1316 sizeof(int), XtOffset(AppDataPtr, firstNPS),
1317 XtRImmediate, (XtPointer) -1},
1318 { "secondNPS", "secondNPS", XtRInt,
1319 sizeof(int), XtOffset(AppDataPtr, secondNPS),
1320 XtRImmediate, (XtPointer) -1},
1321 { "serverMoves", "serverMoves", XtRString,
1322 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1323 XtRImmediate, (XtPointer) 0},
1324 { "serverPause", "serverPause", XtRInt,
1325 sizeof(int), XtOffset(AppDataPtr, serverPause),
1326 XtRImmediate, (XtPointer) 0},
1327 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1328 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1329 XtRImmediate, (XtPointer) False},
1330 { "userName", "userName", XtRString,
1331 sizeof(String), XtOffset(AppDataPtr, userName),
1332 XtRImmediate, (XtPointer) 0},
1333 { "egtFormats", "egtFormats", XtRString,
1334 sizeof(String), XtOffset(AppDataPtr, egtFormats),
1335 XtRImmediate, (XtPointer) 0},
1336 { "rewindIndex", "rewindIndex", XtRInt,
1337 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1338 XtRImmediate, (XtPointer) 0},
1339 { "sameColorGames", "sameColorGames", XtRInt,
1340 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1341 XtRImmediate, (XtPointer) 0},
1342 { "smpCores", "smpCores", XtRInt,
1343 sizeof(int), XtOffset(AppDataPtr, smpCores),
1344 XtRImmediate, (XtPointer) 1},
1345 { "niceEngines", "niceEngines", XtRInt,
1346 sizeof(int), XtOffset(AppDataPtr, niceEngines),
1347 XtRImmediate, (XtPointer) 0},
1348 { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1349 sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1350 XtRImmediate, (XtPointer) "xboard.debug"},
1351 { "engineDebugOutput", "engineDebugOutput", XtRInt,
1352 sizeof(int), XtOffset(AppDataPtr, engineComments),
1353 XtRImmediate, (XtPointer) 1},
1354 { "noGUI", "noGUI", XtRBoolean,
1355 sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1356 XtRImmediate, (XtPointer) 0},
1357 { "firstOptions", "firstOptions", XtRString,
1358 sizeof(String), XtOffset(AppDataPtr, firstOptions),
1359 XtRImmediate, (XtPointer) "" },
1360 { "secondOptions", "secondOptions", XtRString,
1361 sizeof(String), XtOffset(AppDataPtr, secondOptions),
1362 XtRImmediate, (XtPointer) "" },
1363 { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1364 sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1365 XtRImmediate, (XtPointer) 0 },
1366 { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1367 sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1368 XtRImmediate, (XtPointer) 0 },
1370 // [HGM] Winboard_x UCI options
1371 { "firstIsUCI", "firstIsUCI", XtRBoolean,
1372 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1373 XtRImmediate, (XtPointer) False},
1374 { "secondIsUCI", "secondIsUCI", XtRBoolean,
1375 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1376 XtRImmediate, (XtPointer) False},
1377 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1378 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1379 XtRImmediate, (XtPointer) True},
1380 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1381 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1382 XtRImmediate, (XtPointer) True},
1383 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1384 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1385 XtRImmediate, (XtPointer) False},
1386 { "defaultHashSize", "defaultHashSize", XtRInt,
1387 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1388 XtRImmediate, (XtPointer) 64},
1389 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1390 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1391 XtRImmediate, (XtPointer) 4},
1392 { "polyglotDir", "polyglotDir", XtRString,
1393 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1394 XtRImmediate, (XtPointer) "." },
1395 { "polyglotBook", "polyglotBook", XtRString,
1396 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1397 XtRImmediate, (XtPointer) "" },
1398 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1399 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1400 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1401 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1402 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1403 XtRImmediate, (XtPointer) 0},
1404 { "delayAfterQuit", "delayAfterQuit", XtRInt,
1405 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1406 XtRImmediate, (XtPointer) 0},
1407 { "keepAlive", "keepAlive", XtRInt,
1408 sizeof(int), XtOffset(AppDataPtr, keepAlive),
1409 XtRImmediate, (XtPointer) 0},
1410 { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
1411 sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
1412 XtRImmediate, (XtPointer) False},
1413 { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean,
1414 sizeof(Boolean), XtOffset(AppDataPtr, noJoin),
1415 XtRImmediate, (XtPointer) True},
1418 XrmOptionDescRec shellOptions[] = {
1419 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1420 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1421 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1422 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1423 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1424 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1425 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1426 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1427 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1428 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1429 { "-initString", "initString", XrmoptionSepArg, NULL },
1430 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1431 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1432 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1433 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1434 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1435 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1436 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1437 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1438 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1439 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1440 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1441 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1442 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1443 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1444 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1445 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1446 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1447 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1448 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1449 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1450 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1451 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1452 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1453 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1454 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1455 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1456 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1457 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1458 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1459 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1460 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1461 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1462 { "-internetChessServerMode", "internetChessServerMode",
1463 XrmoptionSepArg, NULL },
1464 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1465 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1466 { "-internetChessServerHost", "internetChessServerHost",
1467 XrmoptionSepArg, NULL },
1468 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1469 { "-internetChessServerPort", "internetChessServerPort",
1470 XrmoptionSepArg, NULL },
1471 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1472 { "-internetChessServerCommPort", "internetChessServerCommPort",
1473 XrmoptionSepArg, NULL },
1474 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1475 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1476 XrmoptionSepArg, NULL },
1477 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1478 { "-internetChessServerHelper", "internetChessServerHelper",
1479 XrmoptionSepArg, NULL },
1480 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1481 { "-internetChessServerInputBox", "internetChessServerInputBox",
1482 XrmoptionSepArg, NULL },
1483 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1484 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1485 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1486 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1487 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1488 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1489 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1490 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1491 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1492 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1493 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1494 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1495 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1496 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1497 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1498 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1499 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1500 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1501 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1502 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1503 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1504 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1505 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1506 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1507 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1508 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1509 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1510 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1511 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1512 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1513 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1514 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1515 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1516 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1517 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1518 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1519 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1520 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1521 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1522 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1523 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1524 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1525 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1526 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1527 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1528 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1529 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1530 { "-size", "boardSize", XrmoptionSepArg, NULL },
1531 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1532 { "-st", "searchTime", XrmoptionSepArg, NULL },
1533 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1534 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1535 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1536 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1537 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1539 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1540 { "-jail", "showJail", XrmoptionNoArg, "1" },
1541 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1542 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1544 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1545 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1546 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1547 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1548 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1549 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1550 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1551 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1552 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1553 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1554 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1555 { "-font", "font", XrmoptionSepArg, NULL },
1556 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1557 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1558 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1559 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1560 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1561 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1562 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1563 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1564 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1565 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1566 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1567 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1568 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1569 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1570 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1571 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1572 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1573 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1574 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1575 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1577 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1578 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1579 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1581 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1582 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1583 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1584 { "-premove", "premove", XrmoptionSepArg, NULL },
1585 { "-pre", "premove", XrmoptionNoArg, "True" },
1586 { "-xpre", "premove", XrmoptionNoArg, "False" },
1587 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1588 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1589 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1590 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1591 { "-flip", "flipView", XrmoptionNoArg, "True" },
1592 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1593 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1594 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1595 XrmoptionSepArg, NULL },
1596 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1597 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1598 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1599 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1600 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1601 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1602 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1603 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1604 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1605 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1606 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1608 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1609 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1610 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1611 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1612 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1613 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1614 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1615 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1616 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1617 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1618 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1619 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1620 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1621 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1622 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1623 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1624 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1625 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1626 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1627 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1628 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1629 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1630 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1631 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1632 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1633 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1634 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1635 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1636 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1637 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1638 { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1640 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1641 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1642 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1643 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1644 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1645 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1646 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1647 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1648 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1649 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1650 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1651 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1652 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1653 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1654 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1655 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1656 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1657 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1658 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1659 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1660 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1661 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1662 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1663 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1664 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1665 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1666 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1667 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1668 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1669 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1670 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1671 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1672 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1673 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1674 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1675 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1676 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1677 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1678 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1679 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1680 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1681 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1682 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1683 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1684 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1685 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1686 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1687 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1688 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1689 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1690 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1691 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1692 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1693 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1694 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1695 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1696 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1697 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1698 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1699 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1700 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1701 { "-variant", "variant", XrmoptionSepArg, NULL },
1702 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1703 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1704 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1705 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1706 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1707 { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1708 { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1709 /* [AS,HR] New features */
1710 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1711 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1712 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1713 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1714 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1715 { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL },
1716 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1717 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1718 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1719 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1720 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1721 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1722 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1723 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1724 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1725 { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1726 { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1727 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1728 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1729 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1730 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1731 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1732 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1733 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1734 { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1735 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1737 /* [HGM,HR] User-selectable board size */
1738 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1739 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1740 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1742 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1743 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1744 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
1745 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
1746 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1747 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1748 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1749 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1750 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1751 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1752 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1753 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1754 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1755 { "-userName", "userName", XrmoptionSepArg, NULL },
1756 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1757 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1758 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1759 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1760 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1761 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1762 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1763 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1764 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1765 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1766 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1767 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1768 { "-userName", "userName", XrmoptionSepArg, NULL },
1769 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1770 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1771 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1772 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1773 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1774 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1775 { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1776 { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1777 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1778 { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1779 { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1780 { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1781 { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1782 { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1783 { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
1784 { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
1785 { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL },
1789 XtActionsRec boardActions[] = {
1790 { "DrawPosition", DrawPositionProc },
1791 { "HandleUserMove", HandleUserMove },
1792 { "AnimateUserMove", AnimateUserMove },
1793 { "FileNameAction", FileNameAction },
1794 { "AskQuestionProc", AskQuestionProc },
1795 { "AskQuestionReplyAction", AskQuestionReplyAction },
1796 { "PieceMenuPopup", PieceMenuPopup },
1797 { "WhiteClock", WhiteClock },
1798 { "BlackClock", BlackClock },
1799 { "Iconify", Iconify },
1800 { "ResetProc", ResetProc },
1801 { "LoadGameProc", LoadGameProc },
1802 { "LoadNextGameProc", LoadNextGameProc },
1803 { "LoadPrevGameProc", LoadPrevGameProc },
1804 { "LoadSelectedProc", LoadSelectedProc },
1805 { "ReloadGameProc", ReloadGameProc },
1806 { "LoadPositionProc", LoadPositionProc },
1807 { "LoadNextPositionProc", LoadNextPositionProc },
1808 { "LoadPrevPositionProc", LoadPrevPositionProc },
1809 { "ReloadPositionProc", ReloadPositionProc },
1810 { "CopyPositionProc", CopyPositionProc },
1811 { "PastePositionProc", PastePositionProc },
1812 { "CopyGameProc", CopyGameProc },
1813 { "PasteGameProc", PasteGameProc },
1814 { "SaveGameProc", SaveGameProc },
1815 { "SavePositionProc", SavePositionProc },
1816 { "MailMoveProc", MailMoveProc },
1817 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1818 { "QuitProc", QuitProc },
1819 { "MachineWhiteProc", MachineWhiteProc },
1820 { "MachineBlackProc", MachineBlackProc },
1821 { "AnalysisModeProc", AnalyzeModeProc },
1822 { "AnalyzeFileProc", AnalyzeFileProc },
1823 { "TwoMachinesProc", TwoMachinesProc },
1824 { "IcsClientProc", IcsClientProc },
1825 { "EditGameProc", EditGameProc },
1826 { "EditPositionProc", EditPositionProc },
1827 { "TrainingProc", EditPositionProc },
1828 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1829 { "ShowGameListProc", ShowGameListProc },
1830 { "ShowMoveListProc", HistoryShowProc},
1831 { "EditTagsProc", EditCommentProc },
1832 { "EditCommentProc", EditCommentProc },
1833 { "IcsAlarmProc", IcsAlarmProc },
1834 { "IcsInputBoxProc", IcsInputBoxProc },
1835 { "PauseProc", PauseProc },
1836 { "AcceptProc", AcceptProc },
1837 { "DeclineProc", DeclineProc },
1838 { "RematchProc", RematchProc },
1839 { "CallFlagProc", CallFlagProc },
1840 { "DrawProc", DrawProc },
1841 { "AdjournProc", AdjournProc },
1842 { "AbortProc", AbortProc },
1843 { "ResignProc", ResignProc },
1844 { "AdjuWhiteProc", AdjuWhiteProc },
1845 { "AdjuBlackProc", AdjuBlackProc },
1846 { "AdjuDrawProc", AdjuDrawProc },
1847 { "EnterKeyProc", EnterKeyProc },
1848 { "StopObservingProc", StopObservingProc },
1849 { "StopExaminingProc", StopExaminingProc },
1850 { "BackwardProc", BackwardProc },
1851 { "ForwardProc", ForwardProc },
1852 { "ToStartProc", ToStartProc },
1853 { "ToEndProc", ToEndProc },
1854 { "RevertProc", RevertProc },
1855 { "TruncateGameProc", TruncateGameProc },
1856 { "MoveNowProc", MoveNowProc },
1857 { "RetractMoveProc", RetractMoveProc },
1858 { "AlwaysQueenProc", AlwaysQueenProc },
1859 { "AnimateDraggingProc", AnimateDraggingProc },
1860 { "AnimateMovingProc", AnimateMovingProc },
1861 { "AutoflagProc", AutoflagProc },
1862 { "AutoflipProc", AutoflipProc },
1863 { "AutobsProc", AutobsProc },
1864 { "AutoraiseProc", AutoraiseProc },
1865 { "AutosaveProc", AutosaveProc },
1866 { "BlindfoldProc", BlindfoldProc },
1867 { "FlashMovesProc", FlashMovesProc },
1868 { "FlipViewProc", FlipViewProc },
1869 { "GetMoveListProc", GetMoveListProc },
1871 { "HighlightDraggingProc", HighlightDraggingProc },
1873 { "HighlightLastMoveProc", HighlightLastMoveProc },
1874 { "IcsAlarmProc", IcsAlarmProc },
1875 { "MoveSoundProc", MoveSoundProc },
1876 { "OldSaveStyleProc", OldSaveStyleProc },
1877 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1878 { "PonderNextMoveProc", PonderNextMoveProc },
1879 { "PopupExitMessageProc", PopupExitMessageProc },
1880 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1881 { "PremoveProc", PremoveProc },
1882 { "QuietPlayProc", QuietPlayProc },
1883 { "ShowCoordsProc", ShowCoordsProc },
1884 { "ShowThinkingProc", ShowThinkingProc },
1885 { "HideThinkingProc", HideThinkingProc },
1886 { "TestLegalityProc", TestLegalityProc },
1887 { "InfoProc", InfoProc },
1888 { "ManProc", ManProc },
1889 { "HintProc", HintProc },
1890 { "BookProc", BookProc },
1891 { "AboutGameProc", AboutGameProc },
1892 { "AboutProc", AboutProc },
1893 { "DebugProc", DebugProc },
1894 { "NothingProc", NothingProc },
1895 { "CommentPopDown", (XtActionProc) CommentPopDown },
1896 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1897 { "TagsPopDown", (XtActionProc) TagsPopDown },
1898 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1899 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1900 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1901 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1902 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1903 { "GameListPopDown", (XtActionProc) GameListPopDown },
1904 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1905 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1906 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1907 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1908 { "EnginePopDown", (XtActionProc) EnginePopDown },
1909 { "UciPopDown", (XtActionProc) UciPopDown },
1910 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1911 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1912 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1915 char globalTranslations[] =
1916 ":<Key>R: ResignProc() \n \
1917 :<Key>r: ResetProc() \n \
1918 :<Key>g: LoadGameProc() \n \
1919 :<Key>N: LoadNextGameProc() \n \
1920 :<Key>P: LoadPrevGameProc() \n \
1921 :<Key>Q: QuitProc() \n \
1922 :<Key>F: ToEndProc() \n \
1923 :<Key>f: ForwardProc() \n \
1924 :<Key>B: ToStartProc() \n \
1925 :<Key>b: BackwardProc() \n \
1926 :<Key>p: PauseProc() \n \
1927 :<Key>d: DrawProc() \n \
1928 :<Key>t: CallFlagProc() \n \
1929 :<Key>i: Iconify() \n \
1930 :<Key>c: Iconify() \n \
1931 :<Key>v: FlipViewProc() \n \
1932 <KeyDown>Control_L: BackwardProc() \n \
1933 <KeyUp>Control_L: ForwardProc() \n \
1934 <KeyDown>Control_R: BackwardProc() \n \
1935 <KeyUp>Control_R: ForwardProc() \n \
1936 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1937 \"Send to chess program:\",,1) \n \
1938 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1939 \"Send to second chess program:\",,2) \n";
1941 char boardTranslations[] =
1942 "<Btn1Down>: HandleUserMove() \n \
1943 <Btn1Up>: HandleUserMove() \n \
1944 <Btn1Motion>: AnimateUserMove() \n \
1945 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1946 PieceMenuPopup(menuB) \n \
1947 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1948 PieceMenuPopup(menuW) \n \
1949 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1950 PieceMenuPopup(menuW) \n \
1951 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1952 PieceMenuPopup(menuB) \n";
1954 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1955 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1957 char ICSInputTranslations[] =
1958 "<Key>Return: EnterKeyProc() \n";
1960 String xboardResources[] = {
1961 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1962 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1963 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1968 /* Max possible square size */
1969 #define MAXSQSIZE 256
1971 static int xpm_avail[MAXSQSIZE];
1973 #ifdef HAVE_DIR_STRUCT
1975 /* Extract piece size from filename */
1977 xpm_getsize(name, len, ext)
1988 if ((p=strchr(name, '.')) == NULL ||
1989 StrCaseCmp(p+1, ext) != 0)
1995 while (*p && isdigit(*p))
2002 /* Setup xpm_avail */
2004 xpm_getavail(dirname, ext)
2012 for (i=0; i<MAXSQSIZE; ++i)
2015 if (appData.debugMode)
2016 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
2018 dir = opendir(dirname);
2021 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2022 programName, dirname);
2026 while ((ent=readdir(dir)) != NULL) {
2027 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2028 if (i > 0 && i < MAXSQSIZE)
2038 xpm_print_avail(fp, ext)
2044 fprintf(fp, _("Available `%s' sizes:\n"), ext);
2045 for (i=1; i<MAXSQSIZE; ++i) {
2051 /* Return XPM piecesize closest to size */
2053 xpm_closest_to(dirname, size, ext)
2059 int sm_diff = MAXSQSIZE;
2063 xpm_getavail(dirname, ext);
2065 if (appData.debugMode)
2066 xpm_print_avail(stderr, ext);
2068 for (i=1; i<MAXSQSIZE; ++i) {
2071 diff = (diff<0) ? -diff : diff;
2072 if (diff < sm_diff) {
2080 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2086 #else /* !HAVE_DIR_STRUCT */
2087 /* If we are on a system without a DIR struct, we can't
2088 read the directory, so we can't collect a list of
2089 filenames, etc., so we can't do any size-fitting. */
2091 xpm_closest_to(dirname, size, ext)
2096 fprintf(stderr, _("\
2097 Warning: No DIR structure found on this system --\n\
2098 Unable to autosize for XPM/XIM pieces.\n\
2099 Please report this error to frankm@hiwaay.net.\n\
2100 Include system type & operating system in message.\n"));
2103 #endif /* HAVE_DIR_STRUCT */
2105 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2106 "magenta", "cyan", "white" };
2110 TextColors textColors[(int)NColorClasses];
2112 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2114 parse_color(str, which)
2118 char *p, buf[100], *d;
2121 if (strlen(str) > 99) /* watch bounds on buf */
2126 for (i=0; i<which; ++i) {
2133 /* Could be looking at something like:
2135 .. in which case we want to stop on a comma also */
2136 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2140 return -1; /* Use default for empty field */
2143 if (which == 2 || isdigit(*p))
2146 while (*p && isalpha(*p))
2151 for (i=0; i<8; ++i) {
2152 if (!StrCaseCmp(buf, cnames[i]))
2153 return which? (i+40) : (i+30);
2155 if (!StrCaseCmp(buf, "default")) return -1;
2157 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2162 parse_cpair(cc, str)
2166 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2167 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2172 /* bg and attr are optional */
2173 textColors[(int)cc].bg = parse_color(str, 1);
2174 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2175 textColors[(int)cc].attr = 0;
2181 /* Arrange to catch delete-window events */
2182 Atom wm_delete_window;
2184 CatchDeleteWindow(Widget w, String procname)
2187 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2188 snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2189 XtAugmentTranslations(w, XtParseTranslationTable(buf));
2196 XtSetArg(args[0], XtNiconic, False);
2197 XtSetValues(shellWidget, args, 1);
2199 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
2203 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2205 #define BoardSize int
2206 void InitDrawingSizes(BoardSize boardSize, int flags)
2207 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2208 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2210 XtGeometryResult gres;
2213 if(!formWidget) return;
2216 * Enable shell resizing.
2218 shellArgs[0].value = (XtArgVal) &w;
2219 shellArgs[1].value = (XtArgVal) &h;
2220 XtGetValues(shellWidget, shellArgs, 2);
2222 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2223 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2224 XtSetValues(shellWidget, &shellArgs[2], 4);
2226 XtSetArg(args[0], XtNdefaultDistance, &sep);
2227 XtGetValues(formWidget, args, 1);
2229 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2230 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2233 XtSetArg(args[0], XtNwidth, boardWidth);
2234 XtSetArg(args[1], XtNheight, boardHeight);
2235 XtSetValues(boardWidget, args, 2);
2237 timerWidth = (boardWidth - sep) / 2;
2238 XtSetArg(args[0], XtNwidth, timerWidth);
2239 XtSetValues(whiteTimerWidget, args, 1);
2240 XtSetValues(blackTimerWidget, args, 1);
2242 XawFormDoLayout(formWidget, False);
2244 if (appData.titleInWindow) {
2246 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2247 XtSetArg(args[i], XtNheight, &h); i++;
2248 XtGetValues(titleWidget, args, i);
2250 w = boardWidth - 2*bor;
2252 XtSetArg(args[0], XtNwidth, &w);
2253 XtGetValues(menuBarWidget, args, 1);
2254 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2257 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2258 if (gres != XtGeometryYes && appData.debugMode) {
2260 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2261 programName, gres, w, h, wr, hr);
2265 XawFormDoLayout(formWidget, True);
2268 * Inhibit shell resizing.
2270 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2271 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2272 shellArgs[4].value = shellArgs[2].value = w;
2273 shellArgs[5].value = shellArgs[3].value = h;
2274 XtSetValues(shellWidget, &shellArgs[0], 6);
2276 // [HGM] pieces: tailor piece bitmaps to needs of specific variant
2279 for(i=0; i<4; i++) {
2281 for(p=0; p<=(int)WhiteKing; p++)
2282 xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
2283 if(gameInfo.variant == VariantShogi) {
2284 xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
2285 xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
2286 xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
2287 xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
2288 xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
2291 if(gameInfo.variant == VariantGothic) {
2292 xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
2296 // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
2297 for(p=0; p<=(int)WhiteKing; p++)
2298 ximMaskPm[p] = ximMaskPm2[p]; // defaults
2299 if(gameInfo.variant == VariantShogi) {
2300 ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
2301 ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
2302 ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
2303 ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
2304 ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
2307 if(gameInfo.variant == VariantGothic) {
2308 ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
2314 for(i=0; i<2; i++) {
2316 for(p=0; p<=(int)WhiteKing; p++)
2317 pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
2318 if(gameInfo.variant == VariantShogi) {
2319 pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
2320 pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
2321 pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
2322 pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
2323 pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
2326 if(gameInfo.variant == VariantGothic) {
2327 pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
2338 void EscapeExpand(char *p, char *q)
2339 { // [HGM] initstring: routine to shape up string arguments
2340 while(*p++ = *q++) if(p[-1] == '\\')
2342 case 'n': p[-1] = '\n'; break;
2343 case 'r': p[-1] = '\r'; break;
2344 case 't': p[-1] = '\t'; break;
2345 case '\\': p[-1] = '\\'; break;
2346 case 0: *p = 0; return;
2347 default: p[-1] = q[-1]; break;
2356 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2357 XSetWindowAttributes window_attributes;
2359 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2360 XrmValue vFrom, vTo;
2361 XtGeometryResult gres;
2364 int forceMono = False;
2367 // [HGM] before anything else, expand any indirection files amongst options
2368 char *argvCopy[1000]; // 1000 seems enough
2369 char newArgs[10000]; // holds actual characters
2372 srandom(time(0)); // [HGM] book: make random truly random
2375 for(i=0; i<argc; i++) {
2376 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2377 //fprintf(stderr, "arg %s\n", argv[i]);
2378 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2380 FILE *f = fopen(argv[i]+1, "rb");
2381 if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2382 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2383 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2385 if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2386 newArgs[k++] = 0; // terminate current arg
2387 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2388 argvCopy[j++] = newArgs + k; // get ready for next
2390 if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2404 setbuf(stdout, NULL);
2405 setbuf(stderr, NULL);
2408 programName = strrchr(argv[0], '/');
2409 if (programName == NULL)
2410 programName = argv[0];
2415 XtSetLanguageProc(NULL, NULL, NULL);
2416 bindtextdomain(PACKAGE, LOCALEDIR);
2417 textdomain(PACKAGE);
2421 XtAppInitialize(&appContext, "XBoard", shellOptions,
2422 XtNumber(shellOptions),
2423 &argc, argv, xboardResources, NULL, 0);
2425 { /* left over command line arguments, print out help and exit.
2426 * Use two columns to print help
2428 fprintf(stderr, _("%s: unrecognized argument %s\n"),
2429 programName, argv[1]);
2431 fprintf(stderr, "Recognized options:\n");
2432 for(i = 0; i < XtNumber(shellOptions); i++)
2434 /* print first column */
2435 j = fprintf(stderr, " %s%s", shellOptions[i].option,
2436 (shellOptions[i].argKind == XrmoptionSepArg
2438 /* print second column and end line */
2439 if (++i < XtNumber(shellOptions))
2441 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2442 shellOptions[i].option,
2443 (shellOptions[i].argKind == XrmoptionSepArg
2448 fprintf(stderr, "\n");
2455 if (p == NULL) p = "/tmp";
2456 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2457 gameCopyFilename = (char*) malloc(i);
2458 gamePasteFilename = (char*) malloc(i);
2459 snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2460 snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2462 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2463 clientResources, XtNumber(clientResources),
2466 { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
2467 static char buf[MSG_SIZ];
2468 EscapeExpand(buf, appData.initString);
2469 appData.initString = strdup(buf);
2470 EscapeExpand(buf, appData.secondInitString);
2471 appData.secondInitString = strdup(buf);
2472 EscapeExpand(buf, appData.firstComputerString);
2473 appData.firstComputerString = strdup(buf);
2474 EscapeExpand(buf, appData.secondComputerString);
2475 appData.secondComputerString = strdup(buf);
2478 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2481 if (chdir(chessDir) != 0) {
2482 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2488 if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2489 /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2490 if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) {
2491 printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2494 setbuf(debugFP, NULL);
2497 /* [HGM,HR] make sure board size is acceptable */
2498 if(appData.NrFiles > BOARD_SIZE ||
2499 appData.NrRanks > BOARD_SIZE )
2500 DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2503 /* This feature does not work; animation needs a rewrite */
2504 appData.highlightDragging = FALSE;
2508 xDisplay = XtDisplay(shellWidget);
2509 xScreen = DefaultScreen(xDisplay);
2510 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2512 gameInfo.variant = StringToVariant(appData.variant);
2513 InitPosition(FALSE);
2516 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2518 if (isdigit(appData.boardSize[0])) {
2519 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2520 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2521 &fontPxlSize, &smallLayout, &tinyLayout);
2523 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2524 programName, appData.boardSize);
2528 /* Find some defaults; use the nearest known size */
2529 SizeDefaults *szd, *nearest;
2530 int distance = 99999;
2531 nearest = szd = sizeDefaults;
2532 while (szd->name != NULL) {
2533 if (abs(szd->squareSize - squareSize) < distance) {
2535 distance = abs(szd->squareSize - squareSize);
2536 if (distance == 0) break;
2540 if (i < 2) lineGap = nearest->lineGap;
2541 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2542 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2543 if (i < 5) fontPxlSize = nearest->fontPxlSize;
2544 if (i < 6) smallLayout = nearest->smallLayout;
2545 if (i < 7) tinyLayout = nearest->tinyLayout;
2548 SizeDefaults *szd = sizeDefaults;
2549 if (*appData.boardSize == NULLCHAR) {
2550 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2551 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2554 if (szd->name == NULL) szd--;
2556 while (szd->name != NULL &&
2557 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2558 if (szd->name == NULL) {
2559 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2560 programName, appData.boardSize);
2564 squareSize = szd->squareSize;
2565 lineGap = szd->lineGap;
2566 clockFontPxlSize = szd->clockFontPxlSize;
2567 coordFontPxlSize = szd->coordFontPxlSize;
2568 fontPxlSize = szd->fontPxlSize;
2569 smallLayout = szd->smallLayout;
2570 tinyLayout = szd->tinyLayout;
2573 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2574 if (strlen(appData.pixmapDirectory) > 0) {
2575 p = ExpandPathName(appData.pixmapDirectory);
2577 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2578 appData.pixmapDirectory);
2581 if (appData.debugMode) {
2582 fprintf(stderr, _("\
2583 XBoard square size (hint): %d\n\
2584 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2586 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2587 if (appData.debugMode) {
2588 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2592 /* [HR] height treated separately (hacked) */
2593 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2594 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2595 if (appData.showJail == 1) {
2596 /* Jail on top and bottom */
2597 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2598 XtSetArg(boardArgs[2], XtNheight,
2599 boardHeight + 2*(lineGap + squareSize));
2600 } else if (appData.showJail == 2) {
2602 XtSetArg(boardArgs[1], XtNwidth,
2603 boardWidth + 2*(lineGap + squareSize));
2604 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2607 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2608 XtSetArg(boardArgs[2], XtNheight, boardHeight);
2612 * Determine what fonts to use.
2614 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2615 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2616 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2617 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2618 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2619 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2620 appData.font = FindFont(appData.font, fontPxlSize);
2621 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2622 countFontStruct = XQueryFont(xDisplay, countFontID);
2623 // appData.font = FindFont(appData.font, fontPxlSize);
2625 xdb = XtDatabase(xDisplay);
2626 XrmPutStringResource(&xdb, "*font", appData.font);
2629 * Detect if there are not enough colors available and adapt.
2631 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2632 appData.monoMode = True;
2635 if (!appData.monoMode) {
2636 vFrom.addr = (caddr_t) appData.lightSquareColor;
2637 vFrom.size = strlen(appData.lightSquareColor);
2638 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2639 if (vTo.addr == NULL) {
2640 appData.monoMode = True;
2643 lightSquareColor = *(Pixel *) vTo.addr;
2646 if (!appData.monoMode) {
2647 vFrom.addr = (caddr_t) appData.darkSquareColor;
2648 vFrom.size = strlen(appData.darkSquareColor);
2649 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2650 if (vTo.addr == NULL) {
2651 appData.monoMode = True;
2654 darkSquareColor = *(Pixel *) vTo.addr;
2657 if (!appData.monoMode) {
2658 vFrom.addr = (caddr_t) appData.whitePieceColor;
2659 vFrom.size = strlen(appData.whitePieceColor);
2660 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2661 if (vTo.addr == NULL) {
2662 appData.monoMode = True;
2665 whitePieceColor = *(Pixel *) vTo.addr;
2668 if (!appData.monoMode) {
2669 vFrom.addr = (caddr_t) appData.blackPieceColor;
2670 vFrom.size = strlen(appData.blackPieceColor);
2671 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2672 if (vTo.addr == NULL) {
2673 appData.monoMode = True;
2676 blackPieceColor = *(Pixel *) vTo.addr;
2680 if (!appData.monoMode) {
2681 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2682 vFrom.size = strlen(appData.highlightSquareColor);
2683 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2684 if (vTo.addr == NULL) {
2685 appData.monoMode = True;
2688 highlightSquareColor = *(Pixel *) vTo.addr;
2692 if (!appData.monoMode) {
2693 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2694 vFrom.size = strlen(appData.premoveHighlightColor);
2695 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2696 if (vTo.addr == NULL) {
2697 appData.monoMode = True;
2700 premoveHighlightColor = *(Pixel *) vTo.addr;
2705 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2708 if (appData.bitmapDirectory == NULL ||
2709 appData.bitmapDirectory[0] == NULLCHAR)
2710 appData.bitmapDirectory = DEF_BITMAP_DIR;
2713 if (appData.lowTimeWarning && !appData.monoMode) {
2714 vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2715 vFrom.size = strlen(appData.lowTimeWarningColor);
2716 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2717 if (vTo.addr == NULL)
2718 appData.monoMode = True;
2720 lowTimeWarningColor = *(Pixel *) vTo.addr;
2723 if (appData.monoMode && appData.debugMode) {
2724 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2725 (unsigned long) XWhitePixel(xDisplay, xScreen),
2726 (unsigned long) XBlackPixel(xDisplay, xScreen));
2729 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2730 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2731 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2732 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2733 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2734 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2735 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2736 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2737 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2738 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2740 if (appData.colorize) {
2742 _("%s: can't parse color names; disabling colorization\n"),
2745 appData.colorize = FALSE;
2747 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2748 textColors[ColorNone].attr = 0;
2750 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2756 layoutName = "tinyLayout";
2757 } else if (smallLayout) {
2758 layoutName = "smallLayout";
2760 layoutName = "normalLayout";
2762 /* Outer layoutWidget is there only to provide a name for use in
2763 resources that depend on the layout style */
2765 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2766 layoutArgs, XtNumber(layoutArgs));
2768 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2769 formArgs, XtNumber(formArgs));
2770 XtSetArg(args[0], XtNdefaultDistance, &sep);
2771 XtGetValues(formWidget, args, 1);
2774 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2775 XtSetArg(args[0], XtNtop, XtChainTop);
2776 XtSetArg(args[1], XtNbottom, XtChainTop);
2777 XtSetValues(menuBarWidget, args, 2);
2779 widgetList[j++] = whiteTimerWidget =
2780 XtCreateWidget("whiteTime", labelWidgetClass,
2781 formWidget, timerArgs, XtNumber(timerArgs));
2782 XtSetArg(args[0], XtNfont, clockFontStruct);
2783 XtSetArg(args[1], XtNtop, XtChainTop);
2784 XtSetArg(args[2], XtNbottom, XtChainTop);
2785 XtSetValues(whiteTimerWidget, args, 3);
2787 widgetList[j++] = blackTimerWidget =
2788 XtCreateWidget("blackTime", labelWidgetClass,
2789 formWidget, timerArgs, XtNumber(timerArgs));
2790 XtSetArg(args[0], XtNfont, clockFontStruct);
2791 XtSetArg(args[1], XtNtop, XtChainTop);
2792 XtSetArg(args[2], XtNbottom, XtChainTop);
2793 XtSetValues(blackTimerWidget, args, 3);
2795 if (appData.titleInWindow) {
2796 widgetList[j++] = titleWidget =
2797 XtCreateWidget("title", labelWidgetClass, formWidget,
2798 titleArgs, XtNumber(titleArgs));
2799 XtSetArg(args[0], XtNtop, XtChainTop);
2800 XtSetArg(args[1], XtNbottom, XtChainTop);
2801 XtSetValues(titleWidget, args, 2);
2804 if (appData.showButtonBar) {
2805 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2806 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
2807 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2808 XtSetArg(args[2], XtNtop, XtChainTop);
2809 XtSetArg(args[3], XtNbottom, XtChainTop);
2810 XtSetValues(buttonBarWidget, args, 4);
2813 widgetList[j++] = messageWidget =
2814 XtCreateWidget("message", labelWidgetClass, formWidget,
2815 messageArgs, XtNumber(messageArgs));
2816 XtSetArg(args[0], XtNtop, XtChainTop);
2817 XtSetArg(args[1], XtNbottom, XtChainTop);
2818 XtSetValues(messageWidget, args, 2);
2820 widgetList[j++] = boardWidget =
2821 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2822 XtNumber(boardArgs));
2824 XtManageChildren(widgetList, j);
2826 timerWidth = (boardWidth - sep) / 2;
2827 XtSetArg(args[0], XtNwidth, timerWidth);
2828 XtSetValues(whiteTimerWidget, args, 1);
2829 XtSetValues(blackTimerWidget, args, 1);
2831 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2832 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2833 XtGetValues(whiteTimerWidget, args, 2);
2835 if (appData.showButtonBar) {
2836 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2837 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2838 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2842 * formWidget uses these constraints but they are stored
2846 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2847 XtSetValues(menuBarWidget, args, i);
2848 if (appData.titleInWindow) {
2851 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2852 XtSetValues(whiteTimerWidget, args, i);
2854 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2855 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2856 XtSetValues(blackTimerWidget, args, i);
2858 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2859 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2860 XtSetValues(titleWidget, args, i);
2862 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2863 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2864 XtSetValues(messageWidget, args, i);
2865 if (appData.showButtonBar) {
2867 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2868 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2869 XtSetValues(buttonBarWidget, args, i);
2873 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2874 XtSetValues(whiteTimerWidget, args, i);
2876 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2877 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2878 XtSetValues(blackTimerWidget, args, i);
2880 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2881 XtSetValues(titleWidget, args, i);
2883 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2884 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2885 XtSetValues(messageWidget, args, i);
2886 if (appData.showButtonBar) {
2888 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2889 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2890 XtSetValues(buttonBarWidget, args, i);
2895 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2896 XtSetValues(whiteTimerWidget, args, i);
2898 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2899 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2900 XtSetValues(blackTimerWidget, args, i);
2902 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2903 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2904 XtSetValues(messageWidget, args, i);
2905 if (appData.showButtonBar) {
2907 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2908 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2909 XtSetValues(buttonBarWidget, args, i);
2913 XtSetArg(args[0], XtNfromVert, messageWidget);
2914 XtSetArg(args[1], XtNtop, XtChainTop);
2915 XtSetArg(args[2], XtNbottom, XtChainBottom);
2916 XtSetArg(args[3], XtNleft, XtChainLeft);
2917 XtSetArg(args[4], XtNright, XtChainRight);
2918 XtSetValues(boardWidget, args, 5);
2920 XtRealizeWidget(shellWidget);
2923 * Correct the width of the message and title widgets.
2924 * It is not known why some systems need the extra fudge term.
2925 * The value "2" is probably larger than needed.
2927 XawFormDoLayout(formWidget, False);
2929 #define WIDTH_FUDGE 2
2931 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2932 XtSetArg(args[i], XtNheight, &h); i++;
2933 XtGetValues(messageWidget, args, i);
2934 if (appData.showButtonBar) {
2936 XtSetArg(args[i], XtNwidth, &w); i++;
2937 XtGetValues(buttonBarWidget, args, i);
2938 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2940 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2943 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2944 if (gres != XtGeometryYes && appData.debugMode) {
2945 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2946 programName, gres, w, h, wr, hr);
2949 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2950 /* The size used for the child widget in layout lags one resize behind
2951 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2953 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2954 if (gres != XtGeometryYes && appData.debugMode) {
2955 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2956 programName, gres, w, h, wr, hr);
2959 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
2960 XtSetArg(args[1], XtNright, XtChainRight);
2961 XtSetValues(messageWidget, args, 2);
2963 if (appData.titleInWindow) {
2965 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2966 XtSetArg(args[i], XtNheight, &h); i++;
2967 XtGetValues(titleWidget, args, i);
2969 w = boardWidth - 2*bor;
2971 XtSetArg(args[0], XtNwidth, &w);
2972 XtGetValues(menuBarWidget, args, 1);
2973 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2976 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2977 if (gres != XtGeometryYes && appData.debugMode) {
2979 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2980 programName, gres, w, h, wr, hr);
2983 XawFormDoLayout(formWidget, True);
2985 xBoardWindow = XtWindow(boardWidget);
2987 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2988 // not need to go into InitDrawingSizes().
2992 * Create X checkmark bitmap and initialize option menu checks.
2994 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2995 checkmark_bits, checkmark_width, checkmark_height);
2996 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2997 if (appData.alwaysPromoteToQueen) {
2998 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
3001 if (appData.animateDragging) {
3002 XtSetValues(XtNameToWidget(menuBarWidget,
3003 "menuOptions.Animate Dragging"),
3006 if (appData.animate) {
3007 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
3010 if (appData.autoComment) {
3011 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
3014 if (appData.autoCallFlag) {
3015 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
3018 if (appData.autoFlipView) {
3019 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
3022 if (appData.autoObserve) {
3023 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
3026 if (appData.autoRaiseBoard) {
3027 XtSetValues(XtNameToWidget(menuBarWidget,
3028 "menuOptions.Auto Raise Board"), args, 1);
3030 if (appData.autoSaveGames) {
3031 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3034 if (appData.saveGameFile[0] != NULLCHAR) {
3035 /* Can't turn this off from menu */
3036 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3038 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
3042 if (appData.blindfold) {
3043 XtSetValues(XtNameToWidget(menuBarWidget,
3044 "menuOptions.Blindfold"), args, 1);
3046 if (appData.flashCount > 0) {
3047 XtSetValues(XtNameToWidget(menuBarWidget,
3048 "menuOptions.Flash Moves"),
3051 if (appData.getMoveList) {
3052 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
3056 if (appData.highlightDragging) {
3057 XtSetValues(XtNameToWidget(menuBarWidget,
3058 "menuOptions.Highlight Dragging"),
3062 if (appData.highlightLastMove) {
3063 XtSetValues(XtNameToWidget(menuBarWidget,
3064 "menuOptions.Highlight Last Move"),
3067 if (appData.icsAlarm) {
3068 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
3071 if (appData.ringBellAfterMoves) {
3072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
3075 if (appData.oldSaveStyle) {
3076 XtSetValues(XtNameToWidget(menuBarWidget,
3077 "menuOptions.Old Save Style"), args, 1);
3079 if (appData.periodicUpdates) {
3080 XtSetValues(XtNameToWidget(menuBarWidget,
3081 "menuOptions.Periodic Updates"), args, 1);
3083 if (appData.ponderNextMove) {
3084 XtSetValues(XtNameToWidget(menuBarWidget,
3085 "menuOptions.Ponder Next Move"), args, 1);
3087 if (appData.popupExitMessage) {
3088 XtSetValues(XtNameToWidget(menuBarWidget,
3089 "menuOptions.Popup Exit Message"), args, 1);
3091 if (appData.popupMoveErrors) {
3092 XtSetValues(XtNameToWidget(menuBarWidget,
3093 "menuOptions.Popup Move Errors"), args, 1);
3095 if (appData.premove) {
3096 XtSetValues(XtNameToWidget(menuBarWidget,
3097 "menuOptions.Premove"), args, 1);
3099 if (appData.quietPlay) {
3100 XtSetValues(XtNameToWidget(menuBarWidget,
3101 "menuOptions.Quiet Play"), args, 1);
3103 if (appData.showCoords) {
3104 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3107 if (appData.hideThinkingFromHuman) {
3108 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3111 if (appData.testLegality) {
3112 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3119 ReadBitmap(&wIconPixmap, "icon_white.bm",
3120 icon_white_bits, icon_white_width, icon_white_height);
3121 ReadBitmap(&bIconPixmap, "icon_black.bm",
3122 icon_black_bits, icon_black_width, icon_black_height);
3123 iconPixmap = wIconPixmap;
3125 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
3126 XtSetValues(shellWidget, args, i);
3129 * Create a cursor for the board widget.
3131 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3132 XChangeWindowAttributes(xDisplay, xBoardWindow,
3133 CWCursor, &window_attributes);
3136 * Inhibit shell resizing.
3138 shellArgs[0].value = (XtArgVal) &w;
3139 shellArgs[1].value = (XtArgVal) &h;
3140 XtGetValues(shellWidget, shellArgs, 2);
3141 shellArgs[4].value = shellArgs[2].value = w;
3142 shellArgs[5].value = shellArgs[3].value = h;
3143 XtSetValues(shellWidget, &shellArgs[2], 4);
3144 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3145 marginH = h - boardHeight;
3147 CatchDeleteWindow(shellWidget, "QuitProc");
3152 if (appData.bitmapDirectory[0] != NULLCHAR) {
3159 /* Create regular pieces */
3160 if (!useImages) CreatePieces();
3165 if (appData.animate || appData.animateDragging)
3168 XtAugmentTranslations(formWidget,
3169 XtParseTranslationTable(globalTranslations));
3170 XtAugmentTranslations(boardWidget,
3171 XtParseTranslationTable(boardTranslations));
3172 XtAugmentTranslations(whiteTimerWidget,
3173 XtParseTranslationTable(whiteTranslations));
3174 XtAugmentTranslations(blackTimerWidget,
3175 XtParseTranslationTable(blackTranslations));
3177 /* Why is the following needed on some versions of X instead
3178 * of a translation? */
3179 XtAddEventHandler(boardWidget, ExposureMask, False,
3180 (XtEventHandler) EventProc, NULL);
3185 if (errorExitStatus == -1) {
3186 if (appData.icsActive) {
3187 /* We now wait until we see "login:" from the ICS before
3188 sending the logon script (problems with timestamp otherwise) */
3189 /*ICSInitScript();*/
3190 if (appData.icsInputBox) ICSInputBoxPopUp();
3193 signal(SIGINT, IntSigHandler);
3194 signal(SIGTERM, IntSigHandler);
3195 if (*appData.cmailGameName != NULLCHAR) {
3196 signal(SIGUSR1, CmailSigHandler);
3199 gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
3202 XtAppMainLoop(appContext);
3203 if (appData.debugMode) fclose(debugFP); // [DM] debug
3210 if (appData.icsActive && oldICSInteractionTitle != NULL) {
3211 DisplayIcsInteractionTitle(oldICSInteractionTitle);
3213 unlink(gameCopyFilename);
3214 unlink(gamePasteFilename);
3217 RETSIGTYPE TermSizeSigHandler(int sig)
3230 CmailSigHandler(sig)
3236 signal(SIGUSR1, SIG_IGN); /* suspend handler */
3238 /* Activate call-back function CmailSigHandlerCallBack() */
3239 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3241 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3245 CmailSigHandlerCallBack(isr, closure, message, count, error)
3253 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
3255 /**** end signal code ****/
3265 f = fopen(appData.icsLogon, "r");
3271 strcat(buf, appData.icsLogon);
3272 f = fopen(buf, "r");
3276 ProcessICSInitScript(f);
3283 EditCommentPopDown();
3294 SetMenuEnables(enab)
3298 if (!menuBarWidget) return;
3299 while (enab->name != NULL) {
3300 w = XtNameToWidget(menuBarWidget, enab->name);
3302 DisplayError(enab->name, 0);
3304 XtSetSensitive(w, enab->value);
3310 Enables icsEnables[] = {
3311 { "menuFile.Mail Move", False },
3312 { "menuFile.Reload CMail Message", False },
3313 { "menuMode.Machine Black", False },
3314 { "menuMode.Machine White", False },
3315 { "menuMode.Analysis Mode", False },
3316 { "menuMode.Analyze File", False },
3317 { "menuMode.Two Machines", False },
3319 { "menuHelp.Hint", False },
3320 { "menuHelp.Book", False },
3321 { "menuStep.Move Now", False },
3322 { "menuOptions.Periodic Updates", False },
3323 { "menuOptions.Hide Thinking", False },
3324 { "menuOptions.Ponder Next Move", False },
3329 Enables ncpEnables[] = {
3330 { "menuFile.Mail Move", False },
3331 { "menuFile.Reload CMail Message", False },
3332 { "menuMode.Machine White", False },
3333 { "menuMode.Machine Black", False },
3334 { "menuMode.Analysis Mode", False },
3335 { "menuMode.Analyze File", False },
3336 { "menuMode.Two Machines", False },
3337 { "menuMode.ICS Client", False },
3338 { "menuMode.ICS Input Box", False },
3339 { "Action", False },
3340 { "menuStep.Revert", False },
3341 { "menuStep.Move Now", False },
3342 { "menuStep.Retract Move", False },
3343 { "menuOptions.Auto Comment", False },
3344 { "menuOptions.Auto Flag", False },
3345 { "menuOptions.Auto Flip View", False },
3346 { "menuOptions.Auto Observe", False },
3347 { "menuOptions.Auto Raise Board", False },
3348 { "menuOptions.Get Move List", False },
3349 { "menuOptions.ICS Alarm", False },
3350 { "menuOptions.Move Sound", False },
3351 { "menuOptions.Quiet Play", False },
3352 { "menuOptions.Hide Thinking", False },
3353 { "menuOptions.Periodic Updates", False },
3354 { "menuOptions.Ponder Next Move", False },
3355 { "menuHelp.Hint", False },
3356 { "menuHelp.Book", False },
3360 Enables gnuEnables[] = {
3361 { "menuMode.ICS Client", False },
3362 { "menuMode.ICS Input Box", False },
3363 { "menuAction.Accept", False },
3364 { "menuAction.Decline", False },
3365 { "menuAction.Rematch", False },
3366 { "menuAction.Adjourn", False },
3367 { "menuAction.Stop Examining", False },
3368 { "menuAction.Stop Observing", False },
3369 { "menuStep.Revert", False },
3370 { "menuOptions.Auto Comment", False },
3371 { "menuOptions.Auto Observe", False },
3372 { "menuOptions.Auto Raise Board", False },
3373 { "menuOptions.Get Move List", False },
3374 { "menuOptions.Premove", False },
3375 { "menuOptions.Quiet Play", False },
3377 /* The next two options rely on SetCmailMode being called *after* */
3378 /* SetGNUMode so that when GNU is being used to give hints these */
3379 /* menu options are still available */
3381 { "menuFile.Mail Move", False },
3382 { "menuFile.Reload CMail Message", False },
3386 Enables cmailEnables[] = {
3388 { "menuAction.Call Flag", False },
3389 { "menuAction.Draw", True },
3390 { "menuAction.Adjourn", False },
3391 { "menuAction.Abort", False },
3392 { "menuAction.Stop Observing", False },
3393 { "menuAction.Stop Examining", False },
3394 { "menuFile.Mail Move", True },
3395 { "menuFile.Reload CMail Message", True },
3399 Enables trainingOnEnables[] = {
3400 { "menuMode.Edit Comment", False },
3401 { "menuMode.Pause", False },
3402 { "menuStep.Forward", False },
3403 { "menuStep.Backward", False },
3404 { "menuStep.Forward to End", False },
3405 { "menuStep.Back to Start", False },
3406 { "menuStep.Move Now", False },
3407 { "menuStep.Truncate Game", False },
3411 Enables trainingOffEnables[] = {
3412 { "menuMode.Edit Comment", True },
3413 { "menuMode.Pause", True },
3414 { "menuStep.Forward", True },
3415 { "menuStep.Backward", True },
3416 { "menuStep.Forward to End", True },
3417 { "menuStep.Back to Start", True },
3418 { "menuStep.Move Now", True },
3419 { "menuStep.Truncate Game", True },
3423 Enables machineThinkingEnables[] = {
3424 { "menuFile.Load Game", False },
3425 { "menuFile.Load Next Game", False },
3426 { "menuFile.Load Previous Game", False },
3427 { "menuFile.Reload Same Game", False },
3428 { "menuFile.Paste Game", False },
3429 { "menuFile.Load Position", False },
3430 { "menuFile.Load Next Position", False },
3431 { "menuFile.Load Previous Position", False },
3432 { "menuFile.Reload Same Position", False },
3433 { "menuFile.Paste Position", False },
3434 { "menuMode.Machine White", False },
3435 { "menuMode.Machine Black", False },
3436 { "menuMode.Two Machines", False },
3437 { "menuStep.Retract Move", False },
3441 Enables userThinkingEnables[] = {
3442 { "menuFile.Load Game", True },
3443 { "menuFile.Load Next Game", True },
3444 { "menuFile.Load Previous Game", True },
3445 { "menuFile.Reload Same Game", True },
3446 { "menuFile.Paste Game", True },
3447 { "menuFile.Load Position", True },
3448 { "menuFile.Load Next Position", True },
3449 { "menuFile.Load Previous Position", True },
3450 { "menuFile.Reload Same Position", True },
3451 { "menuFile.Paste Position", True },
3452 { "menuMode.Machine White", True },
3453 { "menuMode.Machine Black", True },
3454 { "menuMode.Two Machines", True },
3455 { "menuStep.Retract Move", True },
3461 SetMenuEnables(icsEnables);
3464 if (appData.zippyPlay && !appData.noChessProgram) /* [DM] icsEngineAnalyze */
3465 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3472 SetMenuEnables(ncpEnables);
3478 SetMenuEnables(gnuEnables);
3484 SetMenuEnables(cmailEnables);
3490 SetMenuEnables(trainingOnEnables);
3491 if (appData.showButtonBar) {
3492 XtSetSensitive(buttonBarWidget, False);
3498 SetTrainingModeOff()
3500 SetMenuEnables(trainingOffEnables);
3501 if (appData.showButtonBar) {
3502 XtSetSensitive(buttonBarWidget, True);
3507 SetUserThinkingEnables()
3509 if (appData.noChessProgram) return;
3510 SetMenuEnables(userThinkingEnables);
3514 SetMachineThinkingEnables()
3516 if (appData.noChessProgram) return;
3517 SetMenuEnables(machineThinkingEnables);
3519 case MachinePlaysBlack:
3520 case MachinePlaysWhite:
3521 case TwoMachinesPlay:
3522 XtSetSensitive(XtNameToWidget(menuBarWidget,
3523 ModeToWidgetName(gameMode)), True);
3530 #define Abs(n) ((n)<0 ? -(n) : (n))
3533 * Find a font that matches "pattern" that is as close as
3534 * possible to the targetPxlSize. Prefer fonts that are k
3535 * pixels smaller to fonts that are k pixels larger. The
3536 * pattern must be in the X Consortium standard format,
3537 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3538 * The return value should be freed with XtFree when no
3541 char *FindFont(pattern, targetPxlSize)
3545 char **fonts, *p, *best, *scalable, *scalableTail;
3546 int i, j, nfonts, minerr, err, pxlSize;
3549 char **missing_list;
3551 char *def_string, *base_fnt_lst, strInt[3];
3553 XFontStruct **fnt_list;
3555 base_fnt_lst = calloc(1, strlen(pattern) + 3);
3556 sprintf(strInt, "%d", targetPxlSize);
3557 p = strstr(pattern, "--");
3558 strncpy(base_fnt_lst, pattern, p - pattern + 2);
3559 strcat(base_fnt_lst, strInt);
3560 strcat(base_fnt_lst, strchr(p + 2, '-'));
3562 if ((fntSet = XCreateFontSet(xDisplay,
3566 &def_string)) == NULL) {
3568 fprintf(stderr, _("Unable to create font set.\n"));
3572 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3574 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3576 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3577 programName, pattern);
3585 for (i=0; i<nfonts; i++) {
3588 if (*p != '-') continue;
3590 if (*p == NULLCHAR) break;
3591 if (*p++ == '-') j++;
3593 if (j < 7) continue;
3596 scalable = fonts[i];
3599 err = pxlSize - targetPxlSize;
3600 if (Abs(err) < Abs(minerr) ||
3601 (minerr > 0 && err < 0 && -err == minerr)) {
3607 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3608 /* If the error is too big and there is a scalable font,
3609 use the scalable font. */
3610 int headlen = scalableTail - scalable;
3611 p = (char *) XtMalloc(strlen(scalable) + 10);
3612 while (isdigit(*scalableTail)) scalableTail++;
3613 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3615 p = (char *) XtMalloc(strlen(best) + 1);
3618 if (appData.debugMode) {
3619 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
3620 pattern, targetPxlSize, p);
3623 if (missing_count > 0)
3624 XFreeStringList(missing_list);
3625 XFreeFontSet(xDisplay, fntSet);
3627 XFreeFontNames(fonts);
3634 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3635 | GCBackground | GCFunction | GCPlaneMask;
3636 XGCValues gc_values;
3639 gc_values.plane_mask = AllPlanes;
3640 gc_values.line_width = lineGap;
3641 gc_values.line_style = LineSolid;
3642 gc_values.function = GXcopy;
3644 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3645 gc_values.background = XBlackPixel(xDisplay, xScreen);
3646 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3648 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3649 gc_values.background = XWhitePixel(xDisplay, xScreen);
3650 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3651 XSetFont(xDisplay, coordGC, coordFontID);
3653 // [HGM] make font for holdings counts (white on black0
3654 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3655 gc_values.background = XBlackPixel(xDisplay, xScreen);
3656 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3657 XSetFont(xDisplay, countGC, countFontID);
3659 if (appData.monoMode) {
3660 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3661 gc_values.background = XWhitePixel(xDisplay, xScreen);
3662 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3664 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3665 gc_values.background = XBlackPixel(xDisplay, xScreen);
3666 lightSquareGC = wbPieceGC
3667 = XtGetGC(shellWidget, value_mask, &gc_values);
3669 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3670 gc_values.background = XWhitePixel(xDisplay, xScreen);
3671 darkSquareGC = bwPieceGC
3672 = XtGetGC(shellWidget, value_mask, &gc_values);
3674 if (DefaultDepth(xDisplay, xScreen) == 1) {
3675 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3676 gc_values.function = GXcopyInverted;
3677 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3678 gc_values.function = GXcopy;
3679 if (XBlackPixel(xDisplay, xScreen) == 1) {
3680 bwPieceGC = darkSquareGC;
3681 wbPieceGC = copyInvertedGC;
3683 bwPieceGC = copyInvertedGC;
3684 wbPieceGC = lightSquareGC;
3688 gc_values.foreground = highlightSquareColor;
3689 gc_values.background = highlightSquareColor;
3690 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3692 gc_values.foreground = premoveHighlightColor;
3693 gc_values.background = premoveHighlightColor;
3694 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3696 gc_values.foreground = lightSquareColor;
3697 gc_values.background = darkSquareColor;
3698 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3700 gc_values.foreground = darkSquareColor;
3701 gc_values.background = lightSquareColor;
3702 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3704 gc_values.foreground = jailSquareColor;
3705 gc_values.background = jailSquareColor;
3706 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3708 gc_values.foreground = whitePieceColor;
3709 gc_values.background = darkSquareColor;
3710 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3712 gc_values.foreground = whitePieceColor;
3713 gc_values.background = lightSquareColor;
3714 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3716 gc_values.foreground = whitePieceColor;
3717 gc_values.background = jailSquareColor;
3718 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3720 gc_values.foreground = blackPieceColor;
3721 gc_values.background = darkSquareColor;
3722 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3724 gc_values.foreground = blackPieceColor;
3725 gc_values.background = lightSquareColor;
3726 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3728 gc_values.foreground = blackPieceColor;
3729 gc_values.background = jailSquareColor;
3730 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3734 void loadXIM(xim, xmask, filename, dest, mask)
3747 fp = fopen(filename, "rb");
3749 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3756 for (y=0; y<h; ++y) {
3757 for (x=0; x<h; ++x) {
3762 XPutPixel(xim, x, y, blackPieceColor);
3764 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3767 XPutPixel(xim, x, y, darkSquareColor);
3769 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3772 XPutPixel(xim, x, y, whitePieceColor);
3774 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3777 XPutPixel(xim, x, y, lightSquareColor);
3779 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3785 /* create Pixmap of piece */
3786 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3788 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3791 /* create Pixmap of clipmask
3792 Note: We assume the white/black pieces have the same
3793 outline, so we make only 6 masks. This is okay
3794 since the XPM clipmask routines do the same. */
3796 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3798 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3801 /* now create the 1-bit version */
3802 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3805 values.foreground = 1;
3806 values.background = 0;
3808 /* Don't use XtGetGC, not read only */
3809 maskGC = XCreateGC(xDisplay, *mask,
3810 GCForeground | GCBackground, &values);
3811 XCopyPlane(xDisplay, temp, *mask, maskGC,
3812 0, 0, squareSize, squareSize, 0, 0, 1);
3813 XFreePixmap(xDisplay, temp);
3818 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
3820 void CreateXIMPieces()
3825 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3830 /* The XSynchronize calls were copied from CreatePieces.
3831 Not sure if needed, but can't hurt */
3832 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3835 /* temp needed by loadXIM() */
3836 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3837 0, 0, ss, ss, AllPlanes, XYPixmap);
3839 if (strlen(appData.pixmapDirectory) == 0) {
3843 if (appData.monoMode) {
3844 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3848 fprintf(stderr, _("\nLoading XIMs...\n"));
3850 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3851 fprintf(stderr, "%d", piece+1);
3852 for (kind=0; kind<4; kind++) {
3853 fprintf(stderr, ".");
3854 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
3855 ExpandPathName(appData.pixmapDirectory),
3856 piece <= (int) WhiteKing ? "" : "w",
3857 pieceBitmapNames[piece],
3859 ximPieceBitmap[kind][piece] =
3860 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3861 0, 0, ss, ss, AllPlanes, XYPixmap);
3862 if (appData.debugMode)
3863 fprintf(stderr, _("(File:%s:) "), buf);
3864 loadXIM(ximPieceBitmap[kind][piece],
3866 &(xpmPieceBitmap2[kind][piece]),
3867 &(ximMaskPm2[piece]));
3868 if(piece <= (int)WhiteKing)
3869 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3871 fprintf(stderr," ");
3873 /* Load light and dark squares */
3874 /* If the LSQ and DSQ pieces don't exist, we will
3875 draw them with solid squares. */
3876 snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3877 if (access(buf, 0) != 0) {
3881 fprintf(stderr, _("light square "));
3883 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3884 0, 0, ss, ss, AllPlanes, XYPixmap);
3885 if (appData.debugMode)
3886 fprintf(stderr, _("(File:%s:) "), buf);
3888 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3889 fprintf(stderr, _("dark square "));
3890 snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3891 ExpandPathName(appData.pixmapDirectory), ss);
3892 if (appData.debugMode)
3893 fprintf(stderr, _("(File:%s:) "), buf);
3895 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3896 0, 0, ss, ss, AllPlanes, XYPixmap);
3897 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3898 xpmJailSquare = xpmLightSquare;
3900 fprintf(stderr, _("Done.\n"));
3902 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3906 void CreateXPMPieces()
3910 u_int ss = squareSize;
3912 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3913 XpmColorSymbol symbols[4];
3915 /* The XSynchronize calls were copied from CreatePieces.
3916 Not sure if needed, but can't hurt */
3917 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3919 /* Setup translations so piece colors match square colors */
3920 symbols[0].name = "light_piece";
3921 symbols[0].value = appData.whitePieceColor;
3922 symbols[1].name = "dark_piece";
3923 symbols[1].value = appData.blackPieceColor;
3924 symbols[2].name = "light_square";
3925 symbols[2].value = appData.lightSquareColor;
3926 symbols[3].name = "dark_square";
3927 symbols[3].value = appData.darkSquareColor;
3929 attr.valuemask = XpmColorSymbols;
3930 attr.colorsymbols = symbols;
3931 attr.numsymbols = 4;
3933 if (appData.monoMode) {
3934 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3938 if (strlen(appData.pixmapDirectory) == 0) {
3939 XpmPieces* pieces = builtInXpms;
3942 while (pieces->size != squareSize && pieces->size) pieces++;
3943 if (!pieces->size) {
3944 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3947 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3948 for (kind=0; kind<4; kind++) {
3950 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3951 pieces->xpm[piece][kind],
3952 &(xpmPieceBitmap2[kind][piece]),
3953 NULL, &attr)) != 0) {
3954 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3958 if(piece <= (int) WhiteKing)
3959 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
3963 xpmJailSquare = xpmLightSquare;
3967 fprintf(stderr, _("\nLoading XPMs...\n"));
3970 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
3971 fprintf(stderr, "%d ", piece+1);
3972 for (kind=0; kind<4; kind++) {
3973 snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
3974 ExpandPathName(appData.pixmapDirectory),
3975 piece > (int) WhiteKing ? "w" : "",
3976 pieceBitmapNames[piece],
3978 if (appData.debugMode) {
3979 fprintf(stderr, _("(File:%s:) "), buf);
3981 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3982 &(xpmPieceBitmap2[kind][piece]),
3983 NULL, &attr)) != 0) {
3984 if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
3985 // [HGM] missing: read of unorthodox piece failed; substitute King.
3986 snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
3987 ExpandPathName(appData.pixmapDirectory),
3989 if (appData.debugMode) {
3990 fprintf(stderr, _("(Replace by File:%s:) "), buf);
3992 r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3993 &(xpmPieceBitmap2[kind][piece]),
3997 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
4002 if(piece <= (int) WhiteKing)
4003 xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
4006 /* Load light and dark squares */
4007 /* If the LSQ and DSQ pieces don't exist, we will
4008 draw them with solid squares. */
4009 fprintf(stderr, _("light square "));
4010 snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
4011 if (access(buf, 0) != 0) {
4015 if (appData.debugMode)
4016 fprintf(stderr, _("(File:%s:) "), buf);
4018 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4019 &xpmLightSquare, NULL, &attr)) != 0) {
4020 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4023 fprintf(stderr, _("dark square "));
4024 snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
4025 ExpandPathName(appData.pixmapDirectory), ss);
4026 if (appData.debugMode) {
4027 fprintf(stderr, _("(File:%s:) "), buf);
4029 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
4030 &xpmDarkSquare, NULL, &attr)) != 0) {
4031 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
4035 xpmJailSquare = xpmLightSquare;
4036 fprintf(stderr, _("Done.\n"));
4038 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4041 #endif /* HAVE_LIBXPM */
4044 /* No built-in bitmaps */
4049 u_int ss = squareSize;
4051 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4054 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4055 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4056 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4057 pieceBitmapNames[piece],
4058 ss, kind == SOLID ? 's' : 'o');
4059 ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
4060 if(piece <= (int)WhiteKing)
4061 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4065 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4069 /* With built-in bitmaps */
4072 BuiltInBits* bib = builtInBits;
4075 u_int ss = squareSize;
4077 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
4080 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
4082 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
4083 for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
4084 sprintf(buf, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
4085 pieceBitmapNames[piece],
4086 ss, kind == SOLID ? 's' : 'o');
4087 ReadBitmap(&pieceBitmap2[kind][piece], buf,
4088 bib->bits[kind][piece], ss, ss);
4089 if(piece <= (int)WhiteKing)
4090 pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
4094 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
4099 void ReadBitmap(pm, name, bits, wreq, hreq)
4102 unsigned char bits[];
4108 char msg[MSG_SIZ], fullname[MSG_SIZ];
4110 if (*appData.bitmapDirectory != NULLCHAR) {
4111 strcpy(fullname, appData.bitmapDirectory);
4112 strcat(fullname, "/");
4113 strcat(fullname, name);
4114 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
4115 &w, &h, pm, &x_hot, &y_hot);
4116 fprintf(stderr, "load %s\n", name);
4117 if (errcode != BitmapSuccess) {
4119 case BitmapOpenFailed:
4120 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
4122 case BitmapFileInvalid:
4123 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
4125 case BitmapNoMemory:
4126 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4130 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4134 fprintf(stderr, _("%s: %s...using built-in\n"),
4136 } else if (w != wreq || h != hreq) {
4138 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4139 programName, fullname, w, h, wreq, hreq);
4145 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4154 if (lineGap == 0) return;
4156 /* [HR] Split this into 2 loops for non-square boards. */
4158 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4159 gridSegments[i].x1 = 0;
4160 gridSegments[i].x2 =
4161 lineGap + BOARD_WIDTH * (squareSize + lineGap);
4162 gridSegments[i].y1 = gridSegments[i].y2
4163 = lineGap / 2 + (i * (squareSize + lineGap));
4166 for (j = 0; j < BOARD_WIDTH + 1; j++) {
4167 gridSegments[j + i].y1 = 0;
4168 gridSegments[j + i].y2 =
4169 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4170 gridSegments[j + i].x1 = gridSegments[j + i].x2
4171 = lineGap / 2 + (j * (squareSize + lineGap));
4175 static void MenuBarSelect(w, addr, index)
4180 XtActionProc proc = (XtActionProc) addr;
4182 (proc)(NULL, NULL, NULL, NULL);
4185 void CreateMenuBarPopup(parent, name, mb)
4195 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4198 XtSetArg(args[j], XtNleftMargin, 20); j++;
4199 XtSetArg(args[j], XtNrightMargin, 20); j++;
4201 while (mi->string != NULL) {
4202 if (strcmp(mi->string, "----") == 0) {
4203 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4206 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4207 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4209 XtAddCallback(entry, XtNcallback,
4210 (XtCallbackProc) MenuBarSelect,
4211 (caddr_t) mi->proc);
4217 Widget CreateMenuBar(mb)
4221 Widget anchor, menuBar;
4223 char menuName[MSG_SIZ];
4226 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4227 XtSetArg(args[j], XtNvSpace, 0); j++;
4228 XtSetArg(args[j], XtNborderWidth, 0); j++;
4229 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4230 formWidget, args, j);
4232 while (mb->name != NULL) {
4233 strcpy(menuName, "menu");
4234 strcat(menuName, mb->name);
4236 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
4239 shortName[0] = _(mb->name)[0];
4240 shortName[1] = NULLCHAR;
4241 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4244 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
4247 XtSetArg(args[j], XtNborderWidth, 0); j++;
4248 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
4250 CreateMenuBarPopup(menuBar, menuName, mb);
4256 Widget CreateButtonBar(mi)
4260 Widget button, buttonBar;
4264 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
4266 XtSetArg(args[j], XtNhSpace, 0); j++;
4268 XtSetArg(args[j], XtNborderWidth, 0); j++;
4269 XtSetArg(args[j], XtNvSpace, 0); j++;
4270 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
4271 formWidget, args, j);
4273 while (mi->string != NULL) {
4276 XtSetArg(args[j], XtNinternalWidth, 2); j++;
4277 XtSetArg(args[j], XtNborderWidth, 0); j++;
4279 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
4280 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
4281 buttonBar, args, j);
4282 XtAddCallback(button, XtNcallback,
4283 (XtCallbackProc) MenuBarSelect,
4284 (caddr_t) mi->proc);
4291 CreatePieceMenu(name, color)
4298 ChessSquare selection;
4300 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4301 boardWidget, args, 0);
4303 for (i = 0; i < PIECE_MENU_SIZE; i++) {
4304 String item = pieceMenuStrings[color][i];
4306 if (strcmp(item, "----") == 0) {
4307 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4310 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4311 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4313 selection = pieceMenuTranslation[color][i];
4314 XtAddCallback(entry, XtNcallback,
4315 (XtCallbackProc) PieceMenuSelect,
4316 (caddr_t) selection);
4317 if (selection == WhitePawn || selection == BlackPawn) {
4318 XtSetArg(args[0], XtNpopupOnEntry, entry);
4319 XtSetValues(menu, args, 1);
4332 ChessSquare selection;
4334 whitePieceMenu = CreatePieceMenu("menuW", 0);
4335 blackPieceMenu = CreatePieceMenu("menuB", 1);
4337 XtRegisterGrabAction(PieceMenuPopup, True,
4338 (unsigned)(ButtonPressMask|ButtonReleaseMask),
4339 GrabModeAsync, GrabModeAsync);
4341 XtSetArg(args[0], XtNlabel, _("Drop"));
4342 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
4343 boardWidget, args, 1);
4344 for (i = 0; i < DROP_MENU_SIZE; i++) {
4345 String item = dropMenuStrings[i];
4347 if (strcmp(item, "----") == 0) {
4348 entry = XtCreateManagedWidget(item, smeLineObjectClass,
4351 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
4352 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
4354 selection = dropMenuTranslation[i];
4355 XtAddCallback(entry, XtNcallback,
4356 (XtCallbackProc) DropMenuSelect,
4357 (caddr_t) selection);
4362 void SetupDropMenu()
4370 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
4371 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
4372 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
4373 dmEnables[i].piece);
4374 XtSetSensitive(entry, p != NULL || !appData.testLegality
4375 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
4376 && !appData.icsActive));
4378 while (p && *p++ == dmEnables[i].piece) count++;
4379 snprintf(label, sizeof(label), "%s %d", dmEnables[i].widget, count);
4381 XtSetArg(args[j], XtNlabel, label); j++;
4382 XtSetValues(entry, args, j);
4386 void PieceMenuPopup(w, event, params, num_params)
4390 Cardinal *num_params;
4393 if (event->type != ButtonPress) return;
4394 if (errorUp) ErrorPopDown();
4398 whichMenu = params[0];
4400 case IcsPlayingWhite:
4401 case IcsPlayingBlack:
4403 case MachinePlaysWhite:
4404 case MachinePlaysBlack:
4405 if (appData.testLegality &&
4406 gameInfo.variant != VariantBughouse &&
4407 gameInfo.variant != VariantCrazyhouse) return;
4409 whichMenu = "menuD";
4415 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
4416 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
4417 pmFromX = pmFromY = -1;
4421 pmFromX = BOARD_WIDTH - 1 - pmFromX;
4423 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
4425 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
4428 static void PieceMenuSelect(w, piece, junk)
4433 if (pmFromX < 0 || pmFromY < 0) return;
4434 EditPositionMenuEvent(piece, pmFromX, pmFromY);
4437 static void DropMenuSelect(w, piece, junk)
4442 if (pmFromX < 0 || pmFromY < 0) return;
4443 DropMenuEvent(piece, pmFromX, pmFromY);
4446 void WhiteClock(w, event, prms, nprms)
4452 if (gameMode == EditPosition || gameMode == IcsExamining) {
4453 SetWhiteToPlayEvent();
4454 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
4459 void BlackClock(w, event, prms, nprms)
4465 if (gameMode == EditPosition || gameMode == IcsExamining) {
4466 SetBlackToPlayEvent();
4467 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
4474 * If the user selects on a border boundary, return -1; if off the board,
4475 * return -2. Otherwise map the event coordinate to the square.
4477 int EventToSquare(x, limit)
4485 if ((x % (squareSize + lineGap)) >= squareSize)
4487 x /= (squareSize + lineGap);
4493 static void do_flash_delay(msec)
4499 static void drawHighlight(file, rank, gc)
4505 if (lineGap == 0 || appData.blindfold) return;
4508 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
4509 (squareSize + lineGap);
4510 y = lineGap/2 + rank * (squareSize + lineGap);
4512 x = lineGap/2 + file * (squareSize + lineGap);
4513 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
4514 (squareSize + lineGap);
4517 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
4518 squareSize+lineGap, squareSize+lineGap);
4521 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
4522 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
4525 SetHighlights(fromX, fromY, toX, toY)
4526 int fromX, fromY, toX, toY;
4528 if (hi1X != fromX || hi1Y != fromY) {
4529 if (hi1X >= 0 && hi1Y >= 0) {
4530 drawHighlight(hi1X, hi1Y, lineGC);
4532 if (fromX >= 0 && fromY >= 0) {
4533 drawHighlight(fromX, fromY, highlineGC);
4536 if (hi2X != toX || hi2Y != toY) {
4537 if (hi2X >= 0 && hi2Y >= 0) {
4538 drawHighlight(hi2X, hi2Y, lineGC);
4540 if (toX >= 0 && toY >= 0) {
4541 drawHighlight(toX, toY, highlineGC);
4553 SetHighlights(-1, -1, -1, -1);
4558 SetPremoveHighlights(fromX, fromY, toX, toY)
4559 int fromX, fromY, toX, toY;
4561 if (pm1X != fromX || pm1Y != fromY) {
4562 if (pm1X >= 0 && pm1Y >= 0) {
4563 drawHighlight(pm1X, pm1Y, lineGC);
4565 if (fromX >= 0 && fromY >= 0) {
4566 drawHighlight(fromX, fromY, prelineGC);
4569 if (pm2X != toX || pm2Y != toY) {
4570 if (pm2X >= 0 && pm2Y >= 0) {
4571 drawHighlight(pm2X, pm2Y, lineGC);
4573 if (toX >= 0 && toY >= 0) {
4574 drawHighlight(toX, toY, prelineGC);
4584 ClearPremoveHighlights()
4586 SetPremoveHighlights(-1, -1, -1, -1);
4589 static void BlankSquare(x, y, color, piece, dest)
4594 if (useImages && useImageSqs) {
4598 pm = xpmLightSquare;
4603 case 2: /* neutral */
4608 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
4609 squareSize, squareSize, x, y);
4619 case 2: /* neutral */
4624 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
4629 I split out the routines to draw a piece so that I could
4630 make a generic flash routine.
4632 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
4634 int square_color, x, y;
4637 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
4638 switch (square_color) {
4640 case 2: /* neutral */
4642 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4643 ? *pieceToOutline(piece)
4644 : *pieceToSolid(piece),
4645 dest, bwPieceGC, 0, 0,
4646 squareSize, squareSize, x, y);
4649 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
4650 ? *pieceToSolid(piece)
4651 : *pieceToOutline(piece),
4652 dest, wbPieceGC, 0, 0,
4653 squareSize, squareSize, x, y);
4658 static void monoDrawPiece(piece, square_color, x, y, dest)
4660 int square_color, x, y;
4663 switch (square_color) {
4665 case 2: /* neutral */
4667 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4668 ? *pieceToOutline(piece)
4669 : *pieceToSolid(piece),
4670 dest, bwPieceGC, 0, 0,
4671 squareSize, squareSize, x, y, 1);
4674 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4675 ? *pieceToSolid(piece)
4676 : *pieceToOutline(piece),
4677 dest, wbPieceGC, 0, 0,
4678 squareSize, squareSize, x, y, 1);
4683 static void colorDrawPiece(piece, square_color, x, y, dest)
4685 int square_color, x, y;
4688 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4689 switch (square_color) {
4691 XCopyPlane(xDisplay, *pieceToSolid(piece),
4692 dest, (int) piece < (int) BlackPawn
4693 ? wlPieceGC : blPieceGC, 0, 0,
4694 squareSize, squareSize, x, y, 1);
4697 XCopyPlane(xDisplay, *pieceToSolid(piece),
4698 dest, (int) piece < (int) BlackPawn
4699 ? wdPieceGC : bdPieceGC, 0, 0,
4700 squareSize, squareSize, x, y, 1);
4702 case 2: /* neutral */
4704 XCopyPlane(xDisplay, *pieceToSolid(piece),
4705 dest, (int) piece < (int) BlackPawn
4706 ? wjPieceGC : bjPieceGC, 0, 0,
4707 squareSize, squareSize, x, y, 1);
4712 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4714 int square_color, x, y;
4719 switch (square_color) {
4721 case 2: /* neutral */
4723 if ((int)piece < (int) BlackPawn) {
4731 if ((int)piece < (int) BlackPawn) {
4739 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4740 dest, wlPieceGC, 0, 0,
4741 squareSize, squareSize, x, y);
4744 typedef void (*DrawFunc)();
4746 DrawFunc ChooseDrawFunc()
4748 if (appData.monoMode) {
4749 if (DefaultDepth(xDisplay, xScreen) == 1) {
4750 return monoDrawPiece_1bit;
4752 return monoDrawPiece;
4756 return colorDrawPieceImage;
4758 return colorDrawPiece;
4762 /* [HR] determine square color depending on chess variant. */
4763 static int SquareColor(row, column)
4768 if (gameInfo.variant == VariantXiangqi) {
4769 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
4771 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
4773 } else if (row <= 4) {
4779 square_color = ((column + row) % 2) == 1;
4782 /* [hgm] holdings: next line makes all holdings squares light */
4783 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
4785 return square_color;
4788 void DrawSquare(row, column, piece, do_flash)
4789 int row, column, do_flash;
4792 int square_color, x, y, direction, font_ascent, font_descent;
4795 XCharStruct overall;
4799 /* Calculate delay in milliseconds (2-delays per complete flash) */
4800 flash_delay = 500 / appData.flashRate;
4803 x = lineGap + ((BOARD_WIDTH-1)-column) *
4804 (squareSize + lineGap);
4805 y = lineGap + row * (squareSize + lineGap);
4807 x = lineGap + column * (squareSize + lineGap);
4808 y = lineGap + ((BOARD_HEIGHT-1)-row) *
4809 (squareSize + lineGap);
4812 square_color = SquareColor(row, column);
4814 if ( // [HGM] holdings: blank out area between board and holdings
4815 column == BOARD_LEFT-1 || column == BOARD_RGHT
4816 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
4817 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
4818 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4820 // [HGM] print piece counts next to holdings
4821 string[1] = NULLCHAR;
4822 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
4823 string[0] = '0' + piece;
4824 XTextExtents(countFontStruct, string, 1, &direction,
4825 &font_ascent, &font_descent, &overall);
4826 if (appData.monoMode) {
4827 XDrawImageString(xDisplay, xBoardWindow, countGC,
4828 x + squareSize - overall.width - 2,
4829 y + font_ascent + 1, string, 1);
4831 XDrawString(xDisplay, xBoardWindow, countGC,
4832 x + squareSize - overall.width - 2,
4833 y + font_ascent + 1, string, 1);
4836 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
4837 string[0] = '0' + piece;
4838 XTextExtents(countFontStruct, string, 1, &direction,
4839 &font_ascent, &font_descent, &overall);
4840 if (appData.monoMode) {
4841 XDrawImageString(xDisplay, xBoardWindow, countGC,
4842 x + 2, y + font_ascent + 1, string, 1);
4844 XDrawString(xDisplay, xBoardWindow, countGC,
4845 x + 2, y + font_ascent + 1, string, 1);
4849 if (piece == EmptySquare || appData.blindfold) {
4850 BlankSquare(x, y, square_color, piece, xBoardWindow);
4852 drawfunc = ChooseDrawFunc();
4853 if (do_flash && appData.flashCount > 0) {
4854 for (i=0; i<appData.flashCount; ++i) {
4856 drawfunc(piece, square_color, x, y, xBoardWindow);
4857 XSync(xDisplay, False);
4858 do_flash_delay(flash_delay);
4860 BlankSquare(x, y, square_color, piece, xBoardWindow);
4861 XSync(xDisplay, False);
4862 do_flash_delay(flash_delay);
4865 drawfunc(piece, square_color, x, y, xBoardWindow);
4869 string[1] = NULLCHAR;
4870 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4871 && column >= BOARD_LEFT && column < BOARD_RGHT) {
4872 string[0] = 'a' + column - BOARD_LEFT;
4873 XTextExtents(coordFontStruct, string, 1, &direction,
4874 &font_ascent, &font_descent, &overall);
4875 if (appData.monoMode) {
4876 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4877 x + squareSize - overall.width - 2,
4878 y + squareSize - font_descent - 1, string, 1);
4880 XDrawString(xDisplay, xBoardWindow, coordGC,
4881 x + squareSize - overall.width - 2,
4882 y + squareSize - font_descent - 1, string, 1);
4885 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
4886 string[0] = ONE + row;
4887 XTextExtents(coordFontStruct, string, 1, &direction,
4888 &font_ascent, &font_descent, &overall);
4889 if (appData.monoMode) {
4890 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4891 x + 2, y + font_ascent + 1, string, 1);
4893 XDrawString(xDisplay, xBoardWindow, coordGC,
4894 x + 2, y + font_ascent + 1, string, 1);
4900 /* Why is this needed on some versions of X? */
4901 void EventProc(widget, unused, event)
4906 if (!XtIsRealized(widget))
4909 switch (event->type) {
4911 if (event->xexpose.count > 0) return; /* no clipping is done */
4912 XDrawPosition(widget, True, NULL);
4920 void DrawPosition(fullRedraw, board)
4921 /*Boolean*/int fullRedraw;
4924 XDrawPosition(boardWidget, fullRedraw, board);
4927 /* Returns 1 if there are "too many" differences between b1 and b2
4928 (i.e. more than 1 move was made) */
4929 static int too_many_diffs(b1, b2)
4935 for (i=0; i<BOARD_HEIGHT; ++i) {
4936 for (j=0; j<BOARD_WIDTH; ++j) {
4937 if (b1[i][j] != b2[i][j]) {
4938 if (++c > 4) /* Castling causes 4 diffs */
4947 /* Matrix describing castling maneuvers */
4948 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4949 static int castling_matrix[4][5] = {
4950 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4951 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4952 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4953 { 7, 7, 4, 5, 6 } /* 0-0, black */
4956 /* Checks whether castling occurred. If it did, *rrow and *rcol
4957 are set to the destination (row,col) of the rook that moved.
4959 Returns 1 if castling occurred, 0 if not.
4961 Note: Only handles a max of 1 castling move, so be sure
4962 to call too_many_diffs() first.
4964 static int check_castle_draw(newb, oldb, rrow, rcol)
4971 /* For each type of castling... */
4972 for (i=0; i<4; ++i) {
4973 r = castling_matrix[i];
4975 /* Check the 4 squares involved in the castling move */
4977 for (j=1; j<=4; ++j) {
4978 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4985 /* All 4 changed, so it must be a castling move */
4994 static int damage[BOARD_SIZE][BOARD_SIZE];
4997 * event handler for redrawing the board
4999 void XDrawPosition(w, repaint, board)
5001 /*Boolean*/int repaint;
5005 static int lastFlipView = 0;
5006 static int lastBoardValid = 0;
5007 static Board lastBoard;
5011 if (board == NULL) {
5012 if (!lastBoardValid) return;
5015 if (!lastBoardValid || lastFlipView != flipView) {
5016 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
5017 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
5022 * It would be simpler to clear the window with XClearWindow()
5023 * but this causes a very distracting flicker.
5026 if (!repaint && lastBoardValid && lastFlipView == flipView) {
5028 /* If too much changes (begin observing new game, etc.), don't
5030 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
5032 /* Special check for castling so we don't flash both the king
5033 and the rook (just flash the king). */
5035 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
5036 /* Draw rook with NO flashing. King will be drawn flashing later */
5037 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
5038 lastBoard[rrow][rcol] = board[rrow][rcol];
5042 /* First pass -- Draw (newly) empty squares and repair damage.
5043 This prevents you from having a piece show up twice while it
5044 is flashing on its new square */
5045 for (i = 0; i < BOARD_HEIGHT; i++)
5046 for (j = 0; j < BOARD_WIDTH; j++)
5047 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
5049 DrawSquare(i, j, board[i][j], 0);
5050 damage[i][j] = False;
5053 /* Second pass -- Draw piece(s) in new position and flash them */
5054 for (i = 0; i < BOARD_HEIGHT; i++)
5055 for (j = 0; j < BOARD_WIDTH; j++)
5056 if (board[i][j] != lastBoard[i][j]) {
5057 DrawSquare(i, j, board[i][j], do_flash);
5061 XDrawSegments(xDisplay, xBoardWindow, lineGC,
5062 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
5064 for (i = 0; i < BOARD_HEIGHT; i++)
5065 for (j = 0; j < BOARD_WIDTH; j++) {
5066 DrawSquare(i, j, board[i][j], 0);
5067 damage[i][j] = False;
5071 CopyBoard(lastBoard, board);
5073 lastFlipView = flipView;
5075 /* Draw highlights */
5076 if (pm1X >= 0 && pm1Y >= 0) {
5077 drawHighlight(pm1X, pm1Y, prelineGC);
5079 if (pm2X >= 0 && pm2Y >= 0) {
5080 drawHighlight(pm2X, pm2Y, prelineGC);
5082 if (hi1X >= 0 && hi1Y >= 0) {
5083 drawHighlight(hi1X, hi1Y, highlineGC);
5085 if (hi2X >= 0 && hi2Y >= 0) {
5086 drawHighlight(hi2X, hi2Y, highlineGC);
5089 /* If piece being dragged around board, must redraw that too */
5092 XSync(xDisplay, False);
5097 * event handler for redrawing the board
5099 void DrawPositionProc(w, event, prms, nprms)
5105 XDrawPosition(w, True, NULL);
5110 * event handler for parsing user moves
5112 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
5113 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
5114 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
5115 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
5116 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
5117 // and at the end FinishMove() to perform the move after optional promotion popups.
5118 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
5119 void HandleUserMove(w, event, prms, nprms)
5126 Boolean saveAnimate;
5127 static int second = 0, promotionChoice = 0;
5130 if (w != boardWidget || errorExitStatus != -1) return;
5132 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
5133 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
5134 if (!flipView && y >= 0) {
5135 y = BOARD_HEIGHT - 1 - y;
5137 if (flipView && x >= 0) {
5138 x = BOARD_WIDTH - 1 - x;
5141 if(promotionChoice) { // we are waiting for a click to indicate promotion piece
5142 if(event->type == ButtonRelease) return; // ignore upclick of click-click destination
5143 promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel
5144 if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);
5145 if(gameInfo.holdingsWidth &&
5146 (WhiteOnMove(currentMove)
5147 ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0
5148 : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {
5149 // click in right holdings, for determining promotion piece
5150 ChessSquare p = boards[currentMove][y][x];
5151 if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);
5152 if(p != EmptySquare) {
5153 FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));
5158 DrawPosition(FALSE, boards[currentMove]);
5161 if (event->type == ButtonPress) ErrorPopDown();
5164 if (event->type == ButtonPress) {
5165 XtPopdown(promotionShell);
5166 XtDestroyWidget(promotionShell);
5167 promotionUp = False;
5175 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
5176 if(event->type == ButtonPress
5177 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
5178 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
5179 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
5183 if (event->type == ButtonPress) {
5184 /* First square, prepare to drag */
5185 if (OKToStartUserMove(x, y)) {
5189 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5190 if (appData.highlightDragging) {
5191 SetHighlights(x, y, -1, -1);
5199 if (event->type == ButtonRelease && x == fromX && y == fromY) {
5200 /* Click on single square in stead of drag-drop */
5201 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5202 if (appData.animateDragging) {
5203 /* Undo animation damage if any */
5204 DrawPosition(FALSE, NULL);
5207 /* Second up/down in same square; just abort move */
5212 ClearPremoveHighlights();
5214 /* First upclick in same square; start click-click mode */
5215 SetHighlights(x, y, -1, -1);
5220 moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease);
5222 if (moveType == Comment) { // kludge for indicating capture-own on Press
5223 /* Clicked again on same color piece -- changed his mind */
5224 /* note that re-clicking same square always hits same color piece */
5225 second = (x == fromX && y == fromY);
5226 if (appData.highlightDragging) {
5227 SetHighlights(x, y, -1, -1);
5231 if (OKToStartUserMove(x, y)) {
5234 DragPieceBegin(event->xbutton.x, event->xbutton.y);
5239 if(moveType == AmbiguousMove) { // kludge to indicate edit-position move
5242 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5243 DrawPosition(FALSE, boards[currentMove]);
5247 /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */
5250 saveAnimate = appData.animate;
5251 if (event->type == ButtonPress) {
5252 /* Finish clickclick move */
5253 if (appData.animate || appData.highlightLastMove) {
5254 SetHighlights(fromX, fromY, toX, toY);
5259 /* Finish drag move */
5260 if (appData.highlightLastMove) {
5261 SetHighlights(fromX, fromY, toX, toY);
5265 DragPieceEnd(event->xbutton.x, event->xbutton.y);
5266 /* Don't animate move and drag both */
5267 appData.animate = FALSE;
5269 if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||
5270 (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&
5271 appData.alwaysPromoteToQueen) { // promotion, but no choice
5272 FinishMove(moveType, fromX, fromY, toX, toY, 'q');
5274 if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {
5275 SetHighlights(fromX, fromY, toX, toY);
5276 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
5277 // [HGM] super: promotion to captured piece selected from holdings
5278 ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
5279 promotionChoice = TRUE;
5280 // kludge follows to temporarily execute move on display, without promoting yet
5281 boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank
5282 boards[currentMove][toY][toX] = p;
5283 DrawPosition(FALSE, boards[currentMove]);
5284 boards[currentMove][fromY][fromX] = p; // take back, but display stays
5285 boards[currentMove][toY][toX] = q;
5286 DisplayMessage("Click in holdings to choose piece", "");
5290 goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback
5292 if(moveType != ImpossibleMove) { // valid move, but no promotion
5293 FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);
5294 } else { // invalid move; could have set premove
5297 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5298 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5301 appData.animate = saveAnimate;
5302 if (appData.animate || appData.animateDragging) {
5303 /* Undo animation damage if needed */
5304 DrawPosition(FALSE, NULL);
5308 void AnimateUserMove (Widget w, XEvent * event,
5309 String * params, Cardinal * nParams)
5311 DragPieceMove(event->xmotion.x, event->xmotion.y);
5314 Widget CommentCreate(name, text, mutable, callback, lines)
5316 int /*Boolean*/ mutable;
5317 XtCallbackProc callback;
5321 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
5326 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5327 XtGetValues(boardWidget, args, j);
5330 XtSetArg(args[j], XtNresizable, True); j++;
5333 XtCreatePopupShell(name, topLevelShellWidgetClass,
5334 shellWidget, args, j);
5337 XtCreatePopupShell(name, transientShellWidgetClass,
5338 shellWidget, args, j);
5341 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5342 layoutArgs, XtNumber(layoutArgs));
5344 XtCreateManagedWidget("form", formWidgetClass, layout,
5345 formArgs, XtNumber(formArgs));
5349 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5350 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5352 XtSetArg(args[j], XtNstring, text); j++;
5353 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5354 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5355 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5356 XtSetArg(args[j], XtNright, XtChainRight); j++;
5357 XtSetArg(args[j], XtNresizable, True); j++;
5358 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
5359 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5360 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5361 XtSetArg(args[j], XtNautoFill, True); j++;
5362 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5364 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5368 XtSetArg(args[j], XtNfromVert, edit); j++;
5369 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5370 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5371 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5372 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5374 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
5375 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
5378 XtSetArg(args[j], XtNfromVert, edit); j++;
5379 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
5380 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5381 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5382 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5383 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5385 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
5386 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
5389 XtSetArg(args[j], XtNfromVert, edit); j++;
5390 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
5391 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5392 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5393 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5394 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5396 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
5397 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
5400 XtSetArg(args[j], XtNfromVert, edit); j++;
5401 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5402 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5403 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5404 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5406 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
5407 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
5410 XtSetArg(args[j], XtNfromVert, edit); j++;
5411 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
5412 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
5413 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5414 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5415 XtSetArg(args[j], XtNright, XtChainLeft); j++;
5417 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
5418 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
5421 XtRealizeWidget(shell);
5423 if (commentX == -1) {
5426 Dimension pw_height;
5427 Dimension ew_height;
5430 XtSetArg(args[j], XtNheight, &ew_height); j++;
5431 XtGetValues(edit, args, j);
5434 XtSetArg(args[j], XtNheight, &pw_height); j++;
5435 XtGetValues(shell, args, j);
5436 commentH = pw_height + (lines - 1) * ew_height;
5437 commentW = bw_width - 16;
5439 XSync(xDisplay, False);
5441 /* This code seems to tickle an X bug if it is executed too soon
5442 after xboard starts up. The coordinates get transformed as if
5443 the main window was positioned at (0, 0).
5445 XtTranslateCoords(shellWidget,
5446 (bw_width - commentW) / 2, 0 - commentH / 2,
5447 &commentX, &commentY);
5449 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5450 RootWindowOfScreen(XtScreen(shellWidget)),
5451 (bw_width - commentW) / 2, 0 - commentH / 2,
5456 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
5459 XtSetArg(args[j], XtNheight, commentH); j++;
5460 XtSetArg(args[j], XtNwidth, commentW); j++;
5461 XtSetArg(args[j], XtNx, commentX); j++;
5462 XtSetArg(args[j], XtNy, commentY); j++;
5463 XtSetValues(shell, args, j);
5464 XtSetKeyboardFocus(shell, edit);
5469 /* Used for analysis window and ICS input window */
5470 Widget MiscCreate(name, text, mutable, callback, lines)
5472 int /*Boolean*/ mutable;
5473 XtCallbackProc callback;
5477 Widget shell, layout, form, edit;
5479 Dimension bw_width, pw_height, ew_height, w, h;
5485 XtSetArg(args[j], XtNresizable, True); j++;
5488 XtCreatePopupShell(name, topLevelShellWidgetClass,
5489 shellWidget, args, j);
5492 XtCreatePopupShell(name, transientShellWidgetClass,
5493 shellWidget, args, j);
5496 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
5497 layoutArgs, XtNumber(layoutArgs));
5499 XtCreateManagedWidget("form", formWidgetClass, layout,
5500 formArgs, XtNumber(formArgs));
5504 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
5505 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
5507 XtSetArg(args[j], XtNstring, text); j++;
5508 XtSetArg(args[j], XtNtop, XtChainTop); j++;
5509 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
5510 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
5511 XtSetArg(args[j], XtNright, XtChainRight); j++;
5512 XtSetArg(args[j], XtNresizable, True); j++;
5513 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
5514 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
5515 XtSetArg(args[j], XtNautoFill, True); j++;
5516 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
5518 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
5520 XtRealizeWidget(shell);
5523 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5524 XtGetValues(boardWidget, args, j);
5527 XtSetArg(args[j], XtNheight, &ew_height); j++;
5528 XtGetValues(edit, args, j);
5531 XtSetArg(args[j], XtNheight, &pw_height); j++;
5532 XtGetValues(shell, args, j);
5533 h = pw_height + (lines - 1) * ew_height;
5536 XSync(xDisplay, False);
5538 /* This code seems to tickle an X bug if it is executed too soon
5539 after xboard starts up. The coordinates get transformed as if
5540 the main window was positioned at (0, 0).
5542 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
5544 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
5545 RootWindowOfScreen(XtScreen(shellWidget)),
5546 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
5550 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5553 XtSetArg(args[j], XtNheight, h); j++;
5554 XtSetArg(args[j], XtNwidth, w); j++;
5555 XtSetArg(args[j], XtNx, x); j++;
5556 XtSetArg(args[j], XtNy, y); j++;
5557 XtSetValues(shell, args, j);
5563 static int savedIndex; /* gross that this is global */
5565 void EditCommentPopUp(index, title, text)
5574 if (text == NULL) text = "";
5576 if (editShell == NULL) {
5578 CommentCreate(title, text, True, EditCommentCallback, 4);
5579 XtRealizeWidget(editShell);
5580 CatchDeleteWindow(editShell, "EditCommentPopDown");
5582 edit = XtNameToWidget(editShell, "*form.text");
5584 XtSetArg(args[j], XtNstring, text); j++;
5585 XtSetValues(edit, args, j);
5587 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5588 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5589 XtSetValues(editShell, args, j);
5592 XtPopup(editShell, XtGrabNone);
5596 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5597 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5601 void EditCommentCallback(w, client_data, call_data)
5603 XtPointer client_data, call_data;
5611 XtSetArg(args[j], XtNlabel, &name); j++;
5612 XtGetValues(w, args, j);
5614 if (strcmp(name, _("ok")) == 0) {
5615 edit = XtNameToWidget(editShell, "*form.text");
5617 XtSetArg(args[j], XtNstring, &val); j++;
5618 XtGetValues(edit, args, j);
5619 ReplaceComment(savedIndex, val);
5620 EditCommentPopDown();
5621 } else if (strcmp(name, _("cancel")) == 0) {
5622 EditCommentPopDown();
5623 } else if (strcmp(name, _("clear")) == 0) {
5624 edit = XtNameToWidget(editShell, "*form.text");
5625 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5626 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5630 void EditCommentPopDown()
5635 if (!editUp) return;
5637 XtSetArg(args[j], XtNx, &commentX); j++;
5638 XtSetArg(args[j], XtNy, &commentY); j++;
5639 XtSetArg(args[j], XtNheight, &commentH); j++;
5640 XtSetArg(args[j], XtNwidth, &commentW); j++;
5641 XtGetValues(editShell, args, j);
5642 XtPopdown(editShell);
5645 XtSetArg(args[j], XtNleftBitmap, None); j++;
5646 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
5650 void ICSInputBoxPopUp()
5655 char *title = _("ICS Input");
5658 if (ICSInputShell == NULL) {
5659 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
5660 tr = XtParseTranslationTable(ICSInputTranslations);
5661 edit = XtNameToWidget(ICSInputShell, "*form.text");
5662 XtOverrideTranslations(edit, tr);
5663 XtRealizeWidget(ICSInputShell);
5664 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
5667 edit = XtNameToWidget(ICSInputShell, "*form.text");
5669 XtSetArg(args[j], XtNstring, ""); j++;
5670 XtSetValues(edit, args, j);
5672 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5673 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5674 XtSetValues(ICSInputShell, args, j);
5677 XtPopup(ICSInputShell, XtGrabNone);
5678 XtSetKeyboardFocus(ICSInputShell, edit);
5680 ICSInputBoxUp = True;
5682 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
5683 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5687 void ICSInputSendText()
5694 edit = XtNameToWidget(ICSInputShell, "*form.text");
5696 XtSetArg(args[j], XtNstring, &val); j++;
5697 XtGetValues(edit, args, j);
5698 SendMultiLineToICS(val);
5699 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
5700 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
5703 void ICSInputBoxPopDown()
5708 if (!ICSInputBoxUp) return;
5710 XtPopdown(ICSInputShell);
5711 ICSInputBoxUp = False;
5713 XtSetArg(args[j], XtNleftBitmap, None); j++;
5714 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
5718 void CommentPopUp(title, text)
5725 if (commentShell == NULL) {
5727 CommentCreate(title, text, False, CommentCallback, 4);
5728 XtRealizeWidget(commentShell);
5729 CatchDeleteWindow(commentShell, "CommentPopDown");
5731 edit = XtNameToWidget(commentShell, "*form.text");
5733 XtSetArg(args[j], XtNstring, text); j++;
5734 XtSetValues(edit, args, j);
5736 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5737 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5738 XtSetValues(commentShell, args, j);
5741 XtPopup(commentShell, XtGrabNone);
5742 XSync(xDisplay, False);
5747 void AnalysisPopUp(title, text)
5754 if (analysisShell == NULL) {
5755 analysisShell = MiscCreate(title, text, False, NULL, 4);
5756 XtRealizeWidget(analysisShell);
5757 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
5760 edit = XtNameToWidget(analysisShell, "*form.text");
5762 XtSetArg(args[j], XtNstring, text); j++;
5763 XtSetValues(edit, args, j);
5765 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
5766 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
5767 XtSetValues(analysisShell, args, j);
5771 XtPopup(analysisShell, XtGrabNone);
5773 XSync(xDisplay, False);
5778 void CommentCallback(w, client_data, call_data)
5780 XtPointer client_data, call_data;
5787 XtSetArg(args[j], XtNlabel, &name); j++;
5788 XtGetValues(w, args, j);
5790 if (strcmp(name, _("close")) == 0) {
5792 } else if (strcmp(name, _("edit")) == 0) {
5799 void CommentPopDown()
5804 if (!commentUp) return;
5806 XtSetArg(args[j], XtNx, &commentX); j++;
5807 XtSetArg(args[j], XtNy, &commentY); j++;
5808 XtSetArg(args[j], XtNwidth, &commentW); j++;
5809 XtSetArg(args[j], XtNheight, &commentH); j++;
5810 XtGetValues(commentShell, args, j);
5811 XtPopdown(commentShell);
5812 XSync(xDisplay, False);
5816 void AnalysisPopDown()
5818 if (!analysisUp) return;
5819 XtPopdown(analysisShell);
5820 XSync(xDisplay, False);
5822 if (appData.icsEngineAnalyze) ExitAnalyzeMode(); /* [DM] icsEngineAnalyze */
5826 void FileNamePopUp(label, def, proc, openMode)
5833 Widget popup, layout, dialog, edit;
5839 fileProc = proc; /* I can't see a way not */
5840 fileOpenMode = openMode; /* to use globals here */
5843 XtSetArg(args[i], XtNresizable, True); i++;
5844 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5845 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5846 fileNameShell = popup =
5847 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5848 shellWidget, args, i);
5851 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5852 layoutArgs, XtNumber(layoutArgs));
5855 XtSetArg(args[i], XtNlabel, label); i++;
5856 XtSetArg(args[i], XtNvalue, def); i++;
5857 XtSetArg(args[i], XtNborderWidth, 0); i++;
5858 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5861 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5862 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5863 (XtPointer) dialog);
5865 XtRealizeWidget(popup);
5866 CatchDeleteWindow(popup, "FileNamePopDown");
5868 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5869 &x, &y, &win_x, &win_y, &mask);
5871 XtSetArg(args[0], XtNx, x - 10);
5872 XtSetArg(args[1], XtNy, y - 30);
5873 XtSetValues(popup, args, 2);
5875 XtPopup(popup, XtGrabExclusive);
5878 edit = XtNameToWidget(dialog, "*value");
5879 XtSetKeyboardFocus(popup, edit);
5882 void FileNamePopDown()
5884 if (!filenameUp) return;
5885 XtPopdown(fileNameShell);
5886 XtDestroyWidget(fileNameShell);
5891 void FileNameCallback(w, client_data, call_data)
5893 XtPointer client_data, call_data;
5898 XtSetArg(args[0], XtNlabel, &name);
5899 XtGetValues(w, args, 1);
5901 if (strcmp(name, _("cancel")) == 0) {
5906 FileNameAction(w, NULL, NULL, NULL);
5909 void FileNameAction(w, event, prms, nprms)
5921 name = XawDialogGetValueString(w = XtParent(w));
5923 if ((name != NULL) && (*name != NULLCHAR)) {
5925 XtPopdown(w = XtParent(XtParent(w)));
5929 p = strrchr(buf, ' ');
5936 fullname = ExpandPathName(buf);
5938 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5941 f = fopen(fullname, fileOpenMode);
5943 DisplayError(_("Failed to open file"), errno);
5945 (void) (*fileProc)(f, index, buf);
5952 XtPopdown(w = XtParent(XtParent(w)));
5958 void PromotionPopUp()
5961 Widget dialog, layout;
5963 Dimension bw_width, pw_width;
5967 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5968 XtGetValues(boardWidget, args, j);
5971 XtSetArg(args[j], XtNresizable, True); j++;
5972 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5974 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5975 shellWidget, args, j);
5977 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5978 layoutArgs, XtNumber(layoutArgs));
5981 XtSetArg(args[j], XtNlabel, _("Promote to what?")); j++;
5982 XtSetArg(args[j], XtNborderWidth, 0); j++;
5983 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5986 if(gameInfo.variant != VariantShogi) {
5987 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5988 (XtPointer) dialog);
5989 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5990 (XtPointer) dialog);
5991 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5992 (XtPointer) dialog);
5993 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5994 (XtPointer) dialog);
5995 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5996 gameInfo.variant == VariantGiveaway) {
5997 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5998 (XtPointer) dialog);
6000 if(gameInfo.variant == VariantCapablanca ||
6001 gameInfo.variant == VariantGothic ||
6002 gameInfo.variant == VariantCapaRandom) {
6003 XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
6004 (XtPointer) dialog);
6005 XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
6006 (XtPointer) dialog);
6008 } else // [HGM] shogi
6010 XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
6011 (XtPointer) dialog);
6012 XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
6013 (XtPointer) dialog);
6015 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
6016 (XtPointer) dialog);
6018 XtRealizeWidget(promotionShell);
6019 CatchDeleteWindow(promotionShell, "PromotionPopDown");
6022 XtSetArg(args[j], XtNwidth, &pw_width); j++;
6023 XtGetValues(promotionShell, args, j);
6025 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6026 lineGap + squareSize/3 +
6027 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
6028 0 : 6*(squareSize + lineGap)), &x, &y);
6031 XtSetArg(args[j], XtNx, x); j++;
6032 XtSetArg(args[j], XtNy, y); j++;
6033 XtSetValues(promotionShell, args, j);
6035 XtPopup(promotionShell, XtGrabNone);
6040 void PromotionPopDown()
6042 if (!promotionUp) return;
6043 XtPopdown(promotionShell);
6044 XtDestroyWidget(promotionShell);
6045 promotionUp = False;
6048 void PromotionCallback(w, client_data, call_data)
6050 XtPointer client_data, call_data;
6056 XtSetArg(args[0], XtNlabel, &name);
6057 XtGetValues(w, args, 1);
6061 if (fromX == -1) return;
6063 if (strcmp(name, _("cancel")) == 0) {
6067 } else if (strcmp(name, _("Knight")) == 0) {
6069 } else if (strcmp(name, _("Promote")) == 0) {
6071 } else if (strcmp(name, _("Defer")) == 0) {
6074 promoChar = ToLower(name[0]);
6077 FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
6079 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
6080 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
6085 void ErrorCallback(w, client_data, call_data)
6087 XtPointer client_data, call_data;
6090 XtPopdown(w = XtParent(XtParent(XtParent(w))));
6092 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6098 if (!errorUp) return;
6100 XtPopdown(errorShell);
6101 XtDestroyWidget(errorShell);
6102 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
6105 void ErrorPopUp(title, label, modal)
6106 char *title, *label;
6110 Widget dialog, layout;
6114 Dimension bw_width, pw_width;
6115 Dimension pw_height;
6119 XtSetArg(args[i], XtNresizable, True); i++;
6120 XtSetArg(args[i], XtNtitle, title); i++;
6122 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
6123 shellWidget, args, i);
6125 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
6126 layoutArgs, XtNumber(layoutArgs));
6129 XtSetArg(args[i], XtNlabel, label); i++;
6130 XtSetArg(args[i], XtNborderWidth, 0); i++;
6131 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
6134 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
6136 XtRealizeWidget(errorShell);
6137 CatchDeleteWindow(errorShell, "ErrorPopDown");
6140 XtSetArg(args[i], XtNwidth, &bw_width); i++;
6141 XtGetValues(boardWidget, args, i);
6143 XtSetArg(args[i], XtNwidth, &pw_width); i++;
6144 XtSetArg(args[i], XtNheight, &pw_height); i++;
6145 XtGetValues(errorShell, args, i);
6148 /* This code seems to tickle an X bug if it is executed too soon
6149 after xboard starts up. The coordinates get transformed as if
6150 the main window was positioned at (0, 0).
6152 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
6153 0 - pw_height + squareSize / 3, &x, &y);
6155 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
6156 RootWindowOfScreen(XtScreen(boardWidget)),
6157 (bw_width - pw_width) / 2,
6158 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
6162 if (y < 0) y = 0; /*avoid positioning top offscreen*/
6165 XtSetArg(args[i], XtNx, x); i++;
6166 XtSetArg(args[i], XtNy, y); i++;
6167 XtSetValues(errorShell, args, i);
6170 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
6173 /* Disable all user input other than deleting the window */
6174 static int frozen = 0;
6178 /* Grab by a widget that doesn't accept input */
6179 XtAddGrab(messageWidget, TRUE, FALSE);
6183 /* Undo a FreezeUI */
6186 if (!frozen) return;
6187 XtRemoveGrab(messageWidget);
6191 char *ModeToWidgetName(mode)
6195 case BeginningOfGame:
6196 if (appData.icsActive)
6197 return "menuMode.ICS Client";
6198 else if (appData.noChessProgram ||
6199 *appData.cmailGameName != NULLCHAR)
6200 return "menuMode.Edit Game";
6202 return "menuMode.Machine Black";
6203 case MachinePlaysBlack:
6204 return "menuMode.Machine Black";
6205 case MachinePlaysWhite:
6206 return "menuMode.Machine White";
6208 return "menuMode.Analysis Mode";
6210 return "menuMode.Analyze File";
6211 case TwoMachinesPlay:
6212 return "menuMode.Two Machines";
6214 return "menuMode.Edit Game";
6215 case PlayFromGameFile:
6216 return "menuFile.Load Game";
6218 return "menuMode.Edit Position";
6220 return "menuMode.Training";
6221 case IcsPlayingWhite:
6222 case IcsPlayingBlack:
6226 return "menuMode.ICS Client";
6233 void ModeHighlight()
6236 static int oldPausing = FALSE;
6237 static GameMode oldmode = (GameMode) -1;
6240 if (!boardWidget || !XtIsRealized(boardWidget)) return;
6242 if (pausing != oldPausing) {
6243 oldPausing = pausing;
6245 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6247 XtSetArg(args[0], XtNleftBitmap, None);
6249 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
6252 if (appData.showButtonBar) {
6253 /* Always toggle, don't set. Previous code messes up when
6254 invoked while the button is pressed, as releasing it
6255 toggles the state again. */
6258 XtSetArg(args[0], XtNbackground, &oldbg);
6259 XtSetArg(args[1], XtNforeground, &oldfg);
6260 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
6262 XtSetArg(args[0], XtNbackground, oldfg);
6263 XtSetArg(args[1], XtNforeground, oldbg);
6265 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
6269 wname = ModeToWidgetName(oldmode);
6270 if (wname != NULL) {
6271 XtSetArg(args[0], XtNleftBitmap, None);
6272 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6274 wname = ModeToWidgetName(gameMode);
6275 if (wname != NULL) {
6276 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6277 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
6281 /* Maybe all the enables should be handled here, not just this one */
6282 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
6283 gameMode == Training || gameMode == PlayFromGameFile);
6288 * Button/menu procedures
6290 void ResetProc(w, event, prms, nprms)
6300 int LoadGamePopUp(f, gameNumber, title)
6305 cmailMsgLoaded = FALSE;
6306 if (gameNumber == 0) {
6307 int error = GameListBuild(f);
6309 DisplayError(_("Cannot build game list"), error);
6310 } else if (!ListEmpty(&gameList) &&
6311 ((ListGame *) gameList.tailPred)->number > 1) {
6312 GameListPopUp(f, title);
6318 return LoadGame(f, gameNumber, title, FALSE);
6321 void LoadGameProc(w, event, prms, nprms)
6327 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6330 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
6333 void LoadNextGameProc(w, event, prms, nprms)
6342 void LoadPrevGameProc(w, event, prms, nprms)
6351 void ReloadGameProc(w, event, prms, nprms)
6360 void LoadNextPositionProc(w, event, prms, nprms)
6369 void LoadPrevPositionProc(w, event, prms, nprms)
6378 void ReloadPositionProc(w, event, prms, nprms)
6387 void LoadPositionProc(w, event, prms, nprms)
6393 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
6396 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
6399 void SaveGameProc(w, event, prms, nprms)
6405 FileNamePopUp(_("Save game file name?"),
6406 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
6410 void SavePositionProc(w, event, prms, nprms)
6416 FileNamePopUp(_("Save position file name?"),
6417 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
6421 void ReloadCmailMsgProc(w, event, prms, nprms)
6427 ReloadCmailMsgEvent(FALSE);
6430 void MailMoveProc(w, event, prms, nprms)
6439 /* this variable is shared between CopyPositionProc and SendPositionSelection */
6440 static char *selected_fen_position=NULL;
6443 SendPositionSelection(Widget w, Atom *selection, Atom *target,
6444 Atom *type_return, XtPointer *value_return,
6445 unsigned long *length_return, int *format_return)
6447 char *selection_tmp;
6449 if (!selected_fen_position) return False; /* should never happen */
6450 if (*target == XA_STRING){
6451 /* note: since no XtSelectionDoneProc was registered, Xt will
6452 * automatically call XtFree on the value returned. So have to
6453 * make a copy of it allocated with XtMalloc */
6454 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
6455 strcpy(selection_tmp, selected_fen_position);
6457 *value_return=selection_tmp;
6458 *length_return=strlen(selection_tmp);
6459 *type_return=XA_STRING;
6460 *format_return = 8; /* bits per byte */
6467 /* note: when called from menu all parameters are NULL, so no clue what the
6468 * Widget which was clicked on was, or what the click event was
6470 void CopyPositionProc(w, event, prms, nprms)
6478 if (selected_fen_position) free(selected_fen_position);
6479 selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
6480 if (!selected_fen_position) return;
6481 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6483 SendPositionSelection,
6484 NULL/* lose_ownership_proc */ ,
6485 NULL/* transfer_done_proc */);
6487 free(selected_fen_position);
6488 selected_fen_position=NULL;
6492 /* function called when the data to Paste is ready */
6494 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
6495 Atom *type, XtPointer value, unsigned long *len, int *format)
6498 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
6499 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
6500 EditPositionPasteFEN(fenstr);
6504 /* called when Paste Position button is pressed,
6505 * all parameters will be NULL */
6506 void PastePositionProc(w, event, prms, nprms)
6512 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6513 /* (XtSelectionCallbackProc) */ PastePositionCB,
6514 NULL, /* client_data passed to PastePositionCB */
6516 /* better to use the time field from the event that triggered the
6517 * call to this function, but that isn't trivial to get
6525 SendGameSelection(Widget w, Atom *selection, Atom *target,
6526 Atom *type_return, XtPointer *value_return,
6527 unsigned long *length_return, int *format_return)
6529 char *selection_tmp;
6531 if (*target == XA_STRING){
6532 FILE* f = fopen(gameCopyFilename, "r");
6535 if (f == NULL) return False;
6539 selection_tmp = XtMalloc(len + 1);
6540 count = fread(selection_tmp, 1, len, f);
6542 XtFree(selection_tmp);
6545 selection_tmp[len] = NULLCHAR;
6546 *value_return = selection_tmp;
6547 *length_return = len;
6548 *type_return = XA_STRING;
6549 *format_return = 8; /* bits per byte */
6556 /* note: when called from menu all parameters are NULL, so no clue what the
6557 * Widget which was clicked on was, or what the click event was
6559 void CopyGameProc(w, event, prms, nprms)
6567 ret = SaveGameToFile(gameCopyFilename, FALSE);
6570 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
6573 NULL/* lose_ownership_proc */ ,
6574 NULL/* transfer_done_proc */);
6577 /* function called when the data to Paste is ready */
6579 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
6580 Atom *type, XtPointer value, unsigned long *len, int *format)
6583 if (value == NULL || *len == 0) {
6584 return; /* nothing had been selected to copy */
6586 f = fopen(gamePasteFilename, "w");
6588 DisplayError(_("Can't open temp file"), errno);
6591 fwrite(value, 1, *len, f);
6594 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
6597 /* called when Paste Game button is pressed,
6598 * all parameters will be NULL */
6599 void PasteGameProc(w, event, prms, nprms)
6605 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
6606 /* (XtSelectionCallbackProc) */ PasteGameCB,
6607 NULL, /* client_data passed to PasteGameCB */
6609 /* better to use the time field from the event that triggered the
6610 * call to this function, but that isn't trivial to get
6620 SaveGameProc(NULL, NULL, NULL, NULL);
6624 void QuitProc(w, event, prms, nprms)
6633 void PauseProc(w, event, prms, nprms)
6643 void MachineBlackProc(w, event, prms, nprms)
6649 MachineBlackEvent();
6652 void MachineWhiteProc(w, event, prms, nprms)
6658 MachineWhiteEvent();
6661 void AnalyzeModeProc(w, event, prms, nprms)
6669 if (!first.analysisSupport) {
6670 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6671 DisplayError(buf, 0);
6674 /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
6675 if (appData.icsActive) {
6676 if (gameMode != IcsObserving) {
6677 sprintf(buf,_("You are not observing a game"));
6678 DisplayError(buf, 0);
6680 if (appData.icsEngineAnalyze) {
6681 if (appData.debugMode)
6682 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
6688 /* if enable, use want disable icsEngineAnalyze */
6689 if (appData.icsEngineAnalyze) {
6694 appData.icsEngineAnalyze = TRUE;
6695 if (appData.debugMode)
6696 fprintf(debugFP, _("ICS engine analyze starting... \n"));
6698 if (!appData.showThinking)
6699 ShowThinkingProc(w,event,prms,nprms);
6704 void AnalyzeFileProc(w, event, prms, nprms)
6710 if (!first.analysisSupport) {
6712 snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
6713 DisplayError(buf, 0);
6718 if (!appData.showThinking)
6719 ShowThinkingProc(w,event,prms,nprms);
6722 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
6723 AnalysisPeriodicEvent(1);
6726 void TwoMachinesProc(w, event, prms, nprms)
6735 void IcsClientProc(w, event, prms, nprms)
6744 void EditGameProc(w, event, prms, nprms)
6753 void EditPositionProc(w, event, prms, nprms)
6759 EditPositionEvent();
6762 void TrainingProc(w, event, prms, nprms)
6771 void EditCommentProc(w, event, prms, nprms)
6778 EditCommentPopDown();
6784 void IcsInputBoxProc(w, event, prms, nprms)
6790 if (ICSInputBoxUp) {
6791 ICSInputBoxPopDown();
6797 void AcceptProc(w, event, prms, nprms)
6806 void DeclineProc(w, event, prms, nprms)
6815 void RematchProc(w, event, prms, nprms)
6824 void CallFlagProc(w, event, prms, nprms)
6833 void DrawProc(w, event, prms, nprms)
6842 void AbortProc(w, event, prms, nprms)
6851 void AdjournProc(w, event, prms, nprms)
6860 void ResignProc(w, event, prms, nprms)
6869 void AdjuWhiteProc(w, event, prms, nprms)
6875 UserAdjudicationEvent(+1);
6878 void AdjuBlackProc(w, event, prms, nprms)
6884 UserAdjudicationEvent(-1);
6887 void AdjuDrawProc(w, event, prms, nprms)
6893 UserAdjudicationEvent(0);
6896 void EnterKeyProc(w, event, prms, nprms)
6902 if (ICSInputBoxUp == True)
6906 void StopObservingProc(w, event, prms, nprms)
6912 StopObservingEvent();
6915 void StopExaminingProc(w, event, prms, nprms)
6921 StopExaminingEvent();
6925 void ForwardProc(w, event, prms, nprms)
6935 void BackwardProc(w, event, prms, nprms)
6944 void ToStartProc(w, event, prms, nprms)
6953 void ToEndProc(w, event, prms, nprms)
6962 void RevertProc(w, event, prms, nprms)
6971 void TruncateGameProc(w, event, prms, nprms)
6977 TruncateGameEvent();
6979 void RetractMoveProc(w, event, prms, nprms)
6988 void MoveNowProc(w, event, prms, nprms)
6998 void AlwaysQueenProc(w, event, prms, nprms)
7006 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
7008 if (appData.alwaysPromoteToQueen) {
7009 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7011 XtSetArg(args[0], XtNleftBitmap, None);
7013 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
7017 void AnimateDraggingProc(w, event, prms, nprms)
7025 appData.animateDragging = !appData.animateDragging;
7027 if (appData.animateDragging) {
7028 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7031 XtSetArg(args[0], XtNleftBitmap, None);
7033 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
7037 void AnimateMovingProc(w, event, prms, nprms)
7045 appData.animate = !appData.animate;
7047 if (appData.animate) {
7048 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7051 XtSetArg(args[0], XtNleftBitmap, None);
7053 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
7057 void AutocommProc(w, event, prms, nprms)
7065 appData.autoComment = !appData.autoComment;
7067 if (appData.autoComment) {
7068 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7070 XtSetArg(args[0], XtNleftBitmap, None);
7072 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
7077 void AutoflagProc(w, event, prms, nprms)
7085 appData.autoCallFlag = !appData.autoCallFlag;
7087 if (appData.autoCallFlag) {
7088 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7090 XtSetArg(args[0], XtNleftBitmap, None);
7092 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
7096 void AutoflipProc(w, event, prms, nprms)
7104 appData.autoFlipView = !appData.autoFlipView;
7106 if (appData.autoFlipView) {
7107 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7109 XtSetArg(args[0], XtNleftBitmap, None);
7111 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
7115 void AutobsProc(w, event, prms, nprms)
7123 appData.autoObserve = !appData.autoObserve;
7125 if (appData.autoObserve) {
7126 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7128 XtSetArg(args[0], XtNleftBitmap, None);
7130 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
7134 void AutoraiseProc(w, event, prms, nprms)
7142 appData.autoRaiseBoard = !appData.autoRaiseBoard;
7144 if (appData.autoRaiseBoard) {
7145 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7147 XtSetArg(args[0], XtNleftBitmap, None);
7149 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
7153 void AutosaveProc(w, event, prms, nprms)
7161 appData.autoSaveGames = !appData.autoSaveGames;
7163 if (appData.autoSaveGames) {
7164 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7166 XtSetArg(args[0], XtNleftBitmap, None);
7168 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
7172 void BlindfoldProc(w, event, prms, nprms)
7180 appData.blindfold = !appData.blindfold;
7182 if (appData.blindfold) {
7183 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7185 XtSetArg(args[0], XtNleftBitmap, None);
7187 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
7190 DrawPosition(True, NULL);
7193 void TestLegalityProc(w, event, prms, nprms)
7201 appData.testLegality = !appData.testLegality;
7203 if (appData.testLegality) {
7204 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7206 XtSetArg(args[0], XtNleftBitmap, None);
7208 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
7213 void FlashMovesProc(w, event, prms, nprms)
7221 if (appData.flashCount == 0) {
7222 appData.flashCount = 3;
7224 appData.flashCount = -appData.flashCount;
7227 if (appData.flashCount > 0) {
7228 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7230 XtSetArg(args[0], XtNleftBitmap, None);
7232 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
7236 void FlipViewProc(w, event, prms, nprms)
7242 flipView = !flipView;
7243 DrawPosition(True, NULL);
7246 void GetMoveListProc(w, event, prms, nprms)
7254 appData.getMoveList = !appData.getMoveList;
7256 if (appData.getMoveList) {
7257 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7260 XtSetArg(args[0], XtNleftBitmap, None);
7262 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
7267 void HighlightDraggingProc(w, event, prms, nprms)
7275 appData.highlightDragging = !appData.highlightDragging;
7277 if (appData.highlightDragging) {
7278 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7280 XtSetArg(args[0], XtNleftBitmap, None);
7282 XtSetValues(XtNameToWidget(menuBarWidget,
7283 "menuOptions.Highlight Dragging"), args, 1);
7287 void HighlightLastMoveProc(w, event, prms, nprms)
7295 appData.highlightLastMove = !appData.highlightLastMove;
7297 if (appData.highlightLastMove) {
7298 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7300 XtSetArg(args[0], XtNleftBitmap, None);
7302 XtSetValues(XtNameToWidget(menuBarWidget,
7303 "menuOptions.Highlight Last Move"), args, 1);
7306 void IcsAlarmProc(w, event, prms, nprms)
7314 appData.icsAlarm = !appData.icsAlarm;
7316 if (appData.icsAlarm) {
7317 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7319 XtSetArg(args[0], XtNleftBitmap, None);
7321 XtSetValues(XtNameToWidget(menuBarWidget,
7322 "menuOptions.ICS Alarm"), args, 1);
7325 void MoveSoundProc(w, event, prms, nprms)
7333 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
7335 if (appData.ringBellAfterMoves) {
7336 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7338 XtSetArg(args[0], XtNleftBitmap, None);
7340 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
7345 void OldSaveStyleProc(w, event, prms, nprms)
7353 appData.oldSaveStyle = !appData.oldSaveStyle;
7355 if (appData.oldSaveStyle) {
7356 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7358 XtSetArg(args[0], XtNleftBitmap, None);
7360 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
7364 void PeriodicUpdatesProc(w, event, prms, nprms)
7372 PeriodicUpdatesEvent(!appData.periodicUpdates);
7374 if (appData.periodicUpdates) {
7375 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7377 XtSetArg(args[0], XtNleftBitmap, None);
7379 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
7383 void PonderNextMoveProc(w, event, prms, nprms)
7391 PonderNextMoveEvent(!appData.ponderNextMove);
7393 if (appData.ponderNextMove) {
7394 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7396 XtSetArg(args[0], XtNleftBitmap, None);
7398 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
7402 void PopupExitMessageProc(w, event, prms, nprms)
7410 appData.popupExitMessage = !appData.popupExitMessage;
7412 if (appData.popupExitMessage) {
7413 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7415 XtSetArg(args[0], XtNleftBitmap, None);
7417 XtSetValues(XtNameToWidget(menuBarWidget,
7418 "menuOptions.Popup Exit Message"), args, 1);
7421 void PopupMoveErrorsProc(w, event, prms, nprms)
7429 appData.popupMoveErrors = !appData.popupMoveErrors;
7431 if (appData.popupMoveErrors) {
7432 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7434 XtSetArg(args[0], XtNleftBitmap, None);
7436 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
7440 void PremoveProc(w, event, prms, nprms)
7448 appData.premove = !appData.premove;
7450 if (appData.premove) {
7451 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7453 XtSetArg(args[0], XtNleftBitmap, None);
7455 XtSetValues(XtNameToWidget(menuBarWidget,
7456 "menuOptions.Premove"), args, 1);
7459 void QuietPlayProc(w, event, prms, nprms)
7467 appData.quietPlay = !appData.quietPlay;
7469 if (appData.quietPlay) {
7470 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7472 XtSetArg(args[0], XtNleftBitmap, None);
7474 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
7478 void ShowCoordsProc(w, event, prms, nprms)
7486 appData.showCoords = !appData.showCoords;
7488 if (appData.showCoords) {
7489 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7491 XtSetArg(args[0], XtNleftBitmap, None);
7493 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
7496 DrawPosition(True, NULL);
7499 void ShowThinkingProc(w, event, prms, nprms)
7507 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7508 ShowThinkingEvent();
7511 void HideThinkingProc(w, event, prms, nprms)
7519 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7520 ShowThinkingEvent();
7522 if (appData.hideThinkingFromHuman) {
7523 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
7525 XtSetArg(args[0], XtNleftBitmap, None);
7527 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
7531 void InfoProc(w, event, prms, nprms)
7538 snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
7543 void ManProc(w, event, prms, nprms)
7551 if (nprms && *nprms > 0)
7555 snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
7559 void HintProc(w, event, prms, nprms)
7568 void BookProc(w, event, prms, nprms)
7577 void AboutProc(w, event, prms, nprms)
7585 char *zippy = " (with Zippy code)";
7589 snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
7590 programVersion, zippy,
7591 "Copyright 1991 Digital Equipment Corporation",
7592 "Enhancements Copyright 1992-2009 Free Software Foundation",
7593 "Enhancements Copyright 2005 Alessandro Scotti",
7594 PACKAGE, " is free software and carries NO WARRANTY;",
7595 "see the file COPYING for more information.");
7596 ErrorPopUp(_("About XBoard"), buf, FALSE);
7599 void DebugProc(w, event, prms, nprms)
7605 appData.debugMode = !appData.debugMode;
7608 void AboutGameProc(w, event, prms, nprms)
7617 void NothingProc(w, event, prms, nprms)
7626 void Iconify(w, event, prms, nprms)
7635 XtSetArg(args[0], XtNiconic, True);
7636 XtSetValues(shellWidget, args, 1);
7639 void DisplayMessage(message, extMessage)
7640 char *message, *extMessage;
7642 /* display a message in the message widget */
7651 snprintf(buf, sizeof(buf), "%s %s", message, extMessage);
7656 message = extMessage;
7660 /* need to test if messageWidget already exists, since this function
7661 can also be called during the startup, if for example a Xresource
7662 is not set up correctly */
7665 XtSetArg(arg, XtNlabel, message);
7666 XtSetValues(messageWidget, &arg, 1);
7672 void DisplayTitle(text)
7677 char title[MSG_SIZ];
7680 if (text == NULL) text = "";
7682 if (appData.titleInWindow) {
7684 XtSetArg(args[i], XtNlabel, text); i++;
7685 XtSetValues(titleWidget, args, i);
7688 if (*text != NULLCHAR) {
7690 strcpy(title, text);
7691 } else if (appData.icsActive) {
7692 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
7693 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
7694 } else if (appData.cmailGameName[0] != NULLCHAR) {
7695 snprintf(icon, sizeof(icon), "%s", "CMail");
7696 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
7698 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7699 } else if (gameInfo.variant == VariantGothic) {
7700 strcpy(icon, programName);
7701 strcpy(title, GOTHIC);
7704 } else if (gameInfo.variant == VariantFalcon) {
7705 strcpy(icon, programName);
7706 strcpy(title, FALCON);
7708 } else if (appData.noChessProgram) {
7709 strcpy(icon, programName);
7710 strcpy(title, programName);
7712 strcpy(icon, first.tidy);
7713 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
7716 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
7717 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
7718 XtSetValues(shellWidget, args, i);
7722 void DisplayError(message, error)
7729 if (appData.debugMode || appData.matchMode) {
7730 fprintf(stderr, "%s: %s\n", programName, message);
7733 if (appData.debugMode || appData.matchMode) {
7734 fprintf(stderr, "%s: %s: %s\n",
7735 programName, message, strerror(error));
7737 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7740 ErrorPopUp(_("Error"), message, FALSE);
7744 void DisplayMoveError(message)
7749 DrawPosition(FALSE, NULL);
7750 if (appData.debugMode || appData.matchMode) {
7751 fprintf(stderr, "%s: %s\n", programName, message);
7753 if (appData.popupMoveErrors) {
7754 ErrorPopUp(_("Error"), message, FALSE);
7756 DisplayMessage(message, "");
7761 void DisplayFatalError(message, error, status)
7767 errorExitStatus = status;
7769 fprintf(stderr, "%s: %s\n", programName, message);
7771 fprintf(stderr, "%s: %s: %s\n",
7772 programName, message, strerror(error));
7773 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
7776 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
7777 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
7783 void DisplayInformation(message)
7787 ErrorPopUp(_("Information"), message, TRUE);
7790 void DisplayNote(message)
7794 ErrorPopUp(_("Note"), message, FALSE);
7798 NullXErrorCheck(dpy, error_event)
7800 XErrorEvent *error_event;
7805 void DisplayIcsInteractionTitle(message)
7808 if (oldICSInteractionTitle == NULL) {
7809 /* Magic to find the old window title, adapted from vim */
7810 char *wina = getenv("WINDOWID");
7812 Window win = (Window) atoi(wina);
7813 Window root, parent, *children;
7814 unsigned int nchildren;
7815 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
7817 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
7818 if (!XQueryTree(xDisplay, win, &root, &parent,
7819 &children, &nchildren)) break;
7820 if (children) XFree((void *)children);
7821 if (parent == root || parent == 0) break;
7824 XSetErrorHandler(oldHandler);
7826 if (oldICSInteractionTitle == NULL) {
7827 oldICSInteractionTitle = "xterm";
7830 printf("\033]0;%s\007", message);
7834 char pendingReplyPrefix[MSG_SIZ];
7835 ProcRef pendingReplyPR;
7837 void AskQuestionProc(w, event, prms, nprms)
7844 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
7848 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
7851 void AskQuestionPopDown()
7853 if (!askQuestionUp) return;
7854 XtPopdown(askQuestionShell);
7855 XtDestroyWidget(askQuestionShell);
7856 askQuestionUp = False;
7859 void AskQuestionReplyAction(w, event, prms, nprms)
7869 reply = XawDialogGetValueString(w = XtParent(w));
7870 strcpy(buf, pendingReplyPrefix);
7871 if (*buf) strcat(buf, " ");
7874 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7875 AskQuestionPopDown();
7877 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7880 void AskQuestionCallback(w, client_data, call_data)
7882 XtPointer client_data, call_data;
7887 XtSetArg(args[0], XtNlabel, &name);
7888 XtGetValues(w, args, 1);
7890 if (strcmp(name, _("cancel")) == 0) {
7891 AskQuestionPopDown();
7893 AskQuestionReplyAction(w, NULL, NULL, NULL);
7897 void AskQuestion(title, question, replyPrefix, pr)
7898 char *title, *question, *replyPrefix;
7902 Widget popup, layout, dialog, edit;
7908 strcpy(pendingReplyPrefix, replyPrefix);
7909 pendingReplyPR = pr;
7912 XtSetArg(args[i], XtNresizable, True); i++;
7913 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7914 askQuestionShell = popup =
7915 XtCreatePopupShell(title, transientShellWidgetClass,
7916 shellWidget, args, i);
7919 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7920 layoutArgs, XtNumber(layoutArgs));
7923 XtSetArg(args[i], XtNlabel, question); i++;
7924 XtSetArg(args[i], XtNvalue, ""); i++;
7925 XtSetArg(args[i], XtNborderWidth, 0); i++;
7926 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7929 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7930 (XtPointer) dialog);
7931 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7932 (XtPointer) dialog);
7934 XtRealizeWidget(popup);
7935 CatchDeleteWindow(popup, "AskQuestionPopDown");
7937 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7938 &x, &y, &win_x, &win_y, &mask);
7940 XtSetArg(args[0], XtNx, x - 10);
7941 XtSetArg(args[1], XtNy, y - 30);
7942 XtSetValues(popup, args, 2);
7944 XtPopup(popup, XtGrabExclusive);
7945 askQuestionUp = True;
7947 edit = XtNameToWidget(dialog, "*value");
7948 XtSetKeyboardFocus(popup, edit);
7956 if (*name == NULLCHAR) {
7958 } else if (strcmp(name, "$") == 0) {
7959 putc(BELLCHAR, stderr);
7962 snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
7970 PlaySound(appData.soundMove);
7976 PlaySound(appData.soundIcsWin);
7982 PlaySound(appData.soundIcsLoss);
7988 PlaySound(appData.soundIcsDraw);
7992 PlayIcsUnfinishedSound()
7994 PlaySound(appData.soundIcsUnfinished);
8000 PlaySound(appData.soundIcsAlarm);
8006 system("stty echo");
8012 system("stty -echo");
8016 Colorize(cc, continuation)
8021 int count, outCount, error;
8023 if (textColors[(int)cc].bg > 0) {
8024 if (textColors[(int)cc].fg > 0) {
8025 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
8026 textColors[(int)cc].fg, textColors[(int)cc].bg);
8028 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8029 textColors[(int)cc].bg);
8032 if (textColors[(int)cc].fg > 0) {
8033 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
8034 textColors[(int)cc].fg);
8036 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
8039 count = strlen(buf);
8040 outCount = OutputToProcess(NoProc, buf, count, &error);
8041 if (outCount < count) {
8042 DisplayFatalError(_("Error writing to display"), error, 1);
8045 if (continuation) return;
8048 PlaySound(appData.soundShout);
8051 PlaySound(appData.soundSShout);
8054 PlaySound(appData.soundChannel1);
8057 PlaySound(appData.soundChannel);
8060 PlaySound(appData.soundKibitz);
8063 PlaySound(appData.soundTell);
8065 case ColorChallenge:
8066 PlaySound(appData.soundChallenge);
8069 PlaySound(appData.soundRequest);
8072 PlaySound(appData.soundSeek);
8083 return getpwuid(getuid())->pw_name;
8086 static char *ExpandPathName(path)
8089 static char static_buf[2000];
8090 char *d, *s, buf[2000];
8096 while (*s && isspace(*s))
8105 if (*(s+1) == '/') {
8106 strcpy(d, getpwuid(getuid())->pw_dir);
8111 *strchr(buf, '/') = 0;
8112 pwd = getpwnam(buf);
8115 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
8119 strcpy(d, pwd->pw_dir);
8120 strcat(d, strchr(s+1, '/'));
8131 static char host_name[MSG_SIZ];
8133 #if HAVE_GETHOSTNAME
8134 gethostname(host_name, MSG_SIZ);
8136 #else /* not HAVE_GETHOSTNAME */
8137 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
8138 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
8140 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8142 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
8143 #endif /* not HAVE_GETHOSTNAME */
8146 XtIntervalId delayedEventTimerXID = 0;
8147 DelayedEventCallback delayedEventCallback = 0;
8152 delayedEventTimerXID = 0;
8153 delayedEventCallback();
8157 ScheduleDelayedEvent(cb, millisec)
8158 DelayedEventCallback cb; long millisec;
8160 if(delayedEventTimerXID && delayedEventCallback == cb)
8161 // [HGM] alive: replace, rather than add or flush identical event
8162 XtRemoveTimeOut(delayedEventTimerXID);
8163 delayedEventCallback = cb;
8164 delayedEventTimerXID =
8165 XtAppAddTimeOut(appContext, millisec,
8166 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
8169 DelayedEventCallback
8172 if (delayedEventTimerXID) {
8173 return delayedEventCallback;
8180 CancelDelayedEvent()
8182 if (delayedEventTimerXID) {
8183 XtRemoveTimeOut(delayedEventTimerXID);
8184 delayedEventTimerXID = 0;
8188 XtIntervalId loadGameTimerXID = 0;
8190 int LoadGameTimerRunning()
8192 return loadGameTimerXID != 0;
8195 int StopLoadGameTimer()
8197 if (loadGameTimerXID != 0) {
8198 XtRemoveTimeOut(loadGameTimerXID);
8199 loadGameTimerXID = 0;
8207 LoadGameTimerCallback(arg, id)
8211 loadGameTimerXID = 0;
8216 StartLoadGameTimer(millisec)
8220 XtAppAddTimeOut(appContext, millisec,
8221 (XtTimerCallbackProc) LoadGameTimerCallback,
8225 XtIntervalId analysisClockXID = 0;
8228 AnalysisClockCallback(arg, id)
8232 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
8233 || appData.icsEngineAnalyze) { // [DM]
8234 AnalysisPeriodicEvent(0);
8235 StartAnalysisClock();
8240 StartAnalysisClock()
8243 XtAppAddTimeOut(appContext, 2000,
8244 (XtTimerCallbackProc) AnalysisClockCallback,
8248 XtIntervalId clockTimerXID = 0;
8250 int ClockTimerRunning()
8252 return clockTimerXID != 0;
8255 int StopClockTimer()
8257 if (clockTimerXID != 0) {
8258 XtRemoveTimeOut(clockTimerXID);
8267 ClockTimerCallback(arg, id)
8276 StartClockTimer(millisec)
8280 XtAppAddTimeOut(appContext, millisec,
8281 (XtTimerCallbackProc) ClockTimerCallback,
8286 DisplayTimerLabel(w, color, timer, highlight)
8295 /* check for low time warning */
8296 Pixel foregroundOrWarningColor = timerForegroundPixel;
8299 appData.lowTimeWarning &&
8300 (timer / 1000) < appData.icsAlarmTime)
8301 foregroundOrWarningColor = lowTimeWarningColor;
8303 if (appData.clockMode) {
8304 sprintf(buf, "%s: %s", color, TimeString(timer));
8305 XtSetArg(args[0], XtNlabel, buf);
8307 sprintf(buf, "%s ", color);
8308 XtSetArg(args[0], XtNlabel, buf);
8313 XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
8314 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
8316 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
8317 XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
8320 XtSetValues(w, args, 3);
8324 DisplayWhiteClock(timeRemaining, highlight)
8330 if(appData.noGUI) return;
8331 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
8332 if (highlight && iconPixmap == bIconPixmap) {
8333 iconPixmap = wIconPixmap;
8334 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8335 XtSetValues(shellWidget, args, 1);
8340 DisplayBlackClock(timeRemaining, highlight)
8346 if(appData.noGUI) return;
8347 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
8348 if (highlight && iconPixmap == wIconPixmap) {
8349 iconPixmap = bIconPixmap;
8350 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
8351 XtSetValues(shellWidget, args, 1);
8369 int StartChildProcess(cmdLine, dir, pr)
8376 int to_prog[2], from_prog[2];
8380 if (appData.debugMode) {
8381 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
8384 /* We do NOT feed the cmdLine to the shell; we just
8385 parse it into blank-separated arguments in the
8386 most simple-minded way possible.
8389 strcpy(buf, cmdLine);
8394 if (p == NULL) break;
8399 SetUpChildIO(to_prog, from_prog);
8401 if ((pid = fork()) == 0) {
8403 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
8404 close(to_prog[1]); // first close the unused pipe ends
8405 close(from_prog[0]);
8406 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
8407 dup2(from_prog[1], 1);
8408 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
8409 close(from_prog[1]); // and closing again loses one of the pipes!
8410 if(fileno(stderr) >= 2) // better safe than sorry...
8411 dup2(1, fileno(stderr)); /* force stderr to the pipe */
8413 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
8418 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
8420 execvp(argv[0], argv);
8422 /* If we get here, exec failed */
8427 /* Parent process */
8429 close(from_prog[1]);
8431 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8434 cp->fdFrom = from_prog[0];
8435 cp->fdTo = to_prog[1];
8440 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
8441 static RETSIGTYPE AlarmCallBack(int n)
8447 DestroyChildProcess(pr, signalType)
8451 ChildProc *cp = (ChildProc *) pr;
8453 if (cp->kind != CPReal) return;
8455 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
8456 signal(SIGALRM, AlarmCallBack);
8458 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
8459 kill(cp->pid, SIGKILL); // kill it forcefully
8460 wait((int *) 0); // and wait again
8464 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
8466 /* Process is exiting either because of the kill or because of
8467 a quit command sent by the backend; either way, wait for it to die.
8476 InterruptChildProcess(pr)
8479 ChildProc *cp = (ChildProc *) pr;
8481 if (cp->kind != CPReal) return;
8482 (void) kill(cp->pid, SIGINT); /* stop it thinking */
8485 int OpenTelnet(host, port, pr)
8490 char cmdLine[MSG_SIZ];
8492 if (port[0] == NULLCHAR) {
8493 snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
8495 snprintf(cmdLine, sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
8497 return StartChildProcess(cmdLine, "", pr);
8500 int OpenTCP(host, port, pr)
8506 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
8507 #else /* !OMIT_SOCKETS */
8509 struct sockaddr_in sa;
8511 unsigned short uport;
8514 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
8518 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8519 sa.sin_family = AF_INET;
8520 sa.sin_addr.s_addr = INADDR_ANY;
8521 uport = (unsigned short) 0;
8522 sa.sin_port = htons(uport);
8523 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
8527 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
8528 if (!(hp = gethostbyname(host))) {
8530 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
8531 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
8532 hp->h_addrtype = AF_INET;
8534 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
8535 hp->h_addr_list[0] = (char *) malloc(4);
8536 hp->h_addr_list[0][0] = b0;
8537 hp->h_addr_list[0][1] = b1;
8538 hp->h_addr_list[0][2] = b2;
8539 hp->h_addr_list[0][3] = b3;
8544 sa.sin_family = hp->h_addrtype;
8545 uport = (unsigned short) atoi(port);
8546 sa.sin_port = htons(uport);
8547 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
8549 if (connect(s, (struct sockaddr *) &sa,
8550 sizeof(struct sockaddr_in)) < 0) {
8554 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8561 #endif /* !OMIT_SOCKETS */
8566 int OpenCommPort(name, pr)
8573 fd = open(name, 2, 0);
8574 if (fd < 0) return errno;
8576 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8586 int OpenLoopback(pr)
8592 SetUpChildIO(to, from);
8594 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
8597 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
8604 int OpenRcmd(host, user, cmd, pr)
8605 char *host, *user, *cmd;
8608 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
8612 #define INPUT_SOURCE_BUF_SIZE 8192
8621 char buf[INPUT_SOURCE_BUF_SIZE];
8626 DoInputCallback(closure, source, xid)
8631 InputSource *is = (InputSource *) closure;
8636 if (is->lineByLine) {
8637 count = read(is->fd, is->unused,
8638 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
8640 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
8643 is->unused += count;
8645 while (p < is->unused) {
8646 q = memchr(p, '\n', is->unused - p);
8647 if (q == NULL) break;
8649 (is->func)(is, is->closure, p, q - p, 0);
8653 while (p < is->unused) {
8658 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
8663 (is->func)(is, is->closure, is->buf, count, error);
8667 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
8674 ChildProc *cp = (ChildProc *) pr;
8676 is = (InputSource *) calloc(1, sizeof(InputSource));
8677 is->lineByLine = lineByLine;
8681 is->fd = fileno(stdin);
8683 is->kind = cp->kind;
8684 is->fd = cp->fdFrom;
8687 is->unused = is->buf;
8690 is->xid = XtAppAddInput(appContext, is->fd,
8691 (XtPointer) (XtInputReadMask),
8692 (XtInputCallbackProc) DoInputCallback,
8694 is->closure = closure;
8695 return (InputSourceRef) is;
8699 RemoveInputSource(isr)
8702 InputSource *is = (InputSource *) isr;
8704 if (is->xid == 0) return;
8705 XtRemoveInput(is->xid);
8709 int OutputToProcess(pr, message, count, outError)
8715 ChildProc *cp = (ChildProc *) pr;
8719 outCount = fwrite(message, 1, count, stdout);
8721 outCount = write(cp->fdTo, message, count);
8731 /* Output message to process, with "ms" milliseconds of delay
8732 between each character. This is needed when sending the logon
8733 script to ICC, which for some reason doesn't like the
8734 instantaneous send. */
8735 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
8742 ChildProc *cp = (ChildProc *) pr;
8747 r = write(cp->fdTo, message++, 1);
8760 /**** Animation code by Hugh Fisher, DCS, ANU.
8762 Known problem: if a window overlapping the board is
8763 moved away while a piece is being animated underneath,
8764 the newly exposed area won't be updated properly.
8765 I can live with this.
8767 Known problem: if you look carefully at the animation
8768 of pieces in mono mode, they are being drawn as solid
8769 shapes without interior detail while moving. Fixing
8770 this would be a major complication for minimal return.
8773 /* Masks for XPM pieces. Black and white pieces can have
8774 different shapes, but in the interest of retaining my
8775 sanity pieces must have the same outline on both light
8776 and dark squares, and all pieces must use the same
8777 background square colors/images. */
8779 static int xpmDone = 0;
8782 CreateAnimMasks (pieceDepth)
8789 unsigned long plane;
8792 /* Need a bitmap just to get a GC with right depth */
8793 buf = XCreatePixmap(xDisplay, xBoardWindow,
8795 values.foreground = 1;
8796 values.background = 0;
8797 /* Don't use XtGetGC, not read only */
8798 maskGC = XCreateGC(xDisplay, buf,
8799 GCForeground | GCBackground, &values);
8800 XFreePixmap(xDisplay, buf);
8802 buf = XCreatePixmap(xDisplay, xBoardWindow,
8803 squareSize, squareSize, pieceDepth);
8804 values.foreground = XBlackPixel(xDisplay, xScreen);
8805 values.background = XWhitePixel(xDisplay, xScreen);
8806 bufGC = XCreateGC(xDisplay, buf,
8807 GCForeground | GCBackground, &values);
8809 for (piece = WhitePawn; piece <= BlackKing; piece++) {
8810 /* Begin with empty mask */
8811 if(!xpmDone) // [HGM] pieces: keep using existing
8812 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
8813 squareSize, squareSize, 1);
8814 XSetFunction(xDisplay, maskGC, GXclear);
8815 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
8816 0, 0, squareSize, squareSize);
8818 /* Take a copy of the piece */
8823 XSetFunction(xDisplay, bufGC, GXcopy);
8824 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
8826 0, 0, squareSize, squareSize, 0, 0);
8828 /* XOR the background (light) over the piece */
8829 XSetFunction(xDisplay, bufGC, GXxor);
8831 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
8832 0, 0, squareSize, squareSize, 0, 0);
8834 XSetForeground(xDisplay, bufGC, lightSquareColor);
8835 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
8838 /* We now have an inverted piece image with the background
8839 erased. Construct mask by just selecting all the non-zero
8840 pixels - no need to reconstruct the original image. */
8841 XSetFunction(xDisplay, maskGC, GXor);
8843 /* Might be quicker to download an XImage and create bitmap
8844 data from it rather than this N copies per piece, but it
8845 only takes a fraction of a second and there is a much
8846 longer delay for loading the pieces. */
8847 for (n = 0; n < pieceDepth; n ++) {
8848 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
8849 0, 0, squareSize, squareSize,
8855 XFreePixmap(xDisplay, buf);
8856 XFreeGC(xDisplay, bufGC);
8857 XFreeGC(xDisplay, maskGC);
8861 InitAnimState (anim, info)
8863 XWindowAttributes * info;
8868 /* Each buffer is square size, same depth as window */
8869 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
8870 squareSize, squareSize, info->depth);
8871 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
8872 squareSize, squareSize, info->depth);
8874 /* Create a plain GC for blitting */
8875 mask = GCForeground | GCBackground | GCFunction |
8876 GCPlaneMask | GCGraphicsExposures;
8877 values.foreground = XBlackPixel(xDisplay, xScreen);
8878 values.background = XWhitePixel(xDisplay, xScreen);
8879 values.function = GXcopy;
8880 values.plane_mask = AllPlanes;
8881 values.graphics_exposures = False;
8882 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
8884 /* Piece will be copied from an existing context at
8885 the start of each new animation/drag. */
8886 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
8888 /* Outline will be a read-only copy of an existing */
8889 anim->outlineGC = None;
8895 static VariantClass old = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
8896 XWindowAttributes info;
8898 if (xpmDone && gameInfo.variant == old) return;
8899 if(xpmDone) old = gameInfo.variant; // first time pieces might not be created yet
8900 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8902 InitAnimState(&game, &info);
8903 InitAnimState(&player, &info);
8905 /* For XPM pieces, we need bitmaps to use as masks. */
8907 CreateAnimMasks(info.depth);
8913 static Boolean frameWaiting;
8915 static RETSIGTYPE FrameAlarm (sig)
8918 frameWaiting = False;
8919 /* In case System-V style signals. Needed?? */
8920 signal(SIGALRM, FrameAlarm);
8927 struct itimerval delay;
8929 XSync(xDisplay, False);
8932 frameWaiting = True;
8933 signal(SIGALRM, FrameAlarm);
8934 delay.it_interval.tv_sec =
8935 delay.it_value.tv_sec = time / 1000;
8936 delay.it_interval.tv_usec =
8937 delay.it_value.tv_usec = (time % 1000) * 1000;
8938 setitimer(ITIMER_REAL, &delay, NULL);
8939 while (frameWaiting) pause();
8940 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8941 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8942 setitimer(ITIMER_REAL, &delay, NULL);
8952 XSync(xDisplay, False);
8954 usleep(time * 1000);
8959 /* Convert board position to corner of screen rect and color */
8962 ScreenSquare(column, row, pt, color)
8963 int column; int row; XPoint * pt; int * color;
8966 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
8967 pt->y = lineGap + row * (squareSize + lineGap);
8969 pt->x = lineGap + column * (squareSize + lineGap);
8970 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
8972 *color = SquareColor(row, column);
8975 /* Convert window coords to square */
8978 BoardSquare(x, y, column, row)
8979 int x; int y; int * column; int * row;
8981 *column = EventToSquare(x, BOARD_WIDTH);
8982 if (flipView && *column >= 0)
8983 *column = BOARD_WIDTH - 1 - *column;
8984 *row = EventToSquare(y, BOARD_HEIGHT);
8985 if (!flipView && *row >= 0)
8986 *row = BOARD_HEIGHT - 1 - *row;
8991 #undef Max /* just in case */
8993 #define Max(a, b) ((a) > (b) ? (a) : (b))
8994 #define Min(a, b) ((a) < (b) ? (a) : (b))
8997 SetRect(rect, x, y, width, height)
8998 XRectangle * rect; int x; int y; int width; int height;
9002 rect->width = width;
9003 rect->height = height;
9006 /* Test if two frames overlap. If they do, return
9007 intersection rect within old and location of
9008 that rect within new. */
9011 Intersect(old, new, size, area, pt)
9012 XPoint * old; XPoint * new;
9013 int size; XRectangle * area; XPoint * pt;
9015 if (old->x > new->x + size || new->x > old->x + size ||
9016 old->y > new->y + size || new->y > old->y + size) {
9019 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
9020 size - abs(old->x - new->x), size - abs(old->y - new->y));
9021 pt->x = Max(old->x - new->x, 0);
9022 pt->y = Max(old->y - new->y, 0);
9027 /* For two overlapping frames, return the rect(s)
9028 in the old that do not intersect with the new. */
9031 CalcUpdateRects(old, new, size, update, nUpdates)
9032 XPoint * old; XPoint * new; int size;
9033 XRectangle update[]; int * nUpdates;
9037 /* If old = new (shouldn't happen) then nothing to draw */
9038 if (old->x == new->x && old->y == new->y) {
9042 /* Work out what bits overlap. Since we know the rects
9043 are the same size we don't need a full intersect calc. */
9045 /* Top or bottom edge? */
9046 if (new->y > old->y) {
9047 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
9049 } else if (old->y > new->y) {
9050 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
9051 size, old->y - new->y);
9054 /* Left or right edge - don't overlap any update calculated above. */
9055 if (new->x > old->x) {
9056 SetRect(&(update[count]), old->x, Max(new->y, old->y),
9057 new->x - old->x, size - abs(new->y - old->y));
9059 } else if (old->x > new->x) {
9060 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
9061 old->x - new->x, size - abs(new->y - old->y));
9068 /* Generate a series of frame coords from start->mid->finish.
9069 The movement rate doubles until the half way point is
9070 reached, then halves back down to the final destination,
9071 which gives a nice slow in/out effect. The algorithmn
9072 may seem to generate too many intermediates for short
9073 moves, but remember that the purpose is to attract the
9074 viewers attention to the piece about to be moved and
9075 then to where it ends up. Too few frames would be less
9079 Tween(start, mid, finish, factor, frames, nFrames)
9080 XPoint * start; XPoint * mid;
9081 XPoint * finish; int factor;
9082 XPoint frames[]; int * nFrames;
9084 int fraction, n, count;
9088 /* Slow in, stepping 1/16th, then 1/8th, ... */
9090 for (n = 0; n < factor; n++)
9092 for (n = 0; n < factor; n++) {
9093 frames[count].x = start->x + (mid->x - start->x) / fraction;
9094 frames[count].y = start->y + (mid->y - start->y) / fraction;
9096 fraction = fraction / 2;
9100 frames[count] = *mid;
9103 /* Slow out, stepping 1/2, then 1/4, ... */
9105 for (n = 0; n < factor; n++) {
9106 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
9107 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
9109 fraction = fraction * 2;
9114 /* Draw a piece on the screen without disturbing what's there */
9117 SelectGCMask(piece, clip, outline, mask)
9118 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
9122 /* Bitmap for piece being moved. */
9123 if (appData.monoMode) {
9124 *mask = *pieceToSolid(piece);
9125 } else if (useImages) {
9127 *mask = xpmMask[piece];
9129 *mask = ximMaskPm[piece];
9132 *mask = *pieceToSolid(piece);
9135 /* GC for piece being moved. Square color doesn't matter, but
9136 since it gets modified we make a copy of the original. */
9138 if (appData.monoMode)
9143 if (appData.monoMode)
9148 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
9150 /* Outline only used in mono mode and is not modified */
9152 *outline = bwPieceGC;
9154 *outline = wbPieceGC;
9158 OverlayPiece(piece, clip, outline, dest)
9159 ChessSquare piece; GC clip; GC outline; Drawable dest;
9164 /* Draw solid rectangle which will be clipped to shape of piece */
9165 XFillRectangle(xDisplay, dest, clip,
9166 0, 0, squareSize, squareSize);
9167 if (appData.monoMode)
9168 /* Also draw outline in contrasting color for black
9169 on black / white on white cases */
9170 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
9171 0, 0, squareSize, squareSize, 0, 0, 1);
9173 /* Copy the piece */
9178 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
9180 0, 0, squareSize, squareSize,
9185 /* Animate the movement of a single piece */
9188 BeginAnimation(anim, piece, startColor, start)
9196 /* The old buffer is initialised with the start square (empty) */
9197 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
9198 anim->prevFrame = *start;
9200 /* The piece will be drawn using its own bitmap as a matte */
9201 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
9202 XSetClipMask(xDisplay, anim->pieceGC, mask);
9206 AnimationFrame(anim, frame, piece)
9211 XRectangle updates[4];
9216 /* Save what we are about to draw into the new buffer */
9217 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
9218 frame->x, frame->y, squareSize, squareSize,
9221 /* Erase bits of the previous frame */
9222 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
9223 /* Where the new frame overlapped the previous,
9224 the contents in newBuf are wrong. */
9225 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
9226 overlap.x, overlap.y,
9227 overlap.width, overlap.height,
9229 /* Repaint the areas in the old that don't overlap new */
9230 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
9231 for (i = 0; i < count; i++)
9232 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9233 updates[i].x - anim->prevFrame.x,
9234 updates[i].y - anim->prevFrame.y,
9235 updates[i].width, updates[i].height,
9236 updates[i].x, updates[i].y);
9238 /* Easy when no overlap */
9239 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9240 0, 0, squareSize, squareSize,
9241 anim->prevFrame.x, anim->prevFrame.y);
9244 /* Save this frame for next time round */
9245 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
9246 0, 0, squareSize, squareSize,
9248 anim->prevFrame = *frame;
9250 /* Draw piece over original screen contents, not current,
9251 and copy entire rect. Wipes out overlapping piece images. */
9252 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
9253 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
9254 0, 0, squareSize, squareSize,
9255 frame->x, frame->y);
9259 EndAnimation (anim, finish)
9263 XRectangle updates[4];
9268 /* The main code will redraw the final square, so we
9269 only need to erase the bits that don't overlap. */
9270 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
9271 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
9272 for (i = 0; i < count; i++)
9273 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9274 updates[i].x - anim->prevFrame.x,
9275 updates[i].y - anim->prevFrame.y,
9276 updates[i].width, updates[i].height,
9277 updates[i].x, updates[i].y);
9279 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
9280 0, 0, squareSize, squareSize,
9281 anim->prevFrame.x, anim->prevFrame.y);
9286 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
9288 ChessSquare piece; int startColor;
9289 XPoint * start; XPoint * finish;
9290 XPoint frames[]; int nFrames;
9294 BeginAnimation(anim, piece, startColor, start);
9295 for (n = 0; n < nFrames; n++) {
9296 AnimationFrame(anim, &(frames[n]), piece);
9297 FrameDelay(appData.animSpeed);
9299 EndAnimation(anim, finish);
9302 /* Main control logic for deciding what to animate and how */
9305 AnimateMove(board, fromX, fromY, toX, toY)
9314 XPoint start, finish, mid;
9315 XPoint frames[kFactor * 2 + 1];
9316 int nFrames, startColor, endColor;
9318 /* Are we animating? */
9319 if (!appData.animate || appData.blindfold)
9322 if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing ||
9323 board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing)
9324 return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square
9326 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
9327 piece = board[fromY][fromX];
9328 if (piece >= EmptySquare) return;
9333 hop = (piece == WhiteKnight || piece == BlackKnight);
9336 if (appData.debugMode) {
9337 fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
9338 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
9339 piece, fromX, fromY, toX, toY); }
9341 ScreenSquare(fromX, fromY, &start, &startColor);
9342 ScreenSquare(toX, toY, &finish, &endColor);
9345 /* Knight: make diagonal movement then straight */
9346 if (abs(toY - fromY) < abs(toX - fromX)) {
9347 mid.x = start.x + (finish.x - start.x) / 2;
9351 mid.y = start.y + (finish.y - start.y) / 2;
9354 mid.x = start.x + (finish.x - start.x) / 2;
9355 mid.y = start.y + (finish.y - start.y) / 2;
9358 /* Don't use as many frames for very short moves */
9359 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
9360 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
9362 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
9363 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
9365 /* Be sure end square is redrawn */
9366 damage[toY][toX] = True;
9370 DragPieceBegin(x, y)
9373 int boardX, boardY, color;
9376 /* Are we animating? */
9377 if (!appData.animateDragging || appData.blindfold)
9380 /* Figure out which square we start in and the
9381 mouse position relative to top left corner. */
9382 BoardSquare(x, y, &boardX, &boardY);
9383 player.startBoardX = boardX;
9384 player.startBoardY = boardY;
9385 ScreenSquare(boardX, boardY, &corner, &color);
9386 player.startSquare = corner;
9387 player.startColor = color;
9388 /* As soon as we start dragging, the piece will jump slightly to
9389 be centered over the mouse pointer. */
9390 player.mouseDelta.x = squareSize/2;
9391 player.mouseDelta.y = squareSize/2;
9392 /* Initialise animation */
9393 player.dragPiece = PieceForSquare(boardX, boardY);
9395 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
9396 player.dragActive = True;
9397 BeginAnimation(&player, player.dragPiece, color, &corner);
9398 /* Mark this square as needing to be redrawn. Note that
9399 we don't remove the piece though, since logically (ie
9400 as seen by opponent) the move hasn't been made yet. */
9401 if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 ||
9402 boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
9403 XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
9404 corner.x, corner.y, squareSize, squareSize,
9405 0, 0); // [HGM] zh: unstack in stead of grab
9406 damage[boardY][boardX] = True;
9408 player.dragActive = False;
9418 /* Are we animating? */
9419 if (!appData.animateDragging || appData.blindfold)
9423 if (! player.dragActive)
9425 /* Move piece, maintaining same relative position
9426 of mouse within square */
9427 corner.x = x - player.mouseDelta.x;
9428 corner.y = y - player.mouseDelta.y;
9429 AnimationFrame(&player, &corner, player.dragPiece);
9431 if (appData.highlightDragging) {
9433 BoardSquare(x, y, &boardX, &boardY);
9434 SetHighlights(fromX, fromY, boardX, boardY);
9443 int boardX, boardY, color;
9446 /* Are we animating? */
9447 if (!appData.animateDragging || appData.blindfold)
9451 if (! player.dragActive)
9453 /* Last frame in sequence is square piece is
9454 placed on, which may not match mouse exactly. */
9455 BoardSquare(x, y, &boardX, &boardY);
9456 ScreenSquare(boardX, boardY, &corner, &color);
9457 EndAnimation(&player, &corner);
9459 /* Be sure end square is redrawn */
9460 damage[boardY][boardX] = True;
9462 /* This prevents weird things happening with fast successive
9463 clicks which on my Sun at least can cause motion events
9464 without corresponding press/release. */
9465 player.dragActive = False;
9468 /* Handle expose event while piece being dragged */
9473 if (!player.dragActive || appData.blindfold)
9476 /* What we're doing: logically, the move hasn't been made yet,
9477 so the piece is still in it's original square. But visually
9478 it's being dragged around the board. So we erase the square
9479 that the piece is on and draw it at the last known drag point. */
9480 BlankSquare(player.startSquare.x, player.startSquare.y,
9481 player.startColor, EmptySquare, xBoardWindow);
9482 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
9483 damage[player.startBoardY][player.startBoardX] = TRUE;
9487 SetProgramStats( FrontEndProgramStats * stats )
9490 // [HGM] done, but perhaps backend should call this directly?
9491 EngineOutputUpdate( stats );
9494 #include <sys/ioctl.h>
9495 int get_term_width()
9497 int fd, default_width;
9500 default_width = 79; // this is FICS default anyway...
9502 #if !defined(TIOCGWINSZ) && defined(TIOCGSIZE)
9504 if (!ioctl(fd, TIOCGSIZE, &win))
9505 default_width = win.ts_cols;
9506 #elif defined(TIOCGWINSZ)
9508 if (!ioctl(fd, TIOCGWINSZ, &win))
9509 default_width = win.ws_col;
9511 return default_width;
9514 void update_ics_width()
9516 static int old_width = 0;
9517 int new_width = get_term_width();
9519 if (old_width != new_width)
9520 ics_printf("set width %d\n", new_width);
9521 old_width = new_width;
9524 void NotifyFrontendLogin()