Added simple ICS vengine analyze for xboard
[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     /* icsEngineAnalyze - default init */
2470     appData.icsEngineAnalyze = FALSE;
2471
2472     /*
2473      * Create an icon.
2474      */
2475     ReadBitmap(&wIconPixmap, "icon_white.bm",
2476                icon_white_bits, icon_white_width, icon_white_height);
2477     ReadBitmap(&bIconPixmap, "icon_black.bm",
2478                icon_black_bits, icon_black_width, icon_black_height);
2479     iconPixmap = wIconPixmap;
2480     i = 0;
2481     XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
2482     XtSetValues(shellWidget, args, i);
2483     
2484     /*
2485      * Create a cursor for the board widget.
2486      */
2487     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2488     XChangeWindowAttributes(xDisplay, xBoardWindow,
2489                             CWCursor, &window_attributes);
2490     
2491     /*
2492      * Inhibit shell resizing.
2493      */
2494     shellArgs[0].value = (XtArgVal) &w;
2495     shellArgs[1].value = (XtArgVal) &h;
2496     XtGetValues(shellWidget, shellArgs, 2);
2497     shellArgs[4].value = shellArgs[2].value = w;
2498     shellArgs[5].value = shellArgs[3].value = h;
2499     XtSetValues(shellWidget, &shellArgs[2], 4);
2500     
2501     CatchDeleteWindow(shellWidget, "QuitProc");
2502
2503     CreateGCs();
2504     CreateGrid();
2505 #if HAVE_LIBXPM
2506     if (appData.bitmapDirectory[0] != NULLCHAR) {
2507       CreatePieces();
2508     } else {
2509       CreateXPMPieces();
2510     }
2511 #else
2512     CreateXIMPieces();
2513     /* Create regular pieces */
2514     if (!useImages) CreatePieces();
2515 #endif  
2516
2517     CreatePieceMenus();
2518
2519     if (appData.animate || appData.animateDragging)
2520       CreateAnimVars();
2521     
2522     XtAugmentTranslations(formWidget,
2523                           XtParseTranslationTable(globalTranslations));
2524     XtAugmentTranslations(boardWidget,
2525                           XtParseTranslationTable(boardTranslations));
2526     XtAugmentTranslations(whiteTimerWidget,
2527                           XtParseTranslationTable(whiteTranslations));
2528     XtAugmentTranslations(blackTimerWidget,
2529                           XtParseTranslationTable(blackTranslations));
2530
2531     /* Why is the following needed on some versions of X instead
2532      * of a translation? */
2533     XtAddEventHandler(boardWidget, ExposureMask, False,
2534                       (XtEventHandler) EventProc, NULL);
2535     /* end why */
2536
2537     InitBackEnd2();
2538     
2539     if (errorExitStatus == -1) {
2540         if (appData.icsActive) {
2541             /* We now wait until we see "login:" from the ICS before
2542                sending the logon script (problems with timestamp otherwise) */
2543             /*ICSInitScript();*/
2544             if (appData.icsInputBox) ICSInputBoxPopUp();
2545         }
2546
2547         signal(SIGINT, IntSigHandler);
2548         signal(SIGTERM, IntSigHandler);
2549         if (*appData.cmailGameName != NULLCHAR) {
2550             signal(SIGUSR1, CmailSigHandler);
2551         }
2552     }
2553
2554     XtAppMainLoop(appContext);
2555     return 0;
2556 }
2557
2558 void
2559 ShutDownFrontEnd()
2560 {
2561     if (appData.icsActive && oldICSInteractionTitle != NULL) {
2562         DisplayIcsInteractionTitle(oldICSInteractionTitle);
2563     }
2564     unlink(gameCopyFilename);
2565     unlink(gamePasteFilename);
2566 }
2567
2568 RETSIGTYPE
2569 IntSigHandler(sig)
2570      int sig;
2571 {
2572     ExitEvent(sig);
2573 }
2574
2575 RETSIGTYPE
2576 CmailSigHandler(sig)
2577      int sig;
2578 {
2579     int dummy = 0;
2580     int error;
2581
2582     signal(SIGUSR1, SIG_IGN);   /* suspend handler     */
2583
2584     /* Activate call-back function CmailSigHandlerCallBack()             */
2585     OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2586
2587     signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2588 }
2589
2590 void
2591 CmailSigHandlerCallBack(isr, closure, message, count, error)
2592      InputSourceRef isr;
2593      VOIDSTAR closure;
2594      char *message;
2595      int count;
2596      int error;
2597 {
2598     BoardToTop();
2599     ReloadCmailMsgEvent(TRUE);  /* Reload cmail msg  */
2600 }
2601 /**** end signal code ****/
2602
2603
2604 void
2605 ICSInitScript()
2606 {
2607     FILE *f;
2608     char buf[MSG_SIZ];
2609     char *p;
2610
2611     f = fopen(appData.icsLogon, "r");
2612     if (f == NULL) {
2613         p = getenv("HOME");
2614         if (p != NULL) {
2615             strcpy(buf, p);
2616             strcat(buf, "/");
2617             strcat(buf, appData.icsLogon);
2618             f = fopen(buf, "r");
2619         }
2620     }
2621     if (f != NULL)
2622       ProcessICSInitScript(f);
2623 }
2624
2625 void
2626 ResetFrontEnd()
2627 {
2628     CommentPopDown();
2629     EditCommentPopDown();
2630     TagsPopDown();
2631     return;
2632 }
2633
2634 typedef struct {
2635     char *name;
2636     Boolean value;
2637 } Enables;
2638
2639 void
2640 SetMenuEnables(enab)
2641      Enables *enab;
2642 {
2643   Widget w;
2644   if (!menuBarWidget) return;
2645   while (enab->name != NULL) {
2646     w = XtNameToWidget(menuBarWidget, enab->name);
2647     if (w == NULL) {
2648       DisplayError(enab->name, 0);
2649     } else {
2650       XtSetSensitive(w, enab->value);
2651     }
2652     enab++;
2653   }
2654 }
2655
2656 Enables icsEnables[] = {
2657     { "menuFile.Mail Move", False },
2658     { "menuFile.Reload CMail Message", False },
2659     { "menuMode.Machine Black", False },
2660     { "menuMode.Machine White", False },
2661     { "menuMode.Analysis Mode", False },
2662     { "menuMode.Analyze File", False },
2663     { "menuMode.Two Machines", False },
2664 #ifndef ZIPPY
2665     { "menuHelp.Hint", False },
2666     { "menuHelp.Book", False },
2667     { "menuStep.Move Now", False },
2668     { "menuOptions.Periodic Updates", False },  
2669     { "menuOptions.Show Thinking", False },
2670     { "menuOptions.Ponder Next Move", False },
2671 #endif
2672     { NULL, False }
2673 };
2674
2675 Enables ncpEnables[] = {    
2676     { "menuFile.Mail Move", False },
2677     { "menuFile.Reload CMail Message", False },
2678     { "menuMode.Machine White", False },
2679     { "menuMode.Machine Black", False },
2680     { "menuMode.Analysis Mode", False },
2681     { "menuMode.Analyze File", False },
2682     { "menuMode.Two Machines", False },
2683     { "menuMode.ICS Client", False },
2684     { "menuMode.ICS Input Box", False },
2685     { "Action", False },
2686     { "menuStep.Revert", False },
2687     { "menuStep.Move Now", False },
2688     { "menuStep.Retract Move", False },
2689     { "menuOptions.Auto Comment", False },
2690     { "menuOptions.Auto Flag", False },
2691     { "menuOptions.Auto Flip View", False },
2692     { "menuOptions.Auto Observe", False },
2693     { "menuOptions.Auto Raise Board", False },
2694     { "menuOptions.Get Move List", False },
2695     { "menuOptions.ICS Alarm", False },
2696     { "menuOptions.Move Sound", False },
2697     { "menuOptions.Quiet Play", False },
2698     { "menuOptions.Show Thinking", False },
2699     { "menuOptions.Periodic Updates", False },  
2700     { "menuOptions.Ponder Next Move", False },
2701     { "menuHelp.Hint", False },
2702     { "menuHelp.Book", False },
2703     { NULL, False }
2704 };
2705
2706 Enables gnuEnables[] = {    
2707     { "menuMode.ICS Client", False },
2708     { "menuMode.ICS Input Box", False },
2709     { "menuAction.Accept", False },
2710     { "menuAction.Decline", False },
2711     { "menuAction.Rematch", False },
2712     { "menuAction.Adjourn", False },
2713     { "menuAction.Stop Examining", False },
2714     { "menuAction.Stop Observing", False },
2715     { "menuStep.Revert", False },
2716     { "menuOptions.Auto Comment", False },
2717     { "menuOptions.Auto Observe", False },
2718     { "menuOptions.Auto Raise Board", False },
2719     { "menuOptions.Get Move List", False },
2720     { "menuOptions.Premove", False },
2721     { "menuOptions.Quiet Play", False },
2722
2723     /* The next two options rely on SetCmailMode being called *after*    */
2724     /* SetGNUMode so that when GNU is being used to give hints these     */
2725     /* menu options are still available                                  */
2726
2727     { "menuFile.Mail Move", False },
2728     { "menuFile.Reload CMail Message", False },
2729     { NULL, False }
2730 };
2731
2732 Enables cmailEnables[] = {    
2733     { "Action", True },
2734     { "menuAction.Call Flag", False },
2735     { "menuAction.Draw", True },
2736     { "menuAction.Adjourn", False },
2737     { "menuAction.Abort", False },
2738     { "menuAction.Stop Observing", False },
2739     { "menuAction.Stop Examining", False },
2740     { "menuFile.Mail Move", True },
2741     { "menuFile.Reload CMail Message", True },
2742     { NULL, False }
2743 };
2744
2745 Enables trainingOnEnables[] = {    
2746   { "menuMode.Edit Comment", False },
2747   { "menuMode.Pause", False },
2748   { "menuStep.Forward", False },
2749   { "menuStep.Backward", False },
2750   { "menuStep.Forward to End", False },
2751   { "menuStep.Back to Start", False },
2752   { "menuStep.Move Now", False },
2753   { "menuStep.Truncate Game", False },
2754   { NULL, False }
2755 };
2756
2757 Enables trainingOffEnables[] = {    
2758   { "menuMode.Edit Comment", True },
2759   { "menuMode.Pause", True },
2760   { "menuStep.Forward", True },
2761   { "menuStep.Backward", True },
2762   { "menuStep.Forward to End", True },
2763   { "menuStep.Back to Start", True },
2764   { "menuStep.Move Now", True },
2765   { "menuStep.Truncate Game", True },
2766   { NULL, False }
2767 };
2768
2769 Enables machineThinkingEnables[] = {
2770   { "menuFile.Load Game", False },
2771   { "menuFile.Load Next Game", False },
2772   { "menuFile.Load Previous Game", False },
2773   { "menuFile.Reload Same Game", False },
2774   { "menuFile.Paste Game", False },
2775   { "menuFile.Load Position", False },
2776   { "menuFile.Load Next Position", False },
2777   { "menuFile.Load Previous Position", False },
2778   { "menuFile.Reload Same Position", False },
2779   { "menuFile.Paste Position", False },
2780   { "menuMode.Machine White", False },
2781   { "menuMode.Machine Black", False },
2782   { "menuMode.Two Machines", False },
2783   { "menuStep.Retract Move", False },
2784   { NULL, False }
2785 };
2786
2787 Enables userThinkingEnables[] = {
2788   { "menuFile.Load Game", True },
2789   { "menuFile.Load Next Game", True },
2790   { "menuFile.Load Previous Game", True },
2791   { "menuFile.Reload Same Game", True },
2792   { "menuFile.Paste Game", True },
2793   { "menuFile.Load Position", True },
2794   { "menuFile.Load Next Position", True },
2795   { "menuFile.Load Previous Position", True },
2796   { "menuFile.Reload Same Position", True },
2797   { "menuFile.Paste Position", True },
2798   { "menuMode.Machine White", True },
2799   { "menuMode.Machine Black", True },
2800   { "menuMode.Two Machines", True },
2801   { "menuStep.Retract Move", True },
2802   { NULL, False }
2803 };
2804
2805 void SetICSMode()
2806 {
2807   SetMenuEnables(icsEnables);
2808
2809  #ifdef ZIPPY
2810   /* icsEngineAnalyze */
2811   if (appData.zippyPlay && !appData.noChessProgram) 
2812      XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2813  #endif
2814 }
2815
2816 void
2817 SetNCPMode()
2818 {
2819   SetMenuEnables(ncpEnables);
2820 }
2821
2822 void
2823 SetGNUMode()
2824 {
2825   SetMenuEnables(gnuEnables);
2826 }
2827
2828 void
2829 SetCmailMode()
2830 {
2831   SetMenuEnables(cmailEnables);
2832 }
2833
2834 void
2835 SetTrainingModeOn()
2836 {
2837   SetMenuEnables(trainingOnEnables);
2838   if (appData.showButtonBar) {
2839     XtSetSensitive(buttonBarWidget, False);
2840   }
2841   CommentPopDown();
2842 }
2843
2844 void
2845 SetTrainingModeOff()
2846 {
2847   SetMenuEnables(trainingOffEnables);
2848   if (appData.showButtonBar) {
2849     XtSetSensitive(buttonBarWidget, True);
2850   }
2851 }
2852
2853 void
2854 SetUserThinkingEnables()
2855 {
2856   if (appData.noChessProgram) return;
2857   SetMenuEnables(userThinkingEnables);
2858 }
2859
2860 void
2861 SetMachineThinkingEnables()
2862 {
2863   if (appData.noChessProgram) return;
2864   SetMenuEnables(machineThinkingEnables);
2865   switch (gameMode) {
2866   case MachinePlaysBlack:
2867   case MachinePlaysWhite:
2868   case TwoMachinesPlay:
2869     XtSetSensitive(XtNameToWidget(menuBarWidget,
2870                                   ModeToWidgetName(gameMode)), True);
2871     break;
2872   default:
2873     break;
2874   }
2875 }
2876
2877 #define Abs(n) ((n)<0 ? -(n) : (n))
2878
2879 /*
2880  * Find a font that matches "pattern" that is as close as
2881  * possible to the targetPxlSize.  Prefer fonts that are k
2882  * pixels smaller to fonts that are k pixels larger.  The
2883  * pattern must be in the X Consortium standard format, 
2884  * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2885  * The return value should be freed with XtFree when no
2886  * longer needed.
2887  */
2888 char *FindFont(pattern, targetPxlSize)
2889      char *pattern;
2890      int targetPxlSize;
2891 {
2892     char **fonts, *p, *best, *scalable, *scalableTail;
2893     int i, j, nfonts, minerr, err, pxlSize;
2894
2895 #ifdef ENABLE_NLS
2896     char **missing_list;
2897     int missing_count;
2898     char *def_string, *base_fnt_lst, strInt[3];
2899     XFontSet fntSet;
2900     XFontStruct **fnt_list;
2901
2902     base_fnt_lst = calloc(1, strlen(pattern) + 3);
2903     sprintf(strInt, "%d", targetPxlSize);
2904     p = strstr(pattern, "--");
2905     strncpy(base_fnt_lst, pattern, p - pattern + 2);
2906     strcat(base_fnt_lst, strInt);
2907     strcat(base_fnt_lst, strchr(p + 2, '-'));
2908
2909     if ((fntSet = XCreateFontSet(xDisplay, 
2910                                  base_fnt_lst, 
2911                                  &missing_list, 
2912                                  &missing_count, 
2913                                  &def_string)) == NULL) {
2914
2915         fprintf(stderr, _("Unable to create font set.\n"));
2916         exit (2);
2917     }
2918
2919     nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2920 #else
2921     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2922     if (nfonts < 1) {
2923         fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2924                 programName, pattern);
2925         exit(2);
2926     }
2927 #endif
2928
2929     best = fonts[0];
2930     scalable = NULL;
2931     minerr = 999999;
2932     for (i=0; i<nfonts; i++) {
2933         j = 0;
2934         p = fonts[i];
2935         if (*p != '-') continue;
2936         while (j < 7) {
2937             if (*p == NULLCHAR) break;
2938             if (*p++ == '-') j++;
2939         }
2940         if (j < 7) continue;
2941         pxlSize = atoi(p);
2942         if (pxlSize == 0) {
2943             scalable = fonts[i];
2944             scalableTail = p;
2945         } else {
2946             err = pxlSize - targetPxlSize;
2947             if (Abs(err) < Abs(minerr) ||
2948                 (minerr > 0 && err < 0 && -err == minerr)) {
2949                 best = fonts[i];
2950                 minerr = err;
2951             }
2952         }
2953     }
2954     if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2955         /* If the error is too big and there is a scalable font,
2956            use the scalable font. */
2957         int headlen = scalableTail - scalable;
2958         p = (char *) XtMalloc(strlen(scalable) + 10);
2959         while (isdigit(*scalableTail)) scalableTail++;
2960         sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2961     } else {
2962         p = (char *) XtMalloc(strlen(best) + 1);
2963         strcpy(p, best);
2964     }
2965     if (appData.debugMode) {
2966         fprintf(debugFP, _("resolved %s at pixel size %d\n  to %s\n"),
2967                 pattern, targetPxlSize, p);
2968     }
2969 #ifdef ENABLE_NLS
2970     if (missing_count > 0)
2971         XFreeStringList(missing_list);
2972     XFreeFontSet(xDisplay, fntSet);
2973 #else
2974     XFreeFontNames(fonts);
2975 #endif
2976     return p;
2977 }
2978
2979 void CreateGCs()
2980 {
2981     XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2982       | GCBackground | GCFunction | GCPlaneMask;
2983     XGCValues gc_values;
2984     GC copyInvertedGC;
2985     
2986     gc_values.plane_mask = AllPlanes;
2987     gc_values.line_width = lineGap;
2988     gc_values.line_style = LineSolid;
2989     gc_values.function = GXcopy;
2990     
2991     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2992     gc_values.background = XBlackPixel(xDisplay, xScreen);
2993     lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2994     
2995     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2996     gc_values.background = XWhitePixel(xDisplay, xScreen);
2997     coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2998     XSetFont(xDisplay, coordGC, coordFontID);
2999     
3000     if (appData.monoMode) {
3001         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3002         gc_values.background = XWhitePixel(xDisplay, xScreen);
3003         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);      
3004
3005         gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3006         gc_values.background = XBlackPixel(xDisplay, xScreen);
3007         lightSquareGC = wbPieceGC 
3008           = XtGetGC(shellWidget, value_mask, &gc_values);
3009
3010         gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3011         gc_values.background = XWhitePixel(xDisplay, xScreen);
3012         darkSquareGC = bwPieceGC
3013           = XtGetGC(shellWidget, value_mask, &gc_values);
3014
3015         if (DefaultDepth(xDisplay, xScreen) == 1) {
3016             /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3017             gc_values.function = GXcopyInverted;
3018             copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3019             gc_values.function = GXcopy;
3020             if (XBlackPixel(xDisplay, xScreen) == 1) {
3021                 bwPieceGC = darkSquareGC;
3022                 wbPieceGC = copyInvertedGC;
3023             } else {
3024                 bwPieceGC = copyInvertedGC;
3025                 wbPieceGC = lightSquareGC;
3026             }
3027         }
3028     } else {
3029         gc_values.foreground = highlightSquareColor;
3030         gc_values.background = highlightSquareColor;
3031         highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);      
3032
3033         gc_values.foreground = premoveHighlightColor;
3034         gc_values.background = premoveHighlightColor;
3035         prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);       
3036
3037         gc_values.foreground = lightSquareColor;
3038         gc_values.background = darkSquareColor;
3039         lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3040         
3041         gc_values.foreground = darkSquareColor;
3042         gc_values.background = lightSquareColor;
3043         darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3044
3045         gc_values.foreground = jailSquareColor;
3046         gc_values.background = jailSquareColor;
3047         jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3048
3049         gc_values.foreground = whitePieceColor;
3050         gc_values.background = darkSquareColor;
3051         wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3052         
3053         gc_values.foreground = whitePieceColor;
3054         gc_values.background = lightSquareColor;
3055         wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3056         
3057         gc_values.foreground = whitePieceColor;
3058         gc_values.background = jailSquareColor;
3059         wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060         
3061         gc_values.foreground = blackPieceColor;
3062         gc_values.background = darkSquareColor;
3063         bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3064         
3065         gc_values.foreground = blackPieceColor;
3066         gc_values.background = lightSquareColor;
3067         blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3068
3069         gc_values.foreground = blackPieceColor;
3070         gc_values.background = jailSquareColor;
3071         bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3072     }
3073 }
3074
3075 void loadXIM(xim, xmask, filename, dest, mask)
3076      XImage *xim;
3077      XImage *xmask;
3078      char *filename;
3079      Pixmap *dest;
3080      Pixmap *mask;
3081 {
3082     int x, y, w, h, p;
3083     FILE *fp;
3084     Pixmap temp;
3085     XGCValues   values;
3086     GC maskGC;
3087
3088     fp = fopen(filename, "rb");
3089     if (!fp) {
3090         fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3091         exit(1);
3092     }
3093           
3094     w = fgetc(fp);
3095     h = fgetc(fp);
3096   
3097     for (y=0; y<h; ++y) {
3098         for (x=0; x<h; ++x) {
3099             p = fgetc(fp);
3100
3101             switch (p) {
3102               case 0:   
3103                 XPutPixel(xim, x, y, blackPieceColor); 
3104                 if (xmask)
3105                   XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3106                 break;
3107               case 1:   
3108                 XPutPixel(xim, x, y, darkSquareColor); 
3109                 if (xmask)
3110                   XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3111                 break;
3112               case 2:   
3113                 XPutPixel(xim, x, y, whitePieceColor); 
3114                 if (xmask)
3115                   XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3116                 break;
3117               case 3:   
3118                 XPutPixel(xim, x, y, lightSquareColor);
3119                 if (xmask)
3120                   XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3121                 break;
3122             }
3123         }
3124     }
3125
3126     /* create Pixmap of piece */
3127     *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3128                           w, h, xim->depth);
3129     XPutImage(xDisplay, *dest, lightSquareGC, xim,
3130               0, 0, 0, 0, w, h);  
3131
3132     /* create Pixmap of clipmask 
3133        Note: We assume the white/black pieces have the same
3134              outline, so we make only 6 masks. This is okay
3135              since the XPM clipmask routines do the same. */
3136     if (xmask) {
3137       temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3138                             w, h, xim->depth);
3139       XPutImage(xDisplay, temp, lightSquareGC, xmask,
3140               0, 0, 0, 0, w, h);  
3141
3142       /* now create the 1-bit version */
3143       *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3144                           w, h, 1);
3145
3146       values.foreground = 1;
3147       values.background = 0;
3148
3149       /* Don't use XtGetGC, not read only */
3150       maskGC = XCreateGC(xDisplay, *mask, 
3151                     GCForeground | GCBackground, &values);
3152       XCopyPlane(xDisplay, temp, *mask, maskGC, 
3153                   0, 0, squareSize, squareSize, 0, 0, 1);
3154       XFreePixmap(xDisplay, temp);
3155     }
3156 }
3157
3158 void CreateXIMPieces()
3159 {
3160     int piece, kind;
3161     char buf[MSG_SIZ];
3162     u_int ss;
3163     static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3164     XImage *ximtemp;
3165
3166     ss = squareSize;
3167
3168     /* The XSynchronize calls were copied from CreatePieces.
3169        Not sure if needed, but can't hurt */
3170     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3171                                      buffering bug */
3172   
3173     /* temp needed by loadXIM() */
3174     ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3175                  0, 0, ss, ss, AllPlanes, XYPixmap);
3176
3177     if (strlen(appData.pixmapDirectory) == 0) {
3178       useImages = 0;
3179     } else {
3180         useImages = 1;
3181         if (appData.monoMode) {
3182           DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3183                             0, 2);
3184           ExitEvent(2);
3185         }
3186         fprintf(stderr, _("\nLoading XIMs...\n"));
3187         /* Load pieces */
3188         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3189             fprintf(stderr, "%d", piece+1);
3190             for (kind=0; kind<4; kind++) {
3191                 fprintf(stderr, ".");
3192                 sprintf(buf, "%s/%c%s%u.xim",
3193                         ExpandPathName(appData.pixmapDirectory),
3194                         ToLower(PieceToChar((ChessSquare)piece)),
3195                         ximkind[kind], ss);
3196                 ximPieceBitmap[kind][piece] =
3197                   XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3198                             0, 0, ss, ss, AllPlanes, XYPixmap);
3199                 if (appData.debugMode)
3200                   fprintf(stderr, _("(File:%s:) "), buf);
3201                 loadXIM(ximPieceBitmap[kind][piece], 
3202                         ximtemp, buf,
3203                         &(xpmPieceBitmap[kind][piece]),
3204                         &(ximMaskPm[piece%6]));
3205             }
3206             fprintf(stderr," ");
3207         }
3208         /* Load light and dark squares */
3209         /* If the LSQ and DSQ pieces don't exist, we will 
3210            draw them with solid squares. */
3211         sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3212         if (access(buf, 0) != 0) {
3213             useImageSqs = 0;
3214         } else {
3215             useImageSqs = 1;
3216             fprintf(stderr, _("light square "));
3217             ximLightSquare= 
3218               XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3219                         0, 0, ss, ss, AllPlanes, XYPixmap);
3220             if (appData.debugMode)
3221               fprintf(stderr, _("(File:%s:) "), buf);
3222
3223             loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3224             fprintf(stderr, _("dark square "));
3225             sprintf(buf, "%s/dsq%u.xim",
3226                     ExpandPathName(appData.pixmapDirectory), ss);
3227             if (appData.debugMode)
3228               fprintf(stderr, _("(File:%s:) "), buf);
3229             ximDarkSquare= 
3230               XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3231                         0, 0, ss, ss, AllPlanes, XYPixmap);
3232             loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3233             xpmJailSquare = xpmLightSquare;
3234         }
3235         fprintf(stderr, _("Done.\n"));
3236     }
3237     XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3238 }
3239
3240 #if HAVE_LIBXPM
3241 void CreateXPMPieces()
3242 {
3243     int piece, kind, r;
3244     char buf[MSG_SIZ];
3245     u_int ss = squareSize;
3246     XpmAttributes attr;
3247     static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3248     XpmColorSymbol symbols[4];
3249
3250 #if 0
3251     /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3252     if (appData.debugMode) {
3253         fprintf(stderr, "XPM Library Version: %d.%d%c\n", 
3254                 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3255     }
3256 #endif
3257   
3258     /* The XSynchronize calls were copied from CreatePieces.
3259        Not sure if needed, but can't hurt */
3260     XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3261   
3262     /* Setup translations so piece colors match square colors */
3263     symbols[0].name = "light_piece";
3264     symbols[0].value = appData.whitePieceColor;
3265     symbols[1].name = "dark_piece";
3266     symbols[1].value = appData.blackPieceColor;
3267     symbols[2].name = "light_square";
3268     symbols[2].value = appData.lightSquareColor;
3269     symbols[3].name = "dark_square";
3270     symbols[3].value = appData.darkSquareColor;
3271
3272     attr.valuemask = XpmColorSymbols;
3273     attr.colorsymbols = symbols;
3274     attr.numsymbols = 4;
3275
3276     if (appData.monoMode) {
3277       DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3278                         0, 2);
3279       ExitEvent(2);
3280     }
3281     if (strlen(appData.pixmapDirectory) == 0) {
3282         XpmPieces* pieces = builtInXpms;
3283         useImages = 1;
3284         /* Load pieces */
3285         while (pieces->size != squareSize && pieces->size) pieces++;
3286         if (!pieces->size) {
3287           fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3288           exit(1);
3289         }
3290         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3291             for (kind=0; kind<4; kind++) {
3292
3293                 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3294                                                pieces->xpm[piece][kind],
3295                                                &(xpmPieceBitmap[kind][piece]),
3296                                                NULL, &attr)) != 0) {
3297                   fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3298                           r, buf);
3299                   exit(1); 
3300                 }       
3301             }   
3302         }
3303         useImageSqs = 0;
3304         xpmJailSquare = xpmLightSquare;
3305     } else {
3306         useImages = 1;
3307         
3308         fprintf(stderr, _("\nLoading XPMs...\n"));
3309
3310         /* Load pieces */
3311         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3312             fprintf(stderr, "%d ", piece+1);
3313             for (kind=0; kind<4; kind++) {
3314                 sprintf(buf, "%s/%c%s%u.xpm",
3315                         ExpandPathName(appData.pixmapDirectory),
3316                         ToLower(PieceToChar((ChessSquare)piece)),
3317                         xpmkind[kind], ss);
3318                 if (appData.debugMode) {
3319                     fprintf(stderr, _("(File:%s:) "), buf);
3320                 }
3321                 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3322                                            &(xpmPieceBitmap[kind][piece]),
3323                                            NULL, &attr)) != 0) {
3324                     fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3325                             r, buf);
3326                     exit(1); 
3327                 }       
3328             }   
3329         }
3330         /* Load light and dark squares */
3331         /* If the LSQ and DSQ pieces don't exist, we will 
3332            draw them with solid squares. */
3333         fprintf(stderr, _("light square "));
3334         sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3335         if (access(buf, 0) != 0) {
3336             useImageSqs = 0;
3337         } else {
3338             useImageSqs = 1;
3339             if (appData.debugMode)
3340               fprintf(stderr, _("(File:%s:) "), buf);
3341
3342             if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3343                                        &xpmLightSquare, NULL, &attr)) != 0) {
3344                 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3345                 exit(1);
3346             }
3347             fprintf(stderr, _("dark square "));
3348             sprintf(buf, "%s/dsq%u.xpm",
3349                     ExpandPathName(appData.pixmapDirectory), ss);
3350             if (appData.debugMode) {
3351                 fprintf(stderr, _("(File:%s:) "), buf);
3352             }
3353             if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3354                                        &xpmDarkSquare, NULL, &attr)) != 0) {
3355                 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3356                 exit(1);
3357             }
3358         }
3359         xpmJailSquare = xpmLightSquare;
3360         fprintf(stderr, _("Done.\n"));
3361     }
3362     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3363                                       buffering bug */  
3364 }
3365 #endif /* HAVE_LIBXPM */
3366
3367 #if HAVE_LIBXPM
3368 /* No built-in bitmaps */
3369 void CreatePieces()
3370 {
3371     int piece, kind;
3372     char buf[MSG_SIZ];
3373     u_int ss = squareSize;
3374         
3375     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3376                                      buffering bug */
3377
3378     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3379         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3380             sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3381                     ss, kind == SOLID ? 's' : 'o');
3382             ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3383         }
3384     }
3385     
3386     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3387                                       buffering bug */
3388 }
3389 #else
3390 /* With built-in bitmaps */
3391 void CreatePieces()
3392 {
3393     BuiltInBits* bib = builtInBits;
3394     int piece, kind;
3395     char buf[MSG_SIZ];
3396     u_int ss = squareSize;
3397         
3398     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3399                                      buffering bug */
3400
3401     while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3402
3403     for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3404         for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3405             sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3406                     ss, kind == SOLID ? 's' : 'o');
3407             ReadBitmap(&pieceBitmap[kind][piece], buf,
3408                        bib->bits[kind][piece], ss, ss);
3409         }
3410     }
3411     
3412     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3413                                       buffering bug */
3414 }
3415 #endif
3416
3417 void ReadBitmap(pm, name, bits, wreq, hreq)
3418      Pixmap *pm;
3419      String name;
3420      unsigned char bits[];
3421      u_int wreq, hreq;
3422 {
3423     int x_hot, y_hot;
3424     u_int w, h;
3425     int errcode;
3426     char msg[MSG_SIZ], fullname[MSG_SIZ];
3427     
3428     if (*appData.bitmapDirectory != NULLCHAR) {
3429         strcpy(fullname, appData.bitmapDirectory);
3430         strcat(fullname, "/");
3431         strcat(fullname, name);
3432         errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3433                                   &w, &h, pm, &x_hot, &y_hot);
3434         if (errcode != BitmapSuccess) {
3435             switch (errcode) {
3436               case BitmapOpenFailed:
3437                 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3438                 break;
3439               case BitmapFileInvalid:
3440                 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3441                 break;
3442               case BitmapNoMemory:
3443                 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3444                         fullname);
3445                 break;
3446               default:
3447                 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3448                         errcode, fullname);
3449                 break;
3450             }
3451             fprintf(stderr, _("%s: %s...using built-in\n"),
3452                     programName, msg);
3453         } else if (w != wreq || h != hreq) {
3454             fprintf(stderr,
3455                     _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3456                     programName, fullname, w, h, wreq, hreq);
3457         } else {
3458             return;
3459         }
3460     }
3461     if (bits == NULL) {
3462         fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3463                 programName, name);
3464         exit(1);
3465     } else {
3466         *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3467                                     wreq, hreq);
3468     }
3469 }
3470
3471 void CreateGrid()
3472 {
3473     int i;
3474     
3475     if (lineGap == 0) return;
3476     for (i = 0; i < BOARD_SIZE + 1; i++) {
3477         gridSegments[i].x1 = 0;
3478         gridSegments[i].x2 =
3479           lineGap + BOARD_SIZE * (squareSize + lineGap);
3480         gridSegments[i].y1 = gridSegments[i].y2
3481           = lineGap / 2 + (i * (squareSize + lineGap));
3482
3483         gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3484         gridSegments[i + BOARD_SIZE + 1].y2 =
3485           BOARD_SIZE * (squareSize + lineGap);
3486         gridSegments[i + BOARD_SIZE + 1].x1 =
3487           gridSegments[i + BOARD_SIZE + 1].x2
3488             = lineGap / 2 + (i * (squareSize + lineGap));
3489     }
3490 }
3491
3492 static void MenuBarSelect(w, addr, index)
3493      Widget w;
3494      caddr_t addr;
3495      caddr_t index;
3496 {
3497     XtActionProc proc = (XtActionProc) addr;
3498
3499     (proc)(NULL, NULL, NULL, NULL);
3500 }
3501
3502 void CreateMenuBarPopup(parent, name, mb)
3503      Widget parent;
3504      String name;
3505      Menu *mb;
3506 {
3507     int j;
3508     Widget menu, entry;
3509     MenuItem *mi;
3510     Arg args[16];
3511
3512     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3513                               parent, NULL, 0);
3514     j = 0;
3515     XtSetArg(args[j], XtNleftMargin, 20);   j++;
3516     XtSetArg(args[j], XtNrightMargin, 20);  j++;
3517     mi = mb->mi;
3518     while (mi->string != NULL) {
3519         if (strcmp(mi->string, "----") == 0) {
3520             entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3521                                           menu, args, j);
3522         } else {
3523             XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3524             entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3525                                           menu, args, j+1);
3526             XtAddCallback(entry, XtNcallback,
3527                           (XtCallbackProc) MenuBarSelect,
3528                           (caddr_t) mi->proc);
3529         }
3530         mi++;
3531     }
3532 }       
3533
3534 Widget CreateMenuBar(mb)
3535      Menu *mb;
3536 {
3537     int j;
3538     Widget anchor, menuBar;
3539     Arg args[16];
3540     char menuName[MSG_SIZ];
3541
3542     j = 0;
3543     XtSetArg(args[j], XtNorientation, XtorientHorizontal);  j++;
3544     XtSetArg(args[j], XtNvSpace, 0);                        j++;
3545     XtSetArg(args[j], XtNborderWidth, 0);                   j++;
3546     menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3547                              formWidget, args, j);
3548
3549     while (mb->name != NULL) {
3550         strcpy(menuName, "menu");
3551         strcat(menuName, mb->name);
3552         j = 0;
3553         XtSetArg(args[j], XtNmenuName, XtNewString(menuName));  j++;
3554         if (tinyLayout) {
3555             char shortName[2];
3556             shortName[0] = _(mb->name)[0];
3557             shortName[1] = NULLCHAR;
3558             XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3559         }
3560         else {
3561             XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3562         }
3563
3564         XtSetArg(args[j], XtNborderWidth, 0);                   j++;
3565         anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3566                                        menuBar, args, j);
3567         CreateMenuBarPopup(menuBar, menuName, mb);
3568         mb++;
3569     }
3570     return menuBar;
3571 }
3572
3573 Widget CreateButtonBar(mi)
3574      MenuItem *mi;
3575 {
3576     int j;
3577     Widget button, buttonBar;
3578     Arg args[16];
3579
3580     j = 0;
3581     XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3582     if (tinyLayout) {
3583         XtSetArg(args[j], XtNhSpace, 0); j++;
3584     }
3585     XtSetArg(args[j], XtNborderWidth, 0); j++;
3586     XtSetArg(args[j], XtNvSpace, 0);                        j++;
3587     buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3588                                formWidget, args, j);
3589
3590     while (mi->string != NULL) {
3591         j = 0;
3592         if (tinyLayout) {
3593             XtSetArg(args[j], XtNinternalWidth, 2); j++;
3594             XtSetArg(args[j], XtNborderWidth, 0); j++;
3595         }
3596         XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3597         button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3598                                        buttonBar, args, j);
3599         XtAddCallback(button, XtNcallback,
3600                       (XtCallbackProc) MenuBarSelect,
3601                       (caddr_t) mi->proc);
3602         mi++;
3603     }
3604     return buttonBar;
3605 }     
3606
3607 Widget
3608 CreatePieceMenu(name, color)
3609      char *name;
3610      int color;
3611 {
3612     int i;
3613     Widget entry, menu;
3614     Arg args[16];
3615     ChessSquare selection;
3616
3617     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3618                               boardWidget, args, 0);
3619     
3620     for (i = 0; i < PIECE_MENU_SIZE; i++) {
3621         String item = pieceMenuStrings[color][i];
3622         
3623         if (strcmp(item, "----") == 0) {
3624             entry = XtCreateManagedWidget(item, smeLineObjectClass,
3625                                           menu, NULL, 0);
3626         } else {
3627             XtSetArg(args[0], XtNlabel, XtNewString(_(item))); 
3628             entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3629                                           menu, args, 1);
3630             selection = pieceMenuTranslation[color][i];
3631             XtAddCallback(entry, XtNcallback,
3632                           (XtCallbackProc) PieceMenuSelect,
3633                           (caddr_t) selection);
3634             if (selection == WhitePawn || selection == BlackPawn) {
3635                 XtSetArg(args[0], XtNpopupOnEntry, entry);
3636                 XtSetValues(menu, args, 1);
3637             }
3638         }
3639     }
3640     return menu;
3641 }
3642
3643 void
3644 CreatePieceMenus()
3645 {
3646     int i;
3647     Widget entry;
3648     Arg args[16];
3649     ChessSquare selection;
3650
3651     whitePieceMenu = CreatePieceMenu("menuW", 0);
3652     blackPieceMenu = CreatePieceMenu("menuB", 1);
3653     
3654     XtRegisterGrabAction(PieceMenuPopup, True,
3655                          (unsigned)(ButtonPressMask|ButtonReleaseMask),
3656                          GrabModeAsync, GrabModeAsync);
3657
3658     XtSetArg(args[0], XtNlabel, _("Drop"));
3659     dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3660                                   boardWidget, args, 1);
3661     for (i = 0; i < DROP_MENU_SIZE; i++) {
3662         String item = dropMenuStrings[i];
3663         
3664         if (strcmp(item, "----") == 0) {
3665             entry = XtCreateManagedWidget(item, smeLineObjectClass,
3666                                           dropMenu, NULL, 0);
3667         } else {
3668             XtSetArg(args[0], XtNlabel, XtNewString(_(item))); 
3669             entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3670                                           dropMenu, args, 1);
3671             selection = dropMenuTranslation[i];
3672             XtAddCallback(entry, XtNcallback,
3673                           (XtCallbackProc) DropMenuSelect,
3674                           (caddr_t) selection);
3675         }
3676     }
3677 }       
3678
3679 void SetupDropMenu()
3680 {
3681     int i, j, count;
3682     char label[32];
3683     Arg args[16];
3684     Widget entry;
3685     char* p;
3686
3687     for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3688         entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3689         p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3690                    dmEnables[i].piece);
3691         XtSetSensitive(entry, p != NULL || !appData.testLegality
3692                        /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3693                                        && !appData.icsActive));
3694         count = 0;
3695         while (p && *p++ == dmEnables[i].piece) count++;
3696         sprintf(label, "%s  %d", dmEnables[i].widget, count);
3697         j = 0;
3698         XtSetArg(args[j], XtNlabel, label); j++;
3699         XtSetValues(entry, args, j);
3700     }
3701 }
3702
3703 void PieceMenuPopup(w, event, params, num_params)
3704      Widget w;
3705      XEvent *event;
3706      String *params;
3707      Cardinal *num_params;
3708 {
3709     String whichMenu;
3710     if (event->type != ButtonPress) return;
3711     if (errorUp) ErrorPopDown();
3712     switch (gameMode) {
3713       case EditPosition:
3714       case IcsExamining:
3715         whichMenu = params[0];
3716         break;
3717       case IcsPlayingWhite:
3718       case IcsPlayingBlack:
3719       case EditGame:
3720       case MachinePlaysWhite:
3721       case MachinePlaysBlack:
3722         if (appData.testLegality &&
3723             gameInfo.variant != VariantBughouse &&
3724             gameInfo.variant != VariantCrazyhouse) return;
3725         SetupDropMenu();
3726         whichMenu = "menuD";
3727         break;
3728       default:
3729         return;
3730     }
3731     
3732     if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3733         ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3734         pmFromX = pmFromY = -1;
3735         return;
3736     }
3737     if (flipView)
3738       pmFromX = BOARD_SIZE - 1 - pmFromX;
3739     else
3740       pmFromY = BOARD_SIZE - 1 - pmFromY;
3741     
3742     XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3743 }
3744
3745 static void PieceMenuSelect(w, piece, junk)
3746      Widget w;
3747      ChessSquare piece;
3748      caddr_t junk;
3749 {
3750     if (pmFromX < 0 || pmFromY < 0) return;
3751     EditPositionMenuEvent(piece, pmFromX, pmFromY);
3752 }
3753
3754 static void DropMenuSelect(w, piece, junk)
3755      Widget w;
3756      ChessSquare piece;
3757      caddr_t junk;
3758 {
3759     if (pmFromX < 0 || pmFromY < 0) return;
3760     DropMenuEvent(piece, pmFromX, pmFromY);
3761 }
3762
3763 void WhiteClock(w, event, prms, nprms)
3764      Widget w;
3765      XEvent *event;
3766      String *prms;
3767      Cardinal *nprms;
3768 {
3769     if (gameMode == EditPosition || gameMode == IcsExamining) {
3770         SetWhiteToPlayEvent();
3771     } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3772         CallFlagEvent();
3773     }
3774 }
3775
3776 void BlackClock(w, event, prms, nprms)
3777      Widget w;
3778      XEvent *event;
3779      String *prms;
3780      Cardinal *nprms;
3781 {
3782     if (gameMode == EditPosition || gameMode == IcsExamining) {
3783         SetBlackToPlayEvent();
3784     } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3785         CallFlagEvent();
3786     }
3787 }
3788
3789
3790 /*
3791  * If the user selects on a border boundary, return -1; if off the board,
3792  *   return -2.  Otherwise map the event coordinate to the square.
3793  */
3794 int EventToSquare(x, limit)
3795      int x;
3796 {
3797     if (x <= 0) 
3798       return -2;
3799     if (x < lineGap)
3800       return -1;
3801     x -= lineGap;
3802     if ((x % (squareSize + lineGap)) >= squareSize)
3803       return -1;
3804     x /= (squareSize + lineGap);
3805     if (x >= limit)
3806       return -2;
3807     return x;
3808 }
3809
3810 static void do_flash_delay(msec)
3811      unsigned long msec;
3812 {
3813     TimeDelay(msec);
3814 }
3815
3816 static void drawHighlight(file, rank, gc)
3817      int file, rank;
3818      GC gc;
3819 {
3820     int x, y;
3821
3822     if (lineGap == 0 || appData.blindfold) return;
3823     
3824     if (flipView) {
3825         x = lineGap/2 + ((BOARD_SIZE-1)-file) * 
3826           (squareSize + lineGap);
3827         y = lineGap/2 + rank * (squareSize + lineGap);
3828     } else {
3829         x = lineGap/2 + file * (squareSize + lineGap);
3830         y = lineGap/2 + ((BOARD_SIZE-1)-rank) * 
3831           (squareSize + lineGap);
3832     }
3833     
3834     XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3835                    squareSize+lineGap, squareSize+lineGap);
3836 }
3837
3838 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3839 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3840
3841 void
3842 SetHighlights(fromX, fromY, toX, toY)
3843      int fromX, fromY, toX, toY;
3844 {
3845     if (hi1X != fromX || hi1Y != fromY) {
3846         if (hi1X >= 0 && hi1Y >= 0) {
3847             drawHighlight(hi1X, hi1Y, lineGC);
3848         }
3849         if (fromX >= 0 && fromY >= 0) {
3850             drawHighlight(fromX, fromY, highlineGC);
3851         }
3852     }
3853     if (hi2X != toX || hi2Y != toY) {
3854         if (hi2X >= 0 && hi2Y >= 0) {
3855             drawHighlight(hi2X, hi2Y, lineGC);
3856         }
3857         if (toX >= 0 && toY >= 0) {
3858             drawHighlight(toX, toY, highlineGC);
3859         }
3860     }
3861     hi1X = fromX;
3862     hi1Y = fromY;
3863     hi2X = toX;
3864     hi2Y = toY;
3865 }
3866
3867 void
3868 ClearHighlights()
3869 {
3870     SetHighlights(-1, -1, -1, -1);
3871 }
3872
3873
3874 void
3875 SetPremoveHighlights(fromX, fromY, toX, toY)
3876      int fromX, fromY, toX, toY;
3877 {
3878     if (pm1X != fromX || pm1Y != fromY) {
3879         if (pm1X >= 0 && pm1Y >= 0) {
3880             drawHighlight(pm1X, pm1Y, lineGC);
3881         }
3882         if (fromX >= 0 && fromY >= 0) {
3883             drawHighlight(fromX, fromY, prelineGC);
3884         }
3885     }
3886     if (pm2X != toX || pm2Y != toY) {
3887         if (pm2X >= 0 && pm2Y >= 0) {
3888             drawHighlight(pm2X, pm2Y, lineGC);
3889         }
3890         if (toX >= 0 && toY >= 0) {
3891             drawHighlight(toX, toY, prelineGC);
3892         }
3893     }
3894     pm1X = fromX;
3895     pm1Y = fromY;
3896     pm2X = toX;
3897     pm2Y = toY;
3898 }
3899
3900 void
3901 ClearPremoveHighlights()
3902 {
3903   SetPremoveHighlights(-1, -1, -1, -1);
3904 }
3905
3906 static void BlankSquare(x, y, color, piece, dest)
3907      int x, y, color;
3908      ChessSquare piece;
3909      Drawable dest;
3910 {
3911     if (useImages && useImageSqs) {
3912         Pixmap pm;
3913         switch (color) {
3914           case 1: /* light */
3915             pm = xpmLightSquare;
3916             break;
3917           case 0: /* dark */
3918             pm = xpmDarkSquare;
3919             break;
3920           case 2: /* neutral */
3921           default:
3922             pm = xpmJailSquare;
3923             break;
3924         }
3925         XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3926                   squareSize, squareSize, x, y);
3927     } else {
3928         GC gc;
3929         switch (color) {
3930           case 1: /* light */
3931             gc = lightSquareGC;
3932             break;
3933           case 0: /* dark */
3934             gc = darkSquareGC;
3935             break;
3936           case 2: /* neutral */
3937           default:
3938             gc = jailSquareGC;
3939             break;
3940         }
3941         XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3942     }
3943 }
3944
3945 /*
3946    I split out the routines to draw a piece so that I could
3947    make a generic flash routine.
3948 */
3949 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3950      ChessSquare piece;
3951      int square_color, x, y;
3952      Drawable dest;
3953 {
3954     /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3955     switch (square_color) {
3956       case 1: /* light */
3957       case 2: /* neutral */
3958       default:
3959         XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3960                   ? *pieceToOutline(piece)
3961                   : *pieceToSolid(piece),
3962                   dest, bwPieceGC, 0, 0,
3963                   squareSize, squareSize, x, y);
3964         break;
3965       case 0: /* dark */
3966         XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3967                   ? *pieceToSolid(piece)
3968                   : *pieceToOutline(piece),
3969                   dest, wbPieceGC, 0, 0,
3970                   squareSize, squareSize, x, y);
3971         break;
3972     }
3973 }
3974
3975 static void monoDrawPiece(piece, square_color, x, y, dest)
3976      ChessSquare piece;
3977      int square_color, x, y;
3978      Drawable dest;
3979 {
3980     switch (square_color) {
3981       case 1: /* light */
3982       case 2: /* neutral */
3983       default:
3984         XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3985                    ? *pieceToOutline(piece)
3986                    : *pieceToSolid(piece),
3987                    dest, bwPieceGC, 0, 0,
3988                    squareSize, squareSize, x, y, 1);
3989         break;
3990       case 0: /* dark */
3991         XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3992                    ? *pieceToSolid(piece)
3993                    : *pieceToOutline(piece),
3994                    dest, wbPieceGC, 0, 0,
3995                    squareSize, squareSize, x, y, 1);
3996         break;
3997     }
3998 }
3999
4000 static void colorDrawPiece(piece, square_color, x, y, dest)
4001      ChessSquare piece;
4002      int square_color, x, y;
4003      Drawable dest;
4004 {
4005     switch (square_color) {
4006       case 1: /* light */
4007         XCopyPlane(xDisplay, *pieceToSolid(piece),
4008                    dest, (int) piece < (int) BlackPawn
4009                    ? wlPieceGC : blPieceGC, 0, 0,
4010                    squareSize, squareSize, x, y, 1);
4011         break;
4012       case 0: /* dark */
4013         XCopyPlane(xDisplay, *pieceToSolid(piece),
4014                    dest, (int) piece < (int) BlackPawn
4015                    ? wdPieceGC : bdPieceGC, 0, 0,
4016                    squareSize, squareSize, x, y, 1);
4017         break;
4018       case 2: /* neutral */
4019       default:
4020         XCopyPlane(xDisplay, *pieceToSolid(piece),
4021                    dest, (int) piece < (int) BlackPawn
4022                    ? wjPieceGC : bjPieceGC, 0, 0,
4023                    squareSize, squareSize, x, y, 1);
4024         break;
4025     }
4026 }
4027
4028 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4029      ChessSquare piece;
4030      int square_color, x, y;
4031      Drawable dest;
4032 {
4033     int kind;
4034
4035     switch (square_color) {
4036       case 1: /* light */
4037       case 2: /* neutral */
4038       default:
4039         if ((int)piece < (int) BlackPawn) {
4040             kind = 0;
4041         } else {
4042             kind = 2;
4043             piece -= BlackPawn;
4044         }
4045         break;
4046       case 0: /* dark */
4047         if ((int)piece < (int) BlackPawn) {
4048             kind = 1;
4049         } else {
4050             kind = 3;
4051             piece -= BlackPawn;
4052         }
4053         break;
4054     }
4055     XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4056               dest, wlPieceGC, 0, 0,
4057               squareSize, squareSize, x, y);            
4058 }
4059
4060 typedef void (*DrawFunc)();
4061
4062 DrawFunc ChooseDrawFunc()
4063 {
4064     if (appData.monoMode) {
4065         if (DefaultDepth(xDisplay, xScreen) == 1) {
4066             return monoDrawPiece_1bit;
4067         } else {
4068             return monoDrawPiece;
4069         }
4070     } else {
4071         if (useImages)
4072           return colorDrawPieceImage;
4073         else
4074           return colorDrawPiece;
4075     }
4076 }
4077
4078 void DrawSquare(row, column, piece, do_flash)
4079      int row, column, do_flash;
4080      ChessSquare piece;
4081 {
4082     int square_color, x, y, direction, font_ascent, font_descent;
4083     int i;
4084     char string[2];
4085     XCharStruct overall;
4086     DrawFunc drawfunc;
4087     int flash_delay;
4088
4089     /* Calculate delay in milliseconds (2-delays per complete flash) */
4090     flash_delay = 500 / appData.flashRate;
4091         
4092     if (flipView) {
4093         x = lineGap + ((BOARD_SIZE-1)-column) * 
4094           (squareSize + lineGap);
4095         y = lineGap + row * (squareSize + lineGap);
4096     } else {
4097         x = lineGap + column * (squareSize + lineGap);
4098         y = lineGap + ((BOARD_SIZE-1)-row) * 
4099           (squareSize + lineGap);
4100     }
4101     
4102     square_color = ((column + row) % 2) == 1;
4103     
4104     if (piece == EmptySquare || appData.blindfold) {
4105         BlankSquare(x, y, square_color, piece, xBoardWindow);
4106     } else {
4107         drawfunc = ChooseDrawFunc();
4108         if (do_flash && appData.flashCount > 0) {
4109             for (i=0; i<appData.flashCount; ++i) {
4110
4111                 drawfunc(piece, square_color, x, y, xBoardWindow);
4112                 XSync(xDisplay, False);
4113                 do_flash_delay(flash_delay);
4114
4115                 BlankSquare(x, y, square_color, piece, xBoardWindow);
4116                 XSync(xDisplay, False);
4117                 do_flash_delay(flash_delay);
4118             }
4119         }
4120         drawfunc(piece, square_color, x, y, xBoardWindow);
4121     }
4122         
4123     string[1] = NULLCHAR;
4124     if (appData.showCoords && row == (flipView ? 7 : 0)) {
4125         string[0] = 'a' + column;
4126         XTextExtents(coordFontStruct, string, 1, &direction, 
4127                      &font_ascent, &font_descent, &overall);
4128         if (appData.monoMode) {
4129             XDrawImageString(xDisplay, xBoardWindow, coordGC,
4130                              x + squareSize - overall.width - 2, 
4131                              y + squareSize - font_descent - 1, string, 1);
4132         } else {
4133             XDrawString(xDisplay, xBoardWindow, coordGC,
4134                         x + squareSize - overall.width - 2, 
4135                         y + squareSize - font_descent - 1, string, 1);
4136         }
4137     }
4138     if (appData.showCoords && column == (flipView ? 7 : 0)) {
4139         string[0] = '1' + row;
4140         XTextExtents(coordFontStruct, string, 1, &direction, 
4141                      &font_ascent, &font_descent, &overall);
4142         if (appData.monoMode) {
4143             XDrawImageString(xDisplay, xBoardWindow, coordGC,
4144                              x + 2, y + font_ascent + 1, string, 1);
4145         } else {
4146             XDrawString(xDisplay, xBoardWindow, coordGC,
4147                         x + 2, y + font_ascent + 1, string, 1);
4148         }           
4149     }   
4150 }
4151
4152