2 * xboard.c -- X front end for XBoard
5 * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
6 * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
8 * The following terms apply to Digital Equipment Corporation's copyright
10 * ------------------------------------------------------------------------
13 * Permission to use, copy, modify, and distribute this software and its
14 * documentation for any purpose and without fee is hereby granted,
15 * provided that the above copyright notice appear in all copies and that
16 * both that copyright notice and this permission notice appear in
17 * supporting documentation, and that the name of Digital not be
18 * used in advertising or publicity pertaining to distribution of the
19 * software without specific, written prior permission.
21 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28 * ------------------------------------------------------------------------
30 * The following terms apply to the enhanced version of XBoard distributed
31 * by the Free Software Foundation:
32 * ------------------------------------------------------------------------
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
43 * You should have received a copy of the GNU General Public License
44 * along with this program; if not, write to the Free Software
45 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 * ------------------------------------------------------------------------
48 * See the file ChangeLog for a revision history.
57 #include <sys/types.h>
62 # if HAVE_SYS_SOCKET_H
63 # include <sys/socket.h>
64 # include <netinet/in.h>
66 # else /* not HAVE_SYS_SOCKET_H */
67 # if HAVE_LAN_SOCKET_H
68 # include <lan/socket.h>
70 # include <lan/netdb.h>
71 # else /* not HAVE_LAN_SOCKET_H */
72 # define OMIT_SOCKETS 1
73 # endif /* not HAVE_LAN_SOCKET_H */
74 # endif /* not HAVE_SYS_SOCKET_H */
75 #endif /* !OMIT_SOCKETS */
80 #else /* not STDC_HEADERS */
81 extern char *getenv();
84 # else /* not HAVE_STRING_H */
86 # endif /* not HAVE_STRING_H */
87 #endif /* not STDC_HEADERS */
90 # include <sys/fcntl.h>
91 #else /* not HAVE_SYS_FCNTL_H */
94 # endif /* HAVE_FCNTL_H */
95 #endif /* not HAVE_SYS_FCNTL_H */
97 #if HAVE_SYS_SYSTEMINFO_H
98 # include <sys/systeminfo.h>
99 #endif /* HAVE_SYS_SYSTEMINFO_H */
101 #if TIME_WITH_SYS_TIME
102 # include <sys/time.h>
106 # include <sys/time.h>
117 # include <sys/wait.h>
122 # define NAMLEN(dirent) strlen((dirent)->d_name)
123 # define HAVE_DIR_STRUCT
125 # define dirent direct
126 # define NAMLEN(dirent) (dirent)->d_namlen
128 # include <sys/ndir.h>
129 # define HAVE_DIR_STRUCT
132 # include <sys/dir.h>
133 # define HAVE_DIR_STRUCT
137 # define HAVE_DIR_STRUCT
141 #include <X11/Intrinsic.h>
142 #include <X11/StringDefs.h>
143 #include <X11/Shell.h>
144 #include <X11/cursorfont.h>
145 #include <X11/Xatom.h>
147 #include <X11/Xaw3d/Dialog.h>
148 #include <X11/Xaw3d/Form.h>
149 #include <X11/Xaw3d/List.h>
150 #include <X11/Xaw3d/Label.h>
151 #include <X11/Xaw3d/SimpleMenu.h>
152 #include <X11/Xaw3d/SmeBSB.h>
153 #include <X11/Xaw3d/SmeLine.h>
154 #include <X11/Xaw3d/Box.h>
155 #include <X11/Xaw3d/MenuButton.h>
156 #include <X11/Xaw3d/Text.h>
157 #include <X11/Xaw3d/AsciiText.h>
159 #include <X11/Xaw/Dialog.h>
160 #include <X11/Xaw/Form.h>
161 #include <X11/Xaw/List.h>
162 #include <X11/Xaw/Label.h>
163 #include <X11/Xaw/SimpleMenu.h>
164 #include <X11/Xaw/SmeBSB.h>
165 #include <X11/Xaw/SmeLine.h>
166 #include <X11/Xaw/Box.h>
167 #include <X11/Xaw/MenuButton.h>
168 #include <X11/Xaw/Text.h>
169 #include <X11/Xaw/AsciiText.h>
174 #include "pixmaps/pixmaps.h"
175 #define IMAGE_EXT "xpm"
177 #define IMAGE_EXT "xim"
178 #include "bitmaps/bitmaps.h"
181 #include "bitmaps/icon_white.bm"
182 #include "bitmaps/icon_black.bm"
183 #include "bitmaps/checkmark.bm"
186 #include "frontend.h"
191 #include "xgamelist.h"
192 #include "xhistory.h"
193 #include "xedittags.h"
200 #define usleep(t) _sleep2(((t)+500)/1000)
204 # define _(s) gettext (s)
205 # define N_(s) gettext_noop (s)
221 int main P((int argc, char **argv));
222 RETSIGTYPE CmailSigHandler P((int sig));
223 RETSIGTYPE IntSigHandler P((int sig));
224 void CreateGCs P((void));
225 void CreateXIMPieces P((void));
226 void CreateXPMPieces P((void));
227 void CreatePieces P((void));
228 void CreatePieceMenus P((void));
229 Widget CreateMenuBar P((Menu *mb));
230 Widget CreateButtonBar P ((MenuItem *mi));
231 char *FindFont P((char *pattern, int targetPxlSize));
232 void PieceMenuPopup P((Widget w, XEvent *event,
233 String *params, Cardinal *num_params));
234 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
235 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
236 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
237 u_int wreq, u_int hreq));
238 void CreateGrid P((void));
239 int EventToSquare P((int x, int limit));
240 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
241 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
242 void HandleUserMove P((Widget w, XEvent *event,
243 String *prms, Cardinal *nprms));
244 void AnimateUserMove P((Widget w, XEvent * event,
245 String * params, Cardinal * nParams));
246 void WhiteClock P((Widget w, XEvent *event,
247 String *prms, Cardinal *nprms));
248 void BlackClock P((Widget w, XEvent *event,
249 String *prms, Cardinal *nprms));
250 void DrawPositionProc P((Widget w, XEvent *event,
251 String *prms, Cardinal *nprms));
252 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
254 void CommentPopUp P((char *title, char *label));
255 void CommentPopDown P((void));
256 void CommentCallback P((Widget w, XtPointer client_data,
257 XtPointer call_data));
258 void ICSInputBoxPopUp P((void));
259 void ICSInputBoxPopDown P((void));
260 void FileNamePopUp P((char *label, char *def,
261 FileProc proc, char *openMode));
262 void FileNamePopDown P((void));
263 void FileNameCallback P((Widget w, XtPointer client_data,
264 XtPointer call_data));
265 void FileNameAction P((Widget w, XEvent *event,
266 String *prms, Cardinal *nprms));
267 void AskQuestionReplyAction P((Widget w, XEvent *event,
268 String *prms, Cardinal *nprms));
269 void AskQuestionProc P((Widget w, XEvent *event,
270 String *prms, Cardinal *nprms));
271 void AskQuestionPopDown P((void));
272 void PromotionPopUp P((void));
273 void PromotionPopDown P((void));
274 void PromotionCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void EditCommentPopDown P((void));
277 void EditCommentCallback P((Widget w, XtPointer client_data,
278 XtPointer call_data));
279 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
280 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
281 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
282 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
284 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
286 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
288 void LoadPositionProc P((Widget w, XEvent *event,
289 String *prms, Cardinal *nprms));
290 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
292 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
294 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
296 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
298 void PastePositionProc P((Widget w, XEvent *event, String *prms,
300 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
301 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
302 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void SavePositionProc P((Widget w, XEvent *event,
304 String *prms, Cardinal *nprms));
305 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
308 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
312 void MachineWhiteProc P((Widget w, XEvent *event,
313 String *prms, Cardinal *nprms));
314 void AnalyzeModeProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void AnalyzeFileProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
320 void IcsClientProc P((Widget w, XEvent *event, String *prms,
322 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void EditPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void EditCommentProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void IcsInputBoxProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void StopObservingProc P((Widget w, XEvent *event, String *prms,
341 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
343 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
350 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
352 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
355 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
357 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
359 void AutocommProc P((Widget w, XEvent *event, String *prms,
361 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AutobsProc P((Widget w, XEvent *event, String *prms,
365 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
370 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
373 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
375 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
377 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
381 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
383 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
385 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
387 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
389 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
393 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
395 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
397 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void DisplayMove P((int moveNumber));
407 void DisplayTitle P((char *title));
408 void ICSInitScript P((void));
409 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
410 void ErrorPopUp P((char *title, char *text, int modal));
411 void ErrorPopDown P((void));
412 static char *ExpandPathName P((char *path));
413 static void CreateAnimVars P((void));
414 static void DragPieceBegin P((int x, int y));
415 static void DragPieceMove P((int x, int y));
416 static void DragPieceEnd P((int x, int y));
417 static void DrawDragPiece P((void));
418 char *ModeToWidgetName P((GameMode mode));
421 * XBoard depends on Xt R4 or higher
423 int xtVersion = XtSpecificationRelease;
428 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
429 jailSquareColor, highlightSquareColor, premoveHighlightColor;
430 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
431 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
432 wjPieceGC, bjPieceGC, prelineGC;
433 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
434 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
435 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
436 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
437 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
438 ICSInputShell, fileNameShell, askQuestionShell;
439 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
440 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
441 Font clockFontID, coordFontID;
442 XFontStruct *clockFontStruct, *coordFontStruct;
443 XtAppContext appContext;
445 char *oldICSInteractionTitle;
450 Position commentX = -1, commentY = -1;
451 Dimension commentW, commentH;
453 int squareSize, smallLayout = 0, tinyLayout = 0,
454 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
455 ICSInputBoxUp = False, askQuestionUp = False,
456 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
457 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
458 Pixel timerForegroundPixel, timerBackgroundPixel;
459 Pixel buttonForegroundPixel, buttonBackgroundPixel;
460 char *chessDir, *programName, *programVersion,
461 *gameCopyFilename, *gamePasteFilename;
465 Pixmap pieceBitmap[2][6];
466 Pixmap xpmPieceBitmap[4][6]; /* LL, LD, DL, DD */
467 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
468 int useImages, useImageSqs;
469 XImage *ximPieceBitmap[4][6]; /* LL, LD, DL, DD */
470 Pixmap ximMaskPm[6]; /* clipmasks, used for XIM pieces */
471 XImage *ximLightSquare, *ximDarkSquare;
474 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % 6]
475 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % 6]
477 #define White(piece) ((int)(piece) < (int)BlackPawn)
479 /* Variables for doing smooth animation. This whole thing
480 would be much easier if the board was double-buffered,
481 but that would require a fairly major rewrite. */
486 GC blitGC, pieceGC, outlineGC;
487 XPoint startSquare, prevFrame, mouseDelta;
491 int startBoardX, startBoardY;
494 /* There can be two pieces being animated at once: a player
495 can begin dragging a piece before the remote opponent has moved. */
497 static AnimState game, player;
499 /* Bitmaps for use as masks when drawing XPM pieces.
500 Need one for each black and white piece. */
501 static Pixmap xpmMask[BlackKing + 1];
503 /* This magic number is the number of intermediate frames used
504 in each half of the animation. For short moves it's reduced
505 by 1. The total number of frames will be factor * 2 + 1. */
508 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
510 MenuItem fileMenu[] = {
511 {N_("Reset Game"), ResetProc},
512 {"----", NothingProc},
513 {N_("Load Game"), LoadGameProc},
514 {N_("Load Next Game"), LoadNextGameProc},
515 {N_("Load Previous Game"), LoadPrevGameProc},
516 {N_("Reload Same Game"), ReloadGameProc},
517 {N_("Save Game"), SaveGameProc},
518 {"----", NothingProc},
519 {N_("Copy Game"), CopyGameProc},
520 {N_("Paste Game"), PasteGameProc},
521 {"----", NothingProc},
522 {N_("Load Position"), LoadPositionProc},
523 {N_("Load Next Position"), LoadNextPositionProc},
524 {N_("Load Previous Position"), LoadPrevPositionProc},
525 {N_("Reload Same Position"), ReloadPositionProc},
526 {N_("Save Position"), SavePositionProc},
527 {"----", NothingProc},
528 {N_("Copy Position"), CopyPositionProc},
529 {N_("Paste Position"), PastePositionProc},
530 {"----", NothingProc},
531 {N_("Mail Move"), MailMoveProc},
532 {N_("Reload CMail Message"), ReloadCmailMsgProc},
533 {"----", NothingProc},
534 {N_("Exit"), QuitProc},
538 MenuItem modeMenu[] = {
539 {N_("Machine White"), MachineWhiteProc},
540 {N_("Machine Black"), MachineBlackProc},
541 {N_("Two Machines"), TwoMachinesProc},
542 {N_("Analysis Mode"), AnalyzeModeProc},
543 {N_("Analyze File"), AnalyzeFileProc },
544 {N_("ICS Client"), IcsClientProc},
545 {N_("Edit Game"), EditGameProc},
546 {N_("Edit Position"), EditPositionProc},
547 {N_("Training"), TrainingProc},
548 {"----", NothingProc},
549 {N_("Show Game List"), ShowGameListProc},
550 {N_("Show Move List"), HistoryShowProc},
551 {N_("Edit Tags"), EditTagsProc},
552 {N_("Edit Comment"), EditCommentProc},
553 {N_("ICS Input Box"), IcsInputBoxProc},
554 {N_("Pause"), PauseProc},
558 MenuItem actionMenu[] = {
559 {N_("Accept"), AcceptProc},
560 {N_("Decline"), DeclineProc},
561 {N_("Rematch"), RematchProc},
562 {"----", NothingProc},
563 {N_("Call Flag"), CallFlagProc},
564 {N_("Draw"), DrawProc},
565 {N_("Adjourn"), AdjournProc},
566 {N_("Abort"), AbortProc},
567 {N_("Resign"), ResignProc},
568 {"----", NothingProc},
569 {N_("Stop Observing"), StopObservingProc},
570 {N_("Stop Examining"), StopExaminingProc},
574 MenuItem stepMenu[] = {
575 {N_("Backward"), BackwardProc},
576 {N_("Forward"), ForwardProc},
577 {N_("Back to Start"), ToStartProc},
578 {N_("Forward to End"), ToEndProc},
579 {N_("Revert"), RevertProc},
580 {N_("Truncate Game"), TruncateGameProc},
581 {"----", NothingProc},
582 {N_("Move Now"), MoveNowProc},
583 {N_("Retract Move"), RetractMoveProc},
587 MenuItem optionsMenu[] = {
588 {N_("Always Queen"), AlwaysQueenProc},
589 {N_("Animate Dragging"), AnimateDraggingProc},
590 {N_("Animate Moving"), AnimateMovingProc},
591 {N_("Auto Comment"), AutocommProc},
592 {N_("Auto Flag"), AutoflagProc},
593 {N_("Auto Flip View"), AutoflipProc},
594 {N_("Auto Observe"), AutobsProc},
595 {N_("Auto Raise Board"), AutoraiseProc},
596 {N_("Auto Save"), AutosaveProc},
597 {N_("Blindfold"), BlindfoldProc},
598 {N_("Flash Moves"), FlashMovesProc},
599 {N_("Flip View"), FlipViewProc},
600 {N_("Get Move List"), GetMoveListProc},
602 {N_("Highlight Dragging"), HighlightDraggingProc},
604 {N_("Highlight Last Move"), HighlightLastMoveProc},
605 {N_("Move Sound"), MoveSoundProc},
606 {N_("ICS Alarm"), IcsAlarmProc},
607 {N_("Old Save Style"), OldSaveStyleProc},
608 {N_("Periodic Updates"), PeriodicUpdatesProc},
609 {N_("Ponder Next Move"), PonderNextMoveProc},
610 {N_("Popup Exit Message"), PopupExitMessageProc},
611 {N_("Popup Move Errors"), PopupMoveErrorsProc},
612 {N_("Premove"), PremoveProc},
613 {N_("Quiet Play"), QuietPlayProc},
614 {N_("Show Coords"), ShowCoordsProc},
615 {N_("Show Thinking"), ShowThinkingProc},
616 {N_("Test Legality"), TestLegalityProc},
620 MenuItem helpMenu[] = {
621 {N_("Info XBoard"), InfoProc},
622 {N_("Man XBoard"), ManProc},
623 {"----", NothingProc},
624 {N_("Hint"), HintProc},
625 {N_("Book"), BookProc},
626 {"----", NothingProc},
627 {N_("About XBoard"), AboutProc},
632 {N_("File"), fileMenu},
633 {N_("Mode"), modeMenu},
634 {N_("Action"), actionMenu},
635 {N_("Step"), stepMenu},
636 {N_("Options"), optionsMenu},
637 {N_("Help"), helpMenu},
642 /* Label on pause button */
643 #define PAUSE_BUTTON N_("P")
644 MenuItem buttonBar[] = {
647 {PAUSE_BUTTON, PauseProc},
653 #define PIECE_MENU_SIZE 11
654 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
655 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
656 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
657 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
658 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
660 /* must be in same order as PieceMenuStrings! */
661 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
662 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
663 WhiteRook, WhiteQueen, WhiteKing,
664 (ChessSquare) 0, EmptySquare, ClearBoard },
665 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
666 BlackRook, BlackQueen, BlackKing,
667 (ChessSquare) 0, EmptySquare, ClearBoard },
670 #define DROP_MENU_SIZE 6
671 String dropMenuStrings[DROP_MENU_SIZE] = {
672 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
674 /* must be in same order as PieceMenuStrings! */
675 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
676 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
677 WhiteRook, WhiteQueen
685 DropMenuEnables dmEnables[] = {
703 { XtNborderWidth, 0 },
704 { XtNdefaultDistance, 0 },
708 { XtNborderWidth, 0 },
709 { XtNresizable, (XtArgVal) True },
713 { XtNborderWidth, 0 },
719 { XtNjustify, (XtArgVal) XtJustifyRight },
720 { XtNlabel, (XtArgVal) "..." },
721 { XtNresizable, (XtArgVal) True },
722 { XtNresize, (XtArgVal) False }
725 Arg messageArgs[] = {
726 { XtNjustify, (XtArgVal) XtJustifyLeft },
727 { XtNlabel, (XtArgVal) "..." },
728 { XtNresizable, (XtArgVal) True },
729 { XtNresize, (XtArgVal) False }
733 { XtNborderWidth, 0 },
734 { XtNjustify, (XtArgVal) XtJustifyLeft }
737 XtResource clientResources[] = {
738 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
739 XtOffset(AppDataPtr, whitePieceColor), XtRString,
741 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
742 XtOffset(AppDataPtr, blackPieceColor), XtRString,
744 { "lightSquareColor", "lightSquareColor", XtRString,
745 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
746 XtRString, LIGHT_SQUARE_COLOR },
747 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
748 XtOffset(AppDataPtr, darkSquareColor), XtRString,
750 { "highlightSquareColor", "highlightSquareColor", XtRString,
751 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
752 XtRString, HIGHLIGHT_SQUARE_COLOR },
753 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
754 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
755 XtRString, PREMOVE_HIGHLIGHT_COLOR },
756 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
757 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
758 (XtPointer) MOVES_PER_SESSION },
759 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
760 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
761 (XtPointer) TIME_INCREMENT },
762 { "initString", "initString", XtRString, sizeof(String),
763 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
764 { "secondInitString", "secondInitString", XtRString, sizeof(String),
765 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
766 { "firstComputerString", "firstComputerString", XtRString,
767 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
769 { "secondComputerString", "secondComputerString", XtRString,
770 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
772 { "firstChessProgram", "firstChessProgram", XtRString,
773 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
774 XtRString, FIRST_CHESS_PROGRAM },
775 { "secondChessProgram", "secondChessProgram", XtRString,
776 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
777 XtRString, SECOND_CHESS_PROGRAM },
778 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
779 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
780 XtRImmediate, (XtPointer) False },
781 { "noChessProgram", "noChessProgram", XtRBoolean,
782 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
783 XtRImmediate, (XtPointer) False },
784 { "firstHost", "firstHost", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
786 { "secondHost", "secondHost", XtRString, sizeof(String),
787 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
788 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
789 XtOffset(AppDataPtr, firstDirectory), XtRString, "" },
790 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
791 XtOffset(AppDataPtr, secondDirectory), XtRString, "" },
792 { "bitmapDirectory", "bitmapDirectory", XtRString,
793 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
795 { "remoteShell", "remoteShell", XtRString, sizeof(String),
796 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
797 { "remoteUser", "remoteUser", XtRString, sizeof(String),
798 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
799 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
800 XtOffset(AppDataPtr, timeDelay), XtRString,
801 (XtPointer) TIME_DELAY_QUOTE },
802 { "timeControl", "timeControl", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, timeControl), XtRString,
804 (XtPointer) TIME_CONTROL },
805 { "internetChessServerMode", "internetChessServerMode",
806 XtRBoolean, sizeof(Boolean),
807 XtOffset(AppDataPtr, icsActive), XtRImmediate,
809 { "internetChessServerHost", "internetChessServerHost",
810 XtRString, sizeof(String),
811 XtOffset(AppDataPtr, icsHost),
812 XtRString, (XtPointer) ICS_HOST },
813 { "internetChessServerPort", "internetChessServerPort",
814 XtRString, sizeof(String),
815 XtOffset(AppDataPtr, icsPort), XtRString,
816 (XtPointer) ICS_PORT },
817 { "internetChessServerCommPort", "internetChessServerCommPort",
818 XtRString, sizeof(String),
819 XtOffset(AppDataPtr, icsCommPort), XtRString,
821 { "internetChessServerLogonScript", "internetChessServerLogonScript",
822 XtRString, sizeof(String),
823 XtOffset(AppDataPtr, icsLogon), XtRString,
825 { "internetChessServerHelper", "internetChessServerHelper",
826 XtRString, sizeof(String),
827 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
828 { "internetChessServerInputBox", "internetChessServerInputBox",
829 XtRBoolean, sizeof(Boolean),
830 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
832 { "icsAlarm", "icsAlarm",
833 XtRBoolean, sizeof(Boolean),
834 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
836 { "icsAlarmTime", "icsAlarmTime",
838 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
840 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
841 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
843 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
845 { "gateway", "gateway", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, gateway), XtRString, "" },
847 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
848 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
849 { "loadGameIndex", "loadGameIndex",
851 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
853 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
854 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
855 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
856 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
857 XtRImmediate, (XtPointer) True },
858 { "autoSaveGames", "autoSaveGames", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
860 XtRImmediate, (XtPointer) False },
861 { "blindfold", "blindfold", XtRBoolean,
862 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
863 XtRImmediate, (XtPointer) False },
864 { "loadPositionFile", "loadPositionFile", XtRString,
865 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
867 { "loadPositionIndex", "loadPositionIndex",
869 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
871 { "savePositionFile", "savePositionFile", XtRString,
872 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
874 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
875 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
876 { "matchGames", "matchGames", XtRInt, sizeof(int),
877 XtOffset(AppDataPtr, matchGames), XtRImmediate,
879 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
880 XtOffset(AppDataPtr, monoMode), XtRImmediate,
882 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
883 XtOffset(AppDataPtr, debugMode), XtRImmediate,
885 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, clockMode), XtRImmediate,
888 { "boardSize", "boardSize", XtRString, sizeof(String),
889 XtOffset(AppDataPtr, boardSize), XtRString, "" },
890 { "searchTime", "searchTime", XtRString, sizeof(String),
891 XtOffset(AppDataPtr, searchTime), XtRString,
893 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
894 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
896 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
897 XtOffset(AppDataPtr, showCoords), XtRImmediate,
899 { "showJail", "showJail", XtRInt, sizeof(int),
900 XtOffset(AppDataPtr, showJail), XtRImmediate,
902 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
903 XtOffset(AppDataPtr, showThinking), XtRImmediate,
905 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
906 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
908 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
909 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
911 { "clockFont", "clockFont", XtRString, sizeof(String),
912 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
913 { "coordFont", "coordFont", XtRString, sizeof(String),
914 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
915 { "font", "font", XtRString, sizeof(String),
916 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
917 { "ringBellAfterMoves", "ringBellAfterMoves",
918 XtRBoolean, sizeof(Boolean),
919 XtOffset(AppDataPtr, ringBellAfterMoves),
920 XtRImmediate, (XtPointer) False },
921 { "autoCallFlag", "autoCallFlag", XtRBoolean,
922 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
923 XtRImmediate, (XtPointer) False },
924 { "autoFlipView", "autoFlipView", XtRBoolean,
925 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
926 XtRImmediate, (XtPointer) True },
927 { "autoObserve", "autoObserve", XtRBoolean,
928 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
929 XtRImmediate, (XtPointer) False },
930 { "autoComment", "autoComment", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
932 XtRImmediate, (XtPointer) False },
933 { "getMoveList", "getMoveList", XtRBoolean,
934 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
935 XtRImmediate, (XtPointer) True },
937 { "highlightDragging", "highlightDragging", XtRBoolean,
938 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
939 XtRImmediate, (XtPointer) False },
941 { "highlightLastMove", "highlightLastMove", XtRBoolean,
942 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
943 XtRImmediate, (XtPointer) False },
944 { "premove", "premove", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, premove),
946 XtRImmediate, (XtPointer) True },
947 { "testLegality", "testLegality", XtRBoolean,
948 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
949 XtRImmediate, (XtPointer) True },
950 { "flipView", "flipView", XtRBoolean,
951 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
952 XtRImmediate, (XtPointer) False },
953 { "cmail", "cmailGameName", XtRString, sizeof(String),
954 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
955 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
956 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
957 XtRImmediate, (XtPointer) False },
958 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
960 XtRImmediate, (XtPointer) False },
961 { "quietPlay", "quietPlay", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
963 XtRImmediate, (XtPointer) False },
964 { "titleInWindow", "titleInWindow", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
966 XtRImmediate, (XtPointer) False },
967 { "localLineEditing", "localLineEditing", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
969 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
971 { "zippyTalk", "zippyTalk", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
973 XtRImmediate, (XtPointer) ZIPPY_TALK },
974 { "zippyPlay", "zippyPlay", XtRBoolean,
975 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
976 XtRImmediate, (XtPointer) ZIPPY_PLAY },
977 { "zippyLines", "zippyLines", XtRString, sizeof(String),
978 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
979 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
980 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
981 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
982 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
983 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
984 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
985 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
986 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
987 ZIPPY_WRONG_PASSWORD },
988 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
990 { "zippyUseI", "zippyUseI", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
992 XtRImmediate, (XtPointer) ZIPPY_USE_I },
993 { "zippyBughouse", "zippyBughouse", XtRInt,
994 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
995 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
996 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
998 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
999 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1000 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1001 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1002 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1003 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1005 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1006 { "zippyAbort", "zippyAbort", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1008 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1009 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1010 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1011 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1012 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1013 (XtPointer) ZIPPY_MAX_GAMES },
1014 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1015 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1016 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1018 { "flashCount", "flashCount", XtRInt, sizeof(int),
1019 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1020 (XtPointer) FLASH_COUNT },
1021 { "flashRate", "flashRate", XtRInt, sizeof(int),
1022 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1023 (XtPointer) FLASH_RATE },
1024 { "pixmapDirectory", "pixmapDirectory", XtRString,
1025 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1027 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1028 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1029 (XtPointer) MS_LOGIN_DELAY },
1030 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1032 XtRImmediate, (XtPointer) False },
1033 { "colorShout", "colorShout", XtRString,
1034 sizeof(String), XtOffset(AppDataPtr, colorShout),
1035 XtRString, COLOR_SHOUT },
1036 { "colorSShout", "colorSShout", XtRString,
1037 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1038 XtRString, COLOR_SSHOUT },
1039 { "colorChannel1", "colorChannel1", XtRString,
1040 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1041 XtRString, COLOR_CHANNEL1 },
1042 { "colorChannel", "colorChannel", XtRString,
1043 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1044 XtRString, COLOR_CHANNEL },
1045 { "colorKibitz", "colorKibitz", XtRString,
1046 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1047 XtRString, COLOR_KIBITZ },
1048 { "colorTell", "colorTell", XtRString,
1049 sizeof(String), XtOffset(AppDataPtr, colorTell),
1050 XtRString, COLOR_TELL },
1051 { "colorChallenge", "colorChallenge", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1053 XtRString, COLOR_CHALLENGE },
1054 { "colorRequest", "colorRequest", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1056 XtRString, COLOR_REQUEST },
1057 { "colorSeek", "colorSeek", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1059 XtRString, COLOR_SEEK },
1060 { "colorNormal", "colorNormal", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1062 XtRString, COLOR_NORMAL },
1063 { "soundProgram", "soundProgram", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1065 XtRString, "play" },
1066 { "soundShout", "soundShout", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, soundShout),
1069 { "soundSShout", "soundSShout", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1072 { "soundChannel1", "soundChannel1", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1075 { "soundChannel", "soundChannel", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1078 { "soundKibitz", "soundKibitz", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1081 { "soundTell", "soundTell", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundTell),
1084 { "soundChallenge", "soundChallenge", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1087 { "soundRequest", "soundRequest", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1090 { "soundSeek", "soundSeek", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1093 { "soundMove", "soundMove", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundMove),
1096 { "soundIcsWin", "soundIcsWin", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1099 { "soundIcsLoss", "soundIcsLoss", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1102 { "soundIcsDraw", "soundIcsDraw", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1105 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1108 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1111 { "reuseFirst", "reuseFirst", XtRBoolean,
1112 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1113 XtRImmediate, (XtPointer) True },
1114 { "reuseSecond", "reuseSecond", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1116 XtRImmediate, (XtPointer) True },
1117 { "animateDragging", "animateDragging", XtRBoolean,
1118 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1119 XtRImmediate, (XtPointer) True },
1120 { "animateMoving", "animateMoving", XtRBoolean,
1121 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1122 XtRImmediate, (XtPointer) True },
1123 { "animateSpeed", "animateSpeed", XtRInt,
1124 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1125 XtRImmediate, (XtPointer)10 },
1126 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1128 XtRImmediate, (XtPointer) True },
1129 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1130 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1131 XtRImmediate, (XtPointer) False },
1132 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1133 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1134 XtRImmediate, (XtPointer)4 },
1135 { "initialMode", "initialMode", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, initialMode),
1137 XtRImmediate, (XtPointer) "" },
1138 { "variant", "variant", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, variant),
1140 XtRImmediate, (XtPointer) "normal" },
1141 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1142 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1143 XtRImmediate, (XtPointer)PROTOVER },
1144 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1145 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1146 XtRImmediate, (XtPointer)PROTOVER },
1147 { "showButtonBar", "showButtonBar", XtRBoolean,
1148 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1149 XtRImmediate, (XtPointer) True },
1150 /* icsEngineAnalyze */
1151 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean,
1152 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1153 XtRImmediate, (XtPointer) False },
1156 XrmOptionDescRec shellOptions[] = {
1157 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1158 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1159 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1160 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1161 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1162 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1163 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1164 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1165 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1166 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1167 { "-initString", "initString", XrmoptionSepArg, NULL },
1168 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1169 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1170 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1171 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1172 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1173 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1174 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1175 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1176 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1177 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1178 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1179 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1180 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1181 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1182 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1183 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1184 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1185 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1186 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1187 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1188 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1189 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1190 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1191 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1192 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1193 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1194 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1195 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1196 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1197 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1198 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1199 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1200 { "-internetChessServerMode", "internetChessServerMode",
1201 XrmoptionSepArg, NULL },
1202 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1203 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1204 { "-internetChessServerHost", "internetChessServerHost",
1205 XrmoptionSepArg, NULL },
1206 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1207 { "-internetChessServerPort", "internetChessServerPort",
1208 XrmoptionSepArg, NULL },
1209 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1210 { "-internetChessServerCommPort", "internetChessServerCommPort",
1211 XrmoptionSepArg, NULL },
1212 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1213 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1214 XrmoptionSepArg, NULL },
1215 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1216 { "-internetChessServerHelper", "internetChessServerHelper",
1217 XrmoptionSepArg, NULL },
1218 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1219 { "-internetChessServerInputBox", "internetChessServerInputBox",
1220 XrmoptionSepArg, NULL },
1221 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1222 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1223 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1224 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1225 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1226 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1227 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1228 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1229 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1230 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1231 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1232 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1233 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1234 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1235 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1236 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1237 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1238 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1239 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1240 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1241 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1242 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1243 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1244 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1245 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1246 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1247 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1248 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1249 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1250 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1251 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1252 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1253 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1254 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1255 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1256 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1257 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1258 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1259 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1260 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1261 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1262 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1263 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1264 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1265 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1266 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1267 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1268 { "-size", "boardSize", XrmoptionSepArg, NULL },
1269 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1270 { "-st", "searchTime", XrmoptionSepArg, NULL },
1271 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1272 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1273 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1274 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1275 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1277 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1278 { "-jail", "showJail", XrmoptionNoArg, "1" },
1279 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1280 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1282 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1283 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1284 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1285 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1286 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1287 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1288 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1289 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1290 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1291 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1292 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1293 { "-font", "font", XrmoptionSepArg, NULL },
1294 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1295 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1296 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1297 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1298 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1299 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1300 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1301 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1302 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1303 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1304 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1305 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1306 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1307 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1308 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1309 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1310 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1311 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1312 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1313 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1315 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1316 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1317 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1319 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1320 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1321 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1322 { "-premove", "premove", XrmoptionSepArg, NULL },
1323 { "-pre", "premove", XrmoptionNoArg, "True" },
1324 { "-xpre", "premove", XrmoptionNoArg, "False" },
1325 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1326 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1327 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1328 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1329 { "-flip", "flipView", XrmoptionNoArg, "True" },
1330 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1331 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1332 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1333 XrmoptionSepArg, NULL },
1334 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1335 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1336 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1337 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1338 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1339 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1340 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1341 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1342 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1343 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1344 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1346 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1347 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1348 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1349 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1350 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1351 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1352 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1353 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1354 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1355 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1356 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1357 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1358 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1359 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1360 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1361 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1362 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1363 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1364 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1365 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1366 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1367 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1368 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1369 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1370 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1371 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1372 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1373 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1374 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1375 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1377 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1378 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1379 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1380 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1381 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1382 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1383 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1384 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1385 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1386 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1387 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1388 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1389 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1390 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1391 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1392 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1393 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1394 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1395 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1396 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1397 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1398 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1399 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1400 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1401 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1402 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1403 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1404 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1405 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1406 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1407 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1408 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1409 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1410 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1411 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1412 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1413 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1414 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1415 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1416 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1417 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1418 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1419 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1420 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1421 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1422 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1423 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1424 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1425 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1426 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1427 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1428 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1429 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1430 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1431 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1432 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1433 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1434 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1435 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1436 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1437 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1438 { "-variant", "variant", XrmoptionSepArg, NULL },
1439 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1440 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1441 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1442 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1443 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1447 XtActionsRec boardActions[] = {
1448 { "DrawPosition", DrawPositionProc },
1449 { "HandleUserMove", HandleUserMove },
1450 { "AnimateUserMove", AnimateUserMove },
1451 { "FileNameAction", FileNameAction },
1452 { "AskQuestionProc", AskQuestionProc },
1453 { "AskQuestionReplyAction", AskQuestionReplyAction },
1454 { "PieceMenuPopup", PieceMenuPopup },
1455 { "WhiteClock", WhiteClock },
1456 { "BlackClock", BlackClock },
1457 { "Iconify", Iconify },
1458 { "ResetProc", ResetProc },
1459 { "LoadGameProc", LoadGameProc },
1460 { "LoadNextGameProc", LoadNextGameProc },
1461 { "LoadPrevGameProc", LoadPrevGameProc },
1462 { "LoadSelectedProc", LoadSelectedProc },
1463 { "ReloadGameProc", ReloadGameProc },
1464 { "LoadPositionProc", LoadPositionProc },
1465 { "LoadNextPositionProc", LoadNextPositionProc },
1466 { "LoadPrevPositionProc", LoadPrevPositionProc },
1467 { "ReloadPositionProc", ReloadPositionProc },
1468 { "CopyPositionProc", CopyPositionProc },
1469 { "PastePositionProc", PastePositionProc },
1470 { "CopyGameProc", CopyGameProc },
1471 { "PasteGameProc", PasteGameProc },
1472 { "SaveGameProc", SaveGameProc },
1473 { "SavePositionProc", SavePositionProc },
1474 { "MailMoveProc", MailMoveProc },
1475 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1476 { "QuitProc", QuitProc },
1477 { "MachineWhiteProc", MachineWhiteProc },
1478 { "MachineBlackProc", MachineBlackProc },
1479 { "AnalysisModeProc", AnalyzeModeProc },
1480 { "AnalyzeFileProc", AnalyzeFileProc },
1481 { "TwoMachinesProc", TwoMachinesProc },
1482 { "IcsClientProc", IcsClientProc },
1483 { "EditGameProc", EditGameProc },
1484 { "EditPositionProc", EditPositionProc },
1485 { "TrainingProc", EditPositionProc },
1486 { "ShowGameListProc", ShowGameListProc },
1487 { "ShowMoveListProc", HistoryShowProc},
1488 { "EditTagsProc", EditCommentProc },
1489 { "EditCommentProc", EditCommentProc },
1490 { "IcsAlarmProc", IcsAlarmProc },
1491 { "IcsInputBoxProc", IcsInputBoxProc },
1492 { "PauseProc", PauseProc },
1493 { "AcceptProc", AcceptProc },
1494 { "DeclineProc", DeclineProc },
1495 { "RematchProc", RematchProc },
1496 { "CallFlagProc", CallFlagProc },
1497 { "DrawProc", DrawProc },
1498 { "AdjournProc", AdjournProc },
1499 { "AbortProc", AbortProc },
1500 { "ResignProc", ResignProc },
1501 { "EnterKeyProc", EnterKeyProc },
1502 { "StopObservingProc", StopObservingProc },
1503 { "StopExaminingProc", StopExaminingProc },
1504 { "BackwardProc", BackwardProc },
1505 { "ForwardProc", ForwardProc },
1506 { "ToStartProc", ToStartProc },
1507 { "ToEndProc", ToEndProc },
1508 { "RevertProc", RevertProc },
1509 { "TruncateGameProc", TruncateGameProc },
1510 { "MoveNowProc", MoveNowProc },
1511 { "RetractMoveProc", RetractMoveProc },
1512 { "AlwaysQueenProc", AlwaysQueenProc },
1513 { "AnimateDraggingProc", AnimateDraggingProc },
1514 { "AnimateMovingProc", AnimateMovingProc },
1515 { "AutoflagProc", AutoflagProc },
1516 { "AutoflipProc", AutoflipProc },
1517 { "AutobsProc", AutobsProc },
1518 { "AutoraiseProc", AutoraiseProc },
1519 { "AutosaveProc", AutosaveProc },
1520 { "BlindfoldProc", BlindfoldProc },
1521 { "FlashMovesProc", FlashMovesProc },
1522 { "FlipViewProc", FlipViewProc },
1523 { "GetMoveListProc", GetMoveListProc },
1525 { "HighlightDraggingProc", HighlightDraggingProc },
1527 { "HighlightLastMoveProc", HighlightLastMoveProc },
1528 { "IcsAlarmProc", IcsAlarmProc },
1529 { "MoveSoundProc", MoveSoundProc },
1530 { "OldSaveStyleProc", OldSaveStyleProc },
1531 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1532 { "PonderNextMoveProc", PonderNextMoveProc },
1533 { "PopupExitMessageProc", PopupExitMessageProc },
1534 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1535 { "PremoveProc", PremoveProc },
1536 { "QuietPlayProc", QuietPlayProc },
1537 { "ShowCoordsProc", ShowCoordsProc },
1538 { "ShowThinkingProc", ShowThinkingProc },
1539 { "TestLegalityProc", TestLegalityProc },
1540 { "InfoProc", InfoProc },
1541 { "ManProc", ManProc },
1542 { "HintProc", HintProc },
1543 { "BookProc", BookProc },
1544 { "AboutGameProc", AboutGameProc },
1545 { "AboutProc", AboutProc },
1546 { "DebugProc", DebugProc },
1547 { "NothingProc", NothingProc },
1548 { "CommentPopDown", (XtActionProc) CommentPopDown },
1549 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1550 { "TagsPopDown", (XtActionProc) TagsPopDown },
1551 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1552 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1553 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1554 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1555 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1556 { "GameListPopDown", (XtActionProc) GameListPopDown },
1557 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1558 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1561 char globalTranslations[] =
1562 ":<Key>R: ResignProc() \n \
1563 :<Key>r: ResetProc() \n \
1564 :<Key>g: LoadGameProc() \n \
1565 :<Key>N: LoadNextGameProc() \n \
1566 :<Key>P: LoadPrevGameProc() \n \
1567 :<Key>Q: QuitProc() \n \
1568 :<Key>F: ToEndProc() \n \
1569 :<Key>f: ForwardProc() \n \
1570 :<Key>B: ToStartProc() \n \
1571 :<Key>b: BackwardProc() \n \
1572 :<Key>p: PauseProc() \n \
1573 :<Key>d: DrawProc() \n \
1574 :<Key>t: CallFlagProc() \n \
1575 :<Key>i: Iconify() \n \
1576 :<Key>c: Iconify() \n \
1577 :<Key>v: FlipViewProc() \n \
1578 <KeyDown>Control_L: BackwardProc() \n \
1579 <KeyUp>Control_L: ForwardProc() \n \
1580 <KeyDown>Control_R: BackwardProc() \n \
1581 <KeyUp>Control_R: ForwardProc() \n \
1582 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1583 \"Send to chess program:\",,1) \n \
1584 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1585 \"Send to second chess program:\",,2) \n";
1587 char boardTranslations[] =
1588 "<Btn1Down>: HandleUserMove() \n \
1589 <Btn1Up>: HandleUserMove() \n \
1590 <Btn1Motion>: AnimateUserMove() \n \
1591 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1592 PieceMenuPopup(menuB) \n \
1593 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1594 PieceMenuPopup(menuW) \n \
1595 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1596 PieceMenuPopup(menuW) \n \
1597 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1598 PieceMenuPopup(menuB) \n";
1600 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1601 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1603 char ICSInputTranslations[] =
1604 "<Key>Return: EnterKeyProc() \n";
1606 String xboardResources[] = {
1607 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1608 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1609 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1614 /* Max possible square size */
1615 #define MAXSQSIZE 256
1617 static int xpm_avail[MAXSQSIZE];
1619 #ifdef HAVE_DIR_STRUCT
1621 /* Extract piece size from filename */
1623 xpm_getsize(name, len, ext)
1634 if ((p=strchr(name, '.')) == NULL ||
1635 StrCaseCmp(p+1, ext) != 0)
1641 while (*p && isdigit(*p))
1648 /* Setup xpm_avail */
1650 xpm_getavail(dirname, ext)
1658 for (i=0; i<MAXSQSIZE; ++i)
1661 if (appData.debugMode)
1662 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1664 dir = opendir(dirname);
1667 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1668 programName, dirname);
1672 while ((ent=readdir(dir)) != NULL) {
1673 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1674 if (i > 0 && i < MAXSQSIZE)
1684 xpm_print_avail(fp, ext)
1690 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1691 for (i=1; i<MAXSQSIZE; ++i) {
1697 /* Return XPM piecesize closest to size */
1699 xpm_closest_to(dirname, size, ext)
1705 int sm_diff = MAXSQSIZE;
1709 xpm_getavail(dirname, ext);
1711 if (appData.debugMode)
1712 xpm_print_avail(stderr, ext);
1714 for (i=1; i<MAXSQSIZE; ++i) {
1717 diff = (diff<0) ? -diff : diff;
1718 if (diff < sm_diff) {
1726 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1732 #else /* !HAVE_DIR_STRUCT */
1733 /* If we are on a system without a DIR struct, we can't
1734 read the directory, so we can't collect a list of
1735 filenames, etc., so we can't do any size-fitting. */
1737 xpm_closest_to(dirname, size, ext)
1742 fprintf(stderr, _("\
1743 Warning: No DIR structure found on this system --\n\
1744 Unable to autosize for XPM/XIM pieces.\n\
1745 Please report this error to frankm@hiwaay.net.\n\
1746 Include system type & operating system in message.\n"));
1749 #endif /* HAVE_DIR_STRUCT */
1751 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1752 "magenta", "cyan", "white" };
1756 TextColors textColors[(int)NColorClasses];
1758 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1760 parse_color(str, which)
1764 char *p, buf[100], *d;
1767 if (strlen(str) > 99) /* watch bounds on buf */
1772 for (i=0; i<which; ++i) {
1779 /* Could be looking at something like:
1781 .. in which case we want to stop on a comma also */
1782 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1786 return -1; /* Use default for empty field */
1789 if (which == 2 || isdigit(*p))
1792 while (*p && isalpha(*p))
1797 for (i=0; i<8; ++i) {
1798 if (!StrCaseCmp(buf, cnames[i]))
1799 return which? (i+40) : (i+30);
1801 if (!StrCaseCmp(buf, "default")) return -1;
1803 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1808 parse_cpair(cc, str)
1812 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1813 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1818 /* bg and attr are optional */
1819 textColors[(int)cc].bg = parse_color(str, 1);
1820 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1821 textColors[(int)cc].attr = 0;
1827 /* Arrange to catch delete-window events */
1828 Atom wm_delete_window;
1830 CatchDeleteWindow(Widget w, String procname)
1833 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1834 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
1835 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1842 XtSetArg(args[0], XtNiconic, False);
1843 XtSetValues(shellWidget, args, 1);
1845 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1853 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1854 XSetWindowAttributes window_attributes;
1856 Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
1857 XrmValue vFrom, vTo;
1858 XtGeometryResult gres;
1861 int forceMono = False;
1863 setbuf(stdout, NULL);
1864 setbuf(stderr, NULL);
1867 programName = strrchr(argv[0], '/');
1868 if (programName == NULL)
1869 programName = argv[0];
1874 XtSetLanguageProc(NULL, NULL, NULL);
1875 bindtextdomain(PRODUCT, LOCALEDIR);
1876 textdomain(PRODUCT);
1880 XtAppInitialize(&appContext, "XBoard", shellOptions,
1881 XtNumber(shellOptions),
1882 &argc, argv, xboardResources, NULL, 0);
1884 fprintf(stderr, _("%s: unrecognized argument %s\n"),
1885 programName, argv[1]);
1889 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1892 if (chdir(chessDir) != 0) {
1893 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1900 if (p == NULL) p = "/tmp";
1901 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1902 gameCopyFilename = (char*) malloc(i);
1903 gamePasteFilename = (char*) malloc(i);
1904 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1905 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1907 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1908 clientResources, XtNumber(clientResources),
1911 if (appData.debugMode) {
1912 if ((debugFP = fopen("xboard.debug", "w")) == NULL) {
1913 printf(_("Failed to open file xboard.debug \n"));
1916 setbuf(debugFP, NULL);
1920 /* This feature does not work; animation needs a rewrite */
1921 appData.highlightDragging = FALSE;
1925 xDisplay = XtDisplay(shellWidget);
1926 xScreen = DefaultScreen(xDisplay);
1927 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1930 * Determine boardSize
1932 if (isdigit(appData.boardSize[0])) {
1933 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1934 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1935 &fontPxlSize, &smallLayout, &tinyLayout);
1937 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1938 programName, appData.boardSize);
1942 /* Find some defaults; use the nearest known size */
1943 SizeDefaults *szd, *nearest;
1944 int distance = 99999;
1945 nearest = szd = sizeDefaults;
1946 while (szd->name != NULL) {
1947 if (abs(szd->squareSize - squareSize) < distance) {
1949 distance = abs(szd->squareSize - squareSize);
1950 if (distance == 0) break;
1954 if (i < 2) lineGap = nearest->lineGap;
1955 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1956 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1957 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1958 if (i < 6) smallLayout = nearest->smallLayout;
1959 if (i < 7) tinyLayout = nearest->tinyLayout;
1962 SizeDefaults *szd = sizeDefaults;
1963 if (*appData.boardSize == NULLCHAR) {
1964 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1965 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1968 if (szd->name == NULL) szd--;
1970 while (szd->name != NULL &&
1971 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1972 if (szd->name == NULL) {
1973 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1974 programName, appData.boardSize);
1978 squareSize = szd->squareSize;
1979 lineGap = szd->lineGap;
1980 clockFontPxlSize = szd->clockFontPxlSize;
1981 coordFontPxlSize = szd->coordFontPxlSize;
1982 fontPxlSize = szd->fontPxlSize;
1983 smallLayout = szd->smallLayout;
1984 tinyLayout = szd->tinyLayout;
1987 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1988 if (strlen(appData.pixmapDirectory) > 0) {
1989 p = ExpandPathName(appData.pixmapDirectory);
1991 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1992 appData.pixmapDirectory);
1995 if (appData.debugMode) {
1996 fprintf(stderr, _("\
1997 XBoard square size (hint): %d\n\
1998 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2000 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2001 if (appData.debugMode) {
2002 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2006 boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
2007 if (appData.showJail == 1) {
2008 /* Jail on top and bottom */
2009 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2010 XtSetArg(boardArgs[2], XtNheight,
2011 boardWidth + 2*(lineGap + squareSize));
2012 } else if (appData.showJail == 2) {
2014 XtSetArg(boardArgs[1], XtNwidth,
2015 boardWidth + 2*(lineGap + squareSize));
2016 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2019 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2020 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2024 * Determine what fonts to use.
2026 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2027 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2028 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2029 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2030 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2031 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2032 appData.font = FindFont(appData.font, fontPxlSize);
2034 xdb = XtDatabase(xDisplay);
2035 XrmPutStringResource(&xdb, "*font", appData.font);
2038 * Detect if there are not enough colors available and adapt.
2040 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2041 appData.monoMode = True;
2044 if (!appData.monoMode) {
2045 vFrom.addr = (caddr_t) appData.lightSquareColor;
2046 vFrom.size = strlen(appData.lightSquareColor);
2047 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2048 if (vTo.addr == NULL) {
2049 appData.monoMode = True;
2052 lightSquareColor = *(Pixel *) vTo.addr;
2055 if (!appData.monoMode) {
2056 vFrom.addr = (caddr_t) appData.darkSquareColor;
2057 vFrom.size = strlen(appData.darkSquareColor);
2058 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2059 if (vTo.addr == NULL) {
2060 appData.monoMode = True;
2063 darkSquareColor = *(Pixel *) vTo.addr;
2066 if (!appData.monoMode) {
2067 vFrom.addr = (caddr_t) appData.whitePieceColor;
2068 vFrom.size = strlen(appData.whitePieceColor);
2069 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2070 if (vTo.addr == NULL) {
2071 appData.monoMode = True;
2074 whitePieceColor = *(Pixel *) vTo.addr;
2077 if (!appData.monoMode) {
2078 vFrom.addr = (caddr_t) appData.blackPieceColor;
2079 vFrom.size = strlen(appData.blackPieceColor);
2080 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2081 if (vTo.addr == NULL) {
2082 appData.monoMode = True;
2085 blackPieceColor = *(Pixel *) vTo.addr;
2089 if (!appData.monoMode) {
2090 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2091 vFrom.size = strlen(appData.highlightSquareColor);
2092 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2093 if (vTo.addr == NULL) {
2094 appData.monoMode = True;
2097 highlightSquareColor = *(Pixel *) vTo.addr;
2101 if (!appData.monoMode) {
2102 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2103 vFrom.size = strlen(appData.premoveHighlightColor);
2104 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2105 if (vTo.addr == NULL) {
2106 appData.monoMode = True;
2109 premoveHighlightColor = *(Pixel *) vTo.addr;
2114 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2118 if (appData.monoMode && appData.debugMode) {
2119 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2120 (unsigned long) XWhitePixel(xDisplay, xScreen),
2121 (unsigned long) XBlackPixel(xDisplay, xScreen));
2124 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2125 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2126 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2127 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2128 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2129 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2130 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2131 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2132 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2133 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2135 if (appData.colorize) {
2137 _("%s: can't parse color names; disabling colorization\n"),
2140 appData.colorize = FALSE;
2142 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2143 textColors[ColorNone].attr = 0;
2145 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2151 layoutName = "tinyLayout";
2152 } else if (smallLayout) {
2153 layoutName = "smallLayout";
2155 layoutName = "normalLayout";
2157 /* Outer layoutWidget is there only to provide a name for use in
2158 resources that depend on the layout style */
2160 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2161 layoutArgs, XtNumber(layoutArgs));
2163 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2164 formArgs, XtNumber(formArgs));
2165 XtSetArg(args[0], XtNdefaultDistance, &sep);
2166 XtGetValues(formWidget, args, 1);
2169 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2171 widgetList[j++] = whiteTimerWidget =
2172 XtCreateWidget("whiteTime", labelWidgetClass,
2173 formWidget, timerArgs, XtNumber(timerArgs));
2174 XtSetArg(args[0], XtNfont, clockFontStruct);
2175 XtSetValues(whiteTimerWidget, args, 1);
2177 widgetList[j++] = blackTimerWidget =
2178 XtCreateWidget("blackTime", labelWidgetClass,
2179 formWidget, timerArgs, XtNumber(timerArgs));
2180 XtSetArg(args[0], XtNfont, clockFontStruct);
2181 XtSetValues(blackTimerWidget, args, 1);
2183 if (appData.titleInWindow) {
2184 widgetList[j++] = titleWidget =
2185 XtCreateWidget("title", labelWidgetClass, formWidget,
2186 titleArgs, XtNumber(titleArgs));
2189 if (appData.showButtonBar) {
2190 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2193 widgetList[j++] = messageWidget =
2194 XtCreateWidget("message", labelWidgetClass, formWidget,
2195 messageArgs, XtNumber(messageArgs));
2197 widgetList[j++] = boardWidget =
2198 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2199 XtNumber(boardArgs));
2201 XtManageChildren(widgetList, j);
2203 timerWidth = (boardWidth - sep) / 2;
2204 XtSetArg(args[0], XtNwidth, timerWidth);
2205 XtSetValues(whiteTimerWidget, args, 1);
2206 XtSetValues(blackTimerWidget, args, 1);
2208 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2209 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2210 XtGetValues(whiteTimerWidget, args, 2);
2212 if (appData.showButtonBar) {
2213 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2214 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2215 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2219 * formWidget uses these constraints but they are stored
2223 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2224 XtSetValues(menuBarWidget, args, i);
2225 if (appData.titleInWindow) {
2228 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2229 XtSetValues(whiteTimerWidget, args, i);
2231 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2232 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2233 XtSetValues(blackTimerWidget, args, i);
2235 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2236 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2237 XtSetValues(titleWidget, args, i);
2239 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2240 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2241 XtSetValues(messageWidget, args, i);
2242 if (appData.showButtonBar) {
2244 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2245 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2246 XtSetValues(buttonBarWidget, args, i);
2250 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2251 XtSetValues(whiteTimerWidget, args, i);
2253 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2254 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2255 XtSetValues(blackTimerWidget, args, i);
2257 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2258 XtSetValues(titleWidget, args, i);
2260 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2261 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2262 XtSetValues(messageWidget, args, i);
2263 if (appData.showButtonBar) {
2265 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2266 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2267 XtSetValues(buttonBarWidget, args, i);
2272 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2273 XtSetValues(whiteTimerWidget, args, i);
2275 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2276 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2277 XtSetValues(blackTimerWidget, args, i);
2279 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2280 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2281 XtSetValues(messageWidget, args, i);
2282 if (appData.showButtonBar) {
2284 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2285 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2286 XtSetValues(buttonBarWidget, args, i);
2290 XtSetArg(args[0], XtNfromVert, messageWidget);
2291 XtSetValues(boardWidget, args, 1);
2293 XtRealizeWidget(shellWidget);
2296 * Correct the width of the message and title widgets.
2297 * It is not known why some systems need the extra fudge term.
2298 * The value "2" is probably larger than needed.
2300 XawFormDoLayout(formWidget, False);
2301 #define WIDTH_FUDGE 2
2303 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2304 XtSetArg(args[i], XtNheight, &h); i++;
2305 XtGetValues(messageWidget, args, i);
2306 if (appData.showButtonBar) {
2308 XtSetArg(args[i], XtNwidth, &w); i++;
2309 XtGetValues(buttonBarWidget, args, i);
2310 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2312 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2315 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2316 if (gres != XtGeometryYes && appData.debugMode) {
2317 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2318 programName, gres, w, h, wr, hr);
2321 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2322 /* The size used for the child widget in layout lags one resize behind
2323 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2325 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2326 if (gres != XtGeometryYes && appData.debugMode) {
2327 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2328 programName, gres, w, h, wr, hr);
2332 if (appData.titleInWindow) {
2334 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2335 XtSetArg(args[i], XtNheight, &h); i++;
2336 XtGetValues(titleWidget, args, i);
2338 w = boardWidth - 2*bor;
2340 XtSetArg(args[0], XtNwidth, &w);
2341 XtGetValues(menuBarWidget, args, 1);
2342 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2345 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2346 if (gres != XtGeometryYes && appData.debugMode) {
2348 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2349 programName, gres, w, h, wr, hr);
2352 XawFormDoLayout(formWidget, True);
2354 xBoardWindow = XtWindow(boardWidget);
2357 * Create X checkmark bitmap and initialize option menu checks.
2359 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2360 checkmark_bits, checkmark_width, checkmark_height);
2361 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2362 if (appData.alwaysPromoteToQueen) {
2363 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2366 if (appData.animateDragging) {
2367 XtSetValues(XtNameToWidget(menuBarWidget,
2368 "menuOptions.Animate Dragging"),
2371 if (appData.animate) {
2372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2375 if (appData.autoComment) {
2376 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2379 if (appData.autoCallFlag) {
2380 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2383 if (appData.autoFlipView) {
2384 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2387 if (appData.autoObserve) {
2388 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2391 if (appData.autoRaiseBoard) {
2392 XtSetValues(XtNameToWidget(menuBarWidget,
2393 "menuOptions.Auto Raise Board"), args, 1);
2395 if (appData.autoSaveGames) {
2396 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2399 if (appData.saveGameFile[0] != NULLCHAR) {
2400 /* Can't turn this off from menu */
2401 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2403 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2407 if (appData.blindfold) {
2408 XtSetValues(XtNameToWidget(menuBarWidget,
2409 "menuOptions.Blindfold"), args, 1);
2411 if (appData.flashCount > 0) {
2412 XtSetValues(XtNameToWidget(menuBarWidget,
2413 "menuOptions.Flash Moves"),
2416 if (appData.getMoveList) {
2417 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2421 if (appData.highlightDragging) {
2422 XtSetValues(XtNameToWidget(menuBarWidget,
2423 "menuOptions.Highlight Dragging"),
2427 if (appData.highlightLastMove) {
2428 XtSetValues(XtNameToWidget(menuBarWidget,
2429 "menuOptions.Highlight Last Move"),
2432 if (appData.icsAlarm) {
2433 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2436 if (appData.ringBellAfterMoves) {
2437 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2440 if (appData.oldSaveStyle) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Old Save Style"), args, 1);
2444 if (appData.periodicUpdates) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Periodic Updates"), args, 1);
2448 if (appData.ponderNextMove) {
2449 XtSetValues(XtNameToWidget(menuBarWidget,
2450 "menuOptions.Ponder Next Move"), args, 1);
2452 if (appData.popupExitMessage) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,
2454 "menuOptions.Popup Exit Message"), args, 1);
2456 if (appData.popupMoveErrors) {
2457 XtSetValues(XtNameToWidget(menuBarWidget,
2458 "menuOptions.Popup Move Errors"), args, 1);
2460 if (appData.premove) {
2461 XtSetValues(XtNameToWidget(menuBarWidget,
2462 "menuOptions.Premove"), args, 1);
2464 if (appData.quietPlay) {
2465 XtSetValues(XtNameToWidget(menuBarWidget,
2466 "menuOptions.Quiet Play"), args, 1);
2468 if (appData.showCoords) {
2469 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2472 if (appData.showThinking) {
2473 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2476 if (appData.testLegality) {
2477 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2484 ReadBitmap(&wIconPixmap, "icon_white.bm",
2485 icon_white_bits, icon_white_width, icon_white_height);
2486 ReadBitmap(&bIconPixmap, "icon_black.bm",
2487 icon_black_bits, icon_black_width, icon_black_height);
2488 iconPixmap = wIconPixmap;
2490 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2491 XtSetValues(shellWidget, args, i);
2494 * Create a cursor for the board widget.
2496 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2497 XChangeWindowAttributes(xDisplay, xBoardWindow,
2498 CWCursor, &window_attributes);
2501 * Inhibit shell resizing.
2503 shellArgs[0].value = (XtArgVal) &w;
2504 shellArgs[1].value = (XtArgVal) &h;
2505 XtGetValues(shellWidget, shellArgs, 2);
2506 shellArgs[4].value = shellArgs[2].value = w;
2507 shellArgs[5].value = shellArgs[3].value = h;
2508 XtSetValues(shellWidget, &shellArgs[2], 4);
2510 CatchDeleteWindow(shellWidget, "QuitProc");
2515 if (appData.bitmapDirectory[0] != NULLCHAR) {
2522 /* Create regular pieces */
2523 if (!useImages) CreatePieces();
2528 if (appData.animate || appData.animateDragging)
2531 XtAugmentTranslations(formWidget,
2532 XtParseTranslationTable(globalTranslations));
2533 XtAugmentTranslations(boardWidget,
2534 XtParseTranslationTable(boardTranslations));
2535 XtAugmentTranslations(whiteTimerWidget,
2536 XtParseTranslationTable(whiteTranslations));
2537 XtAugmentTranslations(blackTimerWidget,
2538 XtParseTranslationTable(blackTranslations));
2540 /* Why is the following needed on some versions of X instead
2541 * of a translation? */
2542 XtAddEventHandler(boardWidget, ExposureMask, False,
2543 (XtEventHandler) EventProc, NULL);
2548 if (errorExitStatus == -1) {
2549 if (appData.icsActive) {
2550 /* We now wait until we see "login:" from the ICS before
2551 sending the logon script (problems with timestamp otherwise) */
2552 /*ICSInitScript();*/
2553 if (appData.icsInputBox) ICSInputBoxPopUp();
2556 signal(SIGINT, IntSigHandler);
2557 signal(SIGTERM, IntSigHandler);
2558 if (*appData.cmailGameName != NULLCHAR) {
2559 signal(SIGUSR1, CmailSigHandler);
2563 XtAppMainLoop(appContext);
2564 if (appData.debugMode) fclose(debugFP);
2572 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2573 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2575 unlink(gameCopyFilename);
2576 unlink(gamePasteFilename);
2587 CmailSigHandler(sig)
2593 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2595 /* Activate call-back function CmailSigHandlerCallBack() */
2596 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2598 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2602 CmailSigHandlerCallBack(isr, closure, message, count, error)
2610 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2612 /**** end signal code ****/
2622 f = fopen(appData.icsLogon, "r");
2628 strcat(buf, appData.icsLogon);
2629 f = fopen(buf, "r");
2633 ProcessICSInitScript(f);
2640 EditCommentPopDown();
2651 SetMenuEnables(enab)
2655 if (!menuBarWidget) return;
2656 while (enab->name != NULL) {
2657 w = XtNameToWidget(menuBarWidget, enab->name);
2659 DisplayError(enab->name, 0);
2661 XtSetSensitive(w, enab->value);
2667 Enables icsEnables[] = {
2668 { "menuFile.Mail Move", False },
2669 { "menuFile.Reload CMail Message", False },
2670 { "menuMode.Machine Black", False },
2671 { "menuMode.Machine White", False },
2672 { "menuMode.Analysis Mode", False },
2673 { "menuMode.Analyze File", False },
2674 { "menuMode.Two Machines", False },
2676 { "menuHelp.Hint", False },
2677 { "menuHelp.Book", False },
2678 { "menuStep.Move Now", False },
2679 { "menuOptions.Periodic Updates", False },
2680 { "menuOptions.Show Thinking", False },
2681 { "menuOptions.Ponder Next Move", False },
2686 Enables ncpEnables[] = {
2687 { "menuFile.Mail Move", False },
2688 { "menuFile.Reload CMail Message", False },
2689 { "menuMode.Machine White", False },
2690 { "menuMode.Machine Black", False },
2691 { "menuMode.Analysis Mode", False },
2692 { "menuMode.Analyze File", False },
2693 { "menuMode.Two Machines", False },
2694 { "menuMode.ICS Client", False },
2695 { "menuMode.ICS Input Box", False },
2696 { "Action", False },
2697 { "menuStep.Revert", False },
2698 { "menuStep.Move Now", False },
2699 { "menuStep.Retract Move", False },
2700 { "menuOptions.Auto Comment", False },
2701 { "menuOptions.Auto Flag", False },
2702 { "menuOptions.Auto Flip View", False },
2703 { "menuOptions.Auto Observe", False },
2704 { "menuOptions.Auto Raise Board", False },
2705 { "menuOptions.Get Move List", False },
2706 { "menuOptions.ICS Alarm", False },
2707 { "menuOptions.Move Sound", False },
2708 { "menuOptions.Quiet Play", False },
2709 { "menuOptions.Show Thinking", False },
2710 { "menuOptions.Periodic Updates", False },
2711 { "menuOptions.Ponder Next Move", False },
2712 { "menuHelp.Hint", False },
2713 { "menuHelp.Book", False },
2717 Enables gnuEnables[] = {
2718 { "menuMode.ICS Client", False },
2719 { "menuMode.ICS Input Box", False },
2720 { "menuAction.Accept", False },
2721 { "menuAction.Decline", False },
2722 { "menuAction.Rematch", False },
2723 { "menuAction.Adjourn", False },
2724 { "menuAction.Stop Examining", False },
2725 { "menuAction.Stop Observing", False },
2726 { "menuStep.Revert", False },
2727 { "menuOptions.Auto Comment", False },
2728 { "menuOptions.Auto Observe", False },
2729 { "menuOptions.Auto Raise Board", False },
2730 { "menuOptions.Get Move List", False },
2731 { "menuOptions.Premove", False },
2732 { "menuOptions.Quiet Play", False },
2734 /* The next two options rely on SetCmailMode being called *after* */
2735 /* SetGNUMode so that when GNU is being used to give hints these */
2736 /* menu options are still available */
2738 { "menuFile.Mail Move", False },
2739 { "menuFile.Reload CMail Message", False },
2743 Enables cmailEnables[] = {
2745 { "menuAction.Call Flag", False },
2746 { "menuAction.Draw", True },
2747 { "menuAction.Adjourn", False },
2748 { "menuAction.Abort", False },
2749 { "menuAction.Stop Observing", False },
2750 { "menuAction.Stop Examining", False },
2751 { "menuFile.Mail Move", True },
2752 { "menuFile.Reload CMail Message", True },
2756 Enables trainingOnEnables[] = {
2757 { "menuMode.Edit Comment", False },
2758 { "menuMode.Pause", False },
2759 { "menuStep.Forward", False },
2760 { "menuStep.Backward", False },
2761 { "menuStep.Forward to End", False },
2762 { "menuStep.Back to Start", False },
2763 { "menuStep.Move Now", False },
2764 { "menuStep.Truncate Game", False },
2768 Enables trainingOffEnables[] = {
2769 { "menuMode.Edit Comment", True },
2770 { "menuMode.Pause", True },
2771 { "menuStep.Forward", True },
2772 { "menuStep.Backward", True },
2773 { "menuStep.Forward to End", True },
2774 { "menuStep.Back to Start", True },
2775 { "menuStep.Move Now", True },
2776 { "menuStep.Truncate Game", True },
2780 Enables machineThinkingEnables[] = {
2781 { "menuFile.Load Game", False },
2782 { "menuFile.Load Next Game", False },
2783 { "menuFile.Load Previous Game", False },
2784 { "menuFile.Reload Same Game", False },
2785 { "menuFile.Paste Game", False },
2786 { "menuFile.Load Position", False },
2787 { "menuFile.Load Next Position", False },
2788 { "menuFile.Load Previous Position", False },
2789 { "menuFile.Reload Same Position", False },
2790 { "menuFile.Paste Position", False },
2791 { "menuMode.Machine White", False },
2792 { "menuMode.Machine Black", False },
2793 { "menuMode.Two Machines", False },
2794 { "menuStep.Retract Move", False },
2798 Enables userThinkingEnables[] = {
2799 { "menuFile.Load Game", True },
2800 { "menuFile.Load Next Game", True },
2801 { "menuFile.Load Previous Game", True },
2802 { "menuFile.Reload Same Game", True },
2803 { "menuFile.Paste Game", True },
2804 { "menuFile.Load Position", True },
2805 { "menuFile.Load Next Position", True },
2806 { "menuFile.Load Previous Position", True },
2807 { "menuFile.Reload Same Position", True },
2808 { "menuFile.Paste Position", True },
2809 { "menuMode.Machine White", True },
2810 { "menuMode.Machine Black", True },
2811 { "menuMode.Two Machines", True },
2812 { "menuStep.Retract Move", True },
2818 SetMenuEnables(icsEnables);
2821 /* icsEngineAnalyze */
2822 if (appData.zippyPlay && !appData.noChessProgram)
2823 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2830 SetMenuEnables(ncpEnables);
2836 SetMenuEnables(gnuEnables);
2842 SetMenuEnables(cmailEnables);
2848 SetMenuEnables(trainingOnEnables);
2849 if (appData.showButtonBar) {
2850 XtSetSensitive(buttonBarWidget, False);
2856 SetTrainingModeOff()
2858 SetMenuEnables(trainingOffEnables);
2859 if (appData.showButtonBar) {
2860 XtSetSensitive(buttonBarWidget, True);
2865 SetUserThinkingEnables()
2867 if (appData.noChessProgram) return;
2868 SetMenuEnables(userThinkingEnables);
2872 SetMachineThinkingEnables()
2874 if (appData.noChessProgram) return;
2875 SetMenuEnables(machineThinkingEnables);
2877 case MachinePlaysBlack:
2878 case MachinePlaysWhite:
2879 case TwoMachinesPlay:
2880 XtSetSensitive(XtNameToWidget(menuBarWidget,
2881 ModeToWidgetName(gameMode)), True);
2888 #define Abs(n) ((n)<0 ? -(n) : (n))
2891 * Find a font that matches "pattern" that is as close as
2892 * possible to the targetPxlSize. Prefer fonts that are k
2893 * pixels smaller to fonts that are k pixels larger. The
2894 * pattern must be in the X Consortium standard format,
2895 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2896 * The return value should be freed with XtFree when no
2899 char *FindFont(pattern, targetPxlSize)
2903 char **fonts, *p, *best, *scalable, *scalableTail;
2904 int i, j, nfonts, minerr, err, pxlSize;
2907 char **missing_list;
2909 char *def_string, *base_fnt_lst, strInt[3];
2911 XFontStruct **fnt_list;
2913 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2914 sprintf(strInt, "%d", targetPxlSize);
2915 p = strstr(pattern, "--");
2916 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2917 strcat(base_fnt_lst, strInt);
2918 strcat(base_fnt_lst, strchr(p + 2, '-'));
2920 if ((fntSet = XCreateFontSet(xDisplay,
2924 &def_string)) == NULL) {
2926 fprintf(stderr, _("Unable to create font set.\n"));
2930 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2932 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2934 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2935 programName, pattern);
2943 for (i=0; i<nfonts; i++) {
2946 if (*p != '-') continue;
2948 if (*p == NULLCHAR) break;
2949 if (*p++ == '-') j++;
2951 if (j < 7) continue;
2954 scalable = fonts[i];
2957 err = pxlSize - targetPxlSize;
2958 if (Abs(err) < Abs(minerr) ||
2959 (minerr > 0 && err < 0 && -err == minerr)) {
2965 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2966 /* If the error is too big and there is a scalable font,
2967 use the scalable font. */
2968 int headlen = scalableTail - scalable;
2969 p = (char *) XtMalloc(strlen(scalable) + 10);
2970 while (isdigit(*scalableTail)) scalableTail++;
2971 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2973 p = (char *) XtMalloc(strlen(best) + 1);
2976 if (appData.debugMode) {
2977 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2978 pattern, targetPxlSize, p);
2981 if (missing_count > 0)
2982 XFreeStringList(missing_list);
2983 XFreeFontSet(xDisplay, fntSet);
2985 XFreeFontNames(fonts);
2992 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2993 | GCBackground | GCFunction | GCPlaneMask;
2994 XGCValues gc_values;
2997 gc_values.plane_mask = AllPlanes;
2998 gc_values.line_width = lineGap;
2999 gc_values.line_style = LineSolid;
3000 gc_values.function = GXcopy;
3002 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3003 gc_values.background = XBlackPixel(xDisplay, xScreen);
3004 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3006 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3007 gc_values.background = XWhitePixel(xDisplay, xScreen);
3008 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3009 XSetFont(xDisplay, coordGC, coordFontID);
3011 if (appData.monoMode) {
3012 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3013 gc_values.background = XWhitePixel(xDisplay, xScreen);
3014 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3016 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3017 gc_values.background = XBlackPixel(xDisplay, xScreen);
3018 lightSquareGC = wbPieceGC
3019 = XtGetGC(shellWidget, value_mask, &gc_values);
3021 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3022 gc_values.background = XWhitePixel(xDisplay, xScreen);
3023 darkSquareGC = bwPieceGC
3024 = XtGetGC(shellWidget, value_mask, &gc_values);
3026 if (DefaultDepth(xDisplay, xScreen) == 1) {
3027 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3028 gc_values.function = GXcopyInverted;
3029 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3030 gc_values.function = GXcopy;
3031 if (XBlackPixel(xDisplay, xScreen) == 1) {
3032 bwPieceGC = darkSquareGC;
3033 wbPieceGC = copyInvertedGC;
3035 bwPieceGC = copyInvertedGC;
3036 wbPieceGC = lightSquareGC;
3040 gc_values.foreground = highlightSquareColor;
3041 gc_values.background = highlightSquareColor;
3042 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3044 gc_values.foreground = premoveHighlightColor;
3045 gc_values.background = premoveHighlightColor;
3046 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3048 gc_values.foreground = lightSquareColor;
3049 gc_values.background = darkSquareColor;
3050 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3052 gc_values.foreground = darkSquareColor;
3053 gc_values.background = lightSquareColor;
3054 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3056 gc_values.foreground = jailSquareColor;
3057 gc_values.background = jailSquareColor;
3058 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3060 gc_values.foreground = whitePieceColor;
3061 gc_values.background = darkSquareColor;
3062 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3064 gc_values.foreground = whitePieceColor;
3065 gc_values.background = lightSquareColor;
3066 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3068 gc_values.foreground = whitePieceColor;
3069 gc_values.background = jailSquareColor;
3070 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3072 gc_values.foreground = blackPieceColor;
3073 gc_values.background = darkSquareColor;
3074 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 gc_values.foreground = blackPieceColor;
3077 gc_values.background = lightSquareColor;
3078 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3080 gc_values.foreground = blackPieceColor;
3081 gc_values.background = jailSquareColor;
3082 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3086 void loadXIM(xim, xmask, filename, dest, mask)
3099 fp = fopen(filename, "rb");
3101 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3108 for (y=0; y<h; ++y) {
3109 for (x=0; x<h; ++x) {
3114 XPutPixel(xim, x, y, blackPieceColor);
3116 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3119 XPutPixel(xim, x, y, darkSquareColor);
3121 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3124 XPutPixel(xim, x, y, whitePieceColor);
3126 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3129 XPutPixel(xim, x, y, lightSquareColor);
3131 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3137 /* create Pixmap of piece */
3138 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3140 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3143 /* create Pixmap of clipmask
3144 Note: We assume the white/black pieces have the same
3145 outline, so we make only 6 masks. This is okay
3146 since the XPM clipmask routines do the same. */
3148 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3150 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3153 /* now create the 1-bit version */
3154 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3157 values.foreground = 1;
3158 values.background = 0;
3160 /* Don't use XtGetGC, not read only */
3161 maskGC = XCreateGC(xDisplay, *mask,
3162 GCForeground | GCBackground, &values);
3163 XCopyPlane(xDisplay, temp, *mask, maskGC,
3164 0, 0, squareSize, squareSize, 0, 0, 1);
3165 XFreePixmap(xDisplay, temp);
3169 void CreateXIMPieces()
3174 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3179 /* The XSynchronize calls were copied from CreatePieces.
3180 Not sure if needed, but can't hurt */
3181 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3184 /* temp needed by loadXIM() */
3185 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3186 0, 0, ss, ss, AllPlanes, XYPixmap);
3188 if (strlen(appData.pixmapDirectory) == 0) {
3192 if (appData.monoMode) {
3193 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3197 fprintf(stderr, _("\nLoading XIMs...\n"));
3199 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3200 fprintf(stderr, "%d", piece+1);
3201 for (kind=0; kind<4; kind++) {
3202 fprintf(stderr, ".");
3203 sprintf(buf, "%s/%c%s%u.xim",
3204 ExpandPathName(appData.pixmapDirectory),
3205 ToLower(PieceToChar((ChessSquare)piece)),
3207 ximPieceBitmap[kind][piece] =
3208 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3209 0, 0, ss, ss, AllPlanes, XYPixmap);
3210 if (appData.debugMode)
3211 fprintf(stderr, _("(File:%s:) "), buf);
3212 loadXIM(ximPieceBitmap[kind][piece],
3214 &(xpmPieceBitmap[kind][piece]),
3215 &(ximMaskPm[piece%6]));
3217 fprintf(stderr," ");
3219 /* Load light and dark squares */
3220 /* If the LSQ and DSQ pieces don't exist, we will
3221 draw them with solid squares. */
3222 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3223 if (access(buf, 0) != 0) {
3227 fprintf(stderr, _("light square "));
3229 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3230 0, 0, ss, ss, AllPlanes, XYPixmap);
3231 if (appData.debugMode)
3232 fprintf(stderr, _("(File:%s:) "), buf);
3234 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3235 fprintf(stderr, _("dark square "));
3236 sprintf(buf, "%s/dsq%u.xim",
3237 ExpandPathName(appData.pixmapDirectory), ss);
3238 if (appData.debugMode)
3239 fprintf(stderr, _("(File:%s:) "), buf);
3241 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3242 0, 0, ss, ss, AllPlanes, XYPixmap);
3243 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3244 xpmJailSquare = xpmLightSquare;
3246 fprintf(stderr, _("Done.\n"));
3248 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3252 void CreateXPMPieces()
3256 u_int ss = squareSize;
3258 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3259 XpmColorSymbol symbols[4];
3262 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3263 if (appData.debugMode) {
3264 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3265 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3269 /* The XSynchronize calls were copied from CreatePieces.
3270 Not sure if needed, but can't hurt */
3271 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3273 /* Setup translations so piece colors match square colors */
3274 symbols[0].name = "light_piece";
3275 symbols[0].value = appData.whitePieceColor;
3276 symbols[1].name = "dark_piece";
3277 symbols[1].value = appData.blackPieceColor;
3278 symbols[2].name = "light_square";
3279 symbols[2].value = appData.lightSquareColor;
3280 symbols[3].name = "dark_square";
3281 symbols[3].value = appData.darkSquareColor;
3283 attr.valuemask = XpmColorSymbols;
3284 attr.colorsymbols = symbols;
3285 attr.numsymbols = 4;
3287 if (appData.monoMode) {
3288 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3292 if (strlen(appData.pixmapDirectory) == 0) {
3293 XpmPieces* pieces = builtInXpms;
3296 while (pieces->size != squareSize && pieces->size) pieces++;
3297 if (!pieces->size) {
3298 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3301 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3302 for (kind=0; kind<4; kind++) {
3304 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3305 pieces->xpm[piece][kind],
3306 &(xpmPieceBitmap[kind][piece]),
3307 NULL, &attr)) != 0) {
3308 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3315 xpmJailSquare = xpmLightSquare;
3319 fprintf(stderr, _("\nLoading XPMs...\n"));
3322 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3323 fprintf(stderr, "%d ", piece+1);
3324 for (kind=0; kind<4; kind++) {
3325 sprintf(buf, "%s/%c%s%u.xpm",
3326 ExpandPathName(appData.pixmapDirectory),
3327 ToLower(PieceToChar((ChessSquare)piece)),
3329 if (appData.debugMode) {
3330 fprintf(stderr, _("(File:%s:) "), buf);
3332 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3333 &(xpmPieceBitmap[kind][piece]),
3334 NULL, &attr)) != 0) {
3335 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3341 /* Load light and dark squares */
3342 /* If the LSQ and DSQ pieces don't exist, we will
3343 draw them with solid squares. */
3344 fprintf(stderr, _("light square "));
3345 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3346 if (access(buf, 0) != 0) {
3350 if (appData.debugMode)
3351 fprintf(stderr, _("(File:%s:) "), buf);
3353 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3354 &xpmLightSquare, NULL, &attr)) != 0) {
3355 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3358 fprintf(stderr, _("dark square "));
3359 sprintf(buf, "%s/dsq%u.xpm",
3360 ExpandPathName(appData.pixmapDirectory), ss);
3361 if (appData.debugMode) {
3362 fprintf(stderr, _("(File:%s:) "), buf);
3364 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3365 &xpmDarkSquare, NULL, &attr)) != 0) {
3366 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3370 xpmJailSquare = xpmLightSquare;
3371 fprintf(stderr, _("Done.\n"));
3373 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3376 #endif /* HAVE_LIBXPM */
3379 /* No built-in bitmaps */
3384 u_int ss = squareSize;
3386 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3389 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3390 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3391 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3392 ss, kind == SOLID ? 's' : 'o');
3393 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3397 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3401 /* With built-in bitmaps */
3404 BuiltInBits* bib = builtInBits;
3407 u_int ss = squareSize;
3409 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3412 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3414 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3415 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3416 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3417 ss, kind == SOLID ? 's' : 'o');
3418 ReadBitmap(&pieceBitmap[kind][piece], buf,
3419 bib->bits[kind][piece], ss, ss);
3423 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3428 void ReadBitmap(pm, name, bits, wreq, hreq)
3431 unsigned char bits[];
3437 char msg[MSG_SIZ], fullname[MSG_SIZ];
3439 if (*appData.bitmapDirectory != NULLCHAR) {
3440 strcpy(fullname, appData.bitmapDirectory);
3441 strcat(fullname, "/");
3442 strcat(fullname, name);
3443 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3444 &w, &h, pm, &x_hot, &y_hot);
3445 if (errcode != BitmapSuccess) {
3447 case BitmapOpenFailed:
3448 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3450 case BitmapFileInvalid:
3451 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3453 case BitmapNoMemory:
3454 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3458 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3462 fprintf(stderr, _("%s: %s...using built-in\n"),
3464 } else if (w != wreq || h != hreq) {
3466 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3467 programName, fullname, w, h, wreq, hreq);
3473 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3477 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3486 if (lineGap == 0) return;
3487 for (i = 0; i < BOARD_SIZE + 1; i++) {
3488 gridSegments[i].x1 = 0;
3489 gridSegments[i].x2 =
3490 lineGap + BOARD_SIZE * (squareSize + lineGap);
3491 gridSegments[i].y1 = gridSegments[i].y2
3492 = lineGap / 2 + (i * (squareSize + lineGap));
3494 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3495 gridSegments[i + BOARD_SIZE + 1].y2 =
3496 BOARD_SIZE * (squareSize + lineGap);
3497 gridSegments[i + BOARD_SIZE + 1].x1 =
3498 gridSegments[i + BOARD_SIZE + 1].x2
3499 = lineGap / 2 + (i * (squareSize + lineGap));
3503 static void MenuBarSelect(w, addr, index)
3508 XtActionProc proc = (XtActionProc) addr;
3510 (proc)(NULL, NULL, NULL, NULL);
3513 void CreateMenuBarPopup(parent, name, mb)
3523 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3526 XtSetArg(args[j], XtNleftMargin, 20); j++;
3527 XtSetArg(args[j], XtNrightMargin, 20); j++;
3529 while (mi->string != NULL) {
3530 if (strcmp(mi->string, "----") == 0) {
3531 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3534 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3535 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3537 XtAddCallback(entry, XtNcallback,
3538 (XtCallbackProc) MenuBarSelect,
3539 (caddr_t) mi->proc);
3545 Widget CreateMenuBar(mb)
3549 Widget anchor, menuBar;
3551 char menuName[MSG_SIZ];
3554 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3555 XtSetArg(args[j], XtNvSpace, 0); j++;
3556 XtSetArg(args[j], XtNborderWidth, 0); j++;
3557 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3558 formWidget, args, j);
3560 while (mb->name != NULL) {
3561 strcpy(menuName, "menu");
3562 strcat(menuName, mb->name);
3564 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3567 shortName[0] = _(mb->name)[0];
3568 shortName[1] = NULLCHAR;
3569 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3572 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3575 XtSetArg(args[j], XtNborderWidth, 0); j++;
3576 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3578 CreateMenuBarPopup(menuBar, menuName, mb);
3584 Widget CreateButtonBar(mi)
3588 Widget button, buttonBar;
3592 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3594 XtSetArg(args[j], XtNhSpace, 0); j++;
3596 XtSetArg(args[j], XtNborderWidth, 0); j++;
3597 XtSetArg(args[j], XtNvSpace, 0); j++;
3598 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3599 formWidget, args, j);
3601 while (mi->string != NULL) {
3604 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3605 XtSetArg(args[j], XtNborderWidth, 0); j++;
3607 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3608 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3609 buttonBar, args, j);
3610 XtAddCallback(button, XtNcallback,
3611 (XtCallbackProc) MenuBarSelect,
3612 (caddr_t) mi->proc);
3619 CreatePieceMenu(name, color)
3626 ChessSquare selection;
3628 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3629 boardWidget, args, 0);
3631 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3632 String item = pieceMenuStrings[color][i];
3634 if (strcmp(item, "----") == 0) {
3635 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3638 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3639 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3641 selection = pieceMenuTranslation[color][i];
3642 XtAddCallback(entry, XtNcallback,
3643 (XtCallbackProc) PieceMenuSelect,
3644 (caddr_t) selection);
3645 if (selection == WhitePawn || selection == BlackPawn) {
3646 XtSetArg(args[0], XtNpopupOnEntry, entry);
3647 XtSetValues(menu, args, 1);
3660 ChessSquare selection;
3662 whitePieceMenu = CreatePieceMenu("menuW", 0);
3663 blackPieceMenu = CreatePieceMenu("menuB", 1);
3665 XtRegisterGrabAction(PieceMenuPopup, True,
3666 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3667 GrabModeAsync, GrabModeAsync);
3669 XtSetArg(args[0], XtNlabel, _("Drop"));
3670 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3671 boardWidget, args, 1);
3672 for (i = 0; i < DROP_MENU_SIZE; i++) {
3673 String item = dropMenuStrings[i];
3675 if (strcmp(item, "----") == 0) {
3676 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3679 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3680 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3682 selection = dropMenuTranslation[i];
3683 XtAddCallback(entry, XtNcallback,
3684 (XtCallbackProc) DropMenuSelect,
3685 (caddr_t) selection);
3690 void SetupDropMenu()
3698 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3699 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3700 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3701 dmEnables[i].piece);
3702 XtSetSensitive(entry, p != NULL || !appData.testLegality
3703 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3704 && !appData.icsActive));
3706 while (p && *p++ == dmEnables[i].piece) count++;
3707 sprintf(label, "%s %d", dmEnables[i].widget, count);
3709 XtSetArg(args[j], XtNlabel, label); j++;
3710 XtSetValues(entry, args, j);
3714 void PieceMenuPopup(w, event, params, num_params)
3718 Cardinal *num_params;
3721 if (event->type != ButtonPress) return;
3722 if (errorUp) ErrorPopDown();
3726 whichMenu = params[0];
3728 case IcsPlayingWhite:
3729 case IcsPlayingBlack:
3731 case MachinePlaysWhite:
3732 case MachinePlaysBlack:
3733 if (appData.testLegality &&
3734 gameInfo.variant != VariantBughouse &&
3735 gameInfo.variant != VariantCrazyhouse) return;
3737 whichMenu = "menuD";
3743 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3744 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3745 pmFromX = pmFromY = -1;
3749 pmFromX = BOARD_SIZE - 1 - pmFromX;
3751 pmFromY = BOARD_SIZE - 1 - pmFromY;
3753 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3756 static void PieceMenuSelect(w, piece, junk)
3761 if (pmFromX < 0 || pmFromY < 0) return;
3762 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3765 static void DropMenuSelect(w, piece, junk)
3770 if (pmFromX < 0 || pmFromY < 0) return;
3771 DropMenuEvent(piece, pmFromX, pmFromY);
3774 void WhiteClock(w, event, prms, nprms)
3780 if (gameMode == EditPosition || gameMode == IcsExamining) {
3781 SetWhiteToPlayEvent();
3782 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3787 void BlackClock(w, event, prms, nprms)
3793 if (gameMode == EditPosition || gameMode == IcsExamining) {
3794 SetBlackToPlayEvent();
3795 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3802 * If the user selects on a border boundary, return -1; if off the board,
3803 * return -2. Otherwise map the event coordinate to the square.
3805 int EventToSquare(x, limit)
3813 if ((x % (squareSize + lineGap)) >= squareSize)
3815 x /= (squareSize + lineGap);
3821 static void do_flash_delay(msec)
3827 static void drawHighlight(file, rank, gc)
3833 if (lineGap == 0 || appData.blindfold) return;
3836 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3837 (squareSize + lineGap);
3838 y = lineGap/2 + rank * (squareSize + lineGap);
3840 x = lineGap/2 + file * (squareSize + lineGap);
3841 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3842 (squareSize + lineGap);
3845 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3846 squareSize+lineGap, squareSize+lineGap);
3849 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3850 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3853 SetHighlights(fromX, fromY, toX, toY)
3854 int fromX, fromY, toX, toY;
3856 if (hi1X != fromX || hi1Y != fromY) {
3857 if (hi1X >= 0 && hi1Y >= 0) {
3858 drawHighlight(hi1X, hi1Y, lineGC);
3860 if (fromX >= 0 && fromY >= 0) {
3861 drawHighlight(fromX, fromY, highlineGC);
3864 if (hi2X != toX || hi2Y != toY) {
3865 if (hi2X >= 0 && hi2Y >= 0) {
3866 drawHighlight(hi2X, hi2Y, lineGC);
3868 if (toX >= 0 && toY >= 0) {
3869 drawHighlight(toX, toY, highlineGC);
3881 SetHighlights(-1, -1, -1, -1);
3886 SetPremoveHighlights(fromX, fromY, toX, toY)
3887 int fromX, fromY, toX, toY;
3889 if (pm1X != fromX || pm1Y != fromY) {
3890 if (pm1X >= 0 && pm1Y >= 0) {
3891 drawHighlight(pm1X, pm1Y, lineGC);
3893 if (fromX >= 0 && fromY >= 0) {
3894 drawHighlight(fromX, fromY, prelineGC);
3897 if (pm2X != toX || pm2Y != toY) {
3898 if (pm2X >= 0 && pm2Y >= 0) {
3899 drawHighlight(pm2X, pm2Y, lineGC);
3901 if (toX >= 0 && toY >= 0) {
3902 drawHighlight(toX, toY, prelineGC);
3912 ClearPremoveHighlights()
3914 SetPremoveHighlights(-1, -1, -1, -1);
3917 static void BlankSquare(x, y, color, piece, dest)
3922 if (useImages && useImageSqs) {
3926 pm = xpmLightSquare;
3931 case 2: /* neutral */
3936 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3937 squareSize, squareSize, x, y);
3947 case 2: /* neutral */
3952 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3957 I split out the routines to draw a piece so that I could
3958 make a generic flash routine.
3960 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3962 int square_color, x, y;
3965 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3966 switch (square_color) {
3968 case 2: /* neutral */
3970 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3971 ? *pieceToOutline(piece)
3972 : *pieceToSolid(piece),
3973 dest, bwPieceGC, 0, 0,
3974 squareSize, squareSize, x, y);
3977 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3978 ? *pieceToSolid(piece)
3979 : *pieceToOutline(piece),
3980 dest, wbPieceGC, 0, 0,
3981 squareSize, squareSize, x, y);
3986 static void monoDrawPiece(piece, square_color, x, y, dest)
3988 int square_color, x, y;
3991 switch (square_color) {
3993 case 2: /* neutral */
3995 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3996 ? *pieceToOutline(piece)
3997 : *pieceToSolid(piece),
3998 dest, bwPieceGC, 0, 0,
3999 squareSize, squareSize, x, y, 1);
4002 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4003 ? *pieceToSolid(piece)
4004 : *pieceToOutline(piece),
4005 dest, wbPieceGC, 0, 0,
4006 squareSize, squareSize, x, y, 1);
4011 static void colorDrawPiece(piece, square_color, x, y, dest)
4013 int square_color, x, y;
4016 switch (square_color) {
4018 XCopyPlane(xDisplay, *pieceToSolid(piece),
4019 dest, (int) piece < (int) BlackPawn
4020 ? wlPieceGC : blPieceGC, 0, 0,
4021 squareSize, squareSize, x, y, 1);
4024 XCopyPlane(xDisplay, *pieceToSolid(piece),
4025 dest, (int) piece < (int) BlackPawn
4026 ? wdPieceGC : bdPieceGC, 0, 0,
4027 squareSize, squareSize, x, y, 1);
4029 case 2: /* neutral */
4031 XCopyPlane(xDisplay, *pieceToSolid(piece),
4032 dest, (int) piece < (int) BlackPawn
4033 ? wjPieceGC : bjPieceGC, 0, 0,
4034 squareSize, squareSize, x, y, 1);
4039 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4041 int square_color, x, y;
4046 switch (square_color) {
4048 case 2: /* neutral */
4050 if ((int)piece < (int) BlackPawn) {
4058 if ((int)piece < (int) BlackPawn) {
4066 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4067 dest, wlPieceGC, 0, 0,
4068 squareSize, squareSize, x, y);
4071 typedef void (*DrawFunc)();
4073 DrawFunc ChooseDrawFunc()
4075 if (appData.monoMode) {
4076 if (DefaultDepth(xDisplay, xScreen) == 1) {
4077 return monoDrawPiece_1bit;
4079 return monoDrawPiece;
4083 return colorDrawPieceImage;
4085 return colorDrawPiece;
4089 void DrawSquare(row, column, piece, do_flash)
4090 int row, column, do_flash;
4093 int square_color, x, y, direction, font_ascent, font_descent;
4096 XCharStruct overall;
4100 /* Calculate delay in milliseconds (2-delays per complete flash) */
4101 flash_delay = 500 / appData.flashRate;
4104 x = lineGap + ((BOARD_SIZE-1)-column) *
4105 (squareSize + lineGap);
4106 y = lineGap + row * (squareSize + lineGap);
4108 x = lineGap + column * (squareSize + lineGap);
4109 y = lineGap + ((BOARD_SIZE-1)-row) *
4110 (squareSize + lineGap);
4113 square_color = ((column + row) % 2) == 1;
4115 if (piece == EmptySquare || appData.blindfold) {
4116 BlankSquare(x, y, square_color, piece, xBoardWindow);
4118 drawfunc = ChooseDrawFunc();
4119 if (do_flash && appData.flashCount > 0) {
4120 for (i=0; i<appData.flashCount; ++i) {
4122 drawfunc(piece, square_color, x, y, xBoardWindow);
4123 XSync(xDisplay, False);
4124 do_flash_delay(flash_delay);
4126 BlankSquare(x, y, square_color, piece, xBoardWindow);
4127 XSync(xDisplay, False);
4128 do_flash_delay(flash_delay);
4131 drawfunc(piece, square_color, x, y, xBoardWindow);
4134 string[1] = NULLCHAR;
4135 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4136 string[0] = 'a' + column;
4137 XTextExtents(coordFontStruct, string, 1, &direction,
4138 &font_ascent, &font_descent, &overall);
4139 if (appData.monoMode) {
4140 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4141 x + squareSize - overall.width - 2,
4142 y + squareSize - font_descent - 1, string, 1);
4144 XDrawString(xDisplay, xBoardWindow, coordGC,
4145 x + squareSize - overall.width - 2,
4146 y + squareSize - font_descent - 1, string, 1);
4149 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4150 string[0] = '1' + row;
4151 XTextExtents(coordFontStruct, string, 1, &direction,
4152 &font_ascent, &font_descent, &overall);
4153 if (appData.monoMode) {
4154 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4155 x + 2, y + font_ascent + 1, string, 1);
4157 XDrawString(xDisplay, xBoardWindow, coordGC,
4158 x + 2, y + font_ascent + 1, string, 1);
4164 /* Why is this needed on some versions of X? */
4165 void EventProc(widget, unused, event)
4170 if (!XtIsRealized(widget))
4173 switch (event->type) {
4175 if (event->xexpose.count > 0) return; /* no clipping is done */
4176 XDrawPosition(widget, True, NULL);
4184 void DrawPosition(fullRedraw, board)
4185 /*Boolean*/int fullRedraw;
4188 XDrawPosition(boardWidget, fullRedraw, board);
4191 /* Returns 1 if there are "too many" differences between b1 and b2
4192 (i.e. more than 1 move was made) */
4193 static int too_many_diffs(b1, b2)
4199 for (i=0; i<BOARD_SIZE; ++i) {
4200 for (j=0; j<BOARD_SIZE; ++j) {
4201 if (b1[i][j] != b2[i][j]) {
4202 if (++c > 4) /* Castling causes 4 diffs */
4211 /* Matrix describing castling maneuvers */
4212 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4213 static int castling_matrix[4][5] = {
4214 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4215 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4216 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4217 { 7, 7, 4, 5, 6 } /* 0-0, black */
4220 /* Checks whether castling occurred. If it did, *rrow and *rcol
4221 are set to the destination (row,col) of the rook that moved.
4223 Returns 1 if castling occurred, 0 if not.
4225 Note: Only handles a max of 1 castling move, so be sure
4226 to call too_many_diffs() first.
4228 static int check_castle_draw(newb, oldb, rrow, rcol)
4235 /* For each type of castling... */
4236 for (i=0; i<4; ++i) {
4237 r = castling_matrix[i];
4239 /* Check the 4 squares involved in the castling move */
4241 for (j=1; j<=4; ++j) {
4242 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4249 /* All 4 changed, so it must be a castling move */
4258 static int damage[BOARD_SIZE][BOARD_SIZE];
4261 * event handler for redrawing the board
4263 void XDrawPosition(w, repaint, board)
4265 /*Boolean*/int repaint;
4269 static int lastFlipView = 0;
4270 static int lastBoardValid = 0;
4271 static Board lastBoard;
4275 if (board == NULL) {
4276 if (!lastBoardValid) return;
4279 if (!lastBoardValid || lastFlipView != flipView) {
4280 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4281 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4286 * It would be simpler to clear the window with XClearWindow()
4287 * but this causes a very distracting flicker.
4290 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4292 /* If too much changes (begin observing new game, etc.), don't
4294 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4296 /* Special check for castling so we don't flash both the king
4297 and the rook (just flash the king). */
4299 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4300 /* Draw rook with NO flashing. King will be drawn flashing later */
4301 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4302 lastBoard[rrow][rcol] = board[rrow][rcol];
4306 /* First pass -- Draw (newly) empty squares and repair damage.
4307 This prevents you from having a piece show up twice while it
4308 is flashing on its new square */
4309 for (i = 0; i < BOARD_SIZE; i++)
4310 for (j = 0; j < BOARD_SIZE; j++)
4311 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4313 DrawSquare(i, j, board[i][j], 0);
4314 damage[i][j] = False;
4317 /* Second pass -- Draw piece(s) in new position and flash them */
4318 for (i = 0; i < BOARD_SIZE; i++)
4319 for (j = 0; j < BOARD_SIZE; j++)
4320 if (board[i][j] != lastBoard[i][j]) {
4321 DrawSquare(i, j, board[i][j], do_flash);
4325 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4326 gridSegments, (BOARD_SIZE + 1) * 2);
4328 for (i = 0; i < BOARD_SIZE; i++)
4329 for (j = 0; j < BOARD_SIZE; j++) {
4330 DrawSquare(i, j, board[i][j], 0);
4331 damage[i][j] = False;
4335 CopyBoard(lastBoard, board);
4337 lastFlipView = flipView;
4339 /* Draw highlights */
4340 if (pm1X >= 0 && pm1Y >= 0) {
4341 drawHighlight(pm1X, pm1Y, prelineGC);
4343 if (pm2X >= 0 && pm2Y >= 0) {
4344 drawHighlight(pm2X, pm2Y, prelineGC);
4346 if (hi1X >= 0 && hi1Y >= 0) {
4347 drawHighlight(hi1X, hi1Y, highlineGC);
4349 if (hi2X >= 0 && hi2Y >= 0) {
4350 drawHighlight(hi2X, hi2Y, highlineGC);
4353 /* If piece being dragged around board, must redraw that too */
4356 XSync(xDisplay, False);
4361 * event handler for redrawing the board
4363 void DrawPositionProc(w, event, prms, nprms)
4369 XDrawPosition(w, True, NULL);
4374 * event handler for parsing user moves
4376 void HandleUserMove(w, event, prms, nprms)
4383 Boolean saveAnimate;
4384 static int second = 0;
4386 if (w != boardWidget || errorExitStatus != -1) return;
4388 if (event->type == ButtonPress) ErrorPopDown();
4391 if (event->type == ButtonPress) {
4392 XtPopdown(promotionShell);
4393 XtDestroyWidget(promotionShell);
4394 promotionUp = False;
4402 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4403 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4404 if (!flipView && y >= 0) {
4405 y = BOARD_SIZE - 1 - y;
4407 if (flipView && x >= 0) {
4408 x = BOARD_SIZE - 1 - x;
4412 if (event->type == ButtonPress) {
4414 if (OKToStartUserMove(x, y)) {
4418 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4419 if (appData.highlightDragging) {
4420 SetHighlights(x, y, -1, -1);
4428 if (event->type == ButtonPress && gameMode != EditPosition &&
4432 /* Check if clicking again on the same color piece */
4433 fromP = boards[currentMove][fromY][fromX];
4434 toP = boards[currentMove][y][x];
4435 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4436 WhitePawn <= toP && toP <= WhiteKing) ||
4437 (BlackPawn <= fromP && fromP <= BlackKing &&
4438 BlackPawn <= toP && toP <= BlackKing)) {
4439 /* Clicked again on same color piece -- changed his mind */
4440 second = (x == fromX && y == fromY);
4441 if (appData.highlightDragging) {
4442 SetHighlights(x, y, -1, -1);
4446 if (OKToStartUserMove(x, y)) {
4449 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4455 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4456 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4457 if (appData.animateDragging) {
4458 /* Undo animation damage if any */
4459 DrawPosition(FALSE, NULL);
4462 /* Second up/down in same square; just abort move */
4467 ClearPremoveHighlights();
4469 /* First upclick in same square; start click-click mode */
4470 SetHighlights(x, y, -1, -1);
4475 /* Completed move */
4478 saveAnimate = appData.animate;
4479 if (event->type == ButtonPress) {
4480 /* Finish clickclick move */
4481 if (appData.animate || appData.highlightLastMove) {
4482 SetHighlights(fromX, fromY, toX, toY);
4487 /* Finish drag move */
4488 if (appData.highlightLastMove) {
4489 SetHighlights(fromX, fromY, toX, toY);
4493 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4494 /* Don't animate move and drag both */
4495 appData.animate = FALSE;
4497 if (IsPromotion(fromX, fromY, toX, toY)) {
4498 if (appData.alwaysPromoteToQueen) {
4499 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4500 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4501 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4504 SetHighlights(fromX, fromY, toX, toY);
4508 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4509 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4510 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4513 appData.animate = saveAnimate;
4514 if (appData.animate || appData.animateDragging) {
4515 /* Undo animation damage if needed */
4516 DrawPosition(FALSE, NULL);
4520 void AnimateUserMove (Widget w, XEvent * event,
4521 String * params, Cardinal * nParams)
4523 DragPieceMove(event->xmotion.x, event->xmotion.y);
4526 Widget CommentCreate(name, text, mutable, callback, lines)
4528 int /*Boolean*/ mutable;
4529 XtCallbackProc callback;
4533 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4538 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4539 XtGetValues(boardWidget, args, j);
4542 XtSetArg(args[j], XtNresizable, True); j++;
4545 XtCreatePopupShell(name, topLevelShellWidgetClass,
4546 shellWidget, args, j);
4549 XtCreatePopupShell(name, transientShellWidgetClass,
4550 shellWidget, args, j);
4553 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4554 layoutArgs, XtNumber(layoutArgs));
4556 XtCreateManagedWidget("form", formWidgetClass, layout,
4557 formArgs, XtNumber(formArgs));
4561 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4562 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4564 XtSetArg(args[j], XtNstring, text); j++;
4565 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4566 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4567 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4568 XtSetArg(args[j], XtNright, XtChainRight); j++;
4569 XtSetArg(args[j], XtNresizable, True); j++;
4570 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4572 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4574 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4575 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4577 XtSetArg(args[j], XtNautoFill, True); j++;
4578 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4580 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4584 XtSetArg(args[j], XtNfromVert, edit); j++;
4585 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4586 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4587 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4588 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4590 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4591 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4594 XtSetArg(args[j], XtNfromVert, edit); j++;
4595 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4596 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4597 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4598 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4599 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4601 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4602 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4605 XtSetArg(args[j], XtNfromVert, edit); j++;
4606 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4607 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4608 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4609 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4610 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4612 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4613 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4616 XtSetArg(args[j], XtNfromVert, edit); j++;
4617 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4618 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4619 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4620 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4622 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4623 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4626 XtSetArg(args[j], XtNfromVert, edit); j++;
4627 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4628 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4629 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4630 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4631 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4633 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4634 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4637 XtRealizeWidget(shell);
4639 if (commentX == -1) {
4642 Dimension pw_height;
4643 Dimension ew_height;
4646 XtSetArg(args[j], XtNheight, &ew_height); j++;
4647 XtGetValues(edit, args, j);
4650 XtSetArg(args[j], XtNheight, &pw_height); j++;
4651 XtGetValues(shell, args, j);
4652 commentH = pw_height + (lines - 1) * ew_height;
4653 commentW = bw_width - 16;
4655 XSync(xDisplay, False);
4657 /* This code seems to tickle an X bug if it is executed too soon
4658 after xboard starts up. The coordinates get transformed as if
4659 the main window was positioned at (0, 0).
4661 XtTranslateCoords(shellWidget,
4662 (bw_width - commentW) / 2, 0 - commentH / 2,
4663 &commentX, &commentY);
4665 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4666 RootWindowOfScreen(XtScreen(shellWidget)),
4667 (bw_width - commentW) / 2, 0 - commentH / 2,
4672 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4675 XtSetArg(args[j], XtNheight, commentH); j++;
4676 XtSetArg(args[j], XtNwidth, commentW); j++;
4677 XtSetArg(args[j], XtNx, commentX); j++;
4678 XtSetArg(args[j], XtNy, commentY); j++;
4679 XtSetValues(shell, args, j);
4680 XtSetKeyboardFocus(shell, edit);
4685 /* Used for analysis window and ICS input window */
4686 Widget MiscCreate(name, text, mutable, callback, lines)
4688 int /*Boolean*/ mutable;
4689 XtCallbackProc callback;
4693 Widget shell, layout, form, edit;
4695 Dimension bw_width, pw_height, ew_height, w, h;
4701 XtSetArg(args[j], XtNresizable, True); j++;
4704 XtCreatePopupShell(name, topLevelShellWidgetClass,
4705 shellWidget, args, j);
4708 XtCreatePopupShell(name, transientShellWidgetClass,
4709 shellWidget, args, j);
4712 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4713 layoutArgs, XtNumber(layoutArgs));
4715 XtCreateManagedWidget("form", formWidgetClass, layout,
4716 formArgs, XtNumber(formArgs));
4720 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4721 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4723 XtSetArg(args[j], XtNstring, text); j++;
4724 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4725 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4726 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4727 XtSetArg(args[j], XtNright, XtChainRight); j++;
4728 XtSetArg(args[j], XtNresizable, True); j++;
4730 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4732 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4733 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4735 XtSetArg(args[j], XtNautoFill, True); j++;
4736 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4738 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4740 XtRealizeWidget(shell);
4743 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4744 XtGetValues(boardWidget, args, j);
4747 XtSetArg(args[j], XtNheight, &ew_height); j++;
4748 XtGetValues(edit, args, j);
4751 XtSetArg(args[j], XtNheight, &pw_height); j++;
4752 XtGetValues(shell, args, j);
4753 h = pw_height + (lines - 1) * ew_height;
4756 XSync(xDisplay, False);
4758 /* This code seems to tickle an X bug if it is executed too soon
4759 after xboard starts up. The coordinates get transformed as if
4760 the main window was positioned at (0, 0).
4762 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4764 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4765 RootWindowOfScreen(XtScreen(shellWidget)),
4766 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4770 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4773 XtSetArg(args[j], XtNheight, h); j++;
4774 XtSetArg(args[j], XtNwidth, w); j++;
4775 XtSetArg(args[j], XtNx, x); j++;
4776 XtSetArg(args[j], XtNy, y); j++;
4777 XtSetValues(shell, args, j);
4783 static int savedIndex; /* gross that this is global */
4785 void EditCommentPopUp(index, title, text)
4794 if (text == NULL) text = "";
4796 if (editShell == NULL) {
4798 CommentCreate(title, text, True, EditCommentCallback, 4);
4799 XtRealizeWidget(editShell);
4800 CatchDeleteWindow(editShell, "EditCommentPopDown");
4802 edit = XtNameToWidget(editShell, "*form.text");
4804 XtSetArg(args[j], XtNstring, text); j++;
4805 XtSetValues(edit, args, j);
4807 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4808 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4809 XtSetValues(editShell, args, j);
4812 XtPopup(editShell, XtGrabNone);
4816 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4817 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4821 void EditCommentCallback(w, client_data, call_data)
4823 XtPointer client_data, call_data;
4831 XtSetArg(args[j], XtNlabel, &name); j++;
4832 XtGetValues(w, args, j);
4834 if (strcmp(name, _("ok")) == 0) {
4835 edit = XtNameToWidget(editShell, "*form.text");
4837 XtSetArg(args[j], XtNstring, &val); j++;
4838 XtGetValues(edit, args, j);
4839 ReplaceComment(savedIndex, val);
4840 EditCommentPopDown();
4841 } else if (strcmp(name, _("cancel")) == 0) {
4842 EditCommentPopDown();
4843 } else if (strcmp(name, _("clear")) == 0) {
4844 edit = XtNameToWidget(editShell, "*form.text");
4845 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4846 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4850 void EditCommentPopDown()
4855 if (!editUp) return;
4857 XtSetArg(args[j], XtNx, &commentX); j++;
4858 XtSetArg(args[j], XtNy, &commentY); j++;
4859 XtSetArg(args[j], XtNheight, &commentH); j++;
4860 XtSetArg(args[j], XtNwidth, &commentW); j++;
4861 XtGetValues(editShell, args, j);
4862 XtPopdown(editShell);
4865 XtSetArg(args[j], XtNleftBitmap, None); j++;
4866 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4870 void ICSInputBoxPopUp()
4875 char *title = _("ICS Input");
4878 if (ICSInputShell == NULL) {
4879 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4880 tr = XtParseTranslationTable(ICSInputTranslations);
4881 edit = XtNameToWidget(ICSInputShell, "*form.text");
4882 XtOverrideTranslations(edit, tr);
4883 XtRealizeWidget(ICSInputShell);
4884 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4887 edit = XtNameToWidget(ICSInputShell, "*form.text");
4889 XtSetArg(args[j], XtNstring, ""); j++;
4890 XtSetValues(edit, args, j);
4892 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4893 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4894 XtSetValues(ICSInputShell, args, j);
4897 XtPopup(ICSInputShell, XtGrabNone);
4898 XtSetKeyboardFocus(ICSInputShell, edit);
4900 ICSInputBoxUp = True;
4902 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4903 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4907 void ICSInputSendText()
4914 edit = XtNameToWidget(ICSInputShell, "*form.text");
4916 XtSetArg(args[j], XtNstring, &val); j++;
4917 XtGetValues(edit, args, j);
4918 SendMultiLineToICS(val);
4919 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4920 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4923 void ICSInputBoxPopDown()
4928 if (!ICSInputBoxUp) return;
4930 XtPopdown(ICSInputShell);
4931 ICSInputBoxUp = False;
4933 XtSetArg(args[j], XtNleftBitmap, None); j++;
4934 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4938 void CommentPopUp(title, text)
4945 if (commentShell == NULL) {
4947 CommentCreate(title, text, False, CommentCallback, 4);
4948 XtRealizeWidget(commentShell);
4949 CatchDeleteWindow(commentShell, "CommentPopDown");
4951 edit = XtNameToWidget(commentShell, "*form.text");
4953 XtSetArg(args[j], XtNstring, text); j++;
4954 XtSetValues(edit, args, j);
4956 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4957 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4958 XtSetValues(commentShell, args, j);
4961 XtPopup(commentShell, XtGrabNone);
4962 XSync(xDisplay, False);
4967 void AnalysisPopUp(title, text)
4974 if (analysisShell == NULL) {
4975 analysisShell = MiscCreate(title, text, False, NULL, 4);
4976 XtRealizeWidget(analysisShell);
4977 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4980 edit = XtNameToWidget(analysisShell, "*form.text");
4982 XtSetArg(args[j], XtNstring, text); j++;
4983 XtSetValues(edit, args, j);
4985 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4986 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4987 XtSetValues(analysisShell, args, j);
4991 XtPopup(analysisShell, XtGrabNone);
4993 XSync(xDisplay, False);
4998 void CommentCallback(w, client_data, call_data)
5000 XtPointer client_data, call_data;
5007 XtSetArg(args[j], XtNlabel, &name); j++;
5008 XtGetValues(w, args, j);
5010 if (strcmp(name, _("close")) == 0) {
5012 } else if (strcmp(name, _("edit")) == 0) {
5019 void CommentPopDown()
5024 if (!commentUp) return;
5026 XtSetArg(args[j], XtNx, &commentX); j++;
5027 XtSetArg(args[j], XtNy, &commentY); j++;
5028 XtSetArg(args[j], XtNwidth, &commentW); j++;
5029 XtSetArg(args[j], XtNheight, &commentH); j++;
5030 XtGetValues(commentShell, args, j);
5031 XtPopdown(commentShell);
5032 XSync(xDisplay, False);
5036 void AnalysisPopDown()
5038 if (!analysisUp) return;
5039 XtPopdown(analysisShell);
5040 XSync(xDisplay, False);
5042 /* icsEngineAnalyze */
5043 if (appData.icsEngineAnalyze) ExitAnalyzeMode();
5047 void FileNamePopUp(label, def, proc, openMode)
5054 Widget popup, layout, dialog, edit;
5060 fileProc = proc; /* I can't see a way not */
5061 fileOpenMode = openMode; /* to use globals here */
5064 XtSetArg(args[i], XtNresizable, True); i++;
5065 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5066 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5067 fileNameShell = popup =
5068 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5069 shellWidget, args, i);
5072 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5073 layoutArgs, XtNumber(layoutArgs));
5076 XtSetArg(args[i], XtNlabel, label); i++;
5077 XtSetArg(args[i], XtNvalue, def); i++;
5078 XtSetArg(args[i], XtNborderWidth, 0); i++;
5079 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5082 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5083 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5084 (XtPointer) dialog);
5086 XtRealizeWidget(popup);
5087 CatchDeleteWindow(popup, "FileNamePopDown");
5089 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5090 &x, &y, &win_x, &win_y, &mask);
5092 XtSetArg(args[0], XtNx, x - 10);
5093 XtSetArg(args[1], XtNy, y - 30);
5094 XtSetValues(popup, args, 2);
5096 XtPopup(popup, XtGrabExclusive);
5099 edit = XtNameToWidget(dialog, "*value");
5100 XtSetKeyboardFocus(popup, edit);
5103 void FileNamePopDown()
5105 if (!filenameUp) return;
5106 XtPopdown(fileNameShell);
5107 XtDestroyWidget(fileNameShell);
5112 void FileNameCallback(w, client_data, call_data)
5114 XtPointer client_data, call_data;
5119 XtSetArg(args[0], XtNlabel, &name);
5120 XtGetValues(w, args, 1);
5122 if (strcmp(name, _("cancel")) == 0) {
5127 FileNameAction(w, NULL, NULL, NULL);
5130 void FileNameAction(w, event, prms, nprms)
5142 name = XawDialogGetValueString(w = XtParent(w));
5144 if ((name != NULL) && (*name != NULLCHAR)) {
5146 XtPopdown(w = XtParent(XtParent(w)));
5150 p = strrchr(buf, ' ');
5157 fullname = ExpandPathName(buf);
5159 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5162 f = fopen(fullname, fileOpenMode);
5164 DisplayError(_("Failed to open file"), errno);
5166 (void) (*fileProc)(f, index, buf);
5173 XtPopdown(w = XtParent(XtParent(w)));
5179 void PromotionPopUp()
5182 Widget dialog, layout;
5184 Dimension bw_width, pw_width;
5188 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5189 XtGetValues(boardWidget, args, j);
5192 XtSetArg(args[j], XtNresizable, True); j++;
5193 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5195 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5196 shellWidget, args, j);
5198 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5199 layoutArgs, XtNumber(layoutArgs));
5202 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5203 XtSetArg(args[j], XtNborderWidth, 0); j++;
5204 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5207 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5208 (XtPointer) dialog);
5209 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5210 (XtPointer) dialog);
5211 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5212 (XtPointer) dialog);
5213 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5214 (XtPointer) dialog);
5215 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5216 gameInfo.variant == VariantGiveaway) {
5217 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5218 (XtPointer) dialog);
5220 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5221 (XtPointer) dialog);
5223 XtRealizeWidget(promotionShell);
5224 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5227 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5228 XtGetValues(promotionShell, args, j);
5230 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5231 lineGap + squareSize/3 +
5232 ((toY == 7) ^ (flipView) ?
5233 0 : 6*(squareSize + lineGap)), &x, &y);
5236 XtSetArg(args[j], XtNx, x); j++;
5237 XtSetArg(args[j], XtNy, y); j++;
5238 XtSetValues(promotionShell, args, j);
5240 XtPopup(promotionShell, XtGrabNone);
5245 void PromotionPopDown()
5247 if (!promotionUp) return;
5248 XtPopdown(promotionShell);
5249 XtDestroyWidget(promotionShell);
5250 promotionUp = False;
5253 void PromotionCallback(w, client_data, call_data)
5255 XtPointer client_data, call_data;
5261 XtSetArg(args[0], XtNlabel, &name);
5262 XtGetValues(w, args, 1);
5266 if (fromX == -1) return;
5268 if (strcmp(name, _("cancel")) == 0) {
5272 } else if (strcmp(name, _("Knight")) == 0) {
5275 promoChar = ToLower(name[0]);
5278 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5280 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5281 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5286 void ErrorCallback(w, client_data, call_data)
5288 XtPointer client_data, call_data;
5291 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5293 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5299 if (!errorUp) return;
5301 XtPopdown(errorShell);
5302 XtDestroyWidget(errorShell);
5303 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5306 void ErrorPopUp(title, label, modal)
5307 char *title, *label;
5311 Widget dialog, layout;
5315 Dimension bw_width, pw_width;
5316 Dimension pw_height;
5320 XtSetArg(args[i], XtNresizable, True); i++;
5321 XtSetArg(args[i], XtNtitle, title); i++;
5323 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5324 shellWidget, args, i);
5326 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5327 layoutArgs, XtNumber(layoutArgs));
5330 XtSetArg(args[i], XtNlabel, label); i++;
5331 XtSetArg(args[i], XtNborderWidth, 0); i++;
5332 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5335 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5337 XtRealizeWidget(errorShell);
5338 CatchDeleteWindow(errorShell, "ErrorPopDown");
5341 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5342 XtGetValues(boardWidget, args, i);
5344 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5345 XtSetArg(args[i], XtNheight, &pw_height); i++;
5346 XtGetValues(errorShell, args, i);
5349 /* This code seems to tickle an X bug if it is executed too soon
5350 after xboard starts up. The coordinates get transformed as if
5351 the main window was positioned at (0, 0).
5353 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5354 0 - pw_height + squareSize / 3, &x, &y);
5356 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5357 RootWindowOfScreen(XtScreen(boardWidget)),
5358 (bw_width - pw_width) / 2,
5359 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5363 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5366 XtSetArg(args[i], XtNx, x); i++;
5367 XtSetArg(args[i], XtNy, y); i++;
5368 XtSetValues(errorShell, args, i);
5371 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5374 /* Disable all user input other than deleting the window */
5375 static int frozen = 0;
5379 /* Grab by a widget that doesn't accept input */
5380 XtAddGrab(messageWidget, TRUE, FALSE);
5384 /* Undo a FreezeUI */
5387 if (!frozen) return;
5388 XtRemoveGrab(messageWidget);
5392 char *ModeToWidgetName(mode)
5396 case BeginningOfGame:
5397 if (appData.icsActive)
5398 return "menuMode.ICS Client";
5399 else if (appData.noChessProgram ||
5400 *appData.cmailGameName != NULLCHAR)
5401 return "menuMode.Edit Game";
5403 return "menuMode.Machine Black";
5404 case MachinePlaysBlack:
5405 return "menuMode.Machine Black";
5406 case MachinePlaysWhite:
5407 return "menuMode.Machine White";
5409 return "menuMode.Analysis Mode";
5411 return "menuMode.Analyze File";
5412 case TwoMachinesPlay:
5413 return "menuMode.Two Machines";
5415 return "menuMode.Edit Game";
5416 case PlayFromGameFile:
5417 return "menuFile.Load Game";
5419 return "menuMode.Edit Position";
5421 return "menuMode.Training";
5422 case IcsPlayingWhite:
5423 case IcsPlayingBlack:
5427 return "menuMode.ICS Client";
5434 void ModeHighlight()
5437 static int oldPausing = FALSE;
5438 static GameMode oldmode = (GameMode) -1;
5441 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5443 if (pausing != oldPausing) {
5444 oldPausing = pausing;
5446 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5448 XtSetArg(args[0], XtNleftBitmap, None);
5450 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5453 if (appData.showButtonBar) {
5456 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5457 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5459 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5460 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5463 /* Always toggle, don't set. Previous code messes up when
5464 invoked while the button is pressed, as releasing it
5465 toggles the state again. */
5468 XtSetArg(args[0], XtNbackground, &oldbg);
5469 XtSetArg(args[1], XtNforeground, &oldfg);
5470 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5472 XtSetArg(args[0], XtNbackground, oldfg);
5473 XtSetArg(args[1], XtNforeground, oldbg);
5476 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5480 wname = ModeToWidgetName(oldmode);
5481 if (wname != NULL) {
5482 XtSetArg(args[0], XtNleftBitmap, None);
5483 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5485 wname = ModeToWidgetName(gameMode);
5486 if (wname != NULL) {
5487 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5488 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5492 /* Maybe all the enables should be handled here, not just this one */
5493 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5494 gameMode == Training || gameMode == PlayFromGameFile);
5498 * Button/menu procedures
5500 void ResetProc(w, event, prms, nprms)
5510 int LoadGamePopUp(f, gameNumber, title)
5515 cmailMsgLoaded = FALSE;
5516 if (gameNumber == 0) {
5517 int error = GameListBuild(f);
5519 DisplayError(_("Cannot build game list"), error);
5520 } else if (!ListEmpty(&gameList) &&
5521 ((ListGame *) gameList.tailPred)->number > 1) {
5522 GameListPopUp(f, title);
5528 return LoadGame(f, gameNumber, title, FALSE);
5531 void LoadGameProc(w, event, prms, nprms)
5537 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5540 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
5543 void LoadNextGameProc(w, event, prms, nprms)
5552 void LoadPrevGameProc(w, event, prms, nprms)
5561 void ReloadGameProc(w, event, prms, nprms)
5570 void LoadNextPositionProc(w, event, prms, nprms)
5579 void LoadPrevPositionProc(w, event, prms, nprms)
5588 void ReloadPositionProc(w, event, prms, nprms)
5597 void LoadPositionProc(w, event, prms, nprms)
5603 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5606 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5609 void SaveGameProc(w, event, prms, nprms)
5615 FileNamePopUp(_("Save game file name?"),
5616 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5620 void SavePositionProc(w, event, prms, nprms)
5626 FileNamePopUp(_("Save position file name?"),
5627 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5631 void ReloadCmailMsgProc(w, event, prms, nprms)
5637 ReloadCmailMsgEvent(FALSE);
5640 void MailMoveProc(w, event, prms, nprms)
5649 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5650 static char *selected_fen_position=NULL;
5653 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5654 Atom *type_return, XtPointer *value_return,
5655 unsigned long *length_return, int *format_return)
5657 char *selection_tmp;
5659 if (!selected_fen_position) return False; /* should never happen */
5660 if (*target == XA_STRING){
5661 /* note: since no XtSelectionDoneProc was registered, Xt will
5662 * automatically call XtFree on the value returned. So have to
5663 * make a copy of it allocated with XtMalloc */
5664 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5665 strcpy(selection_tmp, selected_fen_position);
5667 *value_return=selection_tmp;
5668 *length_return=strlen(selection_tmp);
5669 *type_return=XA_STRING;
5670 *format_return = 8; /* bits per byte */
5677 /* note: when called from menu all parameters are NULL, so no clue what the
5678 * Widget which was clicked on was, or what the click event was
5680 void CopyPositionProc(w, event, prms, nprms)
5688 if (selected_fen_position) free(selected_fen_position);
5689 selected_fen_position = (char *)PositionToFEN(currentMove);
5690 if (!selected_fen_position) return;
5691 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5693 SendPositionSelection,
5694 NULL/* lose_ownership_proc */ ,
5695 NULL/* transfer_done_proc */);
5697 free(selected_fen_position);
5698 selected_fen_position=NULL;
5702 /* function called when the data to Paste is ready */
5704 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5705 Atom *type, XtPointer value, unsigned long *len, int *format)
5708 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5709 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5710 EditPositionPasteFEN(fenstr);
5714 /* called when Paste Position button is pressed,
5715 * all parameters will be NULL */
5716 void PastePositionProc(w, event, prms, nprms)
5722 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5723 /* (XtSelectionCallbackProc) */ PastePositionCB,
5724 NULL, /* client_data passed to PastePositionCB */
5726 /* better to use the time field from the event that triggered the
5727 * call to this function, but that isn't trivial to get
5735 SendGameSelection(Widget w, Atom *selection, Atom *target,
5736 Atom *type_return, XtPointer *value_return,
5737 unsigned long *length_return, int *format_return)
5739 char *selection_tmp;
5741 if (*target == XA_STRING){
5742 FILE* f = fopen(gameCopyFilename, "r");
5745 if (f == NULL) return False;
5749 selection_tmp = XtMalloc(len + 1);
5750 count = fread(selection_tmp, 1, len, f);
5752 XtFree(selection_tmp);
5755 selection_tmp[len] = NULLCHAR;
5756 *value_return = selection_tmp;
5757 *length_return = len;
5758 *type_return = XA_STRING;
5759 *format_return = 8; /* bits per byte */
5766 /* note: when called from menu all parameters are NULL, so no clue what the
5767 * Widget which was clicked on was, or what the click event was
5769 void CopyGameProc(w, event, prms, nprms)
5777 ret = SaveGameToFile(gameCopyFilename, FALSE);
5780 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5783 NULL/* lose_ownership_proc */ ,
5784 NULL/* transfer_done_proc */);
5787 /* function called when the data to Paste is ready */
5789 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5790 Atom *type, XtPointer value, unsigned long *len, int *format)
5793 if (value == NULL || *len == 0) {
5794 return; /* nothing had been selected to copy */
5796 f = fopen(gamePasteFilename, "w");
5798 DisplayError(_("Can't open temp file"), errno);
5801 fwrite(value, 1, *len, f);
5804 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5807 /* called when Paste Game button is pressed,
5808 * all parameters will be NULL */
5809 void PasteGameProc(w, event, prms, nprms)
5815 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5816 /* (XtSelectionCallbackProc) */ PasteGameCB,
5817 NULL, /* client_data passed to PasteGameCB */
5819 /* better to use the time field from the event that triggered the
5820 * call to this function, but that isn't trivial to get
5830 SaveGameProc(NULL, NULL, NULL, NULL);
5834 void QuitProc(w, event, prms, nprms)
5843 void PauseProc(w, event, prms, nprms)
5853 void MachineBlackProc(w, event, prms, nprms)
5859 MachineBlackEvent();
5862 void MachineWhiteProc(w, event, prms, nprms)
5868 MachineWhiteEvent();
5871 void AnalyzeModeProc(w, event, prms, nprms)
5879 if (!first.analysisSupport) {
5880 sprintf(buf, _("%s does not support analysis"), first.tidy);
5881 DisplayError(buf, 0);
5884 /* icsEngineAnalyze */
5885 if (appData.icsActive) {
5886 if (gameMode != IcsObserving) {
5887 sprintf(buf,_("You are not observing a game"));
5888 DisplayError(buf, 0);
5890 if (appData.icsEngineAnalyze) {
5891 if (appData.debugMode)
5892 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5899 /* if enable, use want disable icsEngineAnalyze */
5900 if (appData.icsEngineAnalyze) {
5905 appData.icsEngineAnalyze = TRUE;
5906 if (appData.debugMode)
5907 fprintf(debugFP, "ICS engine analyze starting... \n");
5910 if (!appData.showThinking)
5911 ShowThinkingProc(w,event,prms,nprms);
5915 void AnalyzeFileProc(w, event, prms, nprms)
5921 if (!first.analysisSupport) {
5923 sprintf(buf, _("%s does not support analysis"), first.tidy);
5924 DisplayError(buf, 0);
5929 if (!appData.showThinking)
5930 ShowThinkingProc(w,event,prms,nprms);
5933 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5934 AnalysisPeriodicEvent(1);
5937 void TwoMachinesProc(w, event, prms, nprms)
5946 void IcsClientProc(w, event, prms, nprms)
5955 void EditGameProc(w, event, prms, nprms)
5964 void EditPositionProc(w, event, prms, nprms)
5970 EditPositionEvent();
5973 void TrainingProc(w, event, prms, nprms)
5982 void EditCommentProc(w, event, prms, nprms)
5989 EditCommentPopDown();
5995 void IcsInputBoxProc(w, event, prms, nprms)
6001 if (ICSInputBoxUp) {
6002 ICSInputBoxPopDown();
6008 void AcceptProc(w, event, prms, nprms)
6017 void DeclineProc(w, event, prms, nprms)
6026 void RematchProc(w, event, prms, nprms)
6035 void CallFlagProc(w, event, prms, nprms)
6044 void DrawProc(w, event, prms, nprms)
6053 void AbortProc(w, event, prms, nprms)
6062 void AdjournProc(w, event, prms, nprms)
6071 void ResignProc(w, event, prms, nprms)
6080 void EnterKeyProc(w, event, prms, nprms)
6086 if (ICSInputBoxUp == True)
6090 void StopObservingProc(w, event, prms, nprms)
6096 StopObservingEvent();
6099 void StopExaminingProc(w, event, prms, nprms)
6105 StopExaminingEvent();
6109 void ForwardProc(w, event, prms, nprms)
6119 void BackwardProc(w, event, prms, nprms)
6128 void ToStartProc(w, event, prms, nprms)
6137 void ToEndProc(w, event, prms, nprms)
6146 void RevertProc(w, event, prms, nprms)
6155 void TruncateGameProc(w, event, prms, nprms)
6161 TruncateGameEvent();
6163 void RetractMoveProc(w, event, prms, nprms)
6172 void MoveNowProc(w, event, prms, nprms)
6182 void AlwaysQueenProc(w, event, prms, nprms)
6190 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6192 if (appData.alwaysPromoteToQueen) {
6193 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6195 XtSetArg(args[0], XtNleftBitmap, None);
6197 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6201 void AnimateDraggingProc(w, event, prms, nprms)
6209 appData.animateDragging = !appData.animateDragging;
6211 if (appData.animateDragging) {
6212 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6215 XtSetArg(args[0], XtNleftBitmap, None);
6217 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6221 void AnimateMovingProc(w, event, prms, nprms)
6229 appData.animate = !appData.animate;
6231 if (appData.animate) {
6232 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6235 XtSetArg(args[0], XtNleftBitmap, None);
6237 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6241 void AutocommProc(w, event, prms, nprms)
6249 appData.autoComment = !appData.autoComment;
6251 if (appData.autoComment) {
6252 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6254 XtSetArg(args[0], XtNleftBitmap, None);
6256 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6261 void AutoflagProc(w, event, prms, nprms)
6269 appData.autoCallFlag = !appData.autoCallFlag;
6271 if (appData.autoCallFlag) {
6272 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6274 XtSetArg(args[0], XtNleftBitmap, None);
6276 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6280 void AutoflipProc(w, event, prms, nprms)
6288 appData.autoFlipView = !appData.autoFlipView;
6290 if (appData.autoFlipView) {
6291 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6293 XtSetArg(args[0], XtNleftBitmap, None);
6295 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6299 void AutobsProc(w, event, prms, nprms)
6307 appData.autoObserve = !appData.autoObserve;
6309 if (appData.autoObserve) {
6310 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6312 XtSetArg(args[0], XtNleftBitmap, None);
6314 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6318 void AutoraiseProc(w, event, prms, nprms)
6326 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6328 if (appData.autoRaiseBoard) {
6329 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6331 XtSetArg(args[0], XtNleftBitmap, None);
6333 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6337 void AutosaveProc(w, event, prms, nprms)
6345 appData.autoSaveGames = !appData.autoSaveGames;
6347 if (appData.autoSaveGames) {
6348 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6350 XtSetArg(args[0], XtNleftBitmap, None);
6352 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6356 void BlindfoldProc(w, event, prms, nprms)
6364 appData.blindfold = !appData.blindfold;
6366 if (appData.blindfold) {
6367 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6369 XtSetArg(args[0], XtNleftBitmap, None);
6371 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6374 DrawPosition(True, NULL);
6377 void TestLegalityProc(w, event, prms, nprms)
6385 appData.testLegality = !appData.testLegality;
6387 if (appData.testLegality) {
6388 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6390 XtSetArg(args[0], XtNleftBitmap, None);
6392 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6397 void FlashMovesProc(w, event, prms, nprms)
6405 if (appData.flashCount == 0) {
6406 appData.flashCount = 3;
6408 appData.flashCount = -appData.flashCount;
6411 if (appData.flashCount > 0) {
6412 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6414 XtSetArg(args[0], XtNleftBitmap, None);
6416 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6420 void FlipViewProc(w, event, prms, nprms)
6426 flipView = !flipView;
6427 DrawPosition(True, NULL);
6430 void GetMoveListProc(w, event, prms, nprms)
6438 appData.getMoveList = !appData.getMoveList;
6440 if (appData.getMoveList) {
6441 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6444 XtSetArg(args[0], XtNleftBitmap, None);
6446 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6451 void HighlightDraggingProc(w, event, prms, nprms)
6459 appData.highlightDragging = !appData.highlightDragging;
6461 if (appData.highlightDragging) {
6462 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6464 XtSetArg(args[0], XtNleftBitmap, None);
6466 XtSetValues(XtNameToWidget(menuBarWidget,
6467 "menuOptions.Highlight Dragging"), args, 1);
6471 void HighlightLastMoveProc(w, event, prms, nprms)
6479 appData.highlightLastMove = !appData.highlightLastMove;
6481 if (appData.highlightLastMove) {
6482 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6484 XtSetArg(args[0], XtNleftBitmap, None);
6486 XtSetValues(XtNameToWidget(menuBarWidget,
6487 "menuOptions.Highlight Last Move"), args, 1);
6490 void IcsAlarmProc(w, event, prms, nprms)
6498 appData.icsAlarm = !appData.icsAlarm;
6500 if (appData.icsAlarm) {
6501 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6503 XtSetArg(args[0], XtNleftBitmap, None);
6505 XtSetValues(XtNameToWidget(menuBarWidget,
6506 "menuOptions.ICS Alarm"), args, 1);
6509 void MoveSoundProc(w, event, prms, nprms)
6517 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6519 if (appData.ringBellAfterMoves) {
6520 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6522 XtSetArg(args[0], XtNleftBitmap, None);
6524 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6529 void OldSaveStyleProc(w, event, prms, nprms)
6537 appData.oldSaveStyle = !appData.oldSaveStyle;
6539 if (appData.oldSaveStyle) {
6540 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6542 XtSetArg(args[0], XtNleftBitmap, None);
6544 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6548 void PeriodicUpdatesProc(w, event, prms, nprms)
6556 PeriodicUpdatesEvent(!appData.periodicUpdates);
6558 if (appData.periodicUpdates) {
6559 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6561 XtSetArg(args[0], XtNleftBitmap, None);
6563 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6567 void PonderNextMoveProc(w, event, prms, nprms)
6575 PonderNextMoveEvent(!appData.ponderNextMove);
6577 if (appData.ponderNextMove) {
6578 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6580 XtSetArg(args[0], XtNleftBitmap, None);
6582 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6586 void PopupExitMessageProc(w, event, prms, nprms)
6594 appData.popupExitMessage = !appData.popupExitMessage;
6596 if (appData.popupExitMessage) {
6597 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6599 XtSetArg(args[0], XtNleftBitmap, None);
6601 XtSetValues(XtNameToWidget(menuBarWidget,
6602 "menuOptions.Popup Exit Message"), args, 1);
6605 void PopupMoveErrorsProc(w, event, prms, nprms)
6613 appData.popupMoveErrors = !appData.popupMoveErrors;
6615 if (appData.popupMoveErrors) {
6616 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6618 XtSetArg(args[0], XtNleftBitmap, None);
6620 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6624 void PremoveProc(w, event, prms, nprms)
6632 appData.premove = !appData.premove;
6634 if (appData.premove) {
6635 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6637 XtSetArg(args[0], XtNleftBitmap, None);
6639 XtSetValues(XtNameToWidget(menuBarWidget,
6640 "menuOptions.Premove"), args, 1);
6643 void QuietPlayProc(w, event, prms, nprms)
6651 appData.quietPlay = !appData.quietPlay;
6653 if (appData.quietPlay) {
6654 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6656 XtSetArg(args[0], XtNleftBitmap, None);
6658 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6662 void ShowCoordsProc(w, event, prms, nprms)
6670 appData.showCoords = !appData.showCoords;
6672 if (appData.showCoords) {
6673 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6675 XtSetArg(args[0], XtNleftBitmap, None);
6677 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6680 DrawPosition(True, NULL);
6683 void ShowThinkingProc(w, event, prms, nprms)
6691 ShowThinkingEvent(!appData.showThinking);
6693 if (appData.showThinking) {
6694 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6696 XtSetArg(args[0], XtNleftBitmap, None);
6698 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6702 void InfoProc(w, event, prms, nprms)
6709 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6714 void ManProc(w, event, prms, nprms)
6722 if (nprms && *nprms > 0)
6726 sprintf(buf, "xterm -e man %s &", name);
6730 void HintProc(w, event, prms, nprms)
6739 void BookProc(w, event, prms, nprms)
6748 void AboutProc(w, event, prms, nprms)
6756 char *zippy = " (with Zippy code)";
6760 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6761 programVersion, zippy,
6762 "Copyright 1991 Digital Equipment Corporation",
6763 "Enhancements Copyright 1992-2001 Free Software Foundation",
6764 PRODUCT, " is free software and carries NO WARRANTY;",
6765 "see the file COPYING for more information.");
6766 ErrorPopUp(_("About XBoard"), buf, FALSE);
6769 void DebugProc(w, event, prms, nprms)
6775 appData.debugMode = !appData.debugMode;
6778 void AboutGameProc(w, event, prms, nprms)
6787 void NothingProc(w, event, prms, nprms)
6796 void Iconify(w, event, prms, nprms)
6805 XtSetArg(args[0], XtNiconic, True);
6806 XtSetValues(shellWidget, args, 1);
6809 void DisplayMessage(message, extMessage)
6810 char *message, *extMessage;
6817 sprintf(buf, "%s %s", message, extMessage);
6820 message = extMessage;
6823 XtSetArg(arg, XtNlabel, message);
6824 XtSetValues(messageWidget, &arg, 1);
6827 void DisplayTitle(text)
6832 char title[MSG_SIZ];
6835 if (text == NULL) text = "";
6837 if (appData.titleInWindow) {
6839 XtSetArg(args[i], XtNlabel, text); i++;
6840 XtSetValues(titleWidget, args, i);
6843 if (*text != NULLCHAR) {
6845 strcpy(title, text);
6846 } else if (appData.icsActive) {
6847 sprintf(icon, "%s", appData.icsHost);
6848 sprintf(title, "%s: %s", programName, appData.icsHost);
6849 } else if (appData.cmailGameName[0] != NULLCHAR) {
6850 sprintf(icon, "%s", "CMail");
6851 sprintf(title, "%s: %s", programName, "CMail");
6852 } else if (appData.noChessProgram) {
6853 strcpy(icon, programName);
6854 strcpy(title, programName);
6856 strcpy(icon, first.tidy);
6857 sprintf(title, "%s: %s", programName, first.tidy);
6860 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6861 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6862 XtSetValues(shellWidget, args, i);
6866 void DisplayError(message, error)
6873 if (appData.debugMode || appData.matchMode) {
6874 fprintf(stderr, "%s: %s\n", programName, message);
6877 if (appData.debugMode || appData.matchMode) {
6878 fprintf(stderr, "%s: %s: %s\n",
6879 programName, message, strerror(error));
6881 sprintf(buf, "%s: %s", message, strerror(error));
6884 ErrorPopUp(_("Error"), message, FALSE);
6888 void DisplayMoveError(message)
6893 DrawPosition(FALSE, NULL);
6894 if (appData.debugMode || appData.matchMode) {
6895 fprintf(stderr, "%s: %s\n", programName, message);
6897 if (appData.popupMoveErrors) {
6898 ErrorPopUp(_("Error"), message, FALSE);
6900 DisplayMessage(message, "");
6905 void DisplayFatalError(message, error, status)
6911 errorExitStatus = status;
6913 fprintf(stderr, "%s: %s\n", programName, message);
6915 fprintf(stderr, "%s: %s: %s\n",
6916 programName, message, strerror(error));
6917 sprintf(buf, "%s: %s", message, strerror(error));
6920 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6921 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6927 void DisplayInformation(message)
6931 ErrorPopUp(_("Information"), message, TRUE);
6934 void DisplayNote(message)
6938 ErrorPopUp(_("Note"), message, FALSE);
6942 NullXErrorCheck(dpy, error_event)
6944 XErrorEvent *error_event;
6949 void DisplayIcsInteractionTitle(message)
6952 if (oldICSInteractionTitle == NULL) {
6953 /* Magic to find the old window title, adapted from vim */
6954 char *wina = getenv("WINDOWID");
6956 Window win = (Window) atoi(wina);
6957 Window root, parent, *children;
6958 unsigned int nchildren;
6959 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6961 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6962 if (!XQueryTree(xDisplay, win, &root, &parent,
6963 &children, &nchildren)) break;
6964 if (children) XFree((void *)children);
6965 if (parent == root || parent == 0) break;
6968 XSetErrorHandler(oldHandler);
6970 if (oldICSInteractionTitle == NULL) {
6971 oldICSInteractionTitle = "xterm";
6974 printf("\033]0;%s\007", message);
6978 char pendingReplyPrefix[MSG_SIZ];
6979 ProcRef pendingReplyPR;
6981 void AskQuestionProc(w, event, prms, nprms)
6988 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6992 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6995 void AskQuestionPopDown()
6997 if (!askQuestionUp) return;
6998 XtPopdown(askQuestionShell);
6999 XtDestroyWidget(askQuestionShell);
7000 askQuestionUp = False;
7003 void AskQuestionReplyAction(w, event, prms, nprms)
7013 reply = XawDialogGetValueString(w = XtParent(w));
7014 strcpy(buf, pendingReplyPrefix);
7015 if (*buf) strcat(buf, " ");
7018 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7019 AskQuestionPopDown();
7021 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7024 void AskQuestionCallback(w, client_data, call_data)
7026 XtPointer client_data, call_data;
7031 XtSetArg(args[0], XtNlabel, &name);
7032 XtGetValues(w, args, 1);
7034 if (strcmp(name, _("cancel")) == 0) {
7035 AskQuestionPopDown();
7037 AskQuestionReplyAction(w, NULL, NULL, NULL);
7041 void AskQuestion(title, question, replyPrefix, pr)
7042 char *title, *question, *replyPrefix;
7046 Widget popup, layout, dialog, edit;
7052 strcpy(pendingReplyPrefix, replyPrefix);
7053 pendingReplyPR = pr;
7056 XtSetArg(args[i], XtNresizable, True); i++;
7057 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7058 askQuestionShell = popup =
7059 XtCreatePopupShell(title, transientShellWidgetClass,
7060 shellWidget, args, i);
7063 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7064 layoutArgs, XtNumber(layoutArgs));
7067 XtSetArg(args[i], XtNlabel, question); i++;
7068 XtSetArg(args[i], XtNvalue, ""); i++;
7069 XtSetArg(args[i], XtNborderWidth, 0); i++;
7070 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7073 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7074 (XtPointer) dialog);
7075 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7076 (XtPointer) dialog);
7078 XtRealizeWidget(popup);
7079 CatchDeleteWindow(popup, "AskQuestionPopDown");
7081 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7082 &x, &y, &win_x, &win_y, &mask);
7084 XtSetArg(args[0], XtNx, x - 10);
7085 XtSetArg(args[1], XtNy, y - 30);
7086 XtSetValues(popup, args, 2);
7088 XtPopup(popup, XtGrabExclusive);
7089 askQuestionUp = True;
7091 edit = XtNameToWidget(dialog, "*value");
7092 XtSetKeyboardFocus(popup, edit);
7100 if (*name == NULLCHAR) {
7102 } else if (strcmp(name, "$") == 0) {
7103 putc(BELLCHAR, stderr);
7106 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7114 PlaySound(appData.soundMove);
7120 PlaySound(appData.soundIcsWin);
7126 PlaySound(appData.soundIcsLoss);
7132 PlaySound(appData.soundIcsDraw);
7136 PlayIcsUnfinishedSound()
7138 PlaySound(appData.soundIcsUnfinished);
7144 PlaySound(appData.soundIcsAlarm);
7150 system("stty echo");
7156 system("stty -echo");
7160 Colorize(cc, continuation)
7165 int count, outCount, error;
7167 if (textColors[(int)cc].bg > 0) {
7168 if (textColors[(int)cc].fg > 0) {
7169 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7170 textColors[(int)cc].fg, textColors[(int)cc].bg);
7172 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7173 textColors[(int)cc].bg);
7176 if (textColors[(int)cc].fg > 0) {
7177 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7178 textColors[(int)cc].fg);
7180 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7183 count = strlen(buf);
7184 outCount = OutputToProcess(NoProc, buf, count, &error);
7185 if (outCount < count) {
7186 DisplayFatalError(_("Error writing to display"), error, 1);
7189 if (continuation) return;
7192 PlaySound(appData.soundShout);
7195 PlaySound(appData.soundSShout);
7198 PlaySound(appData.soundChannel1);
7201 PlaySound(appData.soundChannel);
7204 PlaySound(appData.soundKibitz);
7207 PlaySound(appData.soundTell);
7209 case ColorChallenge:
7210 PlaySound(appData.soundChallenge);
7213 PlaySound(appData.soundRequest);
7216 PlaySound(appData.soundSeek);
7227 return getpwuid(getuid())->pw_name;
7230 static char *ExpandPathName(path)
7233 static char static_buf[2000];
7234 char *d, *s, buf[2000];
7240 while (*s && isspace(*s))
7249 if (*(s+1) == '/') {
7250 strcpy(d, getpwuid(getuid())->pw_dir);
7255 *strchr(buf, '/') = 0;
7256 pwd = getpwnam(buf);
7259 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7263 strcpy(d, pwd->pw_dir);
7264 strcat(d, strchr(s+1, '/'));
7275 static char host_name[MSG_SIZ];
7277 #if HAVE_GETHOSTNAME
7278 gethostname(host_name, MSG_SIZ);
7280 #else /* not HAVE_GETHOSTNAME */
7281 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7282 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7284 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7286 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7287 #endif /* not HAVE_GETHOSTNAME */
7290 XtIntervalId delayedEventTimerXID = 0;
7291 DelayedEventCallback delayedEventCallback = 0;
7296 delayedEventTimerXID = 0;
7297 delayedEventCallback();
7301 ScheduleDelayedEvent(cb, millisec)
7302 DelayedEventCallback cb; long millisec;
7304 delayedEventCallback = cb;
7305 delayedEventTimerXID =
7306 XtAppAddTimeOut(appContext, millisec,
7307 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7310 DelayedEventCallback
7313 if (delayedEventTimerXID) {
7314 return delayedEventCallback;
7321 CancelDelayedEvent()
7323 if (delayedEventTimerXID) {
7324 XtRemoveTimeOut(delayedEventTimerXID);
7325 delayedEventTimerXID = 0;
7329 XtIntervalId loadGameTimerXID = 0;
7331 int LoadGameTimerRunning()
7333 return loadGameTimerXID != 0;
7336 int StopLoadGameTimer()
7338 if (loadGameTimerXID != 0) {
7339 XtRemoveTimeOut(loadGameTimerXID);
7340 loadGameTimerXID = 0;
7348 LoadGameTimerCallback(arg, id)
7352 loadGameTimerXID = 0;
7357 StartLoadGameTimer(millisec)
7361 XtAppAddTimeOut(appContext, millisec,
7362 (XtTimerCallbackProc) LoadGameTimerCallback,
7366 XtIntervalId analysisClockXID = 0;
7369 AnalysisClockCallback(arg, id)
7373 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7374 || appData.icsEngineAnalyze) {
7375 AnalysisPeriodicEvent(0);
7376 StartAnalysisClock();
7381 StartAnalysisClock()
7384 XtAppAddTimeOut(appContext, 2000,
7385 (XtTimerCallbackProc) AnalysisClockCallback,
7389 XtIntervalId clockTimerXID = 0;
7391 int ClockTimerRunning()
7393 return clockTimerXID != 0;
7396 int StopClockTimer()
7398 if (clockTimerXID != 0) {
7399 XtRemoveTimeOut(clockTimerXID);
7408 ClockTimerCallback(arg, id)
7417 StartClockTimer(millisec)
7421 XtAppAddTimeOut(appContext, millisec,
7422 (XtTimerCallbackProc) ClockTimerCallback,
7427 DisplayTimerLabel(w, color, timer, highlight)
7436 if (appData.clockMode) {
7437 sprintf(buf, "%s: %s", color, TimeString(timer));
7438 XtSetArg(args[0], XtNlabel, buf);
7440 sprintf(buf, "%s ", color);
7441 XtSetArg(args[0], XtNlabel, buf);
7445 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7446 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7448 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7449 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7452 XtSetValues(w, args, 3);
7456 DisplayWhiteClock(timeRemaining, highlight)
7461 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
7462 if (highlight && iconPixmap == bIconPixmap) {
7463 iconPixmap = wIconPixmap;
7464 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7465 XtSetValues(shellWidget, args, 1);
7470 DisplayBlackClock(timeRemaining, highlight)
7475 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
7476 if (highlight && iconPixmap == wIconPixmap) {
7477 iconPixmap = bIconPixmap;
7478 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7479 XtSetValues(shellWidget, args, 1);
7497 int StartChildProcess(cmdLine, dir, pr)
7504 int to_prog[2], from_prog[2];
7508 if (appData.debugMode) {
7509 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7512 /* We do NOT feed the cmdLine to the shell; we just
7513 parse it into blank-separated arguments in the
7514 most simple-minded way possible.
7517 strcpy(buf, cmdLine);
7522 if (p == NULL) break;
7527 SetUpChildIO(to_prog, from_prog);
7529 if ((pid = fork()) == 0) {
7531 dup2(to_prog[0], 0);
7532 dup2(from_prog[1], 1);
7535 close(from_prog[0]);
7536 close(from_prog[1]);
7537 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7539 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7544 execvp(argv[0], argv);
7546 /* If we get here, exec failed */
7551 /* Parent process */
7553 close(from_prog[1]);
7555 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7558 cp->fdFrom = from_prog[0];
7559 cp->fdTo = to_prog[1];
7565 DestroyChildProcess(pr, signal)
7569 ChildProc *cp = (ChildProc *) pr;
7571 if (cp->kind != CPReal) return;
7574 kill(cp->pid, SIGTERM);
7576 /* Process is exiting either because of the kill or because of
7577 a quit command sent by the backend; either way, wait for it to die.
7585 InterruptChildProcess(pr)
7588 ChildProc *cp = (ChildProc *) pr;
7590 if (cp->kind != CPReal) return;
7591 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7594 int OpenTelnet(host, port, pr)
7599 char cmdLine[MSG_SIZ];
7601 if (port[0] == NULLCHAR) {
7602 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7604 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7606 return StartChildProcess(cmdLine, "", pr);
7609 int OpenTCP(host, port, pr)
7615 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7616 #else /* !OMIT_SOCKETS */
7618 struct sockaddr_in sa;
7620 unsigned short uport;
7623 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7627 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7628 sa.sin_family = AF_INET;
7629 sa.sin_addr.s_addr = INADDR_ANY;
7630 uport = (unsigned short) 0;
7631 sa.sin_port = htons(uport);
7632 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7636 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7637 if (!(hp = gethostbyname(host))) {
7639 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7640 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7641 hp->h_addrtype = AF_INET;
7643 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7644 hp->h_addr_list[0] = (char *) malloc(4);
7645 hp->h_addr_list[0][0] = b0;
7646 hp->h_addr_list[0][1] = b1;
7647 hp->h_addr_list[0][2] = b2;
7648 hp->h_addr_list[0][3] = b3;
7653 sa.sin_family = hp->h_addrtype;
7654 uport = (unsigned short) atoi(port);
7655 sa.sin_port = htons(uport);
7656 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7658 if (connect(s, (struct sockaddr *) &sa,
7659 sizeof(struct sockaddr_in)) < 0) {
7663 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7670 #endif /* !OMIT_SOCKETS */
7675 int OpenCommPort(name, pr)
7682 fd = open(name, 2, 0);
7683 if (fd < 0) return errno;
7685 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7695 int OpenLoopback(pr)
7701 SetUpChildIO(to, from);
7703 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7706 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7713 int OpenRcmd(host, user, cmd, pr)
7714 char *host, *user, *cmd;
7717 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7721 #define INPUT_SOURCE_BUF_SIZE 8192
7730 char buf[INPUT_SOURCE_BUF_SIZE];
7735 DoInputCallback(closure, source, xid)
7740 InputSource *is = (InputSource *) closure;
7745 if (is->lineByLine) {
7746 count = read(is->fd, is->unused,
7747 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7749 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7752 is->unused += count;
7754 while (p < is->unused) {
7755 q = memchr(p, '\n', is->unused - p);
7756 if (q == NULL) break;
7758 (is->func)(is, is->closure, p, q - p, 0);
7762 while (p < is->unused) {
7767 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7772 (is->func)(is, is->closure, is->buf, count, error);
7776 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7783 ChildProc *cp = (ChildProc *) pr;
7785 is = (InputSource *) calloc(1, sizeof(InputSource));
7786 is->lineByLine = lineByLine;
7790 is->fd = fileno(stdin);
7792 is->kind = cp->kind;
7793 is->fd = cp->fdFrom;
7796 is->unused = is->buf;
7799 is->xid = XtAppAddInput(appContext, is->fd,
7800 (XtPointer) (XtInputReadMask),
7801 (XtInputCallbackProc) DoInputCallback,
7803 is->closure = closure;
7804 return (InputSourceRef) is;
7808 RemoveInputSource(isr)
7811 InputSource *is = (InputSource *) isr;
7813 if (is->xid == 0) return;
7814 XtRemoveInput(is->xid);
7818 int OutputToProcess(pr, message, count, outError)
7824 ChildProc *cp = (ChildProc *) pr;
7828 outCount = fwrite(message, 1, count, stdout);
7830 outCount = write(cp->fdTo, message, count);
7840 /* Output message to process, with "ms" milliseconds of delay
7841 between each character. This is needed when sending the logon
7842 script to ICC, which for some reason doesn't like the
7843 instantaneous send. */
7844 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7851 ChildProc *cp = (ChildProc *) pr;
7856 r = write(cp->fdTo, message++, 1);
7869 /**** Animation code by Hugh Fisher, DCS, ANU.
7871 Known problem: if a window overlapping the board is
7872 moved away while a piece is being animated underneath,
7873 the newly exposed area won't be updated properly.
7874 I can live with this.
7876 Known problem: if you look carefully at the animation
7877 of pieces in mono mode, they are being drawn as solid
7878 shapes without interior detail while moving. Fixing
7879 this would be a major complication for minimal return.
7882 /* Masks for XPM pieces. Black and white pieces can have
7883 different shapes, but in the interest of retaining my
7884 sanity pieces must have the same outline on both light
7885 and dark squares, and all pieces must use the same
7886 background square colors/images. */
7889 CreateAnimMasks (pieceDepth)
7896 unsigned long plane;
7899 /* Need a bitmap just to get a GC with right depth */
7900 buf = XCreatePixmap(xDisplay, xBoardWindow,
7902 values.foreground = 1;
7903 values.background = 0;
7904 /* Don't use XtGetGC, not read only */
7905 maskGC = XCreateGC(xDisplay, buf,
7906 GCForeground | GCBackground, &values);
7907 XFreePixmap(xDisplay, buf);
7909 buf = XCreatePixmap(xDisplay, xBoardWindow,
7910 squareSize, squareSize, pieceDepth);
7911 values.foreground = XBlackPixel(xDisplay, xScreen);
7912 values.background = XWhitePixel(xDisplay, xScreen);
7913 bufGC = XCreateGC(xDisplay, buf,
7914 GCForeground | GCBackground, &values);
7916 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7917 /* Begin with empty mask */
7918 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7919 squareSize, squareSize, 1);
7920 XSetFunction(xDisplay, maskGC, GXclear);
7921 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7922 0, 0, squareSize, squareSize);
7924 /* Take a copy of the piece */
7929 XSetFunction(xDisplay, bufGC, GXcopy);
7930 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7932 0, 0, squareSize, squareSize, 0, 0);
7934 /* XOR the background (light) over the piece */
7935 XSetFunction(xDisplay, bufGC, GXxor);
7937 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7938 0, 0, squareSize, squareSize, 0, 0);
7940 XSetForeground(xDisplay, bufGC, lightSquareColor);
7941 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7944 /* We now have an inverted piece image with the background
7945 erased. Construct mask by just selecting all the non-zero
7946 pixels - no need to reconstruct the original image. */
7947 XSetFunction(xDisplay, maskGC, GXor);
7949 /* Might be quicker to download an XImage and create bitmap
7950 data from it rather than this N copies per piece, but it
7951 only takes a fraction of a second and there is a much
7952 longer delay for loading the pieces. */
7953 for (n = 0; n < pieceDepth; n ++) {
7954 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7955 0, 0, squareSize, squareSize,
7961 XFreePixmap(xDisplay, buf);
7962 XFreeGC(xDisplay, bufGC);
7963 XFreeGC(xDisplay, maskGC);
7967 InitAnimState (anim, info)
7969 XWindowAttributes * info;
7974 /* Each buffer is square size, same depth as window */
7975 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7976 squareSize, squareSize, info->depth);
7977 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7978 squareSize, squareSize, info->depth);
7980 /* Create a plain GC for blitting */
7981 mask = GCForeground | GCBackground | GCFunction |
7982 GCPlaneMask | GCGraphicsExposures;
7983 values.foreground = XBlackPixel(xDisplay, xScreen);
7984 values.background = XWhitePixel(xDisplay, xScreen);
7985 values.function = GXcopy;
7986 values.plane_mask = AllPlanes;
7987 values.graphics_exposures = False;
7988 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7990 /* Piece will be copied from an existing context at
7991 the start of each new animation/drag. */
7992 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7994 /* Outline will be a read-only copy of an existing */
7995 anim->outlineGC = None;
8001 static int done = 0;
8002 XWindowAttributes info;
8006 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8008 InitAnimState(&game, &info);
8009 InitAnimState(&player, &info);
8011 /* For XPM pieces, we need bitmaps to use as masks. */
8013 CreateAnimMasks(info.depth);
8018 static Boolean frameWaiting;
8020 static RETSIGTYPE FrameAlarm (sig)
8023 frameWaiting = False;
8024 /* In case System-V style signals. Needed?? */
8025 signal(SIGALRM, FrameAlarm);
8032 struct itimerval delay;
8034 XSync(xDisplay, False);
8037 frameWaiting = True;
8038 signal(SIGALRM, FrameAlarm);
8039 delay.it_interval.tv_sec =
8040 delay.it_value.tv_sec = time / 1000;
8041 delay.it_interval.tv_usec =
8042 delay.it_value.tv_usec = (time % 1000) * 1000;
8043 setitimer(ITIMER_REAL, &delay, NULL);
8045 /* Ugh -- busy-wait! --tpm */
8046 while (frameWaiting);
8048 while (frameWaiting) pause();
8050 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8051 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8052 setitimer(ITIMER_REAL, &delay, NULL);
8062 XSync(xDisplay, False);
8064 usleep(time * 1000);
8069 /* Convert board position to corner of screen rect and color */
8072 ScreenSquare(column, row, pt, color)
8073 int column; int row; XPoint * pt; int * color;
8076 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
8077 pt->y = lineGap + row * (squareSize + lineGap);
8079 pt->x = lineGap + column * (squareSize + lineGap);
8080 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
8082 *color = ((column + row) % 2) == 1;
8085 /* Convert window coords to square */
8088 BoardSquare(x, y, column, row)
8089 int x; int y; int * column; int * row;
8091 *column = EventToSquare(x, BOARD_SIZE);
8092 if (flipView && *column >= 0)
8093 *column = BOARD_SIZE - 1 - *column;
8094 *row = EventToSquare(y, BOARD_SIZE);
8095 if (!flipView && *row >= 0)
8096 *row = BOARD_SIZE - 1 - *row;
8101 #undef Max /* just in case */
8103 #define Max(a, b) ((a) > (b) ? (a) : (b))
8104 #define Min(a, b) ((a) < (b) ? (a) : (b))
8107 SetRect(rect, x, y, width, height)
8108 XRectangle * rect; int x; int y; int width; int height;
8112 rect->width = width;
8113 rect->height = height;
8116 /* Test if two frames overlap. If they do, return
8117 intersection rect within old and location of
8118 that rect within new. */
8121 Intersect(old, new, size, area, pt)
8122 XPoint * old; XPoint * new;
8123 int size; XRectangle * area; XPoint * pt;
8125 if (old->x > new->x + size || new->x > old->x + size ||
8126 old->y > new->y + size || new->y > old->y + size) {
8129 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8130 size - abs(old->x - new->x), size - abs(old->y - new->y));
8131 pt->x = Max(old->x - new->x, 0);
8132 pt->y = Max(old->y - new->y, 0);
8137 /* For two overlapping frames, return the rect(s)
8138 in the old that do not intersect with the new. */
8141 CalcUpdateRects(old, new, size, update, nUpdates)
8142 XPoint * old; XPoint * new; int size;
8143 XRectangle update[]; int * nUpdates;
8147 /* If old = new (shouldn't happen) then nothing to draw */
8148 if (old->x == new->x && old->y == new->y) {
8152 /* Work out what bits overlap. Since we know the rects
8153 are the same size we don't need a full intersect calc. */
8155 /* Top or bottom edge? */
8156 if (new->y > old->y) {
8157 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8159 } else if (old->y > new->y) {
8160 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8161 size, old->y - new->y);
8164 /* Left or right edge - don't overlap any update calculated above. */
8165 if (new->x > old->x) {
8166 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8167 new->x - old->x, size - abs(new->y - old->y));
8169 } else if (old->x > new->x) {
8170 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8171 old->x - new->x, size - abs(new->y - old->y));
8178 /* Generate a series of frame coords from start->mid->finish.
8179 The movement rate doubles until the half way point is
8180 reached, then halves back down to the final destination,
8181 which gives a nice slow in/out effect. The algorithmn
8182 may seem to generate too many intermediates for short
8183 moves, but remember that the purpose is to attract the
8184 viewers attention to the piece about to be moved and
8185 then to where it ends up. Too few frames would be less
8189 Tween(start, mid, finish, factor, frames, nFrames)
8190 XPoint * start; XPoint * mid;
8191 XPoint * finish; int factor;
8192 XPoint frames[]; int * nFrames;
8194 int fraction, n, count;
8198 /* Slow in, stepping 1/16th, then 1/8th, ... */
8200 for (n = 0; n < factor; n++)
8202 for (n = 0; n < factor; n++) {
8203 frames[count].x = start->x + (mid->x - start->x) / fraction;
8204 frames[count].y = start->y + (mid->y - start->y) / fraction;
8206 fraction = fraction / 2;
8210 frames[count] = *mid;
8213 /* Slow out, stepping 1/2, then 1/4, ... */
8215 for (n = 0; n < factor; n++) {
8216 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8217 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8219 fraction = fraction * 2;
8224 /* Draw a piece on the screen without disturbing what's there */
8227 SelectGCMask(piece, clip, outline, mask)
8228 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8232 /* Bitmap for piece being moved. */
8233 if (appData.monoMode) {
8234 *mask = *pieceToSolid(piece);
8235 } else if (useImages) {
8237 *mask = xpmMask[piece];
8239 *mask = ximMaskPm[piece%6];
8242 *mask = *pieceToSolid(piece);
8245 /* GC for piece being moved. Square color doesn't matter, but
8246 since it gets modified we make a copy of the original. */
8248 if (appData.monoMode)
8253 if (appData.monoMode)
8258 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8260 /* Outline only used in mono mode and is not modified */
8262 *outline = bwPieceGC;
8264 *outline = wbPieceGC;
8268 OverlayPiece(piece, clip, outline, dest)
8269 ChessSquare piece; GC clip; GC outline; Drawable dest;
8274 /* Draw solid rectangle which will be clipped to shape of piece */
8275 XFillRectangle(xDisplay, dest, clip,
8276 0, 0, squareSize, squareSize);
8277 if (appData.monoMode)
8278 /* Also draw outline in contrasting color for black
8279 on black / white on white cases */
8280 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8281 0, 0, squareSize, squareSize, 0, 0, 1);
8283 /* Copy the piece */
8288 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8290 0, 0, squareSize, squareSize,
8295 /* Animate the movement of a single piece */
8298 BeginAnimation(anim, piece, startColor, start)
8306 /* The old buffer is initialised with the start square (empty) */
8307 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8308 anim->prevFrame = *start;
8310 /* The piece will be drawn using its own bitmap as a matte */
8311 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8312 XSetClipMask(xDisplay, anim->pieceGC, mask);
8316 AnimationFrame(anim, frame, piece)
8321 XRectangle updates[4];
8326 /* Save what we are about to draw into the new buffer */
8327 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8328 frame->x, frame->y, squareSize, squareSize,
8331 /* Erase bits of the previous frame */
8332 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8333 /* Where the new frame overlapped the previous,
8334 the contents in newBuf are wrong. */
8335 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8336 overlap.x, overlap.y,
8337 overlap.width, overlap.height,
8339 /* Repaint the areas in the old that don't overlap new */
8340 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8341 for (i = 0; i < count; i++)
8342 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8343 updates[i].x - anim->prevFrame.x,
8344 updates[i].y - anim->prevFrame.y,
8345 updates[i].width, updates[i].height,
8346 updates[i].x, updates[i].y);
8348 /* Easy when no overlap */
8349 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8350 0, 0, squareSize, squareSize,
8351 anim->prevFrame.x, anim->prevFrame.y);
8354 /* Save this frame for next time round */
8355 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8356 0, 0, squareSize, squareSize,
8358 anim->prevFrame = *frame;
8360 /* Draw piece over original screen contents, not current,
8361 and copy entire rect. Wipes out overlapping piece images. */
8362 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8363 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8364 0, 0, squareSize, squareSize,
8365 frame->x, frame->y);
8369 EndAnimation (anim, finish)
8373 XRectangle updates[4];
8378 /* The main code will redraw the final square, so we
8379 only need to erase the bits that don't overlap. */
8380 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8381 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8382 for (i = 0; i < count; i++)
8383 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8384 updates[i].x - anim->prevFrame.x,
8385 updates[i].y - anim->prevFrame.y,
8386 updates[i].width, updates[i].height,
8387 updates[i].x, updates[i].y);
8389 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8390 0, 0, squareSize, squareSize,
8391 anim->prevFrame.x, anim->prevFrame.y);
8396 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8398 ChessSquare piece; int startColor;
8399 XPoint * start; XPoint * finish;
8400 XPoint frames[]; int nFrames;
8404 BeginAnimation(anim, piece, startColor, start);
8405 for (n = 0; n < nFrames; n++) {
8406 AnimationFrame(anim, &(frames[n]), piece);
8407 FrameDelay(appData.animSpeed);
8409 EndAnimation(anim, finish);
8412 /* Main control logic for deciding what to animate and how */
8415 AnimateMove(board, fromX, fromY, toX, toY)
8424 XPoint start, finish, mid;
8425 XPoint frames[kFactor * 2 + 1];
8426 int nFrames, startColor, endColor;
8428 /* Are we animating? */
8429 if (!appData.animate || appData.blindfold)
8432 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8433 piece = board[fromY][fromX];
8434 if (piece >= EmptySquare) return;
8439 hop = (piece == WhiteKnight || piece == BlackKnight);
8442 if (appData.debugMode) {
8443 printf(hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8444 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8445 piece, fromX, fromY, toX, toY);
8448 ScreenSquare(fromX, fromY, &start, &startColor);
8449 ScreenSquare(toX, toY, &finish, &endColor);
8452 /* Knight: make diagonal movement then straight */
8453 if (abs(toY - fromY) < abs(toX - fromX)) {
8454 mid.x = start.x + (finish.x - start.x) / 2;
8458 mid.y = start.y + (finish.y - start.y) / 2;
8461 mid.x = start.x + (finish.x - start.x) / 2;
8462 mid.y = start.y + (finish.y - start.y) / 2;
8465 /* Don't use as many frames for very short moves */
8466 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8467 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8469 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8470 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8472 /* Be sure end square is redrawn */
8473 damage[toY][toX] = True;
8477 DragPieceBegin(x, y)
8480 int boardX, boardY, color;
8483 /* Are we animating? */
8484 if (!appData.animateDragging || appData.blindfold)
8487 /* Figure out which square we start in and the
8488 mouse position relative to top left corner. */
8489 BoardSquare(x, y, &boardX, &boardY);
8490 player.startBoardX = boardX;
8491 player.startBoardY = boardY;
8492 ScreenSquare(boardX, boardY, &corner, &color);
8493 player.startSquare = corner;
8494 player.startColor = color;
8496 /* Start from exactly where the piece is. This can be confusing
8497 if you start dragging far from the center of the square; most
8498 or all of the piece can be over a different square from the one
8499 the mouse pointer is in. */
8500 player.mouseDelta.x = x - corner.x;
8501 player.mouseDelta.y = y - corner.y;
8503 /* As soon as we start dragging, the piece will jump slightly to
8504 be centered over the mouse pointer. */
8505 player.mouseDelta.x = squareSize/2;
8506 player.mouseDelta.y = squareSize/2;
8508 /* Initialise animation */
8509 player.dragPiece = PieceForSquare(boardX, boardY);
8511 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8512 player.dragActive = True;
8513 BeginAnimation(&player, player.dragPiece, color, &corner);
8514 /* Mark this square as needing to be redrawn. Note that
8515 we don't remove the piece though, since logically (ie
8516 as seen by opponent) the move hasn't been made yet. */
8517 damage[boardY][boardX] = True;
8519 player.dragActive = False;
8529 /* Are we animating? */
8530 if (!appData.animateDragging || appData.blindfold)
8534 if (! player.dragActive)
8536 /* Move piece, maintaining same relative position
8537 of mouse within square */
8538 corner.x = x - player.mouseDelta.x;
8539 corner.y = y - player.mouseDelta.y;
8540 AnimationFrame(&player, &corner, player.dragPiece);
8542 if (appData.highlightDragging) {
8544 BoardSquare(x, y, &boardX, &boardY);
8545 SetHighlights(fromX, fromY, boardX, boardY);
8554 int boardX, boardY, color;
8557 /* Are we animating? */
8558 if (!appData.animateDragging || appData.blindfold)
8562 if (! player.dragActive)
8564 /* Last frame in sequence is square piece is
8565 placed on, which may not match mouse exactly. */
8566 BoardSquare(x, y, &boardX, &boardY);
8567 ScreenSquare(boardX, boardY, &corner, &color);
8568 EndAnimation(&player, &corner);
8570 /* Be sure end square is redrawn */
8571 damage[boardY][boardX] = True;
8573 /* This prevents weird things happening with fast successive
8574 clicks which on my Sun at least can cause motion events
8575 without corresponding press/release. */
8576 player.dragActive = False;
8579 /* Handle expose event while piece being dragged */
8584 if (!player.dragActive || appData.blindfold)
8587 /* What we're doing: logically, the move hasn't been made yet,
8588 so the piece is still in it's original square. But visually
8589 it's being dragged around the board. So we erase the square
8590 that the piece is on and draw it at the last known drag point. */
8591 BlankSquare(player.startSquare.x, player.startSquare.y,
8592 player.startColor, EmptySquare, xBoardWindow);
8593 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8594 damage[player.startBoardY][player.startBoardX] = TRUE;