f9ed2d7320e5d5c1c557c89bf2691388d42117d5
[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 Pixel lowTimeWarningColor;
460 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
461   bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
462   wjPieceGC, bjPieceGC, prelineGC, countGC;
463 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
464 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
465   whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
466   commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
467   menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
468   ICSInputShell, fileNameShell, askQuestionShell;
469 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
470 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
471 Font clockFontID, coordFontID, countFontID;
472 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
473 XtAppContext appContext;
474 char *layoutName;
475 char *oldICSInteractionTitle;
476
477 FileProc fileProc;
478 char *fileOpenMode;
479 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
480
481 Position commentX = -1, commentY = -1;
482 Dimension commentW, commentH;
483
484 int squareSize, smallLayout = 0, tinyLayout = 0,
485   marginW, marginH, // [HGM] for run-time resizing
486   fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
487   ICSInputBoxUp = False, askQuestionUp = False,
488   filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
489   editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
490 Pixel timerForegroundPixel, timerBackgroundPixel;
491 Pixel buttonForegroundPixel, buttonBackgroundPixel;
492 char *chessDir, *programName, *programVersion,
493   *gameCopyFilename, *gamePasteFilename;
494
495 #define SOLID 0
496 #define OUTLINE 1
497 Pixmap pieceBitmap[2][(int)BlackPawn];
498 Pixmap xpmPieceBitmap[4][(int)BlackPawn];       /* LL, LD, DL, DD */
499 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
500 int useImages, useImageSqs;
501 XImage *ximPieceBitmap[4][(int)BlackPawn];      /* LL, LD, DL, DD */
502 Pixmap ximMaskPm[(int)BlackPawn];            /* clipmasks, used for XIM pieces */
503 XImage *ximLightSquare, *ximDarkSquare;
504 XImage *xim_Cross;
505
506 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
507 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
508
509 #define White(piece) ((int)(piece) < (int)BlackPawn)
510
511 /* Variables for doing smooth animation. This whole thing
512    would be much easier if the board was double-buffered,
513    but that would require a fairly major rewrite.       */
514
515 typedef struct {
516         Pixmap  saveBuf;
517         Pixmap  newBuf;
518         GC      blitGC, pieceGC, outlineGC;
519         XPoint  startSquare, prevFrame, mouseDelta;
520         int     startColor;
521         int     dragPiece;
522         Boolean dragActive;
523         int     startBoardX, startBoardY;
524     } AnimState;
525
526 /* There can be two pieces being animated at once: a player
527    can begin dragging a piece before the remote opponent has moved. */
528
529 static AnimState game, player;
530
531 /* Bitmaps for use as masks when drawing XPM pieces.
532    Need one for each black and white piece.             */
533 static Pixmap xpmMask[BlackKing + 1];
534
535 /* This magic number is the number of intermediate frames used
536    in each half of the animation. For short moves it's reduced
537    by 1. The total number of frames will be factor * 2 + 1.  */
538 #define kFactor    4
539
540 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
541
542 MenuItem fileMenu[] = {
543     {N_("New Game"), ResetProc},
544     {N_("New Shuffle Game ..."), ShuffleMenuProc},
545     {N_("New Variant ..."), NewVariantProc},      // [HGM] variant: not functional yet
546     {"----", NothingProc},
547     {N_("Load Game"), LoadGameProc},
548     {N_("Load Next Game"), LoadNextGameProc},
549     {N_("Load Previous Game"), LoadPrevGameProc},
550     {N_("Reload Same Game"), ReloadGameProc},
551     {N_("Save Game"), SaveGameProc},
552     {"----", NothingProc},
553     {N_("Copy Game"), CopyGameProc},
554     {N_("Paste Game"), PasteGameProc},
555     {"----", NothingProc},
556     {N_("Load Position"), LoadPositionProc},
557     {N_("Load Next Position"), LoadNextPositionProc},
558     {N_("Load Previous Position"), LoadPrevPositionProc},
559     {N_("Reload Same Position"), ReloadPositionProc},
560     {N_("Save Position"), SavePositionProc},
561     {"----", NothingProc},
562     {N_("Copy Position"), CopyPositionProc},
563     {N_("Paste Position"), PastePositionProc},
564     {"----", NothingProc},
565     {N_("Mail Move"), MailMoveProc},
566     {N_("Reload CMail Message"), ReloadCmailMsgProc},
567     {"----", NothingProc},
568     {N_("Exit"), QuitProc},
569     {NULL, NULL}
570 };
571
572 MenuItem modeMenu[] = {
573     {N_("Machine White"), MachineWhiteProc},
574     {N_("Machine Black"), MachineBlackProc},
575     {N_("Two Machines"), TwoMachinesProc},
576     {N_("Analysis Mode"), AnalyzeModeProc},
577     {N_("Analyze File"), AnalyzeFileProc },
578     {N_("ICS Client"), IcsClientProc},
579     {N_("Edit Game"), EditGameProc},
580     {N_("Edit Position"), EditPositionProc},
581     {N_("Training"), TrainingProc},
582     {"----", NothingProc},
583     {N_("Show Engine Output"), EngineOutputProc},
584     {N_("Show Evaluation Graph"), NothingProc}, // [HGM] evalgr: not functional yet
585     {N_("Show Game List"), ShowGameListProc},
586     {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
587     {"----", NothingProc},
588     {N_("Edit Tags"), EditTagsProc},
589     {N_("Edit Comment"), EditCommentProc},
590     {N_("ICS Input Box"), IcsInputBoxProc},
591     {N_("Pause"), PauseProc},
592     {NULL, NULL}
593 };
594
595 MenuItem actionMenu[] = {
596     {N_("Accept"), AcceptProc},
597     {N_("Decline"), DeclineProc},
598     {N_("Rematch"), RematchProc},
599     {"----", NothingProc},
600     {N_("Call Flag"), CallFlagProc},
601     {N_("Draw"), DrawProc},
602     {N_("Adjourn"), AdjournProc},
603     {N_("Abort"), AbortProc},
604     {N_("Resign"), ResignProc},
605     {"----", NothingProc},
606     {N_("Stop Observing"), StopObservingProc},
607     {N_("Stop Examining"), StopExaminingProc},
608     {"----", NothingProc},
609     {N_("Adjudicate to White"), AdjuWhiteProc},
610     {N_("Adjudicate to Black"), AdjuBlackProc},
611     {N_("Adjudicate Draw"), AdjuDrawProc},
612     {NULL, NULL}
613 };
614
615 MenuItem stepMenu[] = {
616     {N_("Backward"), BackwardProc},
617     {N_("Forward"), ForwardProc},
618     {N_("Back to Start"), ToStartProc},
619     {N_("Forward to End"), ToEndProc},
620     {N_("Revert"), RevertProc},
621     {N_("Truncate Game"), TruncateGameProc},
622     {"----", NothingProc},
623     {N_("Move Now"), MoveNowProc},
624     {N_("Retract Move"), RetractMoveProc},
625     {NULL, NULL}
626 };
627
628 MenuItem optionsMenu[] = {
629     {N_("Flip View"), FlipViewProc},
630     {"----", NothingProc},
631     {N_("Adjudications ..."), EngineMenuProc},
632     {N_("General Settings ..."), UciMenuProc},
633     {N_("Engine #1 Settings ..."), FirstSettingsProc},
634     {N_("Engine #2 Settings ..."), SecondSettingsProc},
635     {N_("Time Control ..."), TimeControlProc},
636     {"----", NothingProc},
637     {N_("Always Queen"), AlwaysQueenProc},
638     {N_("Animate Dragging"), AnimateDraggingProc},
639     {N_("Animate Moving"), AnimateMovingProc},
640     {N_("Auto Comment"), AutocommProc},
641     {N_("Auto Flag"), AutoflagProc},
642     {N_("Auto Flip View"), AutoflipProc},
643     {N_("Auto Observe"), AutobsProc},
644     {N_("Auto Raise Board"), AutoraiseProc},
645     {N_("Auto Save"), AutosaveProc},
646     {N_("Blindfold"), BlindfoldProc},
647     {N_("Flash Moves"), FlashMovesProc},
648     {N_("Get Move List"), GetMoveListProc},
649 #if HIGHDRAG
650     {N_("Highlight Dragging"), HighlightDraggingProc},
651 #endif
652     {N_("Highlight Last Move"), HighlightLastMoveProc},
653     {N_("Move Sound"), MoveSoundProc},
654     {N_("ICS Alarm"), IcsAlarmProc},
655     {N_("Old Save Style"), OldSaveStyleProc},
656     {N_("Periodic Updates"), PeriodicUpdatesProc},
657     {N_("Ponder Next Move"), PonderNextMoveProc},
658     {N_("Popup Exit Message"), PopupExitMessageProc},
659     {N_("Popup Move Errors"), PopupMoveErrorsProc},
660     {N_("Premove"), PremoveProc},
661     {N_("Quiet Play"), QuietPlayProc},
662     {N_("Show Coords"), ShowCoordsProc},
663     {N_("Hide Thinking"), HideThinkingProc},
664     {N_("Test Legality"), TestLegalityProc},
665     {NULL, NULL}
666 };
667
668 MenuItem helpMenu[] = {
669     {N_("Info XBoard"), InfoProc},
670     {N_("Man XBoard"), ManProc},
671     {"----", NothingProc},
672     {N_("Hint"), HintProc},
673     {N_("Book"), BookProc},
674     {"----", NothingProc},
675     {N_("About XBoard"), AboutProc},
676     {NULL, NULL}
677 };
678
679 Menu menuBar[] = {
680     {N_("File"), fileMenu},
681     {N_("Mode"), modeMenu},
682     {N_("Action"), actionMenu},
683     {N_("Step"), stepMenu},
684     {N_("Options"), optionsMenu},
685     {N_("Help"), helpMenu},
686     {NULL, NULL}
687 };
688
689 #define PAUSE_BUTTON N_("P")
690 MenuItem buttonBar[] = {
691     {"<<", ToStartProc},
692     {"<", BackwardProc},
693     {PAUSE_BUTTON, PauseProc},
694     {">", ForwardProc},
695     {">>", ToEndProc},
696     {NULL, NULL}
697 };
698
699 #define PIECE_MENU_SIZE 18
700 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
701     { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
702       N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"), 
703       N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"), 
704       N_("Empty square"), N_("Clear board") },
705     { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
706       N_("Queen"), N_("King"), "----", N_("Elephant"), N_("Cannon"), 
707       N_("Archbishop"), N_("Chancellor"), "----", N_("Promote"), N_("Demote"), 
708       N_("Empty square"), N_("Clear board") }
709 };
710 /* must be in same order as PieceMenuStrings! */
711 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
712     { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
713         WhiteRook, WhiteQueen, WhiteKing, (ChessSquare) 0, WhiteAlfil,
714         WhiteCannon, WhiteAngel, WhiteMarshall, (ChessSquare) 0, 
715         PromotePiece, DemotePiece, EmptySquare, ClearBoard },
716     { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
717         BlackRook, BlackQueen, BlackKing, (ChessSquare) 0, BlackAlfil,
718         BlackCannon, BlackAngel, BlackMarshall, (ChessSquare) 0, 
719         PromotePiece, DemotePiece, EmptySquare, ClearBoard },
720 };
721
722 #define DROP_MENU_SIZE 6
723 String dropMenuStrings[DROP_MENU_SIZE] = {
724     "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
725   };
726 /* must be in same order as PieceMenuStrings! */
727 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
728     (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
729     WhiteRook, WhiteQueen
730 };
731
732 typedef struct {
733     char piece;
734     char* widget;
735 } DropMenuEnables;
736
737 DropMenuEnables dmEnables[] = {
738     { 'P', "Pawn" },
739     { 'N', "Knight" },
740     { 'B', "Bishop" },
741     { 'R', "Rook" },
742     { 'Q', "Queen" }
743 };
744
745 Arg shellArgs[] = {
746     { XtNwidth, 0 },
747     { XtNheight, 0 },
748     { XtNminWidth, 0 },
749     { XtNminHeight, 0 },
750     { XtNmaxWidth, 0 },
751     { XtNmaxHeight, 0 }
752 };
753
754 Arg layoutArgs[] = {
755     { XtNborderWidth, 0 },
756     { XtNdefaultDistance, 0 },
757 };
758
759 Arg formArgs[] = {
760     { XtNborderWidth, 0 },
761     { XtNresizable, (XtArgVal) True },
762 };
763
764 Arg boardArgs[] = {
765     { XtNborderWidth, 0 },
766     { XtNwidth, 0 },
767     { XtNheight, 0 }
768 };
769
770 Arg titleArgs[] = {
771     { XtNjustify, (XtArgVal) XtJustifyRight },
772     { XtNlabel, (XtArgVal) "..." },
773     { XtNresizable, (XtArgVal) True },
774     { XtNresize, (XtArgVal) False }
775 };
776
777 Arg messageArgs[] = {
778     { XtNjustify, (XtArgVal) XtJustifyLeft },
779     { XtNlabel, (XtArgVal) "..." },
780     { XtNresizable, (XtArgVal) True },
781     { XtNresize, (XtArgVal) False }
782 };
783
784 Arg timerArgs[] = {
785     { XtNborderWidth, 0 },
786     { XtNjustify, (XtArgVal) XtJustifyLeft }
787 };
788
789 XtResource clientResources[] = {
790     { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
791         XtOffset(AppDataPtr, whitePieceColor), XtRString,
792         WHITE_PIECE_COLOR },
793     { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
794         XtOffset(AppDataPtr, blackPieceColor), XtRString,
795         BLACK_PIECE_COLOR },
796     { "lightSquareColor", "lightSquareColor", XtRString,
797         sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
798         XtRString, LIGHT_SQUARE_COLOR },
799     { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
800         XtOffset(AppDataPtr, darkSquareColor), XtRString,
801         DARK_SQUARE_COLOR },
802     { "highlightSquareColor", "highlightSquareColor", XtRString,
803         sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
804         XtRString, HIGHLIGHT_SQUARE_COLOR },
805     { "premoveHighlightColor", "premoveHighlightColor", XtRString,
806         sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
807         XtRString, PREMOVE_HIGHLIGHT_COLOR },
808     { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
809         XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
810         (XtPointer) MOVES_PER_SESSION },
811     { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
812         XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
813         (XtPointer) TIME_INCREMENT },
814     { "initString", "initString", XtRString, sizeof(String),
815         XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
816     { "secondInitString", "secondInitString", XtRString, sizeof(String),
817         XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
818     { "firstComputerString", "firstComputerString", XtRString,
819         sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
820       COMPUTER_STRING },
821     { "secondComputerString", "secondComputerString", XtRString,
822         sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
823       COMPUTER_STRING },
824     { "firstChessProgram", "firstChessProgram", XtRString,
825         sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
826         XtRString, FIRST_CHESS_PROGRAM },
827     { "secondChessProgram", "secondChessProgram", XtRString,
828         sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
829         XtRString, SECOND_CHESS_PROGRAM },
830     { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
831         sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
832         XtRImmediate, (XtPointer) False },
833     { "noChessProgram", "noChessProgram", XtRBoolean,
834         sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
835         XtRImmediate, (XtPointer) False },
836     { "firstHost", "firstHost", XtRString, sizeof(String),
837         XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
838     { "secondHost", "secondHost", XtRString, sizeof(String),
839         XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
840     { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
841         XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
842     { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
843         XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
844     { "bitmapDirectory", "bitmapDirectory", XtRString,
845         sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
846         XtRString, "" },
847     { "remoteShell", "remoteShell", XtRString, sizeof(String),
848         XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
849     { "remoteUser", "remoteUser", XtRString, sizeof(String),
850         XtOffset(AppDataPtr, remoteUser), XtRString, "" },
851     { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
852         XtOffset(AppDataPtr, timeDelay), XtRString,
853         (XtPointer) TIME_DELAY_QUOTE },
854     { "timeControl", "timeControl", XtRString, sizeof(String),
855         XtOffset(AppDataPtr, timeControl), XtRString,
856         (XtPointer) TIME_CONTROL },
857     { "internetChessServerMode", "internetChessServerMode",
858         XtRBoolean, sizeof(Boolean),
859         XtOffset(AppDataPtr, icsActive), XtRImmediate,
860         (XtPointer) False },
861     { "internetChessServerHost", "internetChessServerHost",
862         XtRString, sizeof(String),
863         XtOffset(AppDataPtr, icsHost),
864         XtRString, (XtPointer) ICS_HOST },
865     { "internetChessServerPort", "internetChessServerPort",
866         XtRString, sizeof(String),
867         XtOffset(AppDataPtr, icsPort), XtRString,
868         (XtPointer) ICS_PORT },
869     { "internetChessServerCommPort", "internetChessServerCommPort",
870         XtRString, sizeof(String),
871         XtOffset(AppDataPtr, icsCommPort), XtRString,
872         ICS_COMM_PORT },
873     { "internetChessServerLogonScript", "internetChessServerLogonScript",
874         XtRString, sizeof(String),
875         XtOffset(AppDataPtr, icsLogon), XtRString,
876         ICS_LOGON },
877     { "internetChessServerHelper", "internetChessServerHelper",
878         XtRString, sizeof(String),
879         XtOffset(AppDataPtr, icsHelper), XtRString, "" },
880     { "internetChessServerInputBox", "internetChessServerInputBox",
881         XtRBoolean, sizeof(Boolean),
882         XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
883         (XtPointer) False },
884     { "icsAlarm", "icsAlarm",
885         XtRBoolean, sizeof(Boolean),
886         XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
887         (XtPointer) True },
888     { "icsAlarmTime", "icsAlarmTime",
889         XtRInt, sizeof(int),
890         XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
891         (XtPointer) 5000 },
892     { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
893         XtOffset(AppDataPtr, useTelnet), XtRImmediate,
894         (XtPointer) False },
895     { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
896         XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
897     { "gateway", "gateway", XtRString, sizeof(String),
898         XtOffset(AppDataPtr, gateway), XtRString, "" },
899     { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
900         XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
901     { "loadGameIndex", "loadGameIndex",
902         XtRInt, sizeof(int),
903         XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
904         (XtPointer) 0 },
905     { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
906         XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
907     { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
908         sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
909         XtRImmediate, (XtPointer) True },
910     { "autoSaveGames", "autoSaveGames", XtRBoolean,
911         sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
912         XtRImmediate, (XtPointer) False },
913     { "blindfold", "blindfold", XtRBoolean,
914         sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
915         XtRImmediate, (XtPointer) False },
916     { "loadPositionFile", "loadPositionFile", XtRString,
917         sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
918         XtRString, "" },
919     { "loadPositionIndex", "loadPositionIndex",
920         XtRInt, sizeof(int),
921         XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
922         (XtPointer) 1 },
923     { "savePositionFile", "savePositionFile", XtRString,
924         sizeof(String), XtOffset(AppDataPtr, savePositionFile),
925         XtRString, "" },
926     { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
927         XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
928     { "matchGames", "matchGames", XtRInt, sizeof(int),
929         XtOffset(AppDataPtr, matchGames), XtRImmediate,
930         (XtPointer) 0 },
931     { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
932         XtOffset(AppDataPtr, monoMode), XtRImmediate,
933         (XtPointer) False },
934     { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
935         XtOffset(AppDataPtr, debugMode), XtRImmediate,
936         (XtPointer) False },
937     { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
938         XtOffset(AppDataPtr, clockMode), XtRImmediate,
939         (XtPointer) True },
940     { "boardSize", "boardSize", XtRString, sizeof(String),
941         XtOffset(AppDataPtr, boardSize), XtRString, "" },
942     { "searchTime", "searchTime", XtRString, sizeof(String),
943         XtOffset(AppDataPtr, searchTime), XtRString,
944         (XtPointer) "" },
945     { "searchDepth", "searchDepth", XtRInt, sizeof(int),
946         XtOffset(AppDataPtr, searchDepth), XtRImmediate,
947         (XtPointer) 0 },
948     { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
949         XtOffset(AppDataPtr, showCoords), XtRImmediate,
950         (XtPointer) False },
951     { "showJail", "showJail", XtRInt, sizeof(int),
952         XtOffset(AppDataPtr, showJail), XtRImmediate,
953         (XtPointer) 0 },
954     { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
955         XtOffset(AppDataPtr, showThinking), XtRImmediate,
956         (XtPointer) True },
957     { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
958         XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
959         (XtPointer) True },
960     { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
961         XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
962         (XtPointer) True },
963     { "clockFont", "clockFont", XtRString, sizeof(String),
964         XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
965     { "coordFont", "coordFont", XtRString, sizeof(String),
966         XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
967     { "font", "font", XtRString, sizeof(String),
968         XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
969     { "ringBellAfterMoves", "ringBellAfterMoves",
970         XtRBoolean, sizeof(Boolean),
971         XtOffset(AppDataPtr, ringBellAfterMoves),
972         XtRImmediate, (XtPointer) False },
973     { "autoCallFlag", "autoCallFlag", XtRBoolean,
974         sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
975         XtRImmediate, (XtPointer) False },
976     { "autoFlipView", "autoFlipView", XtRBoolean,
977         sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
978         XtRImmediate, (XtPointer) True },
979     { "autoObserve", "autoObserve", XtRBoolean,
980         sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
981         XtRImmediate, (XtPointer) False },
982     { "autoComment", "autoComment", XtRBoolean,
983         sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
984         XtRImmediate, (XtPointer) False },
985     { "getMoveList", "getMoveList", XtRBoolean,
986         sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
987         XtRImmediate, (XtPointer) True },
988 #if HIGHDRAG
989     { "highlightDragging", "highlightDragging", XtRBoolean,
990         sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
991         XtRImmediate, (XtPointer) False },
992 #endif
993     { "highlightLastMove", "highlightLastMove", XtRBoolean,
994         sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
995         XtRImmediate, (XtPointer) False },
996     { "premove", "premove", XtRBoolean,
997         sizeof(Boolean), XtOffset(AppDataPtr, premove),
998         XtRImmediate, (XtPointer) True },
999     { "testLegality", "testLegality", XtRBoolean,
1000         sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
1001         XtRImmediate, (XtPointer) True },
1002     { "flipView", "flipView", XtRBoolean,
1003         sizeof(Boolean), XtOffset(AppDataPtr, flipView),
1004         XtRImmediate, (XtPointer) False },
1005     { "cmail", "cmailGameName", XtRString, sizeof(String),
1006         XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
1007     { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
1008         sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
1009         XtRImmediate, (XtPointer) False },
1010     { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
1011         sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
1012         XtRImmediate, (XtPointer) False },
1013     { "quietPlay", "quietPlay", XtRBoolean,
1014         sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
1015         XtRImmediate, (XtPointer) False },
1016     { "titleInWindow", "titleInWindow", XtRBoolean,
1017         sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
1018         XtRImmediate, (XtPointer) False },
1019     { "localLineEditing", "localLineEditing", XtRBoolean,
1020         sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
1021         XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
1022 #ifdef ZIPPY
1023     { "zippyTalk", "zippyTalk", XtRBoolean,
1024         sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
1025         XtRImmediate, (XtPointer) ZIPPY_TALK },
1026     { "zippyPlay", "zippyPlay", XtRBoolean,
1027         sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
1028         XtRImmediate, (XtPointer) ZIPPY_PLAY },
1029     { "zippyLines", "zippyLines", XtRString, sizeof(String),
1030         XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
1031     { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
1032         XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
1033     { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
1034         XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
1035     { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
1036         XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
1037     { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
1038         XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
1039         ZIPPY_WRONG_PASSWORD },
1040     { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
1041         XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
1042     { "zippyUseI", "zippyUseI", XtRBoolean,
1043         sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
1044         XtRImmediate, (XtPointer) ZIPPY_USE_I },
1045     { "zippyBughouse", "zippyBughouse", XtRInt,
1046         sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
1047         XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
1048     { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
1049         sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
1050         XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
1051     { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1052         XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1053     { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1054         XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1055     { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1056         sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1057         XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1058     { "zippyAbort", "zippyAbort", XtRBoolean,
1059         sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1060         XtRImmediate, (XtPointer) ZIPPY_ABORT },
1061     { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1062         XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1063     { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1064         XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1065         (XtPointer) ZIPPY_MAX_GAMES },
1066     { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1067         XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1068         (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1069     { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
1070         XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
1071         (XtPointer) 0 },
1072 #endif
1073     { "flashCount", "flashCount", XtRInt, sizeof(int),
1074         XtOffset(AppDataPtr, flashCount), XtRImmediate,
1075         (XtPointer) FLASH_COUNT  },
1076     { "flashRate", "flashRate", XtRInt, sizeof(int),
1077         XtOffset(AppDataPtr, flashRate), XtRImmediate,
1078         (XtPointer) FLASH_RATE },
1079     { "pixmapDirectory", "pixmapDirectory", XtRString,
1080         sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1081         XtRString, "" },
1082     { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1083         XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1084         (XtPointer) MS_LOGIN_DELAY },
1085     { "colorizeMessages", "colorizeMessages", XtRBoolean,
1086         sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1087         XtRImmediate, (XtPointer) False },
1088     { "colorShout", "colorShout", XtRString,
1089         sizeof(String), XtOffset(AppDataPtr, colorShout),
1090         XtRString, COLOR_SHOUT },
1091     { "colorSShout", "colorSShout", XtRString,
1092         sizeof(String), XtOffset(AppDataPtr, colorSShout),
1093         XtRString, COLOR_SSHOUT },
1094     { "colorChannel1", "colorChannel1", XtRString,
1095         sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1096         XtRString, COLOR_CHANNEL1 },
1097     { "colorChannel", "colorChannel", XtRString,
1098         sizeof(String), XtOffset(AppDataPtr, colorChannel),
1099         XtRString, COLOR_CHANNEL },
1100     { "colorKibitz", "colorKibitz", XtRString,
1101         sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1102         XtRString, COLOR_KIBITZ },
1103     { "colorTell", "colorTell", XtRString,
1104         sizeof(String), XtOffset(AppDataPtr, colorTell),
1105         XtRString, COLOR_TELL },
1106     { "colorChallenge", "colorChallenge", XtRString,
1107         sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1108         XtRString, COLOR_CHALLENGE },
1109     { "colorRequest", "colorRequest", XtRString,
1110         sizeof(String), XtOffset(AppDataPtr, colorRequest),
1111         XtRString, COLOR_REQUEST },
1112     { "colorSeek", "colorSeek", XtRString,
1113         sizeof(String), XtOffset(AppDataPtr, colorSeek),
1114         XtRString, COLOR_SEEK },
1115     { "colorNormal", "colorNormal", XtRString,
1116         sizeof(String), XtOffset(AppDataPtr, colorNormal),
1117         XtRString, COLOR_NORMAL },
1118     { "soundProgram", "soundProgram", XtRString,
1119       sizeof(String), XtOffset(AppDataPtr, soundProgram),
1120       XtRString, "play" },
1121     { "soundShout", "soundShout", XtRString,
1122       sizeof(String), XtOffset(AppDataPtr, soundShout),
1123       XtRString, "" },
1124     { "soundSShout", "soundSShout", XtRString,
1125       sizeof(String), XtOffset(AppDataPtr, soundSShout),
1126       XtRString, "" },
1127     { "soundChannel1", "soundChannel1", XtRString,
1128       sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1129       XtRString, "" },
1130     { "soundChannel", "soundChannel", XtRString,
1131       sizeof(String), XtOffset(AppDataPtr, soundChannel),
1132       XtRString, "" },
1133     { "soundKibitz", "soundKibitz", XtRString,
1134       sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1135       XtRString, "" },
1136     { "soundTell", "soundTell", XtRString,
1137       sizeof(String), XtOffset(AppDataPtr, soundTell),
1138       XtRString, "" },
1139     { "soundChallenge", "soundChallenge", XtRString,
1140       sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1141       XtRString, "" },
1142     { "soundRequest", "soundRequest", XtRString,
1143       sizeof(String), XtOffset(AppDataPtr, soundRequest),
1144       XtRString, "" },
1145     { "soundSeek", "soundSeek", XtRString,
1146       sizeof(String), XtOffset(AppDataPtr, soundSeek),
1147       XtRString, "" },
1148     { "soundMove", "soundMove", XtRString,
1149       sizeof(String), XtOffset(AppDataPtr, soundMove),
1150       XtRString, "$" },
1151     { "soundIcsWin", "soundIcsWin", XtRString,
1152       sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1153       XtRString, "" },
1154     { "soundIcsLoss", "soundIcsLoss", XtRString,
1155       sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1156       XtRString, "" },
1157     { "soundIcsDraw", "soundIcsDraw", XtRString,
1158       sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1159       XtRString, "" },
1160     { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1161       sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1162       XtRString, "" },
1163     { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1164       sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1165       XtRString, "$" },
1166     { "reuseFirst", "reuseFirst", XtRBoolean,
1167         sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1168         XtRImmediate, (XtPointer) True },
1169     { "reuseSecond", "reuseSecond", XtRBoolean,
1170         sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1171         XtRImmediate, (XtPointer) True },
1172     { "animateDragging", "animateDragging", XtRBoolean,
1173         sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1174         XtRImmediate, (XtPointer) True },
1175     { "animateMoving", "animateMoving", XtRBoolean,
1176         sizeof(Boolean), XtOffset(AppDataPtr, animate),
1177         XtRImmediate, (XtPointer) True },
1178     { "animateSpeed", "animateSpeed", XtRInt,
1179         sizeof(int), XtOffset(AppDataPtr, animSpeed),
1180         XtRImmediate, (XtPointer)10 },
1181     { "popupExitMessage", "popupExitMessage", XtRBoolean,
1182         sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1183         XtRImmediate, (XtPointer) True },
1184     { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1185         sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1186         XtRImmediate, (XtPointer) False },
1187     { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1188         sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1189         XtRImmediate, (XtPointer)4 },
1190     { "initialMode", "initialMode", XtRString,
1191         sizeof(String), XtOffset(AppDataPtr, initialMode),
1192         XtRImmediate, (XtPointer) "" },
1193     { "variant", "variant", XtRString,
1194         sizeof(String), XtOffset(AppDataPtr, variant),
1195         XtRImmediate, (XtPointer) "normal" },
1196     { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1197         sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1198         XtRImmediate, (XtPointer)PROTOVER },
1199     { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1200         sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1201         XtRImmediate, (XtPointer)PROTOVER },
1202     { "showButtonBar", "showButtonBar", XtRBoolean,
1203         sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1204         XtRImmediate, (XtPointer) True },
1205     { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
1206       sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
1207       XtRString, COLOR_LOWTIMEWARNING },
1208     { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
1209       sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
1210       XtRImmediate, (XtPointer) False },
1211     {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean,        /* [DM] icsEngineAnalyze */
1212         sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1213         XtRImmediate, (XtPointer) False },
1214     { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
1215         sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
1216         XtRImmediate, (XtPointer) False },
1217     { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
1218         sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
1219         XtRImmediate, (XtPointer) False },
1220     { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
1221         sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
1222         XtRImmediate, (XtPointer) False },
1223     { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
1224         sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
1225         XtRImmediate, (XtPointer) True },
1226     { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
1227         sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
1228         XtRImmediate, (XtPointer) 0},
1229     { "pgnEventHeader", "pgnEventHeader", XtRString,
1230         sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
1231         XtRImmediate, (XtPointer) "Computer Chess Game" },
1232     { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
1233         sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
1234         XtRImmediate, (XtPointer) -1},
1235     { "gameListTags", "gameListTags", XtRString,
1236         sizeof(String), XtOffset(AppDataPtr, gameListTags),
1237         XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
1238
1239     // [HGM] 4.3.xx options
1240     { "boardWidth", "boardWidth", XtRInt,
1241         sizeof(int), XtOffset(AppDataPtr, NrFiles),
1242         XtRImmediate, (XtPointer) -1},
1243     { "boardHeight", "boardHeight", XtRInt,
1244         sizeof(int), XtOffset(AppDataPtr, NrRanks),
1245         XtRImmediate, (XtPointer) -1},
1246     { "matchPause", "matchPause", XtRInt,
1247         sizeof(int), XtOffset(AppDataPtr, matchPause),
1248         XtRImmediate, (XtPointer) 10000},
1249     { "holdingsSize", "holdingsSize", XtRInt,
1250         sizeof(int), XtOffset(AppDataPtr, holdingsSize),
1251         XtRImmediate, (XtPointer) -1},
1252     { "flipBlack", "flipBlack", XtRBoolean,
1253         sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
1254         XtRImmediate, (XtPointer) False},
1255     { "allWhite", "allWhite", XtRBoolean,
1256         sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
1257         XtRImmediate, (XtPointer) False},
1258     { "pieceToCharTable", "pieceToCharTable", XtRString,
1259         sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
1260         XtRImmediate, (XtPointer) 0},
1261     { "alphaRank", "alphaRank", XtRBoolean,
1262         sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
1263         XtRImmediate, (XtPointer) False},
1264     { "testClaims", "testClaims", XtRBoolean,
1265         sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
1266         XtRImmediate, (XtPointer) True},
1267     { "checkMates", "checkMates", XtRBoolean,
1268         sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
1269         XtRImmediate, (XtPointer) True},
1270     { "materialDraws", "materialDraws", XtRBoolean,
1271         sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
1272         XtRImmediate, (XtPointer) True},
1273     { "trivialDraws", "trivialDraws", XtRBoolean,
1274         sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
1275         XtRImmediate, (XtPointer) False},
1276     { "ruleMoves", "ruleMoves", XtRInt,
1277         sizeof(int), XtOffset(AppDataPtr, ruleMoves),
1278         XtRImmediate, (XtPointer) 51},
1279     { "repeatsToDraw", "repeatsToDraw", XtRInt,
1280         sizeof(int), XtOffset(AppDataPtr, drawRepeats),
1281         XtRImmediate, (XtPointer) 6},
1282     { "engineDebugOutput", "engineDebugOutput", XtRInt,
1283         sizeof(int), XtOffset(AppDataPtr, engineComments),
1284         XtRImmediate, (XtPointer) 1},
1285     { "userName", "userName", XtRString,
1286         sizeof(int), XtOffset(AppDataPtr, userName),
1287         XtRImmediate, (XtPointer) 0},
1288     { "autoKibitz", "autoKibitz", XtRBoolean,
1289         sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
1290         XtRImmediate, (XtPointer) False},
1291     { "firstTimeOdds", "firstTimeOdds", XtRInt,
1292         sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
1293         XtRImmediate, (XtPointer) 1},
1294     { "secondTimeOdds", "secondTimeOdds", XtRInt,
1295         sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
1296         XtRImmediate, (XtPointer) 1},
1297     { "timeOddsMode", "timeOddsMode", XtRInt,
1298         sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
1299         XtRImmediate, (XtPointer) 0},
1300     { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
1301         sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
1302         XtRImmediate, (XtPointer) 1},
1303     { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
1304         sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
1305         XtRImmediate, (XtPointer) 1},
1306     { "firstNPS", "firstNPS", XtRInt,
1307         sizeof(int), XtOffset(AppDataPtr, firstNPS),
1308         XtRImmediate, (XtPointer) -1},
1309     { "secondNPS", "secondNPS", XtRInt,
1310         sizeof(int), XtOffset(AppDataPtr, secondNPS),
1311         XtRImmediate, (XtPointer) -1},
1312     { "serverMoves", "serverMoves", XtRString,
1313         sizeof(String), XtOffset(AppDataPtr, serverMovesName),
1314         XtRImmediate, (XtPointer) 0},
1315     { "serverPause", "serverPause", XtRInt,
1316         sizeof(int), XtOffset(AppDataPtr, serverPause),
1317         XtRImmediate, (XtPointer) 0},
1318     { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
1319         sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
1320         XtRImmediate, (XtPointer) False},
1321     { "userName", "userName", XtRString,
1322         sizeof(String), XtOffset(AppDataPtr, userName),
1323         XtRImmediate, (XtPointer) 0},
1324     { "egtFormats", "egtFormats", XtRString,
1325         sizeof(String), XtOffset(AppDataPtr, egtFormats),
1326         XtRImmediate, (XtPointer) 0},
1327     { "rewindIndex", "rewindIndex", XtRInt,
1328         sizeof(int), XtOffset(AppDataPtr, rewindIndex),
1329         XtRImmediate, (XtPointer) 0},
1330     { "sameColorGames", "sameColorGames", XtRInt,
1331         sizeof(int), XtOffset(AppDataPtr, sameColorGames),
1332         XtRImmediate, (XtPointer) 0},
1333     { "smpCores", "smpCores", XtRInt,
1334         sizeof(int), XtOffset(AppDataPtr, smpCores),
1335         XtRImmediate, (XtPointer) 1},
1336     { "niceEngines", "niceEngines", XtRInt,
1337         sizeof(int), XtOffset(AppDataPtr, niceEngines),
1338         XtRImmediate, (XtPointer) 0},
1339     { "nameOfDebugFile", "nameOfDebugFile", XtRString,
1340         sizeof(String), XtOffset(AppDataPtr, nameOfDebugFile),
1341         XtRImmediate, (XtPointer) "xboard.debug"},
1342     { "engineDebugOutput", "engineDebugOutput", XtRInt,
1343         sizeof(int), XtOffset(AppDataPtr, engineComments),
1344         XtRImmediate, (XtPointer) 0},
1345     { "noGUI", "noGUI", XtRBoolean,
1346         sizeof(Boolean), XtOffset(AppDataPtr, noGUI),
1347         XtRImmediate, (XtPointer) 0},
1348     { "firstOptions", "firstOptions", XtRString,
1349         sizeof(String), XtOffset(AppDataPtr, firstOptions),
1350         XtRImmediate, (XtPointer) "" },
1351     { "secondOptions", "secondOptions", XtRString,
1352         sizeof(String), XtOffset(AppDataPtr, secondOptions),
1353         XtRImmediate, (XtPointer) "" },
1354     { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
1355         sizeof(String), XtOffset(AppDataPtr, fenOverride1),
1356         XtRImmediate, (XtPointer) 0 },
1357     { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
1358         sizeof(String), XtOffset(AppDataPtr, fenOverride2),
1359         XtRImmediate, (XtPointer) 0 },
1360
1361     // [HGM] Winboard_x UCI options
1362     { "firstIsUCI", "firstIsUCI", XtRBoolean,
1363         sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
1364         XtRImmediate, (XtPointer) False},
1365     { "secondIsUCI", "secondIsUCI", XtRBoolean,
1366         sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
1367         XtRImmediate, (XtPointer) False},
1368     { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
1369         sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
1370         XtRImmediate, (XtPointer) True},
1371     { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
1372         sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
1373         XtRImmediate, (XtPointer) True},
1374     { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
1375         sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
1376         XtRImmediate, (XtPointer) False},
1377     { "defaultHashSize", "defaultHashSize", XtRInt,
1378         sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
1379         XtRImmediate, (XtPointer) 64},
1380     { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
1381         sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
1382         XtRImmediate, (XtPointer) 4},
1383     { "polyglotDir", "polyglotDir", XtRString,
1384         sizeof(String), XtOffset(AppDataPtr, polyglotDir),
1385         XtRImmediate, (XtPointer) "." },
1386     { "polyglotBook", "polyglotBook", XtRString,
1387         sizeof(String), XtOffset(AppDataPtr, polyglotBook),
1388         XtRImmediate, (XtPointer) "" },
1389     { "defaultPathEGTB", "defaultPathEGTB", XtRString,
1390         sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
1391         XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
1392     { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
1393         sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
1394         XtRImmediate, (XtPointer) 0},
1395     { "delayAfterQuit", "delayAfterQuit", XtRInt,
1396         sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
1397         XtRImmediate, (XtPointer) 0},
1398 };
1399
1400 XrmOptionDescRec shellOptions[] = {
1401     { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1402     { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1403     { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1404     { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1405     { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1406     { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1407     { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1408     { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1409     { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1410     { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1411     { "-initString", "initString", XrmoptionSepArg, NULL },
1412     { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1413     { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1414     { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1415     { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1416     { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1417     { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1418     { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1419     { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1420     { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1421     { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1422     { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1423     { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1424     { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1425     { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1426     { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1427     { "-fh", "firstHost", XrmoptionSepArg, NULL },
1428     { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1429     { "-sh", "secondHost", XrmoptionSepArg, NULL },
1430     { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1431     { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1432     { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1433     { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1434     { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1435     { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1436     { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1437     { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1438     { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1439     { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1440     { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1441     { "-td", "timeDelay", XrmoptionSepArg, NULL },
1442     { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1443     { "-tc", "timeControl", XrmoptionSepArg, NULL },
1444     { "-internetChessServerMode", "internetChessServerMode",
1445         XrmoptionSepArg, NULL },
1446     { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1447     { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1448     { "-internetChessServerHost", "internetChessServerHost",
1449         XrmoptionSepArg, NULL },
1450     { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1451     { "-internetChessServerPort", "internetChessServerPort",
1452         XrmoptionSepArg, NULL },
1453     { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1454     { "-internetChessServerCommPort", "internetChessServerCommPort",
1455         XrmoptionSepArg, NULL },
1456     { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1457     { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1458         XrmoptionSepArg, NULL },
1459     { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1460     { "-internetChessServerHelper", "internetChessServerHelper",
1461         XrmoptionSepArg, NULL },
1462     { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1463     { "-internetChessServerInputBox", "internetChessServerInputBox",
1464         XrmoptionSepArg, NULL },
1465     { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1466     { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1467     { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1468     { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1469     { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1470     { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1471     { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1472     { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1473     { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1474     { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1475     { "-gateway", "gateway", XrmoptionSepArg, NULL },
1476     { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1477     { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1478     { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1479     { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1480     { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1481     { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1482     { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1483     { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1484     { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1485     { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1486     { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1487     { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1488     { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1489     { "-blind", "blindfold", XrmoptionNoArg, "True" },
1490     { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1491     { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1492     { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1493     { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1494     { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1495     { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1496     { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1497     { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1498     { "-mm", "matchMode", XrmoptionNoArg, "True" },
1499     { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1500     { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1501     { "-mg", "matchGames", XrmoptionSepArg, NULL },
1502     { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1503     { "-mono", "monoMode", XrmoptionNoArg, "True" },
1504     { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1505     { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1506     { "-debug", "debugMode", XrmoptionNoArg, "True" },
1507     { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1508     { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1509     { "-clock", "clockMode", XrmoptionNoArg, "True" },
1510     { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1511     { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1512     { "-size", "boardSize", XrmoptionSepArg, NULL },
1513     { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1514     { "-st", "searchTime", XrmoptionSepArg, NULL },
1515     { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1516     { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1517     { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1518     { "-coords", "showCoords", XrmoptionNoArg, "True" },
1519     { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1520 #if JAIL
1521     { "-showJail", "showJail", XrmoptionSepArg, NULL },
1522     { "-jail", "showJail", XrmoptionNoArg, "1" },
1523     { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1524     { "-xjail", "showJail", XrmoptionNoArg, "0" },
1525 #endif
1526     { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1527     { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1528     { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1529     { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1530     { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1531     { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1532     { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1533     { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1534     { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1535     { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1536     { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1537     { "-font", "font", XrmoptionSepArg, NULL },
1538     { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1539     { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1540     { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1541     { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1542     { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1543     { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1544     { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1545     { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1546     { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1547     { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1548     { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1549     { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1550     { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1551     { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1552     { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1553     { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1554     { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1555     { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1556     { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1557     { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1558 #if HIGHDRAG
1559     { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1560     { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1561     { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1562 #endif
1563     { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1564     { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1565     { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1566     { "-premove", "premove", XrmoptionSepArg, NULL },
1567     { "-pre", "premove", XrmoptionNoArg, "True" },
1568     { "-xpre", "premove", XrmoptionNoArg, "False" },
1569     { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1570     { "-legal", "testLegality", XrmoptionNoArg, "True" },
1571     { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1572     { "-flipView", "flipView", XrmoptionSepArg, NULL },
1573     { "-flip", "flipView", XrmoptionNoArg, "True" },
1574     { "-xflip", "flipView", XrmoptionNoArg, "False" },
1575     { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1576     { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1577         XrmoptionSepArg, NULL },
1578     { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1579     { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1580     { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1581     { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1582     { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1583     { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1584     { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1585     { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1586     { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1587     { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1588     { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1589 #ifdef ZIPPY
1590     { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1591     { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1592     { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1593     { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1594     { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1595     { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1596     { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1597     { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1598     { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1599     { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1600     { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1601     { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1602     { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1603     { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1604     { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1605     { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1606     { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1607     { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1608     { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1609     { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1610     { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1611     { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1612     { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1613     { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1614     { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1615     { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1616     { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1617     { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1618     { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1619     { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1620     { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
1621 #endif
1622     { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1623     { "-flash", "flashCount", XrmoptionNoArg, "3" },
1624     { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1625     { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1626     { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1627     { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1628     { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1629     { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1630     { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1631     { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1632     { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1633     { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1634     { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1635     { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1636     { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1637     { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1638     { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1639     { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1640     { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1641     { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1642     { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1643     { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1644     { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1645     { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1646     { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1647     { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1648     { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1649     { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1650     { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1651     { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1652     { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1653     { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1654     { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1655     { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1656     { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1657     { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1658     { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1659     { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1660     { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1661     { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1662     { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1663     { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1664     { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1665     { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1666     { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1667     { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1668     { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1669     { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1670     { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1671     { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1672     { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1673     { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1674     { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1675     { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1676     { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1677     { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1678     { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1679     { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1680     { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1681     { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1682     { "-mode", "initialMode", XrmoptionSepArg, NULL },
1683     { "-variant", "variant", XrmoptionSepArg, NULL },
1684     { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1685     { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1686     { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1687     { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1688     { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1689     { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
1690     { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
1691     /* [AS,HR] New features */
1692     { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
1693     { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
1694     { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
1695     { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
1696     { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
1697     { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
1698     { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
1699     { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
1700     { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
1701     { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
1702     { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
1703     { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
1704     { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1705     { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1706     { "-firstXBook", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
1707     { "-secondXBook", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
1708     { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
1709     { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
1710     { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
1711     { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
1712     { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
1713     { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
1714     { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
1715     { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
1716     // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
1717
1718     /* [HGM,HR] User-selectable board size */
1719     { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
1720     { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
1721     { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
1722
1723     /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
1724     { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
1725     { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL },       // requires front-end changes to work
1726     { "-allWhite", "allWhite", XrmoptionSepArg, NULL },         // requires front-end changes to work
1727     { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
1728     { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
1729     { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
1730     { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
1731     { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
1732     { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
1733     { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
1734     { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
1735     { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1736     { "-userName", "userName", XrmoptionSepArg, NULL },
1737     { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
1738     { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
1739     { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
1740     { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
1741     { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
1742     { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
1743     { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
1744     { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
1745     { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
1746     { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
1747     { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
1748     { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
1749     { "-userName", "userName", XrmoptionSepArg, NULL },
1750     { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
1751     { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
1752     { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
1753     { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
1754     { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
1755     { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
1756     { "-nameOfDebugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1757     { "-debugFile", "nameOfDebugFile", XrmoptionSepArg, NULL },
1758     { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
1759     { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
1760     { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
1761     { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
1762     { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1763     { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
1764 };
1765
1766
1767 XtActionsRec boardActions[] = {
1768     { "DrawPosition", DrawPositionProc },
1769     { "HandleUserMove", HandleUserMove },
1770     { "AnimateUserMove", AnimateUserMove },
1771     { "FileNameAction", FileNameAction },
1772     { "AskQuestionProc", AskQuestionProc },
1773     { "AskQuestionReplyAction", AskQuestionReplyAction },
1774     { "PieceMenuPopup", PieceMenuPopup },
1775     { "WhiteClock", WhiteClock },
1776     { "BlackClock", BlackClock },
1777     { "Iconify", Iconify },
1778     { "ResetProc", ResetProc },
1779     { "LoadGameProc", LoadGameProc },
1780     { "LoadNextGameProc", LoadNextGameProc },
1781     { "LoadPrevGameProc", LoadPrevGameProc },
1782     { "LoadSelectedProc", LoadSelectedProc },
1783     { "ReloadGameProc", ReloadGameProc },
1784     { "LoadPositionProc", LoadPositionProc },
1785     { "LoadNextPositionProc", LoadNextPositionProc },
1786     { "LoadPrevPositionProc", LoadPrevPositionProc },
1787     { "ReloadPositionProc", ReloadPositionProc },
1788     { "CopyPositionProc", CopyPositionProc },
1789     { "PastePositionProc", PastePositionProc },
1790     { "CopyGameProc", CopyGameProc },
1791     { "PasteGameProc", PasteGameProc },
1792     { "SaveGameProc", SaveGameProc },
1793     { "SavePositionProc", SavePositionProc },
1794     { "MailMoveProc", MailMoveProc },
1795     { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1796     { "QuitProc", QuitProc },
1797     { "MachineWhiteProc", MachineWhiteProc },
1798     { "MachineBlackProc", MachineBlackProc },
1799     { "AnalysisModeProc", AnalyzeModeProc },
1800     { "AnalyzeFileProc", AnalyzeFileProc },
1801     { "TwoMachinesProc", TwoMachinesProc },
1802     { "IcsClientProc", IcsClientProc },
1803     { "EditGameProc", EditGameProc },
1804     { "EditPositionProc", EditPositionProc },
1805     { "TrainingProc", EditPositionProc },
1806     { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
1807     { "ShowGameListProc", ShowGameListProc },
1808     { "ShowMoveListProc", HistoryShowProc},
1809     { "EditTagsProc", EditCommentProc },
1810     { "EditCommentProc", EditCommentProc },
1811     { "IcsAlarmProc", IcsAlarmProc },
1812     { "IcsInputBoxProc", IcsInputBoxProc },
1813     { "PauseProc", PauseProc },
1814     { "AcceptProc", AcceptProc },
1815     { "DeclineProc", DeclineProc },
1816     { "RematchProc", RematchProc },
1817     { "CallFlagProc", CallFlagProc },
1818     { "DrawProc", DrawProc },
1819     { "AdjournProc", AdjournProc },
1820     { "AbortProc", AbortProc },
1821     { "ResignProc", ResignProc },
1822     { "AdjuWhiteProc", AdjuWhiteProc },
1823     { "AdjuBlackProc", AdjuBlackProc },
1824     { "AdjuDrawProc", AdjuDrawProc },
1825     { "EnterKeyProc", EnterKeyProc },
1826     { "StopObservingProc", StopObservingProc },
1827     { "StopExaminingProc", StopExaminingProc },
1828     { "BackwardProc", BackwardProc },
1829     { "ForwardProc", ForwardProc },
1830     { "ToStartProc", ToStartProc },
1831     { "ToEndProc", ToEndProc },
1832     { "RevertProc", RevertProc },
1833     { "TruncateGameProc", TruncateGameProc },
1834     { "MoveNowProc", MoveNowProc },
1835     { "RetractMoveProc", RetractMoveProc },
1836     { "AlwaysQueenProc", AlwaysQueenProc },
1837     { "AnimateDraggingProc", AnimateDraggingProc },
1838     { "AnimateMovingProc", AnimateMovingProc },
1839     { "AutoflagProc", AutoflagProc },
1840     { "AutoflipProc", AutoflipProc },
1841     { "AutobsProc", AutobsProc },
1842     { "AutoraiseProc", AutoraiseProc },
1843     { "AutosaveProc", AutosaveProc },
1844     { "BlindfoldProc", BlindfoldProc },
1845     { "FlashMovesProc", FlashMovesProc },
1846     { "FlipViewProc", FlipViewProc },
1847     { "GetMoveListProc", GetMoveListProc },
1848 #if HIGHDRAG
1849     { "HighlightDraggingProc", HighlightDraggingProc },
1850 #endif
1851     { "HighlightLastMoveProc", HighlightLastMoveProc },
1852     { "IcsAlarmProc", IcsAlarmProc },
1853     { "MoveSoundProc", MoveSoundProc },
1854     { "OldSaveStyleProc", OldSaveStyleProc },
1855     { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1856     { "PonderNextMoveProc", PonderNextMoveProc },
1857     { "PopupExitMessageProc", PopupExitMessageProc },
1858     { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1859     { "PremoveProc", PremoveProc },
1860     { "QuietPlayProc", QuietPlayProc },
1861     { "ShowCoordsProc", ShowCoordsProc },
1862     { "ShowThinkingProc", ShowThinkingProc },
1863     { "HideThinkingProc", HideThinkingProc },
1864     { "TestLegalityProc", TestLegalityProc },
1865     { "InfoProc", InfoProc },
1866     { "ManProc", ManProc },
1867     { "HintProc", HintProc },
1868     { "BookProc", BookProc },
1869     { "AboutGameProc", AboutGameProc },
1870     { "AboutProc", AboutProc },
1871     { "DebugProc", DebugProc },
1872     { "NothingProc", NothingProc },
1873     { "CommentPopDown", (XtActionProc) CommentPopDown },
1874     { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1875     { "TagsPopDown", (XtActionProc) TagsPopDown },
1876     { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1877     { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1878     { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1879     { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1880     { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1881     { "GameListPopDown", (XtActionProc) GameListPopDown },
1882     { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1883     { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1884     { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
1885     { "ShufflePopDown", (XtActionProc) ShufflePopDown },
1886     { "EnginePopDown", (XtActionProc) EnginePopDown },
1887     { "UciPopDown", (XtActionProc) UciPopDown },
1888     { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
1889     { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
1890     { "SettingsPopDown", (XtActionProc) SettingsPopDown },
1891 };
1892
1893 char globalTranslations[] =
1894   ":<Key>R: ResignProc() \n \
1895    :<Key>r: ResetProc() \n \
1896    :<Key>g: LoadGameProc() \n \
1897    :<Key>N: LoadNextGameProc() \n \
1898    :<Key>P: LoadPrevGameProc() \n \
1899    :<Key>Q: QuitProc() \n \
1900    :<Key>F: ToEndProc() \n \
1901    :<Key>f: ForwardProc() \n \
1902    :<Key>B: ToStartProc() \n \
1903    :<Key>b: BackwardProc() \n \
1904    :<Key>p: PauseProc() \n \
1905    :<Key>d: DrawProc() \n \
1906    :<Key>t: CallFlagProc() \n \
1907    :<Key>i: Iconify() \n \
1908    :<Key>c: Iconify() \n \
1909    :<Key>v: FlipViewProc() \n \
1910    <KeyDown>Control_L: BackwardProc() \n \
1911    <KeyUp>Control_L: ForwardProc() \n \
1912    <KeyDown>Control_R: BackwardProc() \n \
1913    <KeyUp>Control_R: ForwardProc() \n \
1914    Shift<Key>1: AskQuestionProc(\"Direct command\",\
1915                                 \"Send to chess program:\",,1) \n \
1916    Shift<Key>2: AskQuestionProc(\"Direct command\",\
1917                                 \"Send to second chess program:\",,2) \n";
1918
1919 char boardTranslations[] =
1920    "<Btn1Down>: HandleUserMove() \n \
1921    <Btn1Up>: HandleUserMove() \n \
1922    <Btn1Motion>: AnimateUserMove() \n \
1923    Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1924                  PieceMenuPopup(menuB) \n \
1925    Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1926                  PieceMenuPopup(menuW) \n \
1927    Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1928                  PieceMenuPopup(menuW) \n \
1929    Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1930                  PieceMenuPopup(menuB) \n";
1931
1932 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1933 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1934
1935 char ICSInputTranslations[] =
1936     "<Key>Return: EnterKeyProc() \n";
1937
1938 String xboardResources[] = {
1939     "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1940     "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1941     "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1942     NULL
1943   };
1944
1945
1946 /* Max possible square size */
1947 #define MAXSQSIZE 256
1948
1949 static int xpm_avail[MAXSQSIZE];
1950
1951 #ifdef HAVE_DIR_STRUCT
1952
1953 /* Extract piece size from filename */
1954 static int
1955 xpm_getsize(name, len, ext)
1956      char *name;
1957      int len;
1958      char *ext;
1959 {
1960     char *p, *d;
1961     char buf[10];
1962
1963     if (len < 4)
1964       return 0;
1965
1966     if ((p=strchr(name, '.')) == NULL ||
1967         StrCaseCmp(p+1, ext) != 0)
1968       return 0;
1969
1970     p = name + 3;
1971     d = buf;
1972
1973     while (*p && isdigit(*p))
1974       *(d++) = *(p++);
1975
1976     *d = 0;
1977     return atoi(buf);
1978 }
1979
1980 /* Setup xpm_avail */
1981 static int
1982 xpm_getavail(dirname, ext)
1983      char *dirname;
1984      char *ext;
1985 {
1986     DIR *dir;
1987     struct dirent *ent;
1988     int  i;
1989
1990     for (i=0; i<MAXSQSIZE; ++i)
1991       xpm_avail[i] = 0;
1992
1993     if (appData.debugMode)
1994       fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1995
1996     dir = opendir(dirname);
1997     if (!dir)
1998       {
1999           fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
2000                   programName, dirname);
2001           exit(1);
2002       }
2003
2004     while ((ent=readdir(dir)) != NULL) {
2005         i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
2006         if (i > 0 && i < MAXSQSIZE)
2007           xpm_avail[i] = 1;
2008     }
2009
2010     closedir(dir);
2011
2012     return 0;
2013 }
2014
2015 void
2016 xpm_print_avail(fp, ext)
2017      FILE *fp;
2018      char *ext;
2019 {
2020     int i;
2021
2022     fprintf(fp, _("Available `%s' sizes:\n"), ext);
2023     for (i=1; i<MAXSQSIZE; ++i) {
2024         if (xpm_avail[i])
2025           printf("%d\n", i);
2026     }
2027 }
2028
2029 /* Return XPM piecesize closest to size */
2030 int
2031 xpm_closest_to(dirname, size, ext)
2032      char *dirname;
2033      int size;
2034      char *ext;
2035 {
2036     int i;
2037     int sm_diff = MAXSQSIZE;
2038     int sm_index = 0;
2039     int diff;
2040
2041     xpm_getavail(dirname, ext);
2042
2043     if (appData.debugMode)
2044       xpm_print_avail(stderr, ext);
2045
2046     for (i=1; i<MAXSQSIZE; ++i) {
2047         if (xpm_avail[i]) {
2048             diff = size - i;
2049             diff = (diff<0) ? -diff : diff;
2050             if (diff < sm_diff) {
2051                 sm_diff = diff;
2052                 sm_index = i;
2053             }
2054         }
2055     }
2056
2057     if (!sm_index) {
2058         fprintf(stderr, _("Error: No `%s' files!\n"), ext);
2059         exit(1);
2060     }
2061
2062     return sm_index;
2063 }
2064 #else   /* !HAVE_DIR_STRUCT */
2065 /* If we are on a system without a DIR struct, we can't
2066    read the directory, so we can't collect a list of
2067    filenames, etc., so we can't do any size-fitting. */
2068 int
2069 xpm_closest_to(dirname, size, ext)
2070      char *dirname;
2071      int size;
2072      char *ext;
2073 {
2074     fprintf(stderr, _("\
2075 Warning: No DIR structure found on this system --\n\
2076          Unable to autosize for XPM/XIM pieces.\n\
2077    Please report this error to frankm@hiwaay.net.\n\
2078    Include system type & operating system in message.\n"));
2079     return size;
2080 }
2081 #endif /* HAVE_DIR_STRUCT */
2082
2083 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
2084                              "magenta", "cyan", "white" };
2085 typedef struct {
2086     int attr, bg, fg;
2087 } TextColors;
2088 TextColors textColors[(int)NColorClasses];
2089
2090 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
2091 static int
2092 parse_color(str, which)
2093      char *str;
2094      int which;
2095 {
2096     char *p, buf[100], *d;
2097     int i;
2098
2099     if (strlen(str) > 99)       /* watch bounds on buf */
2100       return -1;
2101
2102     p = str;
2103     d = buf;
2104     for (i=0; i<which; ++i) {
2105         p = strchr(p, ',');
2106         if (!p)
2107           return -1;
2108         ++p;
2109     }
2110
2111     /* Could be looking at something like:
2112        black, , 1
2113        .. in which case we want to stop on a comma also */
2114     while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
2115       ++p;
2116
2117     if (*p == ',') {
2118         return -1;              /* Use default for empty field */
2119     }
2120
2121     if (which == 2 || isdigit(*p))
2122       return atoi(p);
2123
2124     while (*p && isalpha(*p))
2125       *(d++) = *(p++);
2126
2127     *d = 0;
2128
2129     for (i=0; i<8; ++i) {
2130         if (!StrCaseCmp(buf, cnames[i]))
2131           return which? (i+40) : (i+30);
2132     }
2133     if (!StrCaseCmp(buf, "default")) return -1;
2134
2135     fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
2136     return -2;
2137 }
2138
2139 static int
2140 parse_cpair(cc, str)
2141      ColorClass cc;
2142      char *str;
2143 {
2144     if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
2145         fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
2146                 programName, str);
2147         return -1;
2148     }
2149
2150     /* bg and attr are optional */
2151     textColors[(int)cc].bg = parse_color(str, 1);
2152     if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
2153         textColors[(int)cc].attr = 0;
2154     }
2155     return 0;
2156 }
2157
2158
2159 /* Arrange to catch delete-window events */
2160 Atom wm_delete_window;
2161 void
2162 CatchDeleteWindow(Widget w, String procname)
2163 {
2164   char buf[MSG_SIZ];
2165   XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
2166   snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
2167   XtAugmentTranslations(w, XtParseTranslationTable(buf));
2168 }
2169
2170 void
2171 BoardToTop()
2172 {
2173   Arg args[16];
2174   XtSetArg(args[0], XtNiconic, False);
2175   XtSetValues(shellWidget, args, 1);
2176
2177   XtPopup(shellWidget, XtGrabNone); /* Raise if lowered  */
2178 }
2179
2180 #ifdef IDSIZES
2181   // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
2182 #else
2183 #define BoardSize int
2184 void InitDrawingSizes(BoardSize boardSize, int flags)
2185 {   // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
2186     Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2187     Arg args[16];
2188     XtGeometryResult gres;
2189     int i;
2190
2191     if(!formWidget) return;
2192
2193     /*
2194      * Enable shell resizing.
2195      */
2196     shellArgs[0].value = (XtArgVal) &w;
2197     shellArgs[1].value = (XtArgVal) &h;
2198     XtGetValues(shellWidget, shellArgs, 2);
2199
2200     shellArgs[4].value = 2*w; shellArgs[2].value = 10;
2201     shellArgs[5].value = 2*h; shellArgs[3].value = 10;
2202     XtSetValues(shellWidget, &shellArgs[2], 4);
2203
2204     XtSetArg(args[0], XtNdefaultDistance, &sep);
2205     XtGetValues(formWidget, args, 1);
2206
2207     boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2208     boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2209     CreateGrid();
2210
2211     XtSetArg(args[0], XtNwidth, boardWidth);
2212     XtSetArg(args[1], XtNheight, boardHeight);
2213     XtSetValues(boardWidget, args, 2);
2214
2215     timerWidth = (boardWidth - sep) / 2;
2216     XtSetArg(args[0], XtNwidth, timerWidth);
2217     XtSetValues(whiteTimerWidget, args, 1);
2218     XtSetValues(blackTimerWidget, args, 1);
2219
2220     XawFormDoLayout(formWidget, False);
2221
2222     if (appData.titleInWindow) {
2223         i = 0;
2224         XtSetArg(args[i], XtNborderWidth, &bor); i++;
2225         XtSetArg(args[i], XtNheight, &h);  i++;
2226         XtGetValues(titleWidget, args, i);
2227         if (smallLayout) {
2228             w = boardWidth - 2*bor;
2229         } else {
2230             XtSetArg(args[0], XtNwidth, &w);
2231             XtGetValues(menuBarWidget, args, 1);
2232             w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
2233         }
2234
2235         gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2236         if (gres != XtGeometryYes && appData.debugMode) {
2237             fprintf(stderr,
2238                     _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2239                     programName, gres, w, h, wr, hr);
2240         }
2241     }
2242
2243     XawFormDoLayout(formWidget, True);
2244
2245     /*
2246      * Inhibit shell resizing.
2247      */
2248     shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
2249     shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
2250     shellArgs[4].value = shellArgs[2].value = w;
2251     shellArgs[5].value = shellArgs[3].value = h;
2252     XtSetValues(shellWidget, &shellArgs[0], 6);
2253 }
2254 #endif
2255
2256 int
2257 main(argc, argv)
2258      int argc;
2259      char **argv;
2260 {
2261     int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
2262     XSetWindowAttributes window_attributes;
2263     Arg args[16];
2264     Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2265     XrmValue vFrom, vTo;
2266     XtGeometryResult gres;
2267     char *p;
2268     XrmDatabase xdb;
2269     int forceMono = False;
2270 #define INDIRECTION
2271 #ifdef INDIRECTION
2272     // [HGM] before anything else, expand any indirection files amongst options
2273     char *argvCopy[1000]; // 1000 seems enough
2274     char newArgs[10000];  // holds actual characters
2275     int k = 0;
2276
2277     srandom(time(0)); // [HGM] book: make random truly random
2278
2279     j = 0;
2280     for(i=0; i<argc; i++) {
2281         if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2282 //fprintf(stderr, "arg %s\n", argv[i]);
2283         if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2284             char c;
2285             FILE *f = fopen(argv[i]+1, "rb");
2286             if(f == NULL) { fprintf(stderr, _("ignore %s\n"), argv[i]); continue; } // do not expand non-existing
2287             argvCopy[j++] = newArgs + k; // get ready for first argument from file
2288             while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2289                 if(c == '\n') {
2290                     if(j >= 1000-2) { printf(_("too many arguments\n")); exit(-1); }
2291                     newArgs[k++] = 0;  // terminate current arg
2292                     if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2293                     argvCopy[j++] = newArgs + k; // get ready for next
2294                 } else {
2295                     if(k >= 10000-1) { printf(_("too long arguments\n")); exit(-1); }
2296                     newArgs[k++] = c;
2297                 }
2298             }
2299             newArgs[k] = 0;
2300             j--;
2301             fclose(f);
2302         }
2303     }
2304     argvCopy[j] = NULL;
2305     argv = argvCopy;
2306     argc = j;
2307 #if 0
2308     if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2309         for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2310     }
2311 #endif
2312 #endif
2313
2314
2315     setbuf(stdout, NULL);
2316     setbuf(stderr, NULL);
2317     debugFP = stderr;
2318
2319     programName = strrchr(argv[0], '/');
2320     if (programName == NULL)
2321       programName = argv[0];
2322     else
2323       programName++;
2324
2325 #ifdef ENABLE_NLS
2326     XtSetLanguageProc(NULL, NULL, NULL);
2327     bindtextdomain(PRODUCT, LOCALEDIR);
2328     textdomain(PRODUCT);
2329 #endif
2330
2331     shellWidget =
2332       XtAppInitialize(&appContext, "XBoard", shellOptions,
2333                       XtNumber(shellOptions),
2334                       &argc, argv, xboardResources, NULL, 0);
2335     if (argc > 1) {
2336         fprintf(stderr, _("%s: unrecognized argument %s\n"),
2337                 programName, argv[1]);
2338         fprintf(stderr, "Recognized options:\n");
2339         for(i = 0; i < XtNumber(shellOptions); i++) {
2340             j = fprintf(stderr, "  %s%s", shellOptions[i].option,
2341                         (shellOptions[i].argKind == XrmoptionSepArg
2342                          ? " ARG" : ""));
2343             if (i++ < XtNumber(shellOptions)) {
2344                 fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
2345                         shellOptions[i].option,
2346                         (shellOptions[i].argKind == XrmoptionSepArg
2347                          ? " ARG" : ""));
2348             } else {
2349                 fprintf(stderr, "\n");
2350             }
2351         }
2352         exit(2);
2353     }
2354
2355     if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
2356         chessDir = ".";
2357     } else {
2358         if (chdir(chessDir) != 0) {
2359             fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
2360             perror(chessDir);
2361             exit(1);
2362         }
2363     }
2364
2365     p = getenv("HOME");
2366     if (p == NULL) p = "/tmp";
2367     i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
2368     gameCopyFilename = (char*) malloc(i);
2369     gamePasteFilename = (char*) malloc(i);
2370     snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
2371     snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
2372
2373     XtGetApplicationResources(shellWidget, (XtPointer) &appData,
2374                               clientResources, XtNumber(clientResources),
2375                               NULL, 0);
2376
2377     if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
2378         /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
2379         if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL)  {
2380            printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
2381            exit(errno);
2382         }
2383         setbuf(debugFP, NULL);
2384     }
2385
2386     /* [HGM,HR] make sure board size is acceptable */
2387     if(appData.NrFiles > BOARD_SIZE ||
2388        appData.NrRanks > BOARD_SIZE   )
2389          DisplayFatalError(_("Recompile with BOARD_SIZE > 12, to support this size"), 0, 2);
2390
2391 #if !HIGHDRAG
2392     /* This feature does not work; animation needs a rewrite */
2393     appData.highlightDragging = FALSE;
2394 #endif
2395     InitBackEnd1();
2396
2397     xDisplay = XtDisplay(shellWidget);
2398     xScreen = DefaultScreen(xDisplay);
2399     wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
2400
2401         gameInfo.variant = StringToVariant(appData.variant);
2402         InitPosition(FALSE);
2403 #if 0
2404     /*
2405      * Determine boardSize
2406      */
2407     gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
2408
2409 //#ifndef IDSIZE
2410     // [HGM] as long as we have not created the possibility to change size while running, start with requested size
2411     gameInfo.boardWidth    = appData.NrFiles > 0 ? appData.NrFiles : 8;
2412     gameInfo.boardHeight   = appData.NrRanks > 0 ? appData.NrRanks : 8;
2413     gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
2414 #endif
2415
2416
2417 #ifdef IDSIZE
2418     InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
2419 #else
2420     if (isdigit(appData.boardSize[0])) {
2421         i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
2422                    &lineGap, &clockFontPxlSize, &coordFontPxlSize,
2423                    &fontPxlSize, &smallLayout, &tinyLayout);
2424         if (i == 0) {
2425             fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
2426                     programName, appData.boardSize);
2427             exit(2);
2428         }
2429         if (i < 7) {
2430             /* Find some defaults; use the nearest known size */
2431             SizeDefaults *szd, *nearest;
2432             int distance = 99999;
2433             nearest = szd = sizeDefaults;
2434             while (szd->name != NULL) {
2435                 if (abs(szd->squareSize - squareSize) < distance) {
2436                     nearest = szd;
2437                     distance = abs(szd->squareSize - squareSize);
2438                     if (distance == 0) break;
2439                 }
2440                 szd++;
2441             }
2442             if (i < 2) lineGap = nearest->lineGap;
2443             if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
2444             if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
2445             if (i < 5) fontPxlSize = nearest->fontPxlSize;
2446             if (i < 6) smallLayout = nearest->smallLayout;
2447             if (i < 7) tinyLayout = nearest->tinyLayout;
2448         }
2449     } else {
2450         SizeDefaults *szd = sizeDefaults;
2451         if (*appData.boardSize == NULLCHAR) {
2452             while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
2453                    DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
2454               szd++;
2455             }
2456             if (szd->name == NULL) szd--;
2457         } else {
2458             while (szd->name != NULL &&
2459                    StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
2460             if (szd->name == NULL) {
2461                 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
2462                         programName, appData.boardSize);
2463                 exit(2);
2464             }
2465         }
2466         squareSize = szd->squareSize;
2467         lineGap = szd->lineGap;
2468         clockFontPxlSize = szd->clockFontPxlSize;
2469         coordFontPxlSize = szd->coordFontPxlSize;
2470         fontPxlSize = szd->fontPxlSize;
2471         smallLayout = szd->smallLayout;
2472         tinyLayout = szd->tinyLayout;
2473     }
2474
2475     /* Now, using squareSize as a hint, find a good XPM/XIM set size */
2476     if (strlen(appData.pixmapDirectory) > 0) {
2477         p = ExpandPathName(appData.pixmapDirectory);
2478         if (!p) {
2479             fprintf(stderr, _("Error expanding path name \"%s\"\n"),
2480                    appData.pixmapDirectory);
2481             exit(1);
2482         }
2483         if (appData.debugMode) {
2484           fprintf(stderr, _("\
2485 XBoard square size (hint): %d\n\
2486 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2487         }
2488         squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2489         if (appData.debugMode) {
2490             fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2491         }
2492     }
2493
2494     /* [HR] height treated separately (hacked) */
2495     boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
2496     boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2497     if (appData.showJail == 1) {
2498         /* Jail on top and bottom */
2499         XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2500         XtSetArg(boardArgs[2], XtNheight,
2501                  boardHeight + 2*(lineGap + squareSize));
2502     } else if (appData.showJail == 2) {
2503         /* Jail on sides */
2504         XtSetArg(boardArgs[1], XtNwidth,
2505                  boardWidth + 2*(lineGap + squareSize));
2506         XtSetArg(boardArgs[2], XtNheight, boardHeight);
2507     } else {
2508         /* No jail */
2509         XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2510         XtSetArg(boardArgs[2], XtNheight, boardHeight);
2511     }
2512
2513     /*
2514      * Determine what fonts to use.
2515      */
2516     appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2517     clockFontID = XLoadFont(xDisplay, appData.clockFont);
2518     clockFontStruct = XQueryFont(xDisplay, clockFontID);
2519     appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2520     coordFontID = XLoadFont(xDisplay, appData.coordFont);
2521     coordFontStruct = XQueryFont(xDisplay, coordFontID);
2522     appData.font = FindFont(appData.font, fontPxlSize);
2523     countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
2524     countFontStruct = XQueryFont(xDisplay, countFontID);
2525 //    appData.font = FindFont(appData.font, fontPxlSize);
2526
2527     xdb = XtDatabase(xDisplay);
2528     XrmPutStringResource(&xdb, "*font", appData.font);
2529
2530     /*
2531      * Detect if there are not enough colors available and adapt.
2532      */
2533     if (DefaultDepth(xDisplay, xScreen) <= 2) {
2534       appData.monoMode = True;
2535     }
2536
2537     if (!appData.monoMode) {
2538         vFrom.addr = (caddr_t) appData.lightSquareColor;
2539         vFrom.size = strlen(appData.lightSquareColor);
2540         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2541         if (vTo.addr == NULL) {
2542           appData.monoMode = True;
2543           forceMono = True;
2544         } else {
2545           lightSquareColor = *(Pixel *) vTo.addr;
2546         }
2547     }
2548     if (!appData.monoMode) {
2549         vFrom.addr = (caddr_t) appData.darkSquareColor;
2550         vFrom.size = strlen(appData.darkSquareColor);
2551         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2552         if (vTo.addr == NULL) {
2553           appData.monoMode = True;
2554           forceMono = True;
2555         } else {
2556           darkSquareColor = *(Pixel *) vTo.addr;
2557         }
2558     }
2559     if (!appData.monoMode) {
2560         vFrom.addr = (caddr_t) appData.whitePieceColor;
2561         vFrom.size = strlen(appData.whitePieceColor);
2562         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2563         if (vTo.addr == NULL) {
2564           appData.monoMode = True;
2565           forceMono = True;
2566         } else {
2567           whitePieceColor = *(Pixel *) vTo.addr;
2568         }
2569     }
2570     if (!appData.monoMode) {
2571         vFrom.addr = (caddr_t) appData.blackPieceColor;
2572         vFrom.size = strlen(appData.blackPieceColor);
2573         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2574         if (vTo.addr == NULL) {
2575           appData.monoMode = True;
2576           forceMono = True;
2577         } else {
2578           blackPieceColor = *(Pixel *) vTo.addr;
2579         }
2580     }
2581
2582     if (!appData.monoMode) {
2583         vFrom.addr = (caddr_t) appData.highlightSquareColor;
2584         vFrom.size = strlen(appData.highlightSquareColor);
2585         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2586         if (vTo.addr == NULL) {
2587           appData.monoMode = True;
2588           forceMono = True;
2589         } else {
2590           highlightSquareColor = *(Pixel *) vTo.addr;
2591         }
2592     }
2593
2594     if (!appData.monoMode) {
2595         vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2596         vFrom.size = strlen(appData.premoveHighlightColor);
2597         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2598         if (vTo.addr == NULL) {
2599           appData.monoMode = True;
2600           forceMono = True;
2601         } else {
2602           premoveHighlightColor = *(Pixel *) vTo.addr;
2603         }
2604     }
2605
2606     if (forceMono) {
2607       fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2608               programName);
2609       
2610       if (appData.bitmapDirectory == NULL ||
2611               appData.bitmapDirectory[0] == NULLCHAR)
2612             appData.bitmapDirectory = DEF_BITMAP_DIR;
2613     }
2614
2615     if (appData.lowTimeWarning && !appData.monoMode) {
2616       vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
2617       vFrom.size = strlen(appData.lowTimeWarningColor);
2618       XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2619       if (vTo.addr == NULL) 
2620                 appData.monoMode = True;
2621       else
2622                 lowTimeWarningColor = *(Pixel *) vTo.addr;
2623     }
2624
2625     if (appData.monoMode && appData.debugMode) {
2626         fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2627                 (unsigned long) XWhitePixel(xDisplay, xScreen),
2628                 (unsigned long) XBlackPixel(xDisplay, xScreen));
2629     }
2630
2631     if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2632         parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2633         parse_cpair(ColorChannel1, appData.colorChannel1) < 0  ||
2634         parse_cpair(ColorChannel, appData.colorChannel) < 0  ||
2635         parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2636         parse_cpair(ColorTell, appData.colorTell) < 0 ||
2637         parse_cpair(ColorChallenge, appData.colorChallenge) < 0  ||
2638         parse_cpair(ColorRequest, appData.colorRequest) < 0  ||
2639         parse_cpair(ColorSeek, appData.colorSeek) < 0  ||
2640         parse_cpair(ColorNormal, appData.colorNormal) < 0)
2641       {
2642           if (appData.colorize) {
2643               fprintf(stderr,
2644                       _("%s: can't parse color names; disabling colorization\n"),
2645                       programName);
2646           }
2647           appData.colorize = FALSE;
2648       }
2649     textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2650     textColors[ColorNone].attr = 0;
2651
2652     XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2653
2654     /*
2655      * widget hierarchy
2656      */
2657     if (tinyLayout) {
2658         layoutName = "tinyLayout";
2659     } else if (smallLayout) {
2660         layoutName = "smallLayout";
2661     } else {
2662         layoutName = "normalLayout";
2663     }
2664     /* Outer layoutWidget is there only to provide a name for use in
2665        resources that depend on the layout style */
2666     layoutWidget =
2667       XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2668                             layoutArgs, XtNumber(layoutArgs));
2669     formWidget =
2670       XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2671                             formArgs, XtNumber(formArgs));
2672     XtSetArg(args[0], XtNdefaultDistance, &sep);
2673     XtGetValues(formWidget, args, 1);
2674
2675     j = 0;
2676     widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2677     XtSetArg(args[0], XtNtop,    XtChainTop);
2678     XtSetArg(args[1], XtNbottom, XtChainTop);
2679     XtSetValues(menuBarWidget, args, 2);
2680
2681     widgetList[j++] = whiteTimerWidget =
2682       XtCreateWidget("whiteTime", labelWidgetClass,
2683                      formWidget, timerArgs, XtNumber(timerArgs));
2684     XtSetArg(args[0], XtNfont, clockFontStruct);
2685     XtSetArg(args[1], XtNtop,    XtChainTop);
2686     XtSetArg(args[2], XtNbottom, XtChainTop);
2687     XtSetValues(whiteTimerWidget, args, 3);
2688
2689     widgetList[j++] = blackTimerWidget =
2690       XtCreateWidget("blackTime", labelWidgetClass,
2691                      formWidget, timerArgs, XtNumber(timerArgs));
2692     XtSetArg(args[0], XtNfont, clockFontStruct);
2693     XtSetArg(args[1], XtNtop,    XtChainTop);
2694     XtSetArg(args[2], XtNbottom, XtChainTop);
2695     XtSetValues(blackTimerWidget, args, 3);
2696
2697     if (appData.titleInWindow) {
2698         widgetList[j++] = titleWidget =
2699           XtCreateWidget("title", labelWidgetClass, formWidget,
2700                          titleArgs, XtNumber(titleArgs));
2701         XtSetArg(args[0], XtNtop,    XtChainTop);
2702         XtSetArg(args[1], XtNbottom, XtChainTop);
2703         XtSetValues(titleWidget, args, 2);
2704     }
2705
2706     if (appData.showButtonBar) {
2707       widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2708       XtSetArg(args[0], XtNleft,  XtChainRight); // [HGM] glue to right window edge
2709       XtSetArg(args[1], XtNright, XtChainRight); //       for good run-time sizing
2710       XtSetArg(args[2], XtNtop,    XtChainTop);
2711       XtSetArg(args[3], XtNbottom, XtChainTop);
2712       XtSetValues(buttonBarWidget, args, 4);
2713     }
2714
2715     widgetList[j++] = messageWidget =
2716       XtCreateWidget("message", labelWidgetClass, formWidget,
2717                      messageArgs, XtNumber(messageArgs));
2718     XtSetArg(args[0], XtNtop,    XtChainTop);
2719     XtSetArg(args[1], XtNbottom, XtChainTop);
2720     XtSetValues(messageWidget, args, 2);
2721
2722     widgetList[j++] = boardWidget =
2723       XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2724                      XtNumber(boardArgs));
2725
2726     XtManageChildren(widgetList, j);
2727
2728     timerWidth = (boardWidth - sep) / 2;
2729     XtSetArg(args[0], XtNwidth, timerWidth);
2730     XtSetValues(whiteTimerWidget, args, 1);
2731     XtSetValues(blackTimerWidget, args, 1);
2732
2733     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2734     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2735     XtGetValues(whiteTimerWidget, args, 2);
2736
2737     if (appData.showButtonBar) {
2738       XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2739       XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2740       XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2741     }
2742
2743     /*
2744      * formWidget uses these constraints but they are stored
2745      * in the children.
2746      */
2747     i = 0;
2748     XtSetArg(args[i], XtNfromHoriz, 0); i++;
2749     XtSetValues(menuBarWidget, args, i);
2750     if (appData.titleInWindow) {
2751         if (smallLayout) {
2752             i = 0;
2753             XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2754             XtSetValues(whiteTimerWidget, args, i);
2755             i = 0;
2756             XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2757             XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2758             XtSetValues(blackTimerWidget, args, i);
2759             i = 0;
2760             XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2761             XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2762             XtSetValues(titleWidget, args, i);
2763             i = 0;
2764             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2765             XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2766             XtSetValues(messageWidget, args, i);
2767             if (appData.showButtonBar) {
2768               i = 0;
2769               XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2770               XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2771               XtSetValues(buttonBarWidget, args, i);
2772             }
2773         } else {
2774             i = 0;
2775             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2776             XtSetValues(whiteTimerWidget, args, i);
2777             i = 0;
2778             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2779             XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2780             XtSetValues(blackTimerWidget, args, i);
2781             i = 0;
2782             XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2783             XtSetValues(titleWidget, args, i);
2784             i = 0;
2785             XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2786             XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2787             XtSetValues(messageWidget, args, i);
2788             if (appData.showButtonBar) {
2789               i = 0;
2790               XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2791               XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2792               XtSetValues(buttonBarWidget, args, i);
2793             }
2794         }
2795     } else {
2796         i = 0;
2797         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2798         XtSetValues(whiteTimerWidget, args, i);
2799         i = 0;
2800         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2801         XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2802         XtSetValues(blackTimerWidget, args, i);
2803         i = 0;
2804         XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2805         XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2806         XtSetValues(messageWidget, args, i);
2807         if (appData.showButtonBar) {
2808           i = 0;
2809           XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2810           XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2811           XtSetValues(buttonBarWidget, args, i);
2812         }
2813     }
2814     i = 0;
2815     XtSetArg(args[0], XtNfromVert, messageWidget);
2816     XtSetArg(args[1], XtNtop,    XtChainTop);
2817     XtSetArg(args[2], XtNbottom, XtChainBottom);
2818     XtSetArg(args[3], XtNleft,   XtChainLeft);
2819     XtSetArg(args[4], XtNright,  XtChainRight);
2820     XtSetValues(boardWidget, args, 5);
2821
2822     XtRealizeWidget(shellWidget);
2823
2824     /*
2825      * Correct the width of the message and title widgets.
2826      * It is not known why some systems need the extra fudge term.
2827      * The value "2" is probably larger than needed.
2828      */
2829     XawFormDoLayout(formWidget, False);
2830
2831 #define WIDTH_FUDGE 2
2832     i = 0;
2833     XtSetArg(args[i], XtNborderWidth, &bor);  i++;
2834     XtSetArg(args[i], XtNheight, &h);  i++;
2835     XtGetValues(messageWidget, args, i);
2836     if (appData.showButtonBar) {
2837       i = 0;
2838       XtSetArg(args[i], XtNwidth, &w);  i++;
2839       XtGetValues(buttonBarWidget, args, i);
2840       w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2841     } else {
2842       w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2843     }
2844
2845     gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2846     if (gres != XtGeometryYes && appData.debugMode) {
2847       fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2848               programName, gres, w, h, wr, hr);
2849     }
2850
2851     /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2852     /* The size used for the child widget in layout lags one resize behind
2853        its true size, so we resize a second time, 1 pixel smaller.  Yeech! */
2854     w--;
2855     gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2856     if (gres != XtGeometryYes && appData.debugMode) {
2857       fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2858               programName, gres, w, h, wr, hr);
2859     }
2860     /* !! end hack */
2861     XtSetArg(args[0], XtNleft,  XtChainLeft);  // [HGM] glue ends for good run-time sizing
2862     XtSetArg(args[1], XtNright, XtChainRight);
2863     XtSetValues(messageWidget, args, 2);
2864
2865     if (appData.titleInWindow) {
2866         i = 0;
2867         XtSetArg(args[i], XtNborderWidth, &bor); i++;
2868         XtSetArg(args[i], XtNheight, &h);  i++;
2869         XtGetValues(titleWidget, args, i);
2870         if (smallLayout) {
2871             w = boardWidth - 2*bor;
2872         } else {
2873             XtSetArg(args[0], XtNwidth, &w);
2874             XtGetValues(menuBarWidget, args, 1);
2875             w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2876         }
2877
2878         gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2879         if (gres != XtGeometryYes && appData.debugMode) {
2880             fprintf(stderr,
2881                     _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2882                     programName, gres, w, h, wr, hr);
2883         }
2884     }
2885     XawFormDoLayout(formWidget, True);
2886
2887     xBoardWindow = XtWindow(boardWidget);
2888
2889     // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
2890     //       not need to go into InitDrawingSizes().
2891 #endif
2892
2893     /*
2894      * Create X checkmark bitmap and initialize option menu checks.
2895      */
2896     ReadBitmap(&xMarkPixmap, "checkmark.bm",
2897                checkmark_bits, checkmark_width, checkmark_height);
2898     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2899     if (appData.alwaysPromoteToQueen) {
2900         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2901                     args, 1);
2902     }
2903     if (appData.animateDragging) {
2904         XtSetValues(XtNameToWidget(menuBarWidget,
2905                                    "menuOptions.Animate Dragging"),
2906                     args, 1);
2907     }
2908     if (appData.animate) {
2909         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2910                     args, 1);
2911     }
2912     if (appData.autoComment) {
2913         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2914                     args, 1);
2915     }
2916     if (appData.autoCallFlag) {
2917         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2918                     args, 1);
2919     }
2920     if (appData.autoFlipView) {
2921         XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2922                     args, 1);
2923     }
2924     if (appData.autoObserve) {
2925         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2926                     args, 1);
2927     }
2928     if (appData.autoRaiseBoard) {
2929         XtSetValues(XtNameToWidget(menuBarWidget,
2930                                    "menuOptions.Auto Raise Board"), args, 1);
2931     }
2932     if (appData.autoSaveGames) {
2933         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2934                     args, 1);
2935     }
2936     if (appData.saveGameFile[0] != NULLCHAR) {
2937         /* Can't turn this off from menu */
2938         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2939                     args, 1);
2940         XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2941                        False);
2942
2943     }
2944     if (appData.blindfold) {
2945         XtSetValues(XtNameToWidget(menuBarWidget,
2946                                    "menuOptions.Blindfold"), args, 1);
2947     }
2948     if (appData.flashCount > 0) {
2949         XtSetValues(XtNameToWidget(menuBarWidget,
2950                                    "menuOptions.Flash Moves"),
2951                     args, 1);
2952     }
2953     if (appData.getMoveList) {
2954         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2955                     args, 1);
2956     }
2957 #if HIGHDRAG
2958     if (appData.highlightDragging) {
2959         XtSetValues(XtNameToWidget(menuBarWidget,
2960                                    "menuOptions.Highlight Dragging"),
2961                     args, 1);
2962     }
2963 #endif
2964     if (appData.highlightLastMove) {
2965         XtSetValues(XtNameToWidget(menuBarWidget,
2966                                    "menuOptions.Highlight Last Move"),
2967                     args, 1);
2968     }
2969     if (appData.icsAlarm) {
2970         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2971                     args, 1);
2972     }
2973     if (appData.ringBellAfterMoves) {
2974         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2975                     args, 1);
2976     }
2977     if (appData.oldSaveStyle) {
2978         XtSetValues(XtNameToWidget(menuBarWidget,
2979                                    "menuOptions.Old Save Style"), args, 1);
2980     }
2981     if (appData.periodicUpdates) {
2982         XtSetValues(XtNameToWidget(menuBarWidget,
2983                                    "menuOptions.Periodic Updates"), args, 1);
2984     }
2985     if (appData.ponderNextMove) {
2986         XtSetValues(XtNameToWidget(menuBarWidget,
2987                                    "menuOptions.Ponder Next Move"), args, 1);
2988     }
2989     if (appData.popupExitMessage) {
2990         XtSetValues(XtNameToWidget(menuBarWidget,
2991                                    "menuOptions.Popup Exit Message"), args, 1);
2992     }
2993     if (appData.popupMoveErrors) {
2994         XtSetValues(XtNameToWidget(menuBarWidget,
2995                                    "menuOptions.Popup Move Errors"), args, 1);
2996     }
2997     if (appData.premove) {
2998         XtSetValues(XtNameToWidget(menuBarWidget,
2999                                    "menuOptions.Premove"), args, 1);
3000     }
3001     if (appData.quietPlay) {
3002         XtSetValues(XtNameToWidget(menuBarWidget,
3003                                    "menuOptions.Quiet Play"), args, 1);
3004     }
3005     if (appData.showCoords) {
3006         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
3007                     args, 1);
3008     }
3009     if (appData.hideThinkingFromHuman) {
3010         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
3011                     args, 1);
3012     }
3013     if (appData.testLegality) {
3014         XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
3015                     args, 1);
3016     }
3017
3018     /*
3019      * Create an icon.
3020      */
3021     ReadBitmap(&wIconPixmap, "icon_white.bm",
3022                icon_white_bits, icon_white_width, icon_white_height);
3023     ReadBitmap(&bIconPixmap, "icon_black.bm",
3024                icon_black_bits, icon_black_width, icon_black_height);
3025     iconPixmap = wIconPixmap;
3026     i = 0;
3027     XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
3028     XtSetValues(shellWidget, args, i);
3029
3030     /*
3031      * Create a cursor for the board widget.
3032      */
3033     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
3034     XChangeWindowAttributes(xDisplay, xBoardWindow,
3035                             CWCursor, &window_attributes);
3036
3037     /*
3038      * Inhibit shell resizing.
3039      */
3040     shellArgs[0].value = (XtArgVal) &w;
3041     shellArgs[1].value = (XtArgVal) &h;
3042     XtGetValues(shellWidget, shellArgs, 2);
3043     shellArgs[4].value = shellArgs[2].value = w;
3044     shellArgs[5].value = shellArgs[3].value = h;
3045     XtSetValues(shellWidget, &shellArgs[2], 4);
3046     marginW =  w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
3047     marginH =  h - boardHeight;
3048
3049     CatchDeleteWindow(shellWidget, "QuitProc");
3050
3051     CreateGCs();
3052     CreateGrid();
3053 #if HAVE_LIBXPM
3054     if (appData.bitmapDirectory[0] != NULLCHAR) {
3055       CreatePieces();
3056     } else {
3057       CreateXPMPieces();
3058     }
3059 #else
3060     CreateXIMPieces();
3061     /* Create regular pieces */
3062     if (!useImages) CreatePieces();
3063 #endif
3064
3065     CreatePieceMenus();
3066
3067     if (appData.animate || appData.animateDragging)
3068       CreateAnimVars();
3069
3070     XtAugmentTranslations(formWidget,
3071                           XtParseTranslationTable(globalTranslations));
3072     XtAugmentTranslations(boardWidget,
3073                           XtParseTranslationTable(boardTranslations));
3074     XtAugmentTranslations(whiteTimerWidget,
3075                           XtParseTranslationTable(whiteTranslations));
3076     XtAugmentTranslations(blackTimerWidget,
3077                           XtParseTranslationTable(blackTranslations));
3078
3079     /* Why is the following needed on some versions of X instead
3080      * of a translation? */
3081     XtAddEventHandler(boardWidget, ExposureMask, False,
3082                       (XtEventHandler) EventProc, NULL);
3083     /* end why */
3084
3085     InitBackEnd2();
3086
3087     if (errorExitStatus == -1) {
3088         if (appData.icsActive) {
3089             /* We now wait until we see "login:" from the ICS before
3090                sending the logon script (problems with timestamp otherwise) */
3091             /*ICSInitScript();*/
3092             if (appData.icsInputBox) ICSInputBoxPopUp();
3093         }
3094
3095         signal(SIGINT, IntSigHandler);
3096         signal(SIGTERM, IntSigHandler);
3097         if (*appData.cmailGameName != NULLCHAR) {
3098             signal(SIGUSR1, CmailSigHandler);
3099         }
3100     }
3101         InitPosition(TRUE);
3102
3103     XtAppMainLoop(appContext);
3104     if (appData.debugMode) fclose(debugFP); // [DM] debug
3105     return 0;
3106 }
3107
3108 void
3109 ShutDownFrontEnd()
3110 {
3111     if (appData.icsActive && oldICSInteractionTitle != NULL) {
3112         DisplayIcsInteractionTitle(oldICSInteractionTitle);
3113     }
3114     unlink(gameCopyFilename);
3115     unlink(gamePasteFilename);
3116 }
3117
3118 RETSIGTYPE
3119 IntSigHandler(sig)
3120      int sig;
3121 {
3122     ExitEvent(sig);
3123 }
3124
3125 RETSIGTYPE
3126 CmailSigHandler(sig)
3127      int sig;
3128 {
3129     int dummy = 0;
3130     int error;
3131
3132     signal(SIGUSR1, SIG_IGN);   /* suspend handler     */
3133
3134     /* Activate call-back function CmailSigHandlerCallBack()             */
3135     OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
3136
3137     signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
3138 }
3139
3140 void
3141 CmailSigHandlerCallBack(isr, closure, message, count, error)
3142      InputSourceRef isr;
3143      VOIDSTAR closure;
3144      char *message;
3145      int count;
3146      int error;
3147 {
3148     BoardToTop();
3149     ReloadCmailMsgEvent(TRUE);  /* Reload cmail msg  */
3150 }
3151 /**** end signal code ****/
3152
3153
3154 void
3155 ICSInitScript()
3156 {
3157     FILE *f;
3158     char buf[MSG_SIZ];
3159     char *p;
3160
3161     f = fopen(appData.icsLogon, "r");
3162     if (f == NULL) {
3163         p = getenv("HOME");
3164         if (p != NULL) {
3165             strcpy(buf, p);
3166             strcat(buf, "/");
3167             strcat(buf, appData.icsLogon);
3168             f = fopen(buf, "r");
3169         }
3170     }
3171     if (f != NULL)
3172       ProcessICSInitScript(f);
3173 }
3174
3175 void
3176 ResetFrontEnd()
3177 {
3178     CommentPopDown();
3179     EditCommentPopDown();
3180     TagsPopDown();
3181     return;
3182 }
3183
3184 typedef struct {
3185     char *name;
3186     Boolean value;
3187 } Enables;
3188
3189 void
3190 SetMenuEnables(enab)
3191      Enables *enab;
3192 {
3193   Widget w;
3194   if (!menuBarWidget) return;
3195   while (enab->name != NULL) {
3196     w = XtNameToWidget(menuBarWidget, enab->name);
3197     if (w == NULL) {
3198       DisplayError(enab->name, 0);
3199     } else {
3200       XtSetSensitive(w, enab->value);
3201     }
3202     enab++;
3203   }
3204 }
3205
3206 Enables icsEnables[] = {
3207     { "menuFile.Mail Move", False },
3208     { "menuFile.Reload CMail Message", False },
3209     { "menuMode.Machine Black", False },
3210     { "menuMode.Machine White", False },
3211     { "menuMode.Analysis Mode", False },
3212     { "menuMode.Analyze File", False },
3213     { "menuMode.Two Machines", False },
3214 #ifndef ZIPPY
3215     { "menuHelp.Hint", False },
3216     { "menuHelp.Book", False },
3217     { "menuStep.Move Now", False },
3218     { "menuOptions.Periodic Updates", False },
3219     { "menuOptions.Hide Thinking", False },
3220     { "menuOptions.Ponder Next Move", False },
3221 #endif
3222     { NULL, False }
3223 };
3224
3225 Enables ncpEnables[] = {
3226     { "menuFile.Mail Move", False },
3227     { "menuFile.Reload CMail Message", False },
3228     { "menuMode.Machine White", False },
3229     { "menuMode.Machine Black", False },
3230     { "menuMode.Analysis Mode", False },
3231     { "menuMode.Analyze File", False },
3232     { "menuMode.Two Machines", False },
3233     { "menuMode.ICS Client", False },
3234     { "menuMode.ICS Input Box", False },
3235     { "Action", False },
3236     { "menuStep.Revert", False },
3237     { "menuStep.Move Now", False },
3238     { "menuStep.Retract Move", False },
3239     { "menuOptions.Auto Comment", False },
3240     { "menuOptions.Auto Flag", False },
3241     { "menuOptions.Auto Flip View", False },
3242     { "menuOptions.Auto Observe", False },
3243     { "menuOptions.Auto Raise Board", False },
3244     { "menuOptions.Get Move List", False },
3245     { "menuOptions.ICS Alarm", False },
3246     { "menuOptions.Move Sound", False },
3247     { "menuOptions.Quiet Play", False },
3248     { "menuOptions.Hide Thinking", False },
3249     { "menuOptions.Periodic Updates", False },
3250     { "menuOptions.Ponder Next Move", False },
3251     { "menuHelp.Hint", False },
3252     { "menuHelp.Book", False },
3253     { NULL, False }
3254 };
3255
3256 Enables gnuEnables[] = {
3257     { "menuMode.ICS Client", False },
3258     { "menuMode.ICS Input Box", False },
3259     { "menuAction.Accept", False },
3260     { "menuAction.Decline", False },
3261     { "menuAction.Rematch", False },
3262     { "menuAction.Adjourn", False },
3263     { "menuAction.Stop Examining", False },
3264     { "menuAction.Stop Observing", False },
3265     { "menuStep.Revert", False },
3266     { "menuOptions.Auto Comment", False },
3267     { "menuOptions.Auto Observe", False },
3268     { "menuOptions.Auto Raise Board", False },
3269     { "menuOptions.Get Move List", False },
3270     { "menuOptions.Premove", False },
3271     { "menuOptions.Quiet Play", False },
3272
3273     /* The next two options rely on SetCmailMode being called *after*    */
3274     /* SetGNUMode so that when GNU is being used to give hints these     */
3275     /* menu options are still available                                  */
3276
3277     { "menuFile.Mail Move", False },
3278     { "menuFile.Reload CMail Message", False },
3279     { NULL, False }
3280 };
3281
3282 Enables cmailEnables[] = {
3283     { "Action", True },
3284     { "menuAction.Call Flag", False },
3285     { "menuAction.Draw", True },
3286     { "menuAction.Adjourn", False },
3287     { "menuAction.Abort", False },
3288     { "menuAction.Stop Observing", False },
3289     { "menuAction.Stop Examining", False },
3290     { "menuFile.Mail Move", True },
3291     { "menuFile.Reload CMail Message", True },
3292     { NULL, False }
3293 };
3294
3295 Enables trainingOnEnables[] = {
3296   { "menuMode.Edit Comment", False },
3297   { "menuMode.Pause", False },
3298   { "menuStep.Forward", False },
3299   { "menuStep.Backward", False },
3300   { "menuStep.Forward to End", False },
3301   { "menuStep.Back to Start", False },
3302   { "menuStep.Move Now", False },
3303   { "menuStep.Truncate Game", False },
3304   { NULL, False }
3305 };
3306
3307 Enables trainingOffEnables[] = {
3308   { "menuMode.Edit Comment", True },
3309   { "menuMode.Pause", True },
3310   { "menuStep.Forward", True },
3311   { "menuStep.Backward", True },
3312   { "menuStep.Forward to End", True },
3313   { "menuStep.Back to Start", True },
3314   { "menuStep.Move Now", True },
3315   { "menuStep.Truncate Game", True },
3316   { NULL, False }
3317 };
3318
3319 Enables machineThinkingEnables[] = {
3320   { "menuFile.Load Game", False },
3321   { "menuFile.Load Next Game", False },
3322   { "menuFile.Load Previous Game", False },
3323   { "menuFile.Reload Same Game", False },
3324   { "menuFile.Paste Game", False },
3325   { "menuFile.Load Position", False },
3326   { "menuFile.Load Next Position", False },
3327   { "menuFile.Load Previous Position", False },
3328   { "menuFile.Reload Same Position", False },
3329   { "menuFile.Paste Position", False },
3330   { "menuMode.Machine White", False },
3331   { "menuMode.Machine Black", False },
3332   { "menuMode.Two Machines", False },
3333   { "menuStep.Retract Move", False },
3334   { NULL, False }
3335 };
3336
3337 Enables userThinkingEnables[] = {
3338   { "menuFile.Load Game", True },
3339   { "menuFile.Load Next Game", True },
3340   { "menuFile.Load Previous Game", True },
3341   { "menuFile.Reload Same Game", True },
3342   { "menuFile.Paste Game", True },
3343   { "menuFile.Load Position", True },
3344   { "menuFile.Load Next Position", True },
3345   { "menuFile.Load Previous Position", True },
3346   { "menuFile.Reload Same Position", True },
3347   { "menuFile.Paste Position", True },
3348   { "menuMode.Machine White", True },
3349   { "menuMode.Machine Black", True },
3350   { "menuMode.Two Machines", True },
3351   { "menuStep.Retract Move", True },
3352   { NULL, False }
3353 };
3354
3355 void SetICSMode()
3356 {
3357   SetMenuEnables(icsEnables);
3358
3359 #ifdef ZIPPY
3360   if (appData.zippyPlay && !appData.noChessProgram)   /* [DM] icsEngineAnalyze */
3361      XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
3362 #endif
3363 }
3364
3365 void
3366 SetNCPMode()
3367 {
3368   SetMenuEnables(ncpEnables);
3369 }
3370
3371 void
3372 SetGNUMode()
3373 {
3374   SetMenuEnables(gnuEnables);
3375 }
3376
3377 void
3378 SetCmailMode()
3379 {
3380   SetMenuEnables(cmailEnables);
3381 }
3382
3383 void
3384 SetTrainingModeOn()
3385 {
3386   SetMenuEnables(trainingOnEnables);
3387   if (appData.showButtonBar) {
3388     XtSetSensitive(buttonBarWidget, False);
3389   }
3390   CommentPopDown();
3391 }
3392
3393 void
3394 SetTrainingModeOff()
3395 {
3396   SetMenuEnables(trainingOffEnables);
3397   if (appData.showButtonBar) {
3398     XtSetSensitive(buttonBarWidget, True);
3399   }
3400 }
3401
3402 void
3403 SetUserThinkingEnables()
3404 {
3405   if (appData.noChessProgram) return;
3406   SetMenuEnables(userThinkingEnables);
3407 }
3408
3409 void
3410 SetMachineThinkingEnables()
3411 {
3412   if (appData.noChessProgram) return;
3413   SetMenuEnables(machineThinkingEnables);
3414   switch (gameMode) {
3415   case MachinePlaysBlack:
3416   case MachinePlaysWhite:
3417   case TwoMachinesPlay:
3418     XtSetSensitive(XtNameToWidget(menuBarWidget,
3419                                   ModeToWidgetName(gameMode)), True);
3420     break;
3421   default:
3422     break;
3423   }
3424 }
3425
3426 #define Abs(n) ((n)<0 ? -(n) : (n))
3427
3428 /*
3429  * Find a font that matches "pattern" that is as close as
3430  * possible to the targetPxlSize.  Prefer fonts that are k
3431  * pixels smaller to fonts that are k pixels larger.  The
3432  * pattern must be in the X Consortium standard format,
3433  * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
3434  * The return value should be freed with XtFree when no
3435  * longer needed.
3436  */
3437 char *FindFont(pattern, targetPxlSize)
3438      char *pattern;
3439      int targetPxlSize;
3440 {
3441     char **fonts, *p, *best, *scalable, *scalableTail;
3442     int i, j, nfonts, minerr, err, pxlSize;
3443
3444 #ifdef ENABLE_NLS
3445     char **missing_list;
3446     int missing_count;
3447     char *def_string, *base_fnt_lst, strInt[3];
3448     XFontSet fntSet;
3449     XFontStruct **fnt_list;
3450
3451     base_fnt_lst = calloc(1, strlen(pattern) + 3);
3452     sprintf(strInt, "%d", targetPxlSize);
3453     p = strstr(pattern, "--");
3454     strncpy(base_fnt_lst, pattern, p - pattern + 2);
3455     strcat(base_fnt_lst, strInt);
3456     strcat(base_fnt_lst, strchr(p + 2, '-'));
3457
3458     if ((fntSet = XCreateFontSet(xDisplay,
3459                                  base_fnt_lst,
3460                                  &missing_list,
3461                                  &missing_count,
3462                                  &def_string)) == NULL) {
3463
3464        fprintf(stderr, _("Unable to create font set.\n"));
3465        exit (2);
3466     }
3467
3468     nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
3469 #else
3470     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
3471     if (nfonts < 1) {
3472         fprintf(stderr, _("%s: no fonts match pattern %s\n"),
3473                 programName, pattern);
3474         exit(2);
3475     }
3476 #endif
3477
3478     best = fonts[0];
3479     scalable = NULL;
3480     minerr = 999999;
3481     for (i=0; i<nfonts; i++) {
3482         j = 0;
3483         p = fonts[i];
3484         if (*p != '-') continue;
3485         while (j < 7) {
3486             if (*p == NULLCHAR) break;
3487             if (*p++ == '-') j++;
3488         }
3489         if (j < 7) continue;
3490         pxlSize = atoi(p);
3491         if (pxlSize == 0) {
3492             scalable = fonts[i];
3493             scalableTail = p;
3494         } else {
3495             err = pxlSize - targetPxlSize;
3496             if (Abs(err) < Abs(minerr) ||
3497                 (minerr > 0 && err < 0 && -err == minerr)) {
3498                 best = fonts[i];
3499                 minerr = err;
3500             }
3501         }
3502     }
3503     if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
3504         /* If the error is too big and there is a scalable font,
3505            use the scalable font. */
3506         int headlen = scalableTail - scalable;
3507         p = (char *) XtMalloc(strlen(scalable) + 10);
3508         while (isdigit(*scalableTail)) scalableTail++;
3509         sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
3510     } else {
3511         p = (char *) XtMalloc(strlen(best) + 1);
3512         strcpy(p, best);
3513     }
3514     if (appData.debugMode) {
3515         fprintf(debugFP, _("resolved %s at pixel size %d\n  to %s\n"),
3516                 pattern, targetPxlSize, p);
3517     }
3518 #ifdef ENABLE_NLS
3519     if (missing_count > 0)
3520        XFreeStringList(missing_list);
3521     XFreeFontSet(xDisplay, fntSet);
3522 #else
3523      XFreeFontNames(fonts);
3524 #endif
3525     return p;
3526 }
3527
3528 void CreateGCs()
3529 {
3530     XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
3531       | GCBackground | GCFunction | GCPlaneMask;
3532     XGCValues gc_values;
3533     GC copyInvertedGC;
3534
3535     gc_values.plane_mask = AllPlanes;
3536     gc_values.line_width = lineGap;
3537     gc_values.line_style = LineSolid;
3538     gc_values.function = GXcopy;
3539
3540     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3541     gc_values.background = XBlackPixel(xDisplay, xScreen);
3542     lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3543
3544     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3545     gc_values.background = XWhitePixel(xDisplay, xScreen);
3546     coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3547     XSetFont(xDisplay, coordGC, coordFontID);
3548
3549     // [HGM] make font for holdings counts (white on black0
3550     gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3551     gc_values.background = XBlackPixel(xDisplay, xScreen);
3552     countGC = XtGetGC(shellWidget, value_mask, &gc_values);
3553     XSetFont(xDisplay, countGC, countFontID);
3554
3555     if (appData.monoMode) {
3556         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3557         gc_values.background = XWhitePixel(xDisplay, xScreen);
3558         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3559
3560         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3561         gc_values.background = XBlackPixel(xDisplay, xScreen);
3562         lightSquareGC = wbPieceGC
3563           = XtGetGC(shellWidget, value_mask, &gc_values);
3564
3565         gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3566         gc_values.background = XWhitePixel(xDisplay, xScreen);
3567         darkSquareGC = bwPieceGC
3568           = XtGetGC(shellWidget, value_mask, &gc_values);
3569
3570         if (DefaultDepth(xDisplay, xScreen) == 1) {
3571             /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3572             gc_values.function = GXcopyInverted;
3573             copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3574             gc_values.function = GXcopy;
3575             if (XBlackPixel(xDisplay, xScreen) == 1) {
3576                 bwPieceGC = darkSquareGC;
3577                 wbPieceGC = copyInvertedGC;
3578             } else {
3579                 bwPieceGC = copyInvertedGC;
3580                 wbPieceGC = lightSquareGC;
3581             }
3582         }
3583     } else {
3584         gc_values.foreground = highlightSquareColor;
3585         gc_values.background = highlightSquareColor;
3586         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3587
3588         gc_values.foreground = premoveHighlightColor;
3589         gc_values.background = premoveHighlightColor;
3590         prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3591
3592         gc_values.foreground = lightSquareColor;
3593         gc_values.background = darkSquareColor;
3594         lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3595
3596         gc_values.foreground = darkSquareColor;
3597         gc_values.background = lightSquareColor;
3598         darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3599
3600         gc_values.foreground = jailSquareColor;
3601         gc_values.background = jailSquareColor;
3602         jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3603
3604         gc_values.foreground = whitePieceColor;
3605         gc_values.background = darkSquareColor;
3606         wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3607
3608         gc_values.foreground = whitePieceColor;
3609         gc_values.background = lightSquareColor;
3610         wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3611
3612         gc_values.foreground = whitePieceColor;
3613         gc_values.background = jailSquareColor;
3614         wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3615
3616         gc_values.foreground = blackPieceColor;
3617         gc_values.background = darkSquareColor;
3618         bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3619
3620         gc_values.foreground = blackPieceColor;
3621         gc_values.background = lightSquareColor;
3622         blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3623
3624         gc_values.foreground = blackPieceColor;
3625         gc_values.background = jailSquareColor;
3626         bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3627     }
3628 }
3629
3630 void loadXIM(xim, xmask, filename, dest, mask)
3631      XImage *xim;
3632      XImage *xmask;
3633      char *filename;
3634      Pixmap *dest;
3635      Pixmap *mask;
3636 {
3637     int x, y, w, h, p;
3638     FILE *fp;
3639     Pixmap temp;
3640     XGCValues   values;
3641     GC maskGC;
3642
3643     fp = fopen(filename, "rb");
3644     if (!fp) {
3645         fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3646         exit(1);
3647     }
3648
3649     w = fgetc(fp);
3650     h = fgetc(fp);
3651
3652     for (y=0; y<h; ++y) {
3653         for (x=0; x<h; ++x) {
3654             p = fgetc(fp);
3655
3656             switch (p) {
3657               case 0:
3658                 XPutPixel(xim, x, y, blackPieceColor);
3659                 if (xmask)
3660                   XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3661                 break;
3662               case 1:
3663                 XPutPixel(xim, x, y, darkSquareColor);
3664                 if (xmask)
3665                   XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3666                 break;
3667               case 2:
3668                 XPutPixel(xim, x, y, whitePieceColor);
3669                 if (xmask)
3670                   XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3671                 break;
3672               case 3:
3673                 XPutPixel(xim, x, y, lightSquareColor);
3674                 if (xmask)
3675                   XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3676                 break;
3677             }
3678         }
3679     }
3680
3681     /* create Pixmap of piece */
3682     *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3683                           w, h, xim->depth);
3684     XPutImage(xDisplay, *dest, lightSquareGC, xim,
3685               0, 0, 0, 0, w, h);
3686
3687     /* create Pixmap of clipmask
3688        Note: We assume the white/black pieces have the same
3689              outline, so we make only 6 masks. This is okay
3690              since the XPM clipmask routines do the same. */
3691     if (xmask) {
3692       temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3693                             w, h, xim->depth);
3694       XPutImage(xDisplay, temp, lightSquareGC, xmask,
3695               0, 0, 0, 0, w, h);
3696
3697       /* now create the 1-bit version */
3698       *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3699                           w, h, 1);
3700
3701       values.foreground = 1;
3702       values.background = 0;
3703
3704       /* Don't use XtGetGC, not read only */
3705       maskGC = XCreateGC(xDisplay, *mask,
3706                     GCForeground | GCBackground, &values);
3707       XCopyPlane(xDisplay, temp, *mask, maskGC,
3708                   0, 0, squareSize, squareSize, 0, 0, 1);
3709       XFreePixmap(xDisplay, temp);
3710     }
3711 }
3712
3713 void CreateXIMPieces()
3714 {
3715     int piece, kind;
3716     char buf[MSG_SIZ];
3717     u_int ss;
3718     static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3719     XImage *ximtemp;
3720
3721     ss = squareSize;
3722
3723     /* The XSynchronize calls were copied from CreatePieces.
3724        Not sure if needed, but can't hurt */
3725     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3726                                      buffering bug */
3727
3728     /* temp needed by loadXIM() */
3729     ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3730                  0, 0, ss, ss, AllPlanes, XYPixmap);
3731
3732     if (strlen(appData.pixmapDirectory) == 0) {
3733       useImages = 0;
3734     } else {
3735         useImages = 1;
3736         if (appData.monoMode) {
3737           DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3738                             0, 2);
3739           ExitEvent(2);
3740         }
3741         fprintf(stderr, _("\nLoading XIMs...\n"));
3742         /* Load pieces */
3743         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3744             fprintf(stderr, "%d", piece+1);
3745             for (kind=0; kind<4; kind++) {
3746                 fprintf(stderr, ".");
3747                 snprintf(buf, sizeof(buf), "%s/%c%s%u.xim",
3748                         ExpandPathName(appData.pixmapDirectory),
3749                         ToLower(PieceToChar((ChessSquare)piece)),
3750                         ximkind[kind], ss);
3751                 ximPieceBitmap[kind][piece] =
3752                   XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3753                             0, 0, ss, ss, AllPlanes, XYPixmap);
3754                 if (appData.debugMode)
3755                   fprintf(stderr, _("(File:%s:) "), buf);
3756                 loadXIM(ximPieceBitmap[kind][piece],
3757                         ximtemp, buf,
3758                         &(xpmPieceBitmap[kind][piece]),
3759                         &(ximMaskPm[piece%(int)BlackPawn]));
3760             }
3761             fprintf(stderr," ");
3762         }
3763         /* Load light and dark squares */
3764         /* If the LSQ and DSQ pieces don't exist, we will
3765            draw them with solid squares. */
3766         snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3767         if (access(buf, 0) != 0) {
3768             useImageSqs = 0;
3769         } else {
3770             useImageSqs = 1;
3771             fprintf(stderr, _("light square "));
3772             ximLightSquare=
3773               XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3774                         0, 0, ss, ss, AllPlanes, XYPixmap);
3775             if (appData.debugMode)
3776               fprintf(stderr, _("(File:%s:) "), buf);
3777
3778             loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3779             fprintf(stderr, _("dark square "));
3780             snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
3781                     ExpandPathName(appData.pixmapDirectory), ss);
3782             if (appData.debugMode)
3783               fprintf(stderr, _("(File:%s:) "), buf);
3784             ximDarkSquare=
3785               XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3786                         0, 0, ss, ss, AllPlanes, XYPixmap);
3787             loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3788             xpmJailSquare = xpmLightSquare;
3789         }
3790         fprintf(stderr, _("Done.\n"));
3791     }
3792     XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3793 }
3794
3795 char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsuk";
3796
3797 #if HAVE_LIBXPM
3798 void CreateXPMPieces()
3799 {
3800     int piece, kind, r;
3801     char buf[MSG_SIZ];
3802     u_int ss = squareSize;
3803     XpmAttributes attr;
3804     static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3805     XpmColorSymbol symbols[4];
3806
3807 #if 0
3808     /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3809     if (appData.debugMode) {
3810         fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3811                 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3812     }
3813 #endif
3814
3815     /* The XSynchronize calls were copied from CreatePieces.
3816        Not sure if needed, but can't hurt */
3817     XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3818
3819     /* Setup translations so piece colors match square colors */
3820     symbols[0].name = "light_piece";
3821     symbols[0].value = appData.whitePieceColor;
3822     symbols[1].name = "dark_piece";
3823     symbols[1].value = appData.blackPieceColor;
3824     symbols[2].name = "light_square";
3825     symbols[2].value = appData.lightSquareColor;
3826     symbols[3].name = "dark_square";
3827     symbols[3].value = appData.darkSquareColor;
3828
3829     attr.valuemask = XpmColorSymbols;
3830     attr.colorsymbols = symbols;
3831     attr.numsymbols = 4;
3832
3833     if (appData.monoMode) {
3834       DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3835                         0, 2);
3836       ExitEvent(2);
3837     }
3838     if (strlen(appData.pixmapDirectory) == 0) {
3839         XpmPieces* pieces = builtInXpms;
3840         useImages = 1;
3841         /* Load pieces */
3842         while (pieces->size != squareSize && pieces->size) pieces++;
3843         if (!pieces->size) {
3844           fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3845           exit(1);
3846         }
3847         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3848             for (kind=0; kind<4; kind++) {
3849
3850                 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3851                                                pieces->xpm[piece][kind],
3852                                                &(xpmPieceBitmap[kind][piece]),
3853                                                NULL, &attr)) != 0) {
3854                   fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3855                           r, buf);
3856                   exit(1);
3857                 }
3858             }
3859         }
3860         useImageSqs = 0;
3861         xpmJailSquare = xpmLightSquare;
3862     } else {
3863         useImages = 1;
3864
3865         fprintf(stderr, _("\nLoading XPMs...\n"));
3866
3867         /* Load pieces */
3868         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3869             fprintf(stderr, "%d ", piece+1);
3870             for (kind=0; kind<4; kind++) {
3871               snprintf(buf, sizeof(buf), "%s/%c%s%u.xpm",
3872                         ExpandPathName(appData.pixmapDirectory),
3873                         pieceBitmapNames[piece],
3874                         xpmkind[kind], ss);
3875                 if (appData.debugMode) {
3876                     fprintf(stderr, _("(File:%s:) "), buf);
3877                 }
3878                 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3879                                            &(xpmPieceBitmap[kind][piece]),
3880                                            NULL, &attr)) != 0) {
3881                     fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3882                             r, buf);
3883                     exit(1);
3884                 }
3885             }
3886         }
3887         /* Load light and dark squares */
3888         /* If the LSQ and DSQ pieces don't exist, we will
3889            draw them with solid squares. */
3890         fprintf(stderr, _("light square "));
3891         snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3892         if (access(buf, 0) != 0) {
3893             useImageSqs = 0;
3894         } else {
3895             useImageSqs = 1;
3896             if (appData.debugMode)
3897               fprintf(stderr, _("(File:%s:) "), buf);
3898
3899             if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3900                                        &xpmLightSquare, NULL, &attr)) != 0) {
3901                 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3902                 exit(1);
3903             }
3904             fprintf(stderr, _("dark square "));
3905             snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
3906                     ExpandPathName(appData.pixmapDirectory), ss);
3907             if (appData.debugMode) {
3908                 fprintf(stderr, _("(File:%s:) "), buf);
3909             }
3910             if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3911                                        &xpmDarkSquare, NULL, &attr)) != 0) {
3912                 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3913                 exit(1);
3914             }
3915         }
3916         xpmJailSquare = xpmLightSquare;
3917         fprintf(stderr, _("Done.\n"));
3918     }
3919     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3920                                       buffering bug */
3921 }
3922 #endif /* HAVE_LIBXPM */
3923
3924 #if HAVE_LIBXPM
3925 /* No built-in bitmaps */
3926 void CreatePieces()
3927 {
3928     int piece, kind;
3929     char buf[MSG_SIZ];
3930     u_int ss = squareSize;
3931
3932     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3933                                      buffering bug */
3934
3935     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3936         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3937             sprintf(buf, "%c%u%c.bm", pieceBitmapNames[piece],
3938                     ss, kind == SOLID ? 's' : 'o');
3939             ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3940         }
3941     }
3942
3943     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3944                                       buffering bug */
3945 }
3946 #else
3947 /* With built-in bitmaps */
3948 void CreatePieces()
3949 {
3950     BuiltInBits* bib = builtInBits;
3951     int piece, kind;
3952     char buf[MSG_SIZ];
3953     u_int ss = squareSize;
3954
3955     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3956                                      buffering bug */
3957
3958     while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3959
3960     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3961         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3962             sprintf(buf, "%c%u%c.bm", pieceBitmapNames[piece],
3963                     ss, kind == SOLID ? 's' : 'o');
3964             ReadBitmap(&pieceBitmap[kind][piece], buf,
3965                        bib->bits[kind][piece], ss, ss);
3966         }
3967     }
3968
3969     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3970                                       buffering bug */
3971 }
3972 #endif
3973
3974 void ReadBitmap(pm, name, bits, wreq, hreq)
3975      Pixmap *pm;
3976      String name;
3977      unsigned char bits[];
3978      u_int wreq, hreq;
3979 {
3980     int x_hot, y_hot;
3981     u_int w, h;
3982     int errcode;
3983     char msg[MSG_SIZ], fullname[MSG_SIZ];
3984
3985     if (*appData.bitmapDirectory != NULLCHAR) {
3986         strcpy(fullname, appData.bitmapDirectory);
3987         strcat(fullname, "/");
3988         strcat(fullname, name);
3989         errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3990                                   &w, &h, pm, &x_hot, &y_hot);
3991     fprintf(stderr, "load %s\n", name);
3992         if (errcode != BitmapSuccess) {
3993             switch (errcode) {
3994               case BitmapOpenFailed:
3995                 snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
3996                 break;
3997               case BitmapFileInvalid:
3998                 snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
3999                 break;
4000               case BitmapNoMemory:
4001                 snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
4002                         fullname);
4003                 break;
4004               default:
4005                 snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
4006                         errcode, fullname);
4007                 break;
4008             }
4009             fprintf(stderr, _("%s: %s...using built-in\n"),
4010                     programName, msg);
4011         } else if (w != wreq || h != hreq) {
4012             fprintf(stderr,
4013                     _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
4014                     programName, fullname, w, h, wreq, hreq);
4015         } else {
4016             return;
4017         }
4018     }
4019     if (bits == NULL) {
4020 #if 0
4021         fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
4022                 programName, name);
4023         exit(1);
4024 #endif
4025         ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
4026     } else {
4027         *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
4028                                     wreq, hreq);
4029     }
4030 }
4031
4032 void CreateGrid()
4033 {
4034     int i, j;
4035
4036     if (lineGap == 0) return;
4037
4038     /* [HR] Split this into 2 loops for non-square boards. */
4039
4040     for (i = 0; i < BOARD_HEIGHT + 1; i++) {
4041         gridSegments[i].x1 = 0;
4042         gridSegments[i].x2 =
4043           lineGap + BOARD_WIDTH * (squareSize + lineGap);
4044         gridSegments[i].y1 = gridSegments[i].y2
4045           = lineGap / 2 + (i * (squareSize + lineGap));
4046     }
4047
4048     for (j = 0; j < BOARD_WIDTH + 1; j++) {
4049         gridSegments[j + i].y1 = 0;
4050         gridSegments[j + i].y2 =
4051           lineGap + BOARD_HEIGHT * (squareSize + lineGap);
4052         gridSegments[j + i].x1 = gridSegments[j + i].x2
4053           = lineGap / 2 + (j * (squareSize + lineGap));
4054     }
4055 }
4056
4057 static void MenuBarSelect(w, addr, index)
4058      Widget w;
4059      caddr_t addr;
4060      caddr_t index;
4061 {
4062     XtActionProc proc = (XtActionProc) addr;
4063
4064     (proc)(NULL, NULL, NULL, NULL);
4065 }
4066
4067 void CreateMenuBarPopup(parent, name, mb)
4068      Widget parent;
4069      String name;
4070      Menu *mb;
4071 {
4072     int j;
4073     Widget menu, entry;
4074     MenuItem *mi;
4075     Arg args[16];
4076
4077     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
4078                               parent, NULL, 0);
4079     j = 0;
4080     XtSetArg(args[j], XtNleftMargin, 20);   j++;
4081     XtSetArg(args[j], XtNrightMargin, 20);  j++;
4082     mi = mb->mi;
4083     while (mi->string != NULL) {
4084         if (strcmp(mi->string, "----") == 0) {
4085             entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
4086                                           menu, args, j);
4087         } else {
4088           XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
4089             entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
4090                                           menu, args, j+1);
4091             XtAddCallback(entry, XtNcallback,
4092                           (XtCallbackProc) MenuBarSelect,
4093                           (caddr_t) mi->proc);
4094         }
4095         mi++;
4096     }
4097 }
4098
4099 Widget CreateMenuBar(mb)
4100      Menu *mb;
4101 {
4102     int j;
4103     Widget anchor, menuBar;
4104     Arg args[16];
4105     char menuName[MSG_SIZ];
4106
4107     j = 0;
4108     XtSetArg(args[j], XtNorientation, XtorientHorizontal);  j++;
4109     XtSetArg(args[j], XtNvSpace, 0);                        j++;
4110     XtSetArg(args[j], XtNborderWidth, 0);                   j++;
4111     menuBar = XtCreateWidget("menuBar", boxWidgetClass,
4112                              formWidget, args, j);
4113
4114     while (mb->name != NULL) {
4115         strcpy(menuName, "menu");
4116         strcat(menuName, mb->name);
4117         j = 0;
4118         XtSetArg(args[j], XtNmenuName, XtNewString(menuName));  j++;
4119         if (tinyLayout) {
4120             char shortName[2];
4121             shortName[0] = _(mb->name)[0];
4122             shortName[1] = NULLCHAR;
4123             XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
4124         }
4125       else {