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