2 * xboard.c -- X front end for XBoard
5 * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
6 * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
8 * The following terms apply to Digital Equipment Corporation's copyright
10 * ------------------------------------------------------------------------
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.
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
28 * ------------------------------------------------------------------------
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.
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.
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 * ------------------------------------------------------------------------
48 * See the file ChangeLog for a revision history.
57 #include <sys/types.h>
62 # if HAVE_SYS_SOCKET_H
63 # include <sys/socket.h>
64 # include <netinet/in.h>
66 # else /* not HAVE_SYS_SOCKET_H */
67 # if HAVE_LAN_SOCKET_H
68 # include <lan/socket.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 */
80 #else /* not STDC_HEADERS */
81 extern char *getenv();
84 # else /* not HAVE_STRING_H */
86 # endif /* not HAVE_STRING_H */
87 #endif /* not STDC_HEADERS */
90 # include <sys/fcntl.h>
91 #else /* not HAVE_SYS_FCNTL_H */
94 # endif /* HAVE_FCNTL_H */
95 #endif /* not HAVE_SYS_FCNTL_H */
97 #if HAVE_SYS_SYSTEMINFO_H
98 # include <sys/systeminfo.h>
99 #endif /* HAVE_SYS_SYSTEMINFO_H */
101 #if TIME_WITH_SYS_TIME
102 # include <sys/time.h>
106 # include <sys/time.h>
117 # include <sys/wait.h>
122 # define NAMLEN(dirent) strlen((dirent)->d_name)
123 # define HAVE_DIR_STRUCT
125 # define dirent direct
126 # define NAMLEN(dirent) (dirent)->d_namlen
128 # include <sys/ndir.h>
129 # define HAVE_DIR_STRUCT
132 # include <sys/dir.h>
133 # define HAVE_DIR_STRUCT
137 # define HAVE_DIR_STRUCT
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>
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>
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>
174 #include "pixmaps/pixmaps.h"
175 #define IMAGE_EXT "xpm"
177 #define IMAGE_EXT "xim"
178 #include "bitmaps/bitmaps.h"
181 #include "bitmaps/icon_white.bm"
182 #include "bitmaps/icon_black.bm"
183 #include "bitmaps/checkmark.bm"
186 #include "frontend.h"
191 #include "xgamelist.h"
192 #include "xhistory.h"
193 #include "xedittags.h"
200 #define usleep(t) _sleep2(((t)+500)/1000)
204 # define _(s) gettext (s)
205 # define N_(s) gettext_noop (s)
221 int main P((int argc, char **argv));
222 RETSIGTYPE CmailSigHandler P((int sig));
223 RETSIGTYPE IntSigHandler P((int sig));
224 void CreateGCs P((void));
225 void CreateXIMPieces P((void));
226 void CreateXPMPieces P((void));
227 void CreatePieces P((void));
228 void CreatePieceMenus P((void));
229 Widget CreateMenuBar P((Menu *mb));
230 Widget CreateButtonBar P ((MenuItem *mi));
231 char *FindFont P((char *pattern, int targetPxlSize));
232 void PieceMenuPopup P((Widget w, XEvent *event,
233 String *params, Cardinal *num_params));
234 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
235 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
236 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
237 u_int wreq, u_int hreq));
238 void CreateGrid P((void));
239 int EventToSquare P((int x, int limit));
240 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
241 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
242 void HandleUserMove P((Widget w, XEvent *event,
243 String *prms, Cardinal *nprms));
244 void AnimateUserMove P((Widget w, XEvent * event,
245 String * params, Cardinal * nParams));
246 void WhiteClock P((Widget w, XEvent *event,
247 String *prms, Cardinal *nprms));
248 void BlackClock P((Widget w, XEvent *event,
249 String *prms, Cardinal *nprms));
250 void DrawPositionProc P((Widget w, XEvent *event,
251 String *prms, Cardinal *nprms));
252 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
254 void CommentPopUp P((char *title, char *label));
255 void CommentPopDown P((void));
256 void CommentCallback P((Widget w, XtPointer client_data,
257 XtPointer call_data));
258 void ICSInputBoxPopUp P((void));
259 void ICSInputBoxPopDown P((void));
260 void FileNamePopUp P((char *label, char *def,
261 FileProc proc, char *openMode));
262 void FileNamePopDown P((void));
263 void FileNameCallback P((Widget w, XtPointer client_data,
264 XtPointer call_data));
265 void FileNameAction P((Widget w, XEvent *event,
266 String *prms, Cardinal *nprms));
267 void AskQuestionReplyAction P((Widget w, XEvent *event,
268 String *prms, Cardinal *nprms));
269 void AskQuestionProc P((Widget w, XEvent *event,
270 String *prms, Cardinal *nprms));
271 void AskQuestionPopDown P((void));
272 void PromotionPopUp P((void));
273 void PromotionPopDown P((void));
274 void PromotionCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void EditCommentPopDown P((void));
277 void EditCommentCallback P((Widget w, XtPointer client_data,
278 XtPointer call_data));
279 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
280 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
281 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
282 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
284 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
286 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
288 void LoadPositionProc P((Widget w, XEvent *event,
289 String *prms, Cardinal *nprms));
290 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
292 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
294 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
296 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
298 void PastePositionProc P((Widget w, XEvent *event, String *prms,
300 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
301 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
302 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void SavePositionProc P((Widget w, XEvent *event,
304 String *prms, Cardinal *nprms));
305 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
308 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
312 void MachineWhiteProc P((Widget w, XEvent *event,
313 String *prms, Cardinal *nprms));
314 void AnalyzeModeProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void AnalyzeFileProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
320 void IcsClientProc P((Widget w, XEvent *event, String *prms,
322 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void EditPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void EditCommentProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void IcsInputBoxProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void StopObservingProc P((Widget w, XEvent *event, String *prms,
341 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
343 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
350 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
352 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
355 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
357 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
359 void AutocommProc P((Widget w, XEvent *event, String *prms,
361 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AutobsProc P((Widget w, XEvent *event, String *prms,
365 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
370 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
373 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
375 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
377 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
381 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
383 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
385 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
387 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
389 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
393 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
395 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
397 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void DisplayMove P((int moveNumber));
407 void DisplayTitle P((char *title));
408 void ICSInitScript P((void));
409 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
410 void ErrorPopUp P((char *title, char *text, int modal));
411 void ErrorPopDown P((void));
412 static char *ExpandPathName P((char *path));
413 static void CreateAnimVars P((void));
414 static void DragPieceBegin P((int x, int y));
415 static void DragPieceMove P((int x, int y));
416 static void DragPieceEnd P((int x, int y));
417 static void DrawDragPiece P((void));
418 char *ModeToWidgetName P((GameMode mode));
421 * XBoard depends on Xt R4 or higher
423 int xtVersion = XtSpecificationRelease;
428 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
429 jailSquareColor, highlightSquareColor, premoveHighlightColor;
430 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
431 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
432 wjPieceGC, bjPieceGC, prelineGC;
433 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
434 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
435 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
436 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
437 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
438 ICSInputShell, fileNameShell, askQuestionShell;
439 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
440 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
441 Font clockFontID, coordFontID;
442 XFontStruct *clockFontStruct, *coordFontStruct;
443 XtAppContext appContext;
445 char *oldICSInteractionTitle;
450 Position commentX = -1, commentY = -1;
451 Dimension commentW, commentH;
453 int squareSize, smallLayout = 0, tinyLayout = 0,
454 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
455 ICSInputBoxUp = False, askQuestionUp = False,
456 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
457 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
458 Pixel timerForegroundPixel, timerBackgroundPixel;
459 Pixel buttonForegroundPixel, buttonBackgroundPixel;
460 char *chessDir, *programName, *programVersion,
461 *gameCopyFilename, *gamePasteFilename;
465 Pixmap pieceBitmap[2][6];
466 Pixmap xpmPieceBitmap[4][6]; /* LL, LD, DL, DD */
467 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
468 int useImages, useImageSqs;
469 XImage *ximPieceBitmap[4][6]; /* LL, LD, DL, DD */
470 Pixmap ximMaskPm[6]; /* clipmasks, used for XIM pieces */
471 XImage *ximLightSquare, *ximDarkSquare;
474 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % 6]
475 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % 6]
477 #define White(piece) ((int)(piece) < (int)BlackPawn)
479 /* Variables for doing smooth animation. This whole thing
480 would be much easier if the board was double-buffered,
481 but that would require a fairly major rewrite. */
486 GC blitGC, pieceGC, outlineGC;
487 XPoint startSquare, prevFrame, mouseDelta;
491 int startBoardX, startBoardY;
494 /* There can be two pieces being animated at once: a player
495 can begin dragging a piece before the remote opponent has moved. */
497 static AnimState game, player;
499 /* Bitmaps for use as masks when drawing XPM pieces.
500 Need one for each black and white piece. */
501 static Pixmap xpmMask[BlackKing + 1];
503 /* This magic number is the number of intermediate frames used
504 in each half of the animation. For short moves it's reduced
505 by 1. The total number of frames will be factor * 2 + 1. */
508 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
510 MenuItem fileMenu[] = {
511 {N_("Reset Game"), ResetProc},
512 {"----", NothingProc},
513 {N_("Load Game"), LoadGameProc},
514 {N_("Load Next Game"), LoadNextGameProc},
515 {N_("Load Previous Game"), LoadPrevGameProc},
516 {N_("Reload Same Game"), ReloadGameProc},
517 {N_("Save Game"), SaveGameProc},
518 {"----", NothingProc},
519 {N_("Copy Game"), CopyGameProc},
520 {N_("Paste Game"), PasteGameProc},
521 {"----", NothingProc},
522 {N_("Load Position"), LoadPositionProc},
523 {N_("Load Next Position"), LoadNextPositionProc},
524 {N_("Load Previous Position"), LoadPrevPositionProc},
525 {N_("Reload Same Position"), ReloadPositionProc},
526 {N_("Save Position"), SavePositionProc},
527 {"----", NothingProc},
528 {N_("Copy Position"), CopyPositionProc},
529 {N_("Paste Position"), PastePositionProc},
530 {"----", NothingProc},
531 {N_("Mail Move"), MailMoveProc},
532 {N_("Reload CMail Message"), ReloadCmailMsgProc},
533 {"----", NothingProc},
534 {N_("Exit"), QuitProc},
538 MenuItem modeMenu[] = {
539 {N_("Machine White"), MachineWhiteProc},
540 {N_("Machine Black"), MachineBlackProc},
541 {N_("Two Machines"), TwoMachinesProc},
542 {N_("Analysis Mode"), AnalyzeModeProc},
543 {N_("Analyze File"), AnalyzeFileProc },
544 {N_("ICS Client"), IcsClientProc},
545 {N_("Edit Game"), EditGameProc},
546 {N_("Edit Position"), EditPositionProc},
547 {N_("Training"), TrainingProc},
548 {"----", NothingProc},
549 {N_("Show Game List"), ShowGameListProc},
550 {N_("Show Move List"), HistoryShowProc},
551 {N_("Edit Tags"), EditTagsProc},
552 {N_("Edit Comment"), EditCommentProc},
553 {N_("ICS Input Box"), IcsInputBoxProc},
554 {N_("Pause"), PauseProc},
558 MenuItem actionMenu[] = {
559 {N_("Accept"), AcceptProc},
560 {N_("Decline"), DeclineProc},
561 {N_("Rematch"), RematchProc},
562 {"----", NothingProc},
563 {N_("Call Flag"), CallFlagProc},
564 {N_("Draw"), DrawProc},
565 {N_("Adjourn"), AdjournProc},
566 {N_("Abort"), AbortProc},
567 {N_("Resign"), ResignProc},
568 {"----", NothingProc},
569 {N_("Stop Observing"), StopObservingProc},
570 {N_("Stop Examining"), StopExaminingProc},
574 MenuItem stepMenu[] = {
575 {N_("Backward"), BackwardProc},
576 {N_("Forward"), ForwardProc},
577 {N_("Back to Start"), ToStartProc},
578 {N_("Forward to End"), ToEndProc},
579 {N_("Revert"), RevertProc},
580 {N_("Truncate Game"), TruncateGameProc},
581 {"----", NothingProc},
582 {N_("Move Now"), MoveNowProc},
583 {N_("Retract Move"), RetractMoveProc},
587 MenuItem optionsMenu[] = {
588 {N_("Always Queen"), AlwaysQueenProc},
589 {N_("Animate Dragging"), AnimateDraggingProc},
590 {N_("Animate Moving"), AnimateMovingProc},
591 {N_("Auto Comment"), AutocommProc},
592 {N_("Auto Flag"), AutoflagProc},
593 {N_("Auto Flip View"), AutoflipProc},
594 {N_("Auto Observe"), AutobsProc},
595 {N_("Auto Raise Board"), AutoraiseProc},
596 {N_("Auto Save"), AutosaveProc},
597 {N_("Blindfold"), BlindfoldProc},
598 {N_("Flash Moves"), FlashMovesProc},
599 {N_("Flip View"), FlipViewProc},
600 {N_("Get Move List"), GetMoveListProc},
602 {N_("Highlight Dragging"), HighlightDraggingProc},
604 {N_("Highlight Last Move"), HighlightLastMoveProc},
605 {N_("Move Sound"), MoveSoundProc},
606 {N_("ICS Alarm"), IcsAlarmProc},
607 {N_("Old Save Style"), OldSaveStyleProc},
608 {N_("Periodic Updates"), PeriodicUpdatesProc},
609 {N_("Ponder Next Move"), PonderNextMoveProc},
610 {N_("Popup Exit Message"), PopupExitMessageProc},
611 {N_("Popup Move Errors"), PopupMoveErrorsProc},
612 {N_("Premove"), PremoveProc},
613 {N_("Quiet Play"), QuietPlayProc},
614 {N_("Show Coords"), ShowCoordsProc},
615 {N_("Show Thinking"), ShowThinkingProc},
616 {N_("Test Legality"), TestLegalityProc},
620 MenuItem helpMenu[] = {
621 {N_("Info XBoard"), InfoProc},
622 {N_("Man XBoard"), ManProc},
623 {"----", NothingProc},
624 {N_("Hint"), HintProc},
625 {N_("Book"), BookProc},
626 {"----", NothingProc},
627 {N_("About XBoard"), AboutProc},
632 {N_("File"), fileMenu},
633 {N_("Mode"), modeMenu},
634 {N_("Action"), actionMenu},
635 {N_("Step"), stepMenu},
636 {N_("Options"), optionsMenu},
637 {N_("Help"), helpMenu},
642 /* Label on pause button */
643 #define PAUSE_BUTTON N_("P")
644 MenuItem buttonBar[] = {
647 {PAUSE_BUTTON, PauseProc},
653 #define PIECE_MENU_SIZE 11
654 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
655 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
656 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
657 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
658 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
660 /* must be in same order as PieceMenuStrings! */
661 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
662 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
663 WhiteRook, WhiteQueen, WhiteKing,
664 (ChessSquare) 0, EmptySquare, ClearBoard },
665 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
666 BlackRook, BlackQueen, BlackKing,
667 (ChessSquare) 0, EmptySquare, ClearBoard },
670 #define DROP_MENU_SIZE 6
671 String dropMenuStrings[DROP_MENU_SIZE] = {
672 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
674 /* must be in same order as PieceMenuStrings! */
675 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
676 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
677 WhiteRook, WhiteQueen
685 DropMenuEnables dmEnables[] = {
703 { XtNborderWidth, 0 },
704 { XtNdefaultDistance, 0 },
708 { XtNborderWidth, 0 },
709 { XtNresizable, (XtArgVal) True },
713 { XtNborderWidth, 0 },
719 { XtNjustify, (XtArgVal) XtJustifyRight },
720 { XtNlabel, (XtArgVal) "..." },
721 { XtNresizable, (XtArgVal) True },
722 { XtNresize, (XtArgVal) False }
725 Arg messageArgs[] = {
726 { XtNjustify, (XtArgVal) XtJustifyLeft },
727 { XtNlabel, (XtArgVal) "..." },
728 { XtNresizable, (XtArgVal) True },
729 { XtNresize, (XtArgVal) False }
733 { XtNborderWidth, 0 },
734 { XtNjustify, (XtArgVal) XtJustifyLeft }
737 XtResource clientResources[] = {
738 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
739 XtOffset(AppDataPtr, whitePieceColor), XtRString,
741 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
742 XtOffset(AppDataPtr, blackPieceColor), XtRString,
744 { "lightSquareColor", "lightSquareColor", XtRString,
745 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
746 XtRString, LIGHT_SQUARE_COLOR },
747 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
748 XtOffset(AppDataPtr, darkSquareColor), XtRString,
750 { "highlightSquareColor", "highlightSquareColor", XtRString,
751 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
752 XtRString, HIGHLIGHT_SQUARE_COLOR },
753 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
754 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
755 XtRString, PREMOVE_HIGHLIGHT_COLOR },
756 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
757 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
758 (XtPointer) MOVES_PER_SESSION },
759 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
760 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
761 (XtPointer) TIME_INCREMENT },
762 { "initString", "initString", XtRString, sizeof(String),
763 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
764 { "secondInitString", "secondInitString", XtRString, sizeof(String),
765 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
766 { "firstComputerString", "firstComputerString", XtRString,
767 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
769 { "secondComputerString", "secondComputerString", XtRString,
770 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
772 { "firstChessProgram", "firstChessProgram", XtRString,
773 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
774 XtRString, FIRST_CHESS_PROGRAM },
775 { "secondChessProgram", "secondChessProgram", XtRString,
776 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
777 XtRString, SECOND_CHESS_PROGRAM },
778 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
779 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
780 XtRImmediate, (XtPointer) False },
781 { "noChessProgram", "noChessProgram", XtRBoolean,
782 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
783 XtRImmediate, (XtPointer) False },
784 { "firstHost", "firstHost", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
786 { "secondHost", "secondHost", XtRString, sizeof(String),
787 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
788 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
789 XtOffset(AppDataPtr, firstDirectory), XtRString, "" },
790 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
791 XtOffset(AppDataPtr, secondDirectory), XtRString, "" },
792 { "bitmapDirectory", "bitmapDirectory", XtRString,
793 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
795 { "remoteShell", "remoteShell", XtRString, sizeof(String),
796 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
797 { "remoteUser", "remoteUser", XtRString, sizeof(String),
798 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
799 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
800 XtOffset(AppDataPtr, timeDelay), XtRString,
801 (XtPointer) TIME_DELAY_QUOTE },
802 { "timeControl", "timeControl", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, timeControl), XtRString,
804 (XtPointer) TIME_CONTROL },
805 { "internetChessServerMode", "internetChessServerMode",
806 XtRBoolean, sizeof(Boolean),
807 XtOffset(AppDataPtr, icsActive), XtRImmediate,
809 { "internetChessServerHost", "internetChessServerHost",
810 XtRString, sizeof(String),
811 XtOffset(AppDataPtr, icsHost),
812 XtRString, (XtPointer) ICS_HOST },
813 { "internetChessServerPort", "internetChessServerPort",
814 XtRString, sizeof(String),
815 XtOffset(AppDataPtr, icsPort), XtRString,
816 (XtPointer) ICS_PORT },
817 { "internetChessServerCommPort", "internetChessServerCommPort",
818 XtRString, sizeof(String),
819 XtOffset(AppDataPtr, icsCommPort), XtRString,
821 { "internetChessServerLogonScript", "internetChessServerLogonScript",
822 XtRString, sizeof(String),
823 XtOffset(AppDataPtr, icsLogon), XtRString,
825 { "internetChessServerHelper", "internetChessServerHelper",
826 XtRString, sizeof(String),
827 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
828 { "internetChessServerInputBox", "internetChessServerInputBox",
829 XtRBoolean, sizeof(Boolean),
830 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
832 { "icsAlarm", "icsAlarm",
833 XtRBoolean, sizeof(Boolean),
834 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
836 { "icsAlarmTime", "icsAlarmTime",
838 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
840 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
841 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
843 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
845 { "gateway", "gateway", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, gateway), XtRString, "" },
847 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
848 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
849 { "loadGameIndex", "loadGameIndex",
851 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
853 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
854 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
855 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
856 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
857 XtRImmediate, (XtPointer) True },
858 { "autoSaveGames", "autoSaveGames", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
860 XtRImmediate, (XtPointer) False },
861 { "blindfold", "blindfold", XtRBoolean,
862 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
863 XtRImmediate, (XtPointer) False },
864 { "loadPositionFile", "loadPositionFile", XtRString,
865 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
867 { "loadPositionIndex", "loadPositionIndex",
869 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
871 { "savePositionFile", "savePositionFile", XtRString,
872 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
874 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
875 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
876 { "matchGames", "matchGames", XtRInt, sizeof(int),
877 XtOffset(AppDataPtr, matchGames), XtRImmediate,
879 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
880 XtOffset(AppDataPtr, monoMode), XtRImmediate,
882 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
883 XtOffset(AppDataPtr, debugMode), XtRImmediate,
885 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, clockMode), XtRImmediate,
888 { "boardSize", "boardSize", XtRString, sizeof(String),
889 XtOffset(AppDataPtr, boardSize), XtRString, "" },
890 { "searchTime", "searchTime", XtRString, sizeof(String),
891 XtOffset(AppDataPtr, searchTime), XtRString,
893 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
894 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
896 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
897 XtOffset(AppDataPtr, showCoords), XtRImmediate,
899 { "showJail", "showJail", XtRInt, sizeof(int),
900 XtOffset(AppDataPtr, showJail), XtRImmediate,
902 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
903 XtOffset(AppDataPtr, showThinking), XtRImmediate,
905 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
906 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
908 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
909 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
911 { "clockFont", "clockFont", XtRString, sizeof(String),
912 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
913 { "coordFont", "coordFont", XtRString, sizeof(String),
914 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
915 { "font", "font", XtRString, sizeof(String),
916 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
917 { "ringBellAfterMoves", "ringBellAfterMoves",
918 XtRBoolean, sizeof(Boolean),
919 XtOffset(AppDataPtr, ringBellAfterMoves),
920 XtRImmediate, (XtPointer) False },
921 { "autoCallFlag", "autoCallFlag", XtRBoolean,
922 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
923 XtRImmediate, (XtPointer) False },
924 { "autoFlipView", "autoFlipView", XtRBoolean,
925 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
926 XtRImmediate, (XtPointer) True },
927 { "autoObserve", "autoObserve", XtRBoolean,
928 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
929 XtRImmediate, (XtPointer) False },
930 { "autoComment", "autoComment", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
932 XtRImmediate, (XtPointer) False },
933 { "getMoveList", "getMoveList", XtRBoolean,
934 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
935 XtRImmediate, (XtPointer) True },
937 { "highlightDragging", "highlightDragging", XtRBoolean,
938 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
939 XtRImmediate, (XtPointer) False },
941 { "highlightLastMove", "highlightLastMove", XtRBoolean,
942 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
943 XtRImmediate, (XtPointer) False },
944 { "premove", "premove", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, premove),
946 XtRImmediate, (XtPointer) True },
947 { "testLegality", "testLegality", XtRBoolean,
948 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
949 XtRImmediate, (XtPointer) True },
950 { "flipView", "flipView", XtRBoolean,
951 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
952 XtRImmediate, (XtPointer) False },
953 { "cmail", "cmailGameName", XtRString, sizeof(String),
954 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
955 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
956 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
957 XtRImmediate, (XtPointer) False },
958 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
960 XtRImmediate, (XtPointer) False },
961 { "quietPlay", "quietPlay", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
963 XtRImmediate, (XtPointer) False },
964 { "titleInWindow", "titleInWindow", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
966 XtRImmediate, (XtPointer) False },
967 { "localLineEditing", "localLineEditing", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
969 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
971 { "zippyTalk", "zippyTalk", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
973 XtRImmediate, (XtPointer) ZIPPY_TALK },
974 { "zippyPlay", "zippyPlay", XtRBoolean,
975 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
976 XtRImmediate, (XtPointer) ZIPPY_PLAY },
977 { "zippyLines", "zippyLines", XtRString, sizeof(String),
978 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
979 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
980 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
981 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
982 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
983 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
984 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
985 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
986 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
987 ZIPPY_WRONG_PASSWORD },
988 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
990 { "zippyUseI", "zippyUseI", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
992 XtRImmediate, (XtPointer) ZIPPY_USE_I },
993 { "zippyBughouse", "zippyBughouse", XtRInt,
994 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
995 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
996 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
998 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
999 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1000 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1001 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1002 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1003 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1005 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1006 { "zippyAbort", "zippyAbort", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1008 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1009 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1010 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1011 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1012 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1013 (XtPointer) ZIPPY_MAX_GAMES },
1014 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1015 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1016 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1018 { "flashCount", "flashCount", XtRInt, sizeof(int),
1019 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1020 (XtPointer) FLASH_COUNT },
1021 { "flashRate", "flashRate", XtRInt, sizeof(int),
1022 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1023 (XtPointer) FLASH_RATE },
1024 { "pixmapDirectory", "pixmapDirectory", XtRString,
1025 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1027 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1028 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1029 (XtPointer) MS_LOGIN_DELAY },
1030 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1032 XtRImmediate, (XtPointer) False },
1033 { "colorShout", "colorShout", XtRString,
1034 sizeof(String), XtOffset(AppDataPtr, colorShout),
1035 XtRString, COLOR_SHOUT },
1036 { "colorSShout", "colorSShout", XtRString,
1037 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1038 XtRString, COLOR_SSHOUT },
1039 { "colorChannel1", "colorChannel1", XtRString,
1040 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1041 XtRString, COLOR_CHANNEL1 },
1042 { "colorChannel", "colorChannel", XtRString,
1043 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1044 XtRString, COLOR_CHANNEL },
1045 { "colorKibitz", "colorKibitz", XtRString,
1046 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1047 XtRString, COLOR_KIBITZ },
1048 { "colorTell", "colorTell", XtRString,
1049 sizeof(String), XtOffset(AppDataPtr, colorTell),
1050 XtRString, COLOR_TELL },
1051 { "colorChallenge", "colorChallenge", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1053 XtRString, COLOR_CHALLENGE },
1054 { "colorRequest", "colorRequest", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1056 XtRString, COLOR_REQUEST },
1057 { "colorSeek", "colorSeek", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1059 XtRString, COLOR_SEEK },
1060 { "colorNormal", "colorNormal", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1062 XtRString, COLOR_NORMAL },
1063 { "soundProgram", "soundProgram", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1065 XtRString, "play" },
1066 { "soundShout", "soundShout", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, soundShout),
1069 { "soundSShout", "soundSShout", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1072 { "soundChannel1", "soundChannel1", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1075 { "soundChannel", "soundChannel", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1078 { "soundKibitz", "soundKibitz", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1081 { "soundTell", "soundTell", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundTell),
1084 { "soundChallenge", "soundChallenge", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1087 { "soundRequest", "soundRequest", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1090 { "soundSeek", "soundSeek", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1093 { "soundMove", "soundMove", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundMove),
1096 { "soundIcsWin", "soundIcsWin", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1099 { "soundIcsLoss", "soundIcsLoss", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1102 { "soundIcsDraw", "soundIcsDraw", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1105 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1108 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1111 { "reuseFirst", "reuseFirst", XtRBoolean,
1112 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1113 XtRImmediate, (XtPointer) True },
1114 { "reuseSecond", "reuseSecond", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1116 XtRImmediate, (XtPointer) True },
1117 { "animateDragging", "animateDragging", XtRBoolean,
1118 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1119 XtRImmediate, (XtPointer) True },
1120 { "animateMoving", "animateMoving", XtRBoolean,
1121 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1122 XtRImmediate, (XtPointer) True },
1123 { "animateSpeed", "animateSpeed", XtRInt,
1124 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1125 XtRImmediate, (XtPointer)10 },
1126 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1128 XtRImmediate, (XtPointer) True },
1129 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1130 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1131 XtRImmediate, (XtPointer) False },
1132 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1133 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1134 XtRImmediate, (XtPointer)4 },
1135 { "initialMode", "initialMode", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, initialMode),
1137 XtRImmediate, (XtPointer) "" },
1138 { "variant", "variant", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, variant),
1140 XtRImmediate, (XtPointer) "normal" },
1141 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1142 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1143 XtRImmediate, (XtPointer)PROTOVER },
1144 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1145 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1146 XtRImmediate, (XtPointer)PROTOVER },
1147 { "showButtonBar", "showButtonBar", XtRBoolean,
1148 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1149 XtRImmediate, (XtPointer) True },
1152 XrmOptionDescRec shellOptions[] = {
1153 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1154 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1155 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1156 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1157 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1158 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1159 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1160 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1161 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1162 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1163 { "-initString", "initString", XrmoptionSepArg, NULL },
1164 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1165 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1166 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1167 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1168 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1169 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1170 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1171 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1172 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1173 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1174 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1175 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1176 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1177 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1178 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1179 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1180 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1181 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1182 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1183 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1184 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1185 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1186 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1187 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1188 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1189 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1190 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1191 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1192 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1193 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1194 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1195 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1196 { "-internetChessServerMode", "internetChessServerMode",
1197 XrmoptionSepArg, NULL },
1198 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1199 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1200 { "-internetChessServerHost", "internetChessServerHost",
1201 XrmoptionSepArg, NULL },
1202 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1203 { "-internetChessServerPort", "internetChessServerPort",
1204 XrmoptionSepArg, NULL },
1205 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1206 { "-internetChessServerCommPort", "internetChessServerCommPort",
1207 XrmoptionSepArg, NULL },
1208 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1209 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1210 XrmoptionSepArg, NULL },
1211 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1212 { "-internetChessServerHelper", "internetChessServerHelper",
1213 XrmoptionSepArg, NULL },
1214 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1215 { "-internetChessServerInputBox", "internetChessServerInputBox",
1216 XrmoptionSepArg, NULL },
1217 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1218 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1219 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1220 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1221 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1222 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1223 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1224 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1225 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1226 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1227 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1228 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1229 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1230 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1231 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1232 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1233 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1234 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1235 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1236 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1237 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1238 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1239 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1240 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1241 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1242 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1243 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1244 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1245 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1246 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1247 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1248 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1249 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1250 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1251 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1252 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1253 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1254 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1255 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1256 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1257 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1258 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1259 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1260 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1261 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1262 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1263 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1264 { "-size", "boardSize", XrmoptionSepArg, NULL },
1265 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1266 { "-st", "searchTime", XrmoptionSepArg, NULL },
1267 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1268 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1269 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1270 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1271 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1273 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1274 { "-jail", "showJail", XrmoptionNoArg, "1" },
1275 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1276 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1278 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1279 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1280 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1281 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1282 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1283 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1284 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1285 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1286 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1287 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1288 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1289 { "-font", "font", XrmoptionSepArg, NULL },
1290 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1291 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1292 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1293 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1294 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1295 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1296 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1297 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1298 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1299 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1300 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1301 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1302 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1303 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1304 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1305 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1306 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1307 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1308 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1309 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1311 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1312 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1313 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1315 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1316 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1317 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1318 { "-premove", "premove", XrmoptionSepArg, NULL },
1319 { "-pre", "premove", XrmoptionNoArg, "True" },
1320 { "-xpre", "premove", XrmoptionNoArg, "False" },
1321 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1322 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1323 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1324 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1325 { "-flip", "flipView", XrmoptionNoArg, "True" },
1326 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1327 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1328 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1329 XrmoptionSepArg, NULL },
1330 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1331 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1332 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1333 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1334 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1335 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1336 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1337 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1338 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1339 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1340 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1342 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1343 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1344 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1345 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1346 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1347 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1348 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1349 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1350 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1351 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1352 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1353 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1354 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1355 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1356 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1357 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1358 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1359 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1360 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1361 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1362 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1363 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1364 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1365 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1366 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1367 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1368 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1369 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1370 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1371 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1373 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1374 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1375 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1376 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1377 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1378 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1379 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1380 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1381 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1382 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1383 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1384 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1385 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1386 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1387 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1388 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1389 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1390 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1391 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1392 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1393 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1394 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1395 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1396 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1397 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1398 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1399 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1400 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1401 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1402 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1403 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1404 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1405 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1406 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1407 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1408 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1409 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1410 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1411 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1412 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1413 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1414 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1415 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1416 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1417 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1418 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1419 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1420 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1421 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1422 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1423 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1424 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1425 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1426 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1427 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1428 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1429 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1430 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1431 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1432 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1433 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1434 { "-variant", "variant", XrmoptionSepArg, NULL },
1435 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1436 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1437 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1438 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1439 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1443 XtActionsRec boardActions[] = {
1444 { "DrawPosition", DrawPositionProc },
1445 { "HandleUserMove", HandleUserMove },
1446 { "AnimateUserMove", AnimateUserMove },
1447 { "FileNameAction", FileNameAction },
1448 { "AskQuestionProc", AskQuestionProc },
1449 { "AskQuestionReplyAction", AskQuestionReplyAction },
1450 { "PieceMenuPopup", PieceMenuPopup },
1451 { "WhiteClock", WhiteClock },
1452 { "BlackClock", BlackClock },
1453 { "Iconify", Iconify },
1454 { "ResetProc", ResetProc },
1455 { "LoadGameProc", LoadGameProc },
1456 { "LoadNextGameProc", LoadNextGameProc },
1457 { "LoadPrevGameProc", LoadPrevGameProc },
1458 { "LoadSelectedProc", LoadSelectedProc },
1459 { "ReloadGameProc", ReloadGameProc },
1460 { "LoadPositionProc", LoadPositionProc },
1461 { "LoadNextPositionProc", LoadNextPositionProc },
1462 { "LoadPrevPositionProc", LoadPrevPositionProc },
1463 { "ReloadPositionProc", ReloadPositionProc },
1464 { "CopyPositionProc", CopyPositionProc },
1465 { "PastePositionProc", PastePositionProc },
1466 { "CopyGameProc", CopyGameProc },
1467 { "PasteGameProc", PasteGameProc },
1468 { "SaveGameProc", SaveGameProc },
1469 { "SavePositionProc", SavePositionProc },
1470 { "MailMoveProc", MailMoveProc },
1471 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1472 { "QuitProc", QuitProc },
1473 { "MachineWhiteProc", MachineWhiteProc },
1474 { "MachineBlackProc", MachineBlackProc },
1475 { "AnalysisModeProc", AnalyzeModeProc },
1476 { "AnalyzeFileProc", AnalyzeFileProc },
1477 { "TwoMachinesProc", TwoMachinesProc },
1478 { "IcsClientProc", IcsClientProc },
1479 { "EditGameProc", EditGameProc },
1480 { "EditPositionProc", EditPositionProc },
1481 { "TrainingProc", EditPositionProc },
1482 { "ShowGameListProc", ShowGameListProc },
1483 { "ShowMoveListProc", HistoryShowProc},
1484 { "EditTagsProc", EditCommentProc },
1485 { "EditCommentProc", EditCommentProc },
1486 { "IcsAlarmProc", IcsAlarmProc },
1487 { "IcsInputBoxProc", IcsInputBoxProc },
1488 { "PauseProc", PauseProc },
1489 { "AcceptProc", AcceptProc },
1490 { "DeclineProc", DeclineProc },
1491 { "RematchProc", RematchProc },
1492 { "CallFlagProc", CallFlagProc },
1493 { "DrawProc", DrawProc },
1494 { "AdjournProc", AdjournProc },
1495 { "AbortProc", AbortProc },
1496 { "ResignProc", ResignProc },
1497 { "EnterKeyProc", EnterKeyProc },
1498 { "StopObservingProc", StopObservingProc },
1499 { "StopExaminingProc", StopExaminingProc },
1500 { "BackwardProc", BackwardProc },
1501 { "ForwardProc", ForwardProc },
1502 { "ToStartProc", ToStartProc },
1503 { "ToEndProc", ToEndProc },
1504 { "RevertProc", RevertProc },
1505 { "TruncateGameProc", TruncateGameProc },
1506 { "MoveNowProc", MoveNowProc },
1507 { "RetractMoveProc", RetractMoveProc },
1508 { "AlwaysQueenProc", AlwaysQueenProc },
1509 { "AnimateDraggingProc", AnimateDraggingProc },
1510 { "AnimateMovingProc", AnimateMovingProc },
1511 { "AutoflagProc", AutoflagProc },
1512 { "AutoflipProc", AutoflipProc },
1513 { "AutobsProc", AutobsProc },
1514 { "AutoraiseProc", AutoraiseProc },
1515 { "AutosaveProc", AutosaveProc },
1516 { "BlindfoldProc", BlindfoldProc },
1517 { "FlashMovesProc", FlashMovesProc },
1518 { "FlipViewProc", FlipViewProc },
1519 { "GetMoveListProc", GetMoveListProc },
1521 { "HighlightDraggingProc", HighlightDraggingProc },
1523 { "HighlightLastMoveProc", HighlightLastMoveProc },
1524 { "IcsAlarmProc", IcsAlarmProc },
1525 { "MoveSoundProc", MoveSoundProc },
1526 { "OldSaveStyleProc", OldSaveStyleProc },
1527 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1528 { "PonderNextMoveProc", PonderNextMoveProc },
1529 { "PopupExitMessageProc", PopupExitMessageProc },
1530 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1531 { "PremoveProc", PremoveProc },
1532 { "QuietPlayProc", QuietPlayProc },
1533 { "ShowCoordsProc", ShowCoordsProc },
1534 { "ShowThinkingProc", ShowThinkingProc },
1535 { "TestLegalityProc", TestLegalityProc },
1536 { "InfoProc", InfoProc },
1537 { "ManProc", ManProc },
1538 { "HintProc", HintProc },
1539 { "BookProc", BookProc },
1540 { "AboutGameProc", AboutGameProc },
1541 { "AboutProc", AboutProc },
1542 { "DebugProc", DebugProc },
1543 { "NothingProc", NothingProc },
1544 { "CommentPopDown", (XtActionProc) CommentPopDown },
1545 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1546 { "TagsPopDown", (XtActionProc) TagsPopDown },
1547 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1548 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1549 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1550 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1551 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1552 { "GameListPopDown", (XtActionProc) GameListPopDown },
1553 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1554 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1557 char globalTranslations[] =
1558 ":<Key>R: ResignProc() \n \
1559 :<Key>r: ResetProc() \n \
1560 :<Key>g: LoadGameProc() \n \
1561 :<Key>N: LoadNextGameProc() \n \
1562 :<Key>P: LoadPrevGameProc() \n \
1563 :<Key>Q: QuitProc() \n \
1564 :<Key>F: ToEndProc() \n \
1565 :<Key>f: ForwardProc() \n \
1566 :<Key>B: ToStartProc() \n \
1567 :<Key>b: BackwardProc() \n \
1568 :<Key>p: PauseProc() \n \
1569 :<Key>d: DrawProc() \n \
1570 :<Key>t: CallFlagProc() \n \
1571 :<Key>i: Iconify() \n \
1572 :<Key>c: Iconify() \n \
1573 :<Key>v: FlipViewProc() \n \
1574 <KeyDown>Control_L: BackwardProc() \n \
1575 <KeyUp>Control_L: ForwardProc() \n \
1576 <KeyDown>Control_R: BackwardProc() \n \
1577 <KeyUp>Control_R: ForwardProc() \n \
1578 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1579 \"Send to chess program:\",,1) \n \
1580 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1581 \"Send to second chess program:\",,2) \n";
1583 char boardTranslations[] =
1584 "<Btn1Down>: HandleUserMove() \n \
1585 <Btn1Up>: HandleUserMove() \n \
1586 <Btn1Motion>: AnimateUserMove() \n \
1587 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1588 PieceMenuPopup(menuB) \n \
1589 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1590 PieceMenuPopup(menuW) \n \
1591 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1592 PieceMenuPopup(menuW) \n \
1593 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1594 PieceMenuPopup(menuB) \n";
1596 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1597 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1599 char ICSInputTranslations[] =
1600 "<Key>Return: EnterKeyProc() \n";
1602 String xboardResources[] = {
1603 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1604 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1605 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1610 /* Max possible square size */
1611 #define MAXSQSIZE 256
1613 static int xpm_avail[MAXSQSIZE];
1615 #ifdef HAVE_DIR_STRUCT
1617 /* Extract piece size from filename */
1619 xpm_getsize(name, len, ext)
1630 if ((p=strchr(name, '.')) == NULL ||
1631 StrCaseCmp(p+1, ext) != 0)
1637 while (*p && isdigit(*p))
1644 /* Setup xpm_avail */
1646 xpm_getavail(dirname, ext)
1654 for (i=0; i<MAXSQSIZE; ++i)
1657 if (appData.debugMode)
1658 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1660 dir = opendir(dirname);
1663 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1664 programName, dirname);
1668 while ((ent=readdir(dir)) != NULL) {
1669 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1670 if (i > 0 && i < MAXSQSIZE)
1680 xpm_print_avail(fp, ext)
1686 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1687 for (i=1; i<MAXSQSIZE; ++i) {
1693 /* Return XPM piecesize closest to size */
1695 xpm_closest_to(dirname, size, ext)
1701 int sm_diff = MAXSQSIZE;
1705 xpm_getavail(dirname, ext);
1707 if (appData.debugMode)
1708 xpm_print_avail(stderr, ext);
1710 for (i=1; i<MAXSQSIZE; ++i) {
1713 diff = (diff<0) ? -diff : diff;
1714 if (diff < sm_diff) {
1722 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1728 #else /* !HAVE_DIR_STRUCT */
1729 /* If we are on a system without a DIR struct, we can't
1730 read the directory, so we can't collect a list of
1731 filenames, etc., so we can't do any size-fitting. */
1733 xpm_closest_to(dirname, size, ext)
1738 fprintf(stderr, _("\
1739 Warning: No DIR structure found on this system --\n\
1740 Unable to autosize for XPM/XIM pieces.\n\
1741 Please report this error to frankm@hiwaay.net.\n\
1742 Include system type & operating system in message.\n"));
1745 #endif /* HAVE_DIR_STRUCT */
1747 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1748 "magenta", "cyan", "white" };
1752 TextColors textColors[(int)NColorClasses];
1754 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1756 parse_color(str, which)
1760 char *p, buf[100], *d;
1763 if (strlen(str) > 99) /* watch bounds on buf */
1768 for (i=0; i<which; ++i) {
1775 /* Could be looking at something like:
1777 .. in which case we want to stop on a comma also */
1778 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1782 return -1; /* Use default for empty field */
1785 if (which == 2 || isdigit(*p))
1788 while (*p && isalpha(*p))
1793 for (i=0; i<8; ++i) {
1794 if (!StrCaseCmp(buf, cnames[i]))
1795 return which? (i+40) : (i+30);
1797 if (!StrCaseCmp(buf, "default")) return -1;
1799 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1804 parse_cpair(cc, str)
1808 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1809 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1814 /* bg and attr are optional */
1815 textColors[(int)cc].bg = parse_color(str, 1);
1816 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1817 textColors[(int)cc].attr = 0;
1823 /* Arrange to catch delete-window events */
1824 Atom wm_delete_window;
1826 CatchDeleteWindow(Widget w, String procname)
1829 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1830 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
1831 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1838 XtSetArg(args[0], XtNiconic, False);
1839 XtSetValues(shellWidget, args, 1);
1841 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1849 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1850 XSetWindowAttributes window_attributes;
1852 Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
1853 XrmValue vFrom, vTo;
1854 XtGeometryResult gres;
1857 int forceMono = False;
1859 setbuf(stdout, NULL);
1860 setbuf(stderr, NULL);
1863 programName = strrchr(argv[0], '/');
1864 if (programName == NULL)
1865 programName = argv[0];
1870 XtSetLanguageProc(NULL, NULL, NULL);
1871 bindtextdomain(PRODUCT, LOCALEDIR);
1872 textdomain(PRODUCT);
1876 XtAppInitialize(&appContext, "XBoard", shellOptions,
1877 XtNumber(shellOptions),
1878 &argc, argv, xboardResources, NULL, 0);
1880 fprintf(stderr, _("%s: unrecognized argument %s\n"),
1881 programName, argv[1]);
1885 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1888 if (chdir(chessDir) != 0) {
1889 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1896 if (p == NULL) p = "/tmp";
1897 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1898 gameCopyFilename = (char*) malloc(i);
1899 gamePasteFilename = (char*) malloc(i);
1900 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1901 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1903 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1904 clientResources, XtNumber(clientResources),
1908 /* This feature does not work; animation needs a rewrite */
1909 appData.highlightDragging = FALSE;
1913 xDisplay = XtDisplay(shellWidget);
1914 xScreen = DefaultScreen(xDisplay);
1915 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1918 * Determine boardSize
1920 if (isdigit(appData.boardSize[0])) {
1921 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1922 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1923 &fontPxlSize, &smallLayout, &tinyLayout);
1925 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1926 programName, appData.boardSize);
1930 /* Find some defaults; use the nearest known size */
1931 SizeDefaults *szd, *nearest;
1932 int distance = 99999;
1933 nearest = szd = sizeDefaults;
1934 while (szd->name != NULL) {
1935 if (abs(szd->squareSize - squareSize) < distance) {
1937 distance = abs(szd->squareSize - squareSize);
1938 if (distance == 0) break;
1942 if (i < 2) lineGap = nearest->lineGap;
1943 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1944 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1945 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1946 if (i < 6) smallLayout = nearest->smallLayout;
1947 if (i < 7) tinyLayout = nearest->tinyLayout;
1950 SizeDefaults *szd = sizeDefaults;
1951 if (*appData.boardSize == NULLCHAR) {
1952 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1953 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1956 if (szd->name == NULL) szd--;
1958 while (szd->name != NULL &&
1959 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1960 if (szd->name == NULL) {
1961 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1962 programName, appData.boardSize);
1966 squareSize = szd->squareSize;
1967 lineGap = szd->lineGap;
1968 clockFontPxlSize = szd->clockFontPxlSize;
1969 coordFontPxlSize = szd->coordFontPxlSize;
1970 fontPxlSize = szd->fontPxlSize;
1971 smallLayout = szd->smallLayout;
1972 tinyLayout = szd->tinyLayout;
1975 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1976 if (strlen(appData.pixmapDirectory) > 0) {
1977 p = ExpandPathName(appData.pixmapDirectory);
1979 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1980 appData.pixmapDirectory);
1983 if (appData.debugMode) {
1984 fprintf(stderr, _("\
1985 XBoard square size (hint): %d\n\
1986 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1988 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1989 if (appData.debugMode) {
1990 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1994 boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
1995 if (appData.showJail == 1) {
1996 /* Jail on top and bottom */
1997 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1998 XtSetArg(boardArgs[2], XtNheight,
1999 boardWidth + 2*(lineGap + squareSize));
2000 } else if (appData.showJail == 2) {
2002 XtSetArg(boardArgs[1], XtNwidth,
2003 boardWidth + 2*(lineGap + squareSize));
2004 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2007 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2008 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2012 * Determine what fonts to use.
2014 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2015 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2016 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2017 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2018 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2019 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2020 appData.font = FindFont(appData.font, fontPxlSize);
2022 xdb = XtDatabase(xDisplay);
2023 XrmPutStringResource(&xdb, "*font", appData.font);
2026 * Detect if there are not enough colors available and adapt.
2028 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2029 appData.monoMode = True;
2032 if (!appData.monoMode) {
2033 vFrom.addr = (caddr_t) appData.lightSquareColor;
2034 vFrom.size = strlen(appData.lightSquareColor);
2035 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2036 if (vTo.addr == NULL) {
2037 appData.monoMode = True;
2040 lightSquareColor = *(Pixel *) vTo.addr;
2043 if (!appData.monoMode) {
2044 vFrom.addr = (caddr_t) appData.darkSquareColor;
2045 vFrom.size = strlen(appData.darkSquareColor);
2046 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2047 if (vTo.addr == NULL) {
2048 appData.monoMode = True;
2051 darkSquareColor = *(Pixel *) vTo.addr;
2054 if (!appData.monoMode) {
2055 vFrom.addr = (caddr_t) appData.whitePieceColor;
2056 vFrom.size = strlen(appData.whitePieceColor);
2057 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2058 if (vTo.addr == NULL) {
2059 appData.monoMode = True;
2062 whitePieceColor = *(Pixel *) vTo.addr;
2065 if (!appData.monoMode) {
2066 vFrom.addr = (caddr_t) appData.blackPieceColor;
2067 vFrom.size = strlen(appData.blackPieceColor);
2068 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2069 if (vTo.addr == NULL) {
2070 appData.monoMode = True;
2073 blackPieceColor = *(Pixel *) vTo.addr;
2077 if (!appData.monoMode) {
2078 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2079 vFrom.size = strlen(appData.highlightSquareColor);
2080 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2081 if (vTo.addr == NULL) {
2082 appData.monoMode = True;
2085 highlightSquareColor = *(Pixel *) vTo.addr;
2089 if (!appData.monoMode) {
2090 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2091 vFrom.size = strlen(appData.premoveHighlightColor);
2092 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2093 if (vTo.addr == NULL) {
2094 appData.monoMode = True;
2097 premoveHighlightColor = *(Pixel *) vTo.addr;
2102 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2106 if (appData.monoMode && appData.debugMode) {
2107 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2108 (unsigned long) XWhitePixel(xDisplay, xScreen),
2109 (unsigned long) XBlackPixel(xDisplay, xScreen));
2112 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2113 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2114 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2115 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2116 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2117 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2118 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2119 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2120 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2121 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2123 if (appData.colorize) {
2125 _("%s: can't parse color names; disabling colorization\n"),
2128 appData.colorize = FALSE;
2130 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2131 textColors[ColorNone].attr = 0;
2133 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2139 layoutName = "tinyLayout";
2140 } else if (smallLayout) {
2141 layoutName = "smallLayout";
2143 layoutName = "normalLayout";
2145 /* Outer layoutWidget is there only to provide a name for use in
2146 resources that depend on the layout style */
2148 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2149 layoutArgs, XtNumber(layoutArgs));
2151 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2152 formArgs, XtNumber(formArgs));
2153 XtSetArg(args[0], XtNdefaultDistance, &sep);
2154 XtGetValues(formWidget, args, 1);
2157 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2159 widgetList[j++] = whiteTimerWidget =
2160 XtCreateWidget("whiteTime", labelWidgetClass,
2161 formWidget, timerArgs, XtNumber(timerArgs));
2162 XtSetArg(args[0], XtNfont, clockFontStruct);
2163 XtSetValues(whiteTimerWidget, args, 1);
2165 widgetList[j++] = blackTimerWidget =
2166 XtCreateWidget("blackTime", labelWidgetClass,
2167 formWidget, timerArgs, XtNumber(timerArgs));
2168 XtSetArg(args[0], XtNfont, clockFontStruct);
2169 XtSetValues(blackTimerWidget, args, 1);
2171 if (appData.titleInWindow) {
2172 widgetList[j++] = titleWidget =
2173 XtCreateWidget("title", labelWidgetClass, formWidget,
2174 titleArgs, XtNumber(titleArgs));
2177 if (appData.showButtonBar) {
2178 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2181 widgetList[j++] = messageWidget =
2182 XtCreateWidget("message", labelWidgetClass, formWidget,
2183 messageArgs, XtNumber(messageArgs));
2185 widgetList[j++] = boardWidget =
2186 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2187 XtNumber(boardArgs));
2189 XtManageChildren(widgetList, j);
2191 timerWidth = (boardWidth - sep) / 2;
2192 XtSetArg(args[0], XtNwidth, timerWidth);
2193 XtSetValues(whiteTimerWidget, args, 1);
2194 XtSetValues(blackTimerWidget, args, 1);
2196 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2197 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2198 XtGetValues(whiteTimerWidget, args, 2);
2200 if (appData.showButtonBar) {
2201 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2202 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2203 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2207 * formWidget uses these constraints but they are stored
2211 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2212 XtSetValues(menuBarWidget, args, i);
2213 if (appData.titleInWindow) {
2216 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2217 XtSetValues(whiteTimerWidget, args, i);
2219 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2220 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2221 XtSetValues(blackTimerWidget, args, i);
2223 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2224 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2225 XtSetValues(titleWidget, args, i);
2227 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2228 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2229 XtSetValues(messageWidget, args, i);
2230 if (appData.showButtonBar) {
2232 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2233 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2234 XtSetValues(buttonBarWidget, args, i);
2238 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2239 XtSetValues(whiteTimerWidget, args, i);
2241 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2242 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2243 XtSetValues(blackTimerWidget, args, i);
2245 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2246 XtSetValues(titleWidget, args, i);
2248 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2249 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2250 XtSetValues(messageWidget, args, i);
2251 if (appData.showButtonBar) {
2253 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2254 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2255 XtSetValues(buttonBarWidget, args, i);
2260 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2261 XtSetValues(whiteTimerWidget, args, i);
2263 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2264 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2265 XtSetValues(blackTimerWidget, args, i);
2267 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2268 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2269 XtSetValues(messageWidget, args, i);
2270 if (appData.showButtonBar) {
2272 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2273 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2274 XtSetValues(buttonBarWidget, args, i);
2278 XtSetArg(args[0], XtNfromVert, messageWidget);
2279 XtSetValues(boardWidget, args, 1);
2281 XtRealizeWidget(shellWidget);
2284 * Correct the width of the message and title widgets.
2285 * It is not known why some systems need the extra fudge term.
2286 * The value "2" is probably larger than needed.
2288 XawFormDoLayout(formWidget, False);
2289 #define WIDTH_FUDGE 2
2291 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2292 XtSetArg(args[i], XtNheight, &h); i++;
2293 XtGetValues(messageWidget, args, i);
2294 if (appData.showButtonBar) {
2296 XtSetArg(args[i], XtNwidth, &w); i++;
2297 XtGetValues(buttonBarWidget, args, i);
2298 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2300 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2303 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2304 if (gres != XtGeometryYes && appData.debugMode) {
2305 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2306 programName, gres, w, h, wr, hr);
2309 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2310 /* The size used for the child widget in layout lags one resize behind
2311 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2313 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2314 if (gres != XtGeometryYes && appData.debugMode) {
2315 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2316 programName, gres, w, h, wr, hr);
2320 if (appData.titleInWindow) {
2322 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2323 XtSetArg(args[i], XtNheight, &h); i++;
2324 XtGetValues(titleWidget, args, i);
2326 w = boardWidth - 2*bor;
2328 XtSetArg(args[0], XtNwidth, &w);
2329 XtGetValues(menuBarWidget, args, 1);
2330 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2333 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2334 if (gres != XtGeometryYes && appData.debugMode) {
2336 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2337 programName, gres, w, h, wr, hr);
2340 XawFormDoLayout(formWidget, True);
2342 xBoardWindow = XtWindow(boardWidget);
2345 * Create X checkmark bitmap and initialize option menu checks.
2347 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2348 checkmark_bits, checkmark_width, checkmark_height);
2349 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2350 if (appData.alwaysPromoteToQueen) {
2351 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2354 if (appData.animateDragging) {
2355 XtSetValues(XtNameToWidget(menuBarWidget,
2356 "menuOptions.Animate Dragging"),
2359 if (appData.animate) {
2360 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2363 if (appData.autoComment) {
2364 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2367 if (appData.autoCallFlag) {
2368 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2371 if (appData.autoFlipView) {
2372 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2375 if (appData.autoObserve) {
2376 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2379 if (appData.autoRaiseBoard) {
2380 XtSetValues(XtNameToWidget(menuBarWidget,
2381 "menuOptions.Auto Raise Board"), args, 1);
2383 if (appData.autoSaveGames) {
2384 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2387 if (appData.saveGameFile[0] != NULLCHAR) {
2388 /* Can't turn this off from menu */
2389 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2391 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2395 if (appData.blindfold) {
2396 XtSetValues(XtNameToWidget(menuBarWidget,
2397 "menuOptions.Blindfold"), args, 1);
2399 if (appData.flashCount > 0) {
2400 XtSetValues(XtNameToWidget(menuBarWidget,
2401 "menuOptions.Flash Moves"),
2404 if (appData.getMoveList) {
2405 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2409 if (appData.highlightDragging) {
2410 XtSetValues(XtNameToWidget(menuBarWidget,
2411 "menuOptions.Highlight Dragging"),
2415 if (appData.highlightLastMove) {
2416 XtSetValues(XtNameToWidget(menuBarWidget,
2417 "menuOptions.Highlight Last Move"),
2420 if (appData.icsAlarm) {
2421 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2424 if (appData.ringBellAfterMoves) {
2425 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2428 if (appData.oldSaveStyle) {
2429 XtSetValues(XtNameToWidget(menuBarWidget,
2430 "menuOptions.Old Save Style"), args, 1);
2432 if (appData.periodicUpdates) {
2433 XtSetValues(XtNameToWidget(menuBarWidget,
2434 "menuOptions.Periodic Updates"), args, 1);
2436 if (appData.ponderNextMove) {
2437 XtSetValues(XtNameToWidget(menuBarWidget,
2438 "menuOptions.Ponder Next Move"), args, 1);
2440 if (appData.popupExitMessage) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Popup Exit Message"), args, 1);
2444 if (appData.popupMoveErrors) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Popup Move Errors"), args, 1);
2448 if (appData.premove) {
2449 XtSetValues(XtNameToWidget(menuBarWidget,
2450 "menuOptions.Premove"), args, 1);
2452 if (appData.quietPlay) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,
2454 "menuOptions.Quiet Play"), args, 1);
2456 if (appData.showCoords) {
2457 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2460 if (appData.showThinking) {
2461 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2464 if (appData.testLegality) {
2465 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2472 ReadBitmap(&wIconPixmap, "icon_white.bm",
2473 icon_white_bits, icon_white_width, icon_white_height);
2474 ReadBitmap(&bIconPixmap, "icon_black.bm",
2475 icon_black_bits, icon_black_width, icon_black_height);
2476 iconPixmap = wIconPixmap;
2478 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2479 XtSetValues(shellWidget, args, i);
2482 * Create a cursor for the board widget.
2484 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2485 XChangeWindowAttributes(xDisplay, xBoardWindow,
2486 CWCursor, &window_attributes);
2489 * Inhibit shell resizing.
2491 shellArgs[0].value = (XtArgVal) &w;
2492 shellArgs[1].value = (XtArgVal) &h;
2493 XtGetValues(shellWidget, shellArgs, 2);
2494 shellArgs[4].value = shellArgs[2].value = w;
2495 shellArgs[5].value = shellArgs[3].value = h;
2496 XtSetValues(shellWidget, &shellArgs[2], 4);
2498 CatchDeleteWindow(shellWidget, "QuitProc");
2503 if (appData.bitmapDirectory[0] != NULLCHAR) {
2510 /* Create regular pieces */
2511 if (!useImages) CreatePieces();
2516 if (appData.animate || appData.animateDragging)
2519 XtAugmentTranslations(formWidget,
2520 XtParseTranslationTable(globalTranslations));
2521 XtAugmentTranslations(boardWidget,
2522 XtParseTranslationTable(boardTranslations));
2523 XtAugmentTranslations(whiteTimerWidget,
2524 XtParseTranslationTable(whiteTranslations));
2525 XtAugmentTranslations(blackTimerWidget,
2526 XtParseTranslationTable(blackTranslations));
2528 /* Why is the following needed on some versions of X instead
2529 * of a translation? */
2530 XtAddEventHandler(boardWidget, ExposureMask, False,
2531 (XtEventHandler) EventProc, NULL);
2536 if (errorExitStatus == -1) {
2537 if (appData.icsActive) {
2538 /* We now wait until we see "login:" from the ICS before
2539 sending the logon script (problems with timestamp otherwise) */
2540 /*ICSInitScript();*/
2541 if (appData.icsInputBox) ICSInputBoxPopUp();
2544 signal(SIGINT, IntSigHandler);
2545 signal(SIGTERM, IntSigHandler);
2546 if (*appData.cmailGameName != NULLCHAR) {
2547 signal(SIGUSR1, CmailSigHandler);
2551 XtAppMainLoop(appContext);
2558 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2559 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2561 unlink(gameCopyFilename);
2562 unlink(gamePasteFilename);
2573 CmailSigHandler(sig)
2579 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2581 /* Activate call-back function CmailSigHandlerCallBack() */
2582 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2584 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2588 CmailSigHandlerCallBack(isr, closure, message, count, error)
2596 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2598 /**** end signal code ****/
2608 f = fopen(appData.icsLogon, "r");
2614 strcat(buf, appData.icsLogon);
2615 f = fopen(buf, "r");
2619 ProcessICSInitScript(f);
2626 EditCommentPopDown();
2637 SetMenuEnables(enab)
2641 if (!menuBarWidget) return;
2642 while (enab->name != NULL) {
2643 w = XtNameToWidget(menuBarWidget, enab->name);
2645 DisplayError(enab->name, 0);
2647 XtSetSensitive(w, enab->value);
2653 Enables icsEnables[] = {
2654 { "menuFile.Mail Move", False },
2655 { "menuFile.Reload CMail Message", False },
2656 { "menuMode.Machine Black", False },
2657 { "menuMode.Machine White", False },
2658 { "menuMode.Analysis Mode", False },
2659 { "menuMode.Analyze File", False },
2660 { "menuMode.Two Machines", False },
2662 { "menuHelp.Hint", False },
2663 { "menuHelp.Book", False },
2664 { "menuStep.Move Now", False },
2665 { "menuOptions.Periodic Updates", False },
2666 { "menuOptions.Show Thinking", False },
2667 { "menuOptions.Ponder Next Move", False },
2672 Enables ncpEnables[] = {
2673 { "menuFile.Mail Move", False },
2674 { "menuFile.Reload CMail Message", False },
2675 { "menuMode.Machine White", False },
2676 { "menuMode.Machine Black", False },
2677 { "menuMode.Analysis Mode", False },
2678 { "menuMode.Analyze File", False },
2679 { "menuMode.Two Machines", False },
2680 { "menuMode.ICS Client", False },
2681 { "menuMode.ICS Input Box", False },
2682 { "Action", False },
2683 { "menuStep.Revert", False },
2684 { "menuStep.Move Now", False },
2685 { "menuStep.Retract Move", False },
2686 { "menuOptions.Auto Comment", False },
2687 { "menuOptions.Auto Flag", False },
2688 { "menuOptions.Auto Flip View", False },
2689 { "menuOptions.Auto Observe", False },
2690 { "menuOptions.Auto Raise Board", False },
2691 { "menuOptions.Get Move List", False },
2692 { "menuOptions.ICS Alarm", False },
2693 { "menuOptions.Move Sound", False },
2694 { "menuOptions.Quiet Play", False },
2695 { "menuOptions.Show Thinking", False },
2696 { "menuOptions.Periodic Updates", False },
2697 { "menuOptions.Ponder Next Move", False },
2698 { "menuHelp.Hint", False },
2699 { "menuHelp.Book", False },
2703 Enables gnuEnables[] = {
2704 { "menuMode.ICS Client", False },
2705 { "menuMode.ICS Input Box", False },
2706 { "menuAction.Accept", False },
2707 { "menuAction.Decline", False },
2708 { "menuAction.Rematch", False },
2709 { "menuAction.Adjourn", False },
2710 { "menuAction.Stop Examining", False },
2711 { "menuAction.Stop Observing", False },
2712 { "menuStep.Revert", False },
2713 { "menuOptions.Auto Comment", False },
2714 { "menuOptions.Auto Observe", False },
2715 { "menuOptions.Auto Raise Board", False },
2716 { "menuOptions.Get Move List", False },
2717 { "menuOptions.Premove", False },
2718 { "menuOptions.Quiet Play", False },
2720 /* The next two options rely on SetCmailMode being called *after* */
2721 /* SetGNUMode so that when GNU is being used to give hints these */
2722 /* menu options are still available */
2724 { "menuFile.Mail Move", False },
2725 { "menuFile.Reload CMail Message", False },
2729 Enables cmailEnables[] = {
2731 { "menuAction.Call Flag", False },
2732 { "menuAction.Draw", True },
2733 { "menuAction.Adjourn", False },
2734 { "menuAction.Abort", False },
2735 { "menuAction.Stop Observing", False },
2736 { "menuAction.Stop Examining", False },
2737 { "menuFile.Mail Move", True },
2738 { "menuFile.Reload CMail Message", True },
2742 Enables trainingOnEnables[] = {
2743 { "menuMode.Edit Comment", False },
2744 { "menuMode.Pause", False },
2745 { "menuStep.Forward", False },
2746 { "menuStep.Backward", False },
2747 { "menuStep.Forward to End", False },
2748 { "menuStep.Back to Start", False },
2749 { "menuStep.Move Now", False },
2750 { "menuStep.Truncate Game", False },
2754 Enables trainingOffEnables[] = {
2755 { "menuMode.Edit Comment", True },
2756 { "menuMode.Pause", True },
2757 { "menuStep.Forward", True },
2758 { "menuStep.Backward", True },
2759 { "menuStep.Forward to End", True },
2760 { "menuStep.Back to Start", True },
2761 { "menuStep.Move Now", True },
2762 { "menuStep.Truncate Game", True },
2766 Enables machineThinkingEnables[] = {
2767 { "menuFile.Load Game", False },
2768 { "menuFile.Load Next Game", False },
2769 { "menuFile.Load Previous Game", False },
2770 { "menuFile.Reload Same Game", False },
2771 { "menuFile.Paste Game", False },
2772 { "menuFile.Load Position", False },
2773 { "menuFile.Load Next Position", False },
2774 { "menuFile.Load Previous Position", False },
2775 { "menuFile.Reload Same Position", False },
2776 { "menuFile.Paste Position", False },
2777 { "menuMode.Machine White", False },
2778 { "menuMode.Machine Black", False },
2779 { "menuMode.Two Machines", False },
2780 { "menuStep.Retract Move", False },
2784 Enables userThinkingEnables[] = {
2785 { "menuFile.Load Game", True },
2786 { "menuFile.Load Next Game", True },
2787 { "menuFile.Load Previous Game", True },
2788 { "menuFile.Reload Same Game", True },
2789 { "menuFile.Paste Game", True },
2790 { "menuFile.Load Position", True },
2791 { "menuFile.Load Next Position", True },
2792 { "menuFile.Load Previous Position", True },
2793 { "menuFile.Reload Same Position", True },
2794 { "menuFile.Paste Position", True },
2795 { "menuMode.Machine White", True },
2796 { "menuMode.Machine Black", True },
2797 { "menuMode.Two Machines", True },
2798 { "menuStep.Retract Move", True },
2804 SetMenuEnables(icsEnables);
2810 SetMenuEnables(ncpEnables);
2816 SetMenuEnables(gnuEnables);
2822 SetMenuEnables(cmailEnables);
2828 SetMenuEnables(trainingOnEnables);
2829 if (appData.showButtonBar) {
2830 XtSetSensitive(buttonBarWidget, False);
2836 SetTrainingModeOff()
2838 SetMenuEnables(trainingOffEnables);
2839 if (appData.showButtonBar) {
2840 XtSetSensitive(buttonBarWidget, True);
2845 SetUserThinkingEnables()
2847 if (appData.noChessProgram) return;
2848 SetMenuEnables(userThinkingEnables);
2852 SetMachineThinkingEnables()
2854 if (appData.noChessProgram) return;
2855 SetMenuEnables(machineThinkingEnables);
2857 case MachinePlaysBlack:
2858 case MachinePlaysWhite:
2859 case TwoMachinesPlay:
2860 XtSetSensitive(XtNameToWidget(menuBarWidget,
2861 ModeToWidgetName(gameMode)), True);
2868 #define Abs(n) ((n)<0 ? -(n) : (n))
2871 * Find a font that matches "pattern" that is as close as
2872 * possible to the targetPxlSize. Prefer fonts that are k
2873 * pixels smaller to fonts that are k pixels larger. The
2874 * pattern must be in the X Consortium standard format,
2875 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2876 * The return value should be freed with XtFree when no
2879 char *FindFont(pattern, targetPxlSize)
2883 char **fonts, *p, *best, *scalable, *scalableTail;
2884 int i, j, nfonts, minerr, err, pxlSize;
2887 char **missing_list;
2889 char *def_string, *base_fnt_lst, strInt[3];
2891 XFontStruct **fnt_list;
2893 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2894 sprintf(strInt, "%d", targetPxlSize);
2895 p = strstr(pattern, "--");
2896 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2897 strcat(base_fnt_lst, strInt);
2898 strcat(base_fnt_lst, strchr(p + 2, '-'));
2900 if ((fntSet = XCreateFontSet(xDisplay,
2904 &def_string)) == NULL) {
2906 fprintf(stderr, _("Unable to create font set.\n"));
2910 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2912 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2914 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2915 programName, pattern);
2923 for (i=0; i<nfonts; i++) {
2926 if (*p != '-') continue;
2928 if (*p == NULLCHAR) break;
2929 if (*p++ == '-') j++;
2931 if (j < 7) continue;
2934 scalable = fonts[i];
2937 err = pxlSize - targetPxlSize;
2938 if (Abs(err) < Abs(minerr) ||
2939 (minerr > 0 && err < 0 && -err == minerr)) {
2945 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2946 /* If the error is too big and there is a scalable font,
2947 use the scalable font. */
2948 int headlen = scalableTail - scalable;
2949 p = (char *) XtMalloc(strlen(scalable) + 10);
2950 while (isdigit(*scalableTail)) scalableTail++;
2951 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2953 p = (char *) XtMalloc(strlen(best) + 1);
2956 if (appData.debugMode) {
2957 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2958 pattern, targetPxlSize, p);
2961 if (missing_count > 0)
2962 XFreeStringList(missing_list);
2963 XFreeFontSet(xDisplay, fntSet);
2965 XFreeFontNames(fonts);
2972 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2973 | GCBackground | GCFunction | GCPlaneMask;
2974 XGCValues gc_values;
2977 gc_values.plane_mask = AllPlanes;
2978 gc_values.line_width = lineGap;
2979 gc_values.line_style = LineSolid;
2980 gc_values.function = GXcopy;
2982 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2983 gc_values.background = XBlackPixel(xDisplay, xScreen);
2984 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2986 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2987 gc_values.background = XWhitePixel(xDisplay, xScreen);
2988 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2989 XSetFont(xDisplay, coordGC, coordFontID);
2991 if (appData.monoMode) {
2992 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2993 gc_values.background = XWhitePixel(xDisplay, xScreen);
2994 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2996 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2997 gc_values.background = XBlackPixel(xDisplay, xScreen);
2998 lightSquareGC = wbPieceGC
2999 = XtGetGC(shellWidget, value_mask, &gc_values);
3001 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3002 gc_values.background = XWhitePixel(xDisplay, xScreen);
3003 darkSquareGC = bwPieceGC
3004 = XtGetGC(shellWidget, value_mask, &gc_values);
3006 if (DefaultDepth(xDisplay, xScreen) == 1) {
3007 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3008 gc_values.function = GXcopyInverted;
3009 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3010 gc_values.function = GXcopy;
3011 if (XBlackPixel(xDisplay, xScreen) == 1) {
3012 bwPieceGC = darkSquareGC;
3013 wbPieceGC = copyInvertedGC;
3015 bwPieceGC = copyInvertedGC;
3016 wbPieceGC = lightSquareGC;
3020 gc_values.foreground = highlightSquareColor;
3021 gc_values.background = highlightSquareColor;
3022 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3024 gc_values.foreground = premoveHighlightColor;
3025 gc_values.background = premoveHighlightColor;
3026 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3028 gc_values.foreground = lightSquareColor;
3029 gc_values.background = darkSquareColor;
3030 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3032 gc_values.foreground = darkSquareColor;
3033 gc_values.background = lightSquareColor;
3034 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3036 gc_values.foreground = jailSquareColor;
3037 gc_values.background = jailSquareColor;
3038 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3040 gc_values.foreground = whitePieceColor;
3041 gc_values.background = darkSquareColor;
3042 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3044 gc_values.foreground = whitePieceColor;
3045 gc_values.background = lightSquareColor;
3046 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3048 gc_values.foreground = whitePieceColor;
3049 gc_values.background = jailSquareColor;
3050 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3052 gc_values.foreground = blackPieceColor;
3053 gc_values.background = darkSquareColor;
3054 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3056 gc_values.foreground = blackPieceColor;
3057 gc_values.background = lightSquareColor;
3058 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060 gc_values.foreground = blackPieceColor;
3061 gc_values.background = jailSquareColor;
3062 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3066 void loadXIM(xim, xmask, filename, dest, mask)
3079 fp = fopen(filename, "rb");
3081 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3088 for (y=0; y<h; ++y) {
3089 for (x=0; x<h; ++x) {
3094 XPutPixel(xim, x, y, blackPieceColor);
3096 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3099 XPutPixel(xim, x, y, darkSquareColor);
3101 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3104 XPutPixel(xim, x, y, whitePieceColor);
3106 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3109 XPutPixel(xim, x, y, lightSquareColor);
3111 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3117 /* create Pixmap of piece */
3118 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3120 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3123 /* create Pixmap of clipmask
3124 Note: We assume the white/black pieces have the same
3125 outline, so we make only 6 masks. This is okay
3126 since the XPM clipmask routines do the same. */
3128 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3130 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3133 /* now create the 1-bit version */
3134 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3137 values.foreground = 1;
3138 values.background = 0;
3140 /* Don't use XtGetGC, not read only */
3141 maskGC = XCreateGC(xDisplay, *mask,
3142 GCForeground | GCBackground, &values);
3143 XCopyPlane(xDisplay, temp, *mask, maskGC,
3144 0, 0, squareSize, squareSize, 0, 0, 1);
3145 XFreePixmap(xDisplay, temp);
3149 void CreateXIMPieces()
3154 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3159 /* The XSynchronize calls were copied from CreatePieces.
3160 Not sure if needed, but can't hurt */
3161 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3164 /* temp needed by loadXIM() */
3165 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3166 0, 0, ss, ss, AllPlanes, XYPixmap);
3168 if (strlen(appData.pixmapDirectory) == 0) {
3172 if (appData.monoMode) {
3173 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3177 fprintf(stderr, _("\nLoading XIMs...\n"));
3179 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3180 fprintf(stderr, "%d", piece+1);
3181 for (kind=0; kind<4; kind++) {
3182 fprintf(stderr, ".");
3183 sprintf(buf, "%s/%c%s%u.xim",
3184 ExpandPathName(appData.pixmapDirectory),
3185 ToLower(PieceToChar((ChessSquare)piece)),
3187 ximPieceBitmap[kind][piece] =
3188 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3189 0, 0, ss, ss, AllPlanes, XYPixmap);
3190 if (appData.debugMode)
3191 fprintf(stderr, _("(File:%s:) "), buf);
3192 loadXIM(ximPieceBitmap[kind][piece],
3194 &(xpmPieceBitmap[kind][piece]),
3195 &(ximMaskPm[piece%6]));
3197 fprintf(stderr," ");
3199 /* Load light and dark squares */
3200 /* If the LSQ and DSQ pieces don't exist, we will
3201 draw them with solid squares. */
3202 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3203 if (access(buf, 0) != 0) {
3207 fprintf(stderr, _("light square "));
3209 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3210 0, 0, ss, ss, AllPlanes, XYPixmap);
3211 if (appData.debugMode)
3212 fprintf(stderr, _("(File:%s:) "), buf);
3214 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3215 fprintf(stderr, _("dark square "));
3216 sprintf(buf, "%s/dsq%u.xim",
3217 ExpandPathName(appData.pixmapDirectory), ss);
3218 if (appData.debugMode)
3219 fprintf(stderr, _("(File:%s:) "), buf);
3221 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3222 0, 0, ss, ss, AllPlanes, XYPixmap);
3223 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3224 xpmJailSquare = xpmLightSquare;
3226 fprintf(stderr, _("Done.\n"));
3228 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3232 void CreateXPMPieces()
3236 u_int ss = squareSize;
3238 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3239 XpmColorSymbol symbols[4];
3242 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3243 if (appData.debugMode) {
3244 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3245 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3249 /* The XSynchronize calls were copied from CreatePieces.
3250 Not sure if needed, but can't hurt */
3251 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3253 /* Setup translations so piece colors match square colors */
3254 symbols[0].name = "light_piece";
3255 symbols[0].value = appData.whitePieceColor;
3256 symbols[1].name = "dark_piece";
3257 symbols[1].value = appData.blackPieceColor;
3258 symbols[2].name = "light_square";
3259 symbols[2].value = appData.lightSquareColor;
3260 symbols[3].name = "dark_square";
3261 symbols[3].value = appData.darkSquareColor;
3263 attr.valuemask = XpmColorSymbols;
3264 attr.colorsymbols = symbols;
3265 attr.numsymbols = 4;
3267 if (appData.monoMode) {
3268 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3272 if (strlen(appData.pixmapDirectory) == 0) {
3273 XpmPieces* pieces = builtInXpms;
3276 while (pieces->size != squareSize && pieces->size) pieces++;
3277 if (!pieces->size) {
3278 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3281 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3282 for (kind=0; kind<4; kind++) {
3284 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3285 pieces->xpm[piece][kind],
3286 &(xpmPieceBitmap[kind][piece]),
3287 NULL, &attr)) != 0) {
3288 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3295 xpmJailSquare = xpmLightSquare;
3299 fprintf(stderr, _("\nLoading XPMs...\n"));
3302 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3303 fprintf(stderr, "%d ", piece+1);
3304 for (kind=0; kind<4; kind++) {
3305 sprintf(buf, "%s/%c%s%u.xpm",
3306 ExpandPathName(appData.pixmapDirectory),
3307 ToLower(PieceToChar((ChessSquare)piece)),
3309 if (appData.debugMode) {
3310 fprintf(stderr, _("(File:%s:) "), buf);
3312 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3313 &(xpmPieceBitmap[kind][piece]),
3314 NULL, &attr)) != 0) {
3315 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3321 /* Load light and dark squares */
3322 /* If the LSQ and DSQ pieces don't exist, we will
3323 draw them with solid squares. */
3324 fprintf(stderr, _("light square "));
3325 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3326 if (access(buf, 0) != 0) {
3330 if (appData.debugMode)
3331 fprintf(stderr, _("(File:%s:) "), buf);
3333 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3334 &xpmLightSquare, NULL, &attr)) != 0) {
3335 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3338 fprintf(stderr, _("dark square "));
3339 sprintf(buf, "%s/dsq%u.xpm",
3340 ExpandPathName(appData.pixmapDirectory), ss);
3341 if (appData.debugMode) {
3342 fprintf(stderr, _("(File:%s:) "), buf);
3344 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3345 &xpmDarkSquare, NULL, &attr)) != 0) {
3346 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3350 xpmJailSquare = xpmLightSquare;
3351 fprintf(stderr, _("Done.\n"));
3353 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3356 #endif /* HAVE_LIBXPM */
3359 /* No built-in bitmaps */
3364 u_int ss = squareSize;
3366 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3369 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3370 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3371 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3372 ss, kind == SOLID ? 's' : 'o');
3373 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3377 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3381 /* With built-in bitmaps */
3384 BuiltInBits* bib = builtInBits;
3387 u_int ss = squareSize;
3389 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3392 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3394 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3395 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3396 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3397 ss, kind == SOLID ? 's' : 'o');
3398 ReadBitmap(&pieceBitmap[kind][piece], buf,
3399 bib->bits[kind][piece], ss, ss);
3403 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3408 void ReadBitmap(pm, name, bits, wreq, hreq)
3411 unsigned char bits[];
3417 char msg[MSG_SIZ], fullname[MSG_SIZ];
3419 if (*appData.bitmapDirectory != NULLCHAR) {
3420 strcpy(fullname, appData.bitmapDirectory);
3421 strcat(fullname, "/");
3422 strcat(fullname, name);
3423 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3424 &w, &h, pm, &x_hot, &y_hot);
3425 if (errcode != BitmapSuccess) {
3427 case BitmapOpenFailed:
3428 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3430 case BitmapFileInvalid:
3431 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3433 case BitmapNoMemory:
3434 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3438 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3442 fprintf(stderr, _("%s: %s...using built-in\n"),
3444 } else if (w != wreq || h != hreq) {
3446 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3447 programName, fullname, w, h, wreq, hreq);
3453 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3457 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3466 if (lineGap == 0) return;
3467 for (i = 0; i < BOARD_SIZE + 1; i++) {
3468 gridSegments[i].x1 = 0;
3469 gridSegments[i].x2 =
3470 lineGap + BOARD_SIZE * (squareSize + lineGap);
3471 gridSegments[i].y1 = gridSegments[i].y2
3472 = lineGap / 2 + (i * (squareSize + lineGap));
3474 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3475 gridSegments[i + BOARD_SIZE + 1].y2 =
3476 BOARD_SIZE * (squareSize + lineGap);
3477 gridSegments[i + BOARD_SIZE + 1].x1 =
3478 gridSegments[i + BOARD_SIZE + 1].x2
3479 = lineGap / 2 + (i * (squareSize + lineGap));
3483 static void MenuBarSelect(w, addr, index)
3488 XtActionProc proc = (XtActionProc) addr;
3490 (proc)(NULL, NULL, NULL, NULL);
3493 void CreateMenuBarPopup(parent, name, mb)
3503 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3506 XtSetArg(args[j], XtNleftMargin, 20); j++;
3507 XtSetArg(args[j], XtNrightMargin, 20); j++;
3509 while (mi->string != NULL) {
3510 if (strcmp(mi->string, "----") == 0) {
3511 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3514 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3515 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3517 XtAddCallback(entry, XtNcallback,
3518 (XtCallbackProc) MenuBarSelect,
3519 (caddr_t) mi->proc);
3525 Widget CreateMenuBar(mb)
3529 Widget anchor, menuBar;
3531 char menuName[MSG_SIZ];
3534 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3535 XtSetArg(args[j], XtNvSpace, 0); j++;
3536 XtSetArg(args[j], XtNborderWidth, 0); j++;
3537 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3538 formWidget, args, j);
3540 while (mb->name != NULL) {
3541 strcpy(menuName, "menu");
3542 strcat(menuName, mb->name);
3544 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3547 shortName[0] = _(mb->name)[0];
3548 shortName[1] = NULLCHAR;
3549 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3552 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3555 XtSetArg(args[j], XtNborderWidth, 0); j++;
3556 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3558 CreateMenuBarPopup(menuBar, menuName, mb);
3564 Widget CreateButtonBar(mi)
3568 Widget button, buttonBar;
3572 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3574 XtSetArg(args[j], XtNhSpace, 0); j++;
3576 XtSetArg(args[j], XtNborderWidth, 0); j++;
3577 XtSetArg(args[j], XtNvSpace, 0); j++;
3578 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3579 formWidget, args, j);
3581 while (mi->string != NULL) {
3584 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3585 XtSetArg(args[j], XtNborderWidth, 0); j++;
3587 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3588 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3589 buttonBar, args, j);
3590 XtAddCallback(button, XtNcallback,
3591 (XtCallbackProc) MenuBarSelect,
3592 (caddr_t) mi->proc);
3599 CreatePieceMenu(name, color)
3606 ChessSquare selection;
3608 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3609 boardWidget, args, 0);
3611 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3612 String item = pieceMenuStrings[color][i];
3614 if (strcmp(item, "----") == 0) {
3615 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3618 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3619 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3621 selection = pieceMenuTranslation[color][i];
3622 XtAddCallback(entry, XtNcallback,
3623 (XtCallbackProc) PieceMenuSelect,
3624 (caddr_t) selection);
3625 if (selection == WhitePawn || selection == BlackPawn) {
3626 XtSetArg(args[0], XtNpopupOnEntry, entry);
3627 XtSetValues(menu, args, 1);
3640 ChessSquare selection;
3642 whitePieceMenu = CreatePieceMenu("menuW", 0);
3643 blackPieceMenu = CreatePieceMenu("menuB", 1);
3645 XtRegisterGrabAction(PieceMenuPopup, True,
3646 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3647 GrabModeAsync, GrabModeAsync);
3649 XtSetArg(args[0], XtNlabel, _("Drop"));
3650 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3651 boardWidget, args, 1);
3652 for (i = 0; i < DROP_MENU_SIZE; i++) {
3653 String item = dropMenuStrings[i];
3655 if (strcmp(item, "----") == 0) {
3656 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3659 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3660 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3662 selection = dropMenuTranslation[i];
3663 XtAddCallback(entry, XtNcallback,
3664 (XtCallbackProc) DropMenuSelect,
3665 (caddr_t) selection);
3670 void SetupDropMenu()
3678 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3679 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3680 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3681 dmEnables[i].piece);
3682 XtSetSensitive(entry, p != NULL || !appData.testLegality
3683 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3684 && !appData.icsActive));
3686 while (p && *p++ == dmEnables[i].piece) count++;
3687 sprintf(label, "%s %d", dmEnables[i].widget, count);
3689 XtSetArg(args[j], XtNlabel, label); j++;
3690 XtSetValues(entry, args, j);
3694 void PieceMenuPopup(w, event, params, num_params)
3698 Cardinal *num_params;
3701 if (event->type != ButtonPress) return;
3702 if (errorUp) ErrorPopDown();
3706 whichMenu = params[0];
3708 case IcsPlayingWhite:
3709 case IcsPlayingBlack:
3711 case MachinePlaysWhite:
3712 case MachinePlaysBlack:
3713 if (appData.testLegality &&
3714 gameInfo.variant != VariantBughouse &&
3715 gameInfo.variant != VariantCrazyhouse) return;
3717 whichMenu = "menuD";
3723 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3724 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3725 pmFromX = pmFromY = -1;
3729 pmFromX = BOARD_SIZE - 1 - pmFromX;
3731 pmFromY = BOARD_SIZE - 1 - pmFromY;
3733 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3736 static void PieceMenuSelect(w, piece, junk)
3741 if (pmFromX < 0 || pmFromY < 0) return;
3742 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3745 static void DropMenuSelect(w, piece, junk)
3750 if (pmFromX < 0 || pmFromY < 0) return;
3751 DropMenuEvent(piece, pmFromX, pmFromY);
3754 void WhiteClock(w, event, prms, nprms)
3760 if (gameMode == EditPosition || gameMode == IcsExamining) {
3761 SetWhiteToPlayEvent();
3762 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3767 void BlackClock(w, event, prms, nprms)
3773 if (gameMode == EditPosition || gameMode == IcsExamining) {
3774 SetBlackToPlayEvent();
3775 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3782 * If the user selects on a border boundary, return -1; if off the board,
3783 * return -2. Otherwise map the event coordinate to the square.
3785 int EventToSquare(x, limit)
3793 if ((x % (squareSize + lineGap)) >= squareSize)
3795 x /= (squareSize + lineGap);
3801 static void do_flash_delay(msec)
3807 static void drawHighlight(file, rank, gc)
3813 if (lineGap == 0 || appData.blindfold) return;
3816 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3817 (squareSize + lineGap);
3818 y = lineGap/2 + rank * (squareSize + lineGap);
3820 x = lineGap/2 + file * (squareSize + lineGap);
3821 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3822 (squareSize + lineGap);
3825 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3826 squareSize+lineGap, squareSize+lineGap);
3829 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3830 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3833 SetHighlights(fromX, fromY, toX, toY)
3834 int fromX, fromY, toX, toY;
3836 if (hi1X != fromX || hi1Y != fromY) {
3837 if (hi1X >= 0 && hi1Y >= 0) {
3838 drawHighlight(hi1X, hi1Y, lineGC);
3840 if (fromX >= 0 && fromY >= 0) {
3841 drawHighlight(fromX, fromY, highlineGC);
3844 if (hi2X != toX || hi2Y != toY) {
3845 if (hi2X >= 0 && hi2Y >= 0) {
3846 drawHighlight(hi2X, hi2Y, lineGC);
3848 if (toX >= 0 && toY >= 0) {
3849 drawHighlight(toX, toY, highlineGC);
3861 SetHighlights(-1, -1, -1, -1);
3866 SetPremoveHighlights(fromX, fromY, toX, toY)
3867 int fromX, fromY, toX, toY;
3869 if (pm1X != fromX || pm1Y != fromY) {
3870 if (pm1X >= 0 && pm1Y >= 0) {
3871 drawHighlight(pm1X, pm1Y, lineGC);
3873 if (fromX >= 0 && fromY >= 0) {
3874 drawHighlight(fromX, fromY, prelineGC);
3877 if (pm2X != toX || pm2Y != toY) {
3878 if (pm2X >= 0 && pm2Y >= 0) {
3879 drawHighlight(pm2X, pm2Y, lineGC);
3881 if (toX >= 0 && toY >= 0) {
3882 drawHighlight(toX, toY, prelineGC);
3892 ClearPremoveHighlights()
3894 SetPremoveHighlights(-1, -1, -1, -1);
3897 static void BlankSquare(x, y, color, piece, dest)
3902 if (useImages && useImageSqs) {
3906 pm = xpmLightSquare;
3911 case 2: /* neutral */
3916 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3917 squareSize, squareSize, x, y);
3927 case 2: /* neutral */
3932 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3937 I split out the routines to draw a piece so that I could
3938 make a generic flash routine.
3940 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3942 int square_color, x, y;
3945 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3946 switch (square_color) {
3948 case 2: /* neutral */
3950 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3951 ? *pieceToOutline(piece)
3952 : *pieceToSolid(piece),
3953 dest, bwPieceGC, 0, 0,
3954 squareSize, squareSize, x, y);
3957 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3958 ? *pieceToSolid(piece)
3959 : *pieceToOutline(piece),
3960 dest, wbPieceGC, 0, 0,
3961 squareSize, squareSize, x, y);
3966 static void monoDrawPiece(piece, square_color, x, y, dest)
3968 int square_color, x, y;
3971 switch (square_color) {
3973 case 2: /* neutral */
3975 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3976 ? *pieceToOutline(piece)
3977 : *pieceToSolid(piece),
3978 dest, bwPieceGC, 0, 0,
3979 squareSize, squareSize, x, y, 1);
3982 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3983 ? *pieceToSolid(piece)
3984 : *pieceToOutline(piece),
3985 dest, wbPieceGC, 0, 0,
3986 squareSize, squareSize, x, y, 1);
3991 static void colorDrawPiece(piece, square_color, x, y, dest)
3993 int square_color, x, y;
3996 switch (square_color) {
3998 XCopyPlane(xDisplay, *pieceToSolid(piece),
3999 dest, (int) piece < (int) BlackPawn
4000 ? wlPieceGC : blPieceGC, 0, 0,
4001 squareSize, squareSize, x, y, 1);
4004 XCopyPlane(xDisplay, *pieceToSolid(piece),
4005 dest, (int) piece < (int) BlackPawn
4006 ? wdPieceGC : bdPieceGC, 0, 0,
4007 squareSize, squareSize, x, y, 1);
4009 case 2: /* neutral */
4011 XCopyPlane(xDisplay, *pieceToSolid(piece),
4012 dest, (int) piece < (int) BlackPawn
4013 ? wjPieceGC : bjPieceGC, 0, 0,
4014 squareSize, squareSize, x, y, 1);
4019 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4021 int square_color, x, y;
4026 switch (square_color) {
4028 case 2: /* neutral */
4030 if ((int)piece < (int) BlackPawn) {
4038 if ((int)piece < (int) BlackPawn) {
4046 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4047 dest, wlPieceGC, 0, 0,
4048 squareSize, squareSize, x, y);
4051 typedef void (*DrawFunc)();
4053 DrawFunc ChooseDrawFunc()
4055 if (appData.monoMode) {
4056 if (DefaultDepth(xDisplay, xScreen) == 1) {
4057 return monoDrawPiece_1bit;
4059 return monoDrawPiece;
4063 return colorDrawPieceImage;
4065 return colorDrawPiece;
4069 void DrawSquare(row, column, piece, do_flash)
4070 int row, column, do_flash;
4073 int square_color, x, y, direction, font_ascent, font_descent;
4076 XCharStruct overall;
4080 /* Calculate delay in milliseconds (2-delays per complete flash) */
4081 flash_delay = 500 / appData.flashRate;
4084 x = lineGap + ((BOARD_SIZE-1)-column) *
4085 (squareSize + lineGap);
4086 y = lineGap + row * (squareSize + lineGap);
4088 x = lineGap + column * (squareSize + lineGap);
4089 y = lineGap + ((BOARD_SIZE-1)-row) *
4090 (squareSize + lineGap);
4093 square_color = ((column + row) % 2) == 1;
4095 if (piece == EmptySquare || appData.blindfold) {
4096 BlankSquare(x, y, square_color, piece, xBoardWindow);
4098 drawfunc = ChooseDrawFunc();
4099 if (do_flash && appData.flashCount > 0) {
4100 for (i=0; i<appData.flashCount; ++i) {
4102 drawfunc(piece, square_color, x, y, xBoardWindow);
4103 XSync(xDisplay, False);
4104 do_flash_delay(flash_delay);
4106 BlankSquare(x, y, square_color, piece, xBoardWindow);
4107 XSync(xDisplay, False);
4108 do_flash_delay(flash_delay);
4111 drawfunc(piece, square_color, x, y, xBoardWindow);
4114 string[1] = NULLCHAR;
4115 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4116 string[0] = 'a' + column;
4117 XTextExtents(coordFontStruct, string, 1, &direction,
4118 &font_ascent, &font_descent, &overall);
4119 if (appData.monoMode) {
4120 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4121 x + squareSize - overall.width - 2,
4122 y + squareSize - font_descent - 1, string, 1);
4124 XDrawString(xDisplay, xBoardWindow, coordGC,
4125 x + squareSize - overall.width - 2,
4126 y + squareSize - font_descent - 1, string, 1);
4129 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4130 string[0] = '1' + row;
4131 XTextExtents(coordFontStruct, string, 1, &direction,
4132 &font_ascent, &font_descent, &overall);
4133 if (appData.monoMode) {
4134 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4135 x + 2, y + font_ascent + 1, string, 1);
4137 XDrawString(xDisplay, xBoardWindow, coordGC,
4138 x + 2, y + font_ascent + 1, string, 1);
4144 /* Why is this needed on some versions of X? */
4145 void EventProc(widget, unused, event)
4150 if (!XtIsRealized(widget))
4153 switch (event->type) {
4155 if (event->xexpose.count > 0) return; /* no clipping is done */
4156 XDrawPosition(widget, True, NULL);
4164 void DrawPosition(fullRedraw, board)
4165 /*Boolean*/int fullRedraw;
4168 XDrawPosition(boardWidget, fullRedraw, board);
4171 /* Returns 1 if there are "too many" differences between b1 and b2
4172 (i.e. more than 1 move was made) */
4173 static int too_many_diffs(b1, b2)
4179 for (i=0; i<BOARD_SIZE; ++i) {
4180 for (j=0; j<BOARD_SIZE; ++j) {
4181 if (b1[i][j] != b2[i][j]) {
4182 if (++c > 4) /* Castling causes 4 diffs */
4191 /* Matrix describing castling maneuvers */
4192 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4193 static int castling_matrix[4][5] = {
4194 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4195 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4196 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4197 { 7, 7, 4, 5, 6 } /* 0-0, black */
4200 /* Checks whether castling occurred. If it did, *rrow and *rcol
4201 are set to the destination (row,col) of the rook that moved.
4203 Returns 1 if castling occurred, 0 if not.
4205 Note: Only handles a max of 1 castling move, so be sure
4206 to call too_many_diffs() first.
4208 static int check_castle_draw(newb, oldb, rrow, rcol)
4215 /* For each type of castling... */
4216 for (i=0; i<4; ++i) {
4217 r = castling_matrix[i];
4219 /* Check the 4 squares involved in the castling move */
4221 for (j=1; j<=4; ++j) {
4222 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4229 /* All 4 changed, so it must be a castling move */
4238 static int damage[BOARD_SIZE][BOARD_SIZE];
4241 * event handler for redrawing the board
4243 void XDrawPosition(w, repaint, board)
4245 /*Boolean*/int repaint;
4249 static int lastFlipView = 0;
4250 static int lastBoardValid = 0;
4251 static Board lastBoard;
4255 if (board == NULL) {
4256 if (!lastBoardValid) return;
4259 if (!lastBoardValid || lastFlipView != flipView) {
4260 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4261 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4266 * It would be simpler to clear the window with XClearWindow()
4267 * but this causes a very distracting flicker.
4270 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4272 /* If too much changes (begin observing new game, etc.), don't
4274 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4276 /* Special check for castling so we don't flash both the king
4277 and the rook (just flash the king). */
4279 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4280 /* Draw rook with NO flashing. King will be drawn flashing later */
4281 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4282 lastBoard[rrow][rcol] = board[rrow][rcol];
4286 /* First pass -- Draw (newly) empty squares and repair damage.
4287 This prevents you from having a piece show up twice while it
4288 is flashing on its new square */
4289 for (i = 0; i < BOARD_SIZE; i++)
4290 for (j = 0; j < BOARD_SIZE; j++)
4291 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4293 DrawSquare(i, j, board[i][j], 0);
4294 damage[i][j] = False;
4297 /* Second pass -- Draw piece(s) in new position and flash them */
4298 for (i = 0; i < BOARD_SIZE; i++)
4299 for (j = 0; j < BOARD_SIZE; j++)
4300 if (board[i][j] != lastBoard[i][j]) {
4301 DrawSquare(i, j, board[i][j], do_flash);
4305 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4306 gridSegments, (BOARD_SIZE + 1) * 2);
4308 for (i = 0; i < BOARD_SIZE; i++)
4309 for (j = 0; j < BOARD_SIZE; j++) {
4310 DrawSquare(i, j, board[i][j], 0);
4311 damage[i][j] = False;
4315 CopyBoard(lastBoard, board);
4317 lastFlipView = flipView;
4319 /* Draw highlights */
4320 if (pm1X >= 0 && pm1Y >= 0) {
4321 drawHighlight(pm1X, pm1Y, prelineGC);
4323 if (pm2X >= 0 && pm2Y >= 0) {
4324 drawHighlight(pm2X, pm2Y, prelineGC);
4326 if (hi1X >= 0 && hi1Y >= 0) {
4327 drawHighlight(hi1X, hi1Y, highlineGC);
4329 if (hi2X >= 0 && hi2Y >= 0) {
4330 drawHighlight(hi2X, hi2Y, highlineGC);
4333 /* If piece being dragged around board, must redraw that too */
4336 XSync(xDisplay, False);
4341 * event handler for redrawing the board
4343 void DrawPositionProc(w, event, prms, nprms)
4349 XDrawPosition(w, True, NULL);
4354 * event handler for parsing user moves
4356 void HandleUserMove(w, event, prms, nprms)
4363 Boolean saveAnimate;
4364 static int second = 0;
4366 if (w != boardWidget || errorExitStatus != -1) return;
4368 if (event->type == ButtonPress) ErrorPopDown();
4371 if (event->type == ButtonPress) {
4372 XtPopdown(promotionShell);
4373 XtDestroyWidget(promotionShell);
4374 promotionUp = False;
4382 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4383 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4384 if (!flipView && y >= 0) {
4385 y = BOARD_SIZE - 1 - y;
4387 if (flipView && x >= 0) {
4388 x = BOARD_SIZE - 1 - x;
4392 if (event->type == ButtonPress) {
4394 if (OKToStartUserMove(x, y)) {
4398 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4399 if (appData.highlightDragging) {
4400 SetHighlights(x, y, -1, -1);
4408 if (event->type == ButtonPress && gameMode != EditPosition &&
4412 /* Check if clicking again on the same color piece */
4413 fromP = boards[currentMove][fromY][fromX];
4414 toP = boards[currentMove][y][x];
4415 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4416 WhitePawn <= toP && toP <= WhiteKing) ||
4417 (BlackPawn <= fromP && fromP <= BlackKing &&
4418 BlackPawn <= toP && toP <= BlackKing)) {
4419 /* Clicked again on same color piece -- changed his mind */
4420 second = (x == fromX && y == fromY);
4421 if (appData.highlightDragging) {
4422 SetHighlights(x, y, -1, -1);
4426 if (OKToStartUserMove(x, y)) {
4429 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4435 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4436 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4437 if (appData.animateDragging) {
4438 /* Undo animation damage if any */
4439 DrawPosition(FALSE, NULL);
4442 /* Second up/down in same square; just abort move */
4447 ClearPremoveHighlights();
4449 /* First upclick in same square; start click-click mode */
4450 SetHighlights(x, y, -1, -1);
4455 /* Completed move */
4458 saveAnimate = appData.animate;
4459 if (event->type == ButtonPress) {
4460 /* Finish clickclick move */
4461 if (appData.animate || appData.highlightLastMove) {
4462 SetHighlights(fromX, fromY, toX, toY);
4467 /* Finish drag move */
4468 if (appData.highlightLastMove) {
4469 SetHighlights(fromX, fromY, toX, toY);
4473 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4474 /* Don't animate move and drag both */
4475 appData.animate = FALSE;
4477 if (IsPromotion(fromX, fromY, toX, toY)) {
4478 if (appData.alwaysPromoteToQueen) {
4479 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4480 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4481 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4484 SetHighlights(fromX, fromY, toX, toY);
4488 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4489 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4490 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4493 appData.animate = saveAnimate;
4494 if (appData.animate || appData.animateDragging) {
4495 /* Undo animation damage if needed */
4496 DrawPosition(FALSE, NULL);
4500 void AnimateUserMove (Widget w, XEvent * event,
4501 String * params, Cardinal * nParams)
4503 DragPieceMove(event->xmotion.x, event->xmotion.y);
4506 Widget CommentCreate(name, text, mutable, callback, lines)
4508 int /*Boolean*/ mutable;
4509 XtCallbackProc callback;
4513 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4518 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4519 XtGetValues(boardWidget, args, j);
4522 XtSetArg(args[j], XtNresizable, True); j++;
4525 XtCreatePopupShell(name, topLevelShellWidgetClass,
4526 shellWidget, args, j);
4529 XtCreatePopupShell(name, transientShellWidgetClass,
4530 shellWidget, args, j);
4533 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4534 layoutArgs, XtNumber(layoutArgs));
4536 XtCreateManagedWidget("form", formWidgetClass, layout,
4537 formArgs, XtNumber(formArgs));
4541 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4542 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4544 XtSetArg(args[j], XtNstring, text); j++;
4545 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4546 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4547 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4548 XtSetArg(args[j], XtNright, XtChainRight); j++;
4549 XtSetArg(args[j], XtNresizable, True); j++;
4550 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4552 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4554 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4555 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4557 XtSetArg(args[j], XtNautoFill, True); j++;
4558 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4560 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4564 XtSetArg(args[j], XtNfromVert, edit); j++;
4565 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4566 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4567 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4568 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4570 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4571 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4574 XtSetArg(args[j], XtNfromVert, edit); j++;
4575 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4576 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4577 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4578 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4579 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4581 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4582 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4585 XtSetArg(args[j], XtNfromVert, edit); j++;
4586 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4587 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4588 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4589 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4590 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4592 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4593 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4596 XtSetArg(args[j], XtNfromVert, edit); j++;
4597 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4598 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4599 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4600 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4602 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4603 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4606 XtSetArg(args[j], XtNfromVert, edit); j++;
4607 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4608 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4609 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4610 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4611 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4613 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4614 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4617 XtRealizeWidget(shell);
4619 if (commentX == -1) {
4622 Dimension pw_height;
4623 Dimension ew_height;
4626 XtSetArg(args[j], XtNheight, &ew_height); j++;
4627 XtGetValues(edit, args, j);
4630 XtSetArg(args[j], XtNheight, &pw_height); j++;
4631 XtGetValues(shell, args, j);
4632 commentH = pw_height + (lines - 1) * ew_height;
4633 commentW = bw_width - 16;
4635 XSync(xDisplay, False);
4637 /* This code seems to tickle an X bug if it is executed too soon
4638 after xboard starts up. The coordinates get transformed as if
4639 the main window was positioned at (0, 0).
4641 XtTranslateCoords(shellWidget,
4642 (bw_width - commentW) / 2, 0 - commentH / 2,
4643 &commentX, &commentY);
4645 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4646 RootWindowOfScreen(XtScreen(shellWidget)),
4647 (bw_width - commentW) / 2, 0 - commentH / 2,
4652 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4655 XtSetArg(args[j], XtNheight, commentH); j++;
4656 XtSetArg(args[j], XtNwidth, commentW); j++;
4657 XtSetArg(args[j], XtNx, commentX); j++;
4658 XtSetArg(args[j], XtNy, commentY); j++;
4659 XtSetValues(shell, args, j);
4660 XtSetKeyboardFocus(shell, edit);
4665 /* Used for analysis window and ICS input window */
4666 Widget MiscCreate(name, text, mutable, callback, lines)
4668 int /*Boolean*/ mutable;
4669 XtCallbackProc callback;
4673 Widget shell, layout, form, edit;
4675 Dimension bw_width, pw_height, ew_height, w, h;
4681 XtSetArg(args[j], XtNresizable, True); j++;
4684 XtCreatePopupShell(name, topLevelShellWidgetClass,
4685 shellWidget, args, j);
4688 XtCreatePopupShell(name, transientShellWidgetClass,
4689 shellWidget, args, j);
4692 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4693 layoutArgs, XtNumber(layoutArgs));
4695 XtCreateManagedWidget("form", formWidgetClass, layout,
4696 formArgs, XtNumber(formArgs));
4700 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4701 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4703 XtSetArg(args[j], XtNstring, text); j++;
4704 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4705 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4706 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4707 XtSetArg(args[j], XtNright, XtChainRight); j++;
4708 XtSetArg(args[j], XtNresizable, True); j++;
4710 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4712 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4713 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4715 XtSetArg(args[j], XtNautoFill, True); j++;
4716 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4718 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4720 XtRealizeWidget(shell);
4723 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4724 XtGetValues(boardWidget, args, j);
4727 XtSetArg(args[j], XtNheight, &ew_height); j++;
4728 XtGetValues(edit, args, j);
4731 XtSetArg(args[j], XtNheight, &pw_height); j++;
4732 XtGetValues(shell, args, j);
4733 h = pw_height + (lines - 1) * ew_height;
4736 XSync(xDisplay, False);
4738 /* This code seems to tickle an X bug if it is executed too soon
4739 after xboard starts up. The coordinates get transformed as if
4740 the main window was positioned at (0, 0).
4742 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4744 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4745 RootWindowOfScreen(XtScreen(shellWidget)),
4746 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4750 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4753 XtSetArg(args[j], XtNheight, h); j++;
4754 XtSetArg(args[j], XtNwidth, w); j++;
4755 XtSetArg(args[j], XtNx, x); j++;
4756 XtSetArg(args[j], XtNy, y); j++;
4757 XtSetValues(shell, args, j);
4763 static int savedIndex; /* gross that this is global */
4765 void EditCommentPopUp(index, title, text)
4774 if (text == NULL) text = "";
4776 if (editShell == NULL) {
4778 CommentCreate(title, text, True, EditCommentCallback, 4);
4779 XtRealizeWidget(editShell);
4780 CatchDeleteWindow(editShell, "EditCommentPopDown");
4782 edit = XtNameToWidget(editShell, "*form.text");
4784 XtSetArg(args[j], XtNstring, text); j++;
4785 XtSetValues(edit, args, j);
4787 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4788 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4789 XtSetValues(editShell, args, j);
4792 XtPopup(editShell, XtGrabNone);
4796 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4797 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4801 void EditCommentCallback(w, client_data, call_data)
4803 XtPointer client_data, call_data;
4811 XtSetArg(args[j], XtNlabel, &name); j++;
4812 XtGetValues(w, args, j);
4814 if (strcmp(name, _("ok")) == 0) {
4815 edit = XtNameToWidget(editShell, "*form.text");
4817 XtSetArg(args[j], XtNstring, &val); j++;
4818 XtGetValues(edit, args, j);
4819 ReplaceComment(savedIndex, val);
4820 EditCommentPopDown();
4821 } else if (strcmp(name, _("cancel")) == 0) {
4822 EditCommentPopDown();
4823 } else if (strcmp(name, _("clear")) == 0) {
4824 edit = XtNameToWidget(editShell, "*form.text");
4825 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4826 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4830 void EditCommentPopDown()
4835 if (!editUp) return;
4837 XtSetArg(args[j], XtNx, &commentX); j++;
4838 XtSetArg(args[j], XtNy, &commentY); j++;
4839 XtSetArg(args[j], XtNheight, &commentH); j++;
4840 XtSetArg(args[j], XtNwidth, &commentW); j++;
4841 XtGetValues(editShell, args, j);
4842 XtPopdown(editShell);
4845 XtSetArg(args[j], XtNleftBitmap, None); j++;
4846 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4850 void ICSInputBoxPopUp()
4855 char *title = _("ICS Input");
4858 if (ICSInputShell == NULL) {
4859 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4860 tr = XtParseTranslationTable(ICSInputTranslations);
4861 edit = XtNameToWidget(ICSInputShell, "*form.text");
4862 XtOverrideTranslations(edit, tr);
4863 XtRealizeWidget(ICSInputShell);
4864 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4867 edit = XtNameToWidget(ICSInputShell, "*form.text");
4869 XtSetArg(args[j], XtNstring, ""); j++;
4870 XtSetValues(edit, args, j);
4872 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4873 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4874 XtSetValues(ICSInputShell, args, j);
4877 XtPopup(ICSInputShell, XtGrabNone);
4878 XtSetKeyboardFocus(ICSInputShell, edit);
4880 ICSInputBoxUp = True;
4882 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4883 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4887 void ICSInputSendText()
4894 edit = XtNameToWidget(ICSInputShell, "*form.text");
4896 XtSetArg(args[j], XtNstring, &val); j++;
4897 XtGetValues(edit, args, j);
4898 SendMultiLineToICS(val);
4899 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4900 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4903 void ICSInputBoxPopDown()
4908 if (!ICSInputBoxUp) return;
4910 XtPopdown(ICSInputShell);
4911 ICSInputBoxUp = False;
4913 XtSetArg(args[j], XtNleftBitmap, None); j++;
4914 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4918 void CommentPopUp(title, text)
4925 if (commentShell == NULL) {
4927 CommentCreate(title, text, False, CommentCallback, 4);
4928 XtRealizeWidget(commentShell);
4929 CatchDeleteWindow(commentShell, "CommentPopDown");
4931 edit = XtNameToWidget(commentShell, "*form.text");
4933 XtSetArg(args[j], XtNstring, text); j++;
4934 XtSetValues(edit, args, j);
4936 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4937 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4938 XtSetValues(commentShell, args, j);
4941 XtPopup(commentShell, XtGrabNone);
4942 XSync(xDisplay, False);
4947 void AnalysisPopUp(title, text)
4954 if (analysisShell == NULL) {
4955 analysisShell = MiscCreate(title, text, False, NULL, 4);
4956 XtRealizeWidget(analysisShell);
4957 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4960 edit = XtNameToWidget(analysisShell, "*form.text");
4962 XtSetArg(args[j], XtNstring, text); j++;
4963 XtSetValues(edit, args, j);
4965 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4966 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4967 XtSetValues(analysisShell, args, j);
4971 XtPopup(analysisShell, XtGrabNone);
4973 XSync(xDisplay, False);
4978 void CommentCallback(w, client_data, call_data)
4980 XtPointer client_data, call_data;
4987 XtSetArg(args[j], XtNlabel, &name); j++;
4988 XtGetValues(w, args, j);
4990 if (strcmp(name, _("close")) == 0) {
4992 } else if (strcmp(name, _("edit")) == 0) {
4999 void CommentPopDown()
5004 if (!commentUp) return;
5006 XtSetArg(args[j], XtNx, &commentX); j++;
5007 XtSetArg(args[j], XtNy, &commentY); j++;
5008 XtSetArg(args[j], XtNwidth, &commentW); j++;
5009 XtSetArg(args[j], XtNheight, &commentH); j++;
5010 XtGetValues(commentShell, args, j);
5011 XtPopdown(commentShell);
5012 XSync(xDisplay, False);
5016 void AnalysisPopDown()
5018 if (!analysisUp) return;
5019 XtPopdown(analysisShell);
5020 XSync(xDisplay, False);
5025 void FileNamePopUp(label, def, proc, openMode)
5032 Widget popup, layout, dialog, edit;
5038 fileProc = proc; /* I can't see a way not */
5039 fileOpenMode = openMode; /* to use globals here */
5042 XtSetArg(args[i], XtNresizable, True); i++;
5043 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5044 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5045 fileNameShell = popup =
5046 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5047 shellWidget, args, i);
5050 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5051 layoutArgs, XtNumber(layoutArgs));
5054 XtSetArg(args[i], XtNlabel, label); i++;
5055 XtSetArg(args[i], XtNvalue, def); i++;
5056 XtSetArg(args[i], XtNborderWidth, 0); i++;
5057 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5060 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5061 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5062 (XtPointer) dialog);
5064 XtRealizeWidget(popup);
5065 CatchDeleteWindow(popup, "FileNamePopDown");
5067 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5068 &x, &y, &win_x, &win_y, &mask);
5070 XtSetArg(args[0], XtNx, x - 10);
5071 XtSetArg(args[1], XtNy, y - 30);
5072 XtSetValues(popup, args, 2);
5074 XtPopup(popup, XtGrabExclusive);
5077 edit = XtNameToWidget(dialog, "*value");
5078 XtSetKeyboardFocus(popup, edit);
5081 void FileNamePopDown()
5083 if (!filenameUp) return;
5084 XtPopdown(fileNameShell);
5085 XtDestroyWidget(fileNameShell);
5090 void FileNameCallback(w, client_data, call_data)
5092 XtPointer client_data, call_data;
5097 XtSetArg(args[0], XtNlabel, &name);
5098 XtGetValues(w, args, 1);
5100 if (strcmp(name, _("cancel")) == 0) {
5105 FileNameAction(w, NULL, NULL, NULL);
5108 void FileNameAction(w, event, prms, nprms)
5120 name = XawDialogGetValueString(w = XtParent(w));
5122 if ((name != NULL) && (*name != NULLCHAR)) {
5124 XtPopdown(w = XtParent(XtParent(w)));
5128 p = strrchr(buf, ' ');
5135 fullname = ExpandPathName(buf);
5137 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5140 f = fopen(fullname, fileOpenMode);
5142 DisplayError(_("Failed to open file"), errno);
5144 (void) (*fileProc)(f, index, buf);
5151 XtPopdown(w = XtParent(XtParent(w)));
5157 void PromotionPopUp()
5160 Widget dialog, layout;
5162 Dimension bw_width, pw_width;
5166 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5167 XtGetValues(boardWidget, args, j);
5170 XtSetArg(args[j], XtNresizable, True); j++;
5171 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5173 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5174 shellWidget, args, j);
5176 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5177 layoutArgs, XtNumber(layoutArgs));
5180 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5181 XtSetArg(args[j], XtNborderWidth, 0); j++;
5182 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5185 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5186 (XtPointer) dialog);
5187 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5188 (XtPointer) dialog);
5189 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5190 (XtPointer) dialog);
5191 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5192 (XtPointer) dialog);
5193 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5194 gameInfo.variant == VariantGiveaway) {
5195 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5196 (XtPointer) dialog);
5198 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5199 (XtPointer) dialog);
5201 XtRealizeWidget(promotionShell);
5202 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5205 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5206 XtGetValues(promotionShell, args, j);
5208 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5209 lineGap + squareSize/3 +
5210 ((toY == 7) ^ (flipView) ?
5211 0 : 6*(squareSize + lineGap)), &x, &y);
5214 XtSetArg(args[j], XtNx, x); j++;
5215 XtSetArg(args[j], XtNy, y); j++;
5216 XtSetValues(promotionShell, args, j);
5218 XtPopup(promotionShell, XtGrabNone);
5223 void PromotionPopDown()
5225 if (!promotionUp) return;
5226 XtPopdown(promotionShell);
5227 XtDestroyWidget(promotionShell);
5228 promotionUp = False;
5231 void PromotionCallback(w, client_data, call_data)
5233 XtPointer client_data, call_data;
5239 XtSetArg(args[0], XtNlabel, &name);
5240 XtGetValues(w, args, 1);
5244 if (fromX == -1) return;
5246 if (strcmp(name, _("cancel")) == 0) {
5250 } else if (strcmp(name, _("Knight")) == 0) {
5253 promoChar = ToLower(name[0]);
5256 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5258 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5259 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5264 void ErrorCallback(w, client_data, call_data)
5266 XtPointer client_data, call_data;
5269 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5271 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5277 if (!errorUp) return;
5279 XtPopdown(errorShell);
5280 XtDestroyWidget(errorShell);
5281 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5284 void ErrorPopUp(title, label, modal)
5285 char *title, *label;
5289 Widget dialog, layout;
5293 Dimension bw_width, pw_width;
5294 Dimension pw_height;
5298 XtSetArg(args[i], XtNresizable, True); i++;
5299 XtSetArg(args[i], XtNtitle, title); i++;
5301 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5302 shellWidget, args, i);
5304 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5305 layoutArgs, XtNumber(layoutArgs));
5308 XtSetArg(args[i], XtNlabel, label); i++;
5309 XtSetArg(args[i], XtNborderWidth, 0); i++;
5310 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5313 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5315 XtRealizeWidget(errorShell);
5316 CatchDeleteWindow(errorShell, "ErrorPopDown");
5319 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5320 XtGetValues(boardWidget, args, i);
5322 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5323 XtSetArg(args[i], XtNheight, &pw_height); i++;
5324 XtGetValues(errorShell, args, i);
5327 /* This code seems to tickle an X bug if it is executed too soon
5328 after xboard starts up. The coordinates get transformed as if
5329 the main window was positioned at (0, 0).
5331 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5332 0 - pw_height + squareSize / 3, &x, &y);
5334 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5335 RootWindowOfScreen(XtScreen(boardWidget)),
5336 (bw_width - pw_width) / 2,
5337 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5341 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5344 XtSetArg(args[i], XtNx, x); i++;
5345 XtSetArg(args[i], XtNy, y); i++;
5346 XtSetValues(errorShell, args, i);
5349 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5352 /* Disable all user input other than deleting the window */
5353 static int frozen = 0;
5357 /* Grab by a widget that doesn't accept input */
5358 XtAddGrab(messageWidget, TRUE, FALSE);
5362 /* Undo a FreezeUI */
5365 if (!frozen) return;
5366 XtRemoveGrab(messageWidget);
5370 char *ModeToWidgetName(mode)
5374 case BeginningOfGame:
5375 if (appData.icsActive)
5376 return "menuMode.ICS Client";
5377 else if (appData.noChessProgram ||
5378 *appData.cmailGameName != NULLCHAR)
5379 return "menuMode.Edit Game";
5381 return "menuMode.Machine Black";
5382 case MachinePlaysBlack:
5383 return "menuMode.Machine Black";
5384 case MachinePlaysWhite:
5385 return "menuMode.Machine White";
5387 return "menuMode.Analysis Mode";
5389 return "menuMode.Analyze File";
5390 case TwoMachinesPlay:
5391 return "menuMode.Two Machines";
5393 return "menuMode.Edit Game";
5394 case PlayFromGameFile:
5395 return "menuFile.Load Game";
5397 return "menuMode.Edit Position";
5399 return "menuMode.Training";
5400 case IcsPlayingWhite:
5401 case IcsPlayingBlack:
5405 return "menuMode.ICS Client";
5412 void ModeHighlight()
5415 static int oldPausing = FALSE;
5416 static GameMode oldmode = (GameMode) -1;
5419 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5421 if (pausing != oldPausing) {
5422 oldPausing = pausing;
5424 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5426 XtSetArg(args[0], XtNleftBitmap, None);
5428 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5431 if (appData.showButtonBar) {
5434 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5435 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5437 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5438 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5441 /* Always toggle, don't set. Previous code messes up when
5442 invoked while the button is pressed, as releasing it
5443 toggles the state again. */
5446 XtSetArg(args[0], XtNbackground, &oldbg);
5447 XtSetArg(args[1], XtNforeground, &oldfg);
5448 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5450 XtSetArg(args[0], XtNbackground, oldfg);
5451 XtSetArg(args[1], XtNforeground, oldbg);
5454 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5458 wname = ModeToWidgetName(oldmode);
5459 if (wname != NULL) {
5460 XtSetArg(args[0], XtNleftBitmap, None);
5461 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5463 wname = ModeToWidgetName(gameMode);
5464 if (wname != NULL) {
5465 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5466 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5470 /* Maybe all the enables should be handled here, not just this one */
5471 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5472 gameMode == Training || gameMode == PlayFromGameFile);
5477 * Button/menu procedures
5479 void ResetProc(w, event, prms, nprms)
5489 int LoadGamePopUp(f, gameNumber, title)
5494 cmailMsgLoaded = FALSE;
5495 if (gameNumber == 0) {
5496 int error = GameListBuild(f);
5498 DisplayError(_("Cannot build game list"), error);
5499 } else if (!ListEmpty(&gameList) &&
5500 ((ListGame *) gameList.tailPred)->number > 1) {
5501 GameListPopUp(f, title);
5507 return LoadGame(f, gameNumber, title, FALSE);
5510 void LoadGameProc(w, event, prms, nprms)
5516 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5519 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
5522 void LoadNextGameProc(w, event, prms, nprms)
5531 void LoadPrevGameProc(w, event, prms, nprms)
5540 void ReloadGameProc(w, event, prms, nprms)
5549 void LoadNextPositionProc(w, event, prms, nprms)
5558 void LoadPrevPositionProc(w, event, prms, nprms)
5567 void ReloadPositionProc(w, event, prms, nprms)
5576 void LoadPositionProc(w, event, prms, nprms)
5582 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5585 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5588 void SaveGameProc(w, event, prms, nprms)
5594 FileNamePopUp(_("Save game file name?"),
5595 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5599 void SavePositionProc(w, event, prms, nprms)
5605 FileNamePopUp(_("Save position file name?"),
5606 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5610 void ReloadCmailMsgProc(w, event, prms, nprms)
5616 ReloadCmailMsgEvent(FALSE);
5619 void MailMoveProc(w, event, prms, nprms)
5628 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5629 static char *selected_fen_position=NULL;
5632 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5633 Atom *type_return, XtPointer *value_return,
5634 unsigned long *length_return, int *format_return)
5636 char *selection_tmp;
5638 if (!selected_fen_position) return False; /* should never happen */
5639 if (*target == XA_STRING){
5640 /* note: since no XtSelectionDoneProc was registered, Xt will
5641 * automatically call XtFree on the value returned. So have to
5642 * make a copy of it allocated with XtMalloc */
5643 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5644 strcpy(selection_tmp, selected_fen_position);
5646 *value_return=selection_tmp;
5647 *length_return=strlen(selection_tmp);
5648 *type_return=XA_STRING;
5649 *format_return = 8; /* bits per byte */
5656 /* note: when called from menu all parameters are NULL, so no clue what the
5657 * Widget which was clicked on was, or what the click event was
5659 void CopyPositionProc(w, event, prms, nprms)
5667 if (selected_fen_position) free(selected_fen_position);
5668 selected_fen_position = (char *)PositionToFEN(currentMove);
5669 if (!selected_fen_position) return;
5670 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5672 SendPositionSelection,
5673 NULL/* lose_ownership_proc */ ,
5674 NULL/* transfer_done_proc */);
5676 free(selected_fen_position);
5677 selected_fen_position=NULL;
5681 /* function called when the data to Paste is ready */
5683 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5684 Atom *type, XtPointer value, unsigned long *len, int *format)
5687 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5688 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5689 EditPositionPasteFEN(fenstr);
5693 /* called when Paste Position button is pressed,
5694 * all parameters will be NULL */
5695 void PastePositionProc(w, event, prms, nprms)
5701 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5702 /* (XtSelectionCallbackProc) */ PastePositionCB,
5703 NULL, /* client_data passed to PastePositionCB */
5705 /* better to use the time field from the event that triggered the
5706 * call to this function, but that isn't trivial to get
5714 SendGameSelection(Widget w, Atom *selection, Atom *target,
5715 Atom *type_return, XtPointer *value_return,
5716 unsigned long *length_return, int *format_return)
5718 char *selection_tmp;
5720 if (*target == XA_STRING){
5721 FILE* f = fopen(gameCopyFilename, "r");
5724 if (f == NULL) return False;
5728 selection_tmp = XtMalloc(len + 1);
5729 count = fread(selection_tmp, 1, len, f);
5731 XtFree(selection_tmp);
5734 selection_tmp[len] = NULLCHAR;
5735 *value_return = selection_tmp;
5736 *length_return = len;
5737 *type_return = XA_STRING;
5738 *format_return = 8; /* bits per byte */
5745 /* note: when called from menu all parameters are NULL, so no clue what the
5746 * Widget which was clicked on was, or what the click event was
5748 void CopyGameProc(w, event, prms, nprms)
5756 ret = SaveGameToFile(gameCopyFilename, FALSE);
5759 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5762 NULL/* lose_ownership_proc */ ,
5763 NULL/* transfer_done_proc */);
5766 /* function called when the data to Paste is ready */
5768 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5769 Atom *type, XtPointer value, unsigned long *len, int *format)
5772 if (value == NULL || *len == 0) {
5773 return; /* nothing had been selected to copy */
5775 f = fopen(gamePasteFilename, "w");
5777 DisplayError(_("Can't open temp file"), errno);
5780 fwrite(value, 1, *len, f);
5783 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5786 /* called when Paste Game button is pressed,
5787 * all parameters will be NULL */
5788 void PasteGameProc(w, event, prms, nprms)
5794 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5795 /* (XtSelectionCallbackProc) */ PasteGameCB,
5796 NULL, /* client_data passed to PasteGameCB */
5798 /* better to use the time field from the event that triggered the
5799 * call to this function, but that isn't trivial to get
5809 SaveGameProc(NULL, NULL, NULL, NULL);
5813 void QuitProc(w, event, prms, nprms)
5822 void PauseProc(w, event, prms, nprms)
5832 void MachineBlackProc(w, event, prms, nprms)
5838 MachineBlackEvent();
5841 void MachineWhiteProc(w, event, prms, nprms)
5847 MachineWhiteEvent();
5850 void AnalyzeModeProc(w, event, prms, nprms)
5856 if (!first.analysisSupport) {
5858 sprintf(buf, _("%s does not support analysis"), first.tidy);
5859 DisplayError(buf, 0);
5862 if (!appData.showThinking)
5863 ShowThinkingProc(w,event,prms,nprms);
5868 void AnalyzeFileProc(w, event, prms, nprms)
5874 if (!first.analysisSupport) {
5876 sprintf(buf, _("%s does not support analysis"), first.tidy);
5877 DisplayError(buf, 0);
5882 if (!appData.showThinking)
5883 ShowThinkingProc(w,event,prms,nprms);
5886 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5887 AnalysisPeriodicEvent(1);
5890 void TwoMachinesProc(w, event, prms, nprms)
5899 void IcsClientProc(w, event, prms, nprms)
5908 void EditGameProc(w, event, prms, nprms)
5917 void EditPositionProc(w, event, prms, nprms)
5923 EditPositionEvent();
5926 void TrainingProc(w, event, prms, nprms)
5935 void EditCommentProc(w, event, prms, nprms)
5942 EditCommentPopDown();
5948 void IcsInputBoxProc(w, event, prms, nprms)
5954 if (ICSInputBoxUp) {
5955 ICSInputBoxPopDown();
5961 void AcceptProc(w, event, prms, nprms)
5970 void DeclineProc(w, event, prms, nprms)
5979 void RematchProc(w, event, prms, nprms)
5988 void CallFlagProc(w, event, prms, nprms)
5997 void DrawProc(w, event, prms, nprms)
6006 void AbortProc(w, event, prms, nprms)
6015 void AdjournProc(w, event, prms, nprms)
6024 void ResignProc(w, event, prms, nprms)
6033 void EnterKeyProc(w, event, prms, nprms)
6039 if (ICSInputBoxUp == True)
6043 void StopObservingProc(w, event, prms, nprms)
6049 StopObservingEvent();
6052 void StopExaminingProc(w, event, prms, nprms)
6058 StopExaminingEvent();
6062 void ForwardProc(w, event, prms, nprms)
6072 void BackwardProc(w, event, prms, nprms)
6081 void ToStartProc(w, event, prms, nprms)
6090 void ToEndProc(w, event, prms, nprms)
6099 void RevertProc(w, event, prms, nprms)
6108 void TruncateGameProc(w, event, prms, nprms)
6114 TruncateGameEvent();
6116 void RetractMoveProc(w, event, prms, nprms)
6125 void MoveNowProc(w, event, prms, nprms)
6135 void AlwaysQueenProc(w, event, prms, nprms)
6143 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6145 if (appData.alwaysPromoteToQueen) {
6146 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6148 XtSetArg(args[0], XtNleftBitmap, None);
6150 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6154 void AnimateDraggingProc(w, event, prms, nprms)
6162 appData.animateDragging = !appData.animateDragging;
6164 if (appData.animateDragging) {
6165 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6168 XtSetArg(args[0], XtNleftBitmap, None);
6170 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6174 void AnimateMovingProc(w, event, prms, nprms)
6182 appData.animate = !appData.animate;
6184 if (appData.animate) {
6185 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6188 XtSetArg(args[0], XtNleftBitmap, None);
6190 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6194 void AutocommProc(w, event, prms, nprms)
6202 appData.autoComment = !appData.autoComment;
6204 if (appData.autoComment) {
6205 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6207 XtSetArg(args[0], XtNleftBitmap, None);
6209 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6214 void AutoflagProc(w, event, prms, nprms)
6222 appData.autoCallFlag = !appData.autoCallFlag;
6224 if (appData.autoCallFlag) {
6225 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6227 XtSetArg(args[0], XtNleftBitmap, None);
6229 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6233 void AutoflipProc(w, event, prms, nprms)
6241 appData.autoFlipView = !appData.autoFlipView;
6243 if (appData.autoFlipView) {
6244 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6246 XtSetArg(args[0], XtNleftBitmap, None);
6248 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6252 void AutobsProc(w, event, prms, nprms)
6260 appData.autoObserve = !appData.autoObserve;
6262 if (appData.autoObserve) {
6263 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6265 XtSetArg(args[0], XtNleftBitmap, None);
6267 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6271 void AutoraiseProc(w, event, prms, nprms)
6279 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6281 if (appData.autoRaiseBoard) {
6282 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6284 XtSetArg(args[0], XtNleftBitmap, None);
6286 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6290 void AutosaveProc(w, event, prms, nprms)
6298 appData.autoSaveGames = !appData.autoSaveGames;
6300 if (appData.autoSaveGames) {
6301 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6303 XtSetArg(args[0], XtNleftBitmap, None);
6305 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6309 void BlindfoldProc(w, event, prms, nprms)
6317 appData.blindfold = !appData.blindfold;
6319 if (appData.blindfold) {
6320 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6322 XtSetArg(args[0], XtNleftBitmap, None);
6324 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6327 DrawPosition(True, NULL);
6330 void TestLegalityProc(w, event, prms, nprms)
6338 appData.testLegality = !appData.testLegality;
6340 if (appData.testLegality) {
6341 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6343 XtSetArg(args[0], XtNleftBitmap, None);
6345 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6350 void FlashMovesProc(w, event, prms, nprms)
6358 if (appData.flashCount == 0) {
6359 appData.flashCount = 3;
6361 appData.flashCount = -appData.flashCount;
6364 if (appData.flashCount > 0) {
6365 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6367 XtSetArg(args[0], XtNleftBitmap, None);
6369 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6373 void FlipViewProc(w, event, prms, nprms)
6379 flipView = !flipView;
6380 DrawPosition(True, NULL);
6383 void GetMoveListProc(w, event, prms, nprms)
6391 appData.getMoveList = !appData.getMoveList;
6393 if (appData.getMoveList) {
6394 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6397 XtSetArg(args[0], XtNleftBitmap, None);
6399 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6404 void HighlightDraggingProc(w, event, prms, nprms)
6412 appData.highlightDragging = !appData.highlightDragging;
6414 if (appData.highlightDragging) {
6415 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6417 XtSetArg(args[0], XtNleftBitmap, None);
6419 XtSetValues(XtNameToWidget(menuBarWidget,
6420 "menuOptions.Highlight Dragging"), args, 1);
6424 void HighlightLastMoveProc(w, event, prms, nprms)
6432 appData.highlightLastMove = !appData.highlightLastMove;
6434 if (appData.highlightLastMove) {
6435 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6437 XtSetArg(args[0], XtNleftBitmap, None);
6439 XtSetValues(XtNameToWidget(menuBarWidget,
6440 "menuOptions.Highlight Last Move"), args, 1);
6443 void IcsAlarmProc(w, event, prms, nprms)
6451 appData.icsAlarm = !appData.icsAlarm;
6453 if (appData.icsAlarm) {
6454 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6456 XtSetArg(args[0], XtNleftBitmap, None);
6458 XtSetValues(XtNameToWidget(menuBarWidget,
6459 "menuOptions.ICS Alarm"), args, 1);
6462 void MoveSoundProc(w, event, prms, nprms)
6470 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6472 if (appData.ringBellAfterMoves) {
6473 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6475 XtSetArg(args[0], XtNleftBitmap, None);
6477 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6482 void OldSaveStyleProc(w, event, prms, nprms)
6490 appData.oldSaveStyle = !appData.oldSaveStyle;
6492 if (appData.oldSaveStyle) {
6493 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6495 XtSetArg(args[0], XtNleftBitmap, None);
6497 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6501 void PeriodicUpdatesProc(w, event, prms, nprms)
6509 PeriodicUpdatesEvent(!appData.periodicUpdates);
6511 if (appData.periodicUpdates) {
6512 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6514 XtSetArg(args[0], XtNleftBitmap, None);
6516 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6520 void PonderNextMoveProc(w, event, prms, nprms)
6528 PonderNextMoveEvent(!appData.ponderNextMove);
6530 if (appData.ponderNextMove) {
6531 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6533 XtSetArg(args[0], XtNleftBitmap, None);
6535 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6539 void PopupExitMessageProc(w, event, prms, nprms)
6547 appData.popupExitMessage = !appData.popupExitMessage;
6549 if (appData.popupExitMessage) {
6550 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6552 XtSetArg(args[0], XtNleftBitmap, None);
6554 XtSetValues(XtNameToWidget(menuBarWidget,
6555 "menuOptions.Popup Exit Message"), args, 1);
6558 void PopupMoveErrorsProc(w, event, prms, nprms)
6566 appData.popupMoveErrors = !appData.popupMoveErrors;
6568 if (appData.popupMoveErrors) {
6569 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6571 XtSetArg(args[0], XtNleftBitmap, None);
6573 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6577 void PremoveProc(w, event, prms, nprms)
6585 appData.premove = !appData.premove;
6587 if (appData.premove) {
6588 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6590 XtSetArg(args[0], XtNleftBitmap, None);
6592 XtSetValues(XtNameToWidget(menuBarWidget,
6593 "menuOptions.Premove"), args, 1);
6596 void QuietPlayProc(w, event, prms, nprms)
6604 appData.quietPlay = !appData.quietPlay;
6606 if (appData.quietPlay) {
6607 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6609 XtSetArg(args[0], XtNleftBitmap, None);
6611 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6615 void ShowCoordsProc(w, event, prms, nprms)
6623 appData.showCoords = !appData.showCoords;
6625 if (appData.showCoords) {
6626 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6628 XtSetArg(args[0], XtNleftBitmap, None);
6630 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6633 DrawPosition(True, NULL);
6636 void ShowThinkingProc(w, event, prms, nprms)
6644 ShowThinkingEvent(!appData.showThinking);
6646 if (appData.showThinking) {
6647 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6649 XtSetArg(args[0], XtNleftBitmap, None);
6651 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6655 void InfoProc(w, event, prms, nprms)
6662 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6667 void ManProc(w, event, prms, nprms)
6675 if (nprms && *nprms > 0)
6679 sprintf(buf, "xterm -e man %s &", name);
6683 void HintProc(w, event, prms, nprms)
6692 void BookProc(w, event, prms, nprms)
6701 void AboutProc(w, event, prms, nprms)
6709 char *zippy = " (with Zippy code)";
6713 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6714 programVersion, zippy,
6715 "Copyright 1991 Digital Equipment Corporation",
6716 "Enhancements Copyright 1992-2001 Free Software Foundation",
6717 PRODUCT, " is free software and carries NO WARRANTY;",
6718 "see the file COPYING for more information.");
6719 ErrorPopUp(_("About XBoard"), buf, FALSE);
6722 void DebugProc(w, event, prms, nprms)
6728 appData.debugMode = !appData.debugMode;
6731 void AboutGameProc(w, event, prms, nprms)
6740 void NothingProc(w, event, prms, nprms)
6749 void Iconify(w, event, prms, nprms)
6758 XtSetArg(args[0], XtNiconic, True);
6759 XtSetValues(shellWidget, args, 1);
6762 void DisplayMessage(message, extMessage)
6763 char *message, *extMessage;
6770 sprintf(buf, "%s %s", message, extMessage);
6773 message = extMessage;
6776 XtSetArg(arg, XtNlabel, message);
6777 XtSetValues(messageWidget, &arg, 1);
6780 void DisplayTitle(text)
6785 char title[MSG_SIZ];
6788 if (text == NULL) text = "";
6790 if (appData.titleInWindow) {
6792 XtSetArg(args[i], XtNlabel, text); i++;
6793 XtSetValues(titleWidget, args, i);
6796 if (*text != NULLCHAR) {
6798 strcpy(title, text);
6799 } else if (appData.icsActive) {
6800 sprintf(icon, "%s", appData.icsHost);
6801 sprintf(title, "%s: %s", programName, appData.icsHost);
6802 } else if (appData.cmailGameName[0] != NULLCHAR) {
6803 sprintf(icon, "%s", "CMail");
6804 sprintf(title, "%s: %s", programName, "CMail");
6805 } else if (appData.noChessProgram) {
6806 strcpy(icon, programName);
6807 strcpy(title, programName);
6809 strcpy(icon, first.tidy);
6810 sprintf(title, "%s: %s", programName, first.tidy);
6813 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6814 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6815 XtSetValues(shellWidget, args, i);
6819 void DisplayError(message, error)
6826 if (appData.debugMode || appData.matchMode) {
6827 fprintf(stderr, "%s: %s\n", programName, message);
6830 if (appData.debugMode || appData.matchMode) {
6831 fprintf(stderr, "%s: %s: %s\n",
6832 programName, message, strerror(error));
6834 sprintf(buf, "%s: %s", message, strerror(error));
6837 ErrorPopUp(_("Error"), message, FALSE);
6841 void DisplayMoveError(message)
6846 DrawPosition(FALSE, NULL);
6847 if (appData.debugMode || appData.matchMode) {
6848 fprintf(stderr, "%s: %s\n", programName, message);
6850 if (appData.popupMoveErrors) {
6851 ErrorPopUp(_("Error"), message, FALSE);
6853 DisplayMessage(message, "");
6858 void DisplayFatalError(message, error, status)
6864 errorExitStatus = status;
6866 fprintf(stderr, "%s: %s\n", programName, message);
6868 fprintf(stderr, "%s: %s: %s\n",
6869 programName, message, strerror(error));
6870 sprintf(buf, "%s: %s", message, strerror(error));
6873 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6874 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6880 void DisplayInformation(message)
6884 ErrorPopUp(_("Information"), message, TRUE);
6887 void DisplayNote(message)
6891 ErrorPopUp(_("Note"), message, FALSE);
6895 NullXErrorCheck(dpy, error_event)
6897 XErrorEvent *error_event;
6902 void DisplayIcsInteractionTitle(message)
6905 if (oldICSInteractionTitle == NULL) {
6906 /* Magic to find the old window title, adapted from vim */
6907 char *wina = getenv("WINDOWID");
6909 Window win = (Window) atoi(wina);
6910 Window root, parent, *children;
6911 unsigned int nchildren;
6912 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6914 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6915 if (!XQueryTree(xDisplay, win, &root, &parent,
6916 &children, &nchildren)) break;
6917 if (children) XFree((void *)children);
6918 if (parent == root || parent == 0) break;
6921 XSetErrorHandler(oldHandler);
6923 if (oldICSInteractionTitle == NULL) {
6924 oldICSInteractionTitle = "xterm";
6927 printf("\033]0;%s\007", message);
6931 char pendingReplyPrefix[MSG_SIZ];
6932 ProcRef pendingReplyPR;
6934 void AskQuestionProc(w, event, prms, nprms)
6941 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6945 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6948 void AskQuestionPopDown()
6950 if (!askQuestionUp) return;
6951 XtPopdown(askQuestionShell);
6952 XtDestroyWidget(askQuestionShell);
6953 askQuestionUp = False;
6956 void AskQuestionReplyAction(w, event, prms, nprms)
6966 reply = XawDialogGetValueString(w = XtParent(w));
6967 strcpy(buf, pendingReplyPrefix);
6968 if (*buf) strcat(buf, " ");
6971 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6972 AskQuestionPopDown();
6974 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6977 void AskQuestionCallback(w, client_data, call_data)
6979 XtPointer client_data, call_data;
6984 XtSetArg(args[0], XtNlabel, &name);
6985 XtGetValues(w, args, 1);
6987 if (strcmp(name, _("cancel")) == 0) {
6988 AskQuestionPopDown();
6990 AskQuestionReplyAction(w, NULL, NULL, NULL);
6994 void AskQuestion(title, question, replyPrefix, pr)
6995 char *title, *question, *replyPrefix;
6999 Widget popup, layout, dialog, edit;
7005 strcpy(pendingReplyPrefix, replyPrefix);
7006 pendingReplyPR = pr;
7009 XtSetArg(args[i], XtNresizable, True); i++;
7010 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7011 askQuestionShell = popup =
7012 XtCreatePopupShell(title, transientShellWidgetClass,
7013 shellWidget, args, i);
7016 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7017 layoutArgs, XtNumber(layoutArgs));
7020 XtSetArg(args[i], XtNlabel, question); i++;
7021 XtSetArg(args[i], XtNvalue, ""); i++;
7022 XtSetArg(args[i], XtNborderWidth, 0); i++;
7023 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7026 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7027 (XtPointer) dialog);
7028 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7029 (XtPointer) dialog);
7031 XtRealizeWidget(popup);
7032 CatchDeleteWindow(popup, "AskQuestionPopDown");
7034 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7035 &x, &y, &win_x, &win_y, &mask);
7037 XtSetArg(args[0], XtNx, x - 10);
7038 XtSetArg(args[1], XtNy, y - 30);
7039 XtSetValues(popup, args, 2);
7041 XtPopup(popup, XtGrabExclusive);
7042 askQuestionUp = True;
7044 edit = XtNameToWidget(dialog, "*value");
7045 XtSetKeyboardFocus(popup, edit);
7053 if (*name == NULLCHAR) {
7055 } else if (strcmp(name, "$") == 0) {
7056 putc(BELLCHAR, stderr);
7059 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7067 PlaySound(appData.soundMove);
7073 PlaySound(appData.soundIcsWin);
7079 PlaySound(appData.soundIcsLoss);
7085 PlaySound(appData.soundIcsDraw);
7089 PlayIcsUnfinishedSound()
7091 PlaySound(appData.soundIcsUnfinished);
7097 PlaySound(appData.soundIcsAlarm);
7103 system("stty echo");
7109 system("stty -echo");
7113 Colorize(cc, continuation)
7118 int count, outCount, error;
7120 if (textColors[(int)cc].bg > 0) {
7121 if (textColors[(int)cc].fg > 0) {
7122 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7123 textColors[(int)cc].fg, textColors[(int)cc].bg);
7125 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7126 textColors[(int)cc].bg);
7129 if (textColors[(int)cc].fg > 0) {
7130 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7131 textColors[(int)cc].fg);
7133 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7136 count = strlen(buf);
7137 outCount = OutputToProcess(NoProc, buf, count, &error);
7138 if (outCount < count) {
7139 DisplayFatalError(_("Error writing to display"), error, 1);
7142 if (continuation) return;
7145 PlaySound(appData.soundShout);
7148 PlaySound(appData.soundSShout);
7151 PlaySound(appData.soundChannel1);
7154 PlaySound(appData.soundChannel);
7157 PlaySound(appData.soundKibitz);
7160 PlaySound(appData.soundTell);
7162 case ColorChallenge:
7163 PlaySound(appData.soundChallenge);
7166 PlaySound(appData.soundRequest);
7169 PlaySound(appData.soundSeek);
7180 return getpwuid(getuid())->pw_name;
7183 static char *ExpandPathName(path)
7186 static char static_buf[2000];
7187 char *d, *s, buf[2000];
7193 while (*s && isspace(*s))
7202 if (*(s+1) == '/') {
7203 strcpy(d, getpwuid(getuid())->pw_dir);
7208 *strchr(buf, '/') = 0;
7209 pwd = getpwnam(buf);
7212 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7216 strcpy(d, pwd->pw_dir);
7217 strcat(d, strchr(s+1, '/'));
7228 static char host_name[MSG_SIZ];
7230 #if HAVE_GETHOSTNAME
7231 gethostname(host_name, MSG_SIZ);
7233 #else /* not HAVE_GETHOSTNAME */
7234 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7235 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7237 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7239 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7240 #endif /* not HAVE_GETHOSTNAME */
7243 XtIntervalId delayedEventTimerXID = 0;
7244 DelayedEventCallback delayedEventCallback = 0;
7249 delayedEventTimerXID = 0;
7250 delayedEventCallback();
7254 ScheduleDelayedEvent(cb, millisec)
7255 DelayedEventCallback cb; long millisec;
7257 delayedEventCallback = cb;
7258 delayedEventTimerXID =
7259 XtAppAddTimeOut(appContext, millisec,
7260 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7263 DelayedEventCallback
7266 if (delayedEventTimerXID) {
7267 return delayedEventCallback;
7274 CancelDelayedEvent()
7276 if (delayedEventTimerXID) {
7277 XtRemoveTimeOut(delayedEventTimerXID);
7278 delayedEventTimerXID = 0;
7282 XtIntervalId loadGameTimerXID = 0;
7284 int LoadGameTimerRunning()
7286 return loadGameTimerXID != 0;
7289 int StopLoadGameTimer()
7291 if (loadGameTimerXID != 0) {
7292 XtRemoveTimeOut(loadGameTimerXID);
7293 loadGameTimerXID = 0;
7301 LoadGameTimerCallback(arg, id)
7305 loadGameTimerXID = 0;
7310 StartLoadGameTimer(millisec)
7314 XtAppAddTimeOut(appContext, millisec,
7315 (XtTimerCallbackProc) LoadGameTimerCallback,
7319 XtIntervalId analysisClockXID = 0;
7322 AnalysisClockCallback(arg, id)
7326 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
7327 AnalysisPeriodicEvent(0);
7328 StartAnalysisClock();
7333 StartAnalysisClock()
7336 XtAppAddTimeOut(appContext, 2000,
7337 (XtTimerCallbackProc) AnalysisClockCallback,
7341 XtIntervalId clockTimerXID = 0;
7343 int ClockTimerRunning()
7345 return clockTimerXID != 0;
7348 int StopClockTimer()
7350 if (clockTimerXID != 0) {
7351 XtRemoveTimeOut(clockTimerXID);
7360 ClockTimerCallback(arg, id)
7369 StartClockTimer(millisec)
7373 XtAppAddTimeOut(appContext, millisec,
7374 (XtTimerCallbackProc) ClockTimerCallback,
7379 DisplayTimerLabel(w, color, timer, highlight)
7388 if (appData.clockMode) {
7389 sprintf(buf, "%s: %s", color, TimeString(timer));
7390 XtSetArg(args[0], XtNlabel, buf);
7392 sprintf(buf, "%s ", color);
7393 XtSetArg(args[0], XtNlabel, buf);
7397 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7398 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7400 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7401 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7404 XtSetValues(w, args, 3);
7408 DisplayWhiteClock(timeRemaining, highlight)
7413 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
7414 if (highlight && iconPixmap == bIconPixmap) {
7415 iconPixmap = wIconPixmap;
7416 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7417 XtSetValues(shellWidget, args, 1);
7422 DisplayBlackClock(timeRemaining, highlight)
7427 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
7428 if (highlight && iconPixmap == wIconPixmap) {
7429 iconPixmap = bIconPixmap;
7430 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7431 XtSetValues(shellWidget, args, 1);
7449 int StartChildProcess(cmdLine, dir, pr)
7456 int to_prog[2], from_prog[2];
7460 if (appData.debugMode) {
7461 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7464 /* We do NOT feed the cmdLine to the shell; we just
7465 parse it into blank-separated arguments in the
7466 most simple-minded way possible.
7469 strcpy(buf, cmdLine);
7474 if (p == NULL) break;
7479 SetUpChildIO(to_prog, from_prog);
7481 if ((pid = fork()) == 0) {
7483 dup2(to_prog[0], 0);
7484 dup2(from_prog[1], 1);
7487 close(from_prog[0]);
7488 close(from_prog[1]);
7489 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7491 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7496 execvp(argv[0], argv);
7498 /* If we get here, exec failed */
7503 /* Parent process */
7505 close(from_prog[1]);
7507 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7510 cp->fdFrom = from_prog[0];
7511 cp->fdTo = to_prog[1];
7517 DestroyChildProcess(pr, signal)
7521 ChildProc *cp = (ChildProc *) pr;
7523 if (cp->kind != CPReal) return;
7526 kill(cp->pid, SIGTERM);
7528 /* Process is exiting either because of the kill or because of
7529 a quit command sent by the backend; either way, wait for it to die.
7537 InterruptChildProcess(pr)
7540 ChildProc *cp = (ChildProc *) pr;
7542 if (cp->kind != CPReal) return;
7543 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7546 int OpenTelnet(host, port, pr)
7551 char cmdLine[MSG_SIZ];
7553 if (port[0] == NULLCHAR) {
7554 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7556 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7558 return StartChildProcess(cmdLine, "", pr);
7561 int OpenTCP(host, port, pr)
7567 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7568 #else /* !OMIT_SOCKETS */
7570 struct sockaddr_in sa;
7572 unsigned short uport;
7575 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7579 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7580 sa.sin_family = AF_INET;
7581 sa.sin_addr.s_addr = INADDR_ANY;
7582 uport = (unsigned short) 0;
7583 sa.sin_port = htons(uport);
7584 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7588 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7589 if (!(hp = gethostbyname(host))) {
7591 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7592 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7593 hp->h_addrtype = AF_INET;
7595 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7596 hp->h_addr_list[0] = (char *) malloc(4);
7597 hp->h_addr_list[0][0] = b0;
7598 hp->h_addr_list[0][1] = b1;
7599 hp->h_addr_list[0][2] = b2;
7600 hp->h_addr_list[0][3] = b3;
7605 sa.sin_family = hp->h_addrtype;
7606 uport = (unsigned short) atoi(port);
7607 sa.sin_port = htons(uport);
7608 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7610 if (connect(s, (struct sockaddr *) &sa,
7611 sizeof(struct sockaddr_in)) < 0) {
7615 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7622 #endif /* !OMIT_SOCKETS */
7627 int OpenCommPort(name, pr)
7634 fd = open(name, 2, 0);
7635 if (fd < 0) return errno;
7637 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7647 int OpenLoopback(pr)
7653 SetUpChildIO(to, from);
7655 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7658 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7665 int OpenRcmd(host, user, cmd, pr)
7666 char *host, *user, *cmd;
7669 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7673 #define INPUT_SOURCE_BUF_SIZE 8192
7682 char buf[INPUT_SOURCE_BUF_SIZE];
7687 DoInputCallback(closure, source, xid)
7692 InputSource *is = (InputSource *) closure;
7697 if (is->lineByLine) {
7698 count = read(is->fd, is->unused,
7699 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7701 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7704 is->unused += count;
7706 while (p < is->unused) {
7707 q = memchr(p, '\n', is->unused - p);
7708 if (q == NULL) break;
7710 (is->func)(is, is->closure, p, q - p, 0);
7714 while (p < is->unused) {
7719 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7724 (is->func)(is, is->closure, is->buf, count, error);
7728 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7735 ChildProc *cp = (ChildProc *) pr;
7737 is = (InputSource *) calloc(1, sizeof(InputSource));
7738 is->lineByLine = lineByLine;
7742 is->fd = fileno(stdin);
7744 is->kind = cp->kind;
7745 is->fd = cp->fdFrom;
7748 is->unused = is->buf;
7751 is->xid = XtAppAddInput(appContext, is->fd,
7752 (XtPointer) (XtInputReadMask),
7753 (XtInputCallbackProc) DoInputCallback,
7755 is->closure = closure;
7756 return (InputSourceRef) is;
7760 RemoveInputSource(isr)
7763 InputSource *is = (InputSource *) isr;
7765 if (is->xid == 0) return;
7766 XtRemoveInput(is->xid);
7770 int OutputToProcess(pr, message, count, outError)
7776 ChildProc *cp = (ChildProc *) pr;
7780 outCount = fwrite(message, 1, count, stdout);
7782 outCount = write(cp->fdTo, message, count);
7792 /* Output message to process, with "ms" milliseconds of delay
7793 between each character. This is needed when sending the logon
7794 script to ICC, which for some reason doesn't like the
7795 instantaneous send. */
7796 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7803 ChildProc *cp = (ChildProc *) pr;
7808 r = write(cp->fdTo, message++, 1);
7821 /**** Animation code by Hugh Fisher, DCS, ANU.
7823 Known problem: if a window overlapping the board is
7824 moved away while a piece is being animated underneath,
7825 the newly exposed area won't be updated properly.
7826 I can live with this.
7828 Known problem: if you look carefully at the animation
7829 of pieces in mono mode, they are being drawn as solid
7830 shapes without interior detail while moving. Fixing
7831 this would be a major complication for minimal return.
7834 /* Masks for XPM pieces. Black and white pieces can have
7835 different shapes, but in the interest of retaining my
7836 sanity pieces must have the same outline on both light
7837 and dark squares, and all pieces must use the same
7838 background square colors/images. */
7841 CreateAnimMasks (pieceDepth)
7848 unsigned long plane;
7851 /* Need a bitmap just to get a GC with right depth */
7852 buf = XCreatePixmap(xDisplay, xBoardWindow,
7854 values.foreground = 1;
7855 values.background = 0;
7856 /* Don't use XtGetGC, not read only */
7857 maskGC = XCreateGC(xDisplay, buf,
7858 GCForeground | GCBackground, &values);
7859 XFreePixmap(xDisplay, buf);
7861 buf = XCreatePixmap(xDisplay, xBoardWindow,
7862 squareSize, squareSize, pieceDepth);
7863 values.foreground = XBlackPixel(xDisplay, xScreen);
7864 values.background = XWhitePixel(xDisplay, xScreen);
7865 bufGC = XCreateGC(xDisplay, buf,
7866 GCForeground | GCBackground, &values);
7868 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7869 /* Begin with empty mask */
7870 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7871 squareSize, squareSize, 1);
7872 XSetFunction(xDisplay, maskGC, GXclear);
7873 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7874 0, 0, squareSize, squareSize);
7876 /* Take a copy of the piece */
7881 XSetFunction(xDisplay, bufGC, GXcopy);
7882 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7884 0, 0, squareSize, squareSize, 0, 0);
7886 /* XOR the background (light) over the piece */
7887 XSetFunction(xDisplay, bufGC, GXxor);
7889 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7890 0, 0, squareSize, squareSize, 0, 0);
7892 XSetForeground(xDisplay, bufGC, lightSquareColor);
7893 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7896 /* We now have an inverted piece image with the background
7897 erased. Construct mask by just selecting all the non-zero
7898 pixels - no need to reconstruct the original image. */
7899 XSetFunction(xDisplay, maskGC, GXor);
7901 /* Might be quicker to download an XImage and create bitmap
7902 data from it rather than this N copies per piece, but it
7903 only takes a fraction of a second and there is a much
7904 longer delay for loading the pieces. */
7905 for (n = 0; n < pieceDepth; n ++) {
7906 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7907 0, 0, squareSize, squareSize,
7913 XFreePixmap(xDisplay, buf);
7914 XFreeGC(xDisplay, bufGC);
7915 XFreeGC(xDisplay, maskGC);
7919 InitAnimState (anim, info)
7921 XWindowAttributes * info;
7926 /* Each buffer is square size, same depth as window */
7927 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7928 squareSize, squareSize, info->depth);
7929 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7930 squareSize, squareSize, info->depth);
7932 /* Create a plain GC for blitting */
7933 mask = GCForeground | GCBackground | GCFunction |
7934 GCPlaneMask | GCGraphicsExposures;
7935 values.foreground = XBlackPixel(xDisplay, xScreen);
7936 values.background = XWhitePixel(xDisplay, xScreen);
7937 values.function = GXcopy;
7938 values.plane_mask = AllPlanes;
7939 values.graphics_exposures = False;
7940 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7942 /* Piece will be copied from an existing context at
7943 the start of each new animation/drag. */
7944 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7946 /* Outline will be a read-only copy of an existing */
7947 anim->outlineGC = None;
7953 static int done = 0;
7954 XWindowAttributes info;
7958 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7960 InitAnimState(&game, &info);
7961 InitAnimState(&player, &info);
7963 /* For XPM pieces, we need bitmaps to use as masks. */
7965 CreateAnimMasks(info.depth);
7970 static Boolean frameWaiting;
7972 static RETSIGTYPE FrameAlarm (sig)
7975 frameWaiting = False;
7976 /* In case System-V style signals. Needed?? */
7977 signal(SIGALRM, FrameAlarm);
7984 struct itimerval delay;
7986 XSync(xDisplay, False);
7989 frameWaiting = True;
7990 signal(SIGALRM, FrameAlarm);
7991 delay.it_interval.tv_sec =
7992 delay.it_value.tv_sec = time / 1000;
7993 delay.it_interval.tv_usec =
7994 delay.it_value.tv_usec = (time % 1000) * 1000;
7995 setitimer(ITIMER_REAL, &delay, NULL);
7997 /* Ugh -- busy-wait! --tpm */
7998 while (frameWaiting);
8000 while (frameWaiting) pause();
8002 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8003 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8004 setitimer(ITIMER_REAL, &delay, NULL);
8014 XSync(xDisplay, False);
8016 usleep(time * 1000);
8021 /* Convert board position to corner of screen rect and color */
8024 ScreenSquare(column, row, pt, color)
8025 int column; int row; XPoint * pt; int * color;
8028 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
8029 pt->y = lineGap + row * (squareSize + lineGap);
8031 pt->x = lineGap + column * (squareSize + lineGap);
8032 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
8034 *color = ((column + row) % 2) == 1;
8037 /* Convert window coords to square */
8040 BoardSquare(x, y, column, row)
8041 int x; int y; int * column; int * row;
8043 *column = EventToSquare(x, BOARD_SIZE);
8044 if (flipView && *column >= 0)
8045 *column = BOARD_SIZE - 1 - *column;
8046 *row = EventToSquare(y, BOARD_SIZE);
8047 if (!flipView && *row >= 0)
8048 *row = BOARD_SIZE - 1 - *row;
8053 #undef Max /* just in case */
8055 #define Max(a, b) ((a) > (b) ? (a) : (b))
8056 #define Min(a, b) ((a) < (b) ? (a) : (b))
8059 SetRect(rect, x, y, width, height)
8060 XRectangle * rect; int x; int y; int width; int height;
8064 rect->width = width;
8065 rect->height = height;
8068 /* Test if two frames overlap. If they do, return
8069 intersection rect within old and location of
8070 that rect within new. */
8073 Intersect(old, new, size, area, pt)
8074 XPoint * old; XPoint * new;
8075 int size; XRectangle * area; XPoint * pt;
8077 if (old->x > new->x + size || new->x > old->x + size ||
8078 old->y > new->y + size || new->y > old->y + size) {
8081 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8082 size - abs(old->x - new->x), size - abs(old->y - new->y));
8083 pt->x = Max(old->x - new->x, 0);
8084 pt->y = Max(old->y - new->y, 0);
8089 /* For two overlapping frames, return the rect(s)
8090 in the old that do not intersect with the new. */
8093 CalcUpdateRects(old, new, size, update, nUpdates)
8094 XPoint * old; XPoint * new; int size;
8095 XRectangle update[]; int * nUpdates;
8099 /* If old = new (shouldn't happen) then nothing to draw */
8100 if (old->x == new->x && old->y == new->y) {
8104 /* Work out what bits overlap. Since we know the rects
8105 are the same size we don't need a full intersect calc. */
8107 /* Top or bottom edge? */
8108 if (new->y > old->y) {
8109 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8111 } else if (old->y > new->y) {
8112 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8113 size, old->y - new->y);
8116 /* Left or right edge - don't overlap any update calculated above. */
8117 if (new->x > old->x) {
8118 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8119 new->x - old->x, size - abs(new->y - old->y));
8121 } else if (old->x > new->x) {
8122 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8123 old->x - new->x, size - abs(new->y - old->y));
8130 /* Generate a series of frame coords from start->mid->finish.
8131 The movement rate doubles until the half way point is
8132 reached, then halves back down to the final destination,
8133 which gives a nice slow in/out effect. The algorithmn
8134 may seem to generate too many intermediates for short
8135 moves, but remember that the purpose is to attract the
8136 viewers attention to the piece about to be moved and
8137 then to where it ends up. Too few frames would be less
8141 Tween(start, mid, finish, factor, frames, nFrames)
8142 XPoint * start; XPoint * mid;
8143 XPoint * finish; int factor;
8144 XPoint frames[]; int * nFrames;
8146 int fraction, n, count;
8150 /* Slow in, stepping 1/16th, then 1/8th, ... */
8152 for (n = 0; n < factor; n++)
8154 for (n = 0; n < factor; n++) {
8155 frames[count].x = start->x + (mid->x - start->x) / fraction;
8156 frames[count].y = start->y + (mid->y - start->y) / fraction;
8158 fraction = fraction / 2;
8162 frames[count] = *mid;
8165 /* Slow out, stepping 1/2, then 1/4, ... */
8167 for (n = 0; n < factor; n++) {
8168 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8169 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8171 fraction = fraction * 2;
8176 /* Draw a piece on the screen without disturbing what's there */
8179 SelectGCMask(piece, clip, outline, mask)
8180 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8184 /* Bitmap for piece being moved. */
8185 if (appData.monoMode) {
8186 *mask = *pieceToSolid(piece);
8187 } else if (useImages) {
8189 *mask = xpmMask[piece];
8191 *mask = ximMaskPm[piece%6];
8194 *mask = *pieceToSolid(piece);
8197 /* GC for piece being moved. Square color doesn't matter, but
8198 since it gets modified we make a copy of the original. */
8200 if (appData.monoMode)
8205 if (appData.monoMode)
8210 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8212 /* Outline only used in mono mode and is not modified */
8214 *outline = bwPieceGC;
8216 *outline = wbPieceGC;
8220 OverlayPiece(piece, clip, outline, dest)
8221 ChessSquare piece; GC clip; GC outline; Drawable dest;
8226 /* Draw solid rectangle which will be clipped to shape of piece */
8227 XFillRectangle(xDisplay, dest, clip,
8228 0, 0, squareSize, squareSize);
8229 if (appData.monoMode)
8230 /* Also draw outline in contrasting color for black
8231 on black / white on white cases */
8232 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8233 0, 0, squareSize, squareSize, 0, 0, 1);
8235 /* Copy the piece */
8240 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8242 0, 0, squareSize, squareSize,
8247 /* Animate the movement of a single piece */
8250 BeginAnimation(anim, piece, startColor, start)
8258 /* The old buffer is initialised with the start square (empty) */
8259 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8260 anim->prevFrame = *start;
8262 /* The piece will be drawn using its own bitmap as a matte */
8263 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8264 XSetClipMask(xDisplay, anim->pieceGC, mask);
8268 AnimationFrame(anim, frame, piece)
8273 XRectangle updates[4];
8278 /* Save what we are about to draw into the new buffer */
8279 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8280 frame->x, frame->y, squareSize, squareSize,
8283 /* Erase bits of the previous frame */
8284 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8285 /* Where the new frame overlapped the previous,
8286 the contents in newBuf are wrong. */
8287 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8288 overlap.x, overlap.y,
8289 overlap.width, overlap.height,
8291 /* Repaint the areas in the old that don't overlap new */
8292 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8293 for (i = 0; i < count; i++)
8294 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8295 updates[i].x - anim->prevFrame.x,
8296 updates[i].y - anim->prevFrame.y,
8297 updates[i].width, updates[i].height,
8298 updates[i].x, updates[i].y);
8300 /* Easy when no overlap */
8301 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8302 0, 0, squareSize, squareSize,
8303 anim->prevFrame.x, anim->prevFrame.y);
8306 /* Save this frame for next time round */
8307 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8308 0, 0, squareSize, squareSize,
8310 anim->prevFrame = *frame;
8312 /* Draw piece over original screen contents, not current,
8313 and copy entire rect. Wipes out overlapping piece images. */
8314 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8315 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8316 0, 0, squareSize, squareSize,
8317 frame->x, frame->y);
8321 EndAnimation (anim, finish)
8325 XRectangle updates[4];
8330 /* The main code will redraw the final square, so we
8331 only need to erase the bits that don't overlap. */
8332 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8333 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8334 for (i = 0; i < count; i++)
8335 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8336 updates[i].x - anim->prevFrame.x,
8337 updates[i].y - anim->prevFrame.y,
8338 updates[i].width, updates[i].height,
8339 updates[i].x, updates[i].y);
8341 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8342 0, 0, squareSize, squareSize,
8343 anim->prevFrame.x, anim->prevFrame.y);
8348 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8350 ChessSquare piece; int startColor;
8351 XPoint * start; XPoint * finish;
8352 XPoint frames[]; int nFrames;
8356 BeginAnimation(anim, piece, startColor, start);
8357 for (n = 0; n < nFrames; n++) {
8358 AnimationFrame(anim, &(frames[n]), piece);
8359 FrameDelay(appData.animSpeed);
8361 EndAnimation(anim, finish);
8364 /* Main control logic for deciding what to animate and how */
8367 AnimateMove(board, fromX, fromY, toX, toY)
8376 XPoint start, finish, mid;
8377 XPoint frames[kFactor * 2 + 1];
8378 int nFrames, startColor, endColor;
8380 /* Are we animating? */
8381 if (!appData.animate || appData.blindfold)
8384 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8385 piece = board[fromY][fromX];
8386 if (piece >= EmptySquare) return;
8391 hop = (piece == WhiteKnight || piece == BlackKnight);
8394 if (appData.debugMode) {
8395 printf(hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8396 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8397 piece, fromX, fromY, toX, toY);
8400 ScreenSquare(fromX, fromY, &start, &startColor);
8401 ScreenSquare(toX, toY, &finish, &endColor);
8404 /* Knight: make diagonal movement then straight */
8405 if (abs(toY - fromY) < abs(toX - fromX)) {
8406 mid.x = start.x + (finish.x - start.x) / 2;
8410 mid.y = start.y + (finish.y - start.y) / 2;
8413 mid.x = start.x + (finish.x - start.x) / 2;
8414 mid.y = start.y + (finish.y - start.y) / 2;
8417 /* Don't use as many frames for very short moves */
8418 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8419 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8421 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8422 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8424 /* Be sure end square is redrawn */
8425 damage[toY][toX] = True;
8429 DragPieceBegin(x, y)
8432 int boardX, boardY, color;
8435 /* Are we animating? */
8436 if (!appData.animateDragging || appData.blindfold)
8439 /* Figure out which square we start in and the
8440 mouse position relative to top left corner. */
8441 BoardSquare(x, y, &boardX, &boardY);
8442 player.startBoardX = boardX;
8443 player.startBoardY = boardY;
8444 ScreenSquare(boardX, boardY, &corner, &color);
8445 player.startSquare = corner;
8446 player.startColor = color;
8448 /* Start from exactly where the piece is. This can be confusing
8449 if you start dragging far from the center of the square; most
8450 or all of the piece can be over a different square from the one
8451 the mouse pointer is in. */
8452 player.mouseDelta.x = x - corner.x;
8453 player.mouseDelta.y = y - corner.y;
8455 /* As soon as we start dragging, the piece will jump slightly to
8456 be centered over the mouse pointer. */
8457 player.mouseDelta.x = squareSize/2;
8458 player.mouseDelta.y = squareSize/2;
8460 /* Initialise animation */
8461 player.dragPiece = PieceForSquare(boardX, boardY);
8463 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8464 player.dragActive = True;
8465 BeginAnimation(&player, player.dragPiece, color, &corner);
8466 /* Mark this square as needing to be redrawn. Note that
8467 we don't remove the piece though, since logically (ie
8468 as seen by opponent) the move hasn't been made yet. */
8469 damage[boardY][boardX] = True;
8471 player.dragActive = False;
8481 /* Are we animating? */
8482 if (!appData.animateDragging || appData.blindfold)
8486 if (! player.dragActive)
8488 /* Move piece, maintaining same relative position
8489 of mouse within square */
8490 corner.x = x - player.mouseDelta.x;
8491 corner.y = y - player.mouseDelta.y;
8492 AnimationFrame(&player, &corner, player.dragPiece);
8494 if (appData.highlightDragging) {
8496 BoardSquare(x, y, &boardX, &boardY);
8497 SetHighlights(fromX, fromY, boardX, boardY);
8506 int boardX, boardY, color;
8509 /* Are we animating? */
8510 if (!appData.animateDragging || appData.blindfold)
8514 if (! player.dragActive)
8516 /* Last frame in sequence is square piece is
8517 placed on, which may not match mouse exactly. */
8518 BoardSquare(x, y, &boardX, &boardY);
8519 ScreenSquare(boardX, boardY, &corner, &color);
8520 EndAnimation(&player, &corner);
8522 /* Be sure end square is redrawn */
8523 damage[boardY][boardX] = True;
8525 /* This prevents weird things happening with fast successive
8526 clicks which on my Sun at least can cause motion events
8527 without corresponding press/release. */
8528 player.dragActive = False;
8531 /* Handle expose event while piece being dragged */
8536 if (!player.dragActive || appData.blindfold)
8539 /* What we're doing: logically, the move hasn't been made yet,
8540 so the piece is still in it's original square. But visually
8541 it's being dragged around the board. So we erase the square
8542 that the piece is on and draw it at the last known drag point. */
8543 BlankSquare(player.startSquare.x, player.startSquare.y,
8544 player.startColor, EmptySquare, xBoardWindow);
8545 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8546 damage[player.startBoardY][player.startBoardX] = TRUE;