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