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"
199 #define usleep(t) _sleep2(((t)+500)/1000)
212 int main P((int argc, char **argv));
213 RETSIGTYPE CmailSigHandler P((int sig));
214 RETSIGTYPE IntSigHandler P((int sig));
215 void CreateGCs P((void));
216 void CreateXIMPieces P((void));
217 void CreateXPMPieces P((void));
218 void CreatePieces P((void));
219 void CreatePieceMenus P((void));
220 Widget CreateMenuBar P((Menu *mb));
221 Widget CreateButtonBar P ((MenuItem *mi));
222 char *FindFont P((char *pattern, int targetPxlSize));
223 void PieceMenuPopup P((Widget w, XEvent *event,
224 String *params, Cardinal *num_params));
225 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
226 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
227 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
228 u_int wreq, u_int hreq));
229 void CreateGrid P((void));
230 int EventToSquare P((int x, int limit));
231 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
232 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
233 void HandleUserMove P((Widget w, XEvent *event,
234 String *prms, Cardinal *nprms));
235 void AnimateUserMove P((Widget w, XEvent * event,
236 String * params, Cardinal * nParams));
237 void WhiteClock P((Widget w, XEvent *event,
238 String *prms, Cardinal *nprms));
239 void BlackClock P((Widget w, XEvent *event,
240 String *prms, Cardinal *nprms));
241 void DrawPositionProc P((Widget w, XEvent *event,
242 String *prms, Cardinal *nprms));
243 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
245 void CommentPopUp P((char *title, char *label));
246 void CommentPopDown P((void));
247 void CommentCallback P((Widget w, XtPointer client_data,
248 XtPointer call_data));
249 void ICSInputBoxPopUp P((void));
250 void ICSInputBoxPopDown P((void));
251 void FileNamePopUp P((char *label, char *def,
252 FileProc proc, char *openMode));
253 void FileNamePopDown P((void));
254 void FileNameCallback P((Widget w, XtPointer client_data,
255 XtPointer call_data));
256 void FileNameAction P((Widget w, XEvent *event,
257 String *prms, Cardinal *nprms));
258 void AskQuestionReplyAction P((Widget w, XEvent *event,
259 String *prms, Cardinal *nprms));
260 void AskQuestionProc P((Widget w, XEvent *event,
261 String *prms, Cardinal *nprms));
262 void AskQuestionPopDown P((void));
263 void PromotionPopUp P((void));
264 void PromotionPopDown P((void));
265 void PromotionCallback P((Widget w, XtPointer client_data,
266 XtPointer call_data));
267 void EditCommentPopDown P((void));
268 void EditCommentCallback P((Widget w, XtPointer client_data,
269 XtPointer call_data));
270 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
271 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
272 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
273 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
275 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
277 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
279 void LoadPositionProc P((Widget w, XEvent *event,
280 String *prms, Cardinal *nprms));
281 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
283 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
285 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
287 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
289 void PastePositionProc P((Widget w, XEvent *event, String *prms,
291 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
292 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
293 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
294 void SavePositionProc P((Widget w, XEvent *event,
295 String *prms, Cardinal *nprms));
296 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
297 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
299 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
300 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
301 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
303 void MachineWhiteProc P((Widget w, XEvent *event,
304 String *prms, Cardinal *nprms));
305 void AnalyzeModeProc P((Widget w, XEvent *event,
306 String *prms, Cardinal *nprms));
307 void AnalyzeFileProc P((Widget w, XEvent *event,
308 String *prms, Cardinal *nprms));
309 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
311 void IcsClientProc P((Widget w, XEvent *event, String *prms,
313 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
314 void EditPositionProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
317 void EditCommentProc P((Widget w, XEvent *event,
318 String *prms, Cardinal *nprms));
319 void IcsInputBoxProc P((Widget w, XEvent *event,
320 String *prms, Cardinal *nprms));
321 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
322 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
324 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
325 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
327 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
328 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
329 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
330 void StopObservingProc P((Widget w, XEvent *event, String *prms,
332 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
334 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
341 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
343 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
346 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
348 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
350 void AutocommProc P((Widget w, XEvent *event, String *prms,
352 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
354 void AutobsProc P((Widget w, XEvent *event, String *prms,
356 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
357 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
358 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
359 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
361 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
364 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
366 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
368 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
369 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
370 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
372 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
374 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
376 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
378 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
380 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
381 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
382 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
384 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
386 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
388 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
389 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
392 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
393 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
394 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
395 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
396 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
397 void DisplayMove P((int moveNumber));
398 void DisplayTitle P((char *title));
399 void ICSInitScript P((void));
400 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
401 void ErrorPopUp P((char *title, char *text, int modal));
402 void ErrorPopDown P((void));
403 static char *ExpandPathName P((char *path));
404 static void CreateAnimVars P((void));
405 static void DragPieceBegin P((int x, int y));
406 static void DragPieceMove P((int x, int y));
407 static void DragPieceEnd P((int x, int y));
408 static void DrawDragPiece P((void));
409 char *ModeToWidgetName P((GameMode mode));
412 * XBoard depends on Xt R4 or higher
414 int xtVersion = XtSpecificationRelease;
419 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
420 jailSquareColor, highlightSquareColor, premoveHighlightColor;
421 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
422 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
423 wjPieceGC, bjPieceGC, prelineGC;
424 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
425 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
426 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
427 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
428 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
429 ICSInputShell, fileNameShell, askQuestionShell;
430 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
431 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
432 Font clockFontID, coordFontID;
433 XFontStruct *clockFontStruct, *coordFontStruct;
434 XtAppContext appContext;
436 char *oldICSInteractionTitle;
441 Position commentX = -1, commentY = -1;
442 Dimension commentW, commentH;
444 int squareSize, smallLayout = 0, tinyLayout = 0,
445 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
446 ICSInputBoxUp = False, askQuestionUp = False,
447 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
448 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
449 Pixel timerForegroundPixel, timerBackgroundPixel;
450 Pixel buttonForegroundPixel, buttonBackgroundPixel;
451 char *chessDir, *programName, *programVersion,
452 *gameCopyFilename, *gamePasteFilename;
456 Pixmap pieceBitmap[2][6];
457 Pixmap xpmPieceBitmap[4][6]; /* LL, LD, DL, DD */
458 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
459 int useImages, useImageSqs;
460 XImage *ximPieceBitmap[4][6]; /* LL, LD, DL, DD */
461 Pixmap ximMaskPm[6]; /* clipmasks, used for XIM pieces */
462 XImage *ximLightSquare, *ximDarkSquare;
465 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % 6]
466 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % 6]
468 #define White(piece) ((int)(piece) < (int)BlackPawn)
470 /* Variables for doing smooth animation. This whole thing
471 would be much easier if the board was double-buffered,
472 but that would require a fairly major rewrite. */
477 GC blitGC, pieceGC, outlineGC;
478 XPoint startSquare, prevFrame, mouseDelta;
482 int startBoardX, startBoardY;
485 /* There can be two pieces being animated at once: a player
486 can begin dragging a piece before the remote opponent has moved. */
488 static AnimState game, player;
490 /* Bitmaps for use as masks when drawing XPM pieces.
491 Need one for each black and white piece. */
492 static Pixmap xpmMask[BlackKing + 1];
494 /* This magic number is the number of intermediate frames used
495 in each half of the animation. For short moves it's reduced
496 by 1. The total number of frames will be factor * 2 + 1. */
499 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
501 MenuItem fileMenu[] = {
502 {"Reset Game", ResetProc},
503 {"----", NothingProc},
504 {"Load Game", LoadGameProc},
505 {"Load Next Game", LoadNextGameProc},
506 {"Load Previous Game", LoadPrevGameProc},
507 {"Reload Same Game", ReloadGameProc},
508 {"Save Game", SaveGameProc},
509 {"----", NothingProc},
510 {"Copy Game", CopyGameProc},
511 {"Paste Game", PasteGameProc},
512 {"----", NothingProc},
513 {"Load Position", LoadPositionProc},
514 {"Load Next Position", LoadNextPositionProc},
515 {"Load Previous Position", LoadPrevPositionProc},
516 {"Reload Same Position", ReloadPositionProc},
517 {"Save Position", SavePositionProc},
518 {"----", NothingProc},
519 {"Copy Position", CopyPositionProc},
520 {"Paste Position", PastePositionProc},
521 {"----", NothingProc},
522 {"Mail Move", MailMoveProc},
523 {"Reload CMail Message", ReloadCmailMsgProc},
524 {"----", NothingProc},
529 MenuItem modeMenu[] = {
530 {"Machine White", MachineWhiteProc},
531 {"Machine Black", MachineBlackProc},
532 {"Two Machines", TwoMachinesProc},
533 {"Analysis Mode", AnalyzeModeProc},
534 {"Analyze File", AnalyzeFileProc },
535 {"ICS Client", IcsClientProc},
536 {"Edit Game", EditGameProc},
537 {"Edit Position", EditPositionProc},
538 {"Training", TrainingProc},
539 {"----", NothingProc},
540 {"Show Game List", ShowGameListProc},
541 {"Show Move List", HistoryShowProc},
542 {"Edit Tags", EditTagsProc},
543 {"Edit Comment", EditCommentProc},
544 {"ICS Input Box", IcsInputBoxProc},
545 {"Pause", PauseProc},
549 MenuItem actionMenu[] = {
550 {"Accept", AcceptProc},
551 {"Decline", DeclineProc},
552 {"Rematch", RematchProc},
553 {"----", NothingProc},
554 {"Call Flag", CallFlagProc},
556 {"Adjourn", AdjournProc},
557 {"Abort", AbortProc},
558 {"Resign", ResignProc},
559 {"----", NothingProc},
560 {"Stop Observing", StopObservingProc},
561 {"Stop Examining", StopExaminingProc},
565 MenuItem stepMenu[] = {
566 {"Backward", BackwardProc},
567 {"Forward", ForwardProc},
568 {"Back to Start", ToStartProc},
569 {"Forward to End", ToEndProc},
570 {"Revert", RevertProc},
571 {"Truncate Game", TruncateGameProc},
572 {"----", NothingProc},
573 {"Move Now", MoveNowProc},
574 {"Retract Move", RetractMoveProc},
578 MenuItem optionsMenu[] = {
579 {"Always Queen", AlwaysQueenProc},
580 {"Animate Dragging", AnimateDraggingProc},
581 {"Animate Moving", AnimateMovingProc},
582 {"Auto Comment", AutocommProc},
583 {"Auto Flag", AutoflagProc},
584 {"Auto Flip View", AutoflipProc},
585 {"Auto Observe", AutobsProc},
586 {"Auto Raise Board", AutoraiseProc},
587 {"Auto Save", AutosaveProc},
588 {"Blindfold", BlindfoldProc},
589 {"Flash Moves", FlashMovesProc},
590 {"Flip View", FlipViewProc},
591 {"Get Move List", GetMoveListProc},
593 {"Highlight Dragging", HighlightDraggingProc},
595 {"Highlight Last Move", HighlightLastMoveProc},
596 {"Move Sound", MoveSoundProc},
597 {"ICS Alarm", IcsAlarmProc},
598 {"Old Save Style", OldSaveStyleProc},
599 {"Periodic Updates", PeriodicUpdatesProc},
600 {"Ponder Next Move", PonderNextMoveProc},
601 {"Popup Exit Message", PopupExitMessageProc},
602 {"Popup Move Errors", PopupMoveErrorsProc},
603 {"Premove", PremoveProc},
604 {"Quiet Play", QuietPlayProc},
605 {"Show Coords", ShowCoordsProc},
606 {"Show Thinking", ShowThinkingProc},
607 {"Test Legality", TestLegalityProc},
611 MenuItem helpMenu[] = {
612 {"Info XBoard", InfoProc},
613 {"Man XBoard", ManProc},
614 {"----", NothingProc},
617 {"----", NothingProc},
618 {"About XBoard", AboutProc},
625 {"Action", actionMenu},
627 {"Options", optionsMenu},
632 #define PAUSE_BUTTON "P"
633 MenuItem buttonBar[] = {
636 {PAUSE_BUTTON, PauseProc},
642 #define PIECE_MENU_SIZE 11
643 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
644 { "White", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
645 "----", "Empty square", "Clear board" },
646 { "Black", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
647 "----", "Empty square", "Clear board" },
649 /* must be in same order as PieceMenuStrings! */
650 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
651 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
652 WhiteRook, WhiteQueen, WhiteKing,
653 (ChessSquare) 0, EmptySquare, ClearBoard },
654 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
655 BlackRook, BlackQueen, BlackKing,
656 (ChessSquare) 0, EmptySquare, ClearBoard },
659 #define DROP_MENU_SIZE 6
660 String dropMenuStrings[DROP_MENU_SIZE] = {
661 "----", "Pawn", "Knight", "Bishop", "Rook", "Queen"
663 /* must be in same order as PieceMenuStrings! */
664 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
665 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
666 WhiteRook, WhiteQueen
674 DropMenuEnables dmEnables[] = {
692 { XtNborderWidth, 0 },
693 { XtNdefaultDistance, 0 },
697 { XtNborderWidth, 0 },
698 { XtNresizable, (XtArgVal) True },
702 { XtNborderWidth, 0 },
708 { XtNjustify, (XtArgVal) XtJustifyRight },
709 { XtNlabel, (XtArgVal) "..." },
710 { XtNresizable, (XtArgVal) True },
711 { XtNresize, (XtArgVal) False }
714 Arg messageArgs[] = {
715 { XtNjustify, (XtArgVal) XtJustifyLeft },
716 { XtNlabel, (XtArgVal) "..." },
717 { XtNresizable, (XtArgVal) True },
718 { XtNresize, (XtArgVal) False }
722 { XtNborderWidth, 0 },
723 { XtNjustify, (XtArgVal) XtJustifyLeft }
726 XtResource clientResources[] = {
727 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
728 XtOffset(AppDataPtr, whitePieceColor), XtRString,
730 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
731 XtOffset(AppDataPtr, blackPieceColor), XtRString,
733 { "lightSquareColor", "lightSquareColor", XtRString,
734 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
735 XtRString, LIGHT_SQUARE_COLOR },
736 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
737 XtOffset(AppDataPtr, darkSquareColor), XtRString,
739 { "highlightSquareColor", "highlightSquareColor", XtRString,
740 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
741 XtRString, HIGHLIGHT_SQUARE_COLOR },
742 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
743 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
744 XtRString, PREMOVE_HIGHLIGHT_COLOR },
745 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
746 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
747 (XtPointer) MOVES_PER_SESSION },
748 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
749 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
750 (XtPointer) TIME_INCREMENT },
751 { "initString", "initString", XtRString, sizeof(String),
752 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
753 { "secondInitString", "secondInitString", XtRString, sizeof(String),
754 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
755 { "firstComputerString", "firstComputerString", XtRString,
756 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
758 { "secondComputerString", "secondComputerString", XtRString,
759 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
761 { "firstChessProgram", "firstChessProgram", XtRString,
762 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
763 XtRString, FIRST_CHESS_PROGRAM },
764 { "secondChessProgram", "secondChessProgram", XtRString,
765 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
766 XtRString, SECOND_CHESS_PROGRAM },
767 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
768 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
769 XtRImmediate, (XtPointer) False },
770 { "noChessProgram", "noChessProgram", XtRBoolean,
771 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
772 XtRImmediate, (XtPointer) False },
773 { "firstHost", "firstHost", XtRString, sizeof(String),
774 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
775 { "secondHost", "secondHost", XtRString, sizeof(String),
776 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
777 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
778 XtOffset(AppDataPtr, firstDirectory), XtRString, "" },
779 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
780 XtOffset(AppDataPtr, secondDirectory), XtRString, "" },
781 { "bitmapDirectory", "bitmapDirectory", XtRString,
782 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
784 { "remoteShell", "remoteShell", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
786 { "remoteUser", "remoteUser", XtRString, sizeof(String),
787 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
788 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
789 XtOffset(AppDataPtr, timeDelay), XtRString,
790 (XtPointer) TIME_DELAY_QUOTE },
791 { "timeControl", "timeControl", XtRString, sizeof(String),
792 XtOffset(AppDataPtr, timeControl), XtRString,
793 (XtPointer) TIME_CONTROL },
794 { "internetChessServerMode", "internetChessServerMode",
795 XtRBoolean, sizeof(Boolean),
796 XtOffset(AppDataPtr, icsActive), XtRImmediate,
798 { "internetChessServerHost", "internetChessServerHost",
799 XtRString, sizeof(String),
800 XtOffset(AppDataPtr, icsHost),
801 XtRString, (XtPointer) ICS_HOST },
802 { "internetChessServerPort", "internetChessServerPort",
803 XtRString, sizeof(String),
804 XtOffset(AppDataPtr, icsPort), XtRString,
805 (XtPointer) ICS_PORT },
806 { "internetChessServerCommPort", "internetChessServerCommPort",
807 XtRString, sizeof(String),
808 XtOffset(AppDataPtr, icsCommPort), XtRString,
810 { "internetChessServerLogonScript", "internetChessServerLogonScript",
811 XtRString, sizeof(String),
812 XtOffset(AppDataPtr, icsLogon), XtRString,
814 { "internetChessServerHelper", "internetChessServerHelper",
815 XtRString, sizeof(String),
816 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
817 { "internetChessServerInputBox", "internetChessServerInputBox",
818 XtRBoolean, sizeof(Boolean),
819 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
821 { "icsAlarm", "icsAlarm",
822 XtRBoolean, sizeof(Boolean),
823 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
825 { "icsAlarmTime", "icsAlarmTime",
827 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
829 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
830 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
832 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
833 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
834 { "gateway", "gateway", XtRString, sizeof(String),
835 XtOffset(AppDataPtr, gateway), XtRString, "" },
836 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
837 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
838 { "loadGameIndex", "loadGameIndex",
840 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
842 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
843 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
844 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
845 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
846 XtRImmediate, (XtPointer) True },
847 { "autoSaveGames", "autoSaveGames", XtRBoolean,
848 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
849 XtRImmediate, (XtPointer) False },
850 { "blindfold", "blindfold", XtRBoolean,
851 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
852 XtRImmediate, (XtPointer) False },
853 { "loadPositionFile", "loadPositionFile", XtRString,
854 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
856 { "loadPositionIndex", "loadPositionIndex",
858 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
860 { "savePositionFile", "savePositionFile", XtRString,
861 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
863 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
864 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
865 { "matchGames", "matchGames", XtRInt, sizeof(int),
866 XtOffset(AppDataPtr, matchGames), XtRImmediate,
868 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
869 XtOffset(AppDataPtr, monoMode), XtRImmediate,
871 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
872 XtOffset(AppDataPtr, debugMode), XtRImmediate,
874 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
875 XtOffset(AppDataPtr, clockMode), XtRImmediate,
877 { "boardSize", "boardSize", XtRString, sizeof(String),
878 XtOffset(AppDataPtr, boardSize), XtRString, "" },
879 { "searchTime", "searchTime", XtRString, sizeof(String),
880 XtOffset(AppDataPtr, searchTime), XtRString,
882 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
883 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
885 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, showCoords), XtRImmediate,
888 { "showJail", "showJail", XtRInt, sizeof(int),
889 XtOffset(AppDataPtr, showJail), XtRImmediate,
891 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
892 XtOffset(AppDataPtr, showThinking), XtRImmediate,
894 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
895 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
897 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
898 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
900 { "clockFont", "clockFont", XtRString, sizeof(String),
901 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
902 { "coordFont", "coordFont", XtRString, sizeof(String),
903 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
904 { "font", "font", XtRString, sizeof(String),
905 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
906 { "ringBellAfterMoves", "ringBellAfterMoves",
907 XtRBoolean, sizeof(Boolean),
908 XtOffset(AppDataPtr, ringBellAfterMoves),
909 XtRImmediate, (XtPointer) False },
910 { "autoCallFlag", "autoCallFlag", XtRBoolean,
911 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
912 XtRImmediate, (XtPointer) False },
913 { "autoFlipView", "autoFlipView", XtRBoolean,
914 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
915 XtRImmediate, (XtPointer) True },
916 { "autoObserve", "autoObserve", XtRBoolean,
917 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
918 XtRImmediate, (XtPointer) False },
919 { "autoComment", "autoComment", XtRBoolean,
920 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
921 XtRImmediate, (XtPointer) False },
922 { "getMoveList", "getMoveList", XtRBoolean,
923 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
924 XtRImmediate, (XtPointer) True },
926 { "highlightDragging", "highlightDragging", XtRBoolean,
927 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
928 XtRImmediate, (XtPointer) False },
930 { "highlightLastMove", "highlightLastMove", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
932 XtRImmediate, (XtPointer) False },
933 { "premove", "premove", XtRBoolean,
934 sizeof(Boolean), XtOffset(AppDataPtr, premove),
935 XtRImmediate, (XtPointer) True },
936 { "testLegality", "testLegality", XtRBoolean,
937 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
938 XtRImmediate, (XtPointer) True },
939 { "flipView", "flipView", XtRBoolean,
940 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
941 XtRImmediate, (XtPointer) False },
942 { "cmail", "cmailGameName", XtRString, sizeof(String),
943 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
944 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
946 XtRImmediate, (XtPointer) False },
947 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
948 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
949 XtRImmediate, (XtPointer) False },
950 { "quietPlay", "quietPlay", XtRBoolean,
951 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
952 XtRImmediate, (XtPointer) False },
953 { "titleInWindow", "titleInWindow", XtRBoolean,
954 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
955 XtRImmediate, (XtPointer) False },
956 { "localLineEditing", "localLineEditing", XtRBoolean,
957 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
958 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
960 { "zippyTalk", "zippyTalk", XtRBoolean,
961 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
962 XtRImmediate, (XtPointer) ZIPPY_TALK },
963 { "zippyPlay", "zippyPlay", XtRBoolean,
964 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
965 XtRImmediate, (XtPointer) ZIPPY_PLAY },
966 { "zippyLines", "zippyLines", XtRString, sizeof(String),
967 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
968 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
969 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
970 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
971 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
972 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
973 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
974 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
975 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
976 ZIPPY_WRONG_PASSWORD },
977 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
978 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
979 { "zippyUseI", "zippyUseI", XtRBoolean,
980 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
981 XtRImmediate, (XtPointer) ZIPPY_USE_I },
982 { "zippyBughouse", "zippyBughouse", XtRInt,
983 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
984 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
985 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
986 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
987 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
988 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
990 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
991 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
992 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
993 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
994 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
995 { "zippyAbort", "zippyAbort", XtRBoolean,
996 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
997 XtRImmediate, (XtPointer) ZIPPY_ABORT },
998 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
999 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1000 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1001 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1002 (XtPointer) ZIPPY_MAX_GAMES },
1003 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1004 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1005 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1007 { "flashCount", "flashCount", XtRInt, sizeof(int),
1008 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1009 (XtPointer) FLASH_COUNT },
1010 { "flashRate", "flashRate", XtRInt, sizeof(int),
1011 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1012 (XtPointer) FLASH_RATE },
1013 { "pixmapDirectory", "pixmapDirectory", XtRString,
1014 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1016 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1017 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1018 (XtPointer) MS_LOGIN_DELAY },
1019 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1020 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1021 XtRImmediate, (XtPointer) False },
1022 { "colorShout", "colorShout", XtRString,
1023 sizeof(String), XtOffset(AppDataPtr, colorShout),
1024 XtRString, COLOR_SHOUT },
1025 { "colorSShout", "colorSShout", XtRString,
1026 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1027 XtRString, COLOR_SSHOUT },
1028 { "colorChannel1", "colorChannel1", XtRString,
1029 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1030 XtRString, COLOR_CHANNEL1 },
1031 { "colorChannel", "colorChannel", XtRString,
1032 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1033 XtRString, COLOR_CHANNEL },
1034 { "colorKibitz", "colorKibitz", XtRString,
1035 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1036 XtRString, COLOR_KIBITZ },
1037 { "colorTell", "colorTell", XtRString,
1038 sizeof(String), XtOffset(AppDataPtr, colorTell),
1039 XtRString, COLOR_TELL },
1040 { "colorChallenge", "colorChallenge", XtRString,
1041 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1042 XtRString, COLOR_CHALLENGE },
1043 { "colorRequest", "colorRequest", XtRString,
1044 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1045 XtRString, COLOR_REQUEST },
1046 { "colorSeek", "colorSeek", XtRString,
1047 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1048 XtRString, COLOR_SEEK },
1049 { "colorNormal", "colorNormal", XtRString,
1050 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1051 XtRString, COLOR_NORMAL },
1052 { "soundProgram", "soundProgram", XtRString,
1053 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1054 XtRString, "play" },
1055 { "soundShout", "soundShout", XtRString,
1056 sizeof(String), XtOffset(AppDataPtr, soundShout),
1058 { "soundSShout", "soundSShout", XtRString,
1059 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1061 { "soundChannel1", "soundChannel1", XtRString,
1062 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1064 { "soundChannel", "soundChannel", XtRString,
1065 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1067 { "soundKibitz", "soundKibitz", XtRString,
1068 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1070 { "soundTell", "soundTell", XtRString,
1071 sizeof(String), XtOffset(AppDataPtr, soundTell),
1073 { "soundChallenge", "soundChallenge", XtRString,
1074 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1076 { "soundRequest", "soundRequest", XtRString,
1077 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1079 { "soundSeek", "soundSeek", XtRString,
1080 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1082 { "soundMove", "soundMove", XtRString,
1083 sizeof(String), XtOffset(AppDataPtr, soundMove),
1085 { "soundIcsWin", "soundIcsWin", XtRString,
1086 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1088 { "soundIcsLoss", "soundIcsLoss", XtRString,
1089 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1091 { "soundIcsDraw", "soundIcsDraw", XtRString,
1092 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1094 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1095 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1097 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1098 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1100 { "reuseFirst", "reuseFirst", XtRBoolean,
1101 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1102 XtRImmediate, (XtPointer) True },
1103 { "reuseSecond", "reuseSecond", XtRBoolean,
1104 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1105 XtRImmediate, (XtPointer) True },
1106 { "animateDragging", "animateDragging", XtRBoolean,
1107 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1108 XtRImmediate, (XtPointer) True },
1109 { "animateMoving", "animateMoving", XtRBoolean,
1110 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1111 XtRImmediate, (XtPointer) True },
1112 { "animateSpeed", "animateSpeed", XtRInt,
1113 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1114 XtRImmediate, (XtPointer)10 },
1115 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1116 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1117 XtRImmediate, (XtPointer) True },
1118 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1119 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1120 XtRImmediate, (XtPointer) False },
1121 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1122 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1123 XtRImmediate, (XtPointer)4 },
1124 { "initialMode", "initialMode", XtRString,
1125 sizeof(String), XtOffset(AppDataPtr, initialMode),
1126 XtRImmediate, (XtPointer) "" },
1127 { "variant", "variant", XtRString,
1128 sizeof(String), XtOffset(AppDataPtr, variant),
1129 XtRImmediate, (XtPointer) "normal" },
1130 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1131 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1132 XtRImmediate, (XtPointer)PROTOVER },
1133 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1134 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1135 XtRImmediate, (XtPointer)PROTOVER },
1136 { "showButtonBar", "showButtonBar", XtRBoolean,
1137 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1138 XtRImmediate, (XtPointer) True },
1141 XrmOptionDescRec shellOptions[] = {
1142 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1143 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1144 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1145 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1146 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1147 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1148 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1149 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1150 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1151 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1152 { "-initString", "initString", XrmoptionSepArg, NULL },
1153 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1154 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1155 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1156 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1157 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1158 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1159 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1160 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1161 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1162 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1163 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1164 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1165 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1166 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1167 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1168 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1169 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1170 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1171 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1172 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1173 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1174 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1175 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1176 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1177 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1178 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1179 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1180 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1181 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1182 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1183 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1184 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1185 { "-internetChessServerMode", "internetChessServerMode",
1186 XrmoptionSepArg, NULL },
1187 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1188 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1189 { "-internetChessServerHost", "internetChessServerHost",
1190 XrmoptionSepArg, NULL },
1191 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1192 { "-internetChessServerPort", "internetChessServerPort",
1193 XrmoptionSepArg, NULL },
1194 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1195 { "-internetChessServerCommPort", "internetChessServerCommPort",
1196 XrmoptionSepArg, NULL },
1197 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1198 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1199 XrmoptionSepArg, NULL },
1200 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1201 { "-internetChessServerHelper", "internetChessServerHelper",
1202 XrmoptionSepArg, NULL },
1203 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1204 { "-internetChessServerInputBox", "internetChessServerInputBox",
1205 XrmoptionSepArg, NULL },
1206 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1207 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1208 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1209 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1210 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1211 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1212 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1213 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1214 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1215 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1216 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1217 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1218 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1219 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1220 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1221 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1222 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1223 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1224 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1225 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1226 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1227 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1228 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1229 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1230 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1231 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1232 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1233 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1234 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1235 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1236 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1237 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1238 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1239 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1240 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1241 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1242 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1243 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1244 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1245 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1246 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1247 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1248 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1249 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1250 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1251 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1252 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1253 { "-size", "boardSize", XrmoptionSepArg, NULL },
1254 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1255 { "-st", "searchTime", XrmoptionSepArg, NULL },
1256 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1257 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1258 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1259 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1260 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1262 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1263 { "-jail", "showJail", XrmoptionNoArg, "1" },
1264 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1265 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1267 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1268 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1269 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1270 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1271 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1272 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1273 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1274 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1275 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1276 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1277 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1278 { "-font", "font", XrmoptionSepArg, NULL },
1279 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1280 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1281 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1282 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1283 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1284 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1285 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1286 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1287 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1288 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1289 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1290 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1291 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1292 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1293 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1294 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1295 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1296 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1297 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1298 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1300 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1301 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1302 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1304 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1305 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1306 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1307 { "-premove", "premove", XrmoptionSepArg, NULL },
1308 { "-pre", "premove", XrmoptionNoArg, "True" },
1309 { "-xpre", "premove", XrmoptionNoArg, "False" },
1310 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1311 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1312 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1313 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1314 { "-flip", "flipView", XrmoptionNoArg, "True" },
1315 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1316 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1317 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1318 XrmoptionSepArg, NULL },
1319 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1320 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1321 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1322 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1323 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1324 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1325 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1326 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1327 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1328 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1329 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1331 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1332 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1333 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1334 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1335 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1336 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1337 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1338 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1339 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1340 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1341 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1342 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1343 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1344 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1345 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1346 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1347 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1348 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1349 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1350 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1351 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1352 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1353 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1354 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1355 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1356 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1357 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1358 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1359 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1360 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1362 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1363 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1364 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1365 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1366 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1367 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1368 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1369 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1370 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1371 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1372 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1373 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1374 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1375 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1376 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1377 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1378 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1379 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1380 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1381 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1382 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1383 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1384 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1385 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1386 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1387 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1388 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1389 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1390 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1391 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1392 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1393 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1394 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1395 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1396 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1397 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1398 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1399 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1400 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1401 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1402 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1403 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1404 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1405 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1406 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1407 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1408 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1409 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1410 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1411 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1412 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1413 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1414 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1415 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1416 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1417 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1418 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1419 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1420 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1421 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1422 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1423 { "-variant", "variant", XrmoptionSepArg, NULL },
1424 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1425 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1426 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1427 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1428 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1432 XtActionsRec boardActions[] = {
1433 { "DrawPosition", DrawPositionProc },
1434 { "HandleUserMove", HandleUserMove },
1435 { "AnimateUserMove", AnimateUserMove },
1436 { "FileNameAction", FileNameAction },
1437 { "AskQuestionProc", AskQuestionProc },
1438 { "AskQuestionReplyAction", AskQuestionReplyAction },
1439 { "PieceMenuPopup", PieceMenuPopup },
1440 { "WhiteClock", WhiteClock },
1441 { "BlackClock", BlackClock },
1442 { "Iconify", Iconify },
1443 { "ResetProc", ResetProc },
1444 { "LoadGameProc", LoadGameProc },
1445 { "LoadNextGameProc", LoadNextGameProc },
1446 { "LoadPrevGameProc", LoadPrevGameProc },
1447 { "LoadSelectedProc", LoadSelectedProc },
1448 { "ReloadGameProc", ReloadGameProc },
1449 { "LoadPositionProc", LoadPositionProc },
1450 { "LoadNextPositionProc", LoadNextPositionProc },
1451 { "LoadPrevPositionProc", LoadPrevPositionProc },
1452 { "ReloadPositionProc", ReloadPositionProc },
1453 { "CopyPositionProc", CopyPositionProc },
1454 { "PastePositionProc", PastePositionProc },
1455 { "CopyGameProc", CopyGameProc },
1456 { "PasteGameProc", PasteGameProc },
1457 { "SaveGameProc", SaveGameProc },
1458 { "SavePositionProc", SavePositionProc },
1459 { "MailMoveProc", MailMoveProc },
1460 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1461 { "QuitProc", QuitProc },
1462 { "MachineWhiteProc", MachineWhiteProc },
1463 { "MachineBlackProc", MachineBlackProc },
1464 { "AnalysisModeProc", AnalyzeModeProc },
1465 { "AnalyzeFileProc", AnalyzeFileProc },
1466 { "TwoMachinesProc", TwoMachinesProc },
1467 { "IcsClientProc", IcsClientProc },
1468 { "EditGameProc", EditGameProc },
1469 { "EditPositionProc", EditPositionProc },
1470 { "TrainingProc", EditPositionProc },
1471 { "ShowGameListProc", ShowGameListProc },
1472 { "ShowMoveListProc", HistoryShowProc},
1473 { "EditTagsProc", EditCommentProc },
1474 { "EditCommentProc", EditCommentProc },
1475 { "IcsAlarmProc", IcsAlarmProc },
1476 { "IcsInputBoxProc", IcsInputBoxProc },
1477 { "PauseProc", PauseProc },
1478 { "AcceptProc", AcceptProc },
1479 { "DeclineProc", DeclineProc },
1480 { "RematchProc", RematchProc },
1481 { "CallFlagProc", CallFlagProc },
1482 { "DrawProc", DrawProc },
1483 { "AdjournProc", AdjournProc },
1484 { "AbortProc", AbortProc },
1485 { "ResignProc", ResignProc },
1486 { "EnterKeyProc", EnterKeyProc },
1487 { "StopObservingProc", StopObservingProc },
1488 { "StopExaminingProc", StopExaminingProc },
1489 { "BackwardProc", BackwardProc },
1490 { "ForwardProc", ForwardProc },
1491 { "ToStartProc", ToStartProc },
1492 { "ToEndProc", ToEndProc },
1493 { "RevertProc", RevertProc },
1494 { "TruncateGameProc", TruncateGameProc },
1495 { "MoveNowProc", MoveNowProc },
1496 { "RetractMoveProc", RetractMoveProc },
1497 { "AlwaysQueenProc", AlwaysQueenProc },
1498 { "AnimateDraggingProc", AnimateDraggingProc },
1499 { "AnimateMovingProc", AnimateMovingProc },
1500 { "AutoflagProc", AutoflagProc },
1501 { "AutoflipProc", AutoflipProc },
1502 { "AutobsProc", AutobsProc },
1503 { "AutoraiseProc", AutoraiseProc },
1504 { "AutosaveProc", AutosaveProc },
1505 { "BlindfoldProc", BlindfoldProc },
1506 { "FlashMovesProc", FlashMovesProc },
1507 { "FlipViewProc", FlipViewProc },
1508 { "GetMoveListProc", GetMoveListProc },
1510 { "HighlightDraggingProc", HighlightDraggingProc },
1512 { "HighlightLastMoveProc", HighlightLastMoveProc },
1513 { "IcsAlarmProc", IcsAlarmProc },
1514 { "MoveSoundProc", MoveSoundProc },
1515 { "OldSaveStyleProc", OldSaveStyleProc },
1516 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1517 { "PonderNextMoveProc", PonderNextMoveProc },
1518 { "PopupExitMessageProc", PopupExitMessageProc },
1519 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1520 { "PremoveProc", PremoveProc },
1521 { "QuietPlayProc", QuietPlayProc },
1522 { "ShowCoordsProc", ShowCoordsProc },
1523 { "ShowThinkingProc", ShowThinkingProc },
1524 { "TestLegalityProc", TestLegalityProc },
1525 { "InfoProc", InfoProc },
1526 { "ManProc", ManProc },
1527 { "HintProc", HintProc },
1528 { "BookProc", BookProc },
1529 { "AboutGameProc", AboutGameProc },
1530 { "AboutProc", AboutProc },
1531 { "DebugProc", DebugProc },
1532 { "NothingProc", NothingProc },
1533 { "CommentPopDown", (XtActionProc) CommentPopDown },
1534 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1535 { "TagsPopDown", (XtActionProc) TagsPopDown },
1536 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1537 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1538 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1539 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1540 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1541 { "GameListPopDown", (XtActionProc) GameListPopDown },
1542 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1543 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1546 char globalTranslations[] =
1547 ":<Key>R: ResignProc() \n \
1548 :<Key>r: ResetProc() \n \
1549 :<Key>g: LoadGameProc() \n \
1550 :<Key>N: LoadNextGameProc() \n \
1551 :<Key>P: LoadPrevGameProc() \n \
1552 :<Key>Q: QuitProc() \n \
1553 :<Key>F: ToEndProc() \n \
1554 :<Key>f: ForwardProc() \n \
1555 :<Key>B: ToStartProc() \n \
1556 :<Key>b: BackwardProc() \n \
1557 :<Key>p: PauseProc() \n \
1558 :<Key>d: DrawProc() \n \
1559 :<Key>t: CallFlagProc() \n \
1560 :<Key>i: Iconify() \n \
1561 :<Key>c: Iconify() \n \
1562 :<Key>v: FlipViewProc() \n \
1563 <KeyDown>Control_L: BackwardProc() \n \
1564 <KeyUp>Control_L: ForwardProc() \n \
1565 <KeyDown>Control_R: BackwardProc() \n \
1566 <KeyUp>Control_R: ForwardProc() \n \
1567 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1568 \"Send to chess program:\",,1) \n \
1569 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1570 \"Send to second chess program:\",,2) \n";
1572 char boardTranslations[] =
1573 "<Btn1Down>: HandleUserMove() \n \
1574 <Btn1Up>: HandleUserMove() \n \
1575 <Btn1Motion>: AnimateUserMove() \n \
1576 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1577 PieceMenuPopup(menuB) \n \
1578 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1579 PieceMenuPopup(menuW) \n \
1580 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1581 PieceMenuPopup(menuW) \n \
1582 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1583 PieceMenuPopup(menuB) \n";
1585 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1586 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1588 char ICSInputTranslations[] =
1589 "<Key>Return: EnterKeyProc() \n";
1591 String xboardResources[] = {
1592 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1593 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1594 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1599 /* Max possible square size */
1600 #define MAXSQSIZE 256
1602 static int xpm_avail[MAXSQSIZE];
1604 #ifdef HAVE_DIR_STRUCT
1606 /* Extract piece size from filename */
1608 xpm_getsize(name, len, ext)
1619 if ((p=strchr(name, '.')) == NULL ||
1620 StrCaseCmp(p+1, ext) != 0)
1626 while (*p && isdigit(*p))
1633 /* Setup xpm_avail */
1635 xpm_getavail(dirname, ext)
1643 for (i=0; i<MAXSQSIZE; ++i)
1646 if (appData.debugMode)
1647 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1649 dir = opendir(dirname);
1652 fprintf(stderr, "%s: Can't access XPM directory %s\n",
1653 programName, dirname);
1657 while ((ent=readdir(dir)) != NULL) {
1658 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1659 if (i > 0 && i < MAXSQSIZE)
1669 xpm_print_avail(fp, ext)
1675 fprintf(fp, "Available `%s' sizes:\n", ext);
1676 for (i=1; i<MAXSQSIZE; ++i) {
1682 /* Return XPM piecesize closest to size */
1684 xpm_closest_to(dirname, size, ext)
1690 int sm_diff = MAXSQSIZE;
1694 xpm_getavail(dirname, ext);
1696 if (appData.debugMode)
1697 xpm_print_avail(stderr, ext);
1699 for (i=1; i<MAXSQSIZE; ++i) {
1702 diff = (diff<0) ? -diff : diff;
1703 if (diff < sm_diff) {
1711 fprintf(stderr, "Error: No `%s' files!\n", ext);
1717 #else /* !HAVE_DIR_STRUCT */
1718 /* If we are on a system without a DIR struct, we can't
1719 read the directory, so we can't collect a list of
1720 filenames, etc., so we can't do any size-fitting. */
1722 xpm_closest_to(dirname, size, ext)
1727 fprintf(stderr, "Warning: No DIR structure found on this system --\n");
1728 fprintf(stderr, " Unable to autosize for XPM/XIM pieces.\n");
1729 fprintf(stderr, " Please report this error to frankm@hiwaay.net.\n");
1730 fprintf(stderr, " Include system type & operating system in message.\n");
1733 #endif /* HAVE_DIR_STRUCT */
1735 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1736 "magenta", "cyan", "white" };
1740 TextColors textColors[(int)NColorClasses];
1742 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1744 parse_color(str, which)
1748 char *p, buf[100], *d;
1751 if (strlen(str) > 99) /* watch bounds on buf */
1756 for (i=0; i<which; ++i) {
1763 /* Could be looking at something like:
1765 .. in which case we want to stop on a comma also */
1766 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1770 return -1; /* Use default for empty field */
1773 if (which == 2 || isdigit(*p))
1776 while (*p && isalpha(*p))
1781 for (i=0; i<8; ++i) {
1782 if (!StrCaseCmp(buf, cnames[i]))
1783 return which? (i+40) : (i+30);
1785 if (!StrCaseCmp(buf, "default")) return -1;
1787 fprintf(stderr, "%s: unrecognized color %s\n", programName, buf);
1792 parse_cpair(cc, str)
1796 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1797 fprintf(stderr, "%s: can't parse foreground color in `%s'\n",
1802 /* bg and attr are optional */
1803 textColors[(int)cc].bg = parse_color(str, 1);
1804 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1805 textColors[(int)cc].attr = 0;
1811 /* Arrange to catch delete-window events */
1812 Atom wm_delete_window;
1814 CatchDeleteWindow(Widget w, String procname)
1817 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1818 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
1819 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1826 XtSetArg(args[0], XtNiconic, False);
1827 XtSetValues(shellWidget, args, 1);
1829 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1837 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1838 XSetWindowAttributes window_attributes;
1840 Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
1841 XrmValue vFrom, vTo;
1842 XtGeometryResult gres;
1845 int forceMono = False;
1847 setbuf(stdout, NULL);
1848 setbuf(stderr, NULL);
1851 programName = strrchr(argv[0], '/');
1852 if (programName == NULL)
1853 programName = argv[0];
1858 XtAppInitialize(&appContext, "XBoard", shellOptions,
1859 XtNumber(shellOptions),
1860 &argc, argv, xboardResources, NULL, 0);
1862 fprintf(stderr, "%s: unrecognized argument %s\n",
1863 programName, argv[1]);
1867 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1870 if (chdir(chessDir) != 0) {
1871 fprintf(stderr, "%s: can't cd to CHESSDIR: ", programName);
1878 if (p == NULL) p = "/tmp";
1879 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1880 gameCopyFilename = (char*) malloc(i);
1881 gamePasteFilename = (char*) malloc(i);
1882 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1883 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1885 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1886 clientResources, XtNumber(clientResources),
1890 /* This feature does not work; animation needs a rewrite */
1891 appData.highlightDragging = FALSE;
1895 xDisplay = XtDisplay(shellWidget);
1896 xScreen = DefaultScreen(xDisplay);
1897 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1900 * Determine boardSize
1902 if (isdigit(appData.boardSize[0])) {
1903 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1904 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1905 &fontPxlSize, &smallLayout, &tinyLayout);
1907 fprintf(stderr, "%s: bad boardSize syntax %s\n",
1908 programName, appData.boardSize);
1912 /* Find some defaults; use the nearest known size */
1913 SizeDefaults *szd, *nearest;
1914 int distance = 99999;
1915 nearest = szd = sizeDefaults;
1916 while (szd->name != NULL) {
1917 if (abs(szd->squareSize - squareSize) < distance) {
1919 distance = abs(szd->squareSize - squareSize);
1920 if (distance == 0) break;
1924 if (i < 2) lineGap = nearest->lineGap;
1925 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1926 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1927 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1928 if (i < 6) smallLayout = nearest->smallLayout;
1929 if (i < 7) tinyLayout = nearest->tinyLayout;
1932 SizeDefaults *szd = sizeDefaults;
1933 if (*appData.boardSize == NULLCHAR) {
1934 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1935 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1938 if (szd->name == NULL) szd--;
1940 while (szd->name != NULL &&
1941 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1942 if (szd->name == NULL) {
1943 fprintf(stderr, "%s: unrecognized boardSize name %s\n",
1944 programName, appData.boardSize);
1948 squareSize = szd->squareSize;
1949 lineGap = szd->lineGap;
1950 clockFontPxlSize = szd->clockFontPxlSize;
1951 coordFontPxlSize = szd->coordFontPxlSize;
1952 fontPxlSize = szd->fontPxlSize;
1953 smallLayout = szd->smallLayout;
1954 tinyLayout = szd->tinyLayout;
1957 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1958 if (strlen(appData.pixmapDirectory) > 0) {
1959 p = ExpandPathName(appData.pixmapDirectory);
1961 fprintf(stderr, "Error expanding path name \"%s\"\n",
1962 appData.pixmapDirectory);
1965 if (appData.debugMode) {
1966 fprintf(stderr, "XBoard square size (hint): %d\n", squareSize);
1967 fprintf(stderr, "%s fulldir:%s:\n", IMAGE_EXT, p);
1969 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1970 if (appData.debugMode) {
1971 fprintf(stderr, "Closest %s size: %d\n", IMAGE_EXT, squareSize);
1975 boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
1976 if (appData.showJail == 1) {
1977 /* Jail on top and bottom */
1978 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1979 XtSetArg(boardArgs[2], XtNheight,
1980 boardWidth + 2*(lineGap + squareSize));
1981 } else if (appData.showJail == 2) {
1983 XtSetArg(boardArgs[1], XtNwidth,
1984 boardWidth + 2*(lineGap + squareSize));
1985 XtSetArg(boardArgs[2], XtNheight, boardWidth);
1988 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1989 XtSetArg(boardArgs[2], XtNheight, boardWidth);
1993 * Determine what fonts to use.
1995 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
1996 clockFontID = XLoadFont(xDisplay, appData.clockFont);
1997 clockFontStruct = XQueryFont(xDisplay, clockFontID);
1998 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
1999 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2000 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2001 appData.font = FindFont(appData.font, fontPxlSize);
2003 xdb = XtDatabase(xDisplay);
2004 XrmPutStringResource(&xdb, "*font", appData.font);
2007 * Detect if there are not enough colors available and adapt.
2009 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2010 appData.monoMode = True;
2013 if (!appData.monoMode) {
2014 vFrom.addr = (caddr_t) appData.lightSquareColor;
2015 vFrom.size = strlen(appData.lightSquareColor);
2016 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2017 if (vTo.addr == NULL) {
2018 appData.monoMode = True;
2021 lightSquareColor = *(Pixel *) vTo.addr;
2024 if (!appData.monoMode) {
2025 vFrom.addr = (caddr_t) appData.darkSquareColor;
2026 vFrom.size = strlen(appData.darkSquareColor);
2027 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2028 if (vTo.addr == NULL) {
2029 appData.monoMode = True;
2032 darkSquareColor = *(Pixel *) vTo.addr;
2035 if (!appData.monoMode) {
2036 vFrom.addr = (caddr_t) appData.whitePieceColor;
2037 vFrom.size = strlen(appData.whitePieceColor);
2038 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2039 if (vTo.addr == NULL) {
2040 appData.monoMode = True;
2043 whitePieceColor = *(Pixel *) vTo.addr;
2046 if (!appData.monoMode) {
2047 vFrom.addr = (caddr_t) appData.blackPieceColor;
2048 vFrom.size = strlen(appData.blackPieceColor);
2049 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2050 if (vTo.addr == NULL) {
2051 appData.monoMode = True;
2054 blackPieceColor = *(Pixel *) vTo.addr;
2058 if (!appData.monoMode) {
2059 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2060 vFrom.size = strlen(appData.highlightSquareColor);
2061 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2062 if (vTo.addr == NULL) {
2063 appData.monoMode = True;
2066 highlightSquareColor = *(Pixel *) vTo.addr;
2070 if (!appData.monoMode) {
2071 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2072 vFrom.size = strlen(appData.premoveHighlightColor);
2073 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2074 if (vTo.addr == NULL) {
2075 appData.monoMode = True;
2078 premoveHighlightColor = *(Pixel *) vTo.addr;
2083 fprintf(stderr, "%s: too few colors available; trying monochrome mode\n",
2087 if (appData.monoMode && appData.debugMode) {
2088 fprintf(stderr, "white pixel = 0x%lx, black pixel = 0x%lx\n",
2089 (unsigned long) XWhitePixel(xDisplay, xScreen),
2090 (unsigned long) XBlackPixel(xDisplay, xScreen));
2093 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2094 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2095 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2096 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2097 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2098 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2099 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2100 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2101 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2102 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2104 if (appData.colorize) {
2106 "%s: can't parse color names; disabling colorization\n",
2109 appData.colorize = FALSE;
2111 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2112 textColors[ColorNone].attr = 0;
2114 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2120 layoutName = "tinyLayout";
2121 } else if (smallLayout) {
2122 layoutName = "smallLayout";
2124 layoutName = "normalLayout";
2126 /* Outer layoutWidget is there only to provide a name for use in
2127 resources that depend on the layout style */
2129 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2130 layoutArgs, XtNumber(layoutArgs));
2132 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2133 formArgs, XtNumber(formArgs));
2134 XtSetArg(args[0], XtNdefaultDistance, &sep);
2135 XtGetValues(formWidget, args, 1);
2138 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2140 widgetList[j++] = whiteTimerWidget =
2141 XtCreateWidget("whiteTime", labelWidgetClass,
2142 formWidget, timerArgs, XtNumber(timerArgs));
2143 XtSetArg(args[0], XtNfont, clockFontStruct);
2144 XtSetValues(whiteTimerWidget, args, 1);
2146 widgetList[j++] = blackTimerWidget =
2147 XtCreateWidget("blackTime", labelWidgetClass,
2148 formWidget, timerArgs, XtNumber(timerArgs));
2149 XtSetArg(args[0], XtNfont, clockFontStruct);
2150 XtSetValues(blackTimerWidget, args, 1);
2152 if (appData.titleInWindow) {
2153 widgetList[j++] = titleWidget =
2154 XtCreateWidget("title", labelWidgetClass, formWidget,
2155 titleArgs, XtNumber(titleArgs));
2158 if (appData.showButtonBar) {
2159 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2162 widgetList[j++] = messageWidget =
2163 XtCreateWidget("message", labelWidgetClass, formWidget,
2164 messageArgs, XtNumber(messageArgs));
2166 widgetList[j++] = boardWidget =
2167 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2168 XtNumber(boardArgs));
2170 XtManageChildren(widgetList, j);
2172 timerWidth = (boardWidth - sep) / 2;
2173 XtSetArg(args[0], XtNwidth, timerWidth);
2174 XtSetValues(whiteTimerWidget, args, 1);
2175 XtSetValues(blackTimerWidget, args, 1);
2177 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2178 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2179 XtGetValues(whiteTimerWidget, args, 2);
2181 if (appData.showButtonBar) {
2182 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2183 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2184 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2188 * formWidget uses these constraints but they are stored
2192 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2193 XtSetValues(menuBarWidget, args, i);
2194 if (appData.titleInWindow) {
2197 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2198 XtSetValues(whiteTimerWidget, args, i);
2200 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2201 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2202 XtSetValues(blackTimerWidget, args, i);
2204 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2205 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2206 XtSetValues(titleWidget, args, i);
2208 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2209 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2210 XtSetValues(messageWidget, args, i);
2211 if (appData.showButtonBar) {
2213 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2214 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2215 XtSetValues(buttonBarWidget, args, i);
2219 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2220 XtSetValues(whiteTimerWidget, args, i);
2222 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2223 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2224 XtSetValues(blackTimerWidget, args, i);
2226 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2227 XtSetValues(titleWidget, args, i);
2229 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2230 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2231 XtSetValues(messageWidget, args, i);
2232 if (appData.showButtonBar) {
2234 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2235 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2236 XtSetValues(buttonBarWidget, args, i);
2241 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2242 XtSetValues(whiteTimerWidget, args, i);
2244 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2245 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2246 XtSetValues(blackTimerWidget, args, i);
2248 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2249 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2250 XtSetValues(messageWidget, args, i);
2251 if (appData.showButtonBar) {
2253 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2254 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2255 XtSetValues(buttonBarWidget, args, i);
2259 XtSetArg(args[0], XtNfromVert, messageWidget);
2260 XtSetValues(boardWidget, args, 1);
2262 XtRealizeWidget(shellWidget);
2265 * Correct the width of the message and title widgets.
2266 * It is not known why some systems need the extra fudge term.
2267 * The value "2" is probably larger than needed.
2269 XawFormDoLayout(formWidget, False);
2270 #define WIDTH_FUDGE 2
2272 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2273 XtSetArg(args[i], XtNheight, &h); i++;
2274 XtGetValues(messageWidget, args, i);
2275 if (appData.showButtonBar) {
2277 XtSetArg(args[i], XtNwidth, &w); i++;
2278 XtGetValues(buttonBarWidget, args, i);
2279 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2281 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2284 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2285 if (gres != XtGeometryYes && appData.debugMode) {
2286 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
2287 programName, gres, w, h, wr, hr);
2290 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2291 /* The size used for the child widget in layout lags one resize behind
2292 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2294 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2295 if (gres != XtGeometryYes && appData.debugMode) {
2296 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
2297 programName, gres, w, h, wr, hr);
2301 if (appData.titleInWindow) {
2303 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2304 XtSetArg(args[i], XtNheight, &h); i++;
2305 XtGetValues(titleWidget, args, i);
2307 w = boardWidth - 2*bor;
2309 XtSetArg(args[0], XtNwidth, &w);
2310 XtGetValues(menuBarWidget, args, 1);
2311 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2314 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2315 if (gres != XtGeometryYes && appData.debugMode) {
2317 "%s: titleWidget geometry error %d %d %d %d %d\n",
2318 programName, gres, w, h, wr, hr);
2321 XawFormDoLayout(formWidget, True);
2323 xBoardWindow = XtWindow(boardWidget);
2326 * Create X checkmark bitmap and initialize option menu checks.
2328 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2329 checkmark_bits, checkmark_width, checkmark_height);
2330 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2331 if (appData.alwaysPromoteToQueen) {
2332 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2335 if (appData.animateDragging) {
2336 XtSetValues(XtNameToWidget(menuBarWidget,
2337 "menuOptions.Animate Dragging"),
2340 if (appData.animate) {
2341 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2344 if (appData.autoComment) {
2345 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2348 if (appData.autoCallFlag) {
2349 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2352 if (appData.autoFlipView) {
2353 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2356 if (appData.autoObserve) {
2357 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2360 if (appData.autoRaiseBoard) {
2361 XtSetValues(XtNameToWidget(menuBarWidget,
2362 "menuOptions.Auto Raise Board"), args, 1);
2364 if (appData.autoSaveGames) {
2365 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2368 if (appData.saveGameFile[0] != NULLCHAR) {
2369 /* Can't turn this off from menu */
2370 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2372 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2376 if (appData.blindfold) {
2377 XtSetValues(XtNameToWidget(menuBarWidget,
2378 "menuOptions.Blindfold"), args, 1);
2380 if (appData.flashCount > 0) {
2381 XtSetValues(XtNameToWidget(menuBarWidget,
2382 "menuOptions.Flash Moves"),
2385 if (appData.getMoveList) {
2386 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2390 if (appData.highlightDragging) {
2391 XtSetValues(XtNameToWidget(menuBarWidget,
2392 "menuOptions.Highlight Dragging"),
2396 if (appData.highlightLastMove) {
2397 XtSetValues(XtNameToWidget(menuBarWidget,
2398 "menuOptions.Highlight Last Move"),
2401 if (appData.icsAlarm) {
2402 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2405 if (appData.ringBellAfterMoves) {
2406 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2409 if (appData.oldSaveStyle) {
2410 XtSetValues(XtNameToWidget(menuBarWidget,
2411 "menuOptions.Old Save Style"), args, 1);
2413 if (appData.periodicUpdates) {
2414 XtSetValues(XtNameToWidget(menuBarWidget,
2415 "menuOptions.Periodic Updates"), args, 1);
2417 if (appData.ponderNextMove) {
2418 XtSetValues(XtNameToWidget(menuBarWidget,
2419 "menuOptions.Ponder Next Move"), args, 1);
2421 if (appData.popupExitMessage) {
2422 XtSetValues(XtNameToWidget(menuBarWidget,
2423 "menuOptions.Popup Exit Message"), args, 1);
2425 if (appData.popupMoveErrors) {
2426 XtSetValues(XtNameToWidget(menuBarWidget,
2427 "menuOptions.Popup Move Errors"), args, 1);
2429 if (appData.premove) {
2430 XtSetValues(XtNameToWidget(menuBarWidget,
2431 "menuOptions.Premove"), args, 1);
2433 if (appData.quietPlay) {
2434 XtSetValues(XtNameToWidget(menuBarWidget,
2435 "menuOptions.Quiet Play"), args, 1);
2437 if (appData.showCoords) {
2438 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2441 if (appData.showThinking) {
2442 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2445 if (appData.testLegality) {
2446 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2453 ReadBitmap(&wIconPixmap, "icon_white.bm",
2454 icon_white_bits, icon_white_width, icon_white_height);
2455 ReadBitmap(&bIconPixmap, "icon_black.bm",
2456 icon_black_bits, icon_black_width, icon_black_height);
2457 iconPixmap = wIconPixmap;
2459 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2460 XtSetValues(shellWidget, args, i);
2463 * Create a cursor for the board widget.
2465 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2466 XChangeWindowAttributes(xDisplay, xBoardWindow,
2467 CWCursor, &window_attributes);
2470 * Inhibit shell resizing.
2472 shellArgs[0].value = (XtArgVal) &w;
2473 shellArgs[1].value = (XtArgVal) &h;
2474 XtGetValues(shellWidget, shellArgs, 2);
2475 shellArgs[4].value = shellArgs[2].value = w;
2476 shellArgs[5].value = shellArgs[3].value = h;
2477 XtSetValues(shellWidget, &shellArgs[2], 4);
2479 CatchDeleteWindow(shellWidget, "QuitProc");
2484 if (appData.bitmapDirectory[0] != NULLCHAR) {
2491 /* Create regular pieces */
2492 if (!useImages) CreatePieces();
2497 if (appData.animate || appData.animateDragging)
2500 XtAugmentTranslations(formWidget,
2501 XtParseTranslationTable(globalTranslations));
2502 XtAugmentTranslations(boardWidget,
2503 XtParseTranslationTable(boardTranslations));
2504 XtAugmentTranslations(whiteTimerWidget,
2505 XtParseTranslationTable(whiteTranslations));
2506 XtAugmentTranslations(blackTimerWidget,
2507 XtParseTranslationTable(blackTranslations));
2509 /* Why is the following needed on some versions of X instead
2510 * of a translation? */
2511 XtAddEventHandler(boardWidget, ExposureMask, False,
2512 (XtEventHandler) EventProc, NULL);
2517 if (errorExitStatus == -1) {
2518 if (appData.icsActive) {
2519 /* We now wait until we see "login:" from the ICS before
2520 sending the logon script (problems with timestamp otherwise) */
2521 /*ICSInitScript();*/
2522 if (appData.icsInputBox) ICSInputBoxPopUp();
2525 signal(SIGINT, IntSigHandler);
2526 signal(SIGTERM, IntSigHandler);
2527 if (*appData.cmailGameName != NULLCHAR) {
2528 signal(SIGUSR1, CmailSigHandler);
2532 XtAppMainLoop(appContext);
2539 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2540 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2542 unlink(gameCopyFilename);
2543 unlink(gamePasteFilename);
2554 CmailSigHandler(sig)
2560 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2562 /* Activate call-back function CmailSigHandlerCallBack() */
2563 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2565 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2569 CmailSigHandlerCallBack(isr, closure, message, count, error)
2577 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2579 /**** end signal code ****/
2589 f = fopen(appData.icsLogon, "r");
2595 strcat(buf, appData.icsLogon);
2596 f = fopen(buf, "r");
2600 ProcessICSInitScript(f);
2607 EditCommentPopDown();
2618 SetMenuEnables(enab)
2622 if (!menuBarWidget) return;
2623 while (enab->name != NULL) {
2624 w = XtNameToWidget(menuBarWidget, enab->name);
2626 DisplayError(enab->name, 0);
2628 XtSetSensitive(w, enab->value);
2634 Enables icsEnables[] = {
2635 { "menuFile.Mail Move", False },
2636 { "menuFile.Reload CMail Message", False },
2637 { "menuMode.Machine Black", False },
2638 { "menuMode.Machine White", False },
2639 { "menuMode.Analysis Mode", False },
2640 { "menuMode.Analyze File", False },
2641 { "menuMode.Two Machines", False },
2643 { "menuHelp.Hint", False },
2644 { "menuHelp.Book", False },
2645 { "menuStep.Move Now", False },
2646 { "menuOptions.Periodic Updates", False },
2647 { "menuOptions.Show Thinking", False },
2648 { "menuOptions.Ponder Next Move", False },
2653 Enables ncpEnables[] = {
2654 { "menuFile.Mail Move", False },
2655 { "menuFile.Reload CMail Message", False },
2656 { "menuMode.Machine White", False },
2657 { "menuMode.Machine Black", False },
2658 { "menuMode.Analysis Mode", False },
2659 { "menuMode.Analyze File", False },
2660 { "menuMode.Two Machines", False },
2661 { "menuMode.ICS Client", False },
2662 { "menuMode.ICS Input Box", False },
2663 { "Action", False },
2664 { "menuStep.Revert", False },
2665 { "menuStep.Move Now", False },
2666 { "menuStep.Retract Move", False },
2667 { "menuOptions.Auto Comment", False },
2668 { "menuOptions.Auto Flag", False },
2669 { "menuOptions.Auto Flip View", False },
2670 { "menuOptions.Auto Observe", False },
2671 { "menuOptions.Auto Raise Board", False },
2672 { "menuOptions.Get Move List", False },
2673 { "menuOptions.ICS Alarm", False },
2674 { "menuOptions.Move Sound", False },
2675 { "menuOptions.Quiet Play", False },
2676 { "menuOptions.Show Thinking", False },
2677 { "menuOptions.Periodic Updates", False },
2678 { "menuOptions.Ponder Next Move", False },
2679 { "menuHelp.Hint", False },
2680 { "menuHelp.Book", False },
2684 Enables gnuEnables[] = {
2685 { "menuMode.ICS Client", False },
2686 { "menuMode.ICS Input Box", False },
2687 { "menuAction.Accept", False },
2688 { "menuAction.Decline", False },
2689 { "menuAction.Rematch", False },
2690 { "menuAction.Adjourn", False },
2691 { "menuAction.Stop Examining", False },
2692 { "menuAction.Stop Observing", False },
2693 { "menuStep.Revert", False },
2694 { "menuOptions.Auto Comment", False },
2695 { "menuOptions.Auto Observe", False },
2696 { "menuOptions.Auto Raise Board", False },
2697 { "menuOptions.Get Move List", False },
2698 { "menuOptions.Premove", False },
2699 { "menuOptions.Quiet Play", False },
2701 /* The next two options rely on SetCmailMode being called *after* */
2702 /* SetGNUMode so that when GNU is being used to give hints these */
2703 /* menu options are still available */
2705 { "menuFile.Mail Move", False },
2706 { "menuFile.Reload CMail Message", False },
2710 Enables cmailEnables[] = {
2712 { "menuAction.Call Flag", False },
2713 { "menuAction.Draw", True },
2714 { "menuAction.Adjourn", False },
2715 { "menuAction.Abort", False },
2716 { "menuAction.Stop Observing", False },
2717 { "menuAction.Stop Examining", False },
2718 { "menuFile.Mail Move", True },
2719 { "menuFile.Reload CMail Message", True },
2723 Enables trainingOnEnables[] = {
2724 { "menuMode.Edit Comment", False },
2725 { "menuMode.Pause", False },
2726 { "menuStep.Forward", False },
2727 { "menuStep.Backward", False },
2728 { "menuStep.Forward to End", False },
2729 { "menuStep.Back to Start", False },
2730 { "menuStep.Move Now", False },
2731 { "menuStep.Truncate Game", False },
2735 Enables trainingOffEnables[] = {
2736 { "menuMode.Edit Comment", True },
2737 { "menuMode.Pause", True },
2738 { "menuStep.Forward", True },
2739 { "menuStep.Backward", True },
2740 { "menuStep.Forward to End", True },
2741 { "menuStep.Back to Start", True },
2742 { "menuStep.Move Now", True },
2743 { "menuStep.Truncate Game", True },
2747 Enables machineThinkingEnables[] = {
2748 { "menuFile.Load Game", False },
2749 { "menuFile.Load Next Game", False },
2750 { "menuFile.Load Previous Game", False },
2751 { "menuFile.Reload Same Game", False },
2752 { "menuFile.Paste Game", False },
2753 { "menuFile.Load Position", False },
2754 { "menuFile.Load Next Position", False },
2755 { "menuFile.Load Previous Position", False },
2756 { "menuFile.Reload Same Position", False },
2757 { "menuFile.Paste Position", False },
2758 { "menuMode.Machine White", False },
2759 { "menuMode.Machine Black", False },
2760 { "menuMode.Two Machines", False },
2761 { "menuStep.Retract Move", False },
2765 Enables userThinkingEnables[] = {
2766 { "menuFile.Load Game", True },
2767 { "menuFile.Load Next Game", True },
2768 { "menuFile.Load Previous Game", True },
2769 { "menuFile.Reload Same Game", True },
2770 { "menuFile.Paste Game", True },
2771 { "menuFile.Load Position", True },
2772 { "menuFile.Load Next Position", True },
2773 { "menuFile.Load Previous Position", True },
2774 { "menuFile.Reload Same Position", True },
2775 { "menuFile.Paste Position", True },
2776 { "menuMode.Machine White", True },
2777 { "menuMode.Machine Black", True },
2778 { "menuMode.Two Machines", True },
2779 { "menuStep.Retract Move", True },
2785 SetMenuEnables(icsEnables);
2791 SetMenuEnables(ncpEnables);
2797 SetMenuEnables(gnuEnables);
2803 SetMenuEnables(cmailEnables);
2809 SetMenuEnables(trainingOnEnables);
2810 if (appData.showButtonBar) {
2811 XtSetSensitive(buttonBarWidget, False);
2817 SetTrainingModeOff()
2819 SetMenuEnables(trainingOffEnables);
2820 if (appData.showButtonBar) {
2821 XtSetSensitive(buttonBarWidget, True);
2826 SetUserThinkingEnables()
2828 if (appData.noChessProgram) return;
2829 SetMenuEnables(userThinkingEnables);
2833 SetMachineThinkingEnables()
2835 if (appData.noChessProgram) return;
2836 SetMenuEnables(machineThinkingEnables);
2838 case MachinePlaysBlack:
2839 case MachinePlaysWhite:
2840 case TwoMachinesPlay:
2841 XtSetSensitive(XtNameToWidget(menuBarWidget,
2842 ModeToWidgetName(gameMode)), True);
2849 #define Abs(n) ((n)<0 ? -(n) : (n))
2852 * Find a font that matches "pattern" that is as close as
2853 * possible to the targetPxlSize. Prefer fonts that are k
2854 * pixels smaller to fonts that are k pixels larger. The
2855 * pattern must be in the X Consortium standard format,
2856 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2857 * The return value should be freed with XtFree when no
2860 char *FindFont(pattern, targetPxlSize)
2864 char **fonts, *p, *best, *scalable, *scalableTail;
2865 int i, j, nfonts, minerr, err, pxlSize;
2867 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2869 fprintf(stderr, "%s: no fonts match pattern %s\n",
2870 programName, pattern);
2876 for (i=0; i<nfonts; i++) {
2879 if (*p != '-') continue;
2881 if (*p == NULLCHAR) break;
2882 if (*p++ == '-') j++;
2884 if (j < 7) continue;
2887 scalable = fonts[i];
2890 err = pxlSize - targetPxlSize;
2891 if (Abs(err) < Abs(minerr) ||
2892 (minerr > 0 && err < 0 && -err == minerr)) {
2898 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2899 /* If the error is too big and there is a scalable font,
2900 use the scalable font. */
2901 int headlen = scalableTail - scalable;
2902 p = (char *) XtMalloc(strlen(scalable) + 10);
2903 while (isdigit(*scalableTail)) scalableTail++;
2904 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2906 p = (char *) XtMalloc(strlen(best) + 1);
2909 if (appData.debugMode) {
2910 fprintf(debugFP, "resolved %s at pixel size %d\n to %s\n",
2911 pattern, targetPxlSize, p);
2913 XFreeFontNames(fonts);
2919 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2920 | GCBackground | GCFunction | GCPlaneMask;
2921 XGCValues gc_values;
2924 gc_values.plane_mask = AllPlanes;
2925 gc_values.line_width = lineGap;
2926 gc_values.line_style = LineSolid;
2927 gc_values.function = GXcopy;
2929 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2930 gc_values.background = XBlackPixel(xDisplay, xScreen);
2931 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2933 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2934 gc_values.background = XWhitePixel(xDisplay, xScreen);
2935 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2936 XSetFont(xDisplay, coordGC, coordFontID);
2938 if (appData.monoMode) {
2939 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2940 gc_values.background = XWhitePixel(xDisplay, xScreen);
2941 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2943 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2944 gc_values.background = XBlackPixel(xDisplay, xScreen);
2945 lightSquareGC = wbPieceGC
2946 = XtGetGC(shellWidget, value_mask, &gc_values);
2948 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2949 gc_values.background = XWhitePixel(xDisplay, xScreen);
2950 darkSquareGC = bwPieceGC
2951 = XtGetGC(shellWidget, value_mask, &gc_values);
2953 if (DefaultDepth(xDisplay, xScreen) == 1) {
2954 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
2955 gc_values.function = GXcopyInverted;
2956 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
2957 gc_values.function = GXcopy;
2958 if (XBlackPixel(xDisplay, xScreen) == 1) {
2959 bwPieceGC = darkSquareGC;
2960 wbPieceGC = copyInvertedGC;
2962 bwPieceGC = copyInvertedGC;
2963 wbPieceGC = lightSquareGC;
2967 gc_values.foreground = highlightSquareColor;
2968 gc_values.background = highlightSquareColor;
2969 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2971 gc_values.foreground = premoveHighlightColor;
2972 gc_values.background = premoveHighlightColor;
2973 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2975 gc_values.foreground = lightSquareColor;
2976 gc_values.background = darkSquareColor;
2977 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2979 gc_values.foreground = darkSquareColor;
2980 gc_values.background = lightSquareColor;
2981 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2983 gc_values.foreground = jailSquareColor;
2984 gc_values.background = jailSquareColor;
2985 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
2987 gc_values.foreground = whitePieceColor;
2988 gc_values.background = darkSquareColor;
2989 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
2991 gc_values.foreground = whitePieceColor;
2992 gc_values.background = lightSquareColor;
2993 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
2995 gc_values.foreground = whitePieceColor;
2996 gc_values.background = jailSquareColor;
2997 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
2999 gc_values.foreground = blackPieceColor;
3000 gc_values.background = darkSquareColor;
3001 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3003 gc_values.foreground = blackPieceColor;
3004 gc_values.background = lightSquareColor;
3005 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3007 gc_values.foreground = blackPieceColor;
3008 gc_values.background = jailSquareColor;
3009 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3013 void loadXIM(xim, xmask, filename, dest, mask)
3026 fp = fopen(filename, "rb");
3028 fprintf(stderr, "%s: error loading XIM!\n", programName);
3035 for (y=0; y<h; ++y) {
3036 for (x=0; x<h; ++x) {
3041 XPutPixel(xim, x, y, blackPieceColor);
3043 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3046 XPutPixel(xim, x, y, darkSquareColor);
3048 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3051 XPutPixel(xim, x, y, whitePieceColor);
3053 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3056 XPutPixel(xim, x, y, lightSquareColor);
3058 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3064 /* create Pixmap of piece */
3065 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3067 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3070 /* create Pixmap of clipmask
3071 Note: We assume the white/black pieces have the same
3072 outline, so we make only 6 masks. This is okay
3073 since the XPM clipmask routines do the same. */
3075 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3077 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3080 /* now create the 1-bit version */
3081 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3084 values.foreground = 1;
3085 values.background = 0;
3087 /* Don't use XtGetGC, not read only */
3088 maskGC = XCreateGC(xDisplay, *mask,
3089 GCForeground | GCBackground, &values);
3090 XCopyPlane(xDisplay, temp, *mask, maskGC,
3091 0, 0, squareSize, squareSize, 0, 0, 1);
3092 XFreePixmap(xDisplay, temp);
3096 void CreateXIMPieces()
3101 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3106 /* The XSynchronize calls were copied from CreatePieces.
3107 Not sure if needed, but can't hurt */
3108 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3111 /* temp needed by loadXIM() */
3112 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3113 0, 0, ss, ss, AllPlanes, XYPixmap);
3115 if (strlen(appData.pixmapDirectory) == 0) {
3119 if (appData.monoMode) {
3120 DisplayFatalError("XIM pieces cannot be used in monochrome mode",
3124 fprintf(stderr, "\nLoading XIMs...\n");
3126 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3127 fprintf(stderr, "%d", piece+1);
3128 for (kind=0; kind<4; kind++) {
3129 fprintf(stderr, ".");
3130 sprintf(buf, "%s/%c%s%u.xim",
3131 ExpandPathName(appData.pixmapDirectory),
3132 ToLower(PieceToChar((ChessSquare)piece)),
3134 ximPieceBitmap[kind][piece] =
3135 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3136 0, 0, ss, ss, AllPlanes, XYPixmap);
3137 if (appData.debugMode)
3138 fprintf(stderr, "(File:%s:) ", buf);
3139 loadXIM(ximPieceBitmap[kind][piece],
3141 &(xpmPieceBitmap[kind][piece]),
3142 &(ximMaskPm[piece%6]));
3144 fprintf(stderr," ");
3146 /* Load light and dark squares */
3147 /* If the LSQ and DSQ pieces don't exist, we will
3148 draw them with solid squares. */
3149 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3150 if (access(buf, 0) != 0) {
3154 fprintf(stderr, "light square ");
3156 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3157 0, 0, ss, ss, AllPlanes, XYPixmap);
3158 if (appData.debugMode)
3159 fprintf(stderr, "(File:%s:) ", buf);
3161 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3162 fprintf(stderr, "dark square ");
3163 sprintf(buf, "%s/dsq%u.xim",
3164 ExpandPathName(appData.pixmapDirectory), ss);
3165 if (appData.debugMode)
3166 fprintf(stderr, "(File:%s:) ", buf);
3168 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3169 0, 0, ss, ss, AllPlanes, XYPixmap);
3170 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3171 xpmJailSquare = xpmLightSquare;
3173 fprintf(stderr, "Done.\n");
3175 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3179 void CreateXPMPieces()
3183 u_int ss = squareSize;
3185 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3186 XpmColorSymbol symbols[4];
3189 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3190 if (appData.debugMode) {
3191 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3192 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3196 /* The XSynchronize calls were copied from CreatePieces.
3197 Not sure if needed, but can't hurt */
3198 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3200 /* Setup translations so piece colors match square colors */
3201 symbols[0].name = "light_piece";
3202 symbols[0].value = appData.whitePieceColor;
3203 symbols[1].name = "dark_piece";
3204 symbols[1].value = appData.blackPieceColor;
3205 symbols[2].name = "light_square";
3206 symbols[2].value = appData.lightSquareColor;
3207 symbols[3].name = "dark_square";
3208 symbols[3].value = appData.darkSquareColor;
3210 attr.valuemask = XpmColorSymbols;
3211 attr.colorsymbols = symbols;
3212 attr.numsymbols = 4;
3214 if (appData.monoMode) {
3215 DisplayFatalError("XPM pieces cannot be used in monochrome mode",
3219 if (strlen(appData.pixmapDirectory) == 0) {
3220 XpmPieces* pieces = builtInXpms;
3223 while (pieces->size != squareSize && pieces->size) pieces++;
3224 if (!pieces->size) {
3225 fprintf(stderr, "No builtin XPM pieces of size %d\n", squareSize);
3228 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3229 for (kind=0; kind<4; kind++) {
3231 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3232 pieces->xpm[piece][kind],
3233 &(xpmPieceBitmap[kind][piece]),
3234 NULL, &attr)) != 0) {
3235 fprintf(stderr, "Error %d loading XPM image \"%s\"\n",
3242 xpmJailSquare = xpmLightSquare;
3246 fprintf(stderr, "\nLoading XPMs...\n");
3249 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3250 fprintf(stderr, "%d ", piece+1);
3251 for (kind=0; kind<4; kind++) {
3252 sprintf(buf, "%s/%c%s%u.xpm",
3253 ExpandPathName(appData.pixmapDirectory),
3254 ToLower(PieceToChar((ChessSquare)piece)),
3256 if (appData.debugMode) {
3257 fprintf(stderr, "(File:%s:) ", buf);
3259 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3260 &(xpmPieceBitmap[kind][piece]),
3261 NULL, &attr)) != 0) {
3262 fprintf(stderr, "Error %d loading XPM file \"%s\"\n",
3268 /* Load light and dark squares */
3269 /* If the LSQ and DSQ pieces don't exist, we will
3270 draw them with solid squares. */
3271 fprintf(stderr, "light square ");
3272 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3273 if (access(buf, 0) != 0) {
3277 if (appData.debugMode)
3278 fprintf(stderr, "(File:%s:) ", buf);
3280 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3281 &xpmLightSquare, NULL, &attr)) != 0) {
3282 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
3285 fprintf(stderr, "dark square ");
3286 sprintf(buf, "%s/dsq%u.xpm",
3287 ExpandPathName(appData.pixmapDirectory), ss);
3288 if (appData.debugMode) {
3289 fprintf(stderr, "(File:%s:) ", buf);
3291 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3292 &xpmDarkSquare, NULL, &attr)) != 0) {
3293 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
3297 xpmJailSquare = xpmLightSquare;
3298 fprintf(stderr, "Done.\n");
3300 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3303 #endif /* HAVE_LIBXPM */
3306 /* No built-in bitmaps */
3311 u_int ss = squareSize;
3313 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3316 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3317 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3318 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3319 ss, kind == SOLID ? 's' : 'o');
3320 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3324 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3328 /* With built-in bitmaps */
3331 BuiltInBits* bib = builtInBits;
3334 u_int ss = squareSize;
3336 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3339 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3341 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3342 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3343 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3344 ss, kind == SOLID ? 's' : 'o');
3345 ReadBitmap(&pieceBitmap[kind][piece], buf,
3346 bib->bits[kind][piece], ss, ss);
3350 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3355 void ReadBitmap(pm, name, bits, wreq, hreq)
3358 unsigned char bits[];
3364 char msg[MSG_SIZ], fullname[MSG_SIZ];
3366 if (*appData.bitmapDirectory != NULLCHAR) {
3367 strcpy(fullname, appData.bitmapDirectory);
3368 strcat(fullname, "/");
3369 strcat(fullname, name);
3370 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3371 &w, &h, pm, &x_hot, &y_hot);
3372 if (errcode != BitmapSuccess) {
3374 case BitmapOpenFailed:
3375 sprintf(msg, "Can't open bitmap file %s", fullname);
3377 case BitmapFileInvalid:
3378 sprintf(msg, "Invalid bitmap in file %s", fullname);
3380 case BitmapNoMemory:
3381 sprintf(msg, "Ran out of memory reading bitmap file %s",
3385 sprintf(msg, "Unknown XReadBitmapFile error %d on file %s",
3389 fprintf(stderr, "%s: %s...using built-in\n",
3391 } else if (w != wreq || h != hreq) {
3393 "%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n",
3394 programName, fullname, w, h, wreq, hreq);
3400 fprintf(stderr, "%s: No built-in bitmap for %s; giving up\n",
3404 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3413 if (lineGap == 0) return;
3414 for (i = 0; i < BOARD_SIZE + 1; i++) {
3415 gridSegments[i].x1 = 0;
3416 gridSegments[i].x2 =
3417 lineGap + BOARD_SIZE * (squareSize + lineGap);
3418 gridSegments[i].y1 = gridSegments[i].y2
3419 = lineGap / 2 + (i * (squareSize + lineGap));
3421 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3422 gridSegments[i + BOARD_SIZE + 1].y2 =
3423 BOARD_SIZE * (squareSize + lineGap);
3424 gridSegments[i + BOARD_SIZE + 1].x1 =
3425 gridSegments[i + BOARD_SIZE + 1].x2
3426 = lineGap / 2 + (i * (squareSize + lineGap));
3430 static void MenuBarSelect(w, addr, index)
3435 XtActionProc proc = (XtActionProc) addr;
3437 (proc)(NULL, NULL, NULL, NULL);
3440 void CreateMenuBarPopup(parent, name, mb)
3450 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3453 XtSetArg(args[j], XtNleftMargin, 20); j++;
3454 XtSetArg(args[j], XtNrightMargin, 20); j++;
3456 while (mi->string != NULL) {
3457 if (strcmp(mi->string, "----") == 0) {
3458 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3461 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3463 XtAddCallback(entry, XtNcallback,
3464 (XtCallbackProc) MenuBarSelect,
3465 (caddr_t) mi->proc);
3471 Widget CreateMenuBar(mb)
3475 Widget anchor, menuBar;
3477 char menuName[MSG_SIZ];
3480 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3481 XtSetArg(args[j], XtNvSpace, 0); j++;
3482 XtSetArg(args[j], XtNborderWidth, 0); j++;
3483 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3484 formWidget, args, j);
3486 while (mb->name != NULL) {
3487 strcpy(menuName, "menu");
3488 strcat(menuName, mb->name);
3490 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3493 shortName[0] = mb->name[0];
3494 shortName[1] = NULLCHAR;
3495 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3497 XtSetArg(args[j], XtNborderWidth, 0); j++;
3498 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3500 CreateMenuBarPopup(menuBar, menuName, mb);
3506 Widget CreateButtonBar(mi)
3510 Widget button, buttonBar;
3514 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3516 XtSetArg(args[j], XtNhSpace, 0); j++;
3518 XtSetArg(args[j], XtNborderWidth, 0); j++;
3519 XtSetArg(args[j], XtNvSpace, 0); j++;
3520 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3521 formWidget, args, j);
3523 while (mi->string != NULL) {
3526 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3527 XtSetArg(args[j], XtNborderWidth, 0); j++;
3529 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3530 buttonBar, args, j);
3531 XtAddCallback(button, XtNcallback,
3532 (XtCallbackProc) MenuBarSelect,
3533 (caddr_t) mi->proc);
3540 CreatePieceMenu(name, color)
3547 ChessSquare selection;
3549 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3550 boardWidget, args, 0);
3552 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3553 String item = pieceMenuStrings[color][i];
3555 if (strcmp(item, "----") == 0) {
3556 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3559 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3561 selection = pieceMenuTranslation[color][i];
3562 XtAddCallback(entry, XtNcallback,
3563 (XtCallbackProc) PieceMenuSelect,
3564 (caddr_t) selection);
3565 if (selection == WhitePawn || selection == BlackPawn) {
3566 XtSetArg(args[0], XtNpopupOnEntry, entry);
3567 XtSetValues(menu, args, 1);
3580 ChessSquare selection;
3582 whitePieceMenu = CreatePieceMenu("menuW", 0);
3583 blackPieceMenu = CreatePieceMenu("menuB", 1);
3585 XtRegisterGrabAction(PieceMenuPopup, True,
3586 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3587 GrabModeAsync, GrabModeAsync);
3589 XtSetArg(args[0], XtNlabel, "Drop");
3590 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3591 boardWidget, args, 1);
3592 for (i = 0; i < DROP_MENU_SIZE; i++) {
3593 String item = dropMenuStrings[i];
3595 if (strcmp(item, "----") == 0) {
3596 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3599 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3601 selection = dropMenuTranslation[i];
3602 XtAddCallback(entry, XtNcallback,
3603 (XtCallbackProc) DropMenuSelect,
3604 (caddr_t) selection);
3609 void SetupDropMenu()
3617 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3618 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3619 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3620 dmEnables[i].piece);
3621 XtSetSensitive(entry, p != NULL || !appData.testLegality
3622 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3623 && !appData.icsActive));
3625 while (p && *p++ == dmEnables[i].piece) count++;
3626 sprintf(label, "%s %d", dmEnables[i].widget, count);
3628 XtSetArg(args[j], XtNlabel, label); j++;
3629 XtSetValues(entry, args, j);
3633 void PieceMenuPopup(w, event, params, num_params)
3637 Cardinal *num_params;
3640 if (event->type != ButtonPress) return;
3641 if (errorUp) ErrorPopDown();
3645 whichMenu = params[0];
3647 case IcsPlayingWhite:
3648 case IcsPlayingBlack:
3650 case MachinePlaysWhite:
3651 case MachinePlaysBlack:
3652 if (appData.testLegality &&
3653 gameInfo.variant != VariantBughouse &&
3654 gameInfo.variant != VariantCrazyhouse) return;
3656 whichMenu = "menuD";
3662 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3663 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3664 pmFromX = pmFromY = -1;
3668 pmFromX = BOARD_SIZE - 1 - pmFromX;
3670 pmFromY = BOARD_SIZE - 1 - pmFromY;
3672 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3675 static void PieceMenuSelect(w, piece, junk)
3680 if (pmFromX < 0 || pmFromY < 0) return;
3681 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3684 static void DropMenuSelect(w, piece, junk)
3689 if (pmFromX < 0 || pmFromY < 0) return;
3690 DropMenuEvent(piece, pmFromX, pmFromY);
3693 void WhiteClock(w, event, prms, nprms)
3699 if (gameMode == EditPosition || gameMode == IcsExamining) {
3700 SetWhiteToPlayEvent();
3701 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3706 void BlackClock(w, event, prms, nprms)
3712 if (gameMode == EditPosition || gameMode == IcsExamining) {
3713 SetBlackToPlayEvent();
3714 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3721 * If the user selects on a border boundary, return -1; if off the board,
3722 * return -2. Otherwise map the event coordinate to the square.
3724 int EventToSquare(x, limit)
3732 if ((x % (squareSize + lineGap)) >= squareSize)
3734 x /= (squareSize + lineGap);
3740 static void do_flash_delay(msec)
3746 static void drawHighlight(file, rank, gc)
3752 if (lineGap == 0 || appData.blindfold) return;
3755 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3756 (squareSize + lineGap);
3757 y = lineGap/2 + rank * (squareSize + lineGap);
3759 x = lineGap/2 + file * (squareSize + lineGap);
3760 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3761 (squareSize + lineGap);
3764 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3765 squareSize+lineGap, squareSize+lineGap);
3768 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3769 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3772 SetHighlights(fromX, fromY, toX, toY)
3773 int fromX, fromY, toX, toY;
3775 if (hi1X != fromX || hi1Y != fromY) {
3776 if (hi1X >= 0 && hi1Y >= 0) {
3777 drawHighlight(hi1X, hi1Y, lineGC);
3779 if (fromX >= 0 && fromY >= 0) {
3780 drawHighlight(fromX, fromY, highlineGC);
3783 if (hi2X != toX || hi2Y != toY) {
3784 if (hi2X >= 0 && hi2Y >= 0) {
3785 drawHighlight(hi2X, hi2Y, lineGC);
3787 if (toX >= 0 && toY >= 0) {
3788 drawHighlight(toX, toY, highlineGC);
3800 SetHighlights(-1, -1, -1, -1);
3805 SetPremoveHighlights(fromX, fromY, toX, toY)
3806 int fromX, fromY, toX, toY;
3808 if (pm1X != fromX || pm1Y != fromY) {
3809 if (pm1X >= 0 && pm1Y >= 0) {
3810 drawHighlight(pm1X, pm1Y, lineGC);
3812 if (fromX >= 0 && fromY >= 0) {
3813 drawHighlight(fromX, fromY, prelineGC);
3816 if (pm2X != toX || pm2Y != toY) {
3817 if (pm2X >= 0 && pm2Y >= 0) {
3818 drawHighlight(pm2X, pm2Y, lineGC);
3820 if (toX >= 0 && toY >= 0) {
3821 drawHighlight(toX, toY, prelineGC);
3831 ClearPremoveHighlights()
3833 SetPremoveHighlights(-1, -1, -1, -1);
3836 static void BlankSquare(x, y, color, piece, dest)
3841 if (useImages && useImageSqs) {
3845 pm = xpmLightSquare;
3850 case 2: /* neutral */
3855 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3856 squareSize, squareSize, x, y);
3866 case 2: /* neutral */
3871 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3876 I split out the routines to draw a piece so that I could
3877 make a generic flash routine.
3879 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3881 int square_color, x, y;
3884 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3885 switch (square_color) {
3887 case 2: /* neutral */
3889 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3890 ? *pieceToOutline(piece)
3891 : *pieceToSolid(piece),
3892 dest, bwPieceGC, 0, 0,
3893 squareSize, squareSize, x, y);
3896 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3897 ? *pieceToSolid(piece)
3898 : *pieceToOutline(piece),
3899 dest, wbPieceGC, 0, 0,
3900 squareSize, squareSize, x, y);
3905 static void monoDrawPiece(piece, square_color, x, y, dest)
3907 int square_color, x, y;
3910 switch (square_color) {
3912 case 2: /* neutral */
3914 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3915 ? *pieceToOutline(piece)
3916 : *pieceToSolid(piece),
3917 dest, bwPieceGC, 0, 0,
3918 squareSize, squareSize, x, y, 1);
3921 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3922 ? *pieceToSolid(piece)
3923 : *pieceToOutline(piece),
3924 dest, wbPieceGC, 0, 0,
3925 squareSize, squareSize, x, y, 1);
3930 static void colorDrawPiece(piece, square_color, x, y, dest)
3932 int square_color, x, y;
3935 switch (square_color) {
3937 XCopyPlane(xDisplay, *pieceToSolid(piece),
3938 dest, (int) piece < (int) BlackPawn
3939 ? wlPieceGC : blPieceGC, 0, 0,
3940 squareSize, squareSize, x, y, 1);
3943 XCopyPlane(xDisplay, *pieceToSolid(piece),
3944 dest, (int) piece < (int) BlackPawn
3945 ? wdPieceGC : bdPieceGC, 0, 0,
3946 squareSize, squareSize, x, y, 1);
3948 case 2: /* neutral */
3950 XCopyPlane(xDisplay, *pieceToSolid(piece),
3951 dest, (int) piece < (int) BlackPawn
3952 ? wjPieceGC : bjPieceGC, 0, 0,
3953 squareSize, squareSize, x, y, 1);
3958 static void colorDrawPieceImage(piece, square_color, x, y, dest)
3960 int square_color, x, y;
3965 switch (square_color) {
3967 case 2: /* neutral */
3969 if ((int)piece < (int) BlackPawn) {
3977 if ((int)piece < (int) BlackPawn) {
3985 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
3986 dest, wlPieceGC, 0, 0,
3987 squareSize, squareSize, x, y);
3990 typedef void (*DrawFunc)();
3992 DrawFunc ChooseDrawFunc()
3994 if (appData.monoMode) {
3995 if (DefaultDepth(xDisplay, xScreen) == 1) {
3996 return monoDrawPiece_1bit;
3998 return monoDrawPiece;
4002 return colorDrawPieceImage;
4004 return colorDrawPiece;
4008 void DrawSquare(row, column, piece, do_flash)
4009 int row, column, do_flash;
4012 int square_color, x, y, direction, font_ascent, font_descent;
4015 XCharStruct overall;
4019 /* Calculate delay in milliseconds (2-delays per complete flash) */
4020 flash_delay = 500 / appData.flashRate;
4023 x = lineGap + ((BOARD_SIZE-1)-column) *
4024 (squareSize + lineGap);
4025 y = lineGap + row * (squareSize + lineGap);
4027 x = lineGap + column * (squareSize + lineGap);
4028 y = lineGap + ((BOARD_SIZE-1)-row) *
4029 (squareSize + lineGap);
4032 square_color = ((column + row) % 2) == 1;
4034 if (piece == EmptySquare || appData.blindfold) {
4035 BlankSquare(x, y, square_color, piece, xBoardWindow);
4037 drawfunc = ChooseDrawFunc();
4038 if (do_flash && appData.flashCount > 0) {
4039 for (i=0; i<appData.flashCount; ++i) {
4041 drawfunc(piece, square_color, x, y, xBoardWindow);
4042 XSync(xDisplay, False);
4043 do_flash_delay(flash_delay);
4045 BlankSquare(x, y, square_color, piece, xBoardWindow);
4046 XSync(xDisplay, False);
4047 do_flash_delay(flash_delay);
4050 drawfunc(piece, square_color, x, y, xBoardWindow);
4053 string[1] = NULLCHAR;
4054 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4055 string[0] = 'a' + column;
4056 XTextExtents(coordFontStruct, string, 1, &direction,
4057 &font_ascent, &font_descent, &overall);
4058 if (appData.monoMode) {
4059 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4060 x + squareSize - overall.width - 2,
4061 y + squareSize - font_descent - 1, string, 1);
4063 XDrawString(xDisplay, xBoardWindow, coordGC,
4064 x + squareSize - overall.width - 2,
4065 y + squareSize - font_descent - 1, string, 1);
4068 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4069 string[0] = '1' + row;
4070 XTextExtents(coordFontStruct, string, 1, &direction,
4071 &font_ascent, &font_descent, &overall);
4072 if (appData.monoMode) {
4073 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4074 x + 2, y + font_ascent + 1, string, 1);
4076 XDrawString(xDisplay, xBoardWindow, coordGC,
4077 x + 2, y + font_ascent + 1, string, 1);
4083 /* Why is this needed on some versions of X? */
4084 void EventProc(widget, unused, event)
4089 if (!XtIsRealized(widget))
4092 switch (event->type) {
4094 if (event->xexpose.count > 0) return; /* no clipping is done */
4095 XDrawPosition(widget, True, NULL);
4103 void DrawPosition(fullRedraw, board)
4104 /*Boolean*/int fullRedraw;
4107 XDrawPosition(boardWidget, fullRedraw, board);
4110 /* Returns 1 if there are "too many" differences between b1 and b2
4111 (i.e. more than 1 move was made) */
4112 static int too_many_diffs(b1, b2)
4118 for (i=0; i<BOARD_SIZE; ++i) {
4119 for (j=0; j<BOARD_SIZE; ++j) {
4120 if (b1[i][j] != b2[i][j]) {
4121 if (++c > 4) /* Castling causes 4 diffs */
4130 /* Matrix describing castling maneuvers */
4131 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4132 static int castling_matrix[4][5] = {
4133 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4134 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4135 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4136 { 7, 7, 4, 5, 6 } /* 0-0, black */
4139 /* Checks whether castling occurred. If it did, *rrow and *rcol
4140 are set to the destination (row,col) of the rook that moved.
4142 Returns 1 if castling occurred, 0 if not.
4144 Note: Only handles a max of 1 castling move, so be sure
4145 to call too_many_diffs() first.
4147 static int check_castle_draw(newb, oldb, rrow, rcol)
4154 /* For each type of castling... */
4155 for (i=0; i<4; ++i) {
4156 r = castling_matrix[i];
4158 /* Check the 4 squares involved in the castling move */
4160 for (j=1; j<=4; ++j) {
4161 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4168 /* All 4 changed, so it must be a castling move */
4177 static int damage[BOARD_SIZE][BOARD_SIZE];
4180 * event handler for redrawing the board
4182 void XDrawPosition(w, repaint, board)
4184 /*Boolean*/int repaint;
4188 static int lastFlipView = 0;
4189 static int lastBoardValid = 0;
4190 static Board lastBoard;
4194 if (board == NULL) {
4195 if (!lastBoardValid) return;
4198 if (!lastBoardValid || lastFlipView != flipView) {
4199 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4200 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4205 * It would be simpler to clear the window with XClearWindow()
4206 * but this causes a very distracting flicker.
4209 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4211 /* If too much changes (begin observing new game, etc.), don't
4213 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4215 /* Special check for castling so we don't flash both the king
4216 and the rook (just flash the king). */
4218 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4219 /* Draw rook with NO flashing. King will be drawn flashing later */
4220 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4221 lastBoard[rrow][rcol] = board[rrow][rcol];
4225 /* First pass -- Draw (newly) empty squares and repair damage.
4226 This prevents you from having a piece show up twice while it
4227 is flashing on its new square */
4228 for (i = 0; i < BOARD_SIZE; i++)
4229 for (j = 0; j < BOARD_SIZE; j++)
4230 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4232 DrawSquare(i, j, board[i][j], 0);
4233 damage[i][j] = False;
4236 /* Second pass -- Draw piece(s) in new position and flash them */
4237 for (i = 0; i < BOARD_SIZE; i++)
4238 for (j = 0; j < BOARD_SIZE; j++)
4239 if (board[i][j] != lastBoard[i][j]) {
4240 DrawSquare(i, j, board[i][j], do_flash);
4244 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4245 gridSegments, (BOARD_SIZE + 1) * 2);
4247 for (i = 0; i < BOARD_SIZE; i++)
4248 for (j = 0; j < BOARD_SIZE; j++) {
4249 DrawSquare(i, j, board[i][j], 0);
4250 damage[i][j] = False;
4254 CopyBoard(lastBoard, board);
4256 lastFlipView = flipView;
4258 /* Draw highlights */
4259 if (pm1X >= 0 && pm1Y >= 0) {
4260 drawHighlight(pm1X, pm1Y, prelineGC);
4262 if (pm2X >= 0 && pm2Y >= 0) {
4263 drawHighlight(pm2X, pm2Y, prelineGC);
4265 if (hi1X >= 0 && hi1Y >= 0) {
4266 drawHighlight(hi1X, hi1Y, highlineGC);
4268 if (hi2X >= 0 && hi2Y >= 0) {
4269 drawHighlight(hi2X, hi2Y, highlineGC);
4272 /* If piece being dragged around board, must redraw that too */
4275 XSync(xDisplay, False);
4280 * event handler for redrawing the board
4282 void DrawPositionProc(w, event, prms, nprms)
4288 XDrawPosition(w, True, NULL);
4293 * event handler for parsing user moves
4295 void HandleUserMove(w, event, prms, nprms)
4302 Boolean saveAnimate;
4303 static int second = 0;
4305 if (w != boardWidget || errorExitStatus != -1) return;
4307 if (event->type == ButtonPress) ErrorPopDown();
4310 if (event->type == ButtonPress) {
4311 XtPopdown(promotionShell);
4312 XtDestroyWidget(promotionShell);
4313 promotionUp = False;
4321 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4322 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4323 if (!flipView && y >= 0) {
4324 y = BOARD_SIZE - 1 - y;
4326 if (flipView && x >= 0) {
4327 x = BOARD_SIZE - 1 - x;
4331 if (event->type == ButtonPress) {
4333 if (OKToStartUserMove(x, y)) {
4337 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4338 if (appData.highlightDragging) {
4339 SetHighlights(x, y, -1, -1);
4347 if (event->type == ButtonPress && gameMode != EditPosition &&
4351 /* Check if clicking again on the same color piece */
4352 fromP = boards[currentMove][fromY][fromX];
4353 toP = boards[currentMove][y][x];
4354 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4355 WhitePawn <= toP && toP <= WhiteKing) ||
4356 (BlackPawn <= fromP && fromP <= BlackKing &&
4357 BlackPawn <= toP && toP <= BlackKing)) {
4358 /* Clicked again on same color piece -- changed his mind */
4359 second = (x == fromX && y == fromY);
4360 if (appData.highlightDragging) {
4361 SetHighlights(x, y, -1, -1);
4365 if (OKToStartUserMove(x, y)) {
4368 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4374 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4375 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4376 if (appData.animateDragging) {
4377 /* Undo animation damage if any */
4378 DrawPosition(FALSE, NULL);
4381 /* Second up/down in same square; just abort move */
4386 ClearPremoveHighlights();
4388 /* First upclick in same square; start click-click mode */
4389 SetHighlights(x, y, -1, -1);
4394 /* Completed move */
4397 saveAnimate = appData.animate;
4398 if (event->type == ButtonPress) {
4399 /* Finish clickclick move */
4400 if (appData.animate || appData.highlightLastMove) {
4401 SetHighlights(fromX, fromY, toX, toY);
4406 /* Finish drag move */
4407 if (appData.highlightLastMove) {
4408 SetHighlights(fromX, fromY, toX, toY);
4412 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4413 /* Don't animate move and drag both */
4414 appData.animate = FALSE;
4416 if (IsPromotion(fromX, fromY, toX, toY)) {
4417 if (appData.alwaysPromoteToQueen) {
4418 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4419 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4420 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4423 SetHighlights(fromX, fromY, toX, toY);
4427 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4428 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4429 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4432 appData.animate = saveAnimate;
4433 if (appData.animate || appData.animateDragging) {
4434 /* Undo animation damage if needed */
4435 DrawPosition(FALSE, NULL);
4439 void AnimateUserMove (Widget w, XEvent * event,
4440 String * params, Cardinal * nParams)
4442 DragPieceMove(event->xmotion.x, event->xmotion.y);
4445 Widget CommentCreate(name, text, mutable, callback, lines)
4447 int /*Boolean*/ mutable;
4448 XtCallbackProc callback;
4452 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4457 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4458 XtGetValues(boardWidget, args, j);
4461 XtSetArg(args[j], XtNresizable, True); j++;
4464 XtCreatePopupShell(name, topLevelShellWidgetClass,
4465 shellWidget, args, j);
4468 XtCreatePopupShell(name, transientShellWidgetClass,
4469 shellWidget, args, j);
4472 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4473 layoutArgs, XtNumber(layoutArgs));
4475 XtCreateManagedWidget("form", formWidgetClass, layout,
4476 formArgs, XtNumber(formArgs));
4480 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4481 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4483 XtSetArg(args[j], XtNstring, text); j++;
4484 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4485 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4486 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4487 XtSetArg(args[j], XtNright, XtChainRight); j++;
4488 XtSetArg(args[j], XtNresizable, True); j++;
4489 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4491 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4493 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4494 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4496 XtSetArg(args[j], XtNautoFill, True); j++;
4497 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4499 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4503 XtSetArg(args[j], XtNfromVert, edit); j++;
4504 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4505 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4506 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4507 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4509 XtCreateManagedWidget("ok", commandWidgetClass, form, args, j);
4510 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4513 XtSetArg(args[j], XtNfromVert, edit); j++;
4514 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4515 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4516 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4517 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4518 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4520 XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);
4521 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4524 XtSetArg(args[j], XtNfromVert, edit); j++;
4525 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4526 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4527 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4528 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4529 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4531 XtCreateManagedWidget("clear", commandWidgetClass, form, args, j);
4532 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4535 XtSetArg(args[j], XtNfromVert, edit); j++;
4536 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4537 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4538 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4539 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4541 XtCreateManagedWidget("close", commandWidgetClass, form, args, j);
4542 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4545 XtSetArg(args[j], XtNfromVert, edit); j++;
4546 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4547 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4548 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4549 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4550 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4552 XtCreateManagedWidget("edit", commandWidgetClass, form, args, j);
4553 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4556 XtRealizeWidget(shell);
4558 if (commentX == -1) {
4561 Dimension pw_height;
4562 Dimension ew_height;
4565 XtSetArg(args[j], XtNheight, &ew_height); j++;
4566 XtGetValues(edit, args, j);
4569 XtSetArg(args[j], XtNheight, &pw_height); j++;
4570 XtGetValues(shell, args, j);
4571 commentH = pw_height + (lines - 1) * ew_height;
4572 commentW = bw_width - 16;
4574 XSync(xDisplay, False);
4576 /* This code seems to tickle an X bug if it is executed too soon
4577 after xboard starts up. The coordinates get transformed as if
4578 the main window was positioned at (0, 0).
4580 XtTranslateCoords(shellWidget,
4581 (bw_width - commentW) / 2, 0 - commentH / 2,
4582 &commentX, &commentY);
4584 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4585 RootWindowOfScreen(XtScreen(shellWidget)),
4586 (bw_width - commentW) / 2, 0 - commentH / 2,
4591 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4594 XtSetArg(args[j], XtNheight, commentH); j++;
4595 XtSetArg(args[j], XtNwidth, commentW); j++;
4596 XtSetArg(args[j], XtNx, commentX); j++;
4597 XtSetArg(args[j], XtNy, commentY); j++;
4598 XtSetValues(shell, args, j);
4599 XtSetKeyboardFocus(shell, edit);
4604 /* Used for analysis window and ICS input window */
4605 Widget MiscCreate(name, text, mutable, callback, lines)
4607 int /*Boolean*/ mutable;
4608 XtCallbackProc callback;
4612 Widget shell, layout, form, edit;
4614 Dimension bw_width, pw_height, ew_height, w, h;
4620 XtSetArg(args[j], XtNresizable, True); j++;
4623 XtCreatePopupShell(name, topLevelShellWidgetClass,
4624 shellWidget, args, j);
4627 XtCreatePopupShell(name, transientShellWidgetClass,
4628 shellWidget, args, j);
4631 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4632 layoutArgs, XtNumber(layoutArgs));
4634 XtCreateManagedWidget("form", formWidgetClass, layout,
4635 formArgs, XtNumber(formArgs));
4639 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4640 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4642 XtSetArg(args[j], XtNstring, text); j++;
4643 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4644 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4645 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4646 XtSetArg(args[j], XtNright, XtChainRight); j++;
4647 XtSetArg(args[j], XtNresizable, True); j++;
4649 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4651 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4652 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4654 XtSetArg(args[j], XtNautoFill, True); j++;
4655 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4657 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4659 XtRealizeWidget(shell);
4662 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4663 XtGetValues(boardWidget, args, j);
4666 XtSetArg(args[j], XtNheight, &ew_height); j++;
4667 XtGetValues(edit, args, j);
4670 XtSetArg(args[j], XtNheight, &pw_height); j++;
4671 XtGetValues(shell, args, j);
4672 h = pw_height + (lines - 1) * ew_height;
4675 XSync(xDisplay, False);
4677 /* This code seems to tickle an X bug if it is executed too soon
4678 after xboard starts up. The coordinates get transformed as if
4679 the main window was positioned at (0, 0).
4681 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4683 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4684 RootWindowOfScreen(XtScreen(shellWidget)),
4685 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4689 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4692 XtSetArg(args[j], XtNheight, h); j++;
4693 XtSetArg(args[j], XtNwidth, w); j++;
4694 XtSetArg(args[j], XtNx, x); j++;
4695 XtSetArg(args[j], XtNy, y); j++;
4696 XtSetValues(shell, args, j);
4702 static int savedIndex; /* gross that this is global */
4704 void EditCommentPopUp(index, title, text)
4713 if (text == NULL) text = "";
4715 if (editShell == NULL) {
4717 CommentCreate(title, text, True, EditCommentCallback, 4);
4718 XtRealizeWidget(editShell);
4719 CatchDeleteWindow(editShell, "EditCommentPopDown");
4721 edit = XtNameToWidget(editShell, "*form.text");
4723 XtSetArg(args[j], XtNstring, text); j++;
4724 XtSetValues(edit, args, j);
4726 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4727 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4728 XtSetValues(editShell, args, j);
4731 XtPopup(editShell, XtGrabNone);
4735 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4736 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4740 void EditCommentCallback(w, client_data, call_data)
4742 XtPointer client_data, call_data;
4750 XtSetArg(args[j], XtNlabel, &name); j++;
4751 XtGetValues(w, args, j);
4753 if (strcmp(name, "ok") == 0) {
4754 edit = XtNameToWidget(editShell, "*form.text");
4756 XtSetArg(args[j], XtNstring, &val); j++;
4757 XtGetValues(edit, args, j);
4758 ReplaceComment(savedIndex, val);
4759 EditCommentPopDown();
4760 } else if (strcmp(name, "cancel") == 0) {
4761 EditCommentPopDown();
4762 } else if (strcmp(name, "clear") == 0) {
4763 edit = XtNameToWidget(editShell, "*form.text");
4764 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4765 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4769 void EditCommentPopDown()
4774 if (!editUp) return;
4776 XtSetArg(args[j], XtNx, &commentX); j++;
4777 XtSetArg(args[j], XtNy, &commentY); j++;
4778 XtSetArg(args[j], XtNheight, &commentH); j++;
4779 XtSetArg(args[j], XtNwidth, &commentW); j++;
4780 XtGetValues(editShell, args, j);
4781 XtPopdown(editShell);
4784 XtSetArg(args[j], XtNleftBitmap, None); j++;
4785 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4789 void ICSInputBoxPopUp()
4794 char *title = "ICS Input";
4797 if (ICSInputShell == NULL) {
4798 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4799 tr = XtParseTranslationTable(ICSInputTranslations);
4800 edit = XtNameToWidget(ICSInputShell, "*form.text");
4801 XtOverrideTranslations(edit, tr);
4802 XtRealizeWidget(ICSInputShell);
4803 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4806 edit = XtNameToWidget(ICSInputShell, "*form.text");
4808 XtSetArg(args[j], XtNstring, ""); j++;
4809 XtSetValues(edit, args, j);
4811 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4812 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4813 XtSetValues(ICSInputShell, args, j);
4816 XtPopup(ICSInputShell, XtGrabNone);
4817 XtSetKeyboardFocus(ICSInputShell, edit);
4819 ICSInputBoxUp = True;
4821 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4822 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4826 void ICSInputSendText()
4833 edit = XtNameToWidget(ICSInputShell, "*form.text");
4835 XtSetArg(args[j], XtNstring, &val); j++;
4836 XtGetValues(edit, args, j);
4837 SendMultiLineToICS(val);
4838 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4839 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4842 void ICSInputBoxPopDown()
4847 if (!ICSInputBoxUp) return;
4849 XtPopdown(ICSInputShell);
4850 ICSInputBoxUp = False;
4852 XtSetArg(args[j], XtNleftBitmap, None); j++;
4853 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4857 void CommentPopUp(title, text)
4864 if (commentShell == NULL) {
4866 CommentCreate(title, text, False, CommentCallback, 4);
4867 XtRealizeWidget(commentShell);
4868 CatchDeleteWindow(commentShell, "CommentPopDown");
4870 edit = XtNameToWidget(commentShell, "*form.text");
4872 XtSetArg(args[j], XtNstring, text); j++;
4873 XtSetValues(edit, args, j);
4875 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4876 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4877 XtSetValues(commentShell, args, j);
4880 XtPopup(commentShell, XtGrabNone);
4881 XSync(xDisplay, False);
4886 void AnalysisPopUp(title, text)
4893 if (analysisShell == NULL) {
4894 analysisShell = MiscCreate(title, text, False, NULL, 4);
4895 XtRealizeWidget(analysisShell);
4896 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4899 edit = XtNameToWidget(analysisShell, "*form.text");
4901 XtSetArg(args[j], XtNstring, text); j++;
4902 XtSetValues(edit, args, j);
4904 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4905 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4906 XtSetValues(analysisShell, args, j);
4910 XtPopup(analysisShell, XtGrabNone);
4912 XSync(xDisplay, False);
4917 void CommentCallback(w, client_data, call_data)
4919 XtPointer client_data, call_data;
4926 XtSetArg(args[j], XtNlabel, &name); j++;
4927 XtGetValues(w, args, j);
4929 if (strcmp(name, "close") == 0) {
4931 } else if (strcmp(name, "edit") == 0) {
4938 void CommentPopDown()
4943 if (!commentUp) return;
4945 XtSetArg(args[j], XtNx, &commentX); j++;
4946 XtSetArg(args[j], XtNy, &commentY); j++;
4947 XtSetArg(args[j], XtNwidth, &commentW); j++;
4948 XtSetArg(args[j], XtNheight, &commentH); j++;
4949 XtGetValues(commentShell, args, j);
4950 XtPopdown(commentShell);
4951 XSync(xDisplay, False);
4955 void AnalysisPopDown()
4957 if (!analysisUp) return;
4958 XtPopdown(analysisShell);
4959 XSync(xDisplay, False);
4964 void FileNamePopUp(label, def, proc, openMode)
4971 Widget popup, layout, dialog, edit;
4977 fileProc = proc; /* I can't see a way not */
4978 fileOpenMode = openMode; /* to use globals here */
4981 XtSetArg(args[i], XtNresizable, True); i++;
4982 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
4983 fileNameShell = popup =
4984 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
4985 shellWidget, args, i);
4988 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
4989 layoutArgs, XtNumber(layoutArgs));
4992 XtSetArg(args[i], XtNlabel, label); i++;
4993 XtSetArg(args[i], XtNvalue, def); i++;
4994 XtSetArg(args[i], XtNborderWidth, 0); i++;
4995 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
4998 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
4999 XawDialogAddButton(dialog, "cancel", FileNameCallback,
5000 (XtPointer) dialog);
5002 XtRealizeWidget(popup);
5003 CatchDeleteWindow(popup, "FileNamePopDown");
5005 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5006 &x, &y, &win_x, &win_y, &mask);
5008 XtSetArg(args[0], XtNx, x - 10);
5009 XtSetArg(args[1], XtNy, y - 30);
5010 XtSetValues(popup, args, 2);
5012 XtPopup(popup, XtGrabExclusive);
5015 edit = XtNameToWidget(dialog, "*value");
5016 XtSetKeyboardFocus(popup, edit);
5019 void FileNamePopDown()
5021 if (!filenameUp) return;
5022 XtPopdown(fileNameShell);
5023 XtDestroyWidget(fileNameShell);
5028 void FileNameCallback(w, client_data, call_data)
5030 XtPointer client_data, call_data;
5035 XtSetArg(args[0], XtNlabel, &name);
5036 XtGetValues(w, args, 1);
5038 if (strcmp(name, "cancel") == 0) {
5043 FileNameAction(w, NULL, NULL, NULL);
5046 void FileNameAction(w, event, prms, nprms)
5058 name = XawDialogGetValueString(w = XtParent(w));
5060 if ((name != NULL) && (*name != NULLCHAR)) {
5062 XtPopdown(w = XtParent(XtParent(w)));
5066 p = strrchr(buf, ' ');
5073 fullname = ExpandPathName(buf);
5075 ErrorPopUp("Error", "Can't open file", FALSE);
5078 f = fopen(fullname, fileOpenMode);
5080 DisplayError("Failed to open file", errno);
5082 (void) (*fileProc)(f, index, buf);
5089 XtPopdown(w = XtParent(XtParent(w)));
5095 void PromotionPopUp()
5098 Widget dialog, layout;
5100 Dimension bw_width, pw_width;
5104 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5105 XtGetValues(boardWidget, args, j);
5108 XtSetArg(args[j], XtNresizable, True); j++;
5110 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5111 shellWidget, args, j);
5113 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5114 layoutArgs, XtNumber(layoutArgs));
5117 XtSetArg(args[j], XtNlabel, "Promote pawn to what?"); j++;
5118 XtSetArg(args[j], XtNborderWidth, 0); j++;
5119 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5122 XawDialogAddButton(dialog, "Queen", PromotionCallback,
5123 (XtPointer) dialog);
5124 XawDialogAddButton(dialog, "Rook", PromotionCallback,
5125 (XtPointer) dialog);
5126 XawDialogAddButton(dialog, "Bishop", PromotionCallback,
5127 (XtPointer) dialog);
5128 XawDialogAddButton(dialog, "Knight", PromotionCallback,
5129 (XtPointer) dialog);
5130 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5131 gameInfo.variant == VariantGiveaway) {
5132 XawDialogAddButton(dialog, "King", PromotionCallback,
5133 (XtPointer) dialog);
5135 XawDialogAddButton(dialog, "cancel", PromotionCallback,
5136 (XtPointer) dialog);
5138 XtRealizeWidget(promotionShell);
5139 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5142 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5143 XtGetValues(promotionShell, args, j);
5145 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5146 lineGap + squareSize/3 +
5147 ((toY == 7) ^ (flipView) ?
5148 0 : 6*(squareSize + lineGap)), &x, &y);
5151 XtSetArg(args[j], XtNx, x); j++;
5152 XtSetArg(args[j], XtNy, y); j++;
5153 XtSetValues(promotionShell, args, j);
5155 XtPopup(promotionShell, XtGrabNone);
5160 void PromotionPopDown()
5162 if (!promotionUp) return;
5163 XtPopdown(promotionShell);
5164 XtDestroyWidget(promotionShell);
5165 promotionUp = False;
5168 void PromotionCallback(w, client_data, call_data)
5170 XtPointer client_data, call_data;
5176 XtSetArg(args[0], XtNlabel, &name);
5177 XtGetValues(w, args, 1);
5181 if (fromX == -1) return;
5183 if (strcmp(name, "cancel") == 0) {
5187 } else if (strcmp(name, "Knight") == 0) {
5190 promoChar = ToLower(name[0]);
5193 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5195 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5196 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5201 void ErrorCallback(w, client_data, call_data)
5203 XtPointer client_data, call_data;
5206 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5208 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5214 if (!errorUp) return;
5216 XtPopdown(errorShell);
5217 XtDestroyWidget(errorShell);
5218 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5221 void ErrorPopUp(title, label, modal)
5222 char *title, *label;
5226 Widget dialog, layout;
5230 Dimension bw_width, pw_width;
5231 Dimension pw_height;
5235 XtSetArg(args[i], XtNresizable, True); i++;
5236 XtSetArg(args[i], XtNtitle, title); i++;
5238 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5239 shellWidget, args, i);
5241 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5242 layoutArgs, XtNumber(layoutArgs));
5245 XtSetArg(args[i], XtNlabel, label); i++;
5246 XtSetArg(args[i], XtNborderWidth, 0); i++;
5247 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5250 XawDialogAddButton(dialog, "ok", ErrorCallback, (XtPointer) dialog);
5252 XtRealizeWidget(errorShell);
5253 CatchDeleteWindow(errorShell, "ErrorPopDown");
5256 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5257 XtGetValues(boardWidget, args, i);
5259 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5260 XtSetArg(args[i], XtNheight, &pw_height); i++;
5261 XtGetValues(errorShell, args, i);
5264 /* This code seems to tickle an X bug if it is executed too soon
5265 after xboard starts up. The coordinates get transformed as if
5266 the main window was positioned at (0, 0).
5268 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5269 0 - pw_height + squareSize / 3, &x, &y);
5271 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5272 RootWindowOfScreen(XtScreen(boardWidget)),
5273 (bw_width - pw_width) / 2,
5274 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5278 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5281 XtSetArg(args[i], XtNx, x); i++;
5282 XtSetArg(args[i], XtNy, y); i++;
5283 XtSetValues(errorShell, args, i);
5286 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5289 /* Disable all user input other than deleting the window */
5290 static int frozen = 0;
5294 /* Grab by a widget that doesn't accept input */
5295 XtAddGrab(messageWidget, TRUE, FALSE);
5299 /* Undo a FreezeUI */
5302 if (!frozen) return;
5303 XtRemoveGrab(messageWidget);
5307 char *ModeToWidgetName(mode)
5311 case BeginningOfGame:
5312 if (appData.icsActive)
5313 return "menuMode.ICS Client";
5314 else if (appData.noChessProgram ||
5315 *appData.cmailGameName != NULLCHAR)
5316 return "menuMode.Edit Game";
5318 return "menuMode.Machine Black";
5319 case MachinePlaysBlack:
5320 return "menuMode.Machine Black";
5321 case MachinePlaysWhite:
5322 return "menuMode.Machine White";
5324 return "menuMode.Analysis Mode";
5326 return "menuMode.Analyze File";
5327 case TwoMachinesPlay:
5328 return "menuMode.Two Machines";
5330 return "menuMode.Edit Game";
5331 case PlayFromGameFile:
5332 return "menuFile.Load Game";
5334 return "menuMode.Edit Position";
5336 return "menuMode.Training";
5337 case IcsPlayingWhite:
5338 case IcsPlayingBlack:
5342 return "menuMode.ICS Client";
5349 void ModeHighlight()
5352 static int oldPausing = FALSE;
5353 static GameMode oldmode = (GameMode) -1;
5356 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5358 if (pausing != oldPausing) {
5359 oldPausing = pausing;
5361 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5363 XtSetArg(args[0], XtNleftBitmap, None);
5365 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5368 if (appData.showButtonBar) {
5371 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5372 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5374 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5375 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5378 /* Always toggle, don't set. Previous code messes up when
5379 invoked while the button is pressed, as releasing it
5380 toggles the state again. */
5383 XtSetArg(args[0], XtNbackground, &oldbg);
5384 XtSetArg(args[1], XtNforeground, &oldfg);
5385 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5387 XtSetArg(args[0], XtNbackground, oldfg);
5388 XtSetArg(args[1], XtNforeground, oldbg);
5391 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5395 wname = ModeToWidgetName(oldmode);
5396 if (wname != NULL) {
5397 XtSetArg(args[0], XtNleftBitmap, None);
5398 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5400 wname = ModeToWidgetName(gameMode);
5401 if (wname != NULL) {
5402 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5403 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5407 /* Maybe all the enables should be handled here, not just this one */
5408 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5409 gameMode == Training || gameMode == PlayFromGameFile);
5414 * Button/menu procedures
5416 void ResetProc(w, event, prms, nprms)
5426 int LoadGamePopUp(f, gameNumber, title)
5431 cmailMsgLoaded = FALSE;
5432 if (gameNumber == 0) {
5433 int error = GameListBuild(f);
5435 DisplayError("Cannot build game list", error);
5436 } else if (!ListEmpty(&gameList) &&
5437 ((ListGame *) gameList.tailPred)->number > 1) {
5438 GameListPopUp(f, title);
5444 return LoadGame(f, gameNumber, title, FALSE);
5447 void LoadGameProc(w, event, prms, nprms)
5453 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5456 FileNamePopUp("Load game file name?", "", LoadGamePopUp, "rb");
5459 void LoadNextGameProc(w, event, prms, nprms)
5468 void LoadPrevGameProc(w, event, prms, nprms)
5477 void ReloadGameProc(w, event, prms, nprms)
5486 void LoadNextPositionProc(w, event, prms, nprms)
5495 void LoadPrevPositionProc(w, event, prms, nprms)
5504 void ReloadPositionProc(w, event, prms, nprms)
5513 void LoadPositionProc(w, event, prms, nprms)
5519 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5522 FileNamePopUp("Load position file name?", "", LoadPosition, "rb");
5525 void SaveGameProc(w, event, prms, nprms)
5531 FileNamePopUp("Save game file name?",
5532 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5536 void SavePositionProc(w, event, prms, nprms)
5542 FileNamePopUp("Save position file name?",
5543 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5547 void ReloadCmailMsgProc(w, event, prms, nprms)
5553 ReloadCmailMsgEvent(FALSE);
5556 void MailMoveProc(w, event, prms, nprms)
5565 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5566 static char *selected_fen_position=NULL;
5569 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5570 Atom *type_return, XtPointer *value_return,
5571 unsigned long *length_return, int *format_return)
5573 char *selection_tmp;
5575 if (!selected_fen_position) return False; /* should never happen */
5576 if (*target == XA_STRING){
5577 /* note: since no XtSelectionDoneProc was registered, Xt will
5578 * automatically call XtFree on the value returned. So have to
5579 * make a copy of it allocated with XtMalloc */
5580 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5581 strcpy(selection_tmp, selected_fen_position);
5583 *value_return=selection_tmp;
5584 *length_return=strlen(selection_tmp);
5585 *type_return=XA_STRING;
5586 *format_return = 8; /* bits per byte */
5593 /* note: when called from menu all parameters are NULL, so no clue what the
5594 * Widget which was clicked on was, or what the click event was
5596 void CopyPositionProc(w, event, prms, nprms)
5604 if (selected_fen_position) free(selected_fen_position);
5605 selected_fen_position = (char *)PositionToFEN(currentMove);
5606 if (!selected_fen_position) return;
5607 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5609 SendPositionSelection,
5610 NULL/* lose_ownership_proc */ ,
5611 NULL/* transfer_done_proc */);
5613 free(selected_fen_position);
5614 selected_fen_position=NULL;
5618 /* function called when the data to Paste is ready */
5620 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5621 Atom *type, XtPointer value, unsigned long *len, int *format)
5624 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5625 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5626 EditPositionPasteFEN(fenstr);
5630 /* called when Paste Position button is pressed,
5631 * all parameters will be NULL */
5632 void PastePositionProc(w, event, prms, nprms)
5638 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5639 /* (XtSelectionCallbackProc) */ PastePositionCB,
5640 NULL, /* client_data passed to PastePositionCB */
5642 /* better to use the time field from the event that triggered the
5643 * call to this function, but that isn't trivial to get
5651 SendGameSelection(Widget w, Atom *selection, Atom *target,
5652 Atom *type_return, XtPointer *value_return,
5653 unsigned long *length_return, int *format_return)
5655 char *selection_tmp;
5657 if (*target == XA_STRING){
5658 FILE* f = fopen(gameCopyFilename, "r");
5661 if (f == NULL) return False;
5665 selection_tmp = XtMalloc(len + 1);
5666 count = fread(selection_tmp, 1, len, f);
5668 XtFree(selection_tmp);
5671 selection_tmp[len] = NULLCHAR;
5672 *value_return = selection_tmp;
5673 *length_return = len;
5674 *type_return = XA_STRING;
5675 *format_return = 8; /* bits per byte */
5682 /* note: when called from menu all parameters are NULL, so no clue what the
5683 * Widget which was clicked on was, or what the click event was
5685 void CopyGameProc(w, event, prms, nprms)
5693 ret = SaveGameToFile(gameCopyFilename, FALSE);
5696 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5699 NULL/* lose_ownership_proc */ ,
5700 NULL/* transfer_done_proc */);
5703 /* function called when the data to Paste is ready */
5705 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5706 Atom *type, XtPointer value, unsigned long *len, int *format)
5709 if (value == NULL || *len == 0) {
5710 return; /* nothing had been selected to copy */
5712 f = fopen(gamePasteFilename, "w");
5714 DisplayError("Can't open temp file", errno);
5717 fwrite(value, 1, *len, f);
5720 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5723 /* called when Paste Game button is pressed,
5724 * all parameters will be NULL */
5725 void PasteGameProc(w, event, prms, nprms)
5731 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5732 /* (XtSelectionCallbackProc) */ PasteGameCB,
5733 NULL, /* client_data passed to PasteGameCB */
5735 /* better to use the time field from the event that triggered the
5736 * call to this function, but that isn't trivial to get
5746 SaveGameProc(NULL, NULL, NULL, NULL);
5750 void QuitProc(w, event, prms, nprms)
5759 void PauseProc(w, event, prms, nprms)
5769 void MachineBlackProc(w, event, prms, nprms)
5775 MachineBlackEvent();
5778 void MachineWhiteProc(w, event, prms, nprms)
5784 MachineWhiteEvent();
5787 void AnalyzeModeProc(w, event, prms, nprms)
5793 if (!first.analysisSupport) {
5795 sprintf(buf, "%s does not support analysis", first.tidy);
5796 DisplayError(buf, 0);
5799 if (!appData.showThinking)
5800 ShowThinkingProc(w,event,prms,nprms);
5805 void AnalyzeFileProc(w, event, prms, nprms)
5811 if (!first.analysisSupport) {
5813 sprintf(buf, "%s does not support analysis", first.tidy);
5814 DisplayError(buf, 0);
5819 if (!appData.showThinking)
5820 ShowThinkingProc(w,event,prms,nprms);
5823 FileNamePopUp("File to analyze", "", LoadGamePopUp, "rb");
5824 AnalysisPeriodicEvent(1);
5827 void TwoMachinesProc(w, event, prms, nprms)
5836 void IcsClientProc(w, event, prms, nprms)
5845 void EditGameProc(w, event, prms, nprms)
5854 void EditPositionProc(w, event, prms, nprms)
5860 EditPositionEvent();
5863 void TrainingProc(w, event, prms, nprms)
5872 void EditCommentProc(w, event, prms, nprms)
5879 EditCommentPopDown();
5885 void IcsInputBoxProc(w, event, prms, nprms)
5891 if (ICSInputBoxUp) {
5892 ICSInputBoxPopDown();
5898 void AcceptProc(w, event, prms, nprms)
5907 void DeclineProc(w, event, prms, nprms)
5916 void RematchProc(w, event, prms, nprms)
5925 void CallFlagProc(w, event, prms, nprms)
5934 void DrawProc(w, event, prms, nprms)
5943 void AbortProc(w, event, prms, nprms)
5952 void AdjournProc(w, event, prms, nprms)
5961 void ResignProc(w, event, prms, nprms)
5970 void EnterKeyProc(w, event, prms, nprms)
5976 if (ICSInputBoxUp == True)
5980 void StopObservingProc(w, event, prms, nprms)
5986 StopObservingEvent();
5989 void StopExaminingProc(w, event, prms, nprms)
5995 StopExaminingEvent();
5999 void ForwardProc(w, event, prms, nprms)
6009 void BackwardProc(w, event, prms, nprms)
6018 void ToStartProc(w, event, prms, nprms)
6027 void ToEndProc(w, event, prms, nprms)
6036 void RevertProc(w, event, prms, nprms)
6045 void TruncateGameProc(w, event, prms, nprms)
6051 TruncateGameEvent();
6053 void RetractMoveProc(w, event, prms, nprms)
6062 void MoveNowProc(w, event, prms, nprms)
6072 void AlwaysQueenProc(w, event, prms, nprms)
6080 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6082 if (appData.alwaysPromoteToQueen) {
6083 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6085 XtSetArg(args[0], XtNleftBitmap, None);
6087 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6091 void AnimateDraggingProc(w, event, prms, nprms)
6099 appData.animateDragging = !appData.animateDragging;
6101 if (appData.animateDragging) {
6102 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6105 XtSetArg(args[0], XtNleftBitmap, None);
6107 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6111 void AnimateMovingProc(w, event, prms, nprms)
6119 appData.animate = !appData.animate;
6121 if (appData.animate) {
6122 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6125 XtSetArg(args[0], XtNleftBitmap, None);
6127 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6131 void AutocommProc(w, event, prms, nprms)
6139 appData.autoComment = !appData.autoComment;
6141 if (appData.autoComment) {
6142 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6144 XtSetArg(args[0], XtNleftBitmap, None);
6146 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6151 void AutoflagProc(w, event, prms, nprms)
6159 appData.autoCallFlag = !appData.autoCallFlag;
6161 if (appData.autoCallFlag) {
6162 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6164 XtSetArg(args[0], XtNleftBitmap, None);
6166 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6170 void AutoflipProc(w, event, prms, nprms)
6178 appData.autoFlipView = !appData.autoFlipView;
6180 if (appData.autoFlipView) {
6181 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6183 XtSetArg(args[0], XtNleftBitmap, None);
6185 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6189 void AutobsProc(w, event, prms, nprms)
6197 appData.autoObserve = !appData.autoObserve;
6199 if (appData.autoObserve) {
6200 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6202 XtSetArg(args[0], XtNleftBitmap, None);
6204 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6208 void AutoraiseProc(w, event, prms, nprms)
6216 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6218 if (appData.autoRaiseBoard) {
6219 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6221 XtSetArg(args[0], XtNleftBitmap, None);
6223 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6227 void AutosaveProc(w, event, prms, nprms)
6235 appData.autoSaveGames = !appData.autoSaveGames;
6237 if (appData.autoSaveGames) {
6238 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6240 XtSetArg(args[0], XtNleftBitmap, None);
6242 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6246 void BlindfoldProc(w, event, prms, nprms)
6254 appData.blindfold = !appData.blindfold;
6256 if (appData.blindfold) {
6257 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6259 XtSetArg(args[0], XtNleftBitmap, None);
6261 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6264 DrawPosition(True, NULL);
6267 void TestLegalityProc(w, event, prms, nprms)
6275 appData.testLegality = !appData.testLegality;
6277 if (appData.testLegality) {
6278 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6280 XtSetArg(args[0], XtNleftBitmap, None);
6282 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6287 void FlashMovesProc(w, event, prms, nprms)
6295 if (appData.flashCount == 0) {
6296 appData.flashCount = 3;
6298 appData.flashCount = -appData.flashCount;
6301 if (appData.flashCount > 0) {
6302 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6304 XtSetArg(args[0], XtNleftBitmap, None);
6306 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6310 void FlipViewProc(w, event, prms, nprms)
6316 flipView = !flipView;
6317 DrawPosition(True, NULL);
6320 void GetMoveListProc(w, event, prms, nprms)
6328 appData.getMoveList = !appData.getMoveList;
6330 if (appData.getMoveList) {
6331 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6334 XtSetArg(args[0], XtNleftBitmap, None);
6336 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6341 void HighlightDraggingProc(w, event, prms, nprms)
6349 appData.highlightDragging = !appData.highlightDragging;
6351 if (appData.highlightDragging) {
6352 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6354 XtSetArg(args[0], XtNleftBitmap, None);
6356 XtSetValues(XtNameToWidget(menuBarWidget,
6357 "menuOptions.Highlight Dragging"), args, 1);
6361 void HighlightLastMoveProc(w, event, prms, nprms)
6369 appData.highlightLastMove = !appData.highlightLastMove;
6371 if (appData.highlightLastMove) {
6372 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6374 XtSetArg(args[0], XtNleftBitmap, None);
6376 XtSetValues(XtNameToWidget(menuBarWidget,
6377 "menuOptions.Highlight Last Move"), args, 1);
6380 void IcsAlarmProc(w, event, prms, nprms)
6388 appData.icsAlarm = !appData.icsAlarm;
6390 if (appData.icsAlarm) {
6391 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6393 XtSetArg(args[0], XtNleftBitmap, None);
6395 XtSetValues(XtNameToWidget(menuBarWidget,
6396 "menuOptions.ICS Alarm"), args, 1);
6399 void MoveSoundProc(w, event, prms, nprms)
6407 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6409 if (appData.ringBellAfterMoves) {
6410 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6412 XtSetArg(args[0], XtNleftBitmap, None);
6414 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6419 void OldSaveStyleProc(w, event, prms, nprms)
6427 appData.oldSaveStyle = !appData.oldSaveStyle;
6429 if (appData.oldSaveStyle) {
6430 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6432 XtSetArg(args[0], XtNleftBitmap, None);
6434 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6438 void PeriodicUpdatesProc(w, event, prms, nprms)
6446 PeriodicUpdatesEvent(!appData.periodicUpdates);
6448 if (appData.periodicUpdates) {
6449 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6451 XtSetArg(args[0], XtNleftBitmap, None);
6453 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6457 void PonderNextMoveProc(w, event, prms, nprms)
6465 PonderNextMoveEvent(!appData.ponderNextMove);
6467 if (appData.ponderNextMove) {
6468 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6470 XtSetArg(args[0], XtNleftBitmap, None);
6472 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6476 void PopupExitMessageProc(w, event, prms, nprms)
6484 appData.popupExitMessage = !appData.popupExitMessage;
6486 if (appData.popupExitMessage) {
6487 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6489 XtSetArg(args[0], XtNleftBitmap, None);
6491 XtSetValues(XtNameToWidget(menuBarWidget,
6492 "menuOptions.Popup Exit Message"), args, 1);
6495 void PopupMoveErrorsProc(w, event, prms, nprms)
6503 appData.popupMoveErrors = !appData.popupMoveErrors;
6505 if (appData.popupMoveErrors) {
6506 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6508 XtSetArg(args[0], XtNleftBitmap, None);
6510 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6514 void PremoveProc(w, event, prms, nprms)
6522 appData.premove = !appData.premove;
6524 if (appData.premove) {
6525 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6527 XtSetArg(args[0], XtNleftBitmap, None);
6529 XtSetValues(XtNameToWidget(menuBarWidget,
6530 "menuOptions.Premove"), args, 1);
6533 void QuietPlayProc(w, event, prms, nprms)
6541 appData.quietPlay = !appData.quietPlay;
6543 if (appData.quietPlay) {
6544 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6546 XtSetArg(args[0], XtNleftBitmap, None);
6548 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6552 void ShowCoordsProc(w, event, prms, nprms)
6560 appData.showCoords = !appData.showCoords;
6562 if (appData.showCoords) {
6563 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6565 XtSetArg(args[0], XtNleftBitmap, None);
6567 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6570 DrawPosition(True, NULL);
6573 void ShowThinkingProc(w, event, prms, nprms)
6581 ShowThinkingEvent(!appData.showThinking);
6583 if (appData.showThinking) {
6584 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6586 XtSetArg(args[0], XtNleftBitmap, None);
6588 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6592 void InfoProc(w, event, prms, nprms)
6599 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6604 void ManProc(w, event, prms, nprms)
6612 if (nprms && *nprms > 0)
6616 sprintf(buf, "xterm -e man %s &", name);
6620 void HintProc(w, event, prms, nprms)
6629 void BookProc(w, event, prms, nprms)
6638 void AboutProc(w, event, prms, nprms)
6646 char *zippy = " (with Zippy code)";
6650 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6651 programVersion, zippy,
6652 "Copyright 1991 Digital Equipment Corporation",
6653 "Enhancements Copyright 1992-2001 Free Software Foundation",
6654 PRODUCT, " is free software and carries NO WARRANTY;",
6655 "see the file COPYING for more information.");
6656 ErrorPopUp("About XBoard", buf, FALSE);
6659 void DebugProc(w, event, prms, nprms)
6665 appData.debugMode = !appData.debugMode;
6668 void AboutGameProc(w, event, prms, nprms)
6677 void NothingProc(w, event, prms, nprms)
6686 void Iconify(w, event, prms, nprms)
6695 XtSetArg(args[0], XtNiconic, True);
6696 XtSetValues(shellWidget, args, 1);
6699 void DisplayMessage(message, extMessage)
6700 char *message, *extMessage;
6707 sprintf(buf, "%s %s", message, extMessage);
6710 message = extMessage;
6713 XtSetArg(arg, XtNlabel, message);
6714 XtSetValues(messageWidget, &arg, 1);
6717 void DisplayTitle(text)
6722 char title[MSG_SIZ];
6725 if (text == NULL) text = "";
6727 if (appData.titleInWindow) {
6729 XtSetArg(args[i], XtNlabel, text); i++;
6730 XtSetValues(titleWidget, args, i);
6733 if (*text != NULLCHAR) {
6735 strcpy(title, text);
6736 } else if (appData.icsActive) {
6737 sprintf(icon, "%s", appData.icsHost);
6738 sprintf(title, "%s: %s", programName, appData.icsHost);
6739 } else if (appData.cmailGameName[0] != NULLCHAR) {
6740 sprintf(icon, "%s", "CMail");
6741 sprintf(title, "%s: %s", programName, "CMail");
6742 } else if (appData.noChessProgram) {
6743 strcpy(icon, programName);
6744 strcpy(title, programName);
6746 strcpy(icon, first.tidy);
6747 sprintf(title, "%s: %s", programName, first.tidy);
6750 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6751 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6752 XtSetValues(shellWidget, args, i);
6756 void DisplayError(message, error)
6763 if (appData.debugMode || appData.matchMode) {
6764 fprintf(stderr, "%s: %s\n", programName, message);
6767 if (appData.debugMode || appData.matchMode) {
6768 fprintf(stderr, "%s: %s: %s\n",
6769 programName, message, strerror(error));
6771 sprintf(buf, "%s: %s", message, strerror(error));
6774 ErrorPopUp("Error", message, FALSE);
6778 void DisplayMoveError(message)
6783 DrawPosition(FALSE, NULL);
6784 if (appData.debugMode || appData.matchMode) {
6785 fprintf(stderr, "%s: %s\n", programName, message);
6787 if (appData.popupMoveErrors) {
6788 ErrorPopUp("Error", message, FALSE);
6790 DisplayMessage(message, "");
6795 void DisplayFatalError(message, error, status)
6801 errorExitStatus = status;
6803 fprintf(stderr, "%s: %s\n", programName, message);
6805 fprintf(stderr, "%s: %s: %s\n",
6806 programName, message, strerror(error));
6807 sprintf(buf, "%s: %s", message, strerror(error));
6810 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6811 ErrorPopUp(status ? "Fatal Error" : "Exiting", message, TRUE);
6817 void DisplayInformation(message)
6821 ErrorPopUp("Information", message, TRUE);
6824 void DisplayNote(message)
6828 ErrorPopUp("Note", message, FALSE);
6832 NullXErrorCheck(dpy, error_event)
6834 XErrorEvent *error_event;
6839 void DisplayIcsInteractionTitle(message)
6842 if (oldICSInteractionTitle == NULL) {
6843 /* Magic to find the old window title, adapted from vim */
6844 char *wina = getenv("WINDOWID");
6846 Window win = (Window) atoi(wina);
6847 Window root, parent, *children;
6848 unsigned int nchildren;
6849 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6851 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6852 if (!XQueryTree(xDisplay, win, &root, &parent,
6853 &children, &nchildren)) break;
6854 if (children) XFree((void *)children);
6855 if (parent == root || parent == 0) break;
6858 XSetErrorHandler(oldHandler);
6860 if (oldICSInteractionTitle == NULL) {
6861 oldICSInteractionTitle = "xterm";
6864 printf("\033]0;%s\007", message);
6868 char pendingReplyPrefix[MSG_SIZ];
6869 ProcRef pendingReplyPR;
6871 void AskQuestionProc(w, event, prms, nprms)
6878 fprintf(stderr, "AskQuestionProc needed 4 parameters, got %d\n",
6882 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6885 void AskQuestionPopDown()
6887 if (!askQuestionUp) return;
6888 XtPopdown(askQuestionShell);
6889 XtDestroyWidget(askQuestionShell);
6890 askQuestionUp = False;
6893 void AskQuestionReplyAction(w, event, prms, nprms)
6903 reply = XawDialogGetValueString(w = XtParent(w));
6904 strcpy(buf, pendingReplyPrefix);
6905 if (*buf) strcat(buf, " ");
6908 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6909 AskQuestionPopDown();
6911 if (err) DisplayFatalError("Error writing to chess program", err, 0);
6914 void AskQuestionCallback(w, client_data, call_data)
6916 XtPointer client_data, call_data;
6921 XtSetArg(args[0], XtNlabel, &name);
6922 XtGetValues(w, args, 1);
6924 if (strcmp(name, "cancel") == 0) {
6925 AskQuestionPopDown();
6927 AskQuestionReplyAction(w, NULL, NULL, NULL);
6931 void AskQuestion(title, question, replyPrefix, pr)
6932 char *title, *question, *replyPrefix;
6936 Widget popup, layout, dialog, edit;
6942 strcpy(pendingReplyPrefix, replyPrefix);
6943 pendingReplyPR = pr;
6946 XtSetArg(args[i], XtNresizable, True); i++;
6947 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
6948 askQuestionShell = popup =
6949 XtCreatePopupShell(title, transientShellWidgetClass,
6950 shellWidget, args, i);
6953 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
6954 layoutArgs, XtNumber(layoutArgs));
6957 XtSetArg(args[i], XtNlabel, question); i++;
6958 XtSetArg(args[i], XtNvalue, ""); i++;
6959 XtSetArg(args[i], XtNborderWidth, 0); i++;
6960 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
6963 XawDialogAddButton(dialog, "enter", AskQuestionCallback,
6964 (XtPointer) dialog);
6965 XawDialogAddButton(dialog, "cancel", AskQuestionCallback,
6966 (XtPointer) dialog);
6968 XtRealizeWidget(popup);
6969 CatchDeleteWindow(popup, "AskQuestionPopDown");
6971 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
6972 &x, &y, &win_x, &win_y, &mask);
6974 XtSetArg(args[0], XtNx, x - 10);
6975 XtSetArg(args[1], XtNy, y - 30);
6976 XtSetValues(popup, args, 2);
6978 XtPopup(popup, XtGrabExclusive);
6979 askQuestionUp = True;
6981 edit = XtNameToWidget(dialog, "*value");
6982 XtSetKeyboardFocus(popup, edit);
6990 if (*name == NULLCHAR) {
6992 } else if (strcmp(name, "$") == 0) {
6993 putc(BELLCHAR, stderr);
6996 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7004 PlaySound(appData.soundMove);
7010 PlaySound(appData.soundIcsWin);
7016 PlaySound(appData.soundIcsLoss);
7022 PlaySound(appData.soundIcsDraw);
7026 PlayIcsUnfinishedSound()
7028 PlaySound(appData.soundIcsUnfinished);
7034 PlaySound(appData.soundIcsAlarm);
7040 system("stty echo");
7046 system("stty -echo");
7050 Colorize(cc, continuation)
7055 int count, outCount, error;
7057 if (textColors[(int)cc].bg > 0) {
7058 if (textColors[(int)cc].fg > 0) {
7059 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7060 textColors[(int)cc].fg, textColors[(int)cc].bg);
7062 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7063 textColors[(int)cc].bg);
7066 if (textColors[(int)cc].fg > 0) {
7067 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7068 textColors[(int)cc].fg);
7070 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7073 count = strlen(buf);
7074 outCount = OutputToProcess(NoProc, buf, count, &error);
7075 if (outCount < count) {
7076 DisplayFatalError("Error writing to display", error, 1);
7079 if (continuation) return;
7082 PlaySound(appData.soundShout);
7085 PlaySound(appData.soundSShout);
7088 PlaySound(appData.soundChannel1);
7091 PlaySound(appData.soundChannel);
7094 PlaySound(appData.soundKibitz);
7097 PlaySound(appData.soundTell);
7099 case ColorChallenge:
7100 PlaySound(appData.soundChallenge);
7103 PlaySound(appData.soundRequest);
7106 PlaySound(appData.soundSeek);
7117 return getpwuid(getuid())->pw_name;
7120 static char *ExpandPathName(path)
7123 static char static_buf[2000];
7124 char *d, *s, buf[2000];
7130 while (*s && isspace(*s))
7139 if (*(s+1) == '/') {
7140 strcpy(d, getpwuid(getuid())->pw_dir);
7145 *strchr(buf, '/') = 0;
7146 pwd = getpwnam(buf);
7149 fprintf(stderr, "ERROR: Unknown user %s (in path %s)\n",
7153 strcpy(d, pwd->pw_dir);
7154 strcat(d, strchr(s+1, '/'));
7165 static char host_name[MSG_SIZ];
7167 #if HAVE_GETHOSTNAME
7168 gethostname(host_name, MSG_SIZ);
7170 #else /* not HAVE_GETHOSTNAME */
7171 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7172 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7174 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7176 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7177 #endif /* not HAVE_GETHOSTNAME */
7180 XtIntervalId delayedEventTimerXID = 0;
7181 DelayedEventCallback delayedEventCallback = 0;
7186 delayedEventTimerXID = 0;
7187 delayedEventCallback();
7191 ScheduleDelayedEvent(cb, millisec)
7192 DelayedEventCallback cb; long millisec;
7194 delayedEventCallback = cb;
7195 delayedEventTimerXID =
7196 XtAppAddTimeOut(appContext, millisec,
7197 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7200 DelayedEventCallback
7203 if (delayedEventTimerXID) {
7204 return delayedEventCallback;
7211 CancelDelayedEvent()
7213 if (delayedEventTimerXID) {
7214 XtRemoveTimeOut(delayedEventTimerXID);
7215 delayedEventTimerXID = 0;
7219 XtIntervalId loadGameTimerXID = 0;
7221 int LoadGameTimerRunning()
7223 return loadGameTimerXID != 0;
7226 int StopLoadGameTimer()
7228 if (loadGameTimerXID != 0) {
7229 XtRemoveTimeOut(loadGameTimerXID);
7230 loadGameTimerXID = 0;
7238 LoadGameTimerCallback(arg, id)
7242 loadGameTimerXID = 0;
7247 StartLoadGameTimer(millisec)
7251 XtAppAddTimeOut(appContext, millisec,
7252 (XtTimerCallbackProc) LoadGameTimerCallback,
7256 XtIntervalId analysisClockXID = 0;
7259 AnalysisClockCallback(arg, id)
7263 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
7264 AnalysisPeriodicEvent(0);
7265 StartAnalysisClock();
7270 StartAnalysisClock()
7273 XtAppAddTimeOut(appContext, 2000,
7274 (XtTimerCallbackProc) AnalysisClockCallback,
7278 XtIntervalId clockTimerXID = 0;
7280 int ClockTimerRunning()
7282 return clockTimerXID != 0;
7285 int StopClockTimer()
7287 if (clockTimerXID != 0) {
7288 XtRemoveTimeOut(clockTimerXID);
7297 ClockTimerCallback(arg, id)
7306 StartClockTimer(millisec)
7310 XtAppAddTimeOut(appContext, millisec,
7311 (XtTimerCallbackProc) ClockTimerCallback,
7316 DisplayTimerLabel(w, color, timer, highlight)
7325 if (appData.clockMode) {
7326 sprintf(buf, "%s: %s", color, TimeString(timer));
7327 XtSetArg(args[0], XtNlabel, buf);
7329 sprintf(buf, "%s ", color);
7330 XtSetArg(args[0], XtNlabel, buf);
7334 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7335 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7337 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7338 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7341 XtSetValues(w, args, 3);
7345 DisplayWhiteClock(timeRemaining, highlight)
7350 DisplayTimerLabel(whiteTimerWidget, "White", timeRemaining, highlight);
7351 if (highlight && iconPixmap == bIconPixmap) {
7352 iconPixmap = wIconPixmap;
7353 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7354 XtSetValues(shellWidget, args, 1);
7359 DisplayBlackClock(timeRemaining, highlight)
7364 DisplayTimerLabel(blackTimerWidget, "Black", timeRemaining, highlight);
7365 if (highlight && iconPixmap == wIconPixmap) {
7366 iconPixmap = bIconPixmap;
7367 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7368 XtSetValues(shellWidget, args, 1);
7386 int StartChildProcess(cmdLine, dir, pr)
7393 int to_prog[2], from_prog[2];
7397 if (appData.debugMode) {
7398 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7401 /* We do NOT feed the cmdLine to the shell; we just
7402 parse it into blank-separated arguments in the
7403 most simple-minded way possible.
7406 strcpy(buf, cmdLine);
7411 if (p == NULL) break;
7416 SetUpChildIO(to_prog, from_prog);
7418 if ((pid = fork()) == 0) {
7420 dup2(to_prog[0], 0);
7421 dup2(from_prog[1], 1);
7424 close(from_prog[0]);
7425 close(from_prog[1]);
7426 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7428 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7433 execvp(argv[0], argv);
7435 /* If we get here, exec failed */
7440 /* Parent process */
7442 close(from_prog[1]);
7444 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7447 cp->fdFrom = from_prog[0];
7448 cp->fdTo = to_prog[1];
7454 DestroyChildProcess(pr, signal)
7458 ChildProc *cp = (ChildProc *) pr;
7460 if (cp->kind != CPReal) return;
7463 kill(cp->pid, SIGTERM);
7465 /* Process is exiting either because of the kill or because of
7466 a quit command sent by the backend; either way, wait for it to die.
7474 InterruptChildProcess(pr)
7477 ChildProc *cp = (ChildProc *) pr;
7479 if (cp->kind != CPReal) return;
7480 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7483 int OpenTelnet(host, port, pr)
7488 char cmdLine[MSG_SIZ];
7490 if (port[0] == NULLCHAR) {
7491 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7493 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7495 return StartChildProcess(cmdLine, "", pr);
7498 int OpenTCP(host, port, pr)
7504 DisplayFatalError("Socket support is not configured in", 0, 2);
7505 #else /* !OMIT_SOCKETS */
7507 struct sockaddr_in sa;
7509 unsigned short uport;
7512 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7516 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7517 sa.sin_family = AF_INET;
7518 sa.sin_addr.s_addr = INADDR_ANY;
7519 uport = (unsigned short) 0;
7520 sa.sin_port = htons(uport);
7521 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7525 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7526 if (!(hp = gethostbyname(host))) {
7528 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7529 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7530 hp->h_addrtype = AF_INET;
7532 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7533 hp->h_addr_list[0] = (char *) malloc(4);
7534 hp->h_addr_list[0][0] = b0;
7535 hp->h_addr_list[0][1] = b1;
7536 hp->h_addr_list[0][2] = b2;
7537 hp->h_addr_list[0][3] = b3;
7542 sa.sin_family = hp->h_addrtype;
7543 uport = (unsigned short) atoi(port);
7544 sa.sin_port = htons(uport);
7545 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7547 if (connect(s, (struct sockaddr *) &sa,
7548 sizeof(struct sockaddr_in)) < 0) {
7552 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7559 #endif /* !OMIT_SOCKETS */
7564 int OpenCommPort(name, pr)
7571 fd = open(name, 2, 0);
7572 if (fd < 0) return errno;
7574 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7584 int OpenLoopback(pr)
7590 SetUpChildIO(to, from);
7592 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7595 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7602 int OpenRcmd(host, user, cmd, pr)
7603 char *host, *user, *cmd;
7606 DisplayFatalError("internal rcmd not implemented for Unix", 0, 1);
7610 #define INPUT_SOURCE_BUF_SIZE 8192
7619 char buf[INPUT_SOURCE_BUF_SIZE];
7624 DoInputCallback(closure, source, xid)
7629 InputSource *is = (InputSource *) closure;
7634 if (is->lineByLine) {
7635 count = read(is->fd, is->unused,
7636 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7638 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7641 is->unused += count;
7643 while (p < is->unused) {
7644 q = memchr(p, '\n', is->unused - p);
7645 if (q == NULL) break;
7647 (is->func)(is, is->closure, p, q - p, 0);
7651 while (p < is->unused) {
7656 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7661 (is->func)(is, is->closure, is->buf, count, error);
7665 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7672 ChildProc *cp = (ChildProc *) pr;
7674 is = (InputSource *) calloc(1, sizeof(InputSource));
7675 is->lineByLine = lineByLine;
7679 is->fd = fileno(stdin);
7681 is->kind = cp->kind;
7682 is->fd = cp->fdFrom;
7685 is->unused = is->buf;
7688 is->xid = XtAppAddInput(appContext, is->fd,
7689 (XtPointer) (XtInputReadMask),
7690 (XtInputCallbackProc) DoInputCallback,
7692 is->closure = closure;
7693 return (InputSourceRef) is;
7697 RemoveInputSource(isr)
7700 InputSource *is = (InputSource *) isr;
7702 if (is->xid == 0) return;
7703 XtRemoveInput(is->xid);
7707 int OutputToProcess(pr, message, count, outError)
7713 ChildProc *cp = (ChildProc *) pr;
7717 outCount = fwrite(message, 1, count, stdout);
7719 outCount = write(cp->fdTo, message, count);
7729 /* Output message to process, with "ms" milliseconds of delay
7730 between each character. This is needed when sending the logon
7731 script to ICC, which for some reason doesn't like the
7732 instantaneous send. */
7733 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7740 ChildProc *cp = (ChildProc *) pr;
7745 r = write(cp->fdTo, message++, 1);
7758 /**** Animation code by Hugh Fisher, DCS, ANU.
7760 Known problem: if a window overlapping the board is
7761 moved away while a piece is being animated underneath,
7762 the newly exposed area won't be updated properly.
7763 I can live with this.
7765 Known problem: if you look carefully at the animation
7766 of pieces in mono mode, they are being drawn as solid
7767 shapes without interior detail while moving. Fixing
7768 this would be a major complication for minimal return.
7771 /* Masks for XPM pieces. Black and white pieces can have
7772 different shapes, but in the interest of retaining my
7773 sanity pieces must have the same outline on both light
7774 and dark squares, and all pieces must use the same
7775 background square colors/images. */
7778 CreateAnimMasks (pieceDepth)
7785 unsigned long plane;
7788 /* Need a bitmap just to get a GC with right depth */
7789 buf = XCreatePixmap(xDisplay, xBoardWindow,
7791 values.foreground = 1;
7792 values.background = 0;
7793 /* Don't use XtGetGC, not read only */
7794 maskGC = XCreateGC(xDisplay, buf,
7795 GCForeground | GCBackground, &values);
7796 XFreePixmap(xDisplay, buf);
7798 buf = XCreatePixmap(xDisplay, xBoardWindow,
7799 squareSize, squareSize, pieceDepth);
7800 values.foreground = XBlackPixel(xDisplay, xScreen);
7801 values.background = XWhitePixel(xDisplay, xScreen);
7802 bufGC = XCreateGC(xDisplay, buf,
7803 GCForeground | GCBackground, &values);
7805 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7806 /* Begin with empty mask */
7807 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7808 squareSize, squareSize, 1);
7809 XSetFunction(xDisplay, maskGC, GXclear);
7810 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7811 0, 0, squareSize, squareSize);
7813 /* Take a copy of the piece */
7818 XSetFunction(xDisplay, bufGC, GXcopy);
7819 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7821 0, 0, squareSize, squareSize, 0, 0);
7823 /* XOR the background (light) over the piece */
7824 XSetFunction(xDisplay, bufGC, GXxor);
7826 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7827 0, 0, squareSize, squareSize, 0, 0);
7829 XSetForeground(xDisplay, bufGC, lightSquareColor);
7830 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7833 /* We now have an inverted piece image with the background
7834 erased. Construct mask by just selecting all the non-zero
7835 pixels - no need to reconstruct the original image. */
7836 XSetFunction(xDisplay, maskGC, GXor);
7838 /* Might be quicker to download an XImage and create bitmap
7839 data from it rather than this N copies per piece, but it
7840 only takes a fraction of a second and there is a much
7841 longer delay for loading the pieces. */
7842 for (n = 0; n < pieceDepth; n ++) {
7843 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7844 0, 0, squareSize, squareSize,
7850 XFreePixmap(xDisplay, buf);
7851 XFreeGC(xDisplay, bufGC);
7852 XFreeGC(xDisplay, maskGC);
7856 InitAnimState (anim, info)
7858 XWindowAttributes * info;
7863 /* Each buffer is square size, same depth as window */
7864 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7865 squareSize, squareSize, info->depth);
7866 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7867 squareSize, squareSize, info->depth);
7869 /* Create a plain GC for blitting */
7870 mask = GCForeground | GCBackground | GCFunction |
7871 GCPlaneMask | GCGraphicsExposures;
7872 values.foreground = XBlackPixel(xDisplay, xScreen);
7873 values.background = XWhitePixel(xDisplay, xScreen);
7874 values.function = GXcopy;
7875 values.plane_mask = AllPlanes;
7876 values.graphics_exposures = False;
7877 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7879 /* Piece will be copied from an existing context at
7880 the start of each new animation/drag. */
7881 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7883 /* Outline will be a read-only copy of an existing */
7884 anim->outlineGC = None;
7890 static int done = 0;
7891 XWindowAttributes info;
7895 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7897 InitAnimState(&game, &info);
7898 InitAnimState(&player, &info);
7900 /* For XPM pieces, we need bitmaps to use as masks. */
7902 CreateAnimMasks(info.depth);
7907 static Boolean frameWaiting;
7909 static RETSIGTYPE FrameAlarm (sig)
7912 frameWaiting = False;
7913 /* In case System-V style signals. Needed?? */
7914 signal(SIGALRM, FrameAlarm);
7921 struct itimerval delay;
7923 XSync(xDisplay, False);
7926 frameWaiting = True;
7927 signal(SIGALRM, FrameAlarm);
7928 delay.it_interval.tv_sec =
7929 delay.it_value.tv_sec = time / 1000;
7930 delay.it_interval.tv_usec =
7931 delay.it_value.tv_usec = (time % 1000) * 1000;
7932 setitimer(ITIMER_REAL, &delay, NULL);
7934 /* Ugh -- busy-wait! --tpm */
7935 while (frameWaiting);
7937 while (frameWaiting) pause();
7939 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
7940 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
7941 setitimer(ITIMER_REAL, &delay, NULL);
7951 XSync(xDisplay, False);
7953 usleep(time * 1000);
7958 /* Convert board position to corner of screen rect and color */
7961 ScreenSquare(column, row, pt, color)
7962 int column; int row; XPoint * pt; int * color;
7965 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
7966 pt->y = lineGap + row * (squareSize + lineGap);
7968 pt->x = lineGap + column * (squareSize + lineGap);
7969 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
7971 *color = ((column + row) % 2) == 1;
7974 /* Convert window coords to square */
7977 BoardSquare(x, y, column, row)
7978 int x; int y; int * column; int * row;
7980 *column = EventToSquare(x, BOARD_SIZE);
7981 if (flipView && *column >= 0)
7982 *column = BOARD_SIZE - 1 - *column;
7983 *row = EventToSquare(y, BOARD_SIZE);
7984 if (!flipView && *row >= 0)
7985 *row = BOARD_SIZE - 1 - *row;
7990 #undef Max /* just in case */
7992 #define Max(a, b) ((a) > (b) ? (a) : (b))
7993 #define Min(a, b) ((a) < (b) ? (a) : (b))
7996 SetRect(rect, x, y, width, height)
7997 XRectangle * rect; int x; int y; int width; int height;
8001 rect->width = width;
8002 rect->height = height;
8005 /* Test if two frames overlap. If they do, return
8006 intersection rect within old and location of
8007 that rect within new. */
8010 Intersect(old, new, size, area, pt)
8011 XPoint * old; XPoint * new;
8012 int size; XRectangle * area; XPoint * pt;
8014 if (old->x > new->x + size || new->x > old->x + size ||
8015 old->y > new->y + size || new->y > old->y + size) {
8018 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8019 size - abs(old->x - new->x), size - abs(old->y - new->y));
8020 pt->x = Max(old->x - new->x, 0);
8021 pt->y = Max(old->y - new->y, 0);
8026 /* For two overlapping frames, return the rect(s)
8027 in the old that do not intersect with the new. */
8030 CalcUpdateRects(old, new, size, update, nUpdates)
8031 XPoint * old; XPoint * new; int size;
8032 XRectangle update[]; int * nUpdates;
8036 /* If old = new (shouldn't happen) then nothing to draw */
8037 if (old->x == new->x && old->y == new->y) {
8041 /* Work out what bits overlap. Since we know the rects
8042 are the same size we don't need a full intersect calc. */
8044 /* Top or bottom edge? */
8045 if (new->y > old->y) {
8046 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8048 } else if (old->y > new->y) {
8049 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8050 size, old->y - new->y);
8053 /* Left or right edge - don't overlap any update calculated above. */
8054 if (new->x > old->x) {
8055 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8056 new->x - old->x, size - abs(new->y - old->y));
8058 } else if (old->x > new->x) {
8059 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8060 old->x - new->x, size - abs(new->y - old->y));
8067 /* Generate a series of frame coords from start->mid->finish.
8068 The movement rate doubles until the half way point is
8069 reached, then halves back down to the final destination,
8070 which gives a nice slow in/out effect. The algorithmn
8071 may seem to generate too many intermediates for short
8072 moves, but remember that the purpose is to attract the
8073 viewers attention to the piece about to be moved and
8074 then to where it ends up. Too few frames would be less
8078 Tween(start, mid, finish, factor, frames, nFrames)
8079 XPoint * start; XPoint * mid;
8080 XPoint * finish; int factor;
8081 XPoint frames[]; int * nFrames;
8083 int fraction, n, count;
8087 /* Slow in, stepping 1/16th, then 1/8th, ... */
8089 for (n = 0; n < factor; n++)
8091 for (n = 0; n < factor; n++) {
8092 frames[count].x = start->x + (mid->x - start->x) / fraction;
8093 frames[count].y = start->y + (mid->y - start->y) / fraction;
8095 fraction = fraction / 2;
8099 frames[count] = *mid;
8102 /* Slow out, stepping 1/2, then 1/4, ... */
8104 for (n = 0; n < factor; n++) {
8105 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8106 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8108 fraction = fraction * 2;
8113 /* Draw a piece on the screen without disturbing what's there */
8116 SelectGCMask(piece, clip, outline, mask)
8117 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8121 /* Bitmap for piece being moved. */
8122 if (appData.monoMode) {
8123 *mask = *pieceToSolid(piece);
8124 } else if (useImages) {
8126 *mask = xpmMask[piece];
8128 *mask = ximMaskPm[piece%6];
8131 *mask = *pieceToSolid(piece);
8134 /* GC for piece being moved. Square color doesn't matter, but
8135 since it gets modified we make a copy of the original. */
8137 if (appData.monoMode)
8142 if (appData.monoMode)
8147 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8149 /* Outline only used in mono mode and is not modified */
8151 *outline = bwPieceGC;
8153 *outline = wbPieceGC;
8157 OverlayPiece(piece, clip, outline, dest)
8158 ChessSquare piece; GC clip; GC outline; Drawable dest;
8163 /* Draw solid rectangle which will be clipped to shape of piece */
8164 XFillRectangle(xDisplay, dest, clip,
8165 0, 0, squareSize, squareSize);
8166 if (appData.monoMode)
8167 /* Also draw outline in contrasting color for black
8168 on black / white on white cases */
8169 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8170 0, 0, squareSize, squareSize, 0, 0, 1);
8172 /* Copy the piece */
8177 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8179 0, 0, squareSize, squareSize,
8184 /* Animate the movement of a single piece */
8187 BeginAnimation(anim, piece, startColor, start)
8195 /* The old buffer is initialised with the start square (empty) */
8196 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8197 anim->prevFrame = *start;
8199 /* The piece will be drawn using its own bitmap as a matte */
8200 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8201 XSetClipMask(xDisplay, anim->pieceGC, mask);
8205 AnimationFrame(anim, frame, piece)
8210 XRectangle updates[4];
8215 /* Save what we are about to draw into the new buffer */
8216 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8217 frame->x, frame->y, squareSize, squareSize,
8220 /* Erase bits of the previous frame */
8221 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8222 /* Where the new frame overlapped the previous,
8223 the contents in newBuf are wrong. */
8224 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8225 overlap.x, overlap.y,
8226 overlap.width, overlap.height,
8228 /* Repaint the areas in the old that don't overlap new */
8229 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8230 for (i = 0; i < count; i++)
8231 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8232 updates[i].x - anim->prevFrame.x,
8233 updates[i].y - anim->prevFrame.y,
8234 updates[i].width, updates[i].height,
8235 updates[i].x, updates[i].y);
8237 /* Easy when no overlap */
8238 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8239 0, 0, squareSize, squareSize,
8240 anim->prevFrame.x, anim->prevFrame.y);
8243 /* Save this frame for next time round */
8244 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8245 0, 0, squareSize, squareSize,
8247 anim->prevFrame = *frame;
8249 /* Draw piece over original screen contents, not current,
8250 and copy entire rect. Wipes out overlapping piece images. */
8251 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8252 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8253 0, 0, squareSize, squareSize,
8254 frame->x, frame->y);
8258 EndAnimation (anim, finish)
8262 XRectangle updates[4];
8267 /* The main code will redraw the final square, so we
8268 only need to erase the bits that don't overlap. */
8269 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8270 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8271 for (i = 0; i < count; i++)
8272 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8273 updates[i].x - anim->prevFrame.x,
8274 updates[i].y - anim->prevFrame.y,
8275 updates[i].width, updates[i].height,
8276 updates[i].x, updates[i].y);
8278 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8279 0, 0, squareSize, squareSize,
8280 anim->prevFrame.x, anim->prevFrame.y);
8285 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8287 ChessSquare piece; int startColor;
8288 XPoint * start; XPoint * finish;
8289 XPoint frames[]; int nFrames;
8293 BeginAnimation(anim, piece, startColor, start);
8294 for (n = 0; n < nFrames; n++) {
8295 AnimationFrame(anim, &(frames[n]), piece);
8296 FrameDelay(appData.animSpeed);
8298 EndAnimation(anim, finish);
8301 /* Main control logic for deciding what to animate and how */
8304 AnimateMove(board, fromX, fromY, toX, toY)
8313 XPoint start, finish, mid;
8314 XPoint frames[kFactor * 2 + 1];
8315 int nFrames, startColor, endColor;
8317 /* Are we animating? */
8318 if (!appData.animate || appData.blindfold)
8321 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8322 piece = board[fromY][fromX];
8323 if (piece >= EmptySquare) return;
8328 hop = (piece == WhiteKnight || piece == BlackKnight);
8331 if (appData.debugMode) {
8332 printf("AnimateMove: piece %d %s from %d,%d to %d,%d \n",
8333 piece, hop ? "hops" : "slides", fromX, fromY, toX, toY);
8336 ScreenSquare(fromX, fromY, &start, &startColor);
8337 ScreenSquare(toX, toY, &finish, &endColor);
8340 /* Knight: make diagonal movement then straight */
8341 if (abs(toY - fromY) < abs(toX - fromX)) {
8342 mid.x = start.x + (finish.x - start.x) / 2;
8346 mid.y = start.y + (finish.y - start.y) / 2;
8349 mid.x = start.x + (finish.x - start.x) / 2;
8350 mid.y = start.y + (finish.y - start.y) / 2;
8353 /* Don't use as many frames for very short moves */
8354 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8355 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8357 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8358 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8360 /* Be sure end square is redrawn */
8361 damage[toY][toX] = True;
8365 DragPieceBegin(x, y)
8368 int boardX, boardY, color;
8371 /* Are we animating? */
8372 if (!appData.animateDragging || appData.blindfold)
8375 /* Figure out which square we start in and the
8376 mouse position relative to top left corner. */
8377 BoardSquare(x, y, &boardX, &boardY);
8378 player.startBoardX = boardX;
8379 player.startBoardY = boardY;
8380 ScreenSquare(boardX, boardY, &corner, &color);
8381 player.startSquare = corner;
8382 player.startColor = color;
8384 /* Start from exactly where the piece is. This can be confusing
8385 if you start dragging far from the center of the square; most
8386 or all of the piece can be over a different square from the one
8387 the mouse pointer is in. */
8388 player.mouseDelta.x = x - corner.x;
8389 player.mouseDelta.y = y - corner.y;
8391 /* As soon as we start dragging, the piece will jump slightly to
8392 be centered over the mouse pointer. */
8393 player.mouseDelta.x = squareSize/2;
8394 player.mouseDelta.y = squareSize/2;
8396 /* Initialise animation */
8397 player.dragPiece = PieceForSquare(boardX, boardY);
8399 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8400 player.dragActive = True;
8401 BeginAnimation(&player, player.dragPiece, color, &corner);
8402 /* Mark this square as needing to be redrawn. Note that
8403 we don't remove the piece though, since logically (ie
8404 as seen by opponent) the move hasn't been made yet. */
8405 damage[boardY][boardX] = True;
8407 player.dragActive = False;
8417 /* Are we animating? */
8418 if (!appData.animateDragging || appData.blindfold)
8422 if (! player.dragActive)
8424 /* Move piece, maintaining same relative position
8425 of mouse within square */
8426 corner.x = x - player.mouseDelta.x;
8427 corner.y = y - player.mouseDelta.y;
8428 AnimationFrame(&player, &corner, player.dragPiece);
8430 if (appData.highlightDragging) {
8432 BoardSquare(x, y, &boardX, &boardY);
8433 SetHighlights(fromX, fromY, boardX, boardY);
8442 int boardX, boardY, color;
8445 /* Are we animating? */
8446 if (!appData.animateDragging || appData.blindfold)
8450 if (! player.dragActive)
8452 /* Last frame in sequence is square piece is
8453 placed on, which may not match mouse exactly. */
8454 BoardSquare(x, y, &boardX, &boardY);
8455 ScreenSquare(boardX, boardY, &corner, &color);
8456 EndAnimation(&player, &corner);
8458 /* Be sure end square is redrawn */
8459 damage[boardY][boardX] = True;
8461 /* This prevents weird things happening with fast successive
8462 clicks which on my Sun at least can cause motion events
8463 without corresponding press/release. */
8464 player.dragActive = False;
8467 /* Handle expose event while piece being dragged */
8472 if (!player.dragActive || appData.blindfold)
8475 /* What we're doing: logically, the move hasn't been made yet,
8476 so the piece is still in it's original square. But visually
8477 it's being dragged around the board. So we erase the square
8478 that the piece is on and draw it at the last known drag point. */
8479 BlankSquare(player.startSquare.x, player.startSquare.y,
8480 player.startColor, EmptySquare, xBoardWindow);
8481 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8482 damage[player.startBoardY][player.startBoardX] = TRUE;