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