a292a9f0a2e634db80e8b57e2dac8b912868f694
[xboard.git] / xboard.c
1 /*
2  * xboard.c -- X front end for XBoard
3  * $Id: xboard.c,v 2.2 2003/11/06 07:22:14 mann Exp $
4  *
5  * Copyright 1991 by Digital Equipment Corporation, Maynard,
6  * Massachusetts.  Enhancements Copyright
7  * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
8  * Foundation, Inc.
9  *
10  * The following terms apply to Digital Equipment Corporation's copyright
11  * interest in XBoard:
12  * ------------------------------------------------------------------------
13  * All Rights Reserved
14  *
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.
22  *
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
29  * SOFTWARE.
30  * ------------------------------------------------------------------------
31  *
32  * The following terms apply to the enhanced version of XBoard
33  * distributed by the Free Software Foundation:
34  * ------------------------------------------------------------------------
35  *
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.
40  *
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.
45  *
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/.  *
48  *
49  *------------------------------------------------------------------------
50  ** See the file ChangeLog for a revision history.  */
51
52 #include "config.h"
53
54 #include <stdio.h>
55 #include <ctype.h>
56 #include <signal.h>
57 #include <errno.h>
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #include <pwd.h>
61
62 #if !OMIT_SOCKETS
63 # if HAVE_SYS_SOCKET_H
64 #  include <sys/socket.h>
65 #  include <netinet/in.h>
66 #  include <netdb.h>
67 # else /* not HAVE_SYS_SOCKET_H */
68 #  if HAVE_LAN_SOCKET_H
69 #   include <lan/socket.h>
70 #   include <lan/in.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 */
77
78 #if STDC_HEADERS
79 # include <stdlib.h>
80 # include <string.h>
81 #else /* not STDC_HEADERS */
82 extern char *getenv();
83 # if HAVE_STRING_H
84 #  include <string.h>
85 # else /* not HAVE_STRING_H */
86 #  include <strings.h>
87 # endif /* not HAVE_STRING_H */
88 #endif /* not STDC_HEADERS */
89
90 #if HAVE_SYS_FCNTL_H
91 # include <sys/fcntl.h>
92 #else /* not HAVE_SYS_FCNTL_H */
93 # if HAVE_FCNTL_H
94 #  include <fcntl.h>
95 # endif /* HAVE_FCNTL_H */
96 #endif /* not HAVE_SYS_FCNTL_H */
97
98 #if HAVE_SYS_SYSTEMINFO_H
99 # include <sys/systeminfo.h>
100 #endif /* HAVE_SYS_SYSTEMINFO_H */
101
102 #if TIME_WITH_SYS_TIME
103 # include <sys/time.h>
104 # include <time.h>
105 #else
106 # if HAVE_SYS_TIME_H
107 #  include <sys/time.h>
108 # else
109 #  include <time.h>
110 # endif
111 #endif
112
113 #if HAVE_UNISTD_H
114 # include <unistd.h>
115 #endif
116
117 #if HAVE_SYS_WAIT_H
118 # include <sys/wait.h>
119 #endif
120
121 #if HAVE_DIRENT_H
122 # include <dirent.h>
123 # define NAMLEN(dirent) strlen((dirent)->d_name)
124 # define HAVE_DIR_STRUCT
125 #else
126 # define dirent direct
127 # define NAMLEN(dirent) (dirent)->d_namlen
128 # if HAVE_SYS_NDIR_H
129 #  include <sys/ndir.h>
130 #  define HAVE_DIR_STRUCT
131 # endif
132 # if HAVE_SYS_DIR_H
133 #  include <sys/dir.h>
134 #  define HAVE_DIR_STRUCT
135 # endif
136 # if HAVE_NDIR_H
137 #  include <ndir.h>
138 #  define HAVE_DIR_STRUCT
139 # endif
140 #endif
141
142 #include <X11/Intrinsic.h>
143 #include <X11/StringDefs.h>
144 #include <X11/Shell.h>
145 #include <X11/cursorfont.h>
146 #include <X11/Xatom.h>
147 #if USE_XAW3D
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>
159 #else
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>
171 #endif
172
173 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
174 #include "common.h"
175
176 #if HAVE_LIBXPM
177 #include <X11/xpm.h>
178 #include "pixmaps/pixmaps.h"
179 #define IMAGE_EXT "xpm"
180 #else
181 #define IMAGE_EXT "xim"
182 #include "bitmaps/bitmaps.h"
183 #endif
184
185 #include "bitmaps/icon_white.bm"
186 #include "bitmaps/icon_black.bm"
187 #include "bitmaps/checkmark.bm"
188
189 #include "frontend.h"
190 #include "backend.h"
191 #include "moves.h"
192 #include "xboard.h"
193 #include "childio.h"
194 #include "xgamelist.h"
195 #include "xhistory.h"
196 #include "xedittags.h"
197 #include "gettext.h"
198
199 // must be moved to xengineoutput.h
200
201 void EngineOutputProc P((Widget w, XEvent *event,
202  String *prms, Cardinal *nprms));
203
204 void EngineOutputPopDown();
205
206
207 #ifdef __EMX__
208 #ifndef HAVE_USLEEP
209 #define HAVE_USLEEP
210 #endif
211 #define usleep(t)   _sleep2(((t)+500)/1000)
212 #endif
213
214 #ifdef ENABLE_NLS
215 # define  _(s) gettext (s)
216 # define N_(s) gettext_noop (s)
217 #else
218 # define  _(s) (s)
219 # define N_(s)  s
220 #endif
221
222 typedef struct {
223     String string;
224     XtActionProc proc;
225 } MenuItem;
226
227 typedef struct {
228     String name;
229     MenuItem *mi;
230 } Menu;
231
232 int main P((int argc, char **argv));
233 RETSIGTYPE CmailSigHandler P((int sig));
234 RETSIGTYPE IntSigHandler P((int sig));
235 void CreateGCs P((void));
236 void CreateXIMPieces P((void));
237 void CreateXPMPieces P((void));
238 void CreatePieces P((void));
239 void CreatePieceMenus P((void));
240 Widget CreateMenuBar P((Menu *mb));
241 Widget CreateButtonBar P ((MenuItem *mi));
242 char *FindFont P((char *pattern, int targetPxlSize));
243 void PieceMenuPopup P((Widget w, XEvent *event,
244                        String *params, Cardinal *num_params));
245 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
246 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
247 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
248                    u_int wreq, u_int hreq));
249 void CreateGrid P((void));
250 int EventToSquare P((int x, int limit));
251 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
252 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
253 void HandleUserMove P((Widget w, XEvent *event,
254                      String *prms, Cardinal *nprms));
255 void AnimateUserMove P((Widget w, XEvent * event,
256                      String * params, Cardinal * nParams));
257 void WhiteClock P((Widget w, XEvent *event,
258                    String *prms, Cardinal *nprms));
259 void BlackClock P((Widget w, XEvent *event,
260                    String *prms, Cardinal *nprms));
261 void DrawPositionProc P((Widget w, XEvent *event,
262                      String *prms, Cardinal *nprms));
263 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
264                      Board board));
265 void CommentPopUp P((char *title, char *label));
266 void CommentPopDown P((void));
267 void CommentCallback P((Widget w, XtPointer client_data,
268                         XtPointer call_data));
269 void ICSInputBoxPopUp P((void));
270 void ICSInputBoxPopDown P((void));
271 void FileNamePopUp P((char *label, char *def,
272                       FileProc proc, char *openMode));
273 void FileNamePopDown P((void));
274 void FileNameCallback P((Widget w, XtPointer client_data,
275                          XtPointer call_data));
276 void FileNameAction P((Widget w, XEvent *event,
277                        String *prms, Cardinal *nprms));
278 void AskQuestionReplyAction P((Widget w, XEvent *event,
279                           String *prms, Cardinal *nprms));
280 void AskQuestionProc P((Widget w, XEvent *event,
281                           String *prms, Cardinal *nprms));
282 void AskQuestionPopDown P((void));
283 void PromotionPopUp P((void));
284 void PromotionPopDown P((void));
285 void PromotionCallback P((Widget w, XtPointer client_data,
286                           XtPointer call_data));
287 void EditCommentPopDown P((void));
288 void EditCommentCallback P((Widget w, XtPointer client_data,
289                             XtPointer call_data));
290 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
291 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
294                          Cardinal *nprms));
295 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
296                          Cardinal *nprms));
297 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
298                        Cardinal *nprms));
299 void LoadPositionProc P((Widget w, XEvent *event,
300                          String *prms, Cardinal *nprms));
301 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
302                          Cardinal *nprms));
303 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
304                          Cardinal *nprms));
305 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
306                        Cardinal *nprms));
307 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
308                          Cardinal *nprms));
309 void PastePositionProc P((Widget w, XEvent *event, String *prms,
310                           Cardinal *nprms));
311 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
312 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
313 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void SavePositionProc P((Widget w, XEvent *event,
315                          String *prms, Cardinal *nprms));
316 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
318                             Cardinal *nprms));
319 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
320 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
321 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
322                          Cardinal *nprms));
323 void MachineWhiteProc P((Widget w, XEvent *event,
324                          String *prms, Cardinal *nprms));
325 void AnalyzeModeProc P((Widget w, XEvent *event,
326                          String *prms, Cardinal *nprms));
327 void AnalyzeFileProc P((Widget w, XEvent *event,
328                          String *prms, Cardinal *nprms));
329 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
330                         Cardinal *nprms));
331 void IcsClientProc P((Widget w, XEvent *event, String *prms,
332                       Cardinal *nprms));
333 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void EditPositionProc P((Widget w, XEvent *event,
335                          String *prms, Cardinal *nprms));
336 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EditCommentProc P((Widget w, XEvent *event,
338                         String *prms, Cardinal *nprms));
339 void IcsInputBoxProc P((Widget w, XEvent *event,
340                         String *prms, Cardinal *nprms));
341 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
342 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
349 void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
350 void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
351 void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void StopObservingProc P((Widget w, XEvent *event, String *prms,
354                           Cardinal *nprms));
355 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
356                           Cardinal *nprms));
357 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
360 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
363                          Cardinal *nprms));
364 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
365                         Cardinal *nprms));
366 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
368                         Cardinal *nprms));
369 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
370                          Cardinal *nprms));
371 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
372                          Cardinal *nprms));
373 void AutocommProc P((Widget w, XEvent *event, String *prms,
374                      Cardinal *nprms));
375 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
376 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void AutobsProc P((Widget w, XEvent *event, String *prms,
378                         Cardinal *nprms));
379 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
380 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
383                        Cardinal *nprms));
384 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
385 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
386                         Cardinal *nprms));
387 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
388                               Cardinal *nprms));
389 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
390                               Cardinal *nprms));
391 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
394                          Cardinal *nprms));
395 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
396                          Cardinal *nprms));
397 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
398                            Cardinal *nprms));
399 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
400                         Cardinal *nprms));
401 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
402                              Cardinal *nprms));
403 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
406                        Cardinal *nprms));
407 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
408                          Cardinal *nprms));
409 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
410                          Cardinal *nprms));
411 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
412                           Cardinal *nprms));
413 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
414 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
415 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
416 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
417 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
418 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
419 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
420 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
421 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
422 void DisplayMove P((int moveNumber));
423 void DisplayTitle P((char *title));
424 void ICSInitScript P((void));
425 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
426 void ErrorPopUp P((char *title, char *text, int modal));
427 void ErrorPopDown P((void));
428 static char *ExpandPathName P((char *path));
429 static void CreateAnimVars P((void));
430 static void DragPieceBegin P((int x, int y));
431 static void DragPieceMove P((int x, int y));
432 static void DragPieceEnd P((int x, int y));
433 static void DrawDragPiece P((void));
434 char *ModeToWidgetName P((GameMode mode));
435 void EngineOutputUpdate( FrontEndProgramStats * stats );
436 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
437 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
438 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
439 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
440 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
441 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
442 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
443 void ShufflePopDown P(());
444 void EnginePopDown P(());
445 void UciPopDown P(());
446 void TimeControlPopDown P(());
447 void NewVariantPopDown P(());
448 void SettingsPopDown P(());
449 /*
450 * XBoard depends on Xt R4 or higher
451 */
452 int xtVersion = XtSpecificationRelease;
453
454 int xScreen;
455 Display *xDisplay;
456 Window xBoardWindow;
457 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
458   jailSquareColor, highlightSquareColor, premoveHighlightColor;
459 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
460   bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
461   wjPieceGC, bjPieceGC, prelineGC, countGC;
462 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
463 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
464   whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
465   commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
466   menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
467   ICSInputShell, fileNameShell, askQuestionShell;
468 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
469 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
470 Font clockFontID, coordFontID, countFontID;
471 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
472 XtAppContext appContext;
473 char *layoutName;
474 char *oldICSInteractionTitle;
475
476 FileProc fileProc;
477 char *fileOpenMode;
478 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
479
480 Position commentX = -1, commentY = -1;
481 Dimension commentW, commentH;
482
483 int squareSize, smallLayout = 0, tinyLayout = 0,
484   marginW, marginH, // [HGM] for run-time resizing
485   fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
486   ICSInputBoxUp = False, askQuestionUp = False,
487   filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
488   editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
489 Pixel timerForegroundPixel, timerBackgroundPixel;
490 Pixel buttonForegroundPixel, buttonBackgroundPixel;
491 char *chessDir, *programName, *programVersion,
492   *gameCopyFilename, *gamePasteFilename;
493
494 #define SOLID 0
495 #define OUTLINE 1
496 Pixmap pieceBitmap[2][(int)BlackPawn];
497 Pixmap xpmPieceBitmap[4][(int)BlackPawn];       /* LL, LD, DL, DD */
498 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
499 int useImages, useImageSqs;
500 XImage *ximPieceBitmap[4][(int)BlackPawn];      /* LL, LD, DL, DD */
501 Pixmap ximMaskPm[(int)BlackPawn];            /* clipmasks, used for XIM pieces */
502 XImage *ximLightSquare, *ximDarkSquare;
503 XImage *xim_Cross;
504
505 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
506 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
507
508 #define White(piece) ((int)(piece) < (int)BlackPawn)
509
510 /* Variables for doing smooth animation. This whole thing
511    would be much easier if the board was double-buffered,
512    but that would require a fairly major rewrite.       */
513
514 typedef struct {
515         Pixmap  saveBuf;
516         Pixmap  newBuf;
517         GC      blitGC, pieceGC, outlineGC;
518         XPoint  startSquare, prevFrame, mouseDelta;
519         int     startColor;
520         int     dragPiece;
521         Boolean dragActive;
522         int     startBoardX, startBoardY;
523     } AnimState;
524
525 /* There can be two pieces being animated at once: a player
526    can begin dragging a piece before the remote opponent has moved. */
527
528 static AnimState game, player;
529
530 /* Bitmaps for use as masks when drawing XPM pieces.
531    Need one for each black and white piece.             */
532 static Pixmap xpmMask[BlackKing + 1];
533
534 /* This magic number is the number of intermediate frames used
535    in each half of the animation. For short moves it's reduced
536    by 1. The total number of frames will be factor * 2 + 1.  */
537 #define kFactor    4
538
539 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
540
541 MenuItem fileMenu[] = {
542     {N_("New Game"), ResetProc},
543     {N_("New Shuffle Game ..."), ShuffleMenuProc},
544     {N_("New Variant ..."), NewVariantProc},      // [HGM] variant: not functional yet
545     {"----", NothingProc},
546     {N_("Load Game"), LoadGameProc},
547     {N_("Load Next Game"), LoadNextGameProc},
548     {N_("Load Previous Game"), LoadPrevGameProc},
549     {N_("Reload Same Game"), ReloadGameProc},
550     {N_("Save Game"), SaveGameProc},
551     {"----", NothingProc},
552     {N_("Copy Game"), CopyGameProc},
553     {N_("Paste Game"), PasteGameProc},
554     {"----", NothingProc},
555     {N_("Load Position"), LoadPositionProc},
556     {N_("Load Next Position"), LoadNextPositionProc},
557     {N_("Load Previous Position"), LoadPrevPositionProc},
558     {N_("Reload Same Position"), ReloadPositionProc},
559     {N_("Save Position"), SavePositionProc},
560     {"----", NothingProc},
561     {N_("Copy Position"), CopyPositionProc},
562     {N_("Paste Position"), PastePositionProc},
563     {"----", NothingProc},
564     {N_("Mail Move"), MailMoveProc},
565     {N_("Reload CMail Message"), ReloadCmailMsgProc},
566     {"----", NothingProc},
567     {N_("Exit"), QuitProc},
568     {NULL, NULL}
569 };
570
571 MenuItem modeMenu[] = {
572     {N_("Machine White"), MachineWhiteProc},
573     {N_("Machine Black"), MachineBlackProc},
574     {N_("Two Machines"), TwoMachinesProc},
575     {N_("Analysis Mode"), AnalyzeModeProc},
576     {N_("Analyze File"), AnalyzeFileProc },
577     {N_("ICS Client"), IcsClientProc},
578     {N_("Edit Game"), EditGameProc},
579     {N_("Edit Position"), EditPositionProc},
580     {N_("Training"), TrainingProc},
581     {"----", NothingProc},
582     {N_("Show Engine Output"), EngineOutputProc},
583     {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
584     {N_("Show Game List"), ShowGameListProc},
585     {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
586     {"----", NothingProc},
587     {N_("Edit Tags"), EditTagsProc},
588     {N_("Edit Comment"), EditCommentProc},
589     {N_("ICS Input Box"), IcsInputBoxProc},
590     {N_("Pause"), PauseProc},
591     {NULL, NULL}
592 };
593
594 MenuItem actionMenu[] = {
595     {N_("Accept"), AcceptProc},
596     {N_("Decline"), DeclineProc},
597     {N_("Rematch"), RematchProc},
598     {"----", NothingProc},
599     {N_("Call Flag"), CallFlagProc},
600     {N_("Draw"), DrawProc},
601     {N_("Adjourn"), AdjournProc},
602     {N_("Abort"), AbortProc},
603     {N_("Resign"), ResignProc},
604     {"----", NothingProc},
605     {N_("Stop Observing"), StopObservingProc},
606     {N_("Stop Examining"), StopExaminingProc},
607     {"----", NothingProc},
608     {N_("Adjudicate to White"), AdjuWhiteProc},
609     {N_("Adjudicate to Black"), AdjuBlackProc},
610     {N_("Adjudicate Draw"), AdjuDrawProc},
611     {NULL, NULL}
612 };
613
614 MenuItem stepMenu[] = {
615     {N_("Backward"), BackwardProc},
616     {N_("Forward"), ForwardProc},
617     {N_("Back to Start"), ToStartProc},
618     {N_("Forward to End"), ToEndProc},
619     {N_("Revert"), RevertProc},
620     {N_("Truncate Game"), TruncateGameProc},
621     {"----", NothingProc},
622     {N_("Move Now"), MoveNowProc},
623     {N_("Retract Move"), RetractMoveProc},
624     {NULL, NULL}
625 };
626
627 MenuItem optionsMenu[] = {
628     {N_("Flip View"), FlipViewProc},
629     {"----", NothingProc},
630     {N_("Adjudications ..."), EngineMenuProc},
631     {N_("General Settings ..."), UciMenuProc},
632     {N_("Engine #1 Settings ..."), FirstSettingsProc},
633     {N_("Engine #2 Settings ..."), SecondSettingsProc},
634     {N_("Time Control ..."), TimeControlProc},
635     {"----", NothingProc},
636     {N_("Always Queen"), AlwaysQueenProc},
637     {N_("Animate Dragging"), AnimateDraggingProc},
638     {N_("Animate Moving"), AnimateMovingProc},
639     {N_("Auto Comment"), AutocommProc},
640     {N_("Auto Flag"), AutoflagProc},
641     {N_("Auto Flip View"), AutoflipProc},
642     {N_("Auto Observe"), AutobsProc},
643     {N_("Auto Raise Board"), AutoraiseProc},
644     {N_("Auto Save"), AutosaveProc},
645     {N_("Blindfold"), BlindfoldProc},
646     {N_("Flash Moves"), FlashMovesProc},
647     {N_("Get Move List"), GetMoveListProc},
648 #if HIGHDRAG
649     {N_("Highlight Dragging"), HighlightDraggingProc},
650 #endif
651     {N_("Highlight Last Move"), HighlightLastMoveProc},
652     {N_("Move Sound"), MoveSoundProc},
653     {N_("ICS Alarm"), IcsAlarmProc},
654     {N_("Old Save Style"), OldSaveStyleProc},
655     {N_("Periodic Updates"), PeriodicUpdatesProc},
656     {N_("Ponder Next Move"), PonderNextMoveProc},
657     {N_("Popup Exit Message"), PopupExitMessageProc},
658     {N_("Popup Move Errors"), PopupMoveErrorsProc},
659     {N_("Premove"), PremoveProc},
660     {N_("Quiet Play"), QuietPlayProc},
661     {N_("Show Coords"), ShowCoordsProc},
662     {N_("Hide Thinking"), HideThinkingProc},
663     {N_("Test Legality"), TestLegalityProc},
664     {NULL, NULL}
665 };
666
667 MenuItem helpMenu[] = {
668     {N_("Info XBoard"), InfoProc},
669     {N_("Man XBoard"), ManProc},
670     {"----", NothingProc},
671     {N_("Hint"), HintProc},
672     {N_("Book"), BookProc},
673     {"----", NothingProc},
674     {N_("About XBoard"), AboutProc},
675     {NULL, NULL}
676 };
677
678 Menu menuBar[] = {
679     {N_("File"), fileMenu},
680     {N_("Mode"), modeMenu},
681     {N_("Action"), actionMenu},
682     {N_("Step"), stepMenu},
683     {N_("Options"), optionsMenu},
684     {N_("Help"), helpMenu},
685     {NULL, NULL}
686 };
687
688 #define PAUSE_BUTTON N_("P")
689 MenuItem buttonBar[] = {
690     {"<<", ToStartProc},
691     {"<", BackwardProc},
692     {PAUSE_BUTTON, PauseProc},
693     {">", ForwardProc},
694     {">>", ToEndProc},
695     {NULL, NULL}
696 };
697
698 #define PIECE_MENU_SIZE 11
699 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
700     { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
701       N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
702     { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
703       N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
704 };
705 /* must be in same order as PieceMenuStrings! */
706 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
707     { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
708         WhiteRook, WhiteQueen, WhiteKing,
709         (ChessSquare) 0, EmptySquare, ClearBoard },
710     { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
711         BlackRook, BlackQueen, BlackKing,
712         (ChessSquare) 0, EmptySquare, ClearBoard },
713 };
714
715 #define DROP_MENU_SIZE 6
716 String dropMenuStrings[DROP_MENU_SIZE] = {
717     "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
718   };
719 /* must be in same order as PieceMenuStrings! */
720 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
721     (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
722     WhiteRook, WhiteQueen
723 };
724
725 typedef struct {
726     char piece;
727     char* widget;
728 } DropMenuEnables;
729
730 DropMenuEnables dmEnables[] = {
731     { 'P', "Pawn" },
732     { 'N', "Knight" },
733     { 'B', "Bishop" },
734     { 'R', "Rook" },
735     { 'Q', "Queen" }
736 };
737
738 Arg shellArgs[] = {
739     { XtNwidth, 0 },
740     { XtNheight, 0 },
741     { XtNminWidth, 0 },
742     { XtNminHeight, 0 },
743     { XtNmaxWidth, 0 },
744     { XtNmaxHeight, 0 }
745 };
746
747 Arg layoutArgs[] = {
748     { XtNborderWidth, 0 },
749     { XtNdefaultDistance, 0 },
750 };
751
752 Arg formArgs[] = {
753     { XtNborderWidth, 0 },
754     { XtNresizable, (XtArgVal) True },
755 };
756
757 Arg boardArgs[] = {
758     { XtNborderWidth, 0 },
759     { XtNwidth, 0 },
760     { XtNheight, 0 }
761 };
762
763 Arg titleArgs[] = {
764     { XtNjustify, (XtArgVal) XtJustifyRight },
765     { XtNlabel, (XtArgVal) "..." },
766     { XtNresizable, (XtArgVal) True },
767     { XtNresize, (XtArgVal) False }
768 };
769
770 Arg messageArgs[] = {
771     { XtNjustify, (XtArgVal) XtJustifyLeft },
772     { XtNlabel, (XtArgVal) "..." },
773     { XtNresizable, (XtArgVal) True },
774     { XtNresize, (XtArgVal) False }
775 };
776
777 Arg timerArgs[] = {
778     { XtNborderWidth, 0 },
779     { XtNjustify, (XtArgVal) XtJustifyLeft }
780 };
781
782 XtResource clientResources[] = {
783     { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
784         XtOffset(AppDataPtr, whitePieceColor), XtRString,
785         WHITE_PIECE_COLOR },
786     { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
787         XtOffset(AppDataPtr, blackPieceColor), XtRString,
788         BLACK_PIECE_COLOR },
789     { "lightSquareColor", "lightSquareColor", XtRString,
790         sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
791         XtRString, LIGHT_SQUARE_COLOR },
792     { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
793         XtOffset(AppDataPtr, darkSquareColor), XtRString,
794         DARK_SQUARE_COLOR },
795     { "highlightSquareColor", "highlightSquareColor", XtRString,
796         sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
797         XtRString, HIGHLIGHT_SQUARE_COLOR },
798     { "premoveHighlightColor", "premoveHighlightColor", XtRString,
799         sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
800         XtRString, PREMOVE_HIGHLIGHT_COLOR },
801     { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
802         XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
803         (XtPointer) MOVES_PER_SESSION },
804     { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
805         XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
806         (XtPointer) TIME_INCREMENT },
807     { "initString", "initString", XtRString, sizeof(String),
808         XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
809     { "secondInitString", "secondInitString", XtRString, sizeof(String),
810         XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
811     { "firstComputerString", "firstComputerString", XtRString,
812         sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
813       COMPUTER_STRING },
814     { "secondComputerString", "secondComputerString", XtRString,
815         sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
816       COMPUTER_STRING },
817     { "firstChessProgram", "firstChessProgram", XtRString,
818         sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
819         XtRString, FIRST_CHESS_PROGRAM },
820     { "secondChessProgram", "secondChessProgram", XtRString,
821         sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
822         XtRString, SECOND_CHESS_PROGRAM },
823     { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
824         sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
825         XtRImmediate, (XtPointer) False },
826     { "noChessProgram", "noChessProgram", XtRBoolean,
827         sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
828         XtRImmediate, (XtPointer) False },
829     { "firstHost", "firstHost", XtRString, sizeof(String),
830         XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
831     { "secondHost", "secondHost", XtRString, sizeof(String),
832         XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
833     { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
834         XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
835     { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
836         XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
837     { "bitmapDirectory", "bitmapDirectory", XtRString,
838         sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
839         XtRString, "" },
840     { "remoteShell", "remoteShell", XtRString, sizeof(String),
841         XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
842     { "remoteUser", "remoteUser", XtRString, sizeof(String),
843         XtOffset(AppDataPtr, remoteUser), XtRString, "" },
844     { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
845         XtOffset(AppDataPtr, timeDelay), XtRString,
846         (XtPointer) TIME_DELAY_QUOTE },
847     { "timeControl", "timeControl", XtRString, sizeof(String),
848         XtOffset(AppDataPtr, timeControl), XtRString,
849         (XtPointer) TIME_CONTROL },
850     { "internetChessServerMode", "internetChessServerMode",
851         XtRBoolean, sizeof(Boolean),
852         XtOffset(AppDataPtr, icsActive), XtRImmediate,
853         (XtPointer) False },
854     { "internetChessServerHost", "internetChessServerHost",
855         XtRString, sizeof(String),
856         XtOffset(AppDataPtr, icsHost),
857         XtRString, (XtPointer) ICS_HOST },
858     { "internetChessServerPort", "internetChessServerPort",
859         XtRString, sizeof(String),
860         XtOffset(AppDataPtr, icsPort), XtRString,
861         (XtPointer) ICS_PORT },
862     { "internetChessServerCommPort", "internetChessServerCommPort",
863         XtRString, sizeof(String),
864         XtOffset(AppDataPtr, icsCommPort), XtRString,
865         ICS_COMM_PORT },
866     { "internetChessServerLogonScript", "internetChessServerLogonScript",
867         XtRString, sizeof(String),
868         XtOffset(AppDataPtr, icsLogon), XtRString,
869         ICS_LOGON },
870     { "internetChessServerHelper", "internetChessServerHelper",
871         XtRString, sizeof(String),
872         XtOffset(AppDataPtr, icsHelper), XtRString, "" },
873     { "internetChessServerInputBox", "internetChessServerInputBox",
874         XtRBoolean, sizeof(Boolean),
875         XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
876         (XtPointer) False },
877     { "icsAlarm", "icsAlarm",
878         XtRBoolean, sizeof(Boolean),
879         XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
880         (XtPointer) True },
881     { "icsAlarmTime", "icsAlarmTime",
882         XtRInt, sizeof(int),
883         XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
884         (XtPointer) 5000 },
885     { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
886         XtOffset(AppDataPtr, useTelnet), XtRImmediate,
887         (XtPointer) False },
888     { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
889         XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
890     { "gateway", "gateway", XtRString, sizeof(String),
891         XtOffset(AppDataPtr, gateway), XtRString, "" },
892     { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
893         XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
894     { "loadGameIndex", "loadGameIndex",
895         XtRInt, sizeof(int),
896         XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
897         (XtPointer) 0 },
898     { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
899         XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
900     { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
901         sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
902         XtRImmediate, (XtPointer) True },
903     { "autoSaveGames", "autoSaveGames", XtRBoolean,
904         sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
905         XtRImmediate, (XtPointer) False },
906     { "blindfold", "blindfold", XtRBoolean,
907         sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
908         XtRImmediate, (XtPointer) False },
909     { "loadPositionFile", "loadPositionFile", XtRString,
910         sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
911         XtRString, "" },
912     { "loadPositionIndex", "loadPositionIndex",
913         XtRInt, sizeof(int),
914         XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
915         (XtPointer) 1 },
916     { "savePositionFile", "savePositionFile", XtRString,
917         sizeof(String), XtOffset(AppDataPtr, savePositionFile),
918         XtRString, "" },
919     { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
920         XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
921     { "matchGames", "matchGames", XtRInt, sizeof(int),
922         XtOffset(AppDataPtr, matchGames), XtRImmediate,
923         (XtPointer) 0 },
924     { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
925         XtOffset(AppDataPtr, monoMode), XtRImmediate,
926         (XtPointer) False },
927     { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
928         XtOffset(AppDataPtr, debugMode), XtRImmediate,
929         (XtPointer) False },
930     { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
931         XtOffset(AppDataPtr, clockMode), XtRImmediate,
932         (XtPointer) True },
933     { "boardSize", "boardSize", XtRString, sizeof(String),
934         XtOffset(AppDataPtr, boardSize), XtRString, "" },
935     { "searchTime", "searchTime", XtRString, sizeof(String),
936         XtOffset(AppDataPtr, searchTime), XtRString,
937         (XtPointer) "" },
938     { "searchDepth", "searchDepth", XtRInt, sizeof(int),
939         XtOffset(AppDataPtr, searchDepth), XtRImmediate,
940         (XtPointer) 0 },
941     { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
942         XtOffset(AppDataPtr, showCoords), XtRImmediate,
943         (XtPointer) False },
944     { "showJail", "showJail", XtRInt, sizeof(int),
945         XtOffset(AppDataPtr, showJail), XtRImmediate,
946         (XtPointer) 0 },
947     { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
948         XtOffset(AppDataPtr, showThinking), XtRImmediate,
949         (XtPointer) True },
950     { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
951         XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
952         (XtPointer) True },
953     { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
954         XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
955         (XtPointer) True },
956     { "clockFont", "clockFont", XtRString, sizeof(String),
957         XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
958     { "coordFont", "coordFont", XtRString, sizeof(String),
959         XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
960     { "font", "font", XtRString, sizeof(String),
961         XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
962     { "ringBellAfterMoves", "ringBellAfterMoves",
963         XtRBoolean, sizeof(Boolean),
964         XtOffset(AppDataPtr, ringBellAfterMoves),
965         XtRImmediate, (XtPointer) False },
966     { "autoCallFlag", "autoCallFlag", XtRBoolean,
967         sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
968         XtRImmediate, (XtPointer) False },
969     { "autoFlipView", "autoFlipView", XtRBoolean,
970         sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
971         XtRImmediate, (XtPointer) True },
972     { "autoObserve", "autoObserve", XtRBoolean,
973         sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
974         XtRImmediate, (XtPointer) False },
975     { "autoComment", "autoComment", XtRBoolean,
976         sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
977         XtRImmediate, (XtPointer) False },
978     { "getMoveList", "getMoveList", XtRBoolean,
979         sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
980         XtRImmediate, (XtPointer) True },
981 #if HIGHDRAG
982     { "highlightDragging", "highlightDragging", XtRBoolean,
983         sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
984         XtRImmediate, (XtPointer) False },
985 #endif
986     { "highlightLastMove", "highlightLastMove", XtRBoolean,
987         sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
988         XtRImmediate, (XtPointer) False },
989     { "premove", "premove", XtRBoolean,
990         sizeof(Boolean), XtOffset(AppDataPtr, premove),
991         XtRImmediate, (XtPointer) True },
992     { "testLegality", "testLegality", XtRBoolean,
993         sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
994         XtRImmediate, (XtPointer) True },
995     { "flipView", "flipView", XtRBoolean,
996         sizeof(Boolean), XtOffset(AppDataPtr, flipView),
997         XtRImmediate, (XtPointer) False },
998     { "cmail", "cmailGameName", XtRString, sizeof(String),
999         XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1000     { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1001         sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1002         XtRImmediate, (XtPointer) False },
1003     { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1004         sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1005         XtRImmediate, (XtPointer) False },
1006     { "quietPlay", "quietPlay", XtRBoolean,
1007         sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1008         XtRImmediate, (XtPointer) False },
1009     { "titleInWindow", "titleInWindow", XtRBoolean,
1010         sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1011         XtRImmediate, (XtPointer) False },
1012     { "localLineEditing", "localLineEditing", XtRBoolean,
1013         sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1014         XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1015 #ifdef ZIPPY
1016     { "zippyTalk", "zippyTalk", XtRBoolean,
1017         sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1018         XtRImmediate, (XtPointer) ZIPPY_TALK },
1019     { "zippyPlay", "zippyPlay", XtRBoolean,
1020         sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1021         XtRImmediate, (XtPointer) ZIPPY_PLAY },
1022     { "zippyLines", "zippyLines", XtRString, sizeof(String),
1023         XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1024     { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1025         XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1026     { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1027         XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1028     { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1029         XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1030     { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1031         XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1032         ZIPPY_WRONG_PASSWORD },
1033     { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1034         XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1035     { "zippyUseI", "zippyUseI", XtRBoolean,
1036         sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1037         XtRImmediate, (XtPointer) ZIPPY_USE_I },
1038     { "zippyBughouse", "zippyBughouse", XtRInt,
1039         sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1040         XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1041     { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1042         sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1043         XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1044     { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1045         XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1046     { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1047         XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1048     { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1049         sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1050         XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1051     { "zippyAbort", "zippyAbort", XtRBoolean,
1052         sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1053         XtRImmediate, (XtPointer) ZIPPY_ABORT },
1054     { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1055         XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1056     { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1057         XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1058         (XtPointer) ZIPPY_MAX_GAMES },
1059     { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1060         XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1061         (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1062 #endif
1063     { "flashCount", "flashCount", XtRInt, sizeof(int),
1064         XtOffset(AppDataPtr, flashCount), XtRImmediate,
1065         (XtPointer) FLASH_COUNT  },
1066     { "flashRate", "flashRate", XtRInt, sizeof(int),
1067         XtOffset(AppDataPtr, flashRate), XtRImmediate,
1068         (XtPointer) FLASH_RATE },
1069     { "pixmapDirectory", "pixmapDirectory", XtRString,
1070         sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1071         XtRString, "" },
1072     { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1073         XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1074         (XtPointer) MS_LOGIN_DELAY },
1075     { "colorizeMessages", "colorizeMessages", XtRBoolean,
1076         sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1077         XtRImmediate, (XtPointer) False },
1078     { "colorShout", "colorShout", XtRString,
1079         sizeof(String), XtOffset(AppDataPtr, colorShout),
1080         XtRString, COLOR_SHOUT },
1081     { "colorSShout", "colorSShout", XtRString,
1082         sizeof(String), XtOffset(AppDataPtr, colorSShout),
1083         XtRString, COLOR_SSHOUT },
1084     { "colorChannel1", "colorChannel1", XtRString,
1085         sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1086         XtRString, COLOR_CHANNEL1 },
1087     { "colorChannel", "colorChannel", XtRString,
1088         sizeof(String), XtOffset(AppDataPtr, colorChannel),
1089         XtRString, COLOR_CHANNEL },
1090     { "colorKibitz", "colorKibitz", XtRString,
1091         sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1092         XtRString, COLOR_KIBITZ },
1093     { "colorTell", "colorTell", XtRString,
1094         sizeof(String), XtOffset(AppDataPtr, colorTell),
1095         XtRString, COLOR_TELL },
1096     { "colorChallenge", "colorChallenge", XtRString,
1097         sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1098         XtRString, COLOR_CHALLENGE },
1099     { "colorRequest", "colorRequest", XtRString,
1100         sizeof(String), XtOffset(AppDataPtr, colorRequest),
1101         XtRString, COLOR_REQUEST },
1102     { "colorSeek", "colorSeek", XtRString,
1103         sizeof(String), XtOffset(AppDataPtr, colorSeek),
1104         XtRString, COLOR_SEEK },
1105     { "colorNormal", "colorNormal", XtRString,
1106         sizeof(String), XtOffset(AppDataPtr, colorNormal),
1107         XtRString, COLOR_NORMAL },
1108     { "soundProgram", "soundProgram", XtRString,
1109       sizeof(String), XtOffset(AppDataPtr, soundProgram),
1110       XtRString, "play" },
1111     { "soundShout", "soundShout", XtRString,
1112       sizeof(String), XtOffset(AppDataPtr, soundShout),
1113       XtRString, "" },
1114     { "soundSShout", "soundSShout", XtRString,
1115       sizeof(String), XtOffset(AppDataPtr, soundSShout),
1116       XtRString, "" },
1117     { "soundChannel1", "soundChannel1", XtRString,
1118       sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1119       XtRString, "" },
1120     { "soundChannel", "soundChannel", XtRString,
1121       sizeof(String), XtOffset(AppDataPtr, soundChannel),
1122       XtRString, "" },
1123     { "soundKibitz", "soundKibitz", XtRString,
1124       sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1125       XtRString, "" },
1126     { "soundTell", "soundTell", XtRString,
1127       sizeof(String), XtOffset(AppDataPtr, soundTell),
1128       XtRString, "" },
1129     { "soundChallenge", "soundChallenge", XtRString,
1130       sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1131       XtRString, "" },
1132     { "soundRequest", "soundRequest", XtRString,
1133       sizeof(String), XtOffset(AppDataPtr, soundRequest),
1134       XtRString, "" },
1135     { "soundSeek", "soundSeek", XtRString,
1136       sizeof(String), XtOffset(AppDataPtr, soundSeek),
1137       XtRString, "" },
1138     { "soundMove", "soundMove", XtRString,
1139       sizeof(String), XtOffset(AppDataPtr, soundMove),
1140       XtRString, "$" },
1141     { "soundIcsWin", "soundIcsWin", XtRString,
1142       sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1143       XtRString, "" },
1144     { "soundIcsLoss", "soundIcsLoss", XtRString,
1145       sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1146       XtRString, "" },
1147     { "soundIcsDraw", "soundIcsDraw", XtRString,
1148       sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1149       XtRString, "" },
1150     { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1151       sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1152       XtRString, "" },
1153     { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1154       sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1155       XtRString, "$" },
1156     { "reuseFirst", "reuseFirst", XtRBoolean,
1157         sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1158         XtRImmediate, (XtPointer) True },
1159     { "reuseSecond", "reuseSecond", XtRBoolean,
1160         sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1161         XtRImmediate, (XtPointer) True },
1162     { "animateDragging", "animateDragging", XtRBoolean,
1163         sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1164         XtRImmediate, (XtPointer) True },
1165     { "animateMoving", "animateMoving", XtRBoolean,
1166         sizeof(Boolean), XtOffset(AppDataPtr, animate),
1167         XtRImmediate, (XtPointer) True },
1168     { "animateSpeed", "animateSpeed", XtRInt,
1169         sizeof(int), XtOffset(AppDataPtr, animSpeed),
1170         XtRImmediate, (XtPointer)10 },
1171     { "popupExitMessage", "popupExitMessage", XtRBoolean,
1172         sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1173         XtRImmediate, (XtPointer) True },
1174     { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1175         sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1176         XtRImmediate, (XtPointer) False },
1177     { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1178         sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1179         XtRImmediate, (XtPointer)4 },
1180     { "initialMode", "initialMode", XtRString,
1181         sizeof(String), XtOffset(AppDataPtr, initialMode),
1182         XtRImmediate, (XtPointer) "" },
1183     { "variant", "variant", XtRString,
1184         sizeof(String), XtOffset(AppDataPtr, variant),
1185         XtRImmediate, (XtPointer) "normal" },
1186     { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1187         sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1188         XtRImmediate, (XtPointer)PROTOVER },
1189     { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1190         sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1191         XtRImmediate, (XtPointer)PROTOVER },
1192     { "showButtonBar", "showButtonBar", XtRBoolean,
1193         sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1194         XtRImmediate, (XtPointer) True },
1195     {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean,        /* [DM] icsEngineAnalyze */
1196         sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1197         XtRImmediate, (XtPointer) False },
1198     { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1199         sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1200         XtRImmediate, (XtPointer) False },
1201     { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1202         sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1203         XtRImmediate, (XtPointer) False },
1204     { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1205         sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1206         XtRImmediate, (XtPointer) False },
1207     { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1208         sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1209         XtRImmediate, (XtPointer) True },
1210     { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1211         sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1212         XtRImmediate, (XtPointer) 0},
1213     { "pgnEventHeader", "pgnEventHeader", XtRString,
1214         sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1215         XtRImmediate, (XtPointer) "Computer Chess Game" },
1216     { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1217         sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1218         XtRImmediate, (XtPointer) -1},
1219
1220     // [HGM] 4.3.xx options
1221     { "boardWidth", "boardWidth", XtRInt,
1222         sizeof(int), XtOffset(AppDataPtr, NrFiles),
1223         XtRImmediate, (XtPointer) -1},
1224     { "boardHeight", "boardHeight", XtRInt,
1225         sizeof(int), XtOffset(AppDataPtr, NrRanks),
1226         XtRImmediate, (XtPointer) -1},
1227     { "matchPause", "matchPause", XtRInt,
1228         sizeof(int), XtOffset(AppDataPtr, matchPause),
1229         XtRImmediate, (XtPointer) 10000},
1230     { "holdingsSize", "holdingsSize", XtRInt,
1231         sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1232         XtRImmediate, (XtPointer) -1},
1233     { "flipBlack", "flipBlack", XtRBoolean,
1234         sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1235         XtRImmediate, (XtPointer) False},
1236     { "allWhite", "allWhite", XtRBoolean,
1237         sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1238         XtRImmediate, (XtPointer) False},
1239     { "pieceToCharTable", "pieceToCharTable", XtRString,
1240         sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1241         XtRImmediate, (XtPointer) 0},
1242     { "alphaRank", "alphaRank", XtRBoolean,
1243         sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1244         XtRImmediate, (XtPointer) False},
1245     { "testClaims", "testClaims", XtRBoolean,
1246         sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1247         XtRImmediate, (XtPointer) True},
1248     { "checkMates", "checkMates", XtRBoolean,
1249         sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1250         XtRImmediate, (XtPointer) True},
1251     { "materialDraws", "materialDraws", XtRBoolean,
1252         sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1253         XtRImmediate, (XtPointer) True},
1254     { "trivialDraws", "trivialDraws", XtRBoolean,
1255         sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1256         XtRImmediate, (XtPointer) False},
1257     { "ruleMoves", "ruleMoves", XtRInt,
1258         sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1259         XtRImmediate, (XtPointer) 51},
1260     { "repeatsToDraw", "repeatsToDraw", XtRInt,
1261         sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1262         XtRImmediate, (XtPointer) 6},
1263     { "engineDebugOutput", "engineDebugOutput", XtRInt,
1264         sizeof(int), XtOffset(AppDataPtr, engineComments),
1265         XtRImmediate, (XtPointer) 1},
1266     { "userName", "userName", XtRString,
1267         sizeof(int), XtOffset(AppDataPtr, userName),
1268         XtRImmediate, (XtPointer) 0},
1269     { "autoKibitz", "autoKibitz", XtRBoolean,
1270         sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1271         XtRImmediate, (XtPointer) False},
1272     { "firstTimeOdds", "firstTimeOdds", XtRInt,
1273         sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1274         XtRImmediate, (XtPointer) 1},
1275     { "secondTimeOdds", "secondTimeOdds", XtRInt,
1276         sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1277         XtRImmediate, (XtPointer) 1},
1278     { "timeOddsMode", "timeOddsMode", XtRInt,
1279         sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1280         XtRImmediate, (XtPointer) 0},
1281     { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1282         sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1283         XtRImmediate, (XtPointer) 1},
1284     { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1285         sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1286         XtRImmediate, (XtPointer) 1},
1287     { "firstNPS", "firstNPS", XtRInt,
1288         sizeof(int), XtOffset(AppDataPtr, firstNPS),
1289         XtRImmediate, (XtPointer) -1},
1290     { "secondNPS", "secondNPS", XtRInt,
1291         sizeof(int), XtOffset(AppDataPtr, secondNPS),
1292         XtRImmediate, (XtPointer) -1},
1293     { "serverMoves", "serverMoves", XtRString,
1294         sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1295         XtRImmediate, (XtPointer) 0},
1296     { "serverPause", "serverPause", XtRInt,
1297         sizeof(int), XtOffset(AppDataPtr, serverPause),
1298         XtRImmediate, (XtPointer) 0},
1299     { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1300         sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1301         XtRImmediate, (XtPointer) False},
1302     { "userName", "userName", XtRString,
1303         sizeof(String), XtOffset(AppDataPtr, userName),
1304         XtRImmediate, (XtPointer) 0},
1305     { "egtFormats", "egtFormats", XtRString,
1306         sizeof(String), XtOffset(AppDataPtr, egtFormats),
1307         XtRImmediate, (XtPointer) 0},
1308     { "rewindIndex", "rewindIndex", XtRInt,
1309         sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1310         XtRImmediate, (XtPointer) 0},
1311     { "sameColorGames", "sameColorGames", XtRInt,
1312         sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1313         XtRImmediate, (XtPointer) 0},
1314     { "smpCores", "smpCores", XtRInt,
1315         sizeof(int), XtOffset(AppDataPtr, smpCores),
1316         XtRImmediate, (XtPointer) 1},
1317     { "niceEngines", "niceEngines", XtRInt,
1318         sizeof(int), XtOffset(AppDataPtr, niceEngines),
1319         XtRImmediate, (XtPointer) 0},
1320     { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1321         sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1322         XtRImmediate, (XtPointer) "xboard.debug"},
1323     { "engineDebugOutput", "engineDebugOutput", XtRInt,
1324         sizeof(int), XtOffset(AppDataPtr, engineComments),
1325         XtRImmediate, (XtPointer) 0},
1326     { "noGUI", "noGUI", XtRBoolean,
1327         sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1328         XtRImmediate, (XtPointer) 0},
1329     { "firstOptions", "firstOptions", XtRString,
1330         sizeof(String), XtOffset(AppDataPtr, firstOptions),
1331         XtRImmediate, (XtPointer) "" },
1332     { "secondOptions", "secondOptions", XtRString,
1333         sizeof(String), XtOffset(AppDataPtr, secondOptions),
1334         XtRImmediate, (XtPointer) "" },
1335
1336     // [HGM] Winboard_x UCI options
1337     { "firstIsUCI", "firstIsUCI", XtRBoolean,
1338         sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1339         XtRImmediate, (XtPointer) False},
1340     { "secondIsUCI", "secondIsUCI", XtRBoolean,
1341         sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1342         XtRImmediate, (XtPointer) False},
1343     { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1344         sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1345         XtRImmediate, (XtPointer) True},
1346     { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1347         sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1348         XtRImmediate, (XtPointer) True},
1349     { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1350         sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1351         XtRImmediate, (XtPointer) False},
1352     { "defaultHashSize", "defaultHashSize", XtRInt,
1353         sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1354         XtRImmediate, (XtPointer) 64},
1355     { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1356         sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1357         XtRImmediate, (XtPointer) 4},
1358     { "polyglotDir", "polyglotDir", XtRString,
1359         sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1360         XtRImmediate, (XtPointer) "." },
1361     { "polyglotBook", "polyglotBook", XtRString,
1362         sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1363         XtRImmediate, (XtPointer) "" },
1364     { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1365         sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1366         XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1367     { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1368         sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1369         XtRImmediate, (XtPointer) 0},
1370     { "delayAfterQuit", "delayAfterQuit", XtRInt,
1371         sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1372         XtRImmediate, (XtPointer) 0},
1373 };
1374
1375 XrmOptionDescRec shellOptions[] = {
1376     { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1377     { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1378     { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1379     { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1380     { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1381     { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1382     { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1383     { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1384     { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1385     { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1386     { "-initString", "initString", XrmoptionSepArg, NULL },
1387     { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1388     { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1389     { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1390     { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1391     { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1392     { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1393     { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1394     { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1395     { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1396     { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1397     { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1398     { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1399     { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1400     { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1401     { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1402     { "-fh", "firstHost", XrmoptionSepArg, NULL },
1403     { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1404     { "-sh", "secondHost", XrmoptionSepArg, NULL },
1405     { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1406     { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1407     { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1408     { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1409     { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1410     { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1411     { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1412     { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1413     { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1414     { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1415     { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1416     { "-td", "timeDelay", XrmoptionSepArg, NULL },
1417     { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1418     { "-tc", "timeControl", XrmoptionSepArg, NULL },
1419     { "-internetChessServerMode", "internetChessServerMode",
1420         XrmoptionSepArg, NULL },
1421     { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1422     { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1423     { "-internetChessServerHost", "internetChessServerHost",
1424         XrmoptionSepArg, NULL },
1425     { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1426     { "-internetChessServerPort", "internetChessServerPort",
1427         XrmoptionSepArg, NULL },
1428     { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1429     { "-internetChessServerCommPort", "internetChessServerCommPort",
1430         XrmoptionSepArg, NULL },
1431     { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1432     { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1433         XrmoptionSepArg, NULL },
1434     { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1435     { "-internetChessServerHelper", "internetChessServerHelper",
1436         XrmoptionSepArg, NULL },
1437     { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1438     { "-internetChessServerInputBox", "internetChessServerInputBox",
1439         XrmoptionSepArg, NULL },
1440     { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1441     { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1442     { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1443     { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1444     { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1445     { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1446     { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1447     { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1448     { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1449     { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1450     { "-gateway", "gateway", XrmoptionSepArg, NULL },
1451     { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1452     { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1453     { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1454     { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1455     { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1456     { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1457     { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1458     { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1459     { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1460     { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1461     { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1462     { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1463     { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1464     { "-blind", "blindfold", XrmoptionNoArg, "True" },
1465     { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1466     { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1467     { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1468     { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1469     { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1470     { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1471     { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1472     { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1473     { "-mm", "matchMode", XrmoptionNoArg, "True" },
1474     { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1475     { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1476     { "-mg", "matchGames", XrmoptionSepArg, NULL },
1477     { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1478     { "-mono", "monoMode", XrmoptionNoArg, "True" },
1479     { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1480     { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1481     { "-debug", "debugMode", XrmoptionNoArg, "True" },
1482     { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1483     { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1484     { "-clock", "clockMode", XrmoptionNoArg, "True" },
1485     { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1486     { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1487     { "-size", "boardSize", XrmoptionSepArg, NULL },
1488     { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1489     { "-st", "searchTime", XrmoptionSepArg, NULL },
1490     { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1491     { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1492     { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1493     { "-coords", "showCoords", XrmoptionNoArg, "True" },
1494     { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1495 #if JAIL
1496     { "-showJail", "showJail", XrmoptionSepArg, NULL },
1497     { "-jail", "showJail", XrmoptionNoArg, "1" },
1498     { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1499     { "-xjail", "showJail", XrmoptionNoArg, "0" },
1500 #endif
1501     { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1502     { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1503     { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1504     { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1505     { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1506     { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1507     { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1508     { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1509     { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1510     { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1511     { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1512     { "-font", "font", XrmoptionSepArg, NULL },
1513     { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1514     { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1515     { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1516     { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1517     { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1518     { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1519     { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1520     { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1521     { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1522     { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1523     { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1524     { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1525     { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1526     { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1527     { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1528     { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1529     { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1530     { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1531     { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1532     { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1533 #if HIGHDRAG
1534     { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1535     { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1536     { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1537 #endif
1538     { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1539     { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1540     { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1541     { "-premove", "premove", XrmoptionSepArg, NULL },
1542     { "-pre", "premove", XrmoptionNoArg, "True" },
1543     { "-xpre", "premove", XrmoptionNoArg, "False" },
1544     { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1545     { "-legal", "testLegality", XrmoptionNoArg, "True" },
1546     { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1547     { "-flipView", "flipView", XrmoptionSepArg, NULL },
1548     { "-flip", "flipView", XrmoptionNoArg, "True" },
1549     { "-xflip", "flipView", XrmoptionNoArg, "False" },
1550     { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1551     { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1552         XrmoptionSepArg, NULL },
1553     { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1554     { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1555     { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1556     { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1557     { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1558     { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1559     { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1560     { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1561     { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1562     { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1563     { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1564 #ifdef ZIPPY
1565     { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1566     { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1567     { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1568     { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1569     { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1570     { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1571     { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1572     { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1573     { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1574     { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1575     { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1576     { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1577     { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1578     { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1579     { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1580     { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1581     { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1582     { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1583     { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1584     { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1585     { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1586     { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1587     { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1588     { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1589     { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1590     { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1591     { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1592     { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1593     { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1594     { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1595 #endif
1596     { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1597     { "-flash", "flashCount", XrmoptionNoArg, "3" },
1598     { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1599     { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1600     { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1601     { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1602     { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1603     { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1604     { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1605     { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1606     { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1607     { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1608     { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1609     { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1610     { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1611     { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1612     { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1613     { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1614     { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1615     { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1616     { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1617     { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1618     { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1619     { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1620     { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1621     { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1622     { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1623     { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1624     { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1625     { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1626     { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1627     { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1628     { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1629     { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1630     { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1631     { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1632     { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1633     { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1634     { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1635     { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1636     { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1637     { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1638     { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1639     { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1640     { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1641     { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1642     { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1643     { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1644     { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1645     { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1646     { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1647     { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1648     { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1649     { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1650     { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1651     { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1652     { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1653     { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1654     { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1655     { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1656     { "-mode", "initialMode", XrmoptionSepArg, NULL },
1657     { "-variant", "variant", XrmoptionSepArg, NULL },
1658     { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1659     { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1660     { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1661     { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1662     { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1663     /* [AS,HR] New features */
1664     { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1665     { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1666     { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1667     { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1668     { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1669     { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1670     { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1671     { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1672     { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1673     { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1674     { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1675     { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1676     { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1677     { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1678     { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1679     { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1680     { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1681     { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1682     { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1683     { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1684     { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1685     { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1686     { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1687     // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1688
1689     /* [HGM,HR] User-selectable board size */
1690     { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1691     { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1692     { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1693
1694     /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1695     { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1696     { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL },       // requires front-end changes to work
1697     { "-allWhite", "allWhite", XrmoptionSepArg, NULL },         // requires front-end changes to work
1698     { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1699     { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1700     { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1701     { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1702     { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1703     { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1704     { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1705     { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1706     { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1707     { "-userName", "userName", XrmoptionSepArg, NULL },
1708     { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1709     { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1710     { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1711     { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1712     { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1713     { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1714     { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1715     { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1716     { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1717     { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1718     { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1719     { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1720     { "-userName", "userName", XrmoptionSepArg, NULL },
1721     { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1722     { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1723     { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1724     { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1725     { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1726     { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1727     { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1728     { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1729     { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1730     { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1731     { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1732     { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1733 };
1734
1735
1736 XtActionsRec boardActions[] = {
1737     { "DrawPosition", DrawPositionProc },
1738     { "HandleUserMove", HandleUserMove },
1739     { "AnimateUserMove", AnimateUserMove },
1740     { "FileNameAction", FileNameAction },
1741     { "AskQuestionProc", AskQuestionProc },
1742     { "AskQuestionReplyAction", AskQuestionReplyAction },
1743     { "PieceMenuPopup", PieceMenuPopup },
1744     { "WhiteClock", WhiteClock },
1745     { "BlackClock", BlackClock },
1746     { "Iconify", Iconify },
1747     { "ResetProc", ResetProc },
1748     { "LoadGameProc", LoadGameProc },
1749     { "LoadNextGameProc", LoadNextGameProc },
1750     { "LoadPrevGameProc", LoadPrevGameProc },
1751     { "LoadSelectedProc", LoadSelectedProc },
1752     { "ReloadGameProc", ReloadGameProc },
1753     { "LoadPositionProc", LoadPositionProc },
1754     { "LoadNextPositionProc", LoadNextPositionProc },
1755     { "LoadPrevPositionProc", LoadPrevPositionProc },
1756     { "ReloadPositionProc", ReloadPositionProc },
1757     { "CopyPositionProc", CopyPositionProc },
1758     { "PastePositionProc", PastePositionProc },
1759     { "CopyGameProc", CopyGameProc },
1760     { "PasteGameProc", PasteGameProc },
1761     { "SaveGameProc", SaveGameProc },
1762     { "SavePositionProc", SavePositionProc },
1763     { "MailMoveProc", MailMoveProc },
1764     { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1765     { "QuitProc", QuitProc },
1766     { "MachineWhiteProc", MachineWhiteProc },
1767     { "MachineBlackProc", MachineBlackProc },
1768     { "AnalysisModeProc", AnalyzeModeProc },
1769     { "AnalyzeFileProc", AnalyzeFileProc },
1770     { "TwoMachinesProc", TwoMachinesProc },
1771     { "IcsClientProc", IcsClientProc },
1772     { "EditGameProc", EditGameProc },
1773     { "EditPositionProc", EditPositionProc },
1774     { "TrainingProc", EditPositionProc },
1775     { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1776     { "ShowGameListProc", ShowGameListProc },
1777     { "ShowMoveListProc", HistoryShowProc},
1778     { "EditTagsProc", EditCommentProc },
1779     { "EditCommentProc", EditCommentProc },
1780     { "IcsAlarmProc", IcsAlarmProc },
1781     { "IcsInputBoxProc", IcsInputBoxProc },
1782     { "PauseProc", PauseProc },
1783     { "AcceptProc", AcceptProc },
1784     { "DeclineProc", DeclineProc },
1785     { "RematchProc", RematchProc },
1786     { "CallFlagProc", CallFlagProc },
1787     { "DrawProc", DrawProc },
1788     { "AdjournProc", AdjournProc },
1789     { "AbortProc", AbortProc },
1790     { "ResignProc", ResignProc },
1791     { "AdjuWhiteProc", AdjuWhiteProc },
1792     { "AdjuBlackProc", AdjuBlackProc },
1793     { "AdjuDrawProc", AdjuDrawProc },
1794     { "EnterKeyProc", EnterKeyProc },
1795     { "StopObservingProc", StopObservingProc },
1796     { "StopExaminingProc", StopExaminingProc },
1797     { "BackwardProc", BackwardProc },
1798     { "ForwardProc", ForwardProc },
1799     { "ToStartProc", ToStartProc },
1800     { "ToEndProc", ToEndProc },
1801     { "RevertProc", RevertProc },
1802     { "TruncateGameProc", TruncateGameProc },
1803     { "MoveNowProc", MoveNowProc },
1804     { "RetractMoveProc", RetractMoveProc },
1805     { "AlwaysQueenProc", AlwaysQueenProc },
1806     { "AnimateDraggingProc", AnimateDraggingProc },
1807     { "AnimateMovingProc", AnimateMovingProc },
1808     { "AutoflagProc", AutoflagProc },
1809     { "AutoflipProc", AutoflipProc },
1810     { "AutobsProc", AutobsProc },
1811     { "AutoraiseProc", AutoraiseProc },
1812     { "AutosaveProc", AutosaveProc },
1813     { "BlindfoldProc", BlindfoldProc },
1814     { "FlashMovesProc", FlashMovesProc },
1815     { "FlipViewProc", FlipViewProc },
1816     { "GetMoveListProc", GetMoveListProc },
1817 #if HIGHDRAG
1818     { "HighlightDraggingProc", HighlightDraggingProc },
1819 #endif
1820     { "HighlightLastMoveProc", HighlightLastMoveProc },
1821     { "IcsAlarmProc", IcsAlarmProc },
1822     { "MoveSoundProc", MoveSoundProc },
1823     { "OldSaveStyleProc", OldSaveStyleProc },
1824     { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1825     { "PonderNextMoveProc", PonderNextMoveProc },
1826     { "PopupExitMessageProc", PopupExitMessageProc },
1827     { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1828     { "PremoveProc", PremoveProc },
1829     { "QuietPlayProc", QuietPlayProc },
1830     { "ShowCoordsProc", ShowCoordsProc },
1831     { "ShowThinkingProc", ShowThinkingProc },
1832     { "HideThinkingProc", HideThinkingProc },
1833     { "TestLegalityProc", TestLegalityProc },
1834     { "InfoProc", InfoProc },
1835     { "ManProc", ManProc },
1836     { "HintProc", HintProc },
1837     { "BookProc", BookProc },
1838     { "AboutGameProc", AboutGameProc },
1839     { "AboutProc", AboutProc },
1840     { "DebugProc", DebugProc },
1841     { "NothingProc", NothingProc },
1842     { "CommentPopDown", (XtActionProc) CommentPopDown },
1843     { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1844     { "TagsPopDown", (XtActionProc) TagsPopDown },
1845     { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1846     { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1847     { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1848     { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1849     { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1850     { "GameListPopDown", (XtActionProc) GameListPopDown },
1851     { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1852     { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1853     { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1854     { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1855     { "EnginePopDown", (XtActionProc) EnginePopDown },
1856     { "UciPopDown", (XtActionProc) UciPopDown },
1857     { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1858     { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1859     { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1860 };
1861
1862 char globalTranslations[] =
1863   ":<Key>R: ResignProc() \n \
1864    :<Key>r: ResetProc() \n \
1865    :<Key>g: LoadGameProc() \n \
1866    :<Key>N: LoadNextGameProc() \n \
1867    :<Key>P: LoadPrevGameProc() \n \
1868    :<Key>Q: QuitProc() \n \
1869    :<Key>F: ToEndProc() \n \
1870    :<Key>f: ForwardProc() \n \
1871    :<Key>B: ToStartProc() \n \
1872    :<Key>b: BackwardProc() \n \
1873    :<Key>p: PauseProc() \n \
1874    :<Key>d: DrawProc() \n \
1875    :<Key>t: CallFlagProc() \n \
1876    :<Key>i: Iconify() \n \
1877    :<Key>c: Iconify() \n \
1878    :<Key>v: FlipViewProc() \n \
1879    <KeyDown>Control_L: BackwardProc() \n \
1880    <KeyUp>Control_L: ForwardProc() \n \
1881    <KeyDown>Control_R: BackwardProc() \n \
1882    <KeyUp>Control_R: ForwardProc() \n \
1883    Shift<Key>1: AskQuestionProc(\"Direct command\",\
1884                                 \"Send to chess program:\",,1) \n \
1885    Shift<Key>2: AskQuestionProc(\"Direct command\",\
1886                                 \"Send to second chess program:\",,2) \n";
1887
1888 char boardTranslations[] =
1889    "<Btn1Down>: HandleUserMove() \n \
1890    <Btn1Up>: HandleUserMove() \n \
1891    <Btn1Motion>: AnimateUserMove() \n \
1892    Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1893                  PieceMenuPopup(menuB) \n \
1894    Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1895                  PieceMenuPopup(menuW) \n \
1896    Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1897                  PieceMenuPopup(menuW) \n \
1898    Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1899                  PieceMenuPopup(menuB) \n";
1900
1901 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1902 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1903
1904 char ICSInputTranslations[] =
1905     "<Key>Return: EnterKeyProc() \n";
1906
1907 String xboardResources[] = {
1908     "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1909     "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1910     "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1911     NULL
1912   };
1913
1914
1915 /* Max possible square size */
1916 #define MAXSQSIZE 256
1917
1918 static int xpm_avail[MAXSQSIZE];
1919
1920 #ifdef HAVE_DIR_STRUCT
1921
1922 /* Extract piece size from filename */
1923 static int
1924 xpm_getsize(name, len, ext)
1925      char *name;
1926      int len;
1927      char *ext;
1928 {
1929     char *p, *d;
1930     char buf[10];
1931
1932     if (len < 4)
1933       return 0;
1934
1935     if ((p=strchr(name, '.')) == NULL ||
1936         StrCaseCmp(p+1, ext) != 0)
1937       return 0;
1938
1939     p = name + 3;
1940     d = buf;
1941
1942     while (*p && isdigit(*p))
1943       *(d++) = *(p++);
1944
1945     *d = 0;
1946     return atoi(buf);
1947 }
1948
1949 /* Setup xpm_avail */
1950 static int
1951 xpm_getavail(dirname, ext)
1952      char *dirname;
1953      char *ext;
1954 {
1955     DIR *dir;
1956     struct dirent *ent;
1957     int  i;
1958
1959     for (i=0; i<MAXSQSIZE; ++i)
1960       xpm_avail[i] = 0;
1961
1962     if (appData.debugMode)
1963       fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1964
1965     dir = opendir(dirname);
1966     if (!dir)
1967       {
1968           fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1969                   programName, dirname);
1970           exit(1);
1971       }
1972
1973     while ((ent=readdir(dir)) != NULL) {
1974         i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1975         if (i > 0 && i < MAXSQSIZE)
1976           xpm_avail[i] = 1;
1977     }
1978
1979     closedir(dir);
1980
1981     return 0;
1982 }
1983
1984 void
1985 xpm_print_avail(fp, ext)
1986      FILE *fp;
1987      char *ext;
1988 {
1989     int i;
1990
1991     fprintf(fp, _("Available `%s' sizes:\n"), ext);
1992     for (i=1; i<MAXSQSIZE; ++i) {
1993         if (xpm_avail[i])
1994           printf("%d\n", i);
1995     }
1996 }
1997
1998 /* Return XPM piecesize closest to size */
1999 int
2000 xpm_closest_to(dirname, size, ext)
2001      char *dirname;
2002      int size;
2003      char *ext;
2004 {
2005     int i;
2006     int sm_diff = MAXSQSIZE;
2007     int sm_index = 0;
2008     int diff;
2009
2010     xpm_getavail(dirname, ext);
2011
2012     if (appData.debugMode)
2013       xpm_print_avail(stderr, ext);
2014
2015     for (i=1; i<MAXSQSIZE; ++i) {
2016         if (xpm_avail[i]) {
2017             diff = size - i;
2018             diff = (diff<0) ? -diff : diff;
2019             if (diff < sm_diff) {
2020                 sm_diff = diff;
2021                 sm_index = i;
2022             }
2023         }
2024     }
2025
2026     if (!sm_index) {
2027         fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2028         exit(1);
2029     }
2030
2031     return sm_index;
2032 }
2033 #else   /* !HAVE_DIR_STRUCT */
2034 /* If we are on a system without a DIR struct, we can't
2035    read the directory, so we can't collect a list of
2036    filenames, etc., so we can't do any size-fitting. */
2037 int
2038 xpm_closest_to(dirname, size, ext)
2039      char *dirname;
2040      int size;
2041      char *ext;
2042 {
2043     fprintf(stderr, _("\
2044 Warning: No DIR structure found on this system --\n\
2045          Unable to autosize for XPM/XIM pieces.\n\
2046    Please report this error to frankm@hiwaay.net.\n\
2047    Include system type & operating system in message.\n"));
2048     return size;
2049 }
2050 #endif /* HAVE_DIR_STRUCT */
2051
2052 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2053                              "magenta", "cyan", "white" };
2054 typedef struct {
2055     int attr, bg, fg;
2056 } TextColors;
2057 TextColors textColors[(int)NColorClasses];
2058
2059 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2060 static int
2061 parse_color(str, which)
2062      char *str;
2063      int which;
2064 {
2065     char *p, buf[100], *d;
2066     int i;
2067
2068     if (strlen(str) > 99)       /* watch bounds on buf */
2069       return -1;
2070
2071     p = str;
2072     d = buf;
2073     for (i=0; i<which; ++i) {
2074         p = strchr(p, ',');
2075         if (!p)
2076           return -1;
2077         ++p;
2078     }
2079
2080     /* Could be looking at something like:
2081        black, , 1
2082        .. in which case we want to stop on a comma also */
2083     while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2084       ++p;
2085
2086     if (*p == ',') {
2087         return -1;              /* Use default for empty field */
2088     }
2089
2090     if (which == 2 || isdigit(*p))
2091       return atoi(p);
2092
2093     while (*p && isalpha(*p))
2094       *(d++) = *(p++);
2095
2096     *d = 0;
2097
2098     for (i=0; i<8; ++i) {
2099         if (!StrCaseCmp(buf, cnames[i]))
2100           return which? (i+40) : (i+30);
2101     }
2102     if (!StrCaseCmp(buf, "default")) return -1;
2103
2104     fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2105     return -2;
2106 }
2107
2108 static int
2109 parse_cpair(cc, str)
2110      ColorClass cc;
2111      char *str;
2112 {
2113     if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2114         fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2115                 programName, str);
2116         return -1;
2117     }
2118
2119     /* bg and attr are optional */
2120     textColors[(int)cc].bg = parse_color(str, 1);
2121     if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2122         textColors[(int)cc].attr = 0;
2123     }
2124     return 0;
2125 }
2126
2127
2128 /* Arrange to catch delete-window events */
2129 Atom wm_delete_window;
2130 void
2131 CatchDeleteWindow(Widget w, String procname)
2132 {
2133   char buf[MSG_SIZ];
2134   XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2135   sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
2136   XtAugmentTranslations(w, XtParseTranslationTable(buf));
2137 }
2138
2139 void
2140 BoardToTop()
2141 {
2142   Arg args[16];
2143   XtSetArg(args[0], XtNiconic, False);
2144   XtSetValues(shellWidget, args, 1);
2145
2146   XtPopup(shellWidget, XtGrabNone); /* Raise if lowered  */
2147 }
2148
2149 #ifdef IDSIZES
2150   // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2151 #else
2152 #define BoardSize int
2153 void InitDrawingSizes(BoardSize boardSize, int flags)
2154 {   // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2155     Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2156     Arg args[16];
2157     XtGeometryResult gres;
2158     int i;
2159
2160     if(!formWidget) return;
2161
2162     /*
2163      * Enable shell resizing.
2164      */
2165     shellArgs[0].value = (XtArgVal) &w;
2166     shellArgs[1].value = (XtArgVal) &h;
2167     XtGetValues(shellWidget, shellArgs, 2);
2168
2169     shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2170     shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2171     XtSetValues(shellWidget, &shellArgs[2], 4);
2172
2173     XtSetArg(args[0], XtNdefaultDistance, &sep);
2174     XtGetValues(formWidget, args, 1);
2175
2176     boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2177     boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2178     CreateGrid();
2179
2180     XtSetArg(args[0], XtNwidth, boardWidth);
2181     XtSetArg(args[1], XtNheight, boardHeight);
2182     XtSetValues(boardWidget, args, 2);
2183
2184     timerWidth = (boardWidth - sep) / 2;
2185     XtSetArg(args[0], XtNwidth, timerWidth);
2186     XtSetValues(whiteTimerWidget, args, 1);
2187     XtSetValues(blackTimerWidget, args, 1);
2188
2189     XawFormDoLayout(formWidget, False);
2190
2191     if (appData.titleInWindow) {
2192         i = 0;
2193         XtSetArg(args[i], XtNborderWidth, &bor); i++;
2194         XtSetArg(args[i], XtNheight, &h);  i++;
2195         XtGetValues(titleWidget, args, i);
2196         if (smallLayout) {
2197             w = boardWidth - 2*bor;
2198         } else {
2199             XtSetArg(args[0], XtNwidth, &w);
2200             XtGetValues(menuBarWidget, args, 1);
2201             w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2202         }
2203
2204         gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2205         if (gres != XtGeometryYes && appData.debugMode) {
2206             fprintf(stderr,
2207                     _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2208                     programName, gres, w, h, wr, hr);
2209         }
2210     }
2211
2212     XawFormDoLayout(formWidget, True);
2213
2214     /*
2215      * Inhibit shell resizing.
2216      */
2217     shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2218     shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2219     shellArgs[4].value = shellArgs[2].value = w;
2220     shellArgs[5].value = shellArgs[3].value = h;
2221     XtSetValues(shellWidget, &shellArgs[0], 6);
2222 }
2223 #endif
2224
2225 int
2226 main(argc, argv)
2227      int argc;
2228      char **argv;
2229 {
2230     int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2231     XSetWindowAttributes window_attributes;
2232     Arg args[16];
2233     Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2234     XrmValue vFrom, vTo;
2235     XtGeometryResult gres;
2236     char *p;
2237     XrmDatabase xdb;
2238     int forceMono = False;
2239 #define INDIRECTION
2240 #ifdef INDIRECTION
2241     // [HGM] before anything else, expand any indirection files amongst options
2242     char *argvCopy[1000]; // 1000 seems enough
2243     char newArgs[10000];  // holds actual characters
2244     int k = 0;
2245
2246     srandom(time(0)); // [HGM] book: make random truly random
2247
2248     j = 0;
2249     for(i=0; i<argc; i++) {
2250         if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2251 //fprintf(stderr, "arg %s\n", argv[i]);
2252         if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2253             char c;
2254             FILE *f = fopen(argv[i]+1, "rb");
2255             if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2256             argvCopy[j++] = newArgs + k; // get ready for first argument from file
2257             while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2258                 if(c == '\n') {
2259                     if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2260                     newArgs[k++] = 0;  // terminate current arg
2261                     if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2262                     argvCopy[j++] = newArgs + k; // get ready for next
2263                 } else {
2264                     if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2265                     newArgs[k++] = c;
2266                 }
2267             }
2268             newArgs[k] = 0;
2269             j--;
2270             fclose(f);
2271         }
2272     }
2273     argvCopy[j] = NULL;
2274     argv = argvCopy;
2275     argc = j;
2276 #if 0
2277     if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2278         for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2279     }
2280 #endif
2281 #endif
2282
2283
2284     setbuf(stdout, NULL);
2285     setbuf(stderr, NULL);
2286     debugFP = stderr;
2287
2288     programName = strrchr(argv[0], '/');
2289     if (programName == NULL)
2290       programName = argv[0];
2291     else
2292       programName++;
2293
2294 #ifdef ENABLE_NLS
2295     XtSetLanguageProc(NULL, NULL, NULL);
2296     bindtextdomain(PRODUCT, LOCALEDIR);
2297     textdomain(PRODUCT);
2298 #endif
2299
2300     shellWidget =
2301       XtAppInitialize(&appContext, "XBoard", shellOptions,
2302                       XtNumber(shellOptions),
2303                       &argc, argv, xboardResources, NULL, 0);
2304     if (argc > 1) {
2305         fprintf(stderr, _("%s: unrecognized argument %s\n"),
2306                 programName, argv[1]);
2307         exit(2);
2308     }
2309
2310     if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2311         chessDir = ".";
2312     } else {
2313         if (chdir(chessDir) != 0) {
2314             fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2315             perror(chessDir);
2316             exit(1);
2317         }
2318     }
2319
2320     p = getenv("HOME");
2321     if (p == NULL) p = "/tmp";
2322     i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2323     gameCopyFilename = (char*) malloc(i);
2324     gamePasteFilename = (char*) malloc(i);
2325     sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
2326     sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
2327
2328     XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2329                               clientResources, XtNumber(clientResources),
2330                               NULL, 0);
2331
2332     if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2333         /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2334         if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL)  {
2335            printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2336            exit(errno);
2337         }
2338         setbuf(debugFP, NULL);
2339     }
2340
2341     /* [HGM,HR] make sure board size is acceptable */
2342     if(appData.NrFiles > BOARD_SIZE ||
2343        appData.NrRanks > BOARD_SIZE   )
2344          DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2345
2346 #if !HIGHDRAG
2347     /* This feature does not work; animation needs a rewrite */
2348     appData.highlightDragging = FALSE;
2349 #endif
2350     InitBackEnd1();
2351
2352     xDisplay = XtDisplay(shellWidget);
2353     xScreen = DefaultScreen(xDisplay);
2354     wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2355
2356         gameInfo.variant = StringToVariant(appData.variant);
2357         InitPosition(FALSE);
2358 #if 0
2359     /*
2360      * Determine boardSize
2361      */
2362     gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2363
2364 //#ifndef IDSIZE
2365     // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2366     gameInfo.boardWidth    = appData.NrFiles > 0 ? appData.NrFiles : 8;
2367     gameInfo.boardHeight   = appData.NrRanks > 0 ? appData.NrRanks : 8;
2368     gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2369 #endif
2370
2371
2372 #ifdef IDSIZE
2373     InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2374 #else
2375     if (isdigit(appData.boardSize[0])) {
2376         i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2377                    &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2378                    &fontPxlSize, &smallLayout, &tinyLayout);
2379         if (i == 0) {
2380             fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2381                     programName, appData.boardSize);
2382             exit(2);
2383         }
2384         if (i < 7) {
2385             /* Find some defaults; use the nearest known size */
2386             SizeDefaults *szd, *nearest;
2387             int distance = 99999;
2388             nearest = szd = sizeDefaults;
2389             while (szd->name != NULL) {
2390                 if (abs(szd->squareSize - squareSize) < distance) {
2391                     nearest = szd;
2392                     distance = abs(szd->squareSize - squareSize);
2393                     if (distance == 0) break;
2394                 }
2395                 szd++;
2396             }
2397             if (i < 2) lineGap = nearest->lineGap;
2398             if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2399             if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2400             if (i < 5) fontPxlSize = nearest->fontPxlSize;
2401             if (i < 6) smallLayout = nearest->smallLayout;
2402             if (i < 7) tinyLayout = nearest->tinyLayout;
2403         }
2404     } else {
2405         SizeDefaults *szd = sizeDefaults;
2406         if (*appData.boardSize == NULLCHAR) {
2407             while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2408                    DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2409               szd++;
2410             }
2411             if (szd->name == NULL) szd--;
2412         } else {
2413             while (szd->name != NULL &&
2414                    StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2415             if (szd->name == NULL) {
2416                 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2417                         programName, appData.boardSize);
2418                 exit(2);
2419             }
2420         }
2421         squareSize = szd->squareSize;
2422         lineGap = szd->lineGap;
2423         clockFontPxlSize = szd->clockFontPxlSize;
2424         coordFontPxlSize = szd->coordFontPxlSize;
2425         fontPxlSize = szd->fontPxlSize;
2426         smallLayout = szd->smallLayout;
2427         tinyLayout = szd->tinyLayout;
2428     }
2429
2430     /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2431     if (strlen(appData.pixmapDirectory) > 0) {
2432         p = ExpandPathName(appData.pixmapDirectory);
2433         if (!p) {
2434             fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2435                    appData.pixmapDirectory);
2436             exit(1);
2437         }
2438         if (appData.debugMode) {
2439           fprintf(stderr, _("\
2440 XBoard square size (hint): %d\n\
2441 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2442         }
2443         squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2444         if (appData.debugMode) {
2445             fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2446         }
2447     }
2448
2449     /* [HR] height treated separately (hacked) */
2450     boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2451     boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2452     if (appData.showJail == 1) {
2453         /* Jail on top and bottom */
2454         XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2455         XtSetArg(boardArgs[2], XtNheight,
2456                  boardHeight + 2*(lineGap + squareSize));
2457     } else if (appData.showJail == 2) {
2458         /* Jail on sides */
2459         XtSetArg(boardArgs[1], XtNwidth,
2460                  boardWidth + 2*(lineGap + squareSize));
2461         XtSetArg(boardArgs[2], XtNheight, boardHeight);
2462     } else {
2463         /* No jail */
2464         XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2465         XtSetArg(boardArgs[2], XtNheight, boardHeight);
2466     }
2467
2468     /*
2469      * Determine what fonts to use.
2470      */
2471     appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2472     clockFontID = XLoadFont(xDisplay, appData.clockFont);
2473     clockFontStruct = XQueryFont(xDisplay, clockFontID);
2474     appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2475     coordFontID = XLoadFont(xDisplay, appData.coordFont);
2476     coordFontStruct = XQueryFont(xDisplay, coordFontID);
2477     appData.font = FindFont(appData.font, fontPxlSize);
2478     countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2479     countFontStruct = XQueryFont(xDisplay, countFontID);
2480 //    appData.font = FindFont(appData.font, fontPxlSize);
2481
2482     xdb = XtDatabase(xDisplay);
2483     XrmPutStringResource(&xdb, "*font", appData.font);
2484
2485     /*
2486      * Detect if there are not enough colors available and adapt.
2487      */
2488     if (DefaultDepth(xDisplay, xScreen) <= 2) {
2489       appData.monoMode = True;
2490     }
2491
2492     if (!appData.monoMode) {
2493         vFrom.addr = (caddr_t) appData.lightSquareColor;
2494         vFrom.size = strlen(appData.lightSquareColor);
2495         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2496         if (vTo.addr == NULL) {
2497           appData.monoMode = True;
2498           forceMono = True;
2499         } else {
2500           lightSquareColor = *(Pixel *) vTo.addr;
2501         }
2502     }
2503     if (!appData.monoMode) {
2504         vFrom.addr = (caddr_t) appData.darkSquareColor;
2505         vFrom.size = strlen(appData.darkSquareColor);
2506         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2507         if (vTo.addr == NULL) {
2508           appData.monoMode = True;
2509           forceMono = True;
2510         } else {
2511           darkSquareColor = *(Pixel *) vTo.addr;
2512         }
2513     }
2514     if (!appData.monoMode) {
2515         vFrom.addr = (caddr_t) appData.whitePieceColor;
2516         vFrom.size = strlen(appData.whitePieceColor);
2517         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2518         if (vTo.addr == NULL) {
2519           appData.monoMode = True;
2520           forceMono = True;
2521         } else {
2522           whitePieceColor = *(Pixel *) vTo.addr;
2523         }
2524     }
2525     if (!appData.monoMode) {
2526         vFrom.addr = (caddr_t) appData.blackPieceColor;
2527         vFrom.size = strlen(appData.blackPieceColor);
2528         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2529         if (vTo.addr == NULL) {
2530           appData.monoMode = True;
2531           forceMono = True;
2532         } else {
2533           blackPieceColor = *(Pixel *) vTo.addr;
2534         }
2535     }
2536
2537     if (!appData.monoMode) {
2538         vFrom.addr = (caddr_t) appData.highlightSquareColor;
2539         vFrom.size = strlen(appData.highlightSquareColor);
2540         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2541         if (vTo.addr == NULL) {
2542           appData.monoMode = True;
2543           forceMono = True;
2544         } else {
2545           highlightSquareColor = *(Pixel *) vTo.addr;
2546         }
2547     }
2548
2549     if (!appData.monoMode) {
2550         vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2551         vFrom.size = strlen(appData.premoveHighlightColor);
2552         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2553         if (vTo.addr == NULL) {
2554           appData.monoMode = True;
2555           forceMono = True;
2556         } else {
2557           premoveHighlightColor = *(Pixel *) vTo.addr;
2558         }
2559     }
2560
2561     if (forceMono) {
2562       fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2563               programName);
2564     }
2565
2566     if (appData.monoMode && appData.debugMode) {
2567         fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2568                 (unsigned long) XWhitePixel(xDisplay, xScreen),
2569                 (unsigned long) XBlackPixel(xDisplay, xScreen));
2570     }
2571
2572     if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2573         parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2574         parse_cpair(ColorChannel1, appData.colorChannel1) < 0  ||
2575         parse_cpair(ColorChannel, appData.colorChannel) < 0  ||
2576         parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2577         parse_cpair(ColorTell, appData.colorTell) < 0 ||
2578         parse_cpair(ColorChallenge, appData.colorChallenge) < 0  ||
2579         parse_cpair(ColorRequest, appData.colorRequest) < 0  ||
2580         parse_cpair(ColorSeek, appData.colorSeek) < 0  ||
2581         parse_cpair(ColorNormal, appData.colorNormal) < 0)
2582       {
2583           if (appData.colorize) {
2584               fprintf(stderr,
2585                       _("%s: can't parse color names; disabling colorization\n"),
2586                       programName);
2587           }
2588           appData.colorize = FALSE;
2589       }
2590     textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2591     textColors[ColorNone].attr = 0;
2592
2593     XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2594
2595     /*
2596      * widget hierarchy
2597      */
2598     if (tinyLayout) {
2599         layoutName = "tinyLayout";
2600     } else if (smallLayout) {
2601         layoutName = "smallLayout";
2602     } else {
2603         layoutName = "normalLayout";
2604     }
2605     /* Outer layoutWidget is there only to provide a name for use in
2606        resources that depend on the layout style */
2607     layoutWidget =
2608       XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2609                             layoutArgs, XtNumber(layoutArgs));
2610     formWidget =
2611       XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2612                             formArgs, XtNumber(formArgs));
2613     XtSetArg(args[0], XtNdefaultDistance, &sep);
2614     XtGetValues(formWidget, args, 1);
2615
2616     j = 0;
2617     widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2618     XtSetArg(args[0], XtNtop,    XtChainTop);
2619     XtSetArg(args[1], XtNbottom, XtChainTop);
2620     XtSetValues(menuBarWidget, args, 2);
2621
2622     widgetList[j++] = whiteTimerWidget =
2623       XtCreateWidget("whiteTime", labelWidgetClass,
2624                      formWidget, timerArgs, XtNumber(timerArgs));
2625     XtSetArg(args[0], XtNfont, clockFontStruct);
2626     XtSetArg(args[1], XtNtop,    XtChainTop);
2627     XtSetArg(args[2], XtNbottom, XtChainTop);
2628     XtSetValues(whiteTimerWidget, args, 3);
2629
2630     widgetList[j++] = blackTimerWidget =
2631       XtCreateWidget("blackTime", labelWidgetClass,
2632                      formWidget, timerArgs, XtNumber(timerArgs));
2633     XtSetArg(args[0], XtNfont, clockFontStruct);
2634     XtSetArg(args[1], XtNtop,    XtChainTop);
2635     XtSetArg(args[2], XtNbottom, XtChainTop);
2636     XtSetValues(blackTimerWidget, args, 3);
2637
2638     if (appData.titleInWindow) {
2639         widgetList[j++] = titleWidget =
2640           XtCreateWidget("title", labelWidgetClass, formWidget,
2641                          titleArgs, XtNumber(titleArgs));
2642         XtSetArg(args[0], XtNtop,    XtChainTop);
2643         XtSetArg(args[1], XtNbottom, XtChainTop);
2644         XtSetValues(titleWidget, args, 2);
2645     }
2646
2647     if (appData.showButtonBar) {
2648       widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2649       XtSetArg(args[0], XtNleft,  XtChainRight); // [HGM] glue to right window edge
2650       XtSetArg(args[1], XtNright, XtChainRight); //       for good run-time sizing
2651       XtSetArg(args[2], XtNtop,    XtChainTop);
2652       XtSetArg(args[3], XtNbottom, XtChainTop);
2653       XtSetValues(buttonBarWidget, args, 4);
2654     }
2655
2656     widgetList[j++] = messageWidget =
2657       XtCreateWidget("message", labelWidgetClass, formWidget,
2658                      messageArgs, XtNumber(messageArgs));
2659     XtSetArg(args[0], XtNtop,    XtChainTop);
2660     XtSetArg(args[1], XtNbottom, XtChainTop);
2661     XtSetValues(messageWidget, args, 2);
2662
2663     widgetList[j++] = boardWidget =
2664       XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2665                      XtNumber(boardArgs));
2666
2667     XtManageChildren(widgetList, j);
2668
2669     timerWidth = (boardWidth - sep) / 2;
2670     XtSetArg(args[0], XtNwidth, timerWidth);
2671     XtSetValues(whiteTimerWidget, args, 1);
2672     XtSetValues(blackTimerWidget, args, 1);
2673
2674     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2675     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2676     XtGetValues(whiteTimerWidget, args, 2);
2677
2678     if (appData.showButtonBar) {
2679       XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2680       XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2681       XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2682     }
2683
2684     /*
2685      * formWidget uses these constraints but they are stored
2686      * in the children.
2687      */
2688     i = 0;
2689     XtSetArg(args[i], XtNfromHoriz, 0); i++;
2690     XtSetValues(menuBarWidget, args, i);
2691     if (appData.titleInWindow) {
2692         if (smallLayout) {
2693             i = 0;
2694             XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2695             XtSetValues(whiteTimerWidget, args, i);
2696             i = 0;
2697             XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2698             XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2699             XtSetValues(blackTimerWidget, args, i);
2700             i = 0;
2701             XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2702             XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2703             XtSetValues(titleWidget, args, i);
2704             i = 0;
2705             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2706             XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2707             XtSetValues(messageWidget, args, i);
2708             if (appData.showButtonBar) {
2709               i = 0;
2710               XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2711               XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2712               XtSetValues(buttonBarWidget, args, i);
2713             }
2714         } else {
2715             i = 0;
2716             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2717             XtSetValues(whiteTimerWidget, args, i);
2718             i = 0;
2719             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2720             XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2721             XtSetValues(blackTimerWidget, args, i);
2722             i = 0;
2723             XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2724             XtSetValues(titleWidget, args, i);
2725             i = 0;
2726             XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2727             XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2728             XtSetValues(messageWidget, args, i);
2729             if (appData.showButtonBar) {
2730               i = 0;
2731               XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2732               XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2733               XtSetValues(buttonBarWidget, args, i);
2734             }
2735         }
2736     } else {
2737         i = 0;
2738         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2739         XtSetValues(whiteTimerWidget, args, i);
2740         i = 0;
2741         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2742         XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2743         XtSetValues(blackTimerWidget, args, i);
2744         i = 0;
2745         XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2746         XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2747         XtSetValues(messageWidget, args, i);
2748         if (appData.showButtonBar) {
2749           i = 0;
2750           XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2751           XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2752           XtSetValues(buttonBarWidget, args, i);
2753         }
2754     }
2755     i = 0;
2756     XtSetArg(args[0], XtNfromVert, messageWidget);
2757     XtSetArg(args[1], XtNtop,    XtChainTop);
2758     XtSetArg(args[2], XtNbottom, XtChainBottom);
2759     XtSetArg(args[3], XtNleft,   XtChainLeft);
2760     XtSetArg(args[4], XtNright,  XtChainRight);
2761     XtSetValues(boardWidget, args, 5);
2762
2763     XtRealizeWidget(shellWidget);
2764
2765     /*
2766      * Correct the width of the message and title widgets.
2767      * It is not known why some systems need the extra fudge term.
2768      * The value "2" is probably larger than needed.
2769      */
2770     XawFormDoLayout(formWidget, False);
2771
2772 #define WIDTH_FUDGE 2
2773     i = 0;
2774     XtSetArg(args[i], XtNborderWidth, &bor);  i++;
2775     XtSetArg(args[i], XtNheight, &h);  i++;
2776     XtGetValues(messageWidget, args, i);
2777     if (appData.showButtonBar) {
2778       i = 0;
2779       XtSetArg(args[i], XtNwidth, &w);  i++;
2780       XtGetValues(buttonBarWidget, args, i);
2781       w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2782     } else {
2783       w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2784     }
2785
2786     gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2787     if (gres != XtGeometryYes && appData.debugMode) {
2788       fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2789               programName, gres, w, h, wr, hr);
2790     }
2791
2792     /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2793     /* The size used for the child widget in layout lags one resize behind
2794        its true size, so we resize a second time, 1 pixel smaller.  Yeech! */
2795     w--;
2796     gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2797     if (gres != XtGeometryYes && appData.debugMode) {
2798       fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2799               programName, gres, w, h, wr, hr);
2800     }
2801     /* !! end hack */
2802     XtSetArg(args[0], XtNleft,  XtChainLeft);  // [HGM] glue ends for good run-time sizing
2803     XtSetArg(args[1], XtNright, XtChainRight);
2804     XtSetValues(messageWidget, args, 2);
2805
2806     if (appData.titleInWindow) {
2807         i = 0;
2808         XtSetArg(args[i], XtNborderWidth, &bor); i++;
2809         XtSetArg(args[i], XtNheight, &h);  i++;
2810         XtGetValues(titleWidget, args, i);
2811         if (smallLayout) {
2812             w = boardWidth - 2*bor;
2813         } else {
2814             XtSetArg(args[0], XtNwidth, &w);
2815             XtGetValues(menuBarWidget, args, 1);
2816             w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2817         }
2818
2819         gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2820         if (gres != XtGeometryYes && appData.debugMode) {
2821             fprintf(stderr,
2822                     _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2823                     programName, gres, w, h, wr, hr);
2824         }
2825     }
2826     XawFormDoLayout(formWidget, True);
2827
2828     xBoardWindow = XtWindow(boardWidget);
2829
2830     // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2831     //       not need to go into InitDrawingSizes().
2832 #endif
2833
2834     /*
2835      * Create X checkmark bitmap and initialize option menu checks.
2836      */
2837     ReadBitmap(&xMarkPixmap, "checkmark.bm",
2838                checkmark_bits, checkmark_width, checkmark_height);
2839     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2840     if (appData.alwaysPromoteToQueen) {
2841         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2842                     args, 1);
2843     }
2844     if (appData.animateDragging) {
2845         XtSetValues(XtNameToWidget(menuBarWidget,
2846                                    "menuOptions.Animate Dragging"),
2847                     args, 1);
2848     }
2849     if (appData.animate) {
2850         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2851                     args, 1);
2852     }
2853     if (appData.autoComment) {
2854         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2855                     args, 1);
2856     }
2857     if (appData.autoCallFlag) {
2858         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2859                     args, 1);
2860     }
2861     if (appData.autoFlipView) {
2862         XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2863                     args, 1);
2864     }
2865     if (appData.autoObserve) {
2866         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2867                     args, 1);
2868     }
2869     if (appData.autoRaiseBoard) {
2870         XtSetValues(XtNameToWidget(menuBarWidget,
2871                                    "menuOptions.Auto Raise Board"), args, 1);
2872     }
2873     if (appData.autoSaveGames) {
2874         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2875                     args, 1);
2876     }
2877     if (appData.saveGameFile[0] != NULLCHAR) {
2878         /* Can't turn this off from menu */
2879         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2880                     args, 1);
2881         XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2882                        False);
2883
2884     }
2885     if (appData.blindfold) {
2886         XtSetValues(XtNameToWidget(menuBarWidget,
2887                                    "menuOptions.Blindfold"), args, 1);
2888     }
2889     if (appData.flashCount > 0) {
2890         XtSetValues(XtNameToWidget(menuBarWidget,
2891                                    "menuOptions.Flash Moves"),
2892                     args, 1);
2893     }
2894     if (appData.getMoveList) {
2895         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2896                     args, 1);
2897     }
2898 #if HIGHDRAG
2899     if (appData.highlightDragging) {
2900         XtSetValues(XtNameToWidget(menuBarWidget,
2901                                    "menuOptions.Highlight Dragging"),
2902                     args, 1);
2903     }
2904 #endif
2905     if (appData.highlightLastMove) {
2906         XtSetValues(XtNameToWidget(menuBarWidget,
2907                                    "menuOptions.Highlight Last Move"),
2908                     args, 1);
2909     }
2910     if (appData.icsAlarm) {
2911         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2912                     args, 1);
2913     }
2914     if (appData.ringBellAfterMoves) {
2915         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2916                     args, 1);
2917     }
2918     if (appData.oldSaveStyle) {
2919         XtSetValues(XtNameToWidget(menuBarWidget,
2920                                    "menuOptions.Old Save Style"), args, 1);
2921     }
2922     if (appData.periodicUpdates) {
2923         XtSetValues(XtNameToWidget(menuBarWidget,
2924                                    "menuOptions.Periodic Updates"), args, 1);
2925     }
2926     if (appData.ponderNextMove) {
2927         XtSetValues(XtNameToWidget(menuBarWidget,
2928                                    "menuOptions.Ponder Next Move"), args, 1);
2929     }
2930     if (appData.popupExitMessage) {
2931         XtSetValues(XtNameToWidget(menuBarWidget,
2932                                    "menuOptions.Popup Exit Message"), args, 1);
2933     }
2934     if (appData.popupMoveErrors) {
2935         XtSetValues(XtNameToWidget(menuBarWidget,
2936                                    "menuOptions.Popup Move Errors"), args, 1);
2937     }
2938     if (appData.premove) {
2939         XtSetValues(XtNameToWidget(menuBarWidget,
2940                                    "menuOptions.Premove"), args, 1);
2941     }
2942     if (appData.quietPlay) {
2943         XtSetValues(XtNameToWidget(menuBarWidget,
2944                                    "menuOptions.Quiet Play"), args, 1);
2945     }
2946     if (appData.showCoords) {
2947         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2948                     args, 1);
2949     }
2950     if (appData.hideThinkingFromHuman) {
2951         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
2952                     args, 1);
2953     }
2954     if (appData.testLegality) {
2955         XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2956                     args, 1);
2957     }
2958
2959     /*
2960      * Create an icon.
2961      */
2962     ReadBitmap(&wIconPixmap, "icon_white.bm",
2963                icon_white_bits, icon_white_width, icon_white_height);
2964     ReadBitmap(&bIconPixmap, "icon_black.bm",
2965                icon_black_bits, icon_black_width, icon_black_height);
2966     iconPixmap = wIconPixmap;
2967     i = 0;
2968     XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
2969     XtSetValues(shellWidget, args, i);
2970
2971     /*
2972      * Create a cursor for the board widget.
2973      */
2974     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2975     XChangeWindowAttributes(xDisplay, xBoardWindow,
2976                             CWCursor, &window_attributes);
2977
2978     /*
2979      * Inhibit shell resizing.
2980      */
2981     shellArgs[0].value = (XtArgVal) &w;
2982     shellArgs[1].value = (XtArgVal) &h;
2983     XtGetValues(shellWidget, shellArgs, 2);
2984     shellArgs[4].value = shellArgs[2].value = w;
2985     shellArgs[5].value = shellArgs[3].value = h;
2986     XtSetValues(shellWidget, &shellArgs[2], 4);
2987     marginW =  w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
2988     marginH =  h - boardHeight;
2989
2990     CatchDeleteWindow(shellWidget, "QuitProc");
2991
2992     CreateGCs();
2993     CreateGrid();
2994 #if HAVE_LIBXPM
2995     if (appData.bitmapDirectory[0] != NULLCHAR) {
2996       CreatePieces();
2997     } else {
2998       CreateXPMPieces();
2999     }
3000 #else
3001     CreateXIMPieces();
3002     /* Create regular pieces */
3003     if (!useImages) CreatePieces();
3004 #endif
3005
3006     CreatePieceMenus();
3007
3008     if (appData.animate || appData.animateDragging)
3009       CreateAnimVars();
3010
3011     XtAugmentTranslations(formWidget,
3012                           XtParseTranslationTable(globalTranslations));
3013     XtAugmentTranslations(boardWidget,
3014                           XtParseTranslationTable(boardTranslations));
3015     XtAugmentTranslations(whiteTimerWidget,
3016                           XtParseTranslationTable(whiteTranslations));
3017     XtAugmentTranslations(blackTimerWidget,
3018                           XtParseTranslationTable(blackTranslations));
3019
3020     /* Why is the following needed on some versions of X instead
3021      * of a translation? */
3022     XtAddEventHandler(boardWidget, ExposureMask, False,
3023                       (XtEventHandler) EventProc, NULL);
3024     /* end why */
3025
3026     InitBackEnd2();
3027
3028     if (errorExitStatus == -1) {
3029         if (appData.icsActive) {
3030             /* We now wait until we see "login:" from the ICS before
3031                sending the logon script (problems with timestamp otherwise) */
3032             /*ICSInitScript();*/
3033             if (appData.icsInputBox) ICSInputBoxPopUp();
3034         }
3035
3036         signal(SIGINT, IntSigHandler);
3037         signal(SIGTERM, IntSigHandler);
3038         if (*appData.cmailGameName != NULLCHAR) {
3039             signal(SIGUSR1, CmailSigHandler);
3040         }
3041     }
3042         InitPosition(TRUE);
3043
3044     XtAppMainLoop(appContext);
3045     if (appData.debugMode) fclose(debugFP); // [DM] debug
3046     return 0;
3047 }
3048
3049 void
3050 ShutDownFrontEnd()
3051 {
3052     if (appData.icsActive && oldICSInteractionTitle != NULL) {
3053         DisplayIcsInteractionTitle(oldICSInteractionTitle);
3054     }
3055     unlink(gameCopyFilename);
3056     unlink(gamePasteFilename);
3057 }
3058
3059 RETSIGTYPE
3060 IntSigHandler(sig)
3061      int sig;
3062 {
3063     ExitEvent(sig);
3064 }
3065
3066 RETSIGTYPE
3067 CmailSigHandler(sig)
3068      int sig;
3069 {
3070     int dummy = 0;
3071     int error;
3072
3073     signal(SIGUSR1, SIG_IGN);   /* suspend handler     */
3074
3075     /* Activate call-back function CmailSigHandlerCallBack()             */
3076     OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3077
3078     signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3079 }
3080
3081 void
3082 CmailSigHandlerCallBack(isr, closure, message, count, error)
3083      InputSourceRef isr;
3084      VOIDSTAR closure;
3085      char *message;
3086      int count;
3087      int error;
3088 {
3089     BoardToTop();
3090     ReloadCmailMsgEvent(TRUE);  /* Reload cmail msg  */
3091 }
3092 /**** end signal code ****/
3093
3094
3095 void
3096 ICSInitScript()
3097 {
3098     FILE *f;
3099     char buf[MSG_SIZ];
3100     char *p;
3101
3102     f = fopen(appData.icsLogon, "r");
3103     if (f == NULL) {
3104         p = getenv("HOME");
3105         if (p != NULL) {
3106             strcpy(buf, p);
3107             strcat(buf, "/");
3108             strcat(buf, appData.icsLogon);
3109             f = fopen(buf, "r");
3110         }
3111     }
3112     if (f != NULL)
3113       ProcessICSInitScript(f);
3114 }
3115
3116 void
3117 ResetFrontEnd()
3118 {
3119     CommentPopDown();
3120     EditCommentPopDown();
3121     TagsPopDown();
3122     return;
3123 }
3124
3125 typedef struct {
3126     char *name;
3127     Boolean value;
3128 } Enables;
3129
3130 void
3131 SetMenuEnables(enab)
3132      Enables *enab;
3133 {
3134   Widget w;
3135   if (!menuBarWidget) return;
3136   while (enab->name != NULL) {
3137     w = XtNameToWidget(menuBarWidget, enab->name);
3138     if (w == NULL) {
3139       DisplayError(enab->name, 0);
3140     } else {
3141       XtSetSensitive(w, enab->value);
3142     }
3143     enab++;
3144   }
3145 }
3146
3147 Enables icsEnables[] = {
3148     { "menuFile.Mail Move", False },
3149     { "menuFile.Reload CMail Message", False },
3150     { "menuMode.Machine Black", False },
3151     { "menuMode.Machine White", False },
3152     { "menuMode.Analysis Mode", False },
3153     { "menuMode.Analyze File", False },
3154     { "menuMode.Two Machines", False },
3155 #ifndef ZIPPY
3156     { "menuHelp.Hint", False },
3157     { "menuHelp.Book", False },
3158     { "menuStep.Move Now", False },
3159     { "menuOptions.Periodic Updates", False },
3160     { "menuOptions.Hide Thinking", False },
3161     { "menuOptions.Ponder Next Move", False },
3162 #endif
3163     { NULL, False }
3164 };
3165
3166 Enables ncpEnables[] = {
3167     { "menuFile.Mail Move", False },
3168     { "menuFile.Reload CMail Message", False },
3169     { "menuMode.Machine White", False },
3170     { "menuMode.Machine Black", False },
3171     { "menuMode.Analysis Mode", False },
3172     { "menuMode.Analyze File", False },
3173     { "menuMode.Two Machines", False },
3174     { "menuMode.ICS Client", False },
3175     { "menuMode.ICS Input Box", False },
3176     { "Action", False },
3177     { "menuStep.Revert", False },
3178     { "menuStep.Move Now", False },
3179     { "menuStep.Retract Move", False },
3180     { "menuOptions.Auto Comment", False },
3181     { "menuOptions.Auto Flag", False },
3182     { "menuOptions.Auto Flip View", False },
3183     { "menuOptions.Auto Observe", False },
3184     { "menuOptions.Auto Raise Board", False },
3185     { "menuOptions.Get Move List", False },
3186     { "menuOptions.ICS Alarm", False },
3187     { "menuOptions.Move Sound", False },
3188     { "menuOptions.Quiet Play", False },
3189     { "menuOptions.Hide Thinking", False },
3190     { "menuOptions.Periodic Updates", False },
3191     { "menuOptions.Ponder Next Move", False },
3192     { "menuHelp.Hint", False },
3193     { "menuHelp.Book", False },
3194     { NULL, False }
3195 };
3196
3197 Enables gnuEnables[] = {
3198     { "menuMode.ICS Client", False },
3199     { "menuMode.ICS Input Box", False },
3200     { "menuAction.Accept", False },
3201     { "menuAction.Decline", False },
3202     { "menuAction.Rematch", False },
3203     { "menuAction.Adjourn", False },
3204     { "menuAction.Stop Examining", False },
3205     { "menuAction.Stop Observing", False },
3206     { "menuStep.Revert", False },
3207     { "menuOptions.Auto Comment", False },
3208     { "menuOptions.Auto Observe", False },
3209     { "menuOptions.Auto Raise Board", False },
3210     { "menuOptions.Get Move List", False },
3211     { "menuOptions.Premove", False },
3212     { "menuOptions.Quiet Play", False },
3213
3214     /* The next two options rely on SetCmailMode being called *after*    */
3215     /* SetGNUMode so that when GNU is being used to give hints these     */
3216     /* menu options are still available                                  */
3217
3218     { "menuFile.Mail Move", False },
3219     { "menuFile.Reload CMail Message", False },
3220     { NULL, False }
3221 };
3222
3223 Enables cmailEnables[] = {
3224     { "Action", True },
3225     { "menuAction.Call Flag", False },
3226     { "menuAction.Draw", True },
3227     { "menuAction.Adjourn", False },
3228     { "menuAction.Abort", False },
3229     { "menuAction.Stop Observing", False },
3230     { "menuAction.Stop Examining", False },
3231     { "menuFile.Mail Move", True },
3232     { "menuFile.Reload CMail Message", True },
3233     { NULL, False }
3234 };
3235
3236 Enables trainingOnEnables[] = {
3237   { "menuMode.Edit Comment", False },
3238   { "menuMode.Pause", False },
3239   { "menuStep.Forward", False },
3240   { "menuStep.Backward", False },
3241   { "menuStep.Forward to End", False },
3242   { "menuStep.Back to Start", False },
3243   { "menuStep.Move Now", False },
3244   { "menuStep.Truncate Game", False },
3245   { NULL, False }
3246 };
3247
3248 Enables trainingOffEnables[] = {
3249   { "menuMode.Edit Comment", True },
3250   { "menuMode.Pause", True },
3251   { "menuStep.Forward", True },
3252   { "menuStep.Backward", True },
3253   { "menuStep.Forward to End", True },
3254   { "menuStep.Back to Start", True },
3255   { "menuStep.Move Now", True },
3256   { "menuStep.Truncate Game", True },
3257   { NULL, False }
3258 };
3259
3260 Enables machineThinkingEnables[] = {
3261   { "menuFile.Load Game", False },
3262   { "menuFile.Load Next Game", False },
3263   { "menuFile.Load Previous Game", False },
3264   { "menuFile.Reload Same Game", False },
3265   { "menuFile.Paste Game", False },
3266   { "menuFile.Load Position", False },
3267   { "menuFile.Load Next Position", False },
3268   { "menuFile.Load Previous Position", False },
3269   { "menuFile.Reload Same Position", False },
3270   { "menuFile.Paste Position", False },
3271   { "menuMode.Machine White", False },
3272   { "menuMode.Machine Black", False },
3273   { "menuMode.Two Machines", False },
3274   { "menuStep.Retract Move", False },
3275   { NULL, False }
3276 };
3277
3278 Enables userThinkingEnables[] = {
3279   { "menuFile.Load Game", True },
3280   { "menuFile.Load Next Game", True },
3281   { "menuFile.Load Previous Game", True },
3282   { "menuFile.Reload Same Game", True },
3283   { "menuFile.Paste Game", True },
3284   { "menuFile.Load Position", True },
3285   { "menuFile.Load Next Position", True },
3286   { "menuFile.Load Previous Position", True },
3287   { "menuFile.Reload Same Position", True },
3288   { "menuFile.Paste Position", True },
3289   { "menuMode.Machine White", True },
3290   { "menuMode.Machine Black", True },
3291   { "menuMode.Two Machines", True },
3292   { "menuStep.Retract Move", True },
3293   { NULL, False }
3294 };
3295
3296 void SetICSMode()
3297 {
3298   SetMenuEnables(icsEnables);
3299
3300 #ifdef ZIPPY
3301   if (appData.zippyPlay && !appData.noChessProgram)   /* [DM] icsEngineAnalyze */
3302      XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3303 #endif
3304 }
3305
3306 void
3307 SetNCPMode()
3308 {
3309   SetMenuEnables(ncpEnables);
3310 }
3311
3312 void
3313 SetGNUMode()
3314 {
3315   SetMenuEnables(gnuEnables);
3316 }
3317
3318 void
3319 SetCmailMode()
3320 {
3321   SetMenuEnables(cmailEnables);
3322 }
3323
3324 void
3325 SetTrainingModeOn()
3326 {
3327   SetMenuEnables(trainingOnEnables);
3328   if (appData.showButtonBar) {
3329     XtSetSensitive(buttonBarWidget, False);
3330   }
3331   CommentPopDown();
3332 }
3333
3334 void
3335 SetTrainingModeOff()
3336 {
3337   SetMenuEnables(trainingOffEnables);
3338   if (appData.showButtonBar) {
3339     XtSetSensitive(buttonBarWidget, True);
3340   }
3341 }
3342
3343 void
3344 SetUserThinkingEnables()
3345 {
3346   if (appData.noChessProgram) return;
3347   SetMenuEnables(userThinkingEnables);
3348 }
3349
3350 void
3351 SetMachineThinkingEnables()
3352 {
3353   if (appData.noChessProgram) return;
3354   SetMenuEnables(machineThinkingEnables);
3355   switch (gameMode) {
3356   case MachinePlaysBlack:
3357   case MachinePlaysWhite:
3358   case TwoMachinesPlay:
3359     XtSetSensitive(XtNameToWidget(menuBarWidget,
3360                                   ModeToWidgetName(gameMode)), True);
3361     break;
3362   default:
3363     break;
3364   }
3365 }
3366
3367 #define Abs(n) ((n)<0 ? -(n) : (n))
3368
3369 /*
3370  * Find a font that matches "pattern" that is as close as
3371  * possible to the targetPxlSize.  Prefer fonts that are k
3372  * pixels smaller to fonts that are k pixels larger.  The
3373  * pattern must be in the X Consortium standard format,
3374  * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3375  * The return value should be freed with XtFree when no
3376  * longer needed.
3377  */
3378 char *FindFont(pattern, targetPxlSize)
3379      char *pattern;
3380      int targetPxlSize;
3381 {
3382     char **fonts, *p, *best, *scalable, *scalableTail;
3383     int i, j, nfonts, minerr, err, pxlSize;
3384
3385 #ifdef ENABLE_NLS
3386     char **missing_list;
3387     int missing_count;
3388     char *def_string, *base_fnt_lst, strInt[3];
3389     XFontSet fntSet;
3390     XFontStruct **fnt_list;
3391
3392     base_fnt_lst = calloc(1, strlen(pattern) + 3);
3393     sprintf(strInt, "%d", targetPxlSize);
3394     p = strstr(pattern, "--");
3395     strncpy(base_fnt_lst, pattern, p - pattern + 2);
3396     strcat(base_fnt_lst, strInt);
3397     strcat(base_fnt_lst, strchr(p + 2, '-'));
3398
3399     if ((fntSet = XCreateFontSet(xDisplay,
3400                                  base_fnt_lst,
3401                                  &missing_list,
3402                                  &missing_count,
3403                                  &def_string)) == NULL) {
3404
3405        fprintf(stderr, _("Unable to create font set.\n"));
3406        exit (2);
3407     }
3408
3409     nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3410 #else
3411     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3412     if (nfonts < 1) {
3413         fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3414                 programName, pattern);
3415         exit(2);
3416     }
3417 #endif
3418
3419     best = fonts[0];
3420     scalable = NULL;
3421     minerr = 999999;
3422     for (i=0; i<nfonts; i++) {
3423         j = 0;
3424         p = fonts[i];
3425         if (*p != '-') continue;
3426         while (j < 7) {
3427             if (*p == NULLCHAR) break;
3428             if (*p++ == '-') j++;
3429         }
3430         if (j < 7) continue;
3431         pxlSize = atoi(p);
3432         if (pxlSize == 0) {
3433             scalable = fonts[i];
3434             scalableTail = p;
3435         } else {
3436             err = pxlSize - targetPxlSize;
3437             if (Abs(err) < Abs(minerr) ||
3438                 (minerr > 0 && err < 0 && -err == minerr)) {
3439                 best = fonts[i];
3440                 minerr = err;
3441             }
3442         }
3443     }
3444     if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3445         /* If the error is too big and there is a scalable font,
3446            use the scalable font. */
3447         int headlen = scalableTail - scalable;
3448         p = (char *) XtMalloc(strlen(scalable) + 10);
3449         while (isdigit(*scalableTail)) scalableTail++;
3450         sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3451     } else {
3452         p = (char *) XtMalloc(strlen(best) + 1);
3453         strcpy(p, best);
3454     }
3455     if (appData.debugMode) {
3456         fprintf(debugFP, _("resolved %s at pixel size %d\n  to %s\n"),
3457                 pattern, targetPxlSize, p);
3458     }
3459 #ifdef ENABLE_NLS
3460     if (missing_count > 0)
3461        XFreeStringList(missing_list);
3462     XFreeFontSet(xDisplay, fntSet);
3463 #else
3464      XFreeFontNames(fonts);
3465 #endif
3466     return p;
3467 }
3468
3469 void CreateGCs()
3470 {
3471     XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3472       | GCBackground | GCFunction | GCPlaneMask;
3473     XGCValues gc_values;
3474     GC copyInvertedGC;
3475
3476     gc_values.plane_mask = AllPlanes;
3477     gc_values.line_width = lineGap;
3478     gc_values.line_style = LineSolid;
3479     gc_values.function = GXcopy;
3480
3481     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3482     gc_values.background = XBlackPixel(xDisplay, xScreen);
3483     lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3484
3485     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3486     gc_values.background = XWhitePixel(xDisplay, xScreen);
3487     coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3488     XSetFont(xDisplay, coordGC, coordFontID);
3489
3490     // [HGM] make font for holdings counts (white on black0
3491     gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3492     gc_values.background = XBlackPixel(xDisplay, xScreen);
3493     countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3494     XSetFont(xDisplay, countGC, countFontID);
3495
3496     if (appData.monoMode) {
3497         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3498         gc_values.background = XWhitePixel(xDisplay, xScreen);
3499         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3500
3501         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3502         gc_values.background = XBlackPixel(xDisplay, xScreen);
3503         lightSquareGC = wbPieceGC
3504           = XtGetGC(shellWidget, value_mask, &gc_values);
3505
3506         gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3507         gc_values.background = XWhitePixel(xDisplay, xScreen);
3508         darkSquareGC = bwPieceGC
3509           = XtGetGC(shellWidget, value_mask, &gc_values);
3510
3511         if (DefaultDepth(xDisplay, xScreen) == 1) {
3512             /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3513             gc_values.function = GXcopyInverted;
3514             copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3515             gc_values.function = GXcopy;
3516             if (XBlackPixel(xDisplay, xScreen) == 1) {
3517                 bwPieceGC = darkSquareGC;
3518                 wbPieceGC = copyInvertedGC;
3519             } else {
3520                 bwPieceGC = copyInvertedGC;
3521                 wbPieceGC = lightSquareGC;
3522             }
3523         }
3524     } else {
3525         gc_values.foreground = highlightSquareColor;
3526         gc_values.background = highlightSquareColor;
3527         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3528
3529         gc_values.foreground = premoveHighlightColor;
3530         gc_values.background = premoveHighlightColor;
3531         prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3532
3533         gc_values.foreground = lightSquareColor;
3534         gc_values.background = darkSquareColor;
3535         lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);