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