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