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