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