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"
195 #if !DEFINED_SYS_ERRLIST
196 extern char *sys_errlist[];
200 #define sys_errlist _sys_errlist
207 #define usleep(t) _sleep2(((t)+500)/1000)
220 int main P((int argc, char **argv));
221 RETSIGTYPE CmailSigHandler P((int sig));
222 RETSIGTYPE IntSigHandler P((int sig));
223 void CreateGCs P((void));
224 void CreateXIMPieces P((void));
225 void CreateXPMPieces P((void));
226 void CreatePieces P((void));
227 void CreatePieceMenus P((void));
228 Widget CreateMenuBar P((Menu *mb));
229 Widget CreateButtonBar P ((MenuItem *mi));
230 char *FindFont P((char *pattern, int targetPxlSize));
231 void PieceMenuPopup P((Widget w, XEvent *event,
232 String *params, Cardinal *num_params));
233 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
234 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
235 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
236 u_int wreq, u_int hreq));
237 void CreateGrid P((void));
238 int EventToSquare P((int x, int limit));
239 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
240 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
241 void HandleUserMove P((Widget w, XEvent *event,
242 String *prms, Cardinal *nprms));
243 void AnimateUserMove P((Widget w, XEvent * event,
244 String * params, Cardinal * nParams));
245 void WhiteClock P((Widget w, XEvent *event,
246 String *prms, Cardinal *nprms));
247 void BlackClock P((Widget w, XEvent *event,
248 String *prms, Cardinal *nprms));
249 void DrawPositionProc P((Widget w, XEvent *event,
250 String *prms, Cardinal *nprms));
251 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
253 void CommentPopUp P((char *title, char *label));
254 void CommentPopDown P((void));
255 void CommentCallback P((Widget w, XtPointer client_data,
256 XtPointer call_data));
257 void ICSInputBoxPopUp P((void));
258 void ICSInputBoxPopDown P((void));
259 void FileNamePopUp P((char *label, char *def,
260 FileProc proc, char *openMode));
261 void FileNamePopDown P((void));
262 void FileNameCallback P((Widget w, XtPointer client_data,
263 XtPointer call_data));
264 void FileNameAction P((Widget w, XEvent *event,
265 String *prms, Cardinal *nprms));
266 void AskQuestionReplyAction P((Widget w, XEvent *event,
267 String *prms, Cardinal *nprms));
268 void AskQuestionProc P((Widget w, XEvent *event,
269 String *prms, Cardinal *nprms));
270 void AskQuestionPopDown P((void));
271 void PromotionPopUp P((void));
272 void PromotionPopDown P((void));
273 void PromotionCallback P((Widget w, XtPointer client_data,
274 XtPointer call_data));
275 void EditCommentPopDown P((void));
276 void EditCommentCallback P((Widget w, XtPointer client_data,
277 XtPointer call_data));
278 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
279 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
280 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
281 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
283 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
285 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
287 void LoadPositionProc P((Widget w, XEvent *event,
288 String *prms, Cardinal *nprms));
289 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
291 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
293 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
295 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
297 void PastePositionProc P((Widget w, XEvent *event, String *prms,
299 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
301 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
302 void SavePositionProc P((Widget w, XEvent *event,
303 String *prms, Cardinal *nprms));
304 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
305 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
307 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
308 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
311 void MachineWhiteProc P((Widget w, XEvent *event,
312 String *prms, Cardinal *nprms));
313 void AnalyzeModeProc P((Widget w, XEvent *event,
314 String *prms, Cardinal *nprms));
315 void AnalyzeFileProc P((Widget w, XEvent *event,
316 String *prms, Cardinal *nprms));
317 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
319 void IcsClientProc P((Widget w, XEvent *event, String *prms,
321 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
322 void EditPositionProc P((Widget w, XEvent *event,
323 String *prms, Cardinal *nprms));
324 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void EditCommentProc P((Widget w, XEvent *event,
326 String *prms, Cardinal *nprms));
327 void IcsInputBoxProc P((Widget w, XEvent *event,
328 String *prms, Cardinal *nprms));
329 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void StopObservingProc P((Widget w, XEvent *event, String *prms,
340 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
342 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
343 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
349 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
351 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
352 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
354 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
356 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
358 void AutocommProc P((Widget w, XEvent *event, String *prms,
360 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
361 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void AutobsProc P((Widget w, XEvent *event, String *prms,
364 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
365 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
369 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
372 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
374 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
376 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
377 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
380 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
382 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
384 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
386 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
388 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
392 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
394 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
396 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void DisplayMove P((int moveNumber));
406 void DisplayTitle P((char *title));
407 void ICSInitScript P((void));
408 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
409 void ErrorPopUp P((char *title, char *text, int modal));
410 void ErrorPopDown P((void));
411 static char *ExpandPathName P((char *path));
412 static void CreateAnimVars P((void));
413 static void DragPieceBegin P((int x, int y));
414 static void DragPieceMove P((int x, int y));
415 static void DragPieceEnd P((int x, int y));
416 static void DrawDragPiece P((void));
417 char *ModeToWidgetName P((GameMode mode));
420 * XBoard depends on Xt R4 or higher
422 int xtVersion = XtSpecificationRelease;
427 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
428 jailSquareColor, highlightSquareColor, premoveHighlightColor;
429 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
430 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
431 wjPieceGC, bjPieceGC, prelineGC;
432 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
433 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
434 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
435 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
436 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
437 ICSInputShell, fileNameShell, askQuestionShell;
438 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
439 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
440 Font clockFontID, coordFontID;
441 XFontStruct *clockFontStruct, *coordFontStruct;
442 XtAppContext appContext;
444 char *oldICSInteractionTitle;
449 Position commentX = -1, commentY = -1;
450 Dimension commentW, commentH;
452 int squareSize, smallLayout = 0, tinyLayout = 0,
453 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
454 ICSInputBoxUp = False, askQuestionUp = False,
455 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
456 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
457 Pixel timerForegroundPixel, timerBackgroundPixel;
458 Pixel buttonForegroundPixel, buttonBackgroundPixel;
459 char *chessDir, *programName, *programVersion,
460 *gameCopyFilename, *gamePasteFilename;
464 Pixmap pieceBitmap[2][6];
465 Pixmap xpmPieceBitmap[4][6]; /* LL, LD, DL, DD */
466 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
467 int useImages, useImageSqs;
468 XImage *ximPieceBitmap[4][6]; /* LL, LD, DL, DD */
469 Pixmap ximMaskPm[6]; /* clipmasks, used for XIM pieces */
470 XImage *ximLightSquare, *ximDarkSquare;
473 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % 6]
474 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % 6]
476 #define White(piece) ((int)(piece) < (int)BlackPawn)
478 /* Variables for doing smooth animation. This whole thing
479 would be much easier if the board was double-buffered,
480 but that would require a fairly major rewrite. */
485 GC blitGC, pieceGC, outlineGC;
486 XPoint startSquare, prevFrame, mouseDelta;
490 int startBoardX, startBoardY;
493 /* There can be two pieces being animated at once: a player
494 can begin dragging a piece before the remote opponent has moved. */
496 static AnimState game, player;
498 /* Bitmaps for use as masks when drawing XPM pieces.
499 Need one for each black and white piece. */
500 static Pixmap xpmMask[BlackKing + 1];
502 /* This magic number is the number of intermediate frames used
503 in each half of the animation. For short moves it's reduced
504 by 1. The total number of frames will be factor * 2 + 1. */
507 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
509 MenuItem fileMenu[] = {
510 {"Reset Game", ResetProc},
511 {"----", NothingProc},
512 {"Load Game", LoadGameProc},
513 {"Load Next Game", LoadNextGameProc},
514 {"Load Previous Game", LoadPrevGameProc},
515 {"Reload Same Game", ReloadGameProc},
516 {"Save Game", SaveGameProc},
517 {"----", NothingProc},
518 {"Copy Game", CopyGameProc},
519 {"Paste Game", PasteGameProc},
520 {"----", NothingProc},
521 {"Load Position", LoadPositionProc},
522 {"Load Next Position", LoadNextPositionProc},
523 {"Load Previous Position", LoadPrevPositionProc},
524 {"Reload Same Position", ReloadPositionProc},
525 {"Save Position", SavePositionProc},
526 {"----", NothingProc},
527 {"Copy Position", CopyPositionProc},
528 {"Paste Position", PastePositionProc},
529 {"----", NothingProc},
530 {"Mail Move", MailMoveProc},
531 {"Reload CMail Message", ReloadCmailMsgProc},
532 {"----", NothingProc},
537 MenuItem modeMenu[] = {
538 {"Machine White", MachineWhiteProc},
539 {"Machine Black", MachineBlackProc},
540 {"Two Machines", TwoMachinesProc},
541 {"Analysis Mode", AnalyzeModeProc},
542 {"Analyze File", AnalyzeFileProc },
543 {"ICS Client", IcsClientProc},
544 {"Edit Game", EditGameProc},
545 {"Edit Position", EditPositionProc},
546 {"Training", TrainingProc},
547 {"----", NothingProc},
548 {"Show Game List", ShowGameListProc},
549 {"Show Move List", HistoryShowProc},
550 {"Edit Tags", EditTagsProc},
551 {"Edit Comment", EditCommentProc},
552 {"ICS Input Box", IcsInputBoxProc},
553 {"Pause", PauseProc},
557 MenuItem actionMenu[] = {
558 {"Accept", AcceptProc},
559 {"Decline", DeclineProc},
560 {"Rematch", RematchProc},
561 {"----", NothingProc},
562 {"Call Flag", CallFlagProc},
564 {"Adjourn", AdjournProc},
565 {"Abort", AbortProc},
566 {"Resign", ResignProc},
567 {"----", NothingProc},
568 {"Stop Observing", StopObservingProc},
569 {"Stop Examining", StopExaminingProc},
573 MenuItem stepMenu[] = {
574 {"Backward", BackwardProc},
575 {"Forward", ForwardProc},
576 {"Back to Start", ToStartProc},
577 {"Forward to End", ToEndProc},
578 {"Revert", RevertProc},
579 {"Truncate Game", TruncateGameProc},
580 {"----", NothingProc},
581 {"Move Now", MoveNowProc},
582 {"Retract Move", RetractMoveProc},
586 MenuItem optionsMenu[] = {
587 {"Always Queen", AlwaysQueenProc},
588 {"Animate Dragging", AnimateDraggingProc},
589 {"Animate Moving", AnimateMovingProc},
590 {"Auto Comment", AutocommProc},
591 {"Auto Flag", AutoflagProc},
592 {"Auto Flip View", AutoflipProc},
593 {"Auto Observe", AutobsProc},
594 {"Auto Raise Board", AutoraiseProc},
595 {"Auto Save", AutosaveProc},
596 {"Blindfold", BlindfoldProc},
597 {"Flash Moves", FlashMovesProc},
598 {"Flip View", FlipViewProc},
599 {"Get Move List", GetMoveListProc},
601 {"Highlight Dragging", HighlightDraggingProc},
603 {"Highlight Last Move", HighlightLastMoveProc},
604 {"Move Sound", MoveSoundProc},
605 {"ICS Alarm", IcsAlarmProc},
606 {"Old Save Style", OldSaveStyleProc},
607 {"Periodic Updates", PeriodicUpdatesProc},
608 {"Ponder Next Move", PonderNextMoveProc},
609 {"Popup Exit Message", PopupExitMessageProc},
610 {"Popup Move Errors", PopupMoveErrorsProc},
611 {"Premove", PremoveProc},
612 {"Quiet Play", QuietPlayProc},
613 {"Show Coords", ShowCoordsProc},
614 {"Show Thinking", ShowThinkingProc},
615 {"Test Legality", TestLegalityProc},
619 MenuItem helpMenu[] = {
620 {"Info XBoard", InfoProc},
621 {"Man XBoard", ManProc},
622 {"----", NothingProc},
625 {"----", NothingProc},
626 {"About XBoard", AboutProc},
633 {"Action", actionMenu},
635 {"Options", optionsMenu},
640 #define PAUSE_BUTTON "P"
641 MenuItem buttonBar[] = {
644 {PAUSE_BUTTON, PauseProc},
650 #define PIECE_MENU_SIZE 11
651 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
652 { "White", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
653 "----", "Empty square", "Clear board" },
654 { "Black", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
655 "----", "Empty square", "Clear board" },
657 /* must be in same order as PieceMenuStrings! */
658 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
659 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
660 WhiteRook, WhiteQueen, WhiteKing,
661 (ChessSquare) 0, EmptySquare, ClearBoard },
662 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
663 BlackRook, BlackQueen, BlackKing,
664 (ChessSquare) 0, EmptySquare, ClearBoard },
667 #define DROP_MENU_SIZE 6
668 String dropMenuStrings[DROP_MENU_SIZE] = {
669 "----", "Pawn", "Knight", "Bishop", "Rook", "Queen"
671 /* must be in same order as PieceMenuStrings! */
672 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
673 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
674 WhiteRook, WhiteQueen
682 DropMenuEnables dmEnables[] = {
700 { XtNborderWidth, 0 },
701 { XtNdefaultDistance, 0 },
705 { XtNborderWidth, 0 },
706 { XtNresizable, (XtArgVal) True },
710 { XtNborderWidth, 0 },
716 { XtNjustify, (XtArgVal) XtJustifyRight },
717 { XtNlabel, (XtArgVal) "..." },
718 { XtNresizable, (XtArgVal) True },
719 { XtNresize, (XtArgVal) False }
722 Arg messageArgs[] = {
723 { XtNjustify, (XtArgVal) XtJustifyLeft },
724 { XtNlabel, (XtArgVal) "..." },
725 { XtNresizable, (XtArgVal) True },
726 { XtNresize, (XtArgVal) False }
730 { XtNborderWidth, 0 },
731 { XtNjustify, (XtArgVal) XtJustifyLeft }
734 XtResource clientResources[] = {
735 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
736 XtOffset(AppDataPtr, whitePieceColor), XtRString,
738 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
739 XtOffset(AppDataPtr, blackPieceColor), XtRString,
741 { "lightSquareColor", "lightSquareColor", XtRString,
742 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
743 XtRString, LIGHT_SQUARE_COLOR },
744 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
745 XtOffset(AppDataPtr, darkSquareColor), XtRString,
747 { "highlightSquareColor", "highlightSquareColor", XtRString,
748 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
749 XtRString, HIGHLIGHT_SQUARE_COLOR },
750 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
751 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
752 XtRString, PREMOVE_HIGHLIGHT_COLOR },
753 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
754 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
755 (XtPointer) MOVES_PER_SESSION },
756 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
757 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
758 (XtPointer) TIME_INCREMENT },
759 { "initString", "initString", XtRString, sizeof(String),
760 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
761 { "secondInitString", "secondInitString", XtRString, sizeof(String),
762 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
763 { "firstComputerString", "firstComputerString", XtRString,
764 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
766 { "secondComputerString", "secondComputerString", XtRString,
767 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
769 { "firstChessProgram", "firstChessProgram", XtRString,
770 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
771 XtRString, FIRST_CHESS_PROGRAM },
772 { "secondChessProgram", "secondChessProgram", XtRString,
773 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
774 XtRString, SECOND_CHESS_PROGRAM },
775 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
776 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
777 XtRImmediate, (XtPointer) False },
778 { "noChessProgram", "noChessProgram", XtRBoolean,
779 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
780 XtRImmediate, (XtPointer) False },
781 { "firstHost", "firstHost", XtRString, sizeof(String),
782 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
783 { "secondHost", "secondHost", XtRString, sizeof(String),
784 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
785 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
786 XtOffset(AppDataPtr, firstDirectory), XtRString, "" },
787 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
788 XtOffset(AppDataPtr, secondDirectory), XtRString, "" },
789 { "bitmapDirectory", "bitmapDirectory", XtRString,
790 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
792 { "remoteShell", "remoteShell", XtRString, sizeof(String),
793 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
794 { "remoteUser", "remoteUser", XtRString, sizeof(String),
795 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
796 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
797 XtOffset(AppDataPtr, timeDelay), XtRString,
798 (XtPointer) TIME_DELAY_QUOTE },
799 { "timeControl", "timeControl", XtRString, sizeof(String),
800 XtOffset(AppDataPtr, timeControl), XtRString,
801 (XtPointer) TIME_CONTROL },
802 { "internetChessServerMode", "internetChessServerMode",
803 XtRBoolean, sizeof(Boolean),
804 XtOffset(AppDataPtr, icsActive), XtRImmediate,
806 { "internetChessServerHost", "internetChessServerHost",
807 XtRString, sizeof(String),
808 XtOffset(AppDataPtr, icsHost),
809 XtRString, (XtPointer) ICS_HOST },
810 { "internetChessServerPort", "internetChessServerPort",
811 XtRString, sizeof(String),
812 XtOffset(AppDataPtr, icsPort), XtRString,
813 (XtPointer) ICS_PORT },
814 { "internetChessServerCommPort", "internetChessServerCommPort",
815 XtRString, sizeof(String),
816 XtOffset(AppDataPtr, icsCommPort), XtRString,
818 { "internetChessServerLogonScript", "internetChessServerLogonScript",
819 XtRString, sizeof(String),
820 XtOffset(AppDataPtr, icsLogon), XtRString,
822 { "internetChessServerHelper", "internetChessServerHelper",
823 XtRString, sizeof(String),
824 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
825 { "internetChessServerInputBox", "internetChessServerInputBox",
826 XtRBoolean, sizeof(Boolean),
827 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
829 { "icsAlarm", "icsAlarm",
830 XtRBoolean, sizeof(Boolean),
831 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
833 { "icsAlarmTime", "icsAlarmTime",
835 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
837 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
838 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
840 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
841 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
842 { "gateway", "gateway", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, gateway), XtRString, "" },
844 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
845 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
846 { "loadGameIndex", "loadGameIndex",
848 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
850 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
851 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
852 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
853 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
854 XtRImmediate, (XtPointer) True },
855 { "autoSaveGames", "autoSaveGames", XtRBoolean,
856 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
857 XtRImmediate, (XtPointer) False },
858 { "blindfold", "blindfold", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
860 XtRImmediate, (XtPointer) False },
861 { "loadPositionFile", "loadPositionFile", XtRString,
862 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
864 { "loadPositionIndex", "loadPositionIndex",
866 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
868 { "savePositionFile", "savePositionFile", XtRString,
869 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
871 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
872 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
873 { "matchGames", "matchGames", XtRInt, sizeof(int),
874 XtOffset(AppDataPtr, matchGames), XtRImmediate,
876 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
877 XtOffset(AppDataPtr, monoMode), XtRImmediate,
879 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
880 XtOffset(AppDataPtr, debugMode), XtRImmediate,
882 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
883 XtOffset(AppDataPtr, clockMode), XtRImmediate,
885 { "boardSize", "boardSize", XtRString, sizeof(String),
886 XtOffset(AppDataPtr, boardSize), XtRString, "" },
887 { "searchTime", "searchTime", XtRString, sizeof(String),
888 XtOffset(AppDataPtr, searchTime), XtRString,
890 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
891 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
893 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
894 XtOffset(AppDataPtr, showCoords), XtRImmediate,
896 { "showJail", "showJail", XtRInt, sizeof(int),
897 XtOffset(AppDataPtr, showJail), XtRImmediate,
899 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
900 XtOffset(AppDataPtr, showThinking), XtRImmediate,
902 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
903 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
905 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
906 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
908 { "clockFont", "clockFont", XtRString, sizeof(String),
909 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
910 { "coordFont", "coordFont", XtRString, sizeof(String),
911 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
912 { "font", "font", XtRString, sizeof(String),
913 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
914 { "ringBellAfterMoves", "ringBellAfterMoves",
915 XtRBoolean, sizeof(Boolean),
916 XtOffset(AppDataPtr, ringBellAfterMoves),
917 XtRImmediate, (XtPointer) False },
918 { "autoCallFlag", "autoCallFlag", XtRBoolean,
919 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
920 XtRImmediate, (XtPointer) False },
921 { "autoFlipView", "autoFlipView", XtRBoolean,
922 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
923 XtRImmediate, (XtPointer) True },
924 { "autoObserve", "autoObserve", XtRBoolean,
925 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
926 XtRImmediate, (XtPointer) False },
927 { "autoComment", "autoComment", XtRBoolean,
928 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
929 XtRImmediate, (XtPointer) False },
930 { "getMoveList", "getMoveList", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
932 XtRImmediate, (XtPointer) True },
934 { "highlightDragging", "highlightDragging", XtRBoolean,
935 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
936 XtRImmediate, (XtPointer) False },
938 { "highlightLastMove", "highlightLastMove", XtRBoolean,
939 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
940 XtRImmediate, (XtPointer) False },
941 { "premove", "premove", XtRBoolean,
942 sizeof(Boolean), XtOffset(AppDataPtr, premove),
943 XtRImmediate, (XtPointer) True },
944 { "testLegality", "testLegality", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
946 XtRImmediate, (XtPointer) True },
947 { "flipView", "flipView", XtRBoolean,
948 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
949 XtRImmediate, (XtPointer) False },
950 { "cmail", "cmailGameName", XtRString, sizeof(String),
951 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
952 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
953 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
954 XtRImmediate, (XtPointer) False },
955 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
956 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
957 XtRImmediate, (XtPointer) False },
958 { "quietPlay", "quietPlay", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
960 XtRImmediate, (XtPointer) False },
961 { "titleInWindow", "titleInWindow", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
963 XtRImmediate, (XtPointer) False },
964 { "localLineEditing", "localLineEditing", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
966 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
968 { "zippyTalk", "zippyTalk", XtRBoolean,
969 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
970 XtRImmediate, (XtPointer) ZIPPY_TALK },
971 { "zippyPlay", "zippyPlay", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
973 XtRImmediate, (XtPointer) ZIPPY_PLAY },
974 { "zippyLines", "zippyLines", XtRString, sizeof(String),
975 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
976 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
977 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
978 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
979 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
980 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
981 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
982 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
983 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
984 ZIPPY_WRONG_PASSWORD },
985 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
986 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
987 { "zippyUseI", "zippyUseI", XtRBoolean,
988 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
989 XtRImmediate, (XtPointer) ZIPPY_USE_I },
990 { "zippyBughouse", "zippyBughouse", XtRInt,
991 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
992 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
993 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
994 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
995 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
996 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
997 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
998 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
999 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1000 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1001 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1002 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1003 { "zippyAbort", "zippyAbort", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1005 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1006 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1007 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1008 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1009 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1010 (XtPointer) ZIPPY_MAX_GAMES },
1011 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1012 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1013 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1015 { "flashCount", "flashCount", XtRInt, sizeof(int),
1016 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1017 (XtPointer) FLASH_COUNT },
1018 { "flashRate", "flashRate", XtRInt, sizeof(int),
1019 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1020 (XtPointer) FLASH_RATE },
1021 { "pixmapDirectory", "pixmapDirectory", XtRString,
1022 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1024 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1025 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1026 (XtPointer) MS_LOGIN_DELAY },
1027 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1028 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1029 XtRImmediate, (XtPointer) False },
1030 { "colorShout", "colorShout", XtRString,
1031 sizeof(String), XtOffset(AppDataPtr, colorShout),
1032 XtRString, COLOR_SHOUT },
1033 { "colorSShout", "colorSShout", XtRString,
1034 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1035 XtRString, COLOR_SSHOUT },
1036 { "colorChannel1", "colorChannel1", XtRString,
1037 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1038 XtRString, COLOR_CHANNEL1 },
1039 { "colorChannel", "colorChannel", XtRString,
1040 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1041 XtRString, COLOR_CHANNEL },
1042 { "colorKibitz", "colorKibitz", XtRString,
1043 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1044 XtRString, COLOR_KIBITZ },
1045 { "colorTell", "colorTell", XtRString,
1046 sizeof(String), XtOffset(AppDataPtr, colorTell),
1047 XtRString, COLOR_TELL },
1048 { "colorChallenge", "colorChallenge", XtRString,
1049 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1050 XtRString, COLOR_CHALLENGE },
1051 { "colorRequest", "colorRequest", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1053 XtRString, COLOR_REQUEST },
1054 { "colorSeek", "colorSeek", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1056 XtRString, COLOR_SEEK },
1057 { "colorNormal", "colorNormal", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1059 XtRString, COLOR_NORMAL },
1060 { "soundProgram", "soundProgram", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1062 XtRString, "play" },
1063 { "soundShout", "soundShout", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, soundShout),
1066 { "soundSShout", "soundSShout", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1069 { "soundChannel1", "soundChannel1", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1072 { "soundChannel", "soundChannel", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1075 { "soundKibitz", "soundKibitz", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1078 { "soundTell", "soundTell", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, soundTell),
1081 { "soundChallenge", "soundChallenge", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1084 { "soundRequest", "soundRequest", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1087 { "soundSeek", "soundSeek", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1090 { "soundMove", "soundMove", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundMove),
1093 { "soundIcsWin", "soundIcsWin", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1096 { "soundIcsLoss", "soundIcsLoss", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1099 { "soundIcsDraw", "soundIcsDraw", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1102 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1105 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1108 { "reuseFirst", "reuseFirst", XtRBoolean,
1109 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1110 XtRImmediate, (XtPointer) True },
1111 { "reuseSecond", "reuseSecond", XtRBoolean,
1112 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1113 XtRImmediate, (XtPointer) True },
1114 { "animateDragging", "animateDragging", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1116 XtRImmediate, (XtPointer) True },
1117 { "animateMoving", "animateMoving", XtRBoolean,
1118 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1119 XtRImmediate, (XtPointer) True },
1120 { "animateSpeed", "animateSpeed", XtRInt,
1121 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1122 XtRImmediate, (XtPointer)10 },
1123 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1124 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1125 XtRImmediate, (XtPointer) True },
1126 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1128 XtRImmediate, (XtPointer) False },
1129 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1130 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1131 XtRImmediate, (XtPointer)4 },
1132 { "initialMode", "initialMode", XtRString,
1133 sizeof(String), XtOffset(AppDataPtr, initialMode),
1134 XtRImmediate, (XtPointer) "" },
1135 { "variant", "variant", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, variant),
1137 XtRImmediate, (XtPointer) "normal" },
1138 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1139 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1140 XtRImmediate, (XtPointer)PROTOVER },
1141 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1142 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1143 XtRImmediate, (XtPointer)PROTOVER },
1144 { "showButtonBar", "showButtonBar", XtRBoolean,
1145 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1146 XtRImmediate, (XtPointer) True },
1149 XrmOptionDescRec shellOptions[] = {
1150 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1151 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1152 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1153 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1154 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1155 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1156 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1157 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1158 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1159 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1160 { "-initString", "initString", XrmoptionSepArg, NULL },
1161 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1162 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1163 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1164 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1165 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1166 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1167 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1168 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1169 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1170 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1171 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1172 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1173 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1174 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1175 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1176 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1177 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1178 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1179 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1180 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1181 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1182 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1183 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1184 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1185 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1186 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1187 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1188 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1189 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1190 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1191 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1192 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1193 { "-internetChessServerMode", "internetChessServerMode",
1194 XrmoptionSepArg, NULL },
1195 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1196 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1197 { "-internetChessServerHost", "internetChessServerHost",
1198 XrmoptionSepArg, NULL },
1199 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1200 { "-internetChessServerPort", "internetChessServerPort",
1201 XrmoptionSepArg, NULL },
1202 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1203 { "-internetChessServerCommPort", "internetChessServerCommPort",
1204 XrmoptionSepArg, NULL },
1205 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1206 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1207 XrmoptionSepArg, NULL },
1208 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1209 { "-internetChessServerHelper", "internetChessServerHelper",
1210 XrmoptionSepArg, NULL },
1211 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1212 { "-internetChessServerInputBox", "internetChessServerInputBox",
1213 XrmoptionSepArg, NULL },
1214 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1215 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1216 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1217 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1218 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1219 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1220 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1221 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1222 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1223 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1224 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1225 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1226 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1227 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1228 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1229 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1230 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1231 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1232 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1233 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1234 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1235 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1236 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1237 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1238 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1239 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1240 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1241 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1242 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1243 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1244 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1245 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1246 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1247 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1248 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1249 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1250 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1251 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1252 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1253 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1254 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1255 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1256 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1257 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1258 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1259 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1260 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1261 { "-size", "boardSize", XrmoptionSepArg, NULL },
1262 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1263 { "-st", "searchTime", XrmoptionSepArg, NULL },
1264 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1265 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1266 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1267 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1268 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1270 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1271 { "-jail", "showJail", XrmoptionNoArg, "1" },
1272 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1273 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1275 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1276 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1277 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1278 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1279 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1280 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1281 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1282 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1283 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1284 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1285 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1286 { "-font", "font", XrmoptionSepArg, NULL },
1287 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1288 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1289 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1290 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1291 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1292 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1293 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1294 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1295 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1296 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1297 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1298 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1299 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1300 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1301 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1302 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1303 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1304 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1305 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1306 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1308 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1309 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1310 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1312 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1313 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1314 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1315 { "-premove", "premove", XrmoptionSepArg, NULL },
1316 { "-pre", "premove", XrmoptionNoArg, "True" },
1317 { "-xpre", "premove", XrmoptionNoArg, "False" },
1318 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1319 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1320 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1321 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1322 { "-flip", "flipView", XrmoptionNoArg, "True" },
1323 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1324 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1325 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1326 XrmoptionSepArg, NULL },
1327 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1328 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1329 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1330 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1331 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1332 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1333 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1334 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1335 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1336 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1337 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1339 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1340 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1341 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1342 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1343 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1344 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1345 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1346 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1347 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1348 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1349 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1350 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1351 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1352 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1353 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1354 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1355 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1356 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1357 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1358 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1359 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1360 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1361 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1362 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1363 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1364 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1365 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1366 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1367 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1368 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1370 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1371 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1372 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1373 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1374 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1375 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1376 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1377 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1378 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1379 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1380 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1381 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1382 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1383 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1384 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1385 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1386 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1387 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1388 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1389 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1390 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1391 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1392 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1393 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1394 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1395 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1396 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1397 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1398 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1399 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1400 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1401 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1402 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1403 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1404 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1405 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1406 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1407 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1408 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1409 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1410 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1411 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1412 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1413 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1414 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1415 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1416 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1417 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1418 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1419 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1420 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1421 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1422 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1423 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1424 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1425 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1426 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1427 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1428 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1429 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1430 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1431 { "-variant", "variant", XrmoptionSepArg, NULL },
1432 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1433 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1434 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1435 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1436 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1440 XtActionsRec boardActions[] = {
1441 { "DrawPosition", DrawPositionProc },
1442 { "HandleUserMove", HandleUserMove },
1443 { "AnimateUserMove", AnimateUserMove },
1444 { "FileNameAction", FileNameAction },
1445 { "AskQuestionProc", AskQuestionProc },
1446 { "AskQuestionReplyAction", AskQuestionReplyAction },
1447 { "PieceMenuPopup", PieceMenuPopup },
1448 { "WhiteClock", WhiteClock },
1449 { "BlackClock", BlackClock },
1450 { "Iconify", Iconify },
1451 { "ResetProc", ResetProc },
1452 { "LoadGameProc", LoadGameProc },
1453 { "LoadNextGameProc", LoadNextGameProc },
1454 { "LoadPrevGameProc", LoadPrevGameProc },
1455 { "LoadSelectedProc", LoadSelectedProc },
1456 { "ReloadGameProc", ReloadGameProc },
1457 { "LoadPositionProc", LoadPositionProc },
1458 { "LoadNextPositionProc", LoadNextPositionProc },
1459 { "LoadPrevPositionProc", LoadPrevPositionProc },
1460 { "ReloadPositionProc", ReloadPositionProc },
1461 { "CopyPositionProc", CopyPositionProc },
1462 { "PastePositionProc", PastePositionProc },
1463 { "CopyGameProc", CopyGameProc },
1464 { "PasteGameProc", PasteGameProc },
1465 { "SaveGameProc", SaveGameProc },
1466 { "SavePositionProc", SavePositionProc },
1467 { "MailMoveProc", MailMoveProc },
1468 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1469 { "QuitProc", QuitProc },
1470 { "MachineWhiteProc", MachineWhiteProc },
1471 { "MachineBlackProc", MachineBlackProc },
1472 { "AnalysisModeProc", AnalyzeModeProc },
1473 { "AnalyzeFileProc", AnalyzeFileProc },
1474 { "TwoMachinesProc", TwoMachinesProc },
1475 { "IcsClientProc", IcsClientProc },
1476 { "EditGameProc", EditGameProc },
1477 { "EditPositionProc", EditPositionProc },
1478 { "TrainingProc", EditPositionProc },
1479 { "ShowGameListProc", ShowGameListProc },
1480 { "ShowMoveListProc", HistoryShowProc},
1481 { "EditTagsProc", EditCommentProc },
1482 { "EditCommentProc", EditCommentProc },
1483 { "IcsAlarmProc", IcsAlarmProc },
1484 { "IcsInputBoxProc", IcsInputBoxProc },
1485 { "PauseProc", PauseProc },
1486 { "AcceptProc", AcceptProc },
1487 { "DeclineProc", DeclineProc },
1488 { "RematchProc", RematchProc },
1489 { "CallFlagProc", CallFlagProc },
1490 { "DrawProc", DrawProc },
1491 { "AdjournProc", AdjournProc },
1492 { "AbortProc", AbortProc },
1493 { "ResignProc", ResignProc },
1494 { "EnterKeyProc", EnterKeyProc },
1495 { "StopObservingProc", StopObservingProc },
1496 { "StopExaminingProc", StopExaminingProc },
1497 { "BackwardProc", BackwardProc },
1498 { "ForwardProc", ForwardProc },
1499 { "ToStartProc", ToStartProc },
1500 { "ToEndProc", ToEndProc },
1501 { "RevertProc", RevertProc },
1502 { "TruncateGameProc", TruncateGameProc },
1503 { "MoveNowProc", MoveNowProc },
1504 { "RetractMoveProc", RetractMoveProc },
1505 { "AlwaysQueenProc", AlwaysQueenProc },
1506 { "AnimateDraggingProc", AnimateDraggingProc },
1507 { "AnimateMovingProc", AnimateMovingProc },
1508 { "AutoflagProc", AutoflagProc },
1509 { "AutoflipProc", AutoflipProc },
1510 { "AutobsProc", AutobsProc },
1511 { "AutoraiseProc", AutoraiseProc },
1512 { "AutosaveProc", AutosaveProc },
1513 { "BlindfoldProc", BlindfoldProc },
1514 { "FlashMovesProc", FlashMovesProc },
1515 { "FlipViewProc", FlipViewProc },
1516 { "GetMoveListProc", GetMoveListProc },
1518 { "HighlightDraggingProc", HighlightDraggingProc },
1520 { "HighlightLastMoveProc", HighlightLastMoveProc },
1521 { "IcsAlarmProc", IcsAlarmProc },
1522 { "MoveSoundProc", MoveSoundProc },
1523 { "OldSaveStyleProc", OldSaveStyleProc },
1524 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1525 { "PonderNextMoveProc", PonderNextMoveProc },
1526 { "PopupExitMessageProc", PopupExitMessageProc },
1527 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1528 { "PremoveProc", PremoveProc },
1529 { "QuietPlayProc", QuietPlayProc },
1530 { "ShowCoordsProc", ShowCoordsProc },
1531 { "ShowThinkingProc", ShowThinkingProc },
1532 { "TestLegalityProc", TestLegalityProc },
1533 { "InfoProc", InfoProc },
1534 { "ManProc", ManProc },
1535 { "HintProc", HintProc },
1536 { "BookProc", BookProc },
1537 { "AboutGameProc", AboutGameProc },
1538 { "AboutProc", AboutProc },
1539 { "DebugProc", DebugProc },
1540 { "NothingProc", NothingProc },
1541 { "CommentPopDown", (XtActionProc) CommentPopDown },
1542 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1543 { "TagsPopDown", (XtActionProc) TagsPopDown },
1544 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1545 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1546 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1547 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1548 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1549 { "GameListPopDown", (XtActionProc) GameListPopDown },
1550 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1551 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1554 char globalTranslations[] =
1555 ":<Key>R: ResignProc() \n \
1556 :<Key>r: ResetProc() \n \
1557 :<Key>g: LoadGameProc() \n \
1558 :<Key>N: LoadNextGameProc() \n \
1559 :<Key>P: LoadPrevGameProc() \n \
1560 :<Key>Q: QuitProc() \n \
1561 :<Key>F: ToEndProc() \n \
1562 :<Key>f: ForwardProc() \n \
1563 :<Key>B: ToStartProc() \n \
1564 :<Key>b: BackwardProc() \n \
1565 :<Key>p: PauseProc() \n \
1566 :<Key>d: DrawProc() \n \
1567 :<Key>t: CallFlagProc() \n \
1568 :<Key>i: Iconify() \n \
1569 :<Key>c: Iconify() \n \
1570 :<Key>v: FlipViewProc() \n \
1571 <KeyDown>Control_L: BackwardProc() \n \
1572 <KeyUp>Control_L: ForwardProc() \n \
1573 <KeyDown>Control_R: BackwardProc() \n \
1574 <KeyUp>Control_R: ForwardProc() \n \
1575 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1576 \"Send to chess program:\",,1) \n \
1577 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1578 \"Send to second chess program:\",,2) \n";
1580 char boardTranslations[] =
1581 "<Btn1Down>: HandleUserMove() \n \
1582 <Btn1Up>: HandleUserMove() \n \
1583 <Btn1Motion>: AnimateUserMove() \n \
1584 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1585 PieceMenuPopup(menuB) \n \
1586 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1587 PieceMenuPopup(menuW) \n \
1588 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1589 PieceMenuPopup(menuW) \n \
1590 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1591 PieceMenuPopup(menuB) \n";
1593 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1594 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1596 char ICSInputTranslations[] =
1597 "<Key>Return: EnterKeyProc() \n";
1599 String xboardResources[] = {
1600 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1601 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1602 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1607 /* Max possible square size */
1608 #define MAXSQSIZE 256
1610 static int xpm_avail[MAXSQSIZE];
1612 #ifdef HAVE_DIR_STRUCT
1614 /* Extract piece size from filename */
1616 xpm_getsize(name, len, ext)
1627 if ((p=strchr(name, '.')) == NULL ||
1628 StrCaseCmp(p+1, ext) != 0)
1634 while (*p && isdigit(*p))
1641 /* Setup xpm_avail */
1643 xpm_getavail(dirname, ext)
1651 for (i=0; i<MAXSQSIZE; ++i)
1654 if (appData.debugMode)
1655 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1657 dir = opendir(dirname);
1660 fprintf(stderr, "%s: Can't access XPM directory %s\n",
1661 programName, dirname);
1665 while ((ent=readdir(dir)) != NULL) {
1666 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1667 if (i > 0 && i < MAXSQSIZE)
1677 xpm_print_avail(fp, ext)
1683 fprintf(fp, "Available `%s' sizes:\n", ext);
1684 for (i=1; i<MAXSQSIZE; ++i) {
1690 /* Return XPM piecesize closest to size */
1692 xpm_closest_to(dirname, size, ext)
1698 int sm_diff = MAXSQSIZE;
1702 xpm_getavail(dirname, ext);
1704 if (appData.debugMode)
1705 xpm_print_avail(stderr, ext);
1707 for (i=1; i<MAXSQSIZE; ++i) {
1710 diff = (diff<0) ? -diff : diff;
1711 if (diff < sm_diff) {
1719 fprintf(stderr, "Error: No `%s' files!\n", ext);
1725 #else /* !HAVE_DIR_STRUCT */
1726 /* If we are on a system without a DIR struct, we can't
1727 read the directory, so we can't collect a list of
1728 filenames, etc., so we can't do any size-fitting. */
1730 xpm_closest_to(dirname, size, ext)
1735 fprintf(stderr, "Warning: No DIR structure found on this system --\n");
1736 fprintf(stderr, " Unable to autosize for XPM/XIM pieces.\n");
1737 fprintf(stderr, " Please report this error to frankm@hiwaay.net.\n");
1738 fprintf(stderr, " Include system type & operating system in message.\n");
1741 #endif /* HAVE_DIR_STRUCT */
1743 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1744 "magenta", "cyan", "white" };
1748 TextColors textColors[(int)NColorClasses];
1750 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1752 parse_color(str, which)
1756 char *p, buf[100], *d;
1759 if (strlen(str) > 99) /* watch bounds on buf */
1764 for (i=0; i<which; ++i) {
1771 /* Could be looking at something like:
1773 .. in which case we want to stop on a comma also */
1774 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1778 return -1; /* Use default for empty field */
1781 if (which == 2 || isdigit(*p))
1784 while (*p && isalpha(*p))
1789 for (i=0; i<8; ++i) {
1790 if (!StrCaseCmp(buf, cnames[i]))
1791 return which? (i+40) : (i+30);
1793 if (!StrCaseCmp(buf, "default")) return -1;
1795 fprintf(stderr, "%s: unrecognized color %s\n", programName, buf);
1800 parse_cpair(cc, str)
1804 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1805 fprintf(stderr, "%s: can't parse foreground color in `%s'\n",
1810 /* bg and attr are optional */
1811 textColors[(int)cc].bg = parse_color(str, 1);
1812 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1813 textColors[(int)cc].attr = 0;
1819 /* Arrange to catch delete-window events */
1820 Atom wm_delete_window;
1822 CatchDeleteWindow(Widget w, String procname)
1825 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1826 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
1827 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1834 XtSetArg(args[0], XtNiconic, False);
1835 XtSetValues(shellWidget, args, 1);
1837 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1845 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1846 XSetWindowAttributes window_attributes;
1848 Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
1849 XrmValue vFrom, vTo;
1850 XtGeometryResult gres;
1853 int forceMono = False;
1855 setbuf(stdout, NULL);
1856 setbuf(stderr, NULL);
1859 programName = strrchr(argv[0], '/');
1860 if (programName == NULL)
1861 programName = argv[0];
1866 XtAppInitialize(&appContext, "XBoard", shellOptions,
1867 XtNumber(shellOptions),
1868 &argc, argv, xboardResources, NULL, 0);
1870 fprintf(stderr, "%s: unrecognized argument %s\n",
1871 programName, argv[1]);
1875 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1878 if (chdir(chessDir) != 0) {
1879 fprintf(stderr, "%s: can't cd to CHESSDIR: ", programName);
1886 if (p == NULL) p = "/tmp";
1887 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1888 gameCopyFilename = (char*) malloc(i);
1889 gamePasteFilename = (char*) malloc(i);
1890 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1891 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1893 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1894 clientResources, XtNumber(clientResources),
1897 /* This feature does not work; animation needs a rewrite */
1898 appData.highlightDragging = FALSE;
1902 xDisplay = XtDisplay(shellWidget);
1903 xScreen = DefaultScreen(xDisplay);
1904 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1907 * Determine boardSize
1909 if (isdigit(appData.boardSize[0])) {
1910 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1911 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1912 &fontPxlSize, &smallLayout, &tinyLayout);
1914 fprintf(stderr, "%s: bad boardSize syntax %s\n",
1915 programName, appData.boardSize);
1919 /* Find some defaults; use the nearest known size */
1920 SizeDefaults *szd, *nearest;
1921 int distance = 99999;
1922 nearest = szd = sizeDefaults;
1923 while (szd->name != NULL) {
1924 if (abs(szd->squareSize - squareSize) < distance) {
1926 distance = abs(szd->squareSize - squareSize);
1927 if (distance == 0) break;
1931 if (i < 2) lineGap = nearest->lineGap;
1932 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1933 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1934 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1935 if (i < 6) smallLayout = nearest->smallLayout;
1936 if (i < 7) tinyLayout = nearest->tinyLayout;
1939 SizeDefaults *szd = sizeDefaults;
1940 if (*appData.boardSize == NULLCHAR) {
1941 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1942 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1945 if (szd->name == NULL) szd--;
1947 while (szd->name != NULL &&
1948 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1949 if (szd->name == NULL) {
1950 fprintf(stderr, "%s: unrecognized boardSize name %s\n",
1951 programName, appData.boardSize);
1955 squareSize = szd->squareSize;
1956 lineGap = szd->lineGap;
1957 clockFontPxlSize = szd->clockFontPxlSize;
1958 coordFontPxlSize = szd->coordFontPxlSize;
1959 fontPxlSize = szd->fontPxlSize;
1960 smallLayout = szd->smallLayout;
1961 tinyLayout = szd->tinyLayout;
1964 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1965 if (strlen(appData.pixmapDirectory) > 0) {
1966 p = ExpandPathName(appData.pixmapDirectory);
1968 fprintf(stderr, "Error expanding path name \"%s\"\n",
1969 appData.pixmapDirectory);
1972 if (appData.debugMode) {
1973 fprintf(stderr, "XBoard square size (hint): %d\n", squareSize);
1974 fprintf(stderr, "%s fulldir:%s:\n", IMAGE_EXT, p);
1976 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1977 if (appData.debugMode) {
1978 fprintf(stderr, "Closest %s size: %d\n", IMAGE_EXT, squareSize);
1982 boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
1983 if (appData.showJail == 1) {
1984 /* Jail on top and bottom */
1985 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1986 XtSetArg(boardArgs[2], XtNheight,
1987 boardWidth + 2*(lineGap + squareSize));
1988 } else if (appData.showJail == 2) {
1990 XtSetArg(boardArgs[1], XtNwidth,
1991 boardWidth + 2*(lineGap + squareSize));
1992 XtSetArg(boardArgs[2], XtNheight, boardWidth);
1995 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1996 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2000 * Determine what fonts to use.
2002 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2003 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2004 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2005 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2006 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2007 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2008 appData.font = FindFont(appData.font, fontPxlSize);
2010 xdb = XtDatabase(xDisplay);
2011 XrmPutStringResource(&xdb, "*font", appData.font);
2014 * Detect if there are not enough colors available and adapt.
2016 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2017 appData.monoMode = True;
2020 if (!appData.monoMode) {
2021 vFrom.addr = (caddr_t) appData.lightSquareColor;
2022 vFrom.size = strlen(appData.lightSquareColor);
2023 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2024 if (vTo.addr == NULL) {
2025 appData.monoMode = True;
2028 lightSquareColor = *(Pixel *) vTo.addr;
2031 if (!appData.monoMode) {
2032 vFrom.addr = (caddr_t) appData.darkSquareColor;
2033 vFrom.size = strlen(appData.darkSquareColor);
2034 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2035 if (vTo.addr == NULL) {
2036 appData.monoMode = True;
2039 darkSquareColor = *(Pixel *) vTo.addr;
2042 if (!appData.monoMode) {
2043 vFrom.addr = (caddr_t) appData.whitePieceColor;
2044 vFrom.size = strlen(appData.whitePieceColor);
2045 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2046 if (vTo.addr == NULL) {
2047 appData.monoMode = True;
2050 whitePieceColor = *(Pixel *) vTo.addr;
2053 if (!appData.monoMode) {
2054 vFrom.addr = (caddr_t) appData.blackPieceColor;
2055 vFrom.size = strlen(appData.blackPieceColor);
2056 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2057 if (vTo.addr == NULL) {
2058 appData.monoMode = True;
2061 blackPieceColor = *(Pixel *) vTo.addr;
2065 if (!appData.monoMode) {
2066 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2067 vFrom.size = strlen(appData.highlightSquareColor);
2068 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2069 if (vTo.addr == NULL) {
2070 appData.monoMode = True;
2073 highlightSquareColor = *(Pixel *) vTo.addr;
2077 if (!appData.monoMode) {
2078 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2079 vFrom.size = strlen(appData.premoveHighlightColor);
2080 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2081 if (vTo.addr == NULL) {
2082 appData.monoMode = True;
2085 premoveHighlightColor = *(Pixel *) vTo.addr;
2090 fprintf(stderr, "%s: too few colors available; trying monochrome mode\n",
2094 if (appData.monoMode && appData.debugMode) {
2095 fprintf(stderr, "white pixel = 0x%lx, black pixel = 0x%lx\n",
2096 (unsigned long) XWhitePixel(xDisplay, xScreen),
2097 (unsigned long) XBlackPixel(xDisplay, xScreen));
2100 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2101 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2102 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2103 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2104 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2105 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2106 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2107 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2108 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2109 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2111 if (appData.colorize) {
2113 "%s: can't parse color names; disabling colorization\n",
2116 appData.colorize = FALSE;
2118 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2119 textColors[ColorNone].attr = 0;
2121 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2127 layoutName = "tinyLayout";
2128 } else if (smallLayout) {
2129 layoutName = "smallLayout";
2131 layoutName = "normalLayout";
2133 /* Outer layoutWidget is there only to provide a name for use in
2134 resources that depend on the layout style */
2136 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2137 layoutArgs, XtNumber(layoutArgs));
2139 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2140 formArgs, XtNumber(formArgs));
2141 XtSetArg(args[0], XtNdefaultDistance, &sep);
2142 XtGetValues(formWidget, args, 1);
2145 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2147 widgetList[j++] = whiteTimerWidget =
2148 XtCreateWidget("whiteTime", labelWidgetClass,
2149 formWidget, timerArgs, XtNumber(timerArgs));
2150 XtSetArg(args[0], XtNfont, clockFontStruct);
2151 XtSetValues(whiteTimerWidget, args, 1);
2153 widgetList[j++] = blackTimerWidget =
2154 XtCreateWidget("blackTime", labelWidgetClass,
2155 formWidget, timerArgs, XtNumber(timerArgs));
2156 XtSetArg(args[0], XtNfont, clockFontStruct);
2157 XtSetValues(blackTimerWidget, args, 1);
2159 if (appData.titleInWindow) {
2160 widgetList[j++] = titleWidget =
2161 XtCreateWidget("title", labelWidgetClass, formWidget,
2162 titleArgs, XtNumber(titleArgs));
2165 if (appData.showButtonBar) {
2166 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2169 widgetList[j++] = messageWidget =
2170 XtCreateWidget("message", labelWidgetClass, formWidget,
2171 messageArgs, XtNumber(messageArgs));
2173 widgetList[j++] = boardWidget =
2174 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2175 XtNumber(boardArgs));
2177 XtManageChildren(widgetList, j);
2179 timerWidth = (boardWidth - sep) / 2;
2180 XtSetArg(args[0], XtNwidth, timerWidth);
2181 XtSetValues(whiteTimerWidget, args, 1);
2182 XtSetValues(blackTimerWidget, args, 1);
2184 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2185 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2186 XtGetValues(whiteTimerWidget, args, 2);
2188 if (appData.showButtonBar) {
2189 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2190 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2191 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2195 * formWidget uses these constraints but they are stored
2199 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2200 XtSetValues(menuBarWidget, args, i);
2201 if (appData.titleInWindow) {
2204 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2205 XtSetValues(whiteTimerWidget, args, i);
2207 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2208 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2209 XtSetValues(blackTimerWidget, args, i);
2211 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2212 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2213 XtSetValues(titleWidget, args, i);
2215 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2216 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2217 XtSetValues(messageWidget, args, i);
2218 if (appData.showButtonBar) {
2220 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2221 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2222 XtSetValues(buttonBarWidget, args, i);
2226 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2227 XtSetValues(whiteTimerWidget, args, i);
2229 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2230 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2231 XtSetValues(blackTimerWidget, args, i);
2233 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2234 XtSetValues(titleWidget, args, i);
2236 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2237 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2238 XtSetValues(messageWidget, args, i);
2239 if (appData.showButtonBar) {
2241 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2242 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2243 XtSetValues(buttonBarWidget, args, i);
2248 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2249 XtSetValues(whiteTimerWidget, args, i);
2251 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2252 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2253 XtSetValues(blackTimerWidget, args, i);
2255 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2256 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2257 XtSetValues(messageWidget, args, i);
2258 if (appData.showButtonBar) {
2260 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2261 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2262 XtSetValues(buttonBarWidget, args, i);
2266 XtSetArg(args[0], XtNfromVert, messageWidget);
2267 XtSetValues(boardWidget, args, 1);
2269 XtRealizeWidget(shellWidget);
2272 * Correct the width of the message and title widgets.
2273 * It is not known why some systems need the extra fudge term.
2274 * The value "2" is probably larger than needed.
2276 XawFormDoLayout(formWidget, False);
2277 #define WIDTH_FUDGE 2
2279 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2280 XtSetArg(args[i], XtNheight, &h); i++;
2281 XtGetValues(messageWidget, args, i);
2282 if (appData.showButtonBar) {
2284 XtSetArg(args[i], XtNwidth, &w); i++;
2285 XtGetValues(buttonBarWidget, args, i);
2286 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2288 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2291 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2292 if (gres != XtGeometryYes && appData.debugMode) {
2293 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
2294 programName, gres, w, h, wr, hr);
2297 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2298 /* The size used for the child widget in layout lags one resize behind
2299 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2301 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2302 if (gres != XtGeometryYes && appData.debugMode) {
2303 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
2304 programName, gres, w, h, wr, hr);
2308 if (appData.titleInWindow) {
2310 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2311 XtSetArg(args[i], XtNheight, &h); i++;
2312 XtGetValues(titleWidget, args, i);
2314 w = boardWidth - 2*bor;
2316 XtSetArg(args[0], XtNwidth, &w);
2317 XtGetValues(menuBarWidget, args, 1);
2318 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2321 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2322 if (gres != XtGeometryYes && appData.debugMode) {
2324 "%s: titleWidget geometry error %d %d %d %d %d\n",
2325 programName, gres, w, h, wr, hr);
2328 XawFormDoLayout(formWidget, True);
2330 xBoardWindow = XtWindow(boardWidget);
2333 * Create X checkmark bitmap and initialize option menu checks.
2335 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2336 checkmark_bits, checkmark_width, checkmark_height);
2337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2338 if (appData.alwaysPromoteToQueen) {
2339 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2342 if (appData.animateDragging) {
2343 XtSetValues(XtNameToWidget(menuBarWidget,
2344 "menuOptions.Animate Dragging"),
2347 if (appData.animate) {
2348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2351 if (appData.autoComment) {
2352 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2355 if (appData.autoCallFlag) {
2356 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2359 if (appData.autoFlipView) {
2360 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2363 if (appData.autoObserve) {
2364 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2367 if (appData.autoRaiseBoard) {
2368 XtSetValues(XtNameToWidget(menuBarWidget,
2369 "menuOptions.Auto Raise Board"), args, 1);
2371 if (appData.autoSaveGames) {
2372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2375 if (appData.saveGameFile[0] != NULLCHAR) {
2376 /* Can't turn this off from menu */
2377 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2379 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2383 if (appData.blindfold) {
2384 XtSetValues(XtNameToWidget(menuBarWidget,
2385 "menuOptions.Blindfold"), args, 1);
2387 if (appData.flashCount > 0) {
2388 XtSetValues(XtNameToWidget(menuBarWidget,
2389 "menuOptions.Flash Moves"),
2392 if (appData.getMoveList) {
2393 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2397 if (appData.highlightDragging) {
2398 XtSetValues(XtNameToWidget(menuBarWidget,
2399 "menuOptions.Highlight Dragging"),
2403 if (appData.highlightLastMove) {
2404 XtSetValues(XtNameToWidget(menuBarWidget,
2405 "menuOptions.Highlight Last Move"),
2408 if (appData.icsAlarm) {
2409 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2412 if (appData.ringBellAfterMoves) {
2413 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2416 if (appData.oldSaveStyle) {
2417 XtSetValues(XtNameToWidget(menuBarWidget,
2418 "menuOptions.Old Save Style"), args, 1);
2420 if (appData.periodicUpdates) {
2421 XtSetValues(XtNameToWidget(menuBarWidget,
2422 "menuOptions.Periodic Updates"), args, 1);
2424 if (appData.ponderNextMove) {
2425 XtSetValues(XtNameToWidget(menuBarWidget,
2426 "menuOptions.Ponder Next Move"), args, 1);
2428 if (appData.popupExitMessage) {
2429 XtSetValues(XtNameToWidget(menuBarWidget,
2430 "menuOptions.Popup Exit Message"), args, 1);
2432 if (appData.popupMoveErrors) {
2433 XtSetValues(XtNameToWidget(menuBarWidget,
2434 "menuOptions.Popup Move Errors"), args, 1);
2436 if (appData.premove) {
2437 XtSetValues(XtNameToWidget(menuBarWidget,
2438 "menuOptions.Premove"), args, 1);
2440 if (appData.quietPlay) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Quiet Play"), args, 1);
2444 if (appData.showCoords) {
2445 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2448 if (appData.showThinking) {
2449 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2452 if (appData.testLegality) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2460 ReadBitmap(&wIconPixmap, "icon_white.bm",
2461 icon_white_bits, icon_white_width, icon_white_height);
2462 ReadBitmap(&bIconPixmap, "icon_black.bm",
2463 icon_black_bits, icon_black_width, icon_black_height);
2464 iconPixmap = wIconPixmap;
2466 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2467 XtSetValues(shellWidget, args, i);
2470 * Create a cursor for the board widget.
2472 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2473 XChangeWindowAttributes(xDisplay, xBoardWindow,
2474 CWCursor, &window_attributes);
2477 * Inhibit shell resizing.
2479 shellArgs[0].value = (XtArgVal) &w;
2480 shellArgs[1].value = (XtArgVal) &h;
2481 XtGetValues(shellWidget, shellArgs, 2);
2482 shellArgs[4].value = shellArgs[2].value = w;
2483 shellArgs[5].value = shellArgs[3].value = h;
2484 XtSetValues(shellWidget, &shellArgs[2], 4);
2486 CatchDeleteWindow(shellWidget, "QuitProc");
2491 if (appData.bitmapDirectory[0] != NULLCHAR) {
2498 /* Create regular pieces */
2499 if (!useImages) CreatePieces();
2504 if (appData.animate || appData.animateDragging)
2507 XtAugmentTranslations(formWidget,
2508 XtParseTranslationTable(globalTranslations));
2509 XtAugmentTranslations(boardWidget,
2510 XtParseTranslationTable(boardTranslations));
2511 XtAugmentTranslations(whiteTimerWidget,
2512 XtParseTranslationTable(whiteTranslations));
2513 XtAugmentTranslations(blackTimerWidget,
2514 XtParseTranslationTable(blackTranslations));
2516 /* Why is the following needed on some versions of X instead
2517 * of a translation? */
2518 XtAddEventHandler(boardWidget, ExposureMask, False,
2519 (XtEventHandler) EventProc, NULL);
2524 if (errorExitStatus == -1) {
2525 if (appData.icsActive) {
2526 /* We now wait until we see "login:" from the ICS before
2527 sending the logon script (problems with timestamp otherwise) */
2528 /*ICSInitScript();*/
2529 if (appData.icsInputBox) ICSInputBoxPopUp();
2532 signal(SIGINT, IntSigHandler);
2533 signal(SIGTERM, IntSigHandler);
2534 if (*appData.cmailGameName != NULLCHAR) {
2535 signal(SIGUSR1, CmailSigHandler);
2539 XtAppMainLoop(appContext);
2546 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2547 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2549 unlink(gameCopyFilename);
2550 unlink(gamePasteFilename);
2561 CmailSigHandler(sig)
2567 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2569 /* Activate call-back function CmailSigHandlerCallBack() */
2570 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2572 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2576 CmailSigHandlerCallBack(isr, closure, message, count, error)
2584 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2586 /**** end signal code ****/
2596 f = fopen(appData.icsLogon, "r");
2602 strcat(buf, appData.icsLogon);
2603 f = fopen(buf, "r");
2607 ProcessICSInitScript(f);
2614 EditCommentPopDown();
2625 SetMenuEnables(enab)
2629 if (!menuBarWidget) return;
2630 while (enab->name != NULL) {
2631 w = XtNameToWidget(menuBarWidget, enab->name);
2633 DisplayError(enab->name, 0);
2635 XtSetSensitive(w, enab->value);
2641 Enables icsEnables[] = {
2642 { "menuFile.Mail Move", False },
2643 { "menuFile.Reload CMail Message", False },
2644 { "menuMode.Machine Black", False },
2645 { "menuMode.Machine White", False },
2646 { "menuMode.Analysis Mode", False },
2647 { "menuMode.Analyze File", False },
2648 { "menuMode.Two Machines", False },
2650 { "menuHelp.Hint", False },
2651 { "menuHelp.Book", False },
2652 { "menuStep.Move Now", False },
2653 { "menuOptions.Periodic Updates", False },
2654 { "menuOptions.Show Thinking", False },
2655 { "menuOptions.Ponder Next Move", False },
2660 Enables ncpEnables[] = {
2661 { "menuFile.Mail Move", False },
2662 { "menuFile.Reload CMail Message", False },
2663 { "menuMode.Machine White", False },
2664 { "menuMode.Machine Black", False },
2665 { "menuMode.Analysis Mode", False },
2666 { "menuMode.Analyze File", False },
2667 { "menuMode.Two Machines", False },
2668 { "menuMode.ICS Client", False },
2669 { "menuMode.ICS Input Box", False },
2670 { "Action", False },
2671 { "menuStep.Revert", False },
2672 { "menuStep.Move Now", False },
2673 { "menuStep.Retract Move", False },
2674 { "menuOptions.Auto Comment", False },
2675 { "menuOptions.Auto Flag", False },
2676 { "menuOptions.Auto Flip View", False },
2677 { "menuOptions.Auto Observe", False },
2678 { "menuOptions.Auto Raise Board", False },
2679 { "menuOptions.Get Move List", False },
2680 { "menuOptions.ICS Alarm", False },
2681 { "menuOptions.Move Sound", False },
2682 { "menuOptions.Quiet Play", False },
2683 { "menuOptions.Show Thinking", False },
2684 { "menuOptions.Periodic Updates", False },
2685 { "menuOptions.Ponder Next Move", False },
2686 { "menuHelp.Hint", False },
2687 { "menuHelp.Book", False },
2691 Enables gnuEnables[] = {
2692 { "menuMode.ICS Client", False },
2693 { "menuMode.ICS Input Box", False },
2694 { "menuAction.Accept", False },
2695 { "menuAction.Decline", False },
2696 { "menuAction.Rematch", False },
2697 { "menuAction.Adjourn", False },
2698 { "menuAction.Stop Examining", False },
2699 { "menuAction.Stop Observing", False },
2700 { "menuStep.Revert", False },
2701 { "menuOptions.Auto Comment", False },
2702 { "menuOptions.Auto Observe", False },
2703 { "menuOptions.Auto Raise Board", False },
2704 { "menuOptions.Get Move List", False },
2705 { "menuOptions.Premove", False },
2706 { "menuOptions.Quiet Play", False },
2708 /* The next two options rely on SetCmailMode being called *after* */
2709 /* SetGNUMode so that when GNU is being used to give hints these */
2710 /* menu options are still available */
2712 { "menuFile.Mail Move", False },
2713 { "menuFile.Reload CMail Message", False },
2717 Enables cmailEnables[] = {
2719 { "menuAction.Call Flag", False },
2720 { "menuAction.Draw", True },
2721 { "menuAction.Adjourn", False },
2722 { "menuAction.Abort", False },
2723 { "menuAction.Stop Observing", False },
2724 { "menuAction.Stop Examining", False },
2725 { "menuFile.Mail Move", True },
2726 { "menuFile.Reload CMail Message", True },
2730 Enables trainingOnEnables[] = {
2731 { "menuMode.Edit Comment", False },
2732 { "menuMode.Pause", False },
2733 { "menuStep.Forward", False },
2734 { "menuStep.Backward", False },
2735 { "menuStep.Forward to End", False },
2736 { "menuStep.Back to Start", False },
2737 { "menuStep.Move Now", False },
2738 { "menuStep.Truncate Game", False },
2742 Enables trainingOffEnables[] = {
2743 { "menuMode.Edit Comment", True },
2744 { "menuMode.Pause", True },
2745 { "menuStep.Forward", True },
2746 { "menuStep.Backward", True },
2747 { "menuStep.Forward to End", True },
2748 { "menuStep.Back to Start", True },
2749 { "menuStep.Move Now", True },
2750 { "menuStep.Truncate Game", True },
2754 Enables machineThinkingEnables[] = {
2755 { "menuFile.Load Game", False },
2756 { "menuFile.Load Next Game", False },
2757 { "menuFile.Load Previous Game", False },
2758 { "menuFile.Reload Same Game", False },
2759 { "menuFile.Paste Game", False },
2760 { "menuFile.Load Position", False },
2761 { "menuFile.Load Next Position", False },
2762 { "menuFile.Load Previous Position", False },
2763 { "menuFile.Reload Same Position", False },
2764 { "menuFile.Paste Position", False },
2765 { "menuMode.Machine White", False },
2766 { "menuMode.Machine Black", False },
2767 { "menuMode.Two Machines", False },
2768 { "menuStep.Retract Move", False },
2772 Enables userThinkingEnables[] = {
2773 { "menuFile.Load Game", True },
2774 { "menuFile.Load Next Game", True },
2775 { "menuFile.Load Previous Game", True },
2776 { "menuFile.Reload Same Game", True },
2777 { "menuFile.Paste Game", True },
2778 { "menuFile.Load Position", True },
2779 { "menuFile.Load Next Position", True },
2780 { "menuFile.Load Previous Position", True },
2781 { "menuFile.Reload Same Position", True },
2782 { "menuFile.Paste Position", True },
2783 { "menuMode.Machine White", True },
2784 { "menuMode.Machine Black", True },
2785 { "menuMode.Two Machines", True },
2786 { "menuStep.Retract Move", True },
2792 SetMenuEnables(icsEnables);
2798 SetMenuEnables(ncpEnables);
2804 SetMenuEnables(gnuEnables);
2810 SetMenuEnables(cmailEnables);
2816 SetMenuEnables(trainingOnEnables);
2817 if (appData.showButtonBar) {
2818 XtSetSensitive(buttonBarWidget, False);
2824 SetTrainingModeOff()
2826 SetMenuEnables(trainingOffEnables);
2827 if (appData.showButtonBar) {
2828 XtSetSensitive(buttonBarWidget, True);
2833 SetUserThinkingEnables()
2835 if (appData.noChessProgram) return;
2836 SetMenuEnables(userThinkingEnables);
2840 SetMachineThinkingEnables()
2842 if (appData.noChessProgram) return;
2843 SetMenuEnables(machineThinkingEnables);
2845 case MachinePlaysBlack:
2846 case MachinePlaysWhite:
2847 case TwoMachinesPlay:
2848 XtSetSensitive(XtNameToWidget(menuBarWidget,
2849 ModeToWidgetName(gameMode)), True);
2856 #define Abs(n) ((n)<0 ? -(n) : (n))
2859 * Find a font that matches "pattern" that is as close as
2860 * possible to the targetPxlSize. Prefer fonts that are k
2861 * pixels smaller to fonts that are k pixels larger. The
2862 * pattern must be in the X Consortium standard format,
2863 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2864 * The return value should be freed with XtFree when no
2867 char *FindFont(pattern, targetPxlSize)
2871 char **fonts, *p, *best, *scalable, *scalableTail;
2872 int i, j, nfonts, minerr, err, pxlSize;
2874 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2876 fprintf(stderr, "%s: no fonts match pattern %s\n",
2877 programName, pattern);
2883 for (i=0; i<nfonts; i++) {
2886 if (*p != '-') continue;
2888 if (*p == NULLCHAR) break;
2889 if (*p++ == '-') j++;
2891 if (j < 7) continue;
2894 scalable = fonts[i];
2897 err = pxlSize - targetPxlSize;
2898 if (Abs(err) < Abs(minerr) ||
2899 (minerr > 0 && err < 0 && -err == minerr)) {
2905 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2906 /* If the error is too big and there is a scalable font,
2907 use the scalable font. */
2908 int headlen = scalableTail - scalable;
2909 p = (char *) XtMalloc(strlen(scalable) + 10);
2910 while (isdigit(*scalableTail)) scalableTail++;
2911 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2913 p = (char *) XtMalloc(strlen(best) + 1);
2916 if (appData.debugMode) {
2917 fprintf(debugFP, "resolved %s at pixel size %d\n to %s\n",
2918 pattern, targetPxlSize, p);
2920 XFreeFontNames(fonts);
2926 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2927 | GCBackground | GCFunction | GCPlaneMask;
2928 XGCValues gc_values;
2931 gc_values.plane_mask = AllPlanes;
2932 gc_values.line_width = lineGap;
2933 gc_values.line_style = LineSolid;
2934 gc_values.function = GXcopy;
2936 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2937 gc_values.background = XBlackPixel(xDisplay, xScreen);
2938 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2940 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2941 gc_values.background = XWhitePixel(xDisplay, xScreen);
2942 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2943 XSetFont(xDisplay, coordGC, coordFontID);
2945 if (appData.monoMode) {
2946 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2947 gc_values.background = XWhitePixel(xDisplay, xScreen);
2948 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2950 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2951 gc_values.background = XBlackPixel(xDisplay, xScreen);
2952 lightSquareGC = wbPieceGC
2953 = XtGetGC(shellWidget, value_mask, &gc_values);
2955 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2956 gc_values.background = XWhitePixel(xDisplay, xScreen);
2957 darkSquareGC = bwPieceGC
2958 = XtGetGC(shellWidget, value_mask, &gc_values);
2960 if (DefaultDepth(xDisplay, xScreen) == 1) {
2961 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
2962 gc_values.function = GXcopyInverted;
2963 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
2964 gc_values.function = GXcopy;
2965 if (XBlackPixel(xDisplay, xScreen) == 1) {
2966 bwPieceGC = darkSquareGC;
2967 wbPieceGC = copyInvertedGC;
2969 bwPieceGC = copyInvertedGC;
2970 wbPieceGC = lightSquareGC;
2974 gc_values.foreground = highlightSquareColor;
2975 gc_values.background = highlightSquareColor;
2976 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2978 gc_values.foreground = premoveHighlightColor;
2979 gc_values.background = premoveHighlightColor;
2980 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2982 gc_values.foreground = lightSquareColor;
2983 gc_values.background = darkSquareColor;
2984 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2986 gc_values.foreground = darkSquareColor;
2987 gc_values.background = lightSquareColor;
2988 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2990 gc_values.foreground = jailSquareColor;
2991 gc_values.background = jailSquareColor;
2992 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2994 gc_values.foreground = whitePieceColor;
2995 gc_values.background = darkSquareColor;
2996 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
2998 gc_values.foreground = whitePieceColor;
2999 gc_values.background = lightSquareColor;
3000 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3002 gc_values.foreground = whitePieceColor;
3003 gc_values.background = jailSquareColor;
3004 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3006 gc_values.foreground = blackPieceColor;
3007 gc_values.background = darkSquareColor;
3008 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3010 gc_values.foreground = blackPieceColor;
3011 gc_values.background = lightSquareColor;
3012 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3014 gc_values.foreground = blackPieceColor;
3015 gc_values.background = jailSquareColor;
3016 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3020 void loadXIM(xim, xmask, filename, dest, mask)
3033 fp = fopen(filename, "rb");
3035 fprintf(stderr, "%s: error loading XIM!\n", programName);
3042 for (y=0; y<h; ++y) {
3043 for (x=0; x<h; ++x) {
3048 XPutPixel(xim, x, y, blackPieceColor);
3050 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3053 XPutPixel(xim, x, y, darkSquareColor);
3055 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3058 XPutPixel(xim, x, y, whitePieceColor);
3060 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3063 XPutPixel(xim, x, y, lightSquareColor);
3065 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3071 /* create Pixmap of piece */
3072 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3074 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3077 /* create Pixmap of clipmask
3078 Note: We assume the white/black pieces have the same
3079 outline, so we make only 6 masks. This is okay
3080 since the XPM clipmask routines do the same. */
3082 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3084 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3087 /* now create the 1-bit version */
3088 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3091 values.foreground = 1;
3092 values.background = 0;
3094 /* Don't use XtGetGC, not read only */
3095 maskGC = XCreateGC(xDisplay, *mask,
3096 GCForeground | GCBackground, &values);
3097 XCopyPlane(xDisplay, temp, *mask, maskGC,
3098 0, 0, squareSize, squareSize, 0, 0, 1);
3099 XFreePixmap(xDisplay, temp);
3103 void CreateXIMPieces()
3108 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3113 /* The XSynchronize calls were copied from CreatePieces.
3114 Not sure if needed, but can't hurt */
3115 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3118 /* temp needed by loadXIM() */
3119 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3120 0, 0, ss, ss, AllPlanes, XYPixmap);
3122 if (strlen(appData.pixmapDirectory) == 0) {
3126 if (appData.monoMode) {
3127 DisplayFatalError("XIM pieces cannot be used in monochrome mode",
3131 fprintf(stderr, "\nLoading XIMs...\n");
3133 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3134 fprintf(stderr, "%d", piece+1);
3135 for (kind=0; kind<4; kind++) {
3136 fprintf(stderr, ".");
3137 sprintf(buf, "%s/%c%s%u.xim",
3138 ExpandPathName(appData.pixmapDirectory),
3139 ToLower(PieceToChar((ChessSquare)piece)),
3141 ximPieceBitmap[kind][piece] =
3142 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3143 0, 0, ss, ss, AllPlanes, XYPixmap);
3144 if (appData.debugMode)
3145 fprintf(stderr, "(File:%s:) ", buf);
3146 loadXIM(ximPieceBitmap[kind][piece],
3148 &(xpmPieceBitmap[kind][piece]),
3149 &(ximMaskPm[piece%6]));
3151 fprintf(stderr," ");
3153 /* Load light and dark squares */
3154 /* If the LSQ and DSQ pieces don't exist, we will
3155 draw them with solid squares. */
3156 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3157 if (access(buf, 0) != 0) {
3161 fprintf(stderr, "light square ");
3163 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3164 0, 0, ss, ss, AllPlanes, XYPixmap);
3165 if (appData.debugMode)
3166 fprintf(stderr, "(File:%s:) ", buf);
3168 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3169 fprintf(stderr, "dark square ");
3170 sprintf(buf, "%s/dsq%u.xim",
3171 ExpandPathName(appData.pixmapDirectory), ss);
3172 if (appData.debugMode)
3173 fprintf(stderr, "(File:%s:) ", buf);
3175 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3176 0, 0, ss, ss, AllPlanes, XYPixmap);
3177 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3178 xpmJailSquare = xpmLightSquare;
3180 fprintf(stderr, "Done.\n");
3182 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3186 void CreateXPMPieces()
3190 u_int ss = squareSize;
3192 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3193 XpmColorSymbol symbols[4];
3196 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3197 if (appData.debugMode) {
3198 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3199 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3203 /* The XSynchronize calls were copied from CreatePieces.
3204 Not sure if needed, but can't hurt */
3205 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3207 /* Setup translations so piece colors match square colors */
3208 symbols[0].name = "light_piece";
3209 symbols[0].value = appData.whitePieceColor;
3210 symbols[1].name = "dark_piece";
3211 symbols[1].value = appData.blackPieceColor;
3212 symbols[2].name = "light_square";
3213 symbols[2].value = appData.lightSquareColor;
3214 symbols[3].name = "dark_square";
3215 symbols[3].value = appData.darkSquareColor;
3217 attr.valuemask = XpmColorSymbols;
3218 attr.colorsymbols = symbols;
3219 attr.numsymbols = 4;
3221 if (appData.monoMode) {
3222 DisplayFatalError("XPM pieces cannot be used in monochrome mode",
3226 if (strlen(appData.pixmapDirectory) == 0) {
3227 XpmPieces* pieces = builtInXpms;
3230 while (pieces->size != squareSize && pieces->size) pieces++;
3231 if (!pieces->size) {
3232 fprintf(stderr, "No builtin XPM pieces of size %d\n", squareSize);
3235 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3236 for (kind=0; kind<4; kind++) {
3238 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3239 pieces->xpm[piece][kind],
3240 &(xpmPieceBitmap[kind][piece]),
3241 NULL, &attr)) != 0) {
3242 fprintf(stderr, "Error %d loading XPM image \"%s\"\n",
3249 xpmJailSquare = xpmLightSquare;
3253 fprintf(stderr, "\nLoading XPMs...\n");
3256 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3257 fprintf(stderr, "%d ", piece+1);
3258 for (kind=0; kind<4; kind++) {
3259 sprintf(buf, "%s/%c%s%u.xpm",
3260 ExpandPathName(appData.pixmapDirectory),
3261 ToLower(PieceToChar((ChessSquare)piece)),
3263 if (appData.debugMode) {
3264 fprintf(stderr, "(File:%s:) ", buf);
3266 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3267 &(xpmPieceBitmap[kind][piece]),
3268 NULL, &attr)) != 0) {
3269 fprintf(stderr, "Error %d loading XPM file \"%s\"\n",
3275 /* Load light and dark squares */
3276 /* If the LSQ and DSQ pieces don't exist, we will
3277 draw them with solid squares. */
3278 fprintf(stderr, "light square ");
3279 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3280 if (access(buf, 0) != 0) {
3284 if (appData.debugMode)
3285 fprintf(stderr, "(File:%s:) ", buf);
3287 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3288 &xpmLightSquare, NULL, &attr)) != 0) {
3289 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
3292 fprintf(stderr, "dark square ");
3293 sprintf(buf, "%s/dsq%u.xpm",
3294 ExpandPathName(appData.pixmapDirectory), ss);
3295 if (appData.debugMode) {
3296 fprintf(stderr, "(File:%s:) ", buf);
3298 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3299 &xpmDarkSquare, NULL, &attr)) != 0) {
3300 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
3304 xpmJailSquare = xpmLightSquare;
3305 fprintf(stderr, "Done.\n");
3307 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3310 #endif /* HAVE_LIBXPM */
3313 /* No built-in bitmaps */
3318 u_int ss = squareSize;
3320 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3323 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3324 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3325 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3326 ss, kind == SOLID ? 's' : 'o');
3327 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3331 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3335 /* With built-in bitmaps */
3338 BuiltInBits* bib = builtInBits;
3341 u_int ss = squareSize;
3343 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3346 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3348 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3349 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3350 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3351 ss, kind == SOLID ? 's' : 'o');
3352 ReadBitmap(&pieceBitmap[kind][piece], buf,
3353 bib->bits[kind][piece], ss, ss);
3357 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3362 void ReadBitmap(pm, name, bits, wreq, hreq)
3365 unsigned char bits[];
3371 char msg[MSG_SIZ], fullname[MSG_SIZ];
3373 if (*appData.bitmapDirectory != NULLCHAR) {
3374 strcpy(fullname, appData.bitmapDirectory);
3375 strcat(fullname, "/");
3376 strcat(fullname, name);
3377 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3378 &w, &h, pm, &x_hot, &y_hot);
3379 if (errcode != BitmapSuccess) {
3381 case BitmapOpenFailed:
3382 sprintf(msg, "Can't open bitmap file %s", fullname);
3384 case BitmapFileInvalid:
3385 sprintf(msg, "Invalid bitmap in file %s", fullname);
3387 case BitmapNoMemory:
3388 sprintf(msg, "Ran out of memory reading bitmap file %s",
3392 sprintf(msg, "Unknown XReadBitmapFile error %d on file %s",
3396 fprintf(stderr, "%s: %s...using built-in\n",
3398 } else if (w != wreq || h != hreq) {
3400 "%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n",
3401 programName, fullname, w, h, wreq, hreq);
3407 fprintf(stderr, "%s: No built-in bitmap for %s; giving up\n",
3411 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3420 if (lineGap == 0) return;
3421 for (i = 0; i < BOARD_SIZE + 1; i++) {
3422 gridSegments[i].x1 = 0;
3423 gridSegments[i].x2 =
3424 lineGap + BOARD_SIZE * (squareSize + lineGap);
3425 gridSegments[i].y1 = gridSegments[i].y2
3426 = lineGap / 2 + (i * (squareSize + lineGap));
3428 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3429 gridSegments[i + BOARD_SIZE + 1].y2 =
3430 BOARD_SIZE * (squareSize + lineGap);
3431 gridSegments[i + BOARD_SIZE + 1].x1 =
3432 gridSegments[i + BOARD_SIZE + 1].x2
3433 = lineGap / 2 + (i * (squareSize + lineGap));
3437 static void MenuBarSelect(w, addr, index)
3442 XtActionProc proc = (XtActionProc) addr;
3444 (proc)(NULL, NULL, NULL, NULL);
3447 void CreateMenuBarPopup(parent, name, mb)
3457 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3460 XtSetArg(args[j], XtNleftMargin, 20); j++;
3461 XtSetArg(args[j], XtNrightMargin, 20); j++;
3463 while (mi->string != NULL) {
3464 if (strcmp(mi->string, "----") == 0) {
3465 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3468 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3470 XtAddCallback(entry, XtNcallback,
3471 (XtCallbackProc) MenuBarSelect,
3472 (caddr_t) mi->proc);
3478 Widget CreateMenuBar(mb)
3482 Widget anchor, menuBar;
3484 char menuName[MSG_SIZ];
3487 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3488 XtSetArg(args[j], XtNvSpace, 0); j++;
3489 XtSetArg(args[j], XtNborderWidth, 0); j++;
3490 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3491 formWidget, args, j);
3493 while (mb->name != NULL) {
3494 strcpy(menuName, "menu");
3495 strcat(menuName, mb->name);
3497 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3500 shortName[0] = mb->name[0];
3501 shortName[1] = NULLCHAR;
3502 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3504 XtSetArg(args[j], XtNborderWidth, 0); j++;
3505 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3507 CreateMenuBarPopup(menuBar, menuName, mb);
3513 Widget CreateButtonBar(mi)
3517 Widget button, buttonBar;
3521 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3523 XtSetArg(args[j], XtNhSpace, 0); j++;
3525 XtSetArg(args[j], XtNborderWidth, 0); j++;
3526 XtSetArg(args[j], XtNvSpace, 0); j++;
3527 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3528 formWidget, args, j);
3530 while (mi->string != NULL) {
3533 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3534 XtSetArg(args[j], XtNborderWidth, 0); j++;
3536 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3537 buttonBar, args, j);
3538 XtAddCallback(button, XtNcallback,
3539 (XtCallbackProc) MenuBarSelect,
3540 (caddr_t) mi->proc);
3547 CreatePieceMenu(name, color)
3554 ChessSquare selection;
3556 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3557 boardWidget, args, 0);
3559 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3560 String item = pieceMenuStrings[color][i];
3562 if (strcmp(item, "----") == 0) {
3563 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3566 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3568 selection = pieceMenuTranslation[color][i];
3569 XtAddCallback(entry, XtNcallback,
3570 (XtCallbackProc) PieceMenuSelect,
3571 (caddr_t) selection);
3572 if (selection == WhitePawn || selection == BlackPawn) {
3573 XtSetArg(args[0], XtNpopupOnEntry, entry);
3574 XtSetValues(menu, args, 1);
3587 ChessSquare selection;
3589 whitePieceMenu = CreatePieceMenu("menuW", 0);
3590 blackPieceMenu = CreatePieceMenu("menuB", 1);
3592 XtRegisterGrabAction(PieceMenuPopup, True,
3593 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3594 GrabModeAsync, GrabModeAsync);
3596 XtSetArg(args[0], XtNlabel, "Drop");
3597 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3598 boardWidget, args, 1);
3599 for (i = 0; i < DROP_MENU_SIZE; i++) {
3600 String item = dropMenuStrings[i];
3602 if (strcmp(item, "----") == 0) {
3603 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3606 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3608 selection = dropMenuTranslation[i];
3609 XtAddCallback(entry, XtNcallback,
3610 (XtCallbackProc) DropMenuSelect,
3611 (caddr_t) selection);
3616 void SetupDropMenu()
3624 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3625 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3626 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3627 dmEnables[i].piece);
3628 XtSetSensitive(entry, p != NULL || !appData.testLegality
3629 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3630 && !appData.icsActive));
3632 while (p && *p++ == dmEnables[i].piece) count++;
3633 sprintf(label, "%s %d", dmEnables[i].widget, count);
3635 XtSetArg(args[j], XtNlabel, label); j++;
3636 XtSetValues(entry, args, j);
3640 void PieceMenuPopup(w, event, params, num_params)
3644 Cardinal *num_params;
3647 if (event->type != ButtonPress) return;
3648 if (errorUp) ErrorPopDown();
3652 whichMenu = params[0];
3654 case IcsPlayingWhite:
3655 case IcsPlayingBlack:
3657 case MachinePlaysWhite:
3658 case MachinePlaysBlack:
3659 if (appData.testLegality &&
3660 gameInfo.variant != VariantBughouse &&
3661 gameInfo.variant != VariantCrazyhouse) return;
3663 whichMenu = "menuD";
3669 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3670 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3671 pmFromX = pmFromY = -1;
3675 pmFromX = BOARD_SIZE - 1 - pmFromX;
3677 pmFromY = BOARD_SIZE - 1 - pmFromY;
3679 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3682 static void PieceMenuSelect(w, piece, junk)
3687 if (pmFromX < 0 || pmFromY < 0) return;
3688 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3691 static void DropMenuSelect(w, piece, junk)
3696 if (pmFromX < 0 || pmFromY < 0) return;
3697 DropMenuEvent(piece, pmFromX, pmFromY);
3700 void WhiteClock(w, event, prms, nprms)
3706 if (gameMode == EditPosition || gameMode == IcsExamining) {
3707 SetWhiteToPlayEvent();
3708 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3713 void BlackClock(w, event, prms, nprms)
3719 if (gameMode == EditPosition || gameMode == IcsExamining) {
3720 SetBlackToPlayEvent();
3721 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3728 * If the user selects on a border boundary, return -1; if off the board,
3729 * return -2. Otherwise map the event coordinate to the square.
3731 int EventToSquare(x, limit)
3739 if ((x % (squareSize + lineGap)) >= squareSize)
3741 x /= (squareSize + lineGap);
3747 static void do_flash_delay(msec)
3753 static void drawHighlight(file, rank, gc)
3759 if (lineGap == 0 || appData.blindfold) return;
3762 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3763 (squareSize + lineGap);
3764 y = lineGap/2 + rank * (squareSize + lineGap);
3766 x = lineGap/2 + file * (squareSize + lineGap);
3767 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3768 (squareSize + lineGap);
3771 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3772 squareSize+lineGap, squareSize+lineGap);
3775 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3776 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3779 SetHighlights(fromX, fromY, toX, toY)
3780 int fromX, fromY, toX, toY;
3782 if (hi1X != fromX || hi1Y != fromY) {
3783 if (hi1X >= 0 && hi1Y >= 0) {
3784 drawHighlight(hi1X, hi1Y, lineGC);
3786 if (fromX >= 0 && fromY >= 0) {
3787 drawHighlight(fromX, fromY, highlineGC);
3790 if (hi2X != toX || hi2Y != toY) {
3791 if (hi2X >= 0 && hi2Y >= 0) {
3792 drawHighlight(hi2X, hi2Y, lineGC);
3794 if (toX >= 0 && toY >= 0) {
3795 drawHighlight(toX, toY, highlineGC);
3807 SetHighlights(-1, -1, -1, -1);
3812 SetPremoveHighlights(fromX, fromY, toX, toY)
3813 int fromX, fromY, toX, toY;
3815 if (pm1X != fromX || pm1Y != fromY) {
3816 if (pm1X >= 0 && pm1Y >= 0) {
3817 drawHighlight(pm1X, pm1Y, lineGC);
3819 if (fromX >= 0 && fromY >= 0) {
3820 drawHighlight(fromX, fromY, prelineGC);
3823 if (pm2X != toX || pm2Y != toY) {
3824 if (pm2X >= 0 && pm2Y >= 0) {
3825 drawHighlight(pm2X, pm2Y, lineGC);
3827 if (toX >= 0 && toY >= 0) {
3828 drawHighlight(toX, toY, prelineGC);
3838 ClearPremoveHighlights()
3840 SetPremoveHighlights(-1, -1, -1, -1);
3843 static void BlankSquare(x, y, color, piece, dest)
3848 if (useImages && useImageSqs) {
3852 pm = xpmLightSquare;
3857 case 2: /* neutral */
3862 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3863 squareSize, squareSize, x, y);
3873 case 2: /* neutral */
3878 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3883 I split out the routines to draw a piece so that I could
3884 make a generic flash routine.
3886 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3888 int square_color, x, y;
3891 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3892 switch (square_color) {
3894 case 2: /* neutral */
3896 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3897 ? *pieceToOutline(piece)
3898 : *pieceToSolid(piece),
3899 dest, bwPieceGC, 0, 0,
3900 squareSize, squareSize, x, y);
3903 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3904 ? *pieceToSolid(piece)
3905 : *pieceToOutline(piece),
3906 dest, wbPieceGC, 0, 0,
3907 squareSize, squareSize, x, y);
3912 static void monoDrawPiece(piece, square_color, x, y, dest)
3914 int square_color, x, y;
3917 switch (square_color) {
3919 case 2: /* neutral */
3921 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3922 ? *pieceToOutline(piece)
3923 : *pieceToSolid(piece),
3924 dest, bwPieceGC, 0, 0,
3925 squareSize, squareSize, x, y, 1);
3928 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3929 ? *pieceToSolid(piece)
3930 : *pieceToOutline(piece),
3931 dest, wbPieceGC, 0, 0,
3932 squareSize, squareSize, x, y, 1);
3937 static void colorDrawPiece(piece, square_color, x, y, dest)
3939 int square_color, x, y;
3942 switch (square_color) {
3944 XCopyPlane(xDisplay, *pieceToSolid(piece),
3945 dest, (int) piece < (int) BlackPawn
3946 ? wlPieceGC : blPieceGC, 0, 0,
3947 squareSize, squareSize, x, y, 1);
3950 XCopyPlane(xDisplay, *pieceToSolid(piece),
3951 dest, (int) piece < (int) BlackPawn
3952 ? wdPieceGC : bdPieceGC, 0, 0,
3953 squareSize, squareSize, x, y, 1);
3955 case 2: /* neutral */
3957 XCopyPlane(xDisplay, *pieceToSolid(piece),
3958 dest, (int) piece < (int) BlackPawn
3959 ? wjPieceGC : bjPieceGC, 0, 0,
3960 squareSize, squareSize, x, y, 1);
3965 static void colorDrawPieceImage(piece, square_color, x, y, dest)
3967 int square_color, x, y;
3972 switch (square_color) {
3974 case 2: /* neutral */
3976 if ((int)piece < (int) BlackPawn) {
3984 if ((int)piece < (int) BlackPawn) {
3992 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
3993 dest, wlPieceGC, 0, 0,
3994 squareSize, squareSize, x, y);
3997 typedef void (*DrawFunc)();
3999 DrawFunc ChooseDrawFunc()
4001 if (appData.monoMode) {
4002 if (DefaultDepth(xDisplay, xScreen) == 1) {
4003 return monoDrawPiece_1bit;
4005 return monoDrawPiece;
4009 return colorDrawPieceImage;
4011 return colorDrawPiece;
4015 void DrawSquare(row, column, piece, do_flash)
4016 int row, column, do_flash;
4019 int square_color, x, y, direction, font_ascent, font_descent;
4022 XCharStruct overall;
4026 /* Calculate delay in milliseconds (2-delays per complete flash) */
4027 flash_delay = 500 / appData.flashRate;
4030 x = lineGap + ((BOARD_SIZE-1)-column) *
4031 (squareSize + lineGap);
4032 y = lineGap + row * (squareSize + lineGap);
4034 x = lineGap + column * (squareSize + lineGap);
4035 y = lineGap + ((BOARD_SIZE-1)-row) *
4036 (squareSize + lineGap);
4039 square_color = ((column + row) % 2) == 1;
4041 if (piece == EmptySquare || appData.blindfold) {
4042 BlankSquare(x, y, square_color, piece, xBoardWindow);
4044 drawfunc = ChooseDrawFunc();
4045 if (do_flash && appData.flashCount > 0) {
4046 for (i=0; i<appData.flashCount; ++i) {
4048 drawfunc(piece, square_color, x, y, xBoardWindow);
4049 XSync(xDisplay, False);
4050 do_flash_delay(flash_delay);
4052 BlankSquare(x, y, square_color, piece, xBoardWindow);
4053 XSync(xDisplay, False);
4054 do_flash_delay(flash_delay);
4057 drawfunc(piece, square_color, x, y, xBoardWindow);
4060 string[1] = NULLCHAR;
4061 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4062 string[0] = 'a' + column;
4063 XTextExtents(coordFontStruct, string, 1, &direction,
4064 &font_ascent, &font_descent, &overall);
4065 if (appData.monoMode) {
4066 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4067 x + squareSize - overall.width - 2,
4068 y + squareSize - font_descent - 1, string, 1);
4070 XDrawString(xDisplay, xBoardWindow, coordGC,
4071 x + squareSize - overall.width - 2,
4072 y + squareSize - font_descent - 1, string, 1);
4075 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4076 string[0] = '1' + row;
4077 XTextExtents(coordFontStruct, string, 1, &direction,
4078 &font_ascent, &font_descent, &overall);
4079 if (appData.monoMode) {
4080 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4081 x + 2, y + font_ascent + 1, string, 1);
4083 XDrawString(xDisplay, xBoardWindow, coordGC,
4084 x + 2, y + font_ascent + 1, string, 1);
4090 /* Why is this needed on some versions of X? */
4091 void EventProc(widget, unused, event)
4096 if (!XtIsRealized(widget))
4099 switch (event->type) {
4101 if (event->xexpose.count > 0) return; /* no clipping is done */
4102 XDrawPosition(widget, True, NULL);
4110 void DrawPosition(fullRedraw, board)
4111 /*Boolean*/int fullRedraw;
4114 XDrawPosition(boardWidget, fullRedraw, board);
4117 /* Returns 1 if there are "too many" differences between b1 and b2
4118 (i.e. more than 1 move was made) */
4119 static int too_many_diffs(b1, b2)
4125 for (i=0; i<BOARD_SIZE; ++i) {
4126 for (j=0; j<BOARD_SIZE; ++j) {
4127 if (b1[i][j] != b2[i][j]) {
4128 if (++c > 4) /* Castling causes 4 diffs */
4137 /* Matrix describing castling maneuvers */
4138 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4139 static int castling_matrix[4][5] = {
4140 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4141 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4142 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4143 { 7, 7, 4, 5, 6 } /* 0-0, black */
4146 /* Checks whether castling occurred. If it did, *rrow and *rcol
4147 are set to the destination (row,col) of the rook that moved.
4149 Returns 1 if castling occurred, 0 if not.
4151 Note: Only handles a max of 1 castling move, so be sure
4152 to call too_many_diffs() first.
4154 static int check_castle_draw(newb, oldb, rrow, rcol)
4161 /* For each type of castling... */
4162 for (i=0; i<4; ++i) {
4163 r = castling_matrix[i];
4165 /* Check the 4 squares involved in the castling move */
4167 for (j=1; j<=4; ++j) {
4168 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4175 /* All 4 changed, so it must be a castling move */
4184 static int damage[BOARD_SIZE][BOARD_SIZE];
4187 * event handler for redrawing the board
4189 void XDrawPosition(w, repaint, board)
4191 /*Boolean*/int repaint;
4195 static int lastFlipView = 0;
4196 static int lastBoardValid = 0;
4197 static Board lastBoard;
4201 if (board == NULL) {
4202 if (!lastBoardValid) return;
4205 if (!lastBoardValid || lastFlipView != flipView) {
4206 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4207 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4212 * It would be simpler to clear the window with XClearWindow()
4213 * but this causes a very distracting flicker.
4216 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4218 /* If too much changes (begin observing new game, etc.), don't
4220 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4222 /* Special check for castling so we don't flash both the king
4223 and the rook (just flash the king). */
4225 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4226 /* Draw rook with NO flashing. King will be drawn flashing later */
4227 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4228 lastBoard[rrow][rcol] = board[rrow][rcol];
4232 /* First pass -- Draw (newly) empty squares and repair damage.
4233 This prevents you from having a piece show up twice while it
4234 is flashing on its new square */
4235 for (i = 0; i < BOARD_SIZE; i++)
4236 for (j = 0; j < BOARD_SIZE; j++)
4237 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4239 DrawSquare(i, j, board[i][j], 0);
4240 damage[i][j] = False;
4243 /* Second pass -- Draw piece(s) in new position and flash them */
4244 for (i = 0; i < BOARD_SIZE; i++)
4245 for (j = 0; j < BOARD_SIZE; j++)
4246 if (board[i][j] != lastBoard[i][j]) {
4247 DrawSquare(i, j, board[i][j], do_flash);
4251 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4252 gridSegments, (BOARD_SIZE + 1) * 2);
4254 for (i = 0; i < BOARD_SIZE; i++)
4255 for (j = 0; j < BOARD_SIZE; j++) {
4256 DrawSquare(i, j, board[i][j], 0);
4257 damage[i][j] = False;
4261 CopyBoard(lastBoard, board);
4263 lastFlipView = flipView;
4265 /* Draw highlights */
4266 if (pm1X >= 0 && pm1Y >= 0) {
4267 drawHighlight(pm1X, pm1Y, prelineGC);
4269 if (pm2X >= 0 && pm2Y >= 0) {
4270 drawHighlight(pm2X, pm2Y, prelineGC);
4272 if (hi1X >= 0 && hi1Y >= 0) {
4273 drawHighlight(hi1X, hi1Y, highlineGC);
4275 if (hi2X >= 0 && hi2Y >= 0) {
4276 drawHighlight(hi2X, hi2Y, highlineGC);
4279 /* If piece being dragged around board, must redraw that too */
4282 XSync(xDisplay, False);
4287 * event handler for redrawing the board
4289 void DrawPositionProc(w, event, prms, nprms)
4295 XDrawPosition(w, True, NULL);
4300 * event handler for parsing user moves
4302 void HandleUserMove(w, event, prms, nprms)
4309 Boolean saveAnimate;
4310 static int second = 0;
4312 if (w != boardWidget || errorExitStatus != -1) return;
4314 if (event->type == ButtonPress) ErrorPopDown();
4317 if (event->type == ButtonPress) {
4318 XtPopdown(promotionShell);
4319 XtDestroyWidget(promotionShell);
4320 promotionUp = False;
4328 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4329 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4330 if (!flipView && y >= 0) {
4331 y = BOARD_SIZE - 1 - y;
4333 if (flipView && x >= 0) {
4334 x = BOARD_SIZE - 1 - x;
4338 if (event->type == ButtonPress) {
4340 if (OKToStartUserMove(x, y)) {
4344 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4345 if (appData.highlightDragging) {
4346 SetHighlights(x, y, -1, -1);
4354 if (event->type == ButtonPress && gameMode != EditPosition &&
4358 /* Check if clicking again on the same color piece */
4359 fromP = boards[currentMove][fromY][fromX];
4360 toP = boards[currentMove][y][x];
4361 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4362 WhitePawn <= toP && toP <= WhiteKing) ||
4363 (BlackPawn <= fromP && fromP <= BlackKing &&
4364 BlackPawn <= toP && toP <= BlackKing)) {
4365 /* Clicked again on same color piece -- changed his mind */
4366 second = (x == fromX && y == fromY);
4367 if (appData.highlightDragging) {
4368 SetHighlights(x, y, -1, -1);
4372 if (OKToStartUserMove(x, y)) {
4375 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4381 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4382 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4383 if (appData.animateDragging) {
4384 /* Undo animation damage if any */
4385 DrawPosition(FALSE, NULL);
4388 /* Second up/down in same square; just abort move */
4393 ClearPremoveHighlights();
4395 /* First upclick in same square; start click-click mode */
4396 SetHighlights(x, y, -1, -1);
4401 /* Completed move */
4404 saveAnimate = appData.animate;
4405 if (event->type == ButtonPress) {
4406 /* Finish clickclick move */
4407 if (appData.animate || appData.highlightLastMove) {
4408 SetHighlights(fromX, fromY, toX, toY);
4413 /* Finish drag move */
4414 if (appData.highlightLastMove) {
4415 SetHighlights(fromX, fromY, toX, toY);
4419 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4420 /* Don't animate move and drag both */
4421 appData.animate = FALSE;
4423 if (IsPromotion(fromX, fromY, toX, toY)) {
4424 if (appData.alwaysPromoteToQueen) {
4425 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4426 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4427 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4430 SetHighlights(fromX, fromY, toX, toY);
4434 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4435 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4436 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4439 appData.animate = saveAnimate;
4440 if (appData.animate || appData.animateDragging) {
4441 /* Undo animation damage if needed */
4442 DrawPosition(FALSE, NULL);
4446 void AnimateUserMove (Widget w, XEvent * event,
4447 String * params, Cardinal * nParams)
4449 DragPieceMove(event->xmotion.x, event->xmotion.y);
4452 Widget CommentCreate(name, text, mutable, callback, lines)
4454 int /*Boolean*/ mutable;
4455 XtCallbackProc callback;
4459 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4464 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4465 XtGetValues(boardWidget, args, j);
4468 XtSetArg(args[j], XtNresizable, True); j++;
4471 XtCreatePopupShell(name, topLevelShellWidgetClass,
4472 shellWidget, args, j);
4475 XtCreatePopupShell(name, transientShellWidgetClass,
4476 shellWidget, args, j);
4479 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4480 layoutArgs, XtNumber(layoutArgs));
4482 XtCreateManagedWidget("form", formWidgetClass, layout,
4483 formArgs, XtNumber(formArgs));
4487 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4488 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4490 XtSetArg(args[j], XtNstring, text); j++;
4491 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4492 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4493 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4494 XtSetArg(args[j], XtNright, XtChainRight); j++;
4495 XtSetArg(args[j], XtNresizable, True); j++;
4496 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4498 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4500 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4501 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4503 XtSetArg(args[j], XtNautoFill, True); j++;
4504 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4506 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4510 XtSetArg(args[j], XtNfromVert, edit); j++;
4511 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4512 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4513 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4514 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4516 XtCreateManagedWidget("ok", commandWidgetClass, form, args, j);
4517 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4520 XtSetArg(args[j], XtNfromVert, edit); j++;
4521 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4522 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4523 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4524 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4525 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4527 XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);
4528 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4531 XtSetArg(args[j], XtNfromVert, edit); j++;
4532 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4533 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4534 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4535 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4536 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4538 XtCreateManagedWidget("clear", commandWidgetClass, form, args, j);
4539 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4542 XtSetArg(args[j], XtNfromVert, edit); j++;
4543 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4544 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4545 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4546 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4548 XtCreateManagedWidget("close", commandWidgetClass, form, args, j);
4549 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4552 XtSetArg(args[j], XtNfromVert, edit); j++;
4553 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4554 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4555 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4556 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4557 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4559 XtCreateManagedWidget("edit", commandWidgetClass, form, args, j);
4560 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4563 XtRealizeWidget(shell);
4565 if (commentX == -1) {
4568 Dimension pw_height;
4569 Dimension ew_height;
4572 XtSetArg(args[j], XtNheight, &ew_height); j++;
4573 XtGetValues(edit, args, j);
4576 XtSetArg(args[j], XtNheight, &pw_height); j++;
4577 XtGetValues(shell, args, j);
4578 commentH = pw_height + (lines - 1) * ew_height;
4579 commentW = bw_width - 16;
4581 XSync(xDisplay, False);
4583 /* This code seems to tickle an X bug if it is executed too soon
4584 after xboard starts up. The coordinates get transformed as if
4585 the main window was positioned at (0, 0).
4587 XtTranslateCoords(shellWidget,
4588 (bw_width - commentW) / 2, 0 - commentH / 2,
4589 &commentX, &commentY);
4591 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4592 RootWindowOfScreen(XtScreen(shellWidget)),
4593 (bw_width - commentW) / 2, 0 - commentH / 2,
4598 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4601 XtSetArg(args[j], XtNheight, commentH); j++;
4602 XtSetArg(args[j], XtNwidth, commentW); j++;
4603 XtSetArg(args[j], XtNx, commentX); j++;
4604 XtSetArg(args[j], XtNy, commentY); j++;
4605 XtSetValues(shell, args, j);
4606 XtSetKeyboardFocus(shell, edit);
4611 /* Used for analysis window and ICS input window */
4612 Widget MiscCreate(name, text, mutable, callback, lines)
4614 int /*Boolean*/ mutable;
4615 XtCallbackProc callback;
4619 Widget shell, layout, form, edit;
4621 Dimension bw_width, pw_height, ew_height, w, h;
4627 XtSetArg(args[j], XtNresizable, True); j++;
4630 XtCreatePopupShell(name, topLevelShellWidgetClass,
4631 shellWidget, args, j);
4634 XtCreatePopupShell(name, transientShellWidgetClass,
4635 shellWidget, args, j);
4638 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4639 layoutArgs, XtNumber(layoutArgs));
4641 XtCreateManagedWidget("form", formWidgetClass, layout,
4642 formArgs, XtNumber(formArgs));
4646 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4647 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4649 XtSetArg(args[j], XtNstring, text); j++;
4650 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4651 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4652 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4653 XtSetArg(args[j], XtNright, XtChainRight); j++;
4654 XtSetArg(args[j], XtNresizable, True); j++;
4656 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4658 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4659 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4661 XtSetArg(args[j], XtNautoFill, True); j++;
4662 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4664 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4666 XtRealizeWidget(shell);
4669 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4670 XtGetValues(boardWidget, args, j);
4673 XtSetArg(args[j], XtNheight, &ew_height); j++;
4674 XtGetValues(edit, args, j);
4677 XtSetArg(args[j], XtNheight, &pw_height); j++;
4678 XtGetValues(shell, args, j);
4679 h = pw_height + (lines - 1) * ew_height;
4682 XSync(xDisplay, False);
4684 /* This code seems to tickle an X bug if it is executed too soon
4685 after xboard starts up. The coordinates get transformed as if
4686 the main window was positioned at (0, 0).
4688 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4690 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4691 RootWindowOfScreen(XtScreen(shellWidget)),
4692 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4696 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4699 XtSetArg(args[j], XtNheight, h); j++;
4700 XtSetArg(args[j], XtNwidth, w); j++;
4701 XtSetArg(args[j], XtNx, x); j++;
4702 XtSetArg(args[j], XtNy, y); j++;
4703 XtSetValues(shell, args, j);
4709 static int savedIndex; /* gross that this is global */
4711 void EditCommentPopUp(index, title, text)
4720 if (text == NULL) text = "";
4722 if (editShell == NULL) {
4724 CommentCreate(title, text, True, EditCommentCallback, 4);
4725 XtRealizeWidget(editShell);
4726 CatchDeleteWindow(editShell, "EditCommentPopDown");
4728 edit = XtNameToWidget(editShell, "*form.text");
4730 XtSetArg(args[j], XtNstring, text); j++;
4731 XtSetValues(edit, args, j);
4733 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4734 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4735 XtSetValues(editShell, args, j);
4738 XtPopup(editShell, XtGrabNone);
4742 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4743 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4747 void EditCommentCallback(w, client_data, call_data)
4749 XtPointer client_data, call_data;
4757 XtSetArg(args[j], XtNlabel, &name); j++;
4758 XtGetValues(w, args, j);
4760 if (strcmp(name, "ok") == 0) {
4761 edit = XtNameToWidget(editShell, "*form.text");
4763 XtSetArg(args[j], XtNstring, &val); j++;
4764 XtGetValues(edit, args, j);
4765 ReplaceComment(savedIndex, val);
4766 EditCommentPopDown();
4767 } else if (strcmp(name, "cancel") == 0) {
4768 EditCommentPopDown();
4769 } else if (strcmp(name, "clear") == 0) {
4770 edit = XtNameToWidget(editShell, "*form.text");
4771 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4772 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4776 void EditCommentPopDown()
4781 if (!editUp) return;
4783 XtSetArg(args[j], XtNx, &commentX); j++;
4784 XtSetArg(args[j], XtNy, &commentY); j++;
4785 XtSetArg(args[j], XtNheight, &commentH); j++;
4786 XtSetArg(args[j], XtNwidth, &commentW); j++;
4787 XtGetValues(editShell, args, j);
4788 XtPopdown(editShell);
4791 XtSetArg(args[j], XtNleftBitmap, None); j++;
4792 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4796 void ICSInputBoxPopUp()
4801 char *title = "ICS Input";
4804 if (ICSInputShell == NULL) {
4805 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4806 tr = XtParseTranslationTable(ICSInputTranslations);
4807 edit = XtNameToWidget(ICSInputShell, "*form.text");
4808 XtOverrideTranslations(edit, tr);
4809 XtRealizeWidget(ICSInputShell);
4810 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4813 edit = XtNameToWidget(ICSInputShell, "*form.text");
4815 XtSetArg(args[j], XtNstring, ""); j++;
4816 XtSetValues(edit, args, j);
4818 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4819 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4820 XtSetValues(ICSInputShell, args, j);
4823 XtPopup(ICSInputShell, XtGrabNone);
4824 XtSetKeyboardFocus(ICSInputShell, edit);
4826 ICSInputBoxUp = True;
4828 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4829 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4833 void ICSInputSendText()
4840 edit = XtNameToWidget(ICSInputShell, "*form.text");
4842 XtSetArg(args[j], XtNstring, &val); j++;
4843 XtGetValues(edit, args, j);
4844 SendMultiLineToICS(val);
4845 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4846 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4849 void ICSInputBoxPopDown()
4854 if (!ICSInputBoxUp) return;
4856 XtPopdown(ICSInputShell);
4857 ICSInputBoxUp = False;
4859 XtSetArg(args[j], XtNleftBitmap, None); j++;
4860 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4864 void CommentPopUp(title, text)
4871 if (commentShell == NULL) {
4873 CommentCreate(title, text, False, CommentCallback, 4);
4874 XtRealizeWidget(commentShell);
4875 CatchDeleteWindow(commentShell, "CommentPopDown");
4877 edit = XtNameToWidget(commentShell, "*form.text");
4879 XtSetArg(args[j], XtNstring, text); j++;
4880 XtSetValues(edit, args, j);
4882 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4883 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4884 XtSetValues(commentShell, args, j);
4887 XtPopup(commentShell, XtGrabNone);
4888 XSync(xDisplay, False);
4893 void AnalysisPopUp(title, text)
4900 if (analysisShell == NULL) {
4901 analysisShell = MiscCreate(title, text, False, NULL, 4);
4902 XtRealizeWidget(analysisShell);
4903 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4906 edit = XtNameToWidget(analysisShell, "*form.text");
4908 XtSetArg(args[j], XtNstring, text); j++;
4909 XtSetValues(edit, args, j);
4911 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4912 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4913 XtSetValues(analysisShell, args, j);
4917 XtPopup(analysisShell, XtGrabNone);
4919 XSync(xDisplay, False);
4924 void CommentCallback(w, client_data, call_data)
4926 XtPointer client_data, call_data;
4933 XtSetArg(args[j], XtNlabel, &name); j++;
4934 XtGetValues(w, args, j);
4936 if (strcmp(name, "close") == 0) {
4938 } else if (strcmp(name, "edit") == 0) {
4945 void CommentPopDown()
4950 if (!commentUp) return;
4952 XtSetArg(args[j], XtNx, &commentX); j++;
4953 XtSetArg(args[j], XtNy, &commentY); j++;
4954 XtSetArg(args[j], XtNwidth, &commentW); j++;
4955 XtSetArg(args[j], XtNheight, &commentH); j++;
4956 XtGetValues(commentShell, args, j);
4957 XtPopdown(commentShell);
4958 XSync(xDisplay, False);
4962 void AnalysisPopDown()
4964 if (!analysisUp) return;
4965 XtPopdown(analysisShell);
4966 XSync(xDisplay, False);
4971 void FileNamePopUp(label, def, proc, openMode)
4978 Widget popup, layout, dialog, edit;
4984 fileProc = proc; /* I can't see a way not */
4985 fileOpenMode = openMode; /* to use globals here */
4988 XtSetArg(args[i], XtNresizable, True); i++;
4989 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4990 fileNameShell = popup =
4991 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4992 shellWidget, args, i);
4995 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4996 layoutArgs, XtNumber(layoutArgs));
4999 XtSetArg(args[i], XtNlabel, label); i++;
5000 XtSetArg(args[i], XtNvalue, def); i++;
5001 XtSetArg(args[i], XtNborderWidth, 0); i++;
5002 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5005 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
5006 XawDialogAddButton(dialog, "cancel", FileNameCallback,
5007 (XtPointer) dialog);
5009 XtRealizeWidget(popup);
5010 CatchDeleteWindow(popup, "FileNamePopDown");
5012 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5013 &x, &y, &win_x, &win_y, &mask);
5015 XtSetArg(args[0], XtNx, x - 10);
5016 XtSetArg(args[1], XtNy, y - 30);
5017 XtSetValues(popup, args, 2);
5019 XtPopup(popup, XtGrabExclusive);
5022 edit = XtNameToWidget(dialog, "*value");
5023 XtSetKeyboardFocus(popup, edit);
5026 void FileNamePopDown()
5028 if (!filenameUp) return;
5029 XtPopdown(fileNameShell);
5030 XtDestroyWidget(fileNameShell);
5035 void FileNameCallback(w, client_data, call_data)
5037 XtPointer client_data, call_data;
5042 XtSetArg(args[0], XtNlabel, &name);
5043 XtGetValues(w, args, 1);
5045 if (strcmp(name, "cancel") == 0) {
5050 FileNameAction(w, NULL, NULL, NULL);
5053 void FileNameAction(w, event, prms, nprms)
5065 name = XawDialogGetValueString(w = XtParent(w));
5067 if ((name != NULL) && (*name != NULLCHAR)) {
5069 XtPopdown(w = XtParent(XtParent(w)));
5073 p = strrchr(buf, ' ');
5080 fullname = ExpandPathName(buf);
5082 ErrorPopUp("Error", "Can't open file", FALSE);
5085 f = fopen(fullname, fileOpenMode);
5087 DisplayError("Failed to open file", errno);
5089 (void) (*fileProc)(f, index, buf);
5096 XtPopdown(w = XtParent(XtParent(w)));
5102 void PromotionPopUp()
5105 Widget dialog, layout;
5107 Dimension bw_width, pw_width;
5111 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5112 XtGetValues(boardWidget, args, j);
5115 XtSetArg(args[j], XtNresizable, True); j++;
5117 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5118 shellWidget, args, j);
5120 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5121 layoutArgs, XtNumber(layoutArgs));
5124 XtSetArg(args[j], XtNlabel, "Promote pawn to what?"); j++;
5125 XtSetArg(args[j], XtNborderWidth, 0); j++;
5126 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5129 XawDialogAddButton(dialog, "Queen", PromotionCallback,
5130 (XtPointer) dialog);
5131 XawDialogAddButton(dialog, "Rook", PromotionCallback,
5132 (XtPointer) dialog);
5133 XawDialogAddButton(dialog, "Bishop", PromotionCallback,
5134 (XtPointer) dialog);
5135 XawDialogAddButton(dialog, "Knight", PromotionCallback,
5136 (XtPointer) dialog);
5137 if (!appData.testLegality || gameInfo.variant == VariantSuicide) {
5138 XawDialogAddButton(dialog, "King", PromotionCallback,
5139 (XtPointer) dialog);
5141 XawDialogAddButton(dialog, "cancel", PromotionCallback,
5142 (XtPointer) dialog);
5144 XtRealizeWidget(promotionShell);
5145 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5148 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5149 XtGetValues(promotionShell, args, j);
5151 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5152 lineGap + squareSize/3 +
5153 ((toY == 7) ^ (flipView) ?
5154 0 : 6*(squareSize + lineGap)), &x, &y);
5157 XtSetArg(args[j], XtNx, x); j++;
5158 XtSetArg(args[j], XtNy, y); j++;
5159 XtSetValues(promotionShell, args, j);
5161 XtPopup(promotionShell, XtGrabNone);
5166 void PromotionPopDown()
5168 if (!promotionUp) return;
5169 XtPopdown(promotionShell);
5170 XtDestroyWidget(promotionShell);
5171 promotionUp = False;
5174 void PromotionCallback(w, client_data, call_data)
5176 XtPointer client_data, call_data;
5182 XtSetArg(args[0], XtNlabel, &name);
5183 XtGetValues(w, args, 1);
5187 if (fromX == -1) return;
5189 if (strcmp(name, "cancel") == 0) {
5193 } else if (strcmp(name, "Knight") == 0) {
5196 promoChar = ToLower(name[0]);
5199 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5201 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5202 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5207 void ErrorCallback(w, client_data, call_data)
5209 XtPointer client_data, call_data;
5212 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5214 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5220 if (!errorUp) return;
5222 XtPopdown(errorShell);
5223 XtDestroyWidget(errorShell);
5224 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5227 void ErrorPopUp(title, label, modal)
5228 char *title, *label;
5232 Widget dialog, layout;
5236 Dimension bw_width, pw_width;
5237 Dimension pw_height;
5241 XtSetArg(args[i], XtNresizable, True); i++;
5242 XtSetArg(args[i], XtNtitle, title); i++;
5244 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5245 shellWidget, args, i);
5247 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5248 layoutArgs, XtNumber(layoutArgs));
5251 XtSetArg(args[i], XtNlabel, label); i++;
5252 XtSetArg(args[i], XtNborderWidth, 0); i++;
5253 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5256 XawDialogAddButton(dialog, "ok", ErrorCallback, (XtPointer) dialog);
5258 XtRealizeWidget(errorShell);
5259 CatchDeleteWindow(errorShell, "ErrorPopDown");
5262 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5263 XtGetValues(boardWidget, args, i);
5265 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5266 XtSetArg(args[i], XtNheight, &pw_height); i++;
5267 XtGetValues(errorShell, args, i);
5270 /* This code seems to tickle an X bug if it is executed too soon
5271 after xboard starts up. The coordinates get transformed as if
5272 the main window was positioned at (0, 0).
5274 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5275 0 - pw_height + squareSize / 3, &x, &y);
5277 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5278 RootWindowOfScreen(XtScreen(boardWidget)),
5279 (bw_width - pw_width) / 2,
5280 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5284 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5287 XtSetArg(args[i], XtNx, x); i++;
5288 XtSetArg(args[i], XtNy, y); i++;
5289 XtSetValues(errorShell, args, i);
5292 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5295 /* Disable all user input other than deleting the window */
5296 static int frozen = 0;
5300 /* Grab by a widget that doesn't accept input */
5301 XtAddGrab(messageWidget, TRUE, FALSE);
5305 /* Undo a FreezeUI */
5308 if (!frozen) return;
5309 XtRemoveGrab(messageWidget);
5313 char *ModeToWidgetName(mode)
5317 case BeginningOfGame:
5318 if (appData.icsActive)
5319 return "menuMode.ICS Client";
5320 else if (appData.noChessProgram ||
5321 *appData.cmailGameName != NULLCHAR)
5322 return "menuMode.Edit Game";
5324 return "menuMode.Machine Black";
5325 case MachinePlaysBlack:
5326 return "menuMode.Machine Black";
5327 case MachinePlaysWhite:
5328 return "menuMode.Machine White";
5330 return "menuMode.Analysis Mode";
5332 return "menuMode.Analyze File";
5333 case TwoMachinesPlay:
5334 return "menuMode.Two Machines";
5336 return "menuMode.Edit Game";
5337 case PlayFromGameFile:
5338 return "menuFile.Load Game";
5340 return "menuMode.Edit Position";
5342 return "menuMode.Training";
5343 case IcsPlayingWhite:
5344 case IcsPlayingBlack:
5348 return "menuMode.ICS Client";
5355 void ModeHighlight()
5358 static int oldPausing = FALSE;
5359 static GameMode oldmode = (GameMode) -1;
5362 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5364 if (pausing != oldPausing) {
5365 oldPausing = pausing;
5367 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5369 XtSetArg(args[0], XtNleftBitmap, None);
5371 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5374 if (appData.showButtonBar) {
5377 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5378 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5380 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5381 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5384 /* Always toggle, don't set. Previous code messes up when
5385 invoked while the button is pressed, as releasing it
5386 toggles the state again. */
5389 XtSetArg(args[0], XtNbackground, &oldbg);
5390 XtSetArg(args[1], XtNforeground, &oldfg);
5391 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5393 XtSetArg(args[0], XtNbackground, oldfg);
5394 XtSetArg(args[1], XtNforeground, oldbg);
5397 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5401 wname = ModeToWidgetName(oldmode);
5402 if (wname != NULL) {
5403 XtSetArg(args[0], XtNleftBitmap, None);
5404 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5406 wname = ModeToWidgetName(gameMode);
5407 if (wname != NULL) {
5408 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5409 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5413 /* Maybe all the enables should be handled here, not just this one */
5414 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5415 gameMode == Training || gameMode == PlayFromGameFile);
5420 * Button/menu procedures
5422 void ResetProc(w, event, prms, nprms)
5432 int LoadGamePopUp(f, gameNumber, title)
5437 cmailMsgLoaded = FALSE;
5438 if (gameNumber == 0) {
5439 int error = GameListBuild(f);
5441 DisplayError("Cannot build game list", error);
5442 } else if (!ListEmpty(&gameList) &&
5443 ((ListGame *) gameList.tailPred)->number > 1) {
5444 GameListPopUp(f, title);
5450 return LoadGame(f, gameNumber, title, FALSE);
5453 void LoadGameProc(w, event, prms, nprms)
5459 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5462 FileNamePopUp("Load game file name?", "", LoadGamePopUp, "r");
5465 void LoadNextGameProc(w, event, prms, nprms)
5474 void LoadPrevGameProc(w, event, prms, nprms)
5483 void ReloadGameProc(w, event, prms, nprms)
5492 void LoadNextPositionProc(w, event, prms, nprms)
5501 void LoadPrevPositionProc(w, event, prms, nprms)
5510 void ReloadPositionProc(w, event, prms, nprms)
5519 void LoadPositionProc(w, event, prms, nprms)
5525 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5528 FileNamePopUp("Load position file name?", "", LoadPosition, "r");
5531 void SaveGameProc(w, event, prms, nprms)
5537 FileNamePopUp("Save game file name?",
5538 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5542 void SavePositionProc(w, event, prms, nprms)
5548 FileNamePopUp("Save position file name?",
5549 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5553 void ReloadCmailMsgProc(w, event, prms, nprms)
5559 ReloadCmailMsgEvent(FALSE);
5562 void MailMoveProc(w, event, prms, nprms)
5571 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5572 static char *selected_fen_position=NULL;
5575 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5576 Atom *type_return, XtPointer *value_return,
5577 unsigned long *length_return, int *format_return)
5579 char *selection_tmp;
5581 if (!selected_fen_position) return False; /* should never happen */
5582 if (*target == XA_STRING){
5583 /* note: since no XtSelectionDoneProc was registered, Xt will
5584 * automatically call XtFree on the value returned. So have to
5585 * make a copy of it allocated with XtMalloc */
5586 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5587 strcpy(selection_tmp, selected_fen_position);
5589 *value_return=selection_tmp;
5590 *length_return=strlen(selection_tmp);
5591 *type_return=XA_STRING;
5592 *format_return = 8; /* bits per byte */
5599 /* note: when called from menu all parameters are NULL, so no clue what the
5600 * Widget which was clicked on was, or what the click event was
5602 void CopyPositionProc(w, event, prms, nprms)
5610 if (selected_fen_position) free(selected_fen_position);
5611 selected_fen_position = (char *)PositionToFEN(currentMove);
5612 if (!selected_fen_position) return;
5613 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5615 SendPositionSelection,
5616 NULL/* lose_ownership_proc */ ,
5617 NULL/* transfer_done_proc */);
5619 free(selected_fen_position);
5620 selected_fen_position=NULL;
5624 /* function called when the data to Paste is ready */
5626 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5627 Atom *type, XtPointer value, unsigned long *len, int *format)
5630 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5631 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5632 EditPositionPasteFEN(fenstr);
5636 /* called when Paste Position button is pressed,
5637 * all parameters will be NULL */
5638 void PastePositionProc(w, event, prms, nprms)
5644 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5645 /* (XtSelectionCallbackProc) */ PastePositionCB,
5646 NULL, /* client_data passed to PastePositionCB */
5648 /* better to use the time field from the event that triggered the
5649 * call to this function, but that isn't trivial to get
5657 SendGameSelection(Widget w, Atom *selection, Atom *target,
5658 Atom *type_return, XtPointer *value_return,
5659 unsigned long *length_return, int *format_return)
5661 char *selection_tmp;
5663 if (*target == XA_STRING){
5664 FILE* f = fopen(gameCopyFilename, "r");
5667 if (f == NULL) return False;
5671 selection_tmp = XtMalloc(len + 1);
5672 count = fread(selection_tmp, 1, len, f);
5674 XtFree(selection_tmp);
5677 selection_tmp[len] = NULLCHAR;
5678 *value_return = selection_tmp;
5679 *length_return = len;
5680 *type_return = XA_STRING;
5681 *format_return = 8; /* bits per byte */
5688 /* note: when called from menu all parameters are NULL, so no clue what the
5689 * Widget which was clicked on was, or what the click event was
5691 void CopyGameProc(w, event, prms, nprms)
5699 ret = SaveGameToFile(gameCopyFilename, FALSE);
5702 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5705 NULL/* lose_ownership_proc */ ,
5706 NULL/* transfer_done_proc */);
5709 /* function called when the data to Paste is ready */
5711 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5712 Atom *type, XtPointer value, unsigned long *len, int *format)
5715 if (value == NULL || *len == 0) {
5716 return; /* nothing had been selected to copy */
5718 f = fopen(gamePasteFilename, "w");
5720 DisplayError("Can't open temp file", errno);
5723 fwrite(value, 1, *len, f);
5726 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, FALSE);
5729 /* called when Paste Game button is pressed,
5730 * all parameters will be NULL */
5731 void PasteGameProc(w, event, prms, nprms)
5737 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5738 /* (XtSelectionCallbackProc) */ PasteGameCB,
5739 NULL, /* client_data passed to PasteGameCB */
5741 /* better to use the time field from the event that triggered the
5742 * call to this function, but that isn't trivial to get
5752 SaveGameProc(NULL, NULL, NULL, NULL);
5756 void QuitProc(w, event, prms, nprms)
5765 void PauseProc(w, event, prms, nprms)
5775 void MachineBlackProc(w, event, prms, nprms)
5781 MachineBlackEvent();
5784 void MachineWhiteProc(w, event, prms, nprms)
5790 MachineWhiteEvent();
5793 void AnalyzeModeProc(w, event, prms, nprms)
5799 if (!first.analysisSupport) {
5801 sprintf(buf, "%s does not support analysis", first.tidy);
5802 DisplayError(buf, 0);
5805 if (!appData.showThinking)
5806 ShowThinkingProc(w,event,prms,nprms);
5811 void AnalyzeFileProc(w, event, prms, nprms)
5817 if (!first.analysisSupport) {
5819 sprintf(buf, "%s does not support analysis", first.tidy);
5820 DisplayError(buf, 0);
5825 if (!appData.showThinking)
5826 ShowThinkingProc(w,event,prms,nprms);
5829 FileNamePopUp("File to analyze", "", LoadGamePopUp, "r");
5830 AnalysisPeriodicEvent(1);
5833 void TwoMachinesProc(w, event, prms, nprms)
5842 void IcsClientProc(w, event, prms, nprms)
5851 void EditGameProc(w, event, prms, nprms)
5860 void EditPositionProc(w, event, prms, nprms)
5866 EditPositionEvent();
5869 void TrainingProc(w, event, prms, nprms)
5878 void EditCommentProc(w, event, prms, nprms)
5885 EditCommentPopDown();
5891 void IcsInputBoxProc(w, event, prms, nprms)
5897 if (ICSInputBoxUp) {
5898 ICSInputBoxPopDown();
5904 void AcceptProc(w, event, prms, nprms)
5913 void DeclineProc(w, event, prms, nprms)
5922 void RematchProc(w, event, prms, nprms)
5931 void CallFlagProc(w, event, prms, nprms)
5940 void DrawProc(w, event, prms, nprms)
5949 void AbortProc(w, event, prms, nprms)
5958 void AdjournProc(w, event, prms, nprms)
5967 void ResignProc(w, event, prms, nprms)
5976 void EnterKeyProc(w, event, prms, nprms)
5982 if (ICSInputBoxUp == True)
5986 void StopObservingProc(w, event, prms, nprms)
5992 StopObservingEvent();
5995 void StopExaminingProc(w, event, prms, nprms)
6001 StopExaminingEvent();
6005 void ForwardProc(w, event, prms, nprms)
6015 void BackwardProc(w, event, prms, nprms)
6024 void ToStartProc(w, event, prms, nprms)
6033 void ToEndProc(w, event, prms, nprms)
6042 void RevertProc(w, event, prms, nprms)
6051 void TruncateGameProc(w, event, prms, nprms)
6057 TruncateGameEvent();
6059 void RetractMoveProc(w, event, prms, nprms)
6068 void MoveNowProc(w, event, prms, nprms)
6078 void AlwaysQueenProc(w, event, prms, nprms)
6086 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6088 if (appData.alwaysPromoteToQueen) {
6089 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6091 XtSetArg(args[0], XtNleftBitmap, None);
6093 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6097 void AnimateDraggingProc(w, event, prms, nprms)
6105 appData.animateDragging = !appData.animateDragging;
6107 if (appData.animateDragging) {
6108 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6111 XtSetArg(args[0], XtNleftBitmap, None);
6113 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6117 void AnimateMovingProc(w, event, prms, nprms)
6125 appData.animate = !appData.animate;
6127 if (appData.animate) {
6128 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6131 XtSetArg(args[0], XtNleftBitmap, None);
6133 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6137 void AutocommProc(w, event, prms, nprms)
6145 appData.autoComment = !appData.autoComment;
6147 if (appData.autoComment) {
6148 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6150 XtSetArg(args[0], XtNleftBitmap, None);
6152 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6157 void AutoflagProc(w, event, prms, nprms)
6165 appData.autoCallFlag = !appData.autoCallFlag;
6167 if (appData.autoCallFlag) {
6168 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6170 XtSetArg(args[0], XtNleftBitmap, None);
6172 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6176 void AutoflipProc(w, event, prms, nprms)
6184 appData.autoFlipView = !appData.autoFlipView;
6186 if (appData.autoFlipView) {
6187 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6189 XtSetArg(args[0], XtNleftBitmap, None);
6191 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6195 void AutobsProc(w, event, prms, nprms)
6203 appData.autoObserve = !appData.autoObserve;
6205 if (appData.autoObserve) {
6206 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6208 XtSetArg(args[0], XtNleftBitmap, None);
6210 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6214 void AutoraiseProc(w, event, prms, nprms)
6222 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6224 if (appData.autoRaiseBoard) {
6225 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6227 XtSetArg(args[0], XtNleftBitmap, None);
6229 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6233 void AutosaveProc(w, event, prms, nprms)
6241 appData.autoSaveGames = !appData.autoSaveGames;
6243 if (appData.autoSaveGames) {
6244 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6246 XtSetArg(args[0], XtNleftBitmap, None);
6248 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6252 void BlindfoldProc(w, event, prms, nprms)
6260 appData.blindfold = !appData.blindfold;
6262 if (appData.blindfold) {
6263 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6265 XtSetArg(args[0], XtNleftBitmap, None);
6267 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6270 DrawPosition(True, NULL);
6273 void TestLegalityProc(w, event, prms, nprms)
6281 appData.testLegality = !appData.testLegality;
6283 if (appData.testLegality) {
6284 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6286 XtSetArg(args[0], XtNleftBitmap, None);
6288 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6293 void FlashMovesProc(w, event, prms, nprms)
6301 if (appData.flashCount == 0) {
6302 appData.flashCount = 3;
6304 appData.flashCount = -appData.flashCount;
6307 if (appData.flashCount > 0) {
6308 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6310 XtSetArg(args[0], XtNleftBitmap, None);
6312 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6316 void FlipViewProc(w, event, prms, nprms)
6322 flipView = !flipView;
6323 DrawPosition(True, NULL);
6326 void GetMoveListProc(w, event, prms, nprms)
6334 appData.getMoveList = !appData.getMoveList;
6336 if (appData.getMoveList) {
6337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6340 XtSetArg(args[0], XtNleftBitmap, None);
6342 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6347 void HighlightDraggingProc(w, event, prms, nprms)
6355 appData.highlightDragging = !appData.highlightDragging;
6357 if (appData.highlightDragging) {
6358 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6360 XtSetArg(args[0], XtNleftBitmap, None);
6362 XtSetValues(XtNameToWidget(menuBarWidget,
6363 "menuOptions.Highlight Dragging"), args, 1);
6367 void HighlightLastMoveProc(w, event, prms, nprms)
6375 appData.highlightLastMove = !appData.highlightLastMove;
6377 if (appData.highlightLastMove) {
6378 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6380 XtSetArg(args[0], XtNleftBitmap, None);
6382 XtSetValues(XtNameToWidget(menuBarWidget,
6383 "menuOptions.Highlight Last Move"), args, 1);
6386 void IcsAlarmProc(w, event, prms, nprms)
6394 appData.icsAlarm = !appData.icsAlarm;
6396 if (appData.icsAlarm) {
6397 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6399 XtSetArg(args[0], XtNleftBitmap, None);
6401 XtSetValues(XtNameToWidget(menuBarWidget,
6402 "menuOptions.ICS Alarm"), args, 1);
6405 void MoveSoundProc(w, event, prms, nprms)
6413 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6415 if (appData.ringBellAfterMoves) {
6416 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6418 XtSetArg(args[0], XtNleftBitmap, None);
6420 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6425 void OldSaveStyleProc(w, event, prms, nprms)
6433 appData.oldSaveStyle = !appData.oldSaveStyle;
6435 if (appData.oldSaveStyle) {
6436 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6438 XtSetArg(args[0], XtNleftBitmap, None);
6440 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6444 void PeriodicUpdatesProc(w, event, prms, nprms)
6452 PeriodicUpdatesEvent(!appData.periodicUpdates);
6454 if (appData.periodicUpdates) {
6455 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6457 XtSetArg(args[0], XtNleftBitmap, None);
6459 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6463 void PonderNextMoveProc(w, event, prms, nprms)
6471 PonderNextMoveEvent(!appData.ponderNextMove);
6473 if (appData.ponderNextMove) {
6474 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6476 XtSetArg(args[0], XtNleftBitmap, None);
6478 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6482 void PopupExitMessageProc(w, event, prms, nprms)
6490 appData.popupExitMessage = !appData.popupExitMessage;
6492 if (appData.popupExitMessage) {
6493 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6495 XtSetArg(args[0], XtNleftBitmap, None);
6497 XtSetValues(XtNameToWidget(menuBarWidget,
6498 "menuOptions.Popup Exit Message"), args, 1);
6501 void PopupMoveErrorsProc(w, event, prms, nprms)
6509 appData.popupMoveErrors = !appData.popupMoveErrors;
6511 if (appData.popupMoveErrors) {
6512 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6514 XtSetArg(args[0], XtNleftBitmap, None);
6516 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6520 void PremoveProc(w, event, prms, nprms)
6528 appData.premove = !appData.premove;
6530 if (appData.premove) {
6531 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6533 XtSetArg(args[0], XtNleftBitmap, None);
6535 XtSetValues(XtNameToWidget(menuBarWidget,
6536 "menuOptions.Premove"), args, 1);
6539 void QuietPlayProc(w, event, prms, nprms)
6547 appData.quietPlay = !appData.quietPlay;
6549 if (appData.quietPlay) {
6550 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6552 XtSetArg(args[0], XtNleftBitmap, None);
6554 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6558 void ShowCoordsProc(w, event, prms, nprms)
6566 appData.showCoords = !appData.showCoords;
6568 if (appData.showCoords) {
6569 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6571 XtSetArg(args[0], XtNleftBitmap, None);
6573 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6576 DrawPosition(True, NULL);
6579 void ShowThinkingProc(w, event, prms, nprms)
6587 ShowThinkingEvent(!appData.showThinking);
6589 if (appData.showThinking) {
6590 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6592 XtSetArg(args[0], XtNleftBitmap, None);
6594 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6598 void InfoProc(w, event, prms, nprms)
6605 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6610 void ManProc(w, event, prms, nprms)
6618 if (nprms && *nprms > 0)
6622 sprintf(buf, "xterm -e man %s &", name);
6626 void HintProc(w, event, prms, nprms)
6635 void BookProc(w, event, prms, nprms)
6644 void AboutProc(w, event, prms, nprms)
6652 char *zippy = " (with Zippy code)";
6656 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6657 programVersion, zippy,
6658 "Copyright 1991 Digital Equipment Corporation",
6659 "Enhancements Copyright 1992-2001 Free Software Foundation",
6660 PRODUCT, " is free software and carries NO WARRANTY;",
6661 "see the file COPYING for more information.");
6662 ErrorPopUp("About XBoard", buf, FALSE);
6665 void DebugProc(w, event, prms, nprms)
6671 appData.debugMode = !appData.debugMode;
6674 void AboutGameProc(w, event, prms, nprms)
6683 void NothingProc(w, event, prms, nprms)
6692 void Iconify(w, event, prms, nprms)
6701 XtSetArg(args[0], XtNiconic, True);
6702 XtSetValues(shellWidget, args, 1);
6705 void DisplayMessage(message, extMessage)
6706 char *message, *extMessage;
6713 sprintf(buf, "%s %s", message, extMessage);
6716 message = extMessage;
6719 XtSetArg(arg, XtNlabel, message);
6720 XtSetValues(messageWidget, &arg, 1);
6723 void DisplayTitle(text)
6728 char title[MSG_SIZ];
6731 if (text == NULL) text = "";
6733 if (appData.titleInWindow) {
6735 XtSetArg(args[i], XtNlabel, text); i++;
6736 XtSetValues(titleWidget, args, i);
6739 if (*text != NULLCHAR) {
6741 strcpy(title, text);
6742 } else if (appData.icsActive) {
6743 sprintf(icon, "%s", appData.icsHost);
6744 sprintf(title, "%s: %s", programName, appData.icsHost);
6745 } else if (appData.cmailGameName[0] != NULLCHAR) {
6746 sprintf(icon, "%s", "CMail");
6747 sprintf(title, "%s: %s", programName, "CMail");
6748 } else if (appData.noChessProgram) {
6749 strcpy(icon, programName);
6750 strcpy(title, programName);
6752 strcpy(icon, first.tidy);
6753 sprintf(title, "%s: %s", programName, first.tidy);
6756 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6757 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6758 XtSetValues(shellWidget, args, i);
6762 void DisplayError(message, error)
6769 if (appData.debugMode || appData.matchMode) {
6770 fprintf(stderr, "%s: %s\n", programName, message);
6773 if (appData.debugMode || appData.matchMode) {
6774 fprintf(stderr, "%s: %s: %s\n",
6775 programName, message, sys_errlist[error]);
6777 sprintf(buf, "%s: %s", message, sys_errlist[error]);
6780 ErrorPopUp("Error", message, FALSE);
6784 void DisplayMoveError(message)
6789 DrawPosition(FALSE, NULL);
6790 if (appData.debugMode || appData.matchMode) {
6791 fprintf(stderr, "%s: %s\n", programName, message);
6793 if (appData.popupMoveErrors) {
6794 ErrorPopUp("Error", message, FALSE);
6796 DisplayMessage(message, "");
6801 void DisplayFatalError(message, error, status)
6807 errorExitStatus = status;
6809 fprintf(stderr, "%s: %s\n", programName, message);
6811 fprintf(stderr, "%s: %s: %s\n",
6812 programName, message, sys_errlist[error]);
6813 sprintf(buf, "%s: %s", message, sys_errlist[error]);
6816 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6817 ErrorPopUp(status ? "Fatal Error" : "Exiting", message, TRUE);
6823 void DisplayInformation(message)
6827 ErrorPopUp("Information", message, TRUE);
6831 NullXErrorCheck(dpy, error_event)
6833 XErrorEvent *error_event;
6838 void DisplayIcsInteractionTitle(message)
6841 if (oldICSInteractionTitle == NULL) {
6842 /* Magic to find the old window title, adapted from vim */
6843 char *wina = getenv("WINDOWID");
6845 Window win = (Window) atoi(wina);
6846 Window root, parent, *children;
6847 unsigned int nchildren;
6848 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6850 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6851 if (!XQueryTree(xDisplay, win, &root, &parent,
6852 &children, &nchildren)) break;
6853 if (children) XFree((void *)children);
6854 if (parent == root || parent == 0) break;
6857 XSetErrorHandler(oldHandler);
6859 if (oldICSInteractionTitle == NULL) {
6860 oldICSInteractionTitle = "xterm";
6863 printf("\033]0;%s\007", message);
6867 char pendingReplyPrefix[MSG_SIZ];
6868 ProcRef pendingReplyPR;
6870 void AskQuestionProc(w, event, prms, nprms)
6877 fprintf(stderr, "AskQuestionProc needed 4 parameters, got %d\n",
6881 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6884 void AskQuestionPopDown()
6886 if (!askQuestionUp) return;
6887 XtPopdown(askQuestionShell);
6888 XtDestroyWidget(askQuestionShell);
6889 askQuestionUp = False;
6892 void AskQuestionReplyAction(w, event, prms, nprms)
6902 reply = XawDialogGetValueString(w = XtParent(w));
6903 strcpy(buf, pendingReplyPrefix);
6904 if (*buf) strcat(buf, " ");
6907 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6908 AskQuestionPopDown();
6910 if (err) DisplayFatalError("Error writing to chess program", err, 0);
6913 void AskQuestionCallback(w, client_data, call_data)
6915 XtPointer client_data, call_data;
6920 XtSetArg(args[0], XtNlabel, &name);
6921 XtGetValues(w, args, 1);
6923 if (strcmp(name, "cancel") == 0) {
6924 AskQuestionPopDown();
6926 AskQuestionReplyAction(w, NULL, NULL, NULL);
6930 void AskQuestion(title, question, replyPrefix, pr)
6931 char *title, *question, *replyPrefix;
6935 Widget popup, layout, dialog, edit;
6941 strcpy(pendingReplyPrefix, replyPrefix);
6942 pendingReplyPR = pr;
6945 XtSetArg(args[i], XtNresizable, True); i++;
6946 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6947 askQuestionShell = popup =
6948 XtCreatePopupShell(title, transientShellWidgetClass,
6949 shellWidget, args, i);
6952 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6953 layoutArgs, XtNumber(layoutArgs));
6956 XtSetArg(args[i], XtNlabel, question); i++;
6957 XtSetArg(args[i], XtNvalue, ""); i++;
6958 XtSetArg(args[i], XtNborderWidth, 0); i++;
6959 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6962 XawDialogAddButton(dialog, "enter", AskQuestionCallback,
6963 (XtPointer) dialog);
6964 XawDialogAddButton(dialog, "cancel", AskQuestionCallback,
6965 (XtPointer) dialog);
6967 XtRealizeWidget(popup);
6968 CatchDeleteWindow(popup, "AskQuestionPopDown");
6970 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6971 &x, &y, &win_x, &win_y, &mask);
6973 XtSetArg(args[0], XtNx, x - 10);
6974 XtSetArg(args[1], XtNy, y - 30);
6975 XtSetValues(popup, args, 2);
6977 XtPopup(popup, XtGrabExclusive);
6978 askQuestionUp = True;
6980 edit = XtNameToWidget(dialog, "*value");
6981 XtSetKeyboardFocus(popup, edit);
6989 if (*name == NULLCHAR) {
6991 } else if (strcmp(name, "$") == 0) {
6992 putc(BELLCHAR, stderr);
6995 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7003 PlaySound(appData.soundMove);
7009 PlaySound(appData.soundIcsWin);
7015 PlaySound(appData.soundIcsLoss);
7021 PlaySound(appData.soundIcsDraw);
7025 PlayIcsUnfinishedSound()
7027 PlaySound(appData.soundIcsUnfinished);
7033 PlaySound(appData.soundIcsAlarm);
7039 system("stty echo");
7045 system("stty -echo");
7049 Colorize(cc, continuation)
7054 int count, outCount, error;
7056 if (textColors[(int)cc].bg > 0) {
7057 if (textColors[(int)cc].fg > 0) {
7058 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7059 textColors[(int)cc].fg, textColors[(int)cc].bg);
7061 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7062 textColors[(int)cc].bg);
7065 if (textColors[(int)cc].fg > 0) {
7066 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7067 textColors[(int)cc].fg);
7069 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7072 count = strlen(buf);
7073 outCount = OutputToProcess(NoProc, buf, count, &error);
7074 if (outCount < count) {
7075 DisplayFatalError("Error writing to display", error, 1);
7078 if (continuation) return;
7081 PlaySound(appData.soundShout);
7084 PlaySound(appData.soundSShout);
7087 PlaySound(appData.soundChannel1);
7090 PlaySound(appData.soundChannel);
7093 PlaySound(appData.soundKibitz);
7096 PlaySound(appData.soundTell);
7098 case ColorChallenge:
7099 PlaySound(appData.soundChallenge);
7102 PlaySound(appData.soundRequest);
7105 PlaySound(appData.soundSeek);
7116 return getpwuid(getuid())->pw_name;
7119 static char *ExpandPathName(path)
7122 static char static_buf[2000];
7123 char *d, *s, buf[2000];
7129 while (*s && isspace(*s))
7138 if (*(s+1) == '/') {
7139 strcpy(d, getpwuid(getuid())->pw_dir);
7144 *strchr(buf, '/') = 0;
7145 pwd = getpwnam(buf);
7148 fprintf(stderr, "ERROR: Unknown user %s (in path %s)\n",
7152 strcpy(d, pwd->pw_dir);
7153 strcat(d, strchr(s+1, '/'));
7164 static char host_name[MSG_SIZ];
7166 #if HAVE_GETHOSTNAME
7167 gethostname(host_name, MSG_SIZ);
7169 #else /* not HAVE_GETHOSTNAME */
7170 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7171 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7173 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7175 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7176 #endif /* not HAVE_GETHOSTNAME */
7179 XtIntervalId delayedEventTimerXID = 0;
7180 DelayedEventCallback delayedEventCallback = 0;
7182 ScheduleDelayedEvent(cb, millisec)
7183 DelayedEventCallback cb; long millisec;
7185 delayedEventCallback = cb;
7186 delayedEventTimerXID =
7187 XtAppAddTimeOut(appContext, millisec, (XtTimerCallbackProc) cb,
7191 DelayedEventCallback
7194 if (delayedEventTimerXID) {
7195 return delayedEventCallback;
7202 CancelDelayedEvent()
7204 if (delayedEventTimerXID) {
7205 XtRemoveTimeOut(delayedEventTimerXID);
7206 delayedEventTimerXID = 0;
7210 XtIntervalId loadGameTimerXID = 0;
7212 int LoadGameTimerRunning()
7214 return loadGameTimerXID != 0;
7217 int StopLoadGameTimer()
7219 if (loadGameTimerXID != 0) {
7220 XtRemoveTimeOut(loadGameTimerXID);
7221 loadGameTimerXID = 0;
7229 LoadGameTimerCallback(arg, id)
7233 loadGameTimerXID = 0;
7238 StartLoadGameTimer(millisec)
7242 XtAppAddTimeOut(appContext, millisec,
7243 (XtTimerCallbackProc) LoadGameTimerCallback,
7247 XtIntervalId analysisClockXID = 0;
7250 AnalysisClockCallback(arg, id)
7254 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
7255 AnalysisPeriodicEvent(0);
7256 StartAnalysisClock();
7261 StartAnalysisClock()
7264 XtAppAddTimeOut(appContext, 2000,
7265 (XtTimerCallbackProc) AnalysisClockCallback,
7269 XtIntervalId clockTimerXID = 0;
7271 int ClockTimerRunning()
7273 return clockTimerXID != 0;
7276 int StopClockTimer()
7278 if (clockTimerXID != 0) {
7279 XtRemoveTimeOut(clockTimerXID);
7288 ClockTimerCallback(arg, id)
7297 StartClockTimer(millisec)
7301 XtAppAddTimeOut(appContext, millisec,
7302 (XtTimerCallbackProc) ClockTimerCallback,
7307 DisplayTimerLabel(w, color, timer, highlight)
7316 if (appData.clockMode) {
7317 sprintf(buf, "%s: %s", color, TimeString(timer));
7318 XtSetArg(args[0], XtNlabel, buf);
7320 sprintf(buf, "%s ", color);
7321 XtSetArg(args[0], XtNlabel, buf);
7325 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7326 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7328 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7329 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7332 XtSetValues(w, args, 3);
7336 DisplayWhiteClock(timeRemaining, highlight)
7341 DisplayTimerLabel(whiteTimerWidget, "White", timeRemaining, highlight);
7342 if (highlight && iconPixmap == bIconPixmap) {
7343 iconPixmap = wIconPixmap;
7344 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7345 XtSetValues(shellWidget, args, 1);
7350 DisplayBlackClock(timeRemaining, highlight)
7355 DisplayTimerLabel(blackTimerWidget, "Black", timeRemaining, highlight);
7356 if (highlight && iconPixmap == wIconPixmap) {
7357 iconPixmap = bIconPixmap;
7358 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7359 XtSetValues(shellWidget, args, 1);
7377 int StartChildProcess(cmdLine, dir, pr)
7384 int to_prog[2], from_prog[2];
7388 if (appData.debugMode) {
7389 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7392 /* We do NOT feed the cmdLine to the shell; we just
7393 parse it into blank-separated arguments in the
7394 most simple-minded way possible.
7397 strcpy(buf, cmdLine);
7402 if (p == NULL) break;
7407 SetUpChildIO(to_prog, from_prog);
7409 if ((pid = fork()) == 0) {
7411 dup2(to_prog[0], 0);
7412 dup2(from_prog[1], 1);
7415 close(from_prog[0]);
7416 close(from_prog[1]);
7417 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7419 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7424 execvp(argv[0], argv);
7426 /* If we get here, exec failed */
7431 /* Parent process */
7433 close(from_prog[1]);
7435 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7438 cp->fdFrom = from_prog[0];
7439 cp->fdTo = to_prog[1];
7445 DestroyChildProcess(pr, signal)
7449 ChildProc *cp = (ChildProc *) pr;
7451 if (cp->kind != CPReal) return;
7454 kill(cp->pid, SIGTERM);
7456 /* Process is exiting either because of the kill or because of
7457 a quit command sent by the backend; either way, wait for it to die.
7465 InterruptChildProcess(pr)
7468 ChildProc *cp = (ChildProc *) pr;
7470 if (cp->kind != CPReal) return;
7471 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7474 int OpenTelnet(host, port, pr)
7479 char cmdLine[MSG_SIZ];
7481 if (port[0] == NULLCHAR) {
7482 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7484 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7486 return StartChildProcess(cmdLine, "", pr);
7489 int OpenTCP(host, port, pr)
7495 DisplayFatalError("Socket support is not configured in", 0, 2);
7496 #else /* !OMIT_SOCKETS */
7498 struct sockaddr_in sa;
7500 unsigned short uport;
7503 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7507 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7508 sa.sin_family = AF_INET;
7509 sa.sin_addr.s_addr = INADDR_ANY;
7510 uport = (unsigned short) 0;
7511 sa.sin_port = htons(uport);
7512 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7516 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7517 if (!(hp = gethostbyname(host))) {
7519 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7520 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7521 hp->h_addrtype = AF_INET;
7523 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7524 hp->h_addr_list[0] = (char *) malloc(4);
7525 hp->h_addr_list[0][0] = b0;
7526 hp->h_addr_list[0][1] = b1;
7527 hp->h_addr_list[0][2] = b2;
7528 hp->h_addr_list[0][3] = b3;
7533 sa.sin_family = hp->h_addrtype;
7534 uport = (unsigned short) atoi(port);
7535 sa.sin_port = htons(uport);
7536 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7538 if (connect(s, (struct sockaddr *) &sa,
7539 sizeof(struct sockaddr_in)) < 0) {
7543 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7550 #endif /* !OMIT_SOCKETS */
7555 int OpenCommPort(name, pr)
7562 fd = open(name, 2, 0);
7563 if (fd < 0) return errno;
7565 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7575 int OpenLoopback(pr)
7581 SetUpChildIO(to, from);
7583 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7586 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7593 int OpenRcmd(host, user, cmd, pr)
7594 char *host, *user, *cmd;
7597 DisplayFatalError("internal rcmd not implemented for Unix", 0, 1);
7601 #define INPUT_SOURCE_BUF_SIZE 8192
7610 char buf[INPUT_SOURCE_BUF_SIZE];
7615 DoInputCallback(closure, source, xid)
7620 InputSource *is = (InputSource *) closure;
7625 if (is->lineByLine) {
7626 count = read(is->fd, is->unused,
7627 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7629 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7632 is->unused += count;
7634 while (p < is->unused) {
7635 q = memchr(p, '\n', is->unused - p);
7636 if (q == NULL) break;
7638 (is->func)(is, is->closure, p, q - p, 0);
7642 while (p < is->unused) {
7647 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7652 (is->func)(is, is->closure, is->buf, count, error);
7656 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7663 ChildProc *cp = (ChildProc *) pr;
7665 is = (InputSource *) calloc(1, sizeof(InputSource));
7666 is->lineByLine = lineByLine;
7670 is->fd = fileno(stdin);
7672 is->kind = cp->kind;
7673 is->fd = cp->fdFrom;
7676 is->unused = is->buf;
7679 is->xid = XtAppAddInput(appContext, is->fd,
7680 (XtPointer) (XtInputReadMask),
7681 (XtInputCallbackProc) DoInputCallback,
7683 is->closure = closure;
7684 return (InputSourceRef) is;
7688 RemoveInputSource(isr)
7691 InputSource *is = (InputSource *) isr;
7693 if (is->xid == 0) return;
7694 XtRemoveInput(is->xid);
7698 int OutputToProcess(pr, message, count, outError)
7704 ChildProc *cp = (ChildProc *) pr;
7708 outCount = fwrite(message, 1, count, stdout);
7710 outCount = write(cp->fdTo, message, count);
7720 /* Output message to process, with "ms" milliseconds of delay
7721 between each character. This is needed when sending the logon
7722 script to ICC, which for some reason doesn't like the
7723 instantaneous send. */
7724 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7731 ChildProc *cp = (ChildProc *) pr;
7736 r = write(cp->fdTo, message++, 1);
7749 /**** Animation code by Hugh Fisher, DCS, ANU.
7751 Known problem: if a window overlapping the board is
7752 moved away while a piece is being animated underneath,
7753 the newly exposed area won't be updated properly.
7754 I can live with this.
7756 Known problem: if you look carefully at the animation
7757 of pieces in mono mode, they are being drawn as solid
7758 shapes without interior detail while moving. Fixing
7759 this would be a major complication for minimal return.
7762 /* Masks for XPM pieces. Black and white pieces can have
7763 different shapes, but in the interest of retaining my
7764 sanity pieces must have the same outline on both light
7765 and dark squares, and all pieces must use the same
7766 background square colors/images. */
7769 CreateAnimMasks (pieceDepth)
7776 unsigned long plane;
7779 /* Need a bitmap just to get a GC with right depth */
7780 buf = XCreatePixmap(xDisplay, xBoardWindow,
7782 values.foreground = 1;
7783 values.background = 0;
7784 /* Don't use XtGetGC, not read only */
7785 maskGC = XCreateGC(xDisplay, buf,
7786 GCForeground | GCBackground, &values);
7787 XFreePixmap(xDisplay, buf);
7789 buf = XCreatePixmap(xDisplay, xBoardWindow,
7790 squareSize, squareSize, pieceDepth);
7791 values.foreground = XBlackPixel(xDisplay, xScreen);
7792 values.background = XWhitePixel(xDisplay, xScreen);
7793 bufGC = XCreateGC(xDisplay, buf,
7794 GCForeground | GCBackground, &values);
7796 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7797 /* Begin with empty mask */
7798 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7799 squareSize, squareSize, 1);
7800 XSetFunction(xDisplay, maskGC, GXclear);
7801 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7802 0, 0, squareSize, squareSize);
7804 /* Take a copy of the piece */
7809 XSetFunction(xDisplay, bufGC, GXcopy);
7810 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7812 0, 0, squareSize, squareSize, 0, 0);
7814 /* XOR the background (light) over the piece */
7815 XSetFunction(xDisplay, bufGC, GXxor);
7817 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7818 0, 0, squareSize, squareSize, 0, 0);
7820 XSetForeground(xDisplay, bufGC, lightSquareColor);
7821 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7824 /* We now have an inverted piece image with the background
7825 erased. Construct mask by just selecting all the non-zero
7826 pixels - no need to reconstruct the original image. */
7827 XSetFunction(xDisplay, maskGC, GXor);
7829 /* Might be quicker to download an XImage and create bitmap
7830 data from it rather than this N copies per piece, but it
7831 only takes a fraction of a second and there is a much
7832 longer delay for loading the pieces. */
7833 for (n = 0; n < pieceDepth; n ++) {
7834 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7835 0, 0, squareSize, squareSize,
7841 XFreePixmap(xDisplay, buf);
7842 XFreeGC(xDisplay, bufGC);
7843 XFreeGC(xDisplay, maskGC);
7847 InitAnimState (anim, info)
7849 XWindowAttributes * info;
7854 /* Each buffer is square size, same depth as window */
7855 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7856 squareSize, squareSize, info->depth);
7857 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7858 squareSize, squareSize, info->depth);
7860 /* Create a plain GC for blitting */
7861 mask = GCForeground | GCBackground | GCFunction |
7862 GCPlaneMask | GCGraphicsExposures;
7863 values.foreground = XBlackPixel(xDisplay, xScreen);
7864 values.background = XWhitePixel(xDisplay, xScreen);
7865 values.function = GXcopy;
7866 values.plane_mask = AllPlanes;
7867 values.graphics_exposures = False;
7868 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7870 /* Piece will be copied from an existing context at
7871 the start of each new animation/drag. */
7872 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7874 /* Outline will be a read-only copy of an existing */
7875 anim->outlineGC = None;
7881 static int done = 0;
7882 XWindowAttributes info;
7886 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7888 InitAnimState(&game, &info);
7889 InitAnimState(&player, &info);
7891 /* For XPM pieces, we need bitmaps to use as masks. */
7893 CreateAnimMasks(info.depth);
7898 static Boolean frameWaiting;
7900 static RETSIGTYPE FrameAlarm (sig)
7903 frameWaiting = False;
7904 /* In case System-V style signals. Needed?? */
7905 signal(SIGALRM, FrameAlarm);
7912 struct itimerval delay;
7914 XSync(xDisplay, False);
7917 frameWaiting = True;
7918 signal(SIGALRM, FrameAlarm);
7919 delay.it_interval.tv_sec =
7920 delay.it_value.tv_sec = time / 1000;
7921 delay.it_interval.tv_usec =
7922 delay.it_value.tv_usec = (time % 1000) * 1000;
7923 setitimer(ITIMER_REAL, &delay, NULL);
7925 /* Ugh -- busy-wait! --tpm */
7926 while (frameWaiting);
7928 while (frameWaiting) pause();
7930 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7931 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7932 setitimer(ITIMER_REAL, &delay, NULL);
7942 XSync(xDisplay, False);
7944 usleep(time * 1000);
7949 /* Convert board position to corner of screen rect and color */
7952 ScreenSquare(column, row, pt, color)
7953 int column; int row; XPoint * pt; int * color;
7956 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
7957 pt->y = lineGap + row * (squareSize + lineGap);
7959 pt->x = lineGap + column * (squareSize + lineGap);
7960 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
7962 *color = ((column + row) % 2) == 1;
7965 /* Convert window coords to square */
7968 BoardSquare(x, y, column, row)
7969 int x; int y; int * column; int * row;
7971 *column = EventToSquare(x, BOARD_SIZE);
7972 if (flipView && *column >= 0)
7973 *column = BOARD_SIZE - 1 - *column;
7974 *row = EventToSquare(y, BOARD_SIZE);
7975 if (!flipView && *row >= 0)
7976 *row = BOARD_SIZE - 1 - *row;
7981 #undef Max /* just in case */
7983 #define Max(a, b) ((a) > (b) ? (a) : (b))
7984 #define Min(a, b) ((a) < (b) ? (a) : (b))
7987 SetRect(rect, x, y, width, height)
7988 XRectangle * rect; int x; int y; int width; int height;
7992 rect->width = width;
7993 rect->height = height;
7996 /* Test if two frames overlap. If they do, return
7997 intersection rect within old and location of
7998 that rect within new. */
8001 Intersect(old, new, size, area, pt)
8002 XPoint * old; XPoint * new;
8003 int size; XRectangle * area; XPoint * pt;
8005 if (old->x > new->x + size || new->x > old->x + size ||
8006 old->y > new->y + size || new->y > old->y + size) {
8009 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8010 size - abs(old->x - new->x), size - abs(old->y - new->y));
8011 pt->x = Max(old->x - new->x, 0);
8012 pt->y = Max(old->y - new->y, 0);
8017 /* For two overlapping frames, return the rect(s)
8018 in the old that do not intersect with the new. */
8021 CalcUpdateRects(old, new, size, update, nUpdates)
8022 XPoint * old; XPoint * new; int size;
8023 XRectangle update[]; int * nUpdates;
8027 /* If old = new (shouldn't happen) then nothing to draw */
8028 if (old->x == new->x && old->y == new->y) {
8032 /* Work out what bits overlap. Since we know the rects
8033 are the same size we don't need a full intersect calc. */
8035 /* Top or bottom edge? */
8036 if (new->y > old->y) {
8037 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8039 } else if (old->y > new->y) {
8040 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8041 size, old->y - new->y);
8044 /* Left or right edge - don't overlap any update calculated above. */
8045 if (new->x > old->x) {
8046 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8047 new->x - old->x, size - abs(new->y - old->y));
8049 } else if (old->x > new->x) {
8050 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8051 old->x - new->x, size - abs(new->y - old->y));
8058 /* Generate a series of frame coords from start->mid->finish.
8059 The movement rate doubles until the half way point is
8060 reached, then halves back down to the final destination,
8061 which gives a nice slow in/out effect. The algorithmn
8062 may seem to generate too many intermediates for short
8063 moves, but remember that the purpose is to attract the
8064 viewers attention to the piece about to be moved and
8065 then to where it ends up. Too few frames would be less
8069 Tween(start, mid, finish, factor, frames, nFrames)
8070 XPoint * start; XPoint * mid;
8071 XPoint * finish; int factor;
8072 XPoint frames[]; int * nFrames;
8074 int fraction, n, count;
8078 /* Slow in, stepping 1/16th, then 1/8th, ... */
8080 for (n = 0; n < factor; n++)
8082 for (n = 0; n < factor; n++) {
8083 frames[count].x = start->x + (mid->x - start->x) / fraction;
8084 frames[count].y = start->y + (mid->y - start->y) / fraction;
8086 fraction = fraction / 2;
8090 frames[count] = *mid;
8093 /* Slow out, stepping 1/2, then 1/4, ... */
8095 for (n = 0; n < factor; n++) {
8096 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8097 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8099 fraction = fraction * 2;
8104 /* Draw a piece on the screen without disturbing what's there */
8107 SelectGCMask(piece, clip, outline, mask)
8108 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8112 /* Bitmap for piece being moved. */
8113 if (appData.monoMode) {
8114 *mask = *pieceToSolid(piece);
8115 } else if (useImages) {
8117 *mask = xpmMask[piece];
8119 *mask = ximMaskPm[piece%6];
8122 *mask = *pieceToSolid(piece);
8125 /* GC for piece being moved. Square color doesn't matter, but
8126 since it gets modified we make a copy of the original. */
8128 if (appData.monoMode)
8133 if (appData.monoMode)
8138 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8140 /* Outline only used in mono mode and is not modified */
8142 *outline = bwPieceGC;
8144 *outline = wbPieceGC;
8148 OverlayPiece(piece, clip, outline, dest)
8149 ChessSquare piece; GC clip; GC outline; Drawable dest;
8154 /* Draw solid rectangle which will be clipped to shape of piece */
8155 XFillRectangle(xDisplay, dest, clip,
8156 0, 0, squareSize, squareSize);
8157 if (appData.monoMode)
8158 /* Also draw outline in contrasting color for black
8159 on black / white on white cases */
8160 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8161 0, 0, squareSize, squareSize, 0, 0, 1);
8163 /* Copy the piece */
8168 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8170 0, 0, squareSize, squareSize,
8175 /* Animate the movement of a single piece */
8178 BeginAnimation(anim, piece, startColor, start)
8186 /* The old buffer is initialised with the start square (empty) */
8187 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8188 anim->prevFrame = *start;
8190 /* The piece will be drawn using its own bitmap as a matte */
8191 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8192 XSetClipMask(xDisplay, anim->pieceGC, mask);
8196 AnimationFrame(anim, frame, piece)
8201 XRectangle updates[4];
8206 /* Save what we are about to draw into the new buffer */
8207 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8208 frame->x, frame->y, squareSize, squareSize,
8211 /* Erase bits of the previous frame */
8212 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8213 /* Where the new frame overlapped the previous,
8214 the contents in newBuf are wrong. */
8215 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8216 overlap.x, overlap.y,
8217 overlap.width, overlap.height,
8219 /* Repaint the areas in the old that don't overlap new */
8220 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8221 for (i = 0; i < count; i++)
8222 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8223 updates[i].x - anim->prevFrame.x,
8224 updates[i].y - anim->prevFrame.y,
8225 updates[i].width, updates[i].height,
8226 updates[i].x, updates[i].y);
8228 /* Easy when no overlap */
8229 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8230 0, 0, squareSize, squareSize,
8231 anim->prevFrame.x, anim->prevFrame.y);
8234 /* Save this frame for next time round */
8235 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8236 0, 0, squareSize, squareSize,
8238 anim->prevFrame = *frame;
8240 /* Draw piece over original screen contents, not current,
8241 and copy entire rect. Wipes out overlapping piece images. */
8242 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8243 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8244 0, 0, squareSize, squareSize,
8245 frame->x, frame->y);
8249 EndAnimation (anim, finish)
8253 XRectangle updates[4];
8258 /* The main code will redraw the final square, so we
8259 only need to erase the bits that don't overlap. */
8260 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8261 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8262 for (i = 0; i < count; i++)
8263 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8264 updates[i].x - anim->prevFrame.x,
8265 updates[i].y - anim->prevFrame.y,
8266 updates[i].width, updates[i].height,
8267 updates[i].x, updates[i].y);
8269 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8270 0, 0, squareSize, squareSize,
8271 anim->prevFrame.x, anim->prevFrame.y);
8276 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8278 ChessSquare piece; int startColor;
8279 XPoint * start; XPoint * finish;
8280 XPoint frames[]; int nFrames;
8284 BeginAnimation(anim, piece, startColor, start);
8285 for (n = 0; n < nFrames; n++) {
8286 AnimationFrame(anim, &(frames[n]), piece);
8287 FrameDelay(appData.animSpeed);
8289 EndAnimation(anim, finish);
8292 /* Main control logic for deciding what to animate and how */
8295 AnimateMove(board, fromX, fromY, toX, toY)
8304 XPoint start, finish, mid;
8305 XPoint frames[kFactor * 2 + 1];
8306 int nFrames, startColor, endColor;
8308 /* Are we animating? */
8309 if (!appData.animate || appData.blindfold)
8312 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8313 piece = board[fromY][fromX];
8314 if (piece >= EmptySquare) return;
8319 hop = (piece == WhiteKnight || piece == BlackKnight);
8322 if (appData.debugMode) {
8323 printf("AnimateMove: piece %d %s from %d,%d to %d,%d \n",
8324 piece, hop ? "hops" : "slides", fromX, fromY, toX, toY);
8327 ScreenSquare(fromX, fromY, &start, &startColor);
8328 ScreenSquare(toX, toY, &finish, &endColor);
8331 /* Knight: make diagonal movement then straight */
8332 if (abs(toY - fromY) < abs(toX - fromX)) {
8333 mid.x = start.x + (finish.x - start.x) / 2;
8337 mid.y = start.y + (finish.y - start.y) / 2;
8340 mid.x = start.x + (finish.x - start.x) / 2;
8341 mid.y = start.y + (finish.y - start.y) / 2;
8344 /* Don't use as many frames for very short moves */
8345 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8346 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8348 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8349 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8351 /* Be sure end square is redrawn */
8352 damage[toY][toX] = True;
8356 DragPieceBegin(x, y)
8359 int boardX, boardY, color;
8362 /* Are we animating? */
8363 if (!appData.animateDragging || appData.blindfold)
8366 /* Figure out which square we start in and the
8367 mouse position relative to top left corner. */
8368 BoardSquare(x, y, &boardX, &boardY);
8369 player.startBoardX = boardX;
8370 player.startBoardY = boardY;
8371 ScreenSquare(boardX, boardY, &corner, &color);
8372 player.startSquare = corner;
8373 player.startColor = color;
8375 /* Start from exactly where the piece is. This can be confusing
8376 if you start dragging far from the center of the square; most
8377 or all of the piece can be over a different square from the one
8378 the mouse pointer is in. */
8379 player.mouseDelta.x = x - corner.x;
8380 player.mouseDelta.y = y - corner.y;
8382 /* As soon as we start dragging, the piece will jump slightly to
8383 be centered over the mouse pointer. */
8384 player.mouseDelta.x = squareSize/2;
8385 player.mouseDelta.y = squareSize/2;
8387 /* Initialise animation */
8388 player.dragPiece = PieceForSquare(boardX, boardY);
8390 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8391 player.dragActive = True;
8392 BeginAnimation(&player, player.dragPiece, color, &corner);
8393 /* Mark this square as needing to be redrawn. Note that
8394 we don't remove the piece though, since logically (ie
8395 as seen by opponent) the move hasn't been made yet. */
8396 damage[boardY][boardX] = True;
8398 player.dragActive = False;
8408 /* Are we animating? */
8409 if (!appData.animateDragging || appData.blindfold)
8413 if (! player.dragActive)
8415 /* Move piece, maintaining same relative position
8416 of mouse within square */
8417 corner.x = x - player.mouseDelta.x;
8418 corner.y = y - player.mouseDelta.y;
8419 AnimationFrame(&player, &corner, player.dragPiece);
8421 if (appData.highlightDragging) {
8423 BoardSquare(x, y, &boardX, &boardY);
8424 SetHighlights(fromX, fromY, boardX, boardY);
8433 int boardX, boardY, color;
8436 /* Are we animating? */
8437 if (!appData.animateDragging || appData.blindfold)
8441 if (! player.dragActive)
8443 /* Last frame in sequence is square piece is
8444 placed on, which may not match mouse exactly. */
8445 BoardSquare(x, y, &boardX, &boardY);
8446 ScreenSquare(boardX, boardY, &corner, &color);
8447 EndAnimation(&player, &corner);
8449 /* Be sure end square is redrawn */
8450 damage[boardY][boardX] = True;
8452 /* This prevents weird things happening with fast successive
8453 clicks which on my Sun at least can cause motion events
8454 without corresponding press/release. */
8455 player.dragActive = False;
8458 /* Handle expose event while piece being dragged */
8463 if (!player.dragActive || appData.blindfold)
8466 /* What we're doing: logically, the move hasn't been made yet,
8467 so the piece is still in it's original square. But visually
8468 it's being dragged around the board. So we erase the square
8469 that the piece is on and draw it at the last known drag point. */
8470 BlankSquare(player.startSquare.x, player.startSquare.y,
8471 player.startColor, EmptySquare, xBoardWindow);
8472 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8473 damage[player.startBoardY][player.startBoardX] = TRUE;