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