1e009fa8c4c96844d763ff405b77fb71db07e1ad
[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     textdomain(PRODUCT);
1877 #endif
1878
1879     shellWidget =
1880       XtAppInitialize(&appContext, "XBoard", shellOptions,
1881                       XtNumber(shellOptions),
1882                       &argc, argv, xboardResources, NULL, 0);
1883     if (argc > 1) {
1884         fprintf(stderr, _("%s: unrecognized argument %s\n"),
1885                 programName, argv[1]);
1886         exit(2);
1887     }
1888     
1889     if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1890         chessDir = ".";
1891     } else {
1892         if (chdir(chessDir) != 0) {
1893             fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1894             perror(chessDir);
1895             exit(1);
1896         }
1897     }
1898     
1899     p = getenv("HOME");
1900     if (p == NULL) p = "/tmp";
1901     i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1902     gameCopyFilename = (char*) malloc(i);
1903     gamePasteFilename = (char*) malloc(i);
1904     sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1905     sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1906
1907     XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1908                               clientResources, XtNumber(clientResources),
1909                               NULL, 0);
1910                               
1911     if (appData.debugMode) {
1912        if ((debugFP = fopen("xboard.debug", "w")) == NULL)  {
1913           printf(_("Failed to open file xboard.debug \n"));
1914           exit(errno);
1915        }
1916         setbuf(debugFP, NULL);
1917     }
1918     
1919 #if !HIGHDRAG
1920     /* This feature does not work; animation needs a rewrite */
1921     appData.highlightDragging = FALSE;
1922 #endif
1923     InitBackEnd1();
1924
1925     xDisplay = XtDisplay(shellWidget);
1926     xScreen = DefaultScreen(xDisplay);
1927     wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1928
1929     /*
1930      * Determine boardSize
1931      */
1932     if (isdigit(appData.boardSize[0])) {
1933         i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1934                    &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1935                    &fontPxlSize, &smallLayout, &tinyLayout);
1936         if (i == 0) {
1937             fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1938                     programName, appData.boardSize);
1939             exit(2);
1940         }
1941         if (i < 7) {
1942             /* Find some defaults; use the nearest known size */
1943             SizeDefaults *szd, *nearest;
1944             int distance = 99999;
1945             nearest = szd = sizeDefaults;
1946             while (szd->name != NULL) {
1947                 if (abs(szd->squareSize - squareSize) < distance) {
1948                     nearest = szd;
1949                     distance = abs(szd->squareSize - squareSize);
1950                     if (distance == 0) break;
1951                 }
1952                 szd++;
1953             }
1954             if (i < 2) lineGap = nearest->lineGap;
1955             if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1956             if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1957             if (i < 5) fontPxlSize = nearest->fontPxlSize;
1958             if (i < 6) smallLayout = nearest->smallLayout;
1959             if (i < 7) tinyLayout = nearest->tinyLayout;
1960         }
1961     } else {
1962         SizeDefaults *szd = sizeDefaults;
1963         if (*appData.boardSize == NULLCHAR) {
1964             while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1965                    DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1966               szd++;
1967             }
1968             if (szd->name == NULL) szd--;
1969         } else {
1970             while (szd->name != NULL &&
1971                    StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1972             if (szd->name == NULL) {
1973                 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1974                         programName, appData.boardSize);
1975                 exit(2);
1976             }
1977         }
1978         squareSize = szd->squareSize;
1979         lineGap = szd->lineGap;
1980         clockFontPxlSize = szd->clockFontPxlSize;
1981         coordFontPxlSize = szd->coordFontPxlSize;
1982         fontPxlSize = szd->fontPxlSize;
1983         smallLayout = szd->smallLayout;
1984         tinyLayout = szd->tinyLayout;
1985     }
1986
1987     /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1988     if (strlen(appData.pixmapDirectory) > 0) {
1989         p = ExpandPathName(appData.pixmapDirectory);
1990         if (!p) {
1991             fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1992                    appData.pixmapDirectory);
1993             exit(1);
1994         }
1995         if (appData.debugMode) {
1996             fprintf(stderr, _("\
1997 XBoard square size (hint): %d\n\
1998 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1999         }
2000         squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2001         if (appData.debugMode) {
2002             fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2003         }
2004     }
2005                 
2006     boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
2007     if (appData.showJail == 1) {
2008         /* Jail on top and bottom */
2009         XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2010         XtSetArg(boardArgs[2], XtNheight,
2011                  boardWidth + 2*(lineGap + squareSize));
2012     } else if (appData.showJail == 2) {
2013         /* Jail on sides */
2014         XtSetArg(boardArgs[1], XtNwidth,
2015                  boardWidth + 2*(lineGap + squareSize));
2016         XtSetArg(boardArgs[2], XtNheight, boardWidth);
2017     } else {
2018         /* No jail */
2019         XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2020         XtSetArg(boardArgs[2], XtNheight, boardWidth);
2021     }
2022
2023     /*
2024      * Determine what fonts to use.
2025      */
2026     appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2027     clockFontID = XLoadFont(xDisplay, appData.clockFont);
2028     clockFontStruct = XQueryFont(xDisplay, clockFontID);
2029     appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2030     coordFontID = XLoadFont(xDisplay, appData.coordFont);
2031     coordFontStruct = XQueryFont(xDisplay, coordFontID);
2032     appData.font = FindFont(appData.font, fontPxlSize);
2033
2034     xdb = XtDatabase(xDisplay);
2035     XrmPutStringResource(&xdb, "*font", appData.font);
2036
2037     /*
2038      * Detect if there are not enough colors available and adapt.
2039      */
2040     if (DefaultDepth(xDisplay, xScreen) <= 2) {
2041       appData.monoMode = True;
2042     }
2043
2044     if (!appData.monoMode) {
2045         vFrom.addr = (caddr_t) appData.lightSquareColor;
2046         vFrom.size = strlen(appData.lightSquareColor);
2047         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2048         if (vTo.addr == NULL) {
2049           appData.monoMode = True;
2050           forceMono = True;
2051         } else {
2052           lightSquareColor = *(Pixel *) vTo.addr;
2053         }
2054     }
2055     if (!appData.monoMode) {
2056         vFrom.addr = (caddr_t) appData.darkSquareColor;
2057         vFrom.size = strlen(appData.darkSquareColor);
2058         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2059         if (vTo.addr == NULL) {
2060           appData.monoMode = True;
2061           forceMono = True;
2062         } else {
2063           darkSquareColor = *(Pixel *) vTo.addr;
2064         }
2065     }
2066     if (!appData.monoMode) {
2067         vFrom.addr = (caddr_t) appData.whitePieceColor;
2068         vFrom.size = strlen(appData.whitePieceColor);
2069         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2070         if (vTo.addr == NULL) {
2071           appData.monoMode = True;
2072           forceMono = True;
2073         } else {
2074           whitePieceColor = *(Pixel *) vTo.addr;
2075         }
2076     }
2077     if (!appData.monoMode) {
2078         vFrom.addr = (caddr_t) appData.blackPieceColor;
2079         vFrom.size = strlen(appData.blackPieceColor);
2080         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2081         if (vTo.addr == NULL) {
2082           appData.monoMode = True;
2083           forceMono = True;
2084         } else {
2085           blackPieceColor = *(Pixel *) vTo.addr;
2086         }
2087     }
2088
2089     if (!appData.monoMode) {
2090         vFrom.addr = (caddr_t) appData.highlightSquareColor;
2091         vFrom.size = strlen(appData.highlightSquareColor);
2092         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2093         if (vTo.addr == NULL) {
2094           appData.monoMode = True;
2095           forceMono = True;
2096         } else {
2097           highlightSquareColor = *(Pixel *) vTo.addr;
2098         }
2099     }
2100
2101     if (!appData.monoMode) {
2102         vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2103         vFrom.size = strlen(appData.premoveHighlightColor);
2104         XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2105         if (vTo.addr == NULL) {
2106           appData.monoMode = True;
2107           forceMono = True;
2108         } else {
2109           premoveHighlightColor = *(Pixel *) vTo.addr;
2110         }
2111     }
2112
2113     if (forceMono) {
2114       fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2115               programName);
2116     }
2117
2118     if (appData.monoMode && appData.debugMode) {
2119         fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2120                 (unsigned long) XWhitePixel(xDisplay, xScreen),
2121                 (unsigned long) XBlackPixel(xDisplay, xScreen));
2122     }
2123     
2124     if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2125         parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2126         parse_cpair(ColorChannel1, appData.colorChannel1) < 0  ||
2127         parse_cpair(ColorChannel, appData.colorChannel) < 0  ||
2128         parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2129         parse_cpair(ColorTell, appData.colorTell) < 0 ||
2130         parse_cpair(ColorChallenge, appData.colorChallenge) < 0  ||
2131         parse_cpair(ColorRequest, appData.colorRequest) < 0  ||
2132         parse_cpair(ColorSeek, appData.colorSeek) < 0  ||
2133         parse_cpair(ColorNormal, appData.colorNormal) < 0)
2134       {
2135           if (appData.colorize) {
2136               fprintf(stderr,
2137                       _("%s: can't parse color names; disabling colorization\n"),
2138                       programName);
2139           }
2140           appData.colorize = FALSE;
2141       }
2142     textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2143     textColors[ColorNone].attr = 0;
2144     
2145     XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2146     
2147     /*
2148      * widget hierarchy
2149      */
2150     if (tinyLayout) {
2151         layoutName = "tinyLayout";
2152     } else if (smallLayout) {
2153         layoutName = "smallLayout";
2154     } else {
2155         layoutName = "normalLayout";
2156     }
2157     /* Outer layoutWidget is there only to provide a name for use in
2158        resources that depend on the layout style */
2159     layoutWidget =
2160       XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2161                             layoutArgs, XtNumber(layoutArgs));
2162     formWidget =
2163       XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2164                             formArgs, XtNumber(formArgs));
2165     XtSetArg(args[0], XtNdefaultDistance, &sep);
2166     XtGetValues(formWidget, args, 1);
2167     
2168     j = 0;
2169     widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2170
2171     widgetList[j++] = whiteTimerWidget =
2172       XtCreateWidget("whiteTime", labelWidgetClass,
2173                      formWidget, timerArgs, XtNumber(timerArgs));
2174     XtSetArg(args[0], XtNfont, clockFontStruct);
2175     XtSetValues(whiteTimerWidget, args, 1);
2176     
2177     widgetList[j++] = blackTimerWidget =
2178       XtCreateWidget("blackTime", labelWidgetClass,
2179                      formWidget, timerArgs, XtNumber(timerArgs));
2180     XtSetArg(args[0], XtNfont, clockFontStruct);
2181     XtSetValues(blackTimerWidget, args, 1);
2182     
2183     if (appData.titleInWindow) {
2184         widgetList[j++] = titleWidget = 
2185           XtCreateWidget("title", labelWidgetClass, formWidget,
2186                          titleArgs, XtNumber(titleArgs));
2187     }
2188
2189     if (appData.showButtonBar) {
2190       widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2191     }
2192
2193     widgetList[j++] = messageWidget =
2194       XtCreateWidget("message", labelWidgetClass, formWidget,
2195                      messageArgs, XtNumber(messageArgs));
2196     
2197     widgetList[j++] = boardWidget =
2198       XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2199                      XtNumber(boardArgs));
2200
2201     XtManageChildren(widgetList, j);
2202     
2203     timerWidth = (boardWidth - sep) / 2;
2204     XtSetArg(args[0], XtNwidth, timerWidth);
2205     XtSetValues(whiteTimerWidget, args, 1);
2206     XtSetValues(blackTimerWidget, args, 1);
2207     
2208     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2209     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2210     XtGetValues(whiteTimerWidget, args, 2);
2211     
2212     if (appData.showButtonBar) {
2213       XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2214       XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2215       XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2216     }
2217
2218     /*
2219      * formWidget uses these constraints but they are stored
2220      * in the children.
2221      */
2222     i = 0;
2223     XtSetArg(args[i], XtNfromHoriz, 0); i++;
2224     XtSetValues(menuBarWidget, args, i);
2225     if (appData.titleInWindow) {
2226         if (smallLayout) {
2227             i = 0;
2228             XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2229             XtSetValues(whiteTimerWidget, args, i);
2230             i = 0;
2231             XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2232             XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2233             XtSetValues(blackTimerWidget, args, i);
2234             i = 0;
2235             XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2236             XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2237             XtSetValues(titleWidget, args, i);
2238             i = 0;
2239             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2240             XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2241             XtSetValues(messageWidget, args, i);
2242             if (appData.showButtonBar) {
2243               i = 0;
2244               XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2245               XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2246               XtSetValues(buttonBarWidget, args, i);
2247             }
2248         } else {
2249             i = 0;
2250             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2251             XtSetValues(whiteTimerWidget, args, i);
2252             i = 0;
2253             XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2254             XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2255             XtSetValues(blackTimerWidget, args, i);
2256             i = 0;
2257             XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2258             XtSetValues(titleWidget, args, i);
2259             i = 0;
2260             XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2261             XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2262             XtSetValues(messageWidget, args, i);
2263             if (appData.showButtonBar) {
2264               i = 0;
2265               XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2266               XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2267               XtSetValues(buttonBarWidget, args, i);
2268             }
2269         }
2270     } else {
2271         i = 0;
2272         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2273         XtSetValues(whiteTimerWidget, args, i);
2274         i = 0;
2275         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2276         XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2277         XtSetValues(blackTimerWidget, args, i);
2278         i = 0;
2279         XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2280         XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2281         XtSetValues(messageWidget, args, i);
2282         if (appData.showButtonBar) {
2283           i = 0;
2284           XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2285           XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2286           XtSetValues(buttonBarWidget, args, i);
2287         }
2288     }
2289     i = 0;
2290     XtSetArg(args[0], XtNfromVert, messageWidget);
2291     XtSetValues(boardWidget, args, 1);
2292
2293     XtRealizeWidget(shellWidget);
2294
2295     /*
2296      * Correct the width of the message and title widgets.
2297      * It is not known why some systems need the extra fudge term.
2298      * The value "2" is probably larger than needed.
2299      */
2300     XawFormDoLayout(formWidget, False);
2301 #define WIDTH_FUDGE 2
2302     i = 0;
2303     XtSetArg(args[i], XtNborderWidth, &bor);  i++;
2304     XtSetArg(args[i], XtNheight, &h);  i++;
2305     XtGetValues(messageWidget, args, i);
2306     if (appData.showButtonBar) {
2307       i = 0;
2308       XtSetArg(args[i], XtNwidth, &w);  i++;
2309       XtGetValues(buttonBarWidget, args, i);
2310       w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2311     } else {
2312       w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2313     }
2314
2315     gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2316     if (gres != XtGeometryYes && appData.debugMode) {
2317       fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2318               programName, gres, w, h, wr, hr);
2319     }
2320     
2321     /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2322     /* The size used for the child widget in layout lags one resize behind
2323        its true size, so we resize a second time, 1 pixel smaller.  Yeech! */
2324     w--;
2325     gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2326     if (gres != XtGeometryYes && appData.debugMode) {
2327       fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2328               programName, gres, w, h, wr, hr);
2329     }
2330     /* !! end hack */
2331
2332     if (appData.titleInWindow) {
2333         i = 0;
2334         XtSetArg(args[i], XtNborderWidth, &bor); i++;
2335         XtSetArg(args[i], XtNheight, &h);  i++;
2336         XtGetValues(titleWidget, args, i);
2337         if (smallLayout) {
2338             w = boardWidth - 2*bor;
2339         } else {
2340             XtSetArg(args[0], XtNwidth, &w);
2341             XtGetValues(menuBarWidget, args, 1);
2342             w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2343         }
2344
2345         gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2346         if (gres != XtGeometryYes && appData.debugMode) {
2347             fprintf(stderr,
2348                     _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2349                     programName, gres, w, h, wr, hr);
2350         }
2351     }
2352     XawFormDoLayout(formWidget, True);
2353
2354     xBoardWindow = XtWindow(boardWidget);
2355     
2356     /* 
2357      * Create X checkmark bitmap and initialize option menu checks.
2358      */
2359     ReadBitmap(&xMarkPixmap, "checkmark.bm",
2360                checkmark_bits, checkmark_width, checkmark_height);
2361     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2362     if (appData.alwaysPromoteToQueen) {
2363         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2364                     args, 1);
2365     }
2366     if (appData.animateDragging) {
2367         XtSetValues(XtNameToWidget(menuBarWidget,
2368                                    "menuOptions.Animate Dragging"),
2369                     args, 1);
2370     }
2371     if (appData.animate) {
2372         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2373                     args, 1);
2374     }
2375     if (appData.autoComment) {
2376         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2377                     args, 1);
2378     }
2379     if (appData.autoCallFlag) {
2380         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2381                     args, 1);
2382     }
2383     if (appData.autoFlipView) {
2384         XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2385                     args, 1);
2386     }
2387     if (appData.autoObserve) {
2388         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2389                     args, 1);
2390     }
2391     if (appData.autoRaiseBoard) {
2392         XtSetValues(XtNameToWidget(menuBarWidget,
2393                                    "menuOptions.Auto Raise Board"), args, 1);
2394     }
2395     if (appData.autoSaveGames) {
2396         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2397                     args, 1);
2398     }
2399     if (appData.saveGameFile[0] != NULLCHAR) {
2400         /* Can't turn this off from menu */
2401         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2402                     args, 1);
2403         XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2404                        False);
2405
2406     }
2407     if (appData.blindfold) {
2408         XtSetValues(XtNameToWidget(menuBarWidget,
2409                                    "menuOptions.Blindfold"), args, 1);
2410     }
2411     if (appData.flashCount > 0) {
2412         XtSetValues(XtNameToWidget(menuBarWidget,
2413                                    "menuOptions.Flash Moves"),
2414                     args, 1);
2415     }
2416     if (appData.getMoveList) {
2417         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2418                     args, 1);
2419     }
2420 #if HIGHDRAG
2421     if (appData.highlightDragging) {
2422         XtSetValues(XtNameToWidget(menuBarWidget,
2423                                    "menuOptions.Highlight Dragging"),
2424                     args, 1);
2425     }
2426 #endif
2427     if (appData.highlightLastMove) {
2428         XtSetValues(XtNameToWidget(menuBarWidget,
2429                                    "menuOptions.Highlight Last Move"),
2430                     args, 1);
2431     }
2432     if (appData.icsAlarm) {
2433         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2434                     args, 1);
2435     }
2436     if (appData.ringBellAfterMoves) {
2437         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2438                     args, 1);
2439     }
2440     if (appData.oldSaveStyle) {
2441         XtSetValues(XtNameToWidget(menuBarWidget,
2442                                    "menuOptions.Old Save Style"), args, 1);
2443     }
2444     if (appData.periodicUpdates) {
2445         XtSetValues(XtNameToWidget(menuBarWidget,
2446                                    "menuOptions.Periodic Updates"), args, 1);
2447     }   
2448     if (appData.ponderNextMove) {
2449         XtSetValues(XtNameToWidget(menuBarWidget,
2450                                    "menuOptions.Ponder Next Move"), args, 1);
2451     }   
2452     if (appData.popupExitMessage) {
2453         XtSetValues(XtNameToWidget(menuBarWidget,
2454                                    "menuOptions.Popup Exit Message"), args, 1);
2455     }   
2456     if (appData.popupMoveErrors) {
2457         XtSetValues(XtNameToWidget(menuBarWidget,
2458                                    "menuOptions.Popup Move Errors"), args, 1);
2459     }   
2460     if (appData.premove) {
2461         XtSetValues(XtNameToWidget(menuBarWidget,
2462                                    "menuOptions.Premove"), args, 1);
2463     }
2464     if (appData.quietPlay) {
2465         XtSetValues(XtNameToWidget(menuBarWidget,
2466                                    "menuOptions.Quiet Play"), args, 1);
2467     }
2468     if (appData.showCoords) {
2469         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2470                     args, 1);
2471     }
2472     if (appData.showThinking) {
2473         XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2474                     args, 1);
2475     }
2476     if (appData.testLegality) {
2477         XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2478                     args, 1);
2479     }
2480
2481     /*
2482      * Create an icon.
2483      */
2484     ReadBitmap(&wIconPixmap, "icon_white.bm",
2485                icon_white_bits, icon_white_width, icon_white_height);
2486     ReadBitmap(&bIconPixmap, "icon_black.bm",
2487                icon_black_bits, icon_black_width, icon_black_height);
2488     iconPixmap = wIconPixmap;
2489     i = 0;
2490     XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
2491     XtSetValues(shellWidget, args, i);
2492     
2493     /*
2494      * Create a cursor for the board widget.
2495      */
2496     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2497     XChangeWindowAttributes(xDisplay, xBoardWindow,
2498                             CWCursor, &window_attributes);
2499     
2500     /*
2501      * Inhibit shell resizing.
2502      */
2503     shellArgs[0].value = (XtArgVal) &w;
2504     shellArgs[1].value = (XtArgVal) &h;
2505     XtGetValues(shellWidget, shellArgs, 2);
2506     shellArgs[4].value = shellArgs[2].value = w;
2507     shellArgs[5].value = shellArgs[3].value = h;
2508     XtSetValues(shellWidget, &shellArgs[2], 4);
2509     
2510     CatchDeleteWindow(shellWidget, "QuitProc");
2511
2512     CreateGCs();
2513     CreateGrid();
2514 #if HAVE_LIBXPM
2515     if (appData.bitmapDirectory[0] != NULLCHAR) {
2516       CreatePieces();
2517     } else {
2518       CreateXPMPieces();
2519     }
2520 #else
2521     CreateXIMPieces();
2522     /* Create regular pieces */
2523     if (!useImages) CreatePieces();
2524 #endif  
2525
2526     CreatePieceMenus();
2527
2528     if (appData.animate || appData.animateDragging)
2529       CreateAnimVars();
2530     
2531     XtAugmentTranslations(formWidget,
2532                           XtParseTranslationTable(globalTranslations));
2533     XtAugmentTranslations(boardWidget,
2534                           XtParseTranslationTable(boardTranslations));
2535     XtAugmentTranslations(whiteTimerWidget,
2536                           XtParseTranslationTable(whiteTranslations));
2537     XtAugmentTranslations(blackTimerWidget,
2538                           XtParseTranslationTable(blackTranslations));
2539
2540     /* Why is the following needed on some versions of X instead
2541      * of a translation? */
2542     XtAddEventHandler(boardWidget, ExposureMask, False,
2543                       (XtEventHandler) EventProc, NULL);
2544     /* end why */
2545
2546     InitBackEnd2();
2547     
2548     if (errorExitStatus == -1) {
2549         if (appData.icsActive) {
2550             /* We now wait until we see "login:" from the ICS before
2551                sending the logon script (problems with timestamp otherwise) */
2552             /*ICSInitScript();*/
2553             if (appData.icsInputBox) ICSInputBoxPopUp();
2554         }
2555
2556         signal(SIGINT, IntSigHandler);
2557         signal(SIGTERM, IntSigHandler);
2558         if (*appData.cmailGameName != NULLCHAR) {
2559             signal(SIGUSR1, CmailSigHandler);
2560         }
2561     }
2562
2563     XtAppMainLoop(appContext);
2564     if (appData.debugMode) fclose(debugFP);
2565     
2566     return 0;
2567 }
2568
2569 void
2570 ShutDownFrontEnd()
2571 {
2572     if (appData.icsActive && oldICSInteractionTitle != NULL) {
2573         DisplayIcsInteractionTitle(oldICSInteractionTitle);
2574     }
2575     unlink(gameCopyFilename);
2576     unlink(gamePasteFilename);
2577 }
2578
2579 RETSIGTYPE
2580 IntSigHandler(sig)
2581      int sig;
2582 {
2583     ExitEvent(sig);
2584 }
2585
2586 RETSIGTYPE
2587 CmailSigHandler(sig)
2588      int sig;
2589 {
2590     int dummy = 0;
2591     int error;
2592
2593     signal(SIGUSR1, SIG_IGN);   /* suspend handler     */
2594
2595     /* Activate call-back function CmailSigHandlerCallBack()             */
2596     OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2597
2598     signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2599 }
2600
2601 void
2602 CmailSigHandlerCallBack(isr, closure, message, count, error)
2603      InputSourceRef isr;
2604      VOIDSTAR closure;
2605      char *message;
2606      int count;
2607      int error;
2608 {
2609     BoardToTop();
2610     ReloadCmailMsgEvent(TRUE);  /* Reload cmail msg  */
2611 }
2612 /**** end signal code ****/
2613
2614
2615 void
2616 ICSInitScript()
2617 {
2618     FILE *f;
2619     char buf[MSG_SIZ];
2620     char *p;
2621
2622     f = fopen(appData.icsLogon, "r");
2623     if (f == NULL) {
2624         p = getenv("HOME");
2625         if (p != NULL) {
2626             strcpy(buf, p);
2627             strcat(buf, "/");
2628             strcat(buf, appData.icsLogon);
2629             f = fopen(buf, "r");
2630         }
2631     }
2632     if (f != NULL)
2633       ProcessICSInitScript(f);
2634 }
2635
2636 void
2637 ResetFrontEnd()
2638 {
2639     CommentPopDown();
2640     EditCommentPopDown();
2641     TagsPopDown();
2642     return;
2643 }
2644
2645 typedef struct {
2646     char *name;
2647     Boolean value;
2648 } Enables;
2649
2650 void
2651 SetMenuEnables(enab)
2652      Enables *enab;
2653 {
2654   Widget w;
2655   if (!menuBarWidget) return;
2656   while (enab->name != NULL) {
2657     w = XtNameToWidget(menuBarWidget, enab->name);
2658     if (w == NULL) {
2659       DisplayError(enab->name, 0);
2660     } else {
2661       XtSetSensitive(w, enab->value);
2662     }
2663     enab++;
2664   }
2665 }
2666
2667 Enables icsEnables[] = {
2668     { "menuFile.Mail Move", False },
2669     { "menuFile.Reload CMail Message", False },
2670     { "menuMode.Machine Black", False },
2671     { "menuMode.Machine White", False },
2672     { "menuMode.Analysis Mode", False },
2673     { "menuMode.Analyze File", False },
2674     { "menuMode.Two Machines", False },
2675 #ifndef ZIPPY
2676     { "menuHelp.Hint", False },
2677     { "menuHelp.Book", False },
2678     { "menuStep.Move Now", False },
2679     { "menuOptions.Periodic Updates", False },  
2680     { "menuOptions.Show Thinking", False },
2681     { "menuOptions.Ponder Next Move", False },
2682 #endif
2683     { NULL, False }
2684 };
2685
2686 Enables ncpEnables[] = {    
2687     { "menuFile.Mail Move", False },
2688     { "menuFile.Reload CMail Message", False },
2689     { "menuMode.Machine White", False },
2690     { "menuMode.Machine Black", False },
2691     { "menuMode.Analysis Mode", False },
2692     { "menuMode.Analyze File", False },
2693     { "menuMode.Two Machines", False },
2694     { "menuMode.ICS Client", False },
2695     { "menuMode.ICS Input Box", False },
2696     { "Action", False },
2697     { "menuStep.Revert", False },
2698     { "menuStep.Move Now", False },
2699     { "menuStep.Retract Move", False },
2700     { "menuOptions.Auto Comment", False },
2701     { "menuOptions.Auto Flag", False },
2702     { "menuOptions.Auto Flip View", False },
2703     { "menuOptions.Auto Observe", False },
2704     { "menuOptions.Auto Raise Board", False },
2705     { "menuOptions.Get Move List", False },
2706     { "menuOptions.ICS Alarm", False },
2707     { "menuOptions.Move Sound", False },
2708     { "menuOptions.Quiet Play", False },
2709     { "menuOptions.Show Thinking", False },
2710     { "menuOptions.Periodic Updates", False },  
2711     { "menuOptions.Ponder Next Move", False },
2712     { "menuHelp.Hint", False },
2713     { "menuHelp.Book", False },
2714     { NULL, False }
2715 };
2716
2717 Enables gnuEnables[] = {    
2718     { "menuMode.ICS Client", False },
2719     { "menuMode.ICS Input Box", False },
2720     { "menuAction.Accept", False },
2721     { "menuAction.Decline", False },
2722     { "menuAction.Rematch", False },
2723     { "menuAction.Adjourn", False },
2724     { "menuAction.Stop Examining", False },
2725     { "menuAction.Stop Observing", False },
2726     { "menuStep.Revert", False },
2727     { "menuOptions.Auto Comment", False },
2728     { "menuOptions.Auto Observe", False },
2729     { "menuOptions.Auto Raise Board", False },
2730     { "menuOptions.Get Move List", False },
2731     { "menuOptions.Premove", False },
2732     { "menuOptions.Quiet Play", False },
2733
2734     /* The next two options rely on SetCmailMode being called *after*    */
2735     /* SetGNUMode so that when GNU is being used to give hints these     */
2736     /* menu options are still available                                  */
2737
2738     { "menuFile.Mail Move", False },
2739     { "menuFile.Reload CMail Message", False },
2740     { NULL, False }
2741 };
2742
2743 Enables cmailEnables[] = {    
2744     { "Action", True },
2745     { "menuAction.Call Flag", False },
2746     { "menuAction.Draw", True },
2747     { "menuAction.Adjourn", False },
2748     { "menuAction.Abort", False },
2749     { "menuAction.Stop Observing", False },
2750     { "menuAction.Stop Examining", False },
2751     { "menuFile.Mail Move", True },
2752     { "menuFile.Reload CMail Message", True },
2753     { NULL, False }
2754 };
2755
2756 Enables trainingOnEnables[] = {    
2757   { "menuMode.Edit Comment", False },
2758   { "menuMode.Pause", False },
2759   { "menuStep.Forward", False },
2760   { "menuStep.Backward", False },
2761   { "menuStep.Forward to End", False },
2762   { "menuStep.Back to Start", False },
2763   { "menuStep.Move Now", False },
2764   { "menuStep.Truncate Game", False },
2765   { NULL, False }
2766 };
2767
2768 Enables trainingOffEnables[] = {    
2769   { "menuMode.Edit Comment", True },
2770   { "menuMode.Pause", True },
2771   { "menuStep.Forward", True },
2772   { "menuStep.Backward", True },
2773   { "menuStep.Forward to End", True },
2774   { "menuStep.Back to Start", True },
2775   { "menuStep.Move Now", True },
2776   { "menuStep.Truncate Game", True },
2777   { NULL, False }
2778 };
2779
2780 Enables machineThinkingEnables[] = {
2781   { "menuFile.Load Game", False },
2782   { "menuFile.Load Next Game", False },
2783   { "menuFile.Load Previous Game", False },
2784   { "menuFile.Reload Same Game", False },
2785   { "menuFile.Paste Game", False },
2786   { "menuFile.Load Position", False },
2787   { "menuFile.Load Next Position", False },
2788   { "menuFile.Load Previous Position", False },
2789   { "menuFile.Reload Same Position", False },
2790   { "menuFile.Paste Position", False },
2791   { "menuMode.Machine White", False },
2792   { "menuMode.Machine Black", False },
2793   { "menuMode.Two Machines", False },
2794   { "menuStep.Retract Move", False },
2795   { NULL, False }
2796 };
2797
2798 Enables userThinkingEnables[] = {
2799   { "menuFile.Load Game", True },
2800   { "menuFile.Load Next Game", True },
2801   { "menuFile.Load Previous Game", True },
2802   { "menuFile.Reload Same Game", True },
2803   { "menuFile.Paste Game", True },
2804   { "menuFile.Load Position", True },
2805   { "menuFile.Load Next Position", True },
2806   { "menuFile.Load Previous Position", True },
2807   { "menuFile.Reload Same Position", True },
2808   { "menuFile.Paste Position", True },
2809   { "menuMode.Machine White", True },
2810   { "menuMode.Machine Black", True },
2811   { "menuMode.Two Machines", True },
2812   { "menuStep.Retract Move", True },
2813   { NULL, False }
2814 };
2815
2816 void SetICSMode()
2817 {
2818   SetMenuEnables(icsEnables);
2819
2820  #ifdef ZIPPY
2821   /* icsEngineAnalyze */
2822   if (appData.zippyPlay && !appData.noChessProgram) 
2823      XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2824  #endif
2825 }
2826
2827 void
2828 SetNCPMode()
2829 {
2830   SetMenuEnables(ncpEnables);
2831 }
2832
2833 void
2834 SetGNUMode()
2835 {
2836   SetMenuEnables(gnuEnables);
2837 }
2838
2839 void
2840 SetCmailMode()
2841 {
2842   SetMenuEnables(cmailEnables);
2843 }
2844
2845 void
2846 SetTrainingModeOn()
2847 {
2848   SetMenuEnables(trainingOnEnables);
2849   if (appData.showButtonBar) {
2850     XtSetSensitive(buttonBarWidget, False);
2851   }
2852   CommentPopDown();
2853 }
2854
2855 void
2856 SetTrainingModeOff()
2857 {
2858   SetMenuEnables(trainingOffEnables);
2859   if (appData.showButtonBar) {
2860     XtSetSensitive(buttonBarWidget, True);
2861   }
2862 }
2863
2864 void
2865 SetUserThinkingEnables()
2866 {
2867   if (appData.noChessProgram) return;
2868   SetMenuEnables(userThinkingEnables);
2869 }
2870
2871 void
2872 SetMachineThinkingEnables()
2873 {
2874   if (appData.noChessProgram) return;
2875   SetMenuEnables(machineThinkingEnables);
2876   switch (gameMode) {
2877   case MachinePlaysBlack:
2878   case MachinePlaysWhite:
2879   case TwoMachinesPlay:
2880     XtSetSensitive(XtNameToWidget(menuBarWidget,
2881                                   ModeToWidgetName(gameMode)), True);
2882     break;
2883   default:
2884     break;
2885   }
2886 }
2887
2888 #define Abs(n) ((n)<0 ? -(n) : (n))
2889
2890 /*
2891  * Find a font that matches "pattern" that is as close as
2892  * possible to the targetPxlSize.  Prefer fonts that are k
2893  * pixels smaller to fonts that are k pixels larger.  The
2894  * pattern must be in the X Consortium standard format, 
2895  * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2896  * The return value should be freed with XtFree when no
2897  * longer needed.
2898  */
2899 char *FindFont(pattern, targetPxlSize)
2900      char *pattern;
2901      int targetPxlSize;
2902 {
2903     char **fonts, *p, *best, *scalable, *scalableTail;
2904     int i, j, nfonts, minerr, err, pxlSize;
2905
2906 #ifdef ENABLE_NLS
2907     char **missing_list;
2908     int missing_count;
2909     char *def_string, *base_fnt_lst, strInt[3];
2910     XFontSet fntSet;
2911     XFontStruct **fnt_list;
2912
2913     base_fnt_lst = calloc(1, strlen(pattern) + 3);
2914     sprintf(strInt, "%d", targetPxlSize);
2915     p = strstr(pattern, "--");
2916     strncpy(base_fnt_lst, pattern, p - pattern + 2);
2917     strcat(base_fnt_lst, strInt);
2918     strcat(base_fnt_lst, strchr(p + 2, '-'));
2919
2920     if ((fntSet = XCreateFontSet(xDisplay, 
2921                                  base_fnt_lst, 
2922                                  &missing_list, 
2923                                  &missing_count, 
2924                                  &def_string)) == NULL) {
2925
2926         fprintf(stderr, _("Unable to create font set.\n"));
2927         exit (2);
2928     }
2929
2930     nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2931 #else
2932     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2933     if (nfonts < 1) {
2934         fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2935                 programName, pattern);
2936         exit(2);
2937     }
2938 #endif
2939
2940     best = fonts[0];
2941     scalable = NULL;
2942     minerr = 999999;
2943     for (i=0; i<nfonts; i++) {
2944         j = 0;
2945         p = fonts[i];
2946         if (*p != '-') continue;
2947         while (j < 7) {
2948             if (*p == NULLCHAR) break;
2949             if (*p++ == '-') j++;
2950         }
2951         if (j < 7) continue;
2952         pxlSize = atoi(p);
2953         if (pxlSize == 0) {
2954             scalable = fonts[i];
2955             scalableTail = p;
2956         } else {
2957             err = pxlSize - targetPxlSize;
2958             if (Abs(err) < Abs(minerr) ||
2959                 (minerr > 0 && err < 0 && -err == minerr)) {
2960                 best = fonts[i];
2961                 minerr = err;
2962             }
2963         }
2964     }
2965     if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2966         /* If the error is too big and there is a scalable font,
2967            use the scalable font. */
2968         int headlen = scalableTail - scalable;
2969         p = (char *) XtMalloc(strlen(scalable) + 10);
2970         while (isdigit(*scalableTail)) scalableTail++;
2971         sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2972     } else {
2973         p = (char *) XtMalloc(strlen(best) + 1);
2974         strcpy(p, best);
2975     }
2976     if (appData.debugMode) {
2977         fprintf(debugFP, _("resolved %s at pixel size %d\n  to %s\n"),
2978                 pattern, targetPxlSize, p);
2979     }
2980 #ifdef ENABLE_NLS
2981     if (missing_count > 0)
2982         XFreeStringList(missing_list);
2983     XFreeFontSet(xDisplay, fntSet);
2984 #else
2985     XFreeFontNames(fonts);
2986 #endif
2987     return p;
2988 }
2989
2990 void CreateGCs()
2991 {
2992     XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2993       | GCBackground | GCFunction | GCPlaneMask;
2994     XGCValues gc_values;
2995     GC copyInvertedGC;
2996     
2997     gc_values.plane_mask = AllPlanes;
2998     gc_values.line_width = lineGap;
2999     gc_values.line_style = LineSolid;
3000     gc_values.function = GXcopy;
3001     
3002     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3003     gc_values.background = XBlackPixel(xDisplay, xScreen);
3004     lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3005     
3006     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3007     gc_values.background = XWhitePixel(xDisplay, xScreen);
3008     coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3009     XSetFont(xDisplay, coordGC, coordFontID);
3010     
3011     if (appData.monoMode) {
3012         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3013         gc_values.background = XWhitePixel(xDisplay, xScreen);
3014         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);      
3015
3016         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3017         gc_values.background = XBlackPixel(xDisplay, xScreen);
3018         lightSquareGC = wbPieceGC 
3019           = XtGetGC(shellWidget, value_mask, &gc_values);
3020
3021         gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3022         gc_values.background = XWhitePixel(xDisplay, xScreen);
3023         darkSquareGC = bwPieceGC
3024           = XtGetGC(shellWidget, value_mask, &gc_values);
3025
3026         if (DefaultDepth(xDisplay, xScreen) == 1) {
3027             /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3028             gc_values.function = GXcopyInverted;
3029             copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3030             gc_values.function = GXcopy;
3031             if (XBlackPixel(xDisplay, xScreen) == 1) {
3032                 bwPieceGC = darkSquareGC;
3033                 wbPieceGC = copyInvertedGC;
3034             } else {
3035                 bwPieceGC = copyInvertedGC;
3036                 wbPieceGC = lightSquareGC;
3037             }
3038         }
3039     } else {
3040         gc_values.foreground = highlightSquareColor;
3041         gc_values.background = highlightSquareColor;
3042         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);      
3043
3044         gc_values.foreground = premoveHighlightColor;
3045         gc_values.background = premoveHighlightColor;
3046         prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);       
3047
3048         gc_values.foreground = lightSquareColor;
3049         gc_values.background = darkSquareColor;
3050         lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3051         
3052         gc_values.foreground = darkSquareColor;
3053         gc_values.background = lightSquareColor;
3054         darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3055
3056         gc_values.foreground = jailSquareColor;
3057         gc_values.background = jailSquareColor;
3058         jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3059
3060         gc_values.foreground = whitePieceColor;
3061         gc_values.background = darkSquareColor;
3062         wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3063         
3064         gc_values.foreground = whitePieceColor;
3065         gc_values.background = lightSquareColor;
3066         wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3067         
3068         gc_values.foreground = whitePieceColor;
3069         gc_values.background = jailSquareColor;
3070         wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3071         
3072         gc_values.foreground = blackPieceColor;
3073         gc_values.background = darkSquareColor;
3074         bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3075         
3076         gc_values.foreground = blackPieceColor;
3077         gc_values.background = lightSquareColor;
3078         blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3079
3080         gc_values.foreground = blackPieceColor;
3081         gc_values.background = jailSquareColor;
3082         bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3083     }
3084 }
3085
3086 void loadXIM(xim, xmask, filename, dest, mask)
3087      XImage *xim;
3088      XImage *xmask;
3089      char *filename;
3090      Pixmap *dest;
3091      Pixmap *mask;
3092 {
3093     int x, y, w, h, p;
3094     FILE *fp;
3095     Pixmap temp;
3096     XGCValues   values;
3097     GC maskGC;
3098
3099     fp = fopen(filename, "rb");
3100     if (!fp) {
3101         fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3102         exit(1);
3103     }
3104           
3105     w = fgetc(fp);
3106     h = fgetc(fp);
3107   
3108     for (y=0; y<h; ++y) {
3109         for (x=0; x<h; ++x) {
3110             p = fgetc(fp);
3111
3112             switch (p) {
3113               case 0:   
3114                 XPutPixel(xim, x, y, blackPieceColor); 
3115                 if (xmask)
3116                   XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3117                 break;
3118               case 1:   
3119                 XPutPixel(xim, x, y, darkSquareColor); 
3120                 if (xmask)
3121                   XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3122                 break;
3123               case 2:   
3124                 XPutPixel(xim, x, y, whitePieceColor); 
3125                 if (xmask)
3126                   XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3127                 break;
3128               case 3:   
3129                 XPutPixel(xim, x, y, lightSquareColor);
3130                 if (xmask)
3131                   XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3132                 break;
3133             }
3134         }
3135     }
3136
3137     /* create Pixmap of piece */
3138     *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3139                           w, h, xim->depth);
3140     XPutImage(xDisplay, *dest, lightSquareGC, xim,
3141               0, 0, 0, 0, w, h);  
3142
3143     /* create Pixmap of clipmask 
3144        Note: We assume the white/black pieces have the same
3145              outline, so we make only 6 masks. This is okay
3146              since the XPM clipmask routines do the same. */
3147     if (xmask) {
3148       temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3149                             w, h, xim->depth);
3150       XPutImage(xDisplay, temp, lightSquareGC, xmask,
3151               0, 0, 0, 0, w, h);  
3152
3153       /* now create the 1-bit version */
3154       *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3155                           w, h, 1);
3156
3157       values.foreground = 1;
3158       values.background = 0;
3159
3160       /* Don't use XtGetGC, not read only */
3161       maskGC = XCreateGC(xDisplay, *mask, 
3162                     GCForeground | GCBackground, &values);
3163       XCopyPlane(xDisplay, temp, *mask, maskGC, 
3164                   0, 0, squareSize, squareSize, 0, 0, 1);
3165       XFreePixmap(xDisplay, temp);
3166     }
3167 }
3168
3169 void CreateXIMPieces()
3170 {
3171     int piece, kind;
3172     char buf[MSG_SIZ];
3173     u_int ss;
3174     static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3175     XImage *ximtemp;
3176
3177     ss = squareSize;
3178
3179     /* The XSynchronize calls were copied from CreatePieces.
3180        Not sure if needed, but can't hurt */
3181     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3182                                      buffering bug */
3183   
3184     /* temp needed by loadXIM() */
3185     ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3186                  0, 0, ss, ss, AllPlanes, XYPixmap);
3187
3188     if (strlen(appData.pixmapDirectory) == 0) {
3189       useImages = 0;
3190     } else {
3191         useImages = 1;
3192         if (appData.monoMode) {
3193           DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3194                             0, 2);
3195           ExitEvent(2);
3196         }
3197         fprintf(stderr, _("\nLoading XIMs...\n"));
3198         /* Load pieces */
3199         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3200             fprintf(stderr, "%d", piece+1);
3201             for (kind=0; kind<4; kind++) {
3202                 fprintf(stderr, ".");
3203                 sprintf(buf, "%s/%c%s%u.xim",
3204                         ExpandPathName(appData.pixmapDirectory),
3205                         ToLower(PieceToChar((ChessSquare)piece)),
3206                         ximkind[kind], ss);
3207                 ximPieceBitmap[kind][piece] =
3208                   XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3209                             0, 0, ss, ss, AllPlanes, XYPixmap);
3210                 if (appData.debugMode)
3211                   fprintf(stderr, _("(File:%s:) "), buf);
3212                 loadXIM(ximPieceBitmap[kind][piece], 
3213                         ximtemp, buf,
3214                         &(xpmPieceBitmap[kind][piece]),
3215                         &(ximMaskPm[piece%6]));
3216             }
3217             fprintf(stderr," ");
3218         }
3219         /* Load light and dark squares */
3220         /* If the LSQ and DSQ pieces don't exist, we will 
3221            draw them with solid squares. */
3222         sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3223         if (access(buf, 0) != 0) {
3224             useImageSqs = 0;
3225         } else {
3226             useImageSqs = 1;
3227             fprintf(stderr, _("light square "));
3228             ximLightSquare= 
3229               XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3230                         0, 0, ss, ss, AllPlanes, XYPixmap);
3231             if (appData.debugMode)
3232               fprintf(stderr, _("(File:%s:) "), buf);
3233
3234             loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3235             fprintf(stderr, _("dark square "));
3236             sprintf(buf, "%s/dsq%u.xim",
3237                     ExpandPathName(appData.pixmapDirectory), ss);
3238             if (appData.debugMode)
3239               fprintf(stderr, _("(File:%s:) "), buf);
3240             ximDarkSquare= 
3241               XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3242                         0, 0, ss, ss, AllPlanes, XYPixmap);
3243             loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3244             xpmJailSquare = xpmLightSquare;
3245         }
3246         fprintf(stderr, _("Done.\n"));
3247     }
3248     XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3249 }
3250
3251 #if HAVE_LIBXPM
3252 void CreateXPMPieces()
3253 {
3254     int piece, kind, r;
3255     char buf[MSG_SIZ];
3256     u_int ss = squareSize;
3257     XpmAttributes attr;
3258     static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3259     XpmColorSymbol symbols[4];
3260
3261 #if 0
3262     /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3263     if (appData.debugMode) {
3264         fprintf(stderr, "XPM Library Version: %d.%d%c\n", 
3265                 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3266     }
3267 #endif
3268   
3269     /* The XSynchronize calls were copied from CreatePieces.
3270        Not sure if needed, but can't hurt */
3271     XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3272   
3273     /* Setup translations so piece colors match square colors */
3274     symbols[0].name = "light_piece";
3275     symbols[0].value = appData.whitePieceColor;
3276     symbols[1].name = "dark_piece";
3277     symbols[1].value = appData.blackPieceColor;
3278     symbols[2].name = "light_square";
3279     symbols[2].value = appData.lightSquareColor;
3280     symbols[3].name = "dark_square";
3281     symbols[3].value = appData.darkSquareColor;
3282
3283     attr.valuemask = XpmColorSymbols;
3284     attr.colorsymbols = symbols;
3285     attr.numsymbols = 4;
3286
3287     if (appData.monoMode) {
3288       DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3289                         0, 2);
3290       ExitEvent(2);
3291     }
3292     if (strlen(appData.pixmapDirectory) == 0) {
3293         XpmPieces* pieces = builtInXpms;
3294         useImages = 1;
3295         /* Load pieces */
3296         while (pieces->size != squareSize && pieces->size) pieces++;
3297         if (!pieces->size) {
3298           fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3299           exit(1);
3300         }
3301         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3302             for (kind=0; kind<4; kind++) {
3303
3304                 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3305                                                pieces->xpm[piece][kind],
3306                                                &(xpmPieceBitmap[kind][piece]),
3307                                                NULL, &attr)) != 0) {
3308                   fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3309                           r, buf);
3310                   exit(1); 
3311                 }       
3312             }   
3313         }
3314         useImageSqs = 0;
3315         xpmJailSquare = xpmLightSquare;
3316     } else {
3317         useImages = 1;
3318         
3319         fprintf(stderr, _("\nLoading XPMs...\n"));
3320
3321         /* Load pieces */
3322         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3323             fprintf(stderr, "%d ", piece+1);
3324             for (kind=0; kind<4; kind++) {
3325                 sprintf(buf, "%s/%c%s%u.xpm",
3326                         ExpandPathName(appData.pixmapDirectory),
3327                         ToLower(PieceToChar((ChessSquare)piece)),
3328                         xpmkind[kind], ss);
3329                 if (appData.debugMode) {
3330                     fprintf(stderr, _("(File:%s:) "), buf);
3331                 }
3332                 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3333                                            &(xpmPieceBitmap[kind][piece]),
3334                                            NULL, &attr)) != 0) {
3335                     fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3336                             r, buf);
3337                     exit(1); 
3338                 }       
3339             }   
3340         }
3341         /* Load light and dark squares */
3342         /* If the LSQ and DSQ pieces don't exist, we will 
3343            draw them with solid squares. */
3344         fprintf(stderr, _("light square "));
3345         sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3346         if (access(buf, 0) != 0) {
3347             useImageSqs = 0;
3348         } else {
3349             useImageSqs = 1;
3350             if (appData.debugMode)
3351               fprintf(stderr, _("(File:%s:) "), buf);
3352
3353             if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3354                                        &xpmLightSquare, NULL, &attr)) != 0) {
3355                 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3356                 exit(1);
3357             }
3358             fprintf(stderr, _("dark square "));
3359             sprintf(buf, "%s/dsq%u.xpm",
3360                     ExpandPathName(appData.pixmapDirectory), ss);
3361             if (appData.debugMode) {
3362                 fprintf(stderr, _("(File:%s:) "), buf);
3363             }
3364             if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3365                                        &xpmDarkSquare, NULL, &attr)) != 0) {
3366                 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3367                 exit(1);
3368             }
3369         }
3370         xpmJailSquare = xpmLightSquare;
3371         fprintf(stderr, _("Done.\n"));
3372     }
3373     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3374                                       buffering bug */  
3375 }
3376 #endif /* HAVE_LIBXPM */
3377
3378 #if HAVE_LIBXPM
3379 /* No built-in bitmaps */
3380 void CreatePieces()
3381 {
3382     int piece, kind;
3383     char buf[MSG_SIZ];
3384     u_int ss = squareSize;
3385         
3386     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3387                                      buffering bug */
3388
3389     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3390         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3391             sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3392                     ss, kind == SOLID ? 's' : 'o');
3393             ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3394         }
3395     }
3396     
3397     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3398                                       buffering bug */
3399 }
3400 #else
3401 /* With built-in bitmaps */
3402 void CreatePieces()
3403 {
3404     BuiltInBits* bib = builtInBits;
3405     int piece, kind;
3406     char buf[MSG_SIZ];
3407     u_int ss = squareSize;
3408         
3409     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3410                                      buffering bug */
3411
3412     while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3413
3414     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3415         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3416             sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3417                     ss, kind == SOLID ? 's' : 'o');
3418             ReadBitmap(&pieceBitmap[kind][piece], buf,
3419                        bib->bits[kind][piece], ss, ss);
3420         }
3421     }
3422     
3423     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3424                                       buffering bug */
3425 }
3426 #endif
3427
3428 void ReadBitmap(pm, name, bits, wreq, hreq)
3429      Pixmap *pm;
3430      String name;
3431      unsigned char bits[];
3432      u_int wreq, hreq;
3433 {
3434     int x_hot, y_hot;
3435     u_int w, h;
3436     int errcode;
3437     char msg[MSG_SIZ], fullname[MSG_SIZ];
3438     
3439     if (*appData.bitmapDirectory != NULLCHAR) {
3440         strcpy(fullname, appData.bitmapDirectory);
3441         strcat(fullname, "/");
3442         strcat(fullname, name);
3443         errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3444                                   &w, &h, pm, &x_hot, &y_hot);
3445         if (errcode != BitmapSuccess) {
3446             switch (errcode) {
3447               case BitmapOpenFailed:
3448                 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3449                 break;
3450               case BitmapFileInvalid:
3451                 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3452                 break;
3453               case BitmapNoMemory:
3454                 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3455                         fullname);
3456                 break;
3457               default:
3458                 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3459                         errcode, fullname);
3460                 break;
3461             }
3462             fprintf(stderr, _("%s: %s...using built-in\n"),
3463                     programName, msg);
3464         } else if (w != wreq || h != hreq) {
3465             fprintf(stderr,
3466                     _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3467                     programName, fullname, w, h, wreq, hreq);
3468         } else {
3469             return;
3470         }
3471     }
3472     if (bits == NULL) {
3473         fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3474                 programName, name);
3475         exit(1);
3476     } else {
3477         *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3478                                     wreq, hreq);
3479     }
3480 }
3481
3482 void CreateGrid()
3483 {
3484     int i;
3485     
3486     if (lineGap == 0) return;
3487     for (i = 0; i < BOARD_SIZE + 1; i++) {
3488         gridSegments[i].x1 = 0;
3489         gridSegments[i].x2 =
3490           lineGap + BOARD_SIZE * (squareSize + lineGap);
3491         gridSegments[i].y1 = gridSegments[i].y2
3492           = lineGap / 2 + (i * (squareSize + lineGap));
3493
3494         gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3495         gridSegments[i + BOARD_SIZE + 1].y2 =
3496           BOARD_SIZE * (squareSize + lineGap);
3497         gridSegments[i + BOARD_SIZE + 1].x1 =
3498           gridSegments[i + BOARD_SIZE + 1].x2
3499             = lineGap / 2 + (i * (squareSize + lineGap));
3500     }
3501 }
3502
3503 static void MenuBarSelect(w, addr, index)
3504      Widget w;
3505      caddr_t addr;
3506      caddr_t index;
3507 {
3508     XtActionProc proc = (XtActionProc) addr;
3509
3510     (proc)(NULL, NULL, NULL, NULL);
3511 }
3512
3513 void CreateMenuBarPopup(parent, name, mb)
3514      Widget parent;
3515      String name;
3516      Menu *mb;
3517 {
3518     int j;
3519     Widget menu, entry;
3520     MenuItem *mi;
3521     Arg args[16];
3522
3523     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3524                               parent, NULL, 0);
3525     j = 0;
3526     XtSetArg(args[j], XtNleftMargin, 20);   j++;
3527     XtSetArg(args[j], XtNrightMargin, 20);  j++;
3528     mi = mb->mi;
3529     while (mi->string != NULL) {
3530         if (strcmp(mi->string, "----") == 0) {
3531             entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3532                                           menu, args, j);
3533         } else {
3534             XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3535             entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3536                                           menu, args, j+1);
3537             XtAddCallback(entry, XtNcallback,
3538                           (XtCallbackProc) MenuBarSelect,
3539                           (caddr_t) mi->proc);
3540         }
3541         mi++;
3542     }
3543 }       
3544
3545 Widget CreateMenuBar(mb)
3546      Menu *mb;
3547 {
3548     int j;
3549     Widget anchor, menuBar;
3550     Arg args[16];
3551     char menuName[MSG_SIZ];
3552
3553     j = 0;
3554     XtSetArg(args[j], XtNorientation, XtorientHorizontal);  j++;
3555     XtSetArg(args[j], XtNvSpace, 0);                        j++;
3556     XtSetArg(args[j], XtNborderWidth, 0);                   j++;
3557     menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3558                              formWidget, args, j);
3559
3560     while (mb->name != NULL) {
3561         strcpy(menuName, "menu");
3562         strcat(menuName, mb->name);
3563         j = 0;
3564         XtSetArg(args[j], XtNmenuName, XtNewString(menuName));  j++;
3565         if (tinyLayout) {
3566             char shortName[2];
3567             shortName[0] = _(mb->name)[0];
3568             shortName[1] = NULLCHAR;
3569             XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3570         }
3571         else {
3572             XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3573         }
3574
3575         XtSetArg(args[j], XtNborderWidth, 0);                   j++;
3576         anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3577                                        menuBar, args, j);
3578         CreateMenuBarPopup(menuBar, menuName, mb);
3579         mb++;
3580     }
3581     return menuBar;
3582 }
3583
3584 Widget CreateButtonBar(mi)
3585      MenuItem *mi;
3586 {
3587     int j;
3588     Widget button, buttonBar;
3589     Arg args[16];
3590
3591     j = 0;
3592     XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3593     if (tinyLayout) {
3594         XtSetArg(args[j], XtNhSpace, 0); j++;
3595     }
3596     XtSetArg(args[j], XtNborderWidth, 0); j++;
3597     XtSetArg(args[j], XtNvSpace, 0);                        j++;
3598     buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3599                                formWidget, args, j);
3600
3601     while (mi->string != NULL) {
3602         j = 0;
3603         if (tinyLayout) {
3604             XtSetArg(args[j], XtNinternalWidth, 2); j++;
3605             XtSetArg(args[j], XtNborderWidth, 0); j++;
3606         }
3607         XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3608         button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3609                                        buttonBar, args, j);
3610         XtAddCallback(button, XtNcallback,
3611                       (XtCallbackProc) MenuBarSelect,
3612                       (caddr_t) mi->proc);
3613         mi++;
3614     }
3615     return buttonBar;
3616 }     
3617
3618 Widget
3619 CreatePieceMenu(name, color)
3620      char *name;
3621      int color;
3622 {
3623     int i;
3624     Widget entry, menu;
3625     Arg args[16];
3626     ChessSquare selection;
3627
3628     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3629                               boardWidget, args, 0);
3630     
3631     for (i = 0; i < PIECE_MENU_SIZE; i++) {
3632         String item = pieceMenuStrings[color][i];
3633         
3634         if (strcmp(item, "----") == 0) {
3635             entry = XtCreateManagedWidget(item, smeLineObjectClass,
3636                                           menu, NULL, 0);
3637         } else {
3638             XtSetArg(args[0], XtNlabel, XtNewString(_(item))); 
3639             entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3640                                           menu, args, 1);
3641             selection = pieceMenuTranslation[color][i];
3642             XtAddCallback(entry, XtNcallback,
3643                           (XtCallbackProc) PieceMenuSelect,
3644                           (caddr_t) selection);
3645             if (selection == WhitePawn || selection == BlackPawn) {
3646                 XtSetArg(args[0], XtNpopupOnEntry, entry);
3647                 XtSetValues(menu, args, 1);
3648             }
3649         }
3650     }
3651     return menu;
3652 }
3653
3654 void
3655 CreatePieceMenus()
3656 {
3657     int i;
3658     Widget entry;
3659     Arg args[16];
3660     ChessSquare selection;
3661
3662     whitePieceMenu = CreatePieceMenu("menuW", 0);
3663     blackPieceMenu = CreatePieceMenu("menuB", 1);
3664     
3665     XtRegisterGrabAction(PieceMenuPopup, True,
3666                          (unsigned)(ButtonPressMask|ButtonReleaseMask),
3667                          GrabModeAsync, GrabModeAsync);
3668
3669     XtSetArg(args[0], XtNlabel, _("Drop"));
3670     dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3671                                   boardWidget, args, 1);
3672     for (i = 0; i < DROP_MENU_SIZE; i++) {
3673         String item = dropMenuStrings[i];
3674         
3675         if (strcmp(item, "----") == 0) {
3676             entry = XtCreateManagedWidget(item, smeLineObjectClass,
3677                                           dropMenu, NULL, 0);
3678         } else {
3679             XtSetArg(args[0], XtNlabel, XtNewString(_(item))); 
3680             entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3681                                           dropMenu, args, 1);
3682             selection = dropMenuTranslation[i];
3683             XtAddCallback(entry, XtNcallback,
3684                           (XtCallbackProc) DropMenuSelect,
3685                           (caddr_t) selection);
3686         }
3687     }
3688 }       
3689
3690 void SetupDropMenu()
3691 {
3692     int i, j, count;
3693     char label[32];
3694     Arg args[16];
3695     Widget entry;
3696     char* p;
3697
3698     for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3699         entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3700         p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3701                    dmEnables[i].piece);
3702         XtSetSensitive(entry, p != NULL || !appData.testLegality
3703                        /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3704                                        && !appData.icsActive));
3705         count = 0;
3706         while (p && *p++ == dmEnables[i].piece) count++;
3707         sprintf(label, "%s  %d", dmEnables[i].widget, count);
3708         j = 0;
3709         XtSetArg(args[j], XtNlabel, label); j++;
3710         XtSetValues(entry, args, j);
3711     }
3712 }
3713
3714 void PieceMenuPopup(w, event, params, num_params)
3715      Widget w;
3716      XEvent *event;
3717      String *params;
3718      Cardinal *num_params;
3719 {
3720     String whichMenu;
3721     if (event->type != ButtonPress) return;
3722     if (errorUp) ErrorPopDown();
3723     switch (gameMode) {
3724       case EditPosition:
3725       case IcsExamining:
3726         whichMenu = params[0];
3727         break;
3728       case IcsPlayingWhite:
3729       case IcsPlayingBlack:
3730       case EditGame:
3731       case MachinePlaysWhite:
3732       case MachinePlaysBlack:
3733         if (appData.testLegality &&
3734             gameInfo.variant != VariantBughouse &&
3735             gameInfo.variant != VariantCrazyhouse) return;
3736         SetupDropMenu();
3737         whichMenu = "menuD";
3738         break;
3739       default:
3740         return;
3741     }
3742     
3743     if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3744         ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3745         pmFromX = pmFromY = -1;
3746         return;
3747     }
3748     if (flipView)
3749       pmFromX = BOARD_SIZE - 1 - pmFromX;
3750     else
3751       pmFromY = BOARD_SIZE - 1 - pmFromY;
3752     
3753     XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3754 }
3755
3756 static void PieceMenuSelect(w, piece, junk)
3757      Widget w;
3758      ChessSquare piece;
3759      caddr_t junk;
3760 {
3761     if (pmFromX < 0 || pmFromY < 0) return;
3762     EditPositionMenuEvent(piece, pmFromX, pmFromY);
3763 }
3764
3765 static void DropMenuSelect(w, piece, junk)
3766      Widget w;
3767      ChessSquare piece;
3768      caddr_t junk;
3769 {
3770     if (pmFromX < 0 || pmFromY < 0) return;
3771     DropMenuEvent(piece, pmFromX, pmFromY);
3772 }
3773
3774 void WhiteClock(w, event, prms, nprms)
3775      Widget w;
3776      XEvent *event;
3777      String *prms;
3778      Cardinal *nprms;
3779 {
3780     if (gameMode == EditPosition || gameMode == IcsExamining) {
3781         SetWhiteToPlayEvent();
3782     } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3783         CallFlagEvent();
3784     }
3785 }
3786
3787 void BlackClock(w, event, prms, nprms)
3788      Widget w;
3789      XEvent *event;
3790      String *prms;
3791      Cardinal *nprms;
3792 {
3793     if (gameMode == EditPosition || gameMode == IcsExamining) {
3794         SetBlackToPlayEvent();
3795     } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3796         CallFlagEvent();
3797     }
3798 }
3799
3800
3801 /*
3802  * If the user selects on a border boundary, return -1; if off the board,
3803  *   return -2.  Otherwise map the event coordinate to the square.
3804  */
3805 int EventToSquare(x, limit)
3806      int x;
3807 {
3808     if (x <= 0) 
3809       return -2;
3810     if (x < lineGap)
3811       return -1;
3812     x -= lineGap;
3813     if ((x % (squareSize + lineGap)) >= squareSize)
3814       return -1;
3815     x /= (squareSize + lineGap);
3816     if (x >= limit)
3817       return -2;
3818     return x;
3819 }
3820
3821 static void do_flash_delay(msec)
3822      unsigned long msec;
3823 {
3824     TimeDelay(msec);
3825 }
3826
3827 static void drawHighlight(file, rank, gc)
3828      int file, rank;
3829      GC gc;
3830 {
3831     int x, y;
3832
3833     if (lineGap == 0 || appData.blindfold) return;
3834     
3835     if (flipView) {
3836         x = lineGap/2 + ((BOARD_SIZE-1)-file) * 
3837           (squareSize + lineGap);
3838         y = lineGap/2 + rank * (squareSize + lineGap);
3839     } else {
3840         x = lineGap/2 + file * (squareSize + lineGap);
3841         y = lineGap/2 + ((BOARD_SIZE-1)-rank) * 
3842           (squareSize + lineGap);
3843     }
3844     
3845     XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3846                    squareSize+lineGap, squareSize+lineGap);
3847 }
3848
3849 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3850 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3851
3852 void
3853 SetHighlights(fromX, fromY, toX, toY)
3854      int fromX, fromY, toX, toY;
3855 {
3856     if (hi1X != fromX || hi1Y != fromY) {
3857         if (hi1X >= 0 && hi1Y >= 0) {
3858             drawHighlight(hi1X, hi1Y, lineGC);
3859         }
3860         if (fromX >= 0 && fromY >= 0) {
3861             drawHighlight(fromX, fromY, highlineGC);
3862         }
3863     }
3864     if (hi2X != toX || hi2Y != toY) {
3865         if (hi2X >= 0 && hi2Y >= 0) {
3866             drawHighlight(hi2X, hi2Y, lineGC);
3867         }
3868         if (toX >= 0 && toY >= 0) {
3869             drawHighlight(toX, toY, highlineGC);
3870         }
3871     }
3872     hi1X = fromX;
3873     hi1Y = fromY;
3874     hi2X = toX;
3875     hi2Y = toY;
3876 }
3877
3878 void
3879 ClearHighlights()
3880 {
3881     SetHighlights(-1, -1, -1, -1);
3882 }
3883
3884
3885 void
3886 SetPremoveHighlights(fromX, fromY, toX, toY)
3887      int fromX, fromY, toX, toY;
3888 {
3889     if (pm1X != fromX || pm1Y != fromY) {
3890         if (pm1X >= 0 && pm1Y >= 0) {
3891             drawHighlight(pm1X, pm1Y, lineGC);
3892         }
3893         if (fromX >= 0 && fromY >= 0) {
3894             drawHighlight(fromX, fromY, prelineGC);
3895         }
3896     }
3897     if (pm2X != toX || pm2Y != toY) {
3898         if (pm2X >= 0 && pm2Y >= 0) {
3899             drawHighlight(pm2X, pm2Y, lineGC);
3900         }
3901         if (toX >= 0 && toY >= 0) {
3902             drawHighlight(toX, toY, prelineGC);
3903         }
3904     }
3905     pm1X = fromX;
3906     pm1Y = fromY;
3907     pm2X = toX;
3908     pm2Y = toY;
3909 }
3910
3911 void
3912 ClearPremoveHighlights()
3913 {
3914   SetPremoveHighlights(-1, -1, -1, -1);
3915 }
3916
3917 static void BlankSquare(x, y, color, piece, dest)
3918      int x, y, color;
3919      ChessSquare piece;
3920      Drawable dest;
3921 {
3922     if (useImages && useImageSqs) {
3923         Pixmap pm;
3924         switch (color) {
3925           case 1: /* light */
3926             pm = xpmLightSquare;
3927             break;
3928           case 0: /* dark */
3929             pm = xpmDarkSquare;
3930             break;
3931           case 2: /* neutral */
3932           default:
3933             pm = xpmJailSquare;
3934             break;
3935         }
3936         XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3937                   squareSize, squareSize, x, y);
3938     } else {
3939         GC gc;
3940         switch (color) {
3941           case 1: /* light */
3942             gc = lightSquareGC;
3943             break;
3944           case 0: /* dark */
3945             gc = darkSquareGC;
3946             break;
3947           case 2: /* neutral */
3948           default:
3949             gc = jailSquareGC;
3950             break;
3951         }
3952         XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3953     }
3954 }
3955
3956 /*
3957    I split out the routines to draw a piece so that I could
3958    make a generic flash routine.
3959 */
3960 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3961      ChessSquare piece;
3962      int square_color, x, y;
3963      Drawable dest;
3964 {
3965     /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3966     switch (square_color) {
3967       case 1: /* light */
3968       case 2: /* neutral */
3969       default:
3970         XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3971                   ? *pieceToOutline(piece)
3972                   : *pieceToSolid(piece),
3973                   dest, bwPieceGC, 0, 0,
3974                   squareSize, squareSize, x, y);
3975         break;
3976       case 0: /* dark */
3977         XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3978                   ? *pieceToSolid(piece)
3979                   : *pieceToOutline(piece),
3980                   dest, wbPieceGC, 0, 0,
3981                   squareSize, squareSize, x, y);
3982         break;
3983     }
3984 }
3985
3986 static void monoDrawPiece(piece, square_color, x, y, dest)
3987      ChessSquare piece;
3988      int square_color, x, y;
3989      Drawable dest;
3990 {
3991     switch (square_color) {
3992       case 1: /* light */
3993       case 2: /* neutral */
3994       default:
3995         XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3996                    ? *pieceToOutline(piece)
3997                    : *pieceToSolid(piece),
3998                    dest, bwPieceGC, 0, 0,
3999                    squareSize, squareSize, x, y, 1);
4000         break;
4001       case 0: /* dark */
4002         XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4003                    ? *pieceToSolid(piece)
4004                    : *pieceToOutline(piece),
4005                    dest, wbPieceGC, 0, 0,
4006                    squareSize, squareSize, x, y, 1);
4007         break;
4008     }
4009 }
4010
4011 static void colorDrawPiece(piece, square_color, x, y, dest)
4012      ChessSquare piece;
4013      int square_color, x, y;
4014      Drawable dest;
4015 {
4016     switch (square_color) {
4017       case 1: /* light */
4018         XCopyPlane(xDisplay, *pieceToSolid(piece),
4019                    dest, (int) piece < (int) BlackPawn
4020                    ? wlPieceGC : blPieceGC, 0, 0,
4021                    squareSize, squareSize, x, y, 1);
4022         break;
4023       case 0: /* dark */
4024         XCopyPlane(xDisplay, *pieceToSolid(piece),
4025                    dest, (int) piece < (int) BlackPawn
4026                    ? wdPieceGC : bdPieceGC, 0, 0,
4027                    squareSize, squareSize, x, y, 1);
4028         break;
4029       case 2: /* neutral */
4030       default:
4031         XCopyPlane(xDisplay, *pieceToSolid(piece),
4032                    dest, (int) piece < (int) BlackPawn
4033                    ? wjPieceGC : bjPieceGC, 0, 0,
4034                    squareSize, squareSize, x, y, 1);
4035         break;
4036     }
4037 }
4038
4039 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4040      ChessSquare piece;
4041      int square_color, x, y;
4042      Drawable dest;
4043 {
4044     int kind;
4045
4046     switch (square_color) {
4047       case 1: /* light */
4048       case 2: /* neutral */
4049       default:
4050         if ((int)piece < (int) BlackPawn) {
4051             kind = 0;
4052         } else {
4053             kind = 2;
4054             piece -= BlackPawn;
4055         }
4056         break;
4057       case 0: /* dark */
4058         if ((int)piece < (int) BlackPawn) {
4059             kind = 1;
4060         } else {
4061             kind = 3;
4062             piece -= BlackPawn;
4063         }
4064         break;
4065     }
4066     XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4067               dest, wlPieceGC, 0, 0,
4068               squareSize, squareSize, x, y);            
4069 }
4070
4071 typedef void (*DrawFunc)();
4072
4073 DrawFunc ChooseDrawFunc()
4074 {
4075     if (appData.monoMode) {
4076         if (DefaultDepth(xDisplay, xScreen) == 1) {
4077             return monoDrawPiece_1bit;
4078         } else {
4079             return monoDrawPiece;
4080         }
4081     } else {
4082         if (useImages)
4083           return colorDrawPieceImage;
4084         else
4085           return colorDrawPiece;
4086     }
4087 }
4088
4089 void DrawSquare(row, column, piece, do_flash)
4090      int row, column, do_flash;
4091      ChessSquare piece;
4092 {
4093     int square_color, x, y, direction, font_ascent, font_descent;
4094     int i;
4095     char string[2];
4096     XCharStruct overall;
4097     DrawFunc drawfunc;
4098     int flash_delay;
4099
4100     /* Calculate delay in milliseconds (2-delays per complete flash) */
4101     flash_delay = 500 / appData.flashRate;
4102         
4103     if (flipView) {
4104         x = lineGap + ((BOARD_SIZE-1)-column) * 
4105           (squareSize + lineGap);
4106         y = lineGap + row * (squareSize + lineGap);
4107     } else {
4108         x = lineGap + column * (squareSize + lineGap);
4109         y = lineGap + ((BOARD_SIZE-1)-row) * 
4110           (squareSize + lineGap);
4111     }
4112     
4113     square_color = ((column + row) % 2) == 1;
4114     
4115     if (piece == EmptySquare || appData.blindfold) {
4116         BlankSquare(x, y, square_color, piece, xBoardWindow);
4117     } else {
4118         drawfunc = ChooseDrawFunc();
4119         if (do_flash && appData.flashCount > 0) {
4120             for (i=0; i<appData.flashCount; ++i) {
4121
4122                 drawfunc(piece, square_color, x, y, xBoardWindow);
4123                 XSync(xDisplay, False);
4124                 do_flash_delay(flash_delay);
4125
4126                 BlankSquare(x, y, square_color, piece, xBoardWindow);
4127                 XSync(xDisplay, False);
4128                 do_flash_delay(flash_delay);
4129             }
4130         }
4131         drawfunc(piece, square_color, x, y, xBoardWindow);
4132     }
4133         
4134     string[1] = NULLCHAR;
4135     if (appData.showCoords && row == (flipView ? 7 : 0)) {
4136         string[0] = 'a' + column;
4137         XTextExtents(coordFontStruct, string, 1, &direction, 
4138                      &font_ascent, &font_descent, &overall);
4139         if (appData.monoMode) {
4140             XDrawImageString(xDisplay, xBoardWindow, coordGC,
4141                              x + squareSize - overall.width - 2, 
4142                              y + squareSize - font_descent - 1, string, 1);
4143         } else {
4144             XDrawString(xDisplay, xBoardWindow, coordGC,
4145                         x + squareSize - overall.width - 2, 
4146                         y + squareSize - font_descent - 1, string, 1);
4147         }
4148     }
4149     if (appData.showCoords && column == (flipView ? 7 : 0)) {
4150         string[0] = '1' + row;
4151         XTextExtents(coordFontStruct, string, 1, &direction, 
4152                      &font_ascent, &font_descent, &overall);
4153         if (appData.monoMode) {
4154             XDrawImageString(xDisplay, xBoardWindow, coordGC,
4155                              x + 2, y + font_ascent + 1, string, 1);
4156         } else {
4157             XDrawString(xDisplay, xBoardWindow, coordGC,
4158                         x + 2, y + font_ascent + 1, string, 1);
4159         }           
4160     }   
4161 }
4162
4163
4164 /* Why is this needed on some versions of X? */
4165 void EventProc(widget, unused, event)
4166      Widget widget;
4167      caddr_t unused;
4168      XEvent *event;
4169 {
4170     if (!XtIsRealized(widget))
4171       return;
4172
4173     switch (event->type) {
4174    &nb