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 bind_textdomain_codeset(PRODUCT, "UTF-8");
1877 textdomain(PRODUCT);
1881 XtAppInitialize(&appContext, "XBoard", shellOptions,
1882 XtNumber(shellOptions),
1883 &argc, argv, xboardResources, NULL, 0);
1885 fprintf(stderr, _("%s: unrecognized argument %s\n"),
1886 programName, argv[1]);
1890 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1893 if (chdir(chessDir) != 0) {
1894 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1901 if (p == NULL) p = "/tmp";
1902 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1903 gameCopyFilename = (char*) malloc(i);
1904 gamePasteFilename = (char*) malloc(i);
1905 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1906 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1908 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1909 clientResources, XtNumber(clientResources),
1912 if (appData.debugMode) {
1913 if ((debugFP = fopen("xboard.debug", "w")) == NULL) {
1914 printf(_("Failed to open file xboard.debug \n"));
1917 setbuf(debugFP, NULL);
1921 /* This feature does not work; animation needs a rewrite */
1922 appData.highlightDragging = FALSE;
1926 xDisplay = XtDisplay(shellWidget);
1927 xScreen = DefaultScreen(xDisplay);
1928 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1931 * Determine boardSize
1933 if (isdigit(appData.boardSize[0])) {
1934 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1935 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1936 &fontPxlSize, &smallLayout, &tinyLayout);
1938 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1939 programName, appData.boardSize);
1943 /* Find some defaults; use the nearest known size */
1944 SizeDefaults *szd, *nearest;
1945 int distance = 99999;
1946 nearest = szd = sizeDefaults;
1947 while (szd->name != NULL) {
1948 if (abs(szd->squareSize - squareSize) < distance) {
1950 distance = abs(szd->squareSize - squareSize);
1951 if (distance == 0) break;
1955 if (i < 2) lineGap = nearest->lineGap;
1956 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1957 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1958 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1959 if (i < 6) smallLayout = nearest->smallLayout;
1960 if (i < 7) tinyLayout = nearest->tinyLayout;
1963 SizeDefaults *szd = sizeDefaults;
1964 if (*appData.boardSize == NULLCHAR) {
1965 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1966 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1969 if (szd->name == NULL) szd--;
1971 while (szd->name != NULL &&
1972 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1973 if (szd->name == NULL) {
1974 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1975 programName, appData.boardSize);
1979 squareSize = szd->squareSize;
1980 lineGap = szd->lineGap;
1981 clockFontPxlSize = szd->clockFontPxlSize;
1982 coordFontPxlSize = szd->coordFontPxlSize;
1983 fontPxlSize = szd->fontPxlSize;
1984 smallLayout = szd->smallLayout;
1985 tinyLayout = szd->tinyLayout;
1988 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1989 if (strlen(appData.pixmapDirectory) > 0) {
1990 p = ExpandPathName(appData.pixmapDirectory);
1992 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1993 appData.pixmapDirectory);
1996 if (appData.debugMode) {
1997 fprintf(stderr, _("\
1998 XBoard square size (hint): %d\n\
1999 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
2001 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
2002 if (appData.debugMode) {
2003 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
2007 boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
2008 if (appData.showJail == 1) {
2009 /* Jail on top and bottom */
2010 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2011 XtSetArg(boardArgs[2], XtNheight,
2012 boardWidth + 2*(lineGap + squareSize));
2013 } else if (appData.showJail == 2) {
2015 XtSetArg(boardArgs[1], XtNwidth,
2016 boardWidth + 2*(lineGap + squareSize));
2017 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2020 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2021 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2025 * Determine what fonts to use.
2027 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2028 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2029 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2030 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2031 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2032 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2033 appData.font = FindFont(appData.font, fontPxlSize);
2035 xdb = XtDatabase(xDisplay);
2036 XrmPutStringResource(&xdb, "*font", appData.font);
2039 * Detect if there are not enough colors available and adapt.
2041 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2042 appData.monoMode = True;
2045 if (!appData.monoMode) {
2046 vFrom.addr = (caddr_t) appData.lightSquareColor;
2047 vFrom.size = strlen(appData.lightSquareColor);
2048 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2049 if (vTo.addr == NULL) {
2050 appData.monoMode = True;
2053 lightSquareColor = *(Pixel *) vTo.addr;
2056 if (!appData.monoMode) {
2057 vFrom.addr = (caddr_t) appData.darkSquareColor;
2058 vFrom.size = strlen(appData.darkSquareColor);
2059 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2060 if (vTo.addr == NULL) {
2061 appData.monoMode = True;
2064 darkSquareColor = *(Pixel *) vTo.addr;
2067 if (!appData.monoMode) {
2068 vFrom.addr = (caddr_t) appData.whitePieceColor;
2069 vFrom.size = strlen(appData.whitePieceColor);
2070 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2071 if (vTo.addr == NULL) {
2072 appData.monoMode = True;
2075 whitePieceColor = *(Pixel *) vTo.addr;
2078 if (!appData.monoMode) {
2079 vFrom.addr = (caddr_t) appData.blackPieceColor;
2080 vFrom.size = strlen(appData.blackPieceColor);
2081 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2082 if (vTo.addr == NULL) {
2083 appData.monoMode = True;
2086 blackPieceColor = *(Pixel *) vTo.addr;
2090 if (!appData.monoMode) {
2091 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2092 vFrom.size = strlen(appData.highlightSquareColor);
2093 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2094 if (vTo.addr == NULL) {
2095 appData.monoMode = True;
2098 highlightSquareColor = *(Pixel *) vTo.addr;
2102 if (!appData.monoMode) {
2103 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2104 vFrom.size = strlen(appData.premoveHighlightColor);
2105 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2106 if (vTo.addr == NULL) {
2107 appData.monoMode = True;
2110 premoveHighlightColor = *(Pixel *) vTo.addr;
2115 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2119 if (appData.monoMode && appData.debugMode) {
2120 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2121 (unsigned long) XWhitePixel(xDisplay, xScreen),
2122 (unsigned long) XBlackPixel(xDisplay, xScreen));
2125 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2126 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2127 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2128 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2129 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2130 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2131 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2132 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2133 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2134 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2136 if (appData.colorize) {
2138 _("%s: can't parse color names; disabling colorization\n"),
2141 appData.colorize = FALSE;
2143 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2144 textColors[ColorNone].attr = 0;
2146 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2152 layoutName = "tinyLayout";
2153 } else if (smallLayout) {
2154 layoutName = "smallLayout";
2156 layoutName = "normalLayout";
2158 /* Outer layoutWidget is there only to provide a name for use in
2159 resources that depend on the layout style */
2161 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2162 layoutArgs, XtNumber(layoutArgs));
2164 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2165 formArgs, XtNumber(formArgs));
2166 XtSetArg(args[0], XtNdefaultDistance, &sep);
2167 XtGetValues(formWidget, args, 1);
2170 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2172 widgetList[j++] = whiteTimerWidget =
2173 XtCreateWidget("whiteTime", labelWidgetClass,
2174 formWidget, timerArgs, XtNumber(timerArgs));
2175 XtSetArg(args[0], XtNfont, clockFontStruct);
2176 XtSetValues(whiteTimerWidget, args, 1);
2178 widgetList[j++] = blackTimerWidget =
2179 XtCreateWidget("blackTime", labelWidgetClass,
2180 formWidget, timerArgs, XtNumber(timerArgs));
2181 XtSetArg(args[0], XtNfont, clockFontStruct);
2182 XtSetValues(blackTimerWidget, args, 1);
2184 if (appData.titleInWindow) {
2185 widgetList[j++] = titleWidget =
2186 XtCreateWidget("title", labelWidgetClass, formWidget,
2187 titleArgs, XtNumber(titleArgs));
2190 if (appData.showButtonBar) {
2191 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2194 widgetList[j++] = messageWidget =
2195 XtCreateWidget("message", labelWidgetClass, formWidget,
2196 messageArgs, XtNumber(messageArgs));
2198 widgetList[j++] = boardWidget =
2199 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2200 XtNumber(boardArgs));
2202 XtManageChildren(widgetList, j);
2204 timerWidth = (boardWidth - sep) / 2;
2205 XtSetArg(args[0], XtNwidth, timerWidth);
2206 XtSetValues(whiteTimerWidget, args, 1);
2207 XtSetValues(blackTimerWidget, args, 1);
2209 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2210 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2211 XtGetValues(whiteTimerWidget, args, 2);
2213 if (appData.showButtonBar) {
2214 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2215 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2216 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2220 * formWidget uses these constraints but they are stored
2224 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2225 XtSetValues(menuBarWidget, args, i);
2226 if (appData.titleInWindow) {
2229 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2230 XtSetValues(whiteTimerWidget, args, i);
2232 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2233 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2234 XtSetValues(blackTimerWidget, args, i);
2236 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2237 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2238 XtSetValues(titleWidget, args, i);
2240 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2241 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2242 XtSetValues(messageWidget, args, i);
2243 if (appData.showButtonBar) {
2245 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2246 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2247 XtSetValues(buttonBarWidget, args, i);
2251 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2252 XtSetValues(whiteTimerWidget, args, i);
2254 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2255 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2256 XtSetValues(blackTimerWidget, args, i);
2258 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2259 XtSetValues(titleWidget, args, i);
2261 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2262 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2263 XtSetValues(messageWidget, args, i);
2264 if (appData.showButtonBar) {
2266 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2267 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2268 XtSetValues(buttonBarWidget, args, i);
2273 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2274 XtSetValues(whiteTimerWidget, args, i);
2276 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2277 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2278 XtSetValues(blackTimerWidget, args, i);
2280 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2281 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2282 XtSetValues(messageWidget, args, i);
2283 if (appData.showButtonBar) {
2285 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2286 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2287 XtSetValues(buttonBarWidget, args, i);
2291 XtSetArg(args[0], XtNfromVert, messageWidget);
2292 XtSetValues(boardWidget, args, 1);
2294 XtRealizeWidget(shellWidget);
2297 * Correct the width of the message and title widgets.
2298 * It is not known why some systems need the extra fudge term.
2299 * The value "2" is probably larger than needed.
2301 XawFormDoLayout(formWidget, False);
2302 #define WIDTH_FUDGE 2
2304 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2305 XtSetArg(args[i], XtNheight, &h); i++;
2306 XtGetValues(messageWidget, args, i);
2307 if (appData.showButtonBar) {
2309 XtSetArg(args[i], XtNwidth, &w); i++;
2310 XtGetValues(buttonBarWidget, args, i);
2311 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2313 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2316 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2317 if (gres != XtGeometryYes && appData.debugMode) {
2318 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2319 programName, gres, w, h, wr, hr);
2322 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2323 /* The size used for the child widget in layout lags one resize behind
2324 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2326 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2327 if (gres != XtGeometryYes && appData.debugMode) {
2328 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2329 programName, gres, w, h, wr, hr);
2333 if (appData.titleInWindow) {
2335 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2336 XtSetArg(args[i], XtNheight, &h); i++;
2337 XtGetValues(titleWidget, args, i);
2339 w = boardWidth - 2*bor;
2341 XtSetArg(args[0], XtNwidth, &w);
2342 XtGetValues(menuBarWidget, args, 1);
2343 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2346 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2347 if (gres != XtGeometryYes && appData.debugMode) {
2349 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2350 programName, gres, w, h, wr, hr);
2353 XawFormDoLayout(formWidget, True);
2355 xBoardWindow = XtWindow(boardWidget);
2358 * Create X checkmark bitmap and initialize option menu checks.
2360 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2361 checkmark_bits, checkmark_width, checkmark_height);
2362 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2363 if (appData.alwaysPromoteToQueen) {
2364 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2367 if (appData.animateDragging) {
2368 XtSetValues(XtNameToWidget(menuBarWidget,
2369 "menuOptions.Animate Dragging"),
2372 if (appData.animate) {
2373 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2376 if (appData.autoComment) {
2377 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2380 if (appData.autoCallFlag) {
2381 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2384 if (appData.autoFlipView) {
2385 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2388 if (appData.autoObserve) {
2389 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2392 if (appData.autoRaiseBoard) {
2393 XtSetValues(XtNameToWidget(menuBarWidget,
2394 "menuOptions.Auto Raise Board"), args, 1);
2396 if (appData.autoSaveGames) {
2397 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2400 if (appData.saveGameFile[0] != NULLCHAR) {
2401 /* Can't turn this off from menu */
2402 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2404 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2408 if (appData.blindfold) {
2409 XtSetValues(XtNameToWidget(menuBarWidget,
2410 "menuOptions.Blindfold"), args, 1);
2412 if (appData.flashCount > 0) {
2413 XtSetValues(XtNameToWidget(menuBarWidget,
2414 "menuOptions.Flash Moves"),
2417 if (appData.getMoveList) {
2418 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2422 if (appData.highlightDragging) {
2423 XtSetValues(XtNameToWidget(menuBarWidget,
2424 "menuOptions.Highlight Dragging"),
2428 if (appData.highlightLastMove) {
2429 XtSetValues(XtNameToWidget(menuBarWidget,
2430 "menuOptions.Highlight Last Move"),
2433 if (appData.icsAlarm) {
2434 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2437 if (appData.ringBellAfterMoves) {
2438 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2441 if (appData.oldSaveStyle) {
2442 XtSetValues(XtNameToWidget(menuBarWidget,
2443 "menuOptions.Old Save Style"), args, 1);
2445 if (appData.periodicUpdates) {
2446 XtSetValues(XtNameToWidget(menuBarWidget,
2447 "menuOptions.Periodic Updates"), args, 1);
2449 if (appData.ponderNextMove) {
2450 XtSetValues(XtNameToWidget(menuBarWidget,
2451 "menuOptions.Ponder Next Move"), args, 1);
2453 if (appData.popupExitMessage) {
2454 XtSetValues(XtNameToWidget(menuBarWidget,
2455 "menuOptions.Popup Exit Message"), args, 1);
2457 if (appData.popupMoveErrors) {
2458 XtSetValues(XtNameToWidget(menuBarWidget,
2459 "menuOptions.Popup Move Errors"), args, 1);
2461 if (appData.premove) {
2462 XtSetValues(XtNameToWidget(menuBarWidget,
2463 "menuOptions.Premove"), args, 1);
2465 if (appData.quietPlay) {
2466 XtSetValues(XtNameToWidget(menuBarWidget,
2467 "menuOptions.Quiet Play"), args, 1);
2469 if (appData.showCoords) {
2470 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2473 if (appData.showThinking) {
2474 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2477 if (appData.testLegality) {
2478 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2485 ReadBitmap(&wIconPixmap, "icon_white.bm",
2486 icon_white_bits, icon_white_width, icon_white_height);
2487 ReadBitmap(&bIconPixmap, "icon_black.bm",
2488 icon_black_bits, icon_black_width, icon_black_height);
2489 iconPixmap = wIconPixmap;
2491 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2492 XtSetValues(shellWidget, args, i);
2495 * Create a cursor for the board widget.
2497 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2498 XChangeWindowAttributes(xDisplay, xBoardWindow,
2499 CWCursor, &window_attributes);
2502 * Inhibit shell resizing.
2504 shellArgs[0].value = (XtArgVal) &w;
2505 shellArgs[1].value = (XtArgVal) &h;
2506 XtGetValues(shellWidget, shellArgs, 2);
2507 shellArgs[4].value = shellArgs[2].value = w;
2508 shellArgs[5].value = shellArgs[3].value = h;
2509 XtSetValues(shellWidget, &shellArgs[2], 4);
2511 CatchDeleteWindow(shellWidget, "QuitProc");
2516 if (appData.bitmapDirectory[0] != NULLCHAR) {
2523 /* Create regular pieces */
2524 if (!useImages) CreatePieces();
2529 if (appData.animate || appData.animateDragging)
2532 XtAugmentTranslations(formWidget,
2533 XtParseTranslationTable(globalTranslations));
2534 XtAugmentTranslations(boardWidget,
2535 XtParseTranslationTable(boardTranslations));
2536 XtAugmentTranslations(whiteTimerWidget,
2537 XtParseTranslationTable(whiteTranslations));
2538 XtAugmentTranslations(blackTimerWidget,
2539 XtParseTranslationTable(blackTranslations));
2541 /* Why is the following needed on some versions of X instead
2542 * of a translation? */
2543 XtAddEventHandler(boardWidget, ExposureMask, False,
2544 (XtEventHandler) EventProc, NULL);
2549 if (errorExitStatus == -1) {
2550 if (appData.icsActive) {
2551 /* We now wait until we see "login:" from the ICS before
2552 sending the logon script (problems with timestamp otherwise) */
2553 /*ICSInitScript();*/
2554 if (appData.icsInputBox) ICSInputBoxPopUp();
2557 signal(SIGINT, IntSigHandler);
2558 signal(SIGTERM, IntSigHandler);
2559 if (*appData.cmailGameName != NULLCHAR) {
2560 signal(SIGUSR1, CmailSigHandler);
2564 XtAppMainLoop(appContext);
2565 if (appData.debugMode) fclose(debugFP);
2573 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2574 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2576 unlink(gameCopyFilename);
2577 unlink(gamePasteFilename);
2588 CmailSigHandler(sig)
2594 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2596 /* Activate call-back function CmailSigHandlerCallBack() */
2597 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2599 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2603 CmailSigHandlerCallBack(isr, closure, message, count, error)
2611 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2613 /**** end signal code ****/
2623 f = fopen(appData.icsLogon, "r");
2629 strcat(buf, appData.icsLogon);
2630 f = fopen(buf, "r");
2634 ProcessICSInitScript(f);
2641 EditCommentPopDown();
2652 SetMenuEnables(enab)
2656 if (!menuBarWidget) return;
2657 while (enab->name != NULL) {
2658 w = XtNameToWidget(menuBarWidget, enab->name);
2660 DisplayError(enab->name, 0);
2662 XtSetSensitive(w, enab->value);
2668 Enables icsEnables[] = {
2669 { "menuFile.Mail Move", False },
2670 { "menuFile.Reload CMail Message", False },
2671 { "menuMode.Machine Black", False },
2672 { "menuMode.Machine White", False },
2673 { "menuMode.Analysis Mode", False },
2674 { "menuMode.Analyze File", False },
2675 { "menuMode.Two Machines", False },
2677 { "menuHelp.Hint", False },
2678 { "menuHelp.Book", False },
2679 { "menuStep.Move Now", False },
2680 { "menuOptions.Periodic Updates", False },
2681 { "menuOptions.Show Thinking", False },
2682 { "menuOptions.Ponder Next Move", False },
2687 Enables ncpEnables[] = {
2688 { "menuFile.Mail Move", False },
2689 { "menuFile.Reload CMail Message", False },
2690 { "menuMode.Machine White", False },
2691 { "menuMode.Machine Black", False },
2692 { "menuMode.Analysis Mode", False },
2693 { "menuMode.Analyze File", False },
2694 { "menuMode.Two Machines", False },
2695 { "menuMode.ICS Client", False },
2696 { "menuMode.ICS Input Box", False },
2697 { "Action", False },
2698 { "menuStep.Revert", False },
2699 { "menuStep.Move Now", False },
2700 { "menuStep.Retract Move", False },
2701 { "menuOptions.Auto Comment", False },
2702 { "menuOptions.Auto Flag", False },
2703 { "menuOptions.Auto Flip View", False },
2704 { "menuOptions.Auto Observe", False },
2705 { "menuOptions.Auto Raise Board", False },
2706 { "menuOptions.Get Move List", False },
2707 { "menuOptions.ICS Alarm", False },
2708 { "menuOptions.Move Sound", False },
2709 { "menuOptions.Quiet Play", False },
2710 { "menuOptions.Show Thinking", False },
2711 { "menuOptions.Periodic Updates", False },
2712 { "menuOptions.Ponder Next Move", False },
2713 { "menuHelp.Hint", False },
2714 { "menuHelp.Book", False },
2718 Enables gnuEnables[] = {
2719 { "menuMode.ICS Client", False },
2720 { "menuMode.ICS Input Box", False },
2721 { "menuAction.Accept", False },
2722 { "menuAction.Decline", False },
2723 { "menuAction.Rematch", False },
2724 { "menuAction.Adjourn", False },
2725 { "menuAction.Stop Examining", False },
2726 { "menuAction.Stop Observing", False },
2727 { "menuStep.Revert", False },
2728 { "menuOptions.Auto Comment", False },
2729 { "menuOptions.Auto Observe", False },
2730 { "menuOptions.Auto Raise Board", False },
2731 { "menuOptions.Get Move List", False },
2732 { "menuOptions.Premove", False },
2733 { "menuOptions.Quiet Play", False },
2735 /* The next two options rely on SetCmailMode being called *after* */
2736 /* SetGNUMode so that when GNU is being used to give hints these */
2737 /* menu options are still available */
2739 { "menuFile.Mail Move", False },
2740 { "menuFile.Reload CMail Message", False },
2744 Enables cmailEnables[] = {
2746 { "menuAction.Call Flag", False },
2747 { "menuAction.Draw", True },
2748 { "menuAction.Adjourn", False },
2749 { "menuAction.Abort", False },
2750 { "menuAction.Stop Observing", False },
2751 { "menuAction.Stop Examining", False },
2752 { "menuFile.Mail Move", True },
2753 { "menuFile.Reload CMail Message", True },
2757 Enables trainingOnEnables[] = {
2758 { "menuMode.Edit Comment", False },
2759 { "menuMode.Pause", False },
2760 { "menuStep.Forward", False },
2761 { "menuStep.Backward", False },
2762 { "menuStep.Forward to End", False },
2763 { "menuStep.Back to Start", False },
2764 { "menuStep.Move Now", False },
2765 { "menuStep.Truncate Game", False },
2769 Enables trainingOffEnables[] = {
2770 { "menuMode.Edit Comment", True },
2771 { "menuMode.Pause", True },
2772 { "menuStep.Forward", True },
2773 { "menuStep.Backward", True },
2774 { "menuStep.Forward to End", True },
2775 { "menuStep.Back to Start", True },
2776 { "menuStep.Move Now", True },
2777 { "menuStep.Truncate Game", True },
2781 Enables machineThinkingEnables[] = {
2782 { "menuFile.Load Game", False },
2783 { "menuFile.Load Next Game", False },
2784 { "menuFile.Load Previous Game", False },
2785 { "menuFile.Reload Same Game", False },
2786 { "menuFile.Paste Game", False },
2787 { "menuFile.Load Position", False },
2788 { "menuFile.Load Next Position", False },
2789 { "menuFile.Load Previous Position", False },
2790 { "menuFile.Reload Same Position", False },
2791 { "menuFile.Paste Position", False },
2792 { "menuMode.Machine White", False },
2793 { "menuMode.Machine Black", False },
2794 { "menuMode.Two Machines", False },
2795 { "menuStep.Retract Move", False },
2799 Enables userThinkingEnables[] = {
2800 { "menuFile.Load Game", True },
2801 { "menuFile.Load Next Game", True },
2802 { "menuFile.Load Previous Game", True },
2803 { "menuFile.Reload Same Game", True },
2804 { "menuFile.Paste Game", True },
2805 { "menuFile.Load Position", True },
2806 { "menuFile.Load Next Position", True },
2807 { "menuFile.Load Previous Position", True },
2808 { "menuFile.Reload Same Position", True },
2809 { "menuFile.Paste Position", True },
2810 { "menuMode.Machine White", True },
2811 { "menuMode.Machine Black", True },
2812 { "menuMode.Two Machines", True },
2813 { "menuStep.Retract Move", True },
2819 SetMenuEnables(icsEnables);
2822 /* icsEngineAnalyze */
2823 if (appData.zippyPlay && !appData.noChessProgram)
2824 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2831 SetMenuEnables(ncpEnables);
2837 SetMenuEnables(gnuEnables);
2843 SetMenuEnables(cmailEnables);
2849 SetMenuEnables(trainingOnEnables);
2850 if (appData.showButtonBar) {
2851 XtSetSensitive(buttonBarWidget, False);
2857 SetTrainingModeOff()
2859 SetMenuEnables(trainingOffEnables);
2860 if (appData.showButtonBar) {
2861 XtSetSensitive(buttonBarWidget, True);
2866 SetUserThinkingEnables()
2868 if (appData.noChessProgram) return;
2869 SetMenuEnables(userThinkingEnables);
2873 SetMachineThinkingEnables()
2875 if (appData.noChessProgram) return;
2876 SetMenuEnables(machineThinkingEnables);
2878 case MachinePlaysBlack:
2879 case MachinePlaysWhite:
2880 case TwoMachinesPlay:
2881 XtSetSensitive(XtNameToWidget(menuBarWidget,
2882 ModeToWidgetName(gameMode)), True);
2889 #define Abs(n) ((n)<0 ? -(n) : (n))
2892 * Find a font that matches "pattern" that is as close as
2893 * possible to the targetPxlSize. Prefer fonts that are k
2894 * pixels smaller to fonts that are k pixels larger. The
2895 * pattern must be in the X Consortium standard format,
2896 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2897 * The return value should be freed with XtFree when no
2900 char *FindFont(pattern, targetPxlSize)
2904 char **fonts, *p, *best, *scalable, *scalableTail;
2905 int i, j, nfonts, minerr, err, pxlSize;
2908 char **missing_list;
2910 char *def_string, *base_fnt_lst, strInt[3];
2912 XFontStruct **fnt_list;
2914 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2915 sprintf(strInt, "%d", targetPxlSize);
2916 p = strstr(pattern, "--");
2917 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2918 strcat(base_fnt_lst, strInt);
2919 strcat(base_fnt_lst, strchr(p + 2, '-'));
2921 if ((fntSet = XCreateFontSet(xDisplay,
2925 &def_string)) == NULL) {
2927 fprintf(stderr, _("Unable to create font set.\n"));
2931 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2933 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2935 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2936 programName, pattern);
2944 for (i=0; i<nfonts; i++) {
2947 if (*p != '-') continue;
2949 if (*p == NULLCHAR) break;
2950 if (*p++ == '-') j++;
2952 if (j < 7) continue;
2955 scalable = fonts[i];
2958 err = pxlSize - targetPxlSize;
2959 if (Abs(err) < Abs(minerr) ||
2960 (minerr > 0 && err < 0 && -err == minerr)) {
2966 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2967 /* If the error is too big and there is a scalable font,
2968 use the scalable font. */
2969 int headlen = scalableTail - scalable;
2970 p = (char *) XtMalloc(strlen(scalable) + 10);
2971 while (isdigit(*scalableTail)) scalableTail++;
2972 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2974 p = (char *) XtMalloc(strlen(best) + 1);
2977 if (appData.debugMode) {
2978 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2979 pattern, targetPxlSize, p);
2982 if (missing_count > 0)
2983 XFreeStringList(missing_list);
2984 XFreeFontSet(xDisplay, fntSet);
2986 XFreeFontNames(fonts);
2993 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2994 | GCBackground | GCFunction | GCPlaneMask;
2995 XGCValues gc_values;
2998 gc_values.plane_mask = AllPlanes;
2999 gc_values.line_width = lineGap;
3000 gc_values.line_style = LineSolid;
3001 gc_values.function = GXcopy;
3003 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3004 gc_values.background = XBlackPixel(xDisplay, xScreen);
3005 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3007 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3008 gc_values.background = XWhitePixel(xDisplay, xScreen);
3009 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
3010 XSetFont(xDisplay, coordGC, coordFontID);
3012 if (appData.monoMode) {
3013 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3014 gc_values.background = XWhitePixel(xDisplay, xScreen);
3015 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3017 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3018 gc_values.background = XBlackPixel(xDisplay, xScreen);
3019 lightSquareGC = wbPieceGC
3020 = XtGetGC(shellWidget, value_mask, &gc_values);
3022 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3023 gc_values.background = XWhitePixel(xDisplay, xScreen);
3024 darkSquareGC = bwPieceGC
3025 = XtGetGC(shellWidget, value_mask, &gc_values);
3027 if (DefaultDepth(xDisplay, xScreen) == 1) {
3028 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3029 gc_values.function = GXcopyInverted;
3030 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3031 gc_values.function = GXcopy;
3032 if (XBlackPixel(xDisplay, xScreen) == 1) {
3033 bwPieceGC = darkSquareGC;
3034 wbPieceGC = copyInvertedGC;
3036 bwPieceGC = copyInvertedGC;
3037 wbPieceGC = lightSquareGC;
3041 gc_values.foreground = highlightSquareColor;
3042 gc_values.background = highlightSquareColor;
3043 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 gc_values.foreground = premoveHighlightColor;
3046 gc_values.background = premoveHighlightColor;
3047 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 gc_values.foreground = lightSquareColor;
3050 gc_values.background = darkSquareColor;
3051 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = darkSquareColor;
3054 gc_values.background = lightSquareColor;
3055 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3057 gc_values.foreground = jailSquareColor;
3058 gc_values.background = jailSquareColor;
3059 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3061 gc_values.foreground = whitePieceColor;
3062 gc_values.background = darkSquareColor;
3063 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3065 gc_values.foreground = whitePieceColor;
3066 gc_values.background = lightSquareColor;
3067 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3069 gc_values.foreground = whitePieceColor;
3070 gc_values.background = jailSquareColor;
3071 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3073 gc_values.foreground = blackPieceColor;
3074 gc_values.background = darkSquareColor;
3075 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3077 gc_values.foreground = blackPieceColor;
3078 gc_values.background = lightSquareColor;
3079 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3081 gc_values.foreground = blackPieceColor;
3082 gc_values.background = jailSquareColor;
3083 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3087 void loadXIM(xim, xmask, filename, dest, mask)
3100 fp = fopen(filename, "rb");
3102 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3109 for (y=0; y<h; ++y) {
3110 for (x=0; x<h; ++x) {
3115 XPutPixel(xim, x, y, blackPieceColor);
3117 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3120 XPutPixel(xim, x, y, darkSquareColor);
3122 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3125 XPutPixel(xim, x, y, whitePieceColor);
3127 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3130 XPutPixel(xim, x, y, lightSquareColor);
3132 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3138 /* create Pixmap of piece */
3139 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3141 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3144 /* create Pixmap of clipmask
3145 Note: We assume the white/black pieces have the same
3146 outline, so we make only 6 masks. This is okay
3147 since the XPM clipmask routines do the same. */
3149 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3151 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3154 /* now create the 1-bit version */
3155 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3158 values.foreground = 1;
3159 values.background = 0;
3161 /* Don't use XtGetGC, not read only */
3162 maskGC = XCreateGC(xDisplay, *mask,
3163 GCForeground | GCBackground, &values);
3164 XCopyPlane(xDisplay, temp, *mask, maskGC,
3165 0, 0, squareSize, squareSize, 0, 0, 1);
3166 XFreePixmap(xDisplay, temp);
3170 void CreateXIMPieces()
3175 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3180 /* The XSynchronize calls were copied from CreatePieces.
3181 Not sure if needed, but can't hurt */
3182 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3185 /* temp needed by loadXIM() */
3186 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3187 0, 0, ss, ss, AllPlanes, XYPixmap);
3189 if (strlen(appData.pixmapDirectory) == 0) {
3193 if (appData.monoMode) {
3194 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3198 fprintf(stderr, _("\nLoading XIMs...\n"));
3200 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3201 fprintf(stderr, "%d", piece+1);
3202 for (kind=0; kind<4; kind++) {
3203 fprintf(stderr, ".");
3204 sprintf(buf, "%s/%c%s%u.xim",
3205 ExpandPathName(appData.pixmapDirectory),
3206 ToLower(PieceToChar((ChessSquare)piece)),
3208 ximPieceBitmap[kind][piece] =
3209 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3210 0, 0, ss, ss, AllPlanes, XYPixmap);
3211 if (appData.debugMode)
3212 fprintf(stderr, _("(File:%s:) "), buf);
3213 loadXIM(ximPieceBitmap[kind][piece],
3215 &(xpmPieceBitmap[kind][piece]),
3216 &(ximMaskPm[piece%6]));
3218 fprintf(stderr," ");
3220 /* Load light and dark squares */
3221 /* If the LSQ and DSQ pieces don't exist, we will
3222 draw them with solid squares. */
3223 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3224 if (access(buf, 0) != 0) {
3228 fprintf(stderr, _("light square "));
3230 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3231 0, 0, ss, ss, AllPlanes, XYPixmap);
3232 if (appData.debugMode)
3233 fprintf(stderr, _("(File:%s:) "), buf);
3235 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3236 fprintf(stderr, _("dark square "));
3237 sprintf(buf, "%s/dsq%u.xim",
3238 ExpandPathName(appData.pixmapDirectory), ss);
3239 if (appData.debugMode)
3240 fprintf(stderr, _("(File:%s:) "), buf);
3242 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3243 0, 0, ss, ss, AllPlanes, XYPixmap);
3244 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3245 xpmJailSquare = xpmLightSquare;
3247 fprintf(stderr, _("Done.\n"));
3249 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3253 void CreateXPMPieces()
3257 u_int ss = squareSize;
3259 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3260 XpmColorSymbol symbols[4];
3263 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3264 if (appData.debugMode) {
3265 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3266 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3270 /* The XSynchronize calls were copied from CreatePieces.
3271 Not sure if needed, but can't hurt */
3272 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3274 /* Setup translations so piece colors match square colors */
3275 symbols[0].name = "light_piece";
3276 symbols[0].value = appData.whitePieceColor;
3277 symbols[1].name = "dark_piece";
3278 symbols[1].value = appData.blackPieceColor;
3279 symbols[2].name = "light_square";
3280 symbols[2].value = appData.lightSquareColor;
3281 symbols[3].name = "dark_square";
3282 symbols[3].value = appData.darkSquareColor;
3284 attr.valuemask = XpmColorSymbols;
3285 attr.colorsymbols = symbols;
3286 attr.numsymbols = 4;
3288 if (appData.monoMode) {
3289 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3293 if (strlen(appData.pixmapDirectory) == 0) {
3294 XpmPieces* pieces = builtInXpms;
3297 while (pieces->size != squareSize && pieces->size) pieces++;
3298 if (!pieces->size) {
3299 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3302 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3303 for (kind=0; kind<4; kind++) {
3305 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3306 pieces->xpm[piece][kind],
3307 &(xpmPieceBitmap[kind][piece]),
3308 NULL, &attr)) != 0) {
3309 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3316 xpmJailSquare = xpmLightSquare;
3320 fprintf(stderr, _("\nLoading XPMs...\n"));
3323 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3324 fprintf(stderr, "%d ", piece+1);
3325 for (kind=0; kind<4; kind++) {
3326 sprintf(buf, "%s/%c%s%u.xpm",
3327 ExpandPathName(appData.pixmapDirectory),
3328 ToLower(PieceToChar((ChessSquare)piece)),
3330 if (appData.debugMode) {
3331 fprintf(stderr, _("(File:%s:) "), buf);
3333 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3334 &(xpmPieceBitmap[kind][piece]),
3335 NULL, &attr)) != 0) {
3336 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3342 /* Load light and dark squares */
3343 /* If the LSQ and DSQ pieces don't exist, we will
3344 draw them with solid squares. */
3345 fprintf(stderr, _("light square "));
3346 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3347 if (access(buf, 0) != 0) {
3351 if (appData.debugMode)
3352 fprintf(stderr, _("(File:%s:) "), buf);
3354 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3355 &xpmLightSquare, NULL, &attr)) != 0) {
3356 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3359 fprintf(stderr, _("dark square "));
3360 sprintf(buf, "%s/dsq%u.xpm",
3361 ExpandPathName(appData.pixmapDirectory), ss);
3362 if (appData.debugMode) {
3363 fprintf(stderr, _("(File:%s:) "), buf);
3365 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3366 &xpmDarkSquare, NULL, &attr)) != 0) {
3367 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3371 xpmJailSquare = xpmLightSquare;
3372 fprintf(stderr, _("Done.\n"));
3374 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3377 #endif /* HAVE_LIBXPM */
3380 /* No built-in bitmaps */
3385 u_int ss = squareSize;
3387 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3390 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3391 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3392 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3393 ss, kind == SOLID ? 's' : 'o');
3394 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3398 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3402 /* With built-in bitmaps */
3405 BuiltInBits* bib = builtInBits;
3408 u_int ss = squareSize;
3410 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3413 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3415 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3416 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3417 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3418 ss, kind == SOLID ? 's' : 'o');
3419 ReadBitmap(&pieceBitmap[kind][piece], buf,
3420 bib->bits[kind][piece], ss, ss);
3424 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3429 void ReadBitmap(pm, name, bits, wreq, hreq)
3432 unsigned char bits[];
3438 char msg[MSG_SIZ], fullname[MSG_SIZ];
3440 if (*appData.bitmapDirectory != NULLCHAR) {
3441 strcpy(fullname, appData.bitmapDirectory);
3442 strcat(fullname, "/");
3443 strcat(fullname, name);
3444 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3445 &w, &h, pm, &x_hot, &y_hot);
3446 if (errcode != BitmapSuccess) {
3448 case BitmapOpenFailed:
3449 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3451 case BitmapFileInvalid:
3452 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3454 case BitmapNoMemory:
3455 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3459 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3463 fprintf(stderr, _("%s: %s...using built-in\n"),
3465 } else if (w != wreq || h != hreq) {
3467 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3468 programName, fullname, w, h, wreq, hreq);
3474 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3478 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3487 if (lineGap == 0) return;
3488 for (i = 0; i < BOARD_SIZE + 1; i++) {
3489 gridSegments[i].x1 = 0;
3490 gridSegments[i].x2 =
3491 lineGap + BOARD_SIZE * (squareSize + lineGap);
3492 gridSegments[i].y1 = gridSegments[i].y2
3493 = lineGap / 2 + (i * (squareSize + lineGap));
3495 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3496 gridSegments[i + BOARD_SIZE + 1].y2 =
3497 BOARD_SIZE * (squareSize + lineGap);
3498 gridSegments[i + BOARD_SIZE + 1].x1 =
3499 gridSegments[i + BOARD_SIZE + 1].x2
3500 = lineGap / 2 + (i * (squareSize + lineGap));
3504 static void MenuBarSelect(w, addr, index)
3509 XtActionProc proc = (XtActionProc) addr;
3511 (proc)(NULL, NULL, NULL, NULL);
3514 void CreateMenuBarPopup(parent, name, mb)
3524 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3527 XtSetArg(args[j], XtNleftMargin, 20); j++;
3528 XtSetArg(args[j], XtNrightMargin, 20); j++;
3530 while (mi->string != NULL) {
3531 if (strcmp(mi->string, "----") == 0) {
3532 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3535 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3536 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3538 XtAddCallback(entry, XtNcallback,
3539 (XtCallbackProc) MenuBarSelect,
3540 (caddr_t) mi->proc);
3546 Widget CreateMenuBar(mb)
3550 Widget anchor, menuBar;
3552 char menuName[MSG_SIZ];
3555 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3556 XtSetArg(args[j], XtNvSpace, 0); j++;
3557 XtSetArg(args[j], XtNborderWidth, 0); j++;
3558 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3559 formWidget, args, j);
3561 while (mb->name != NULL) {
3562 strcpy(menuName, "menu");
3563 strcat(menuName, mb->name);
3565 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3568 shortName[0] = _(mb->name)[0];
3569 shortName[1] = NULLCHAR;
3570 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3573 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3576 XtSetArg(args[j], XtNborderWidth, 0); j++;
3577 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3579 CreateMenuBarPopup(menuBar, menuName, mb);
3585 Widget CreateButtonBar(mi)
3589 Widget button, buttonBar;
3593 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3595 XtSetArg(args[j], XtNhSpace, 0); j++;
3597 XtSetArg(args[j], XtNborderWidth, 0); j++;
3598 XtSetArg(args[j], XtNvSpace, 0); j++;
3599 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3600 formWidget, args, j);
3602 while (mi->string != NULL) {
3605 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3606 XtSetArg(args[j], XtNborderWidth, 0); j++;
3608 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3609 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3610 buttonBar, args, j);
3611 XtAddCallback(button, XtNcallback,
3612 (XtCallbackProc) MenuBarSelect,
3613 (caddr_t) mi->proc);
3620 CreatePieceMenu(name, color)
3627 ChessSquare selection;
3629 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3630 boardWidget, args, 0);
3632 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3633 String item = pieceMenuStrings[color][i];
3635 if (strcmp(item, "----") == 0) {
3636 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3639 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3640 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3642 selection = pieceMenuTranslation[color][i];
3643 XtAddCallback(entry, XtNcallback,
3644 (XtCallbackProc) PieceMenuSelect,
3645 (caddr_t) selection);
3646 if (selection == WhitePawn || selection == BlackPawn) {
3647 XtSetArg(args[0], XtNpopupOnEntry, entry);
3648 XtSetValues(menu, args, 1);
3661 ChessSquare selection;
3663 whitePieceMenu = CreatePieceMenu("menuW", 0);
3664 blackPieceMenu = CreatePieceMenu("menuB", 1);
3666 XtRegisterGrabAction(PieceMenuPopup, True,
3667 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3668 GrabModeAsync, GrabModeAsync);
3670 XtSetArg(args[0], XtNlabel, _("Drop"));
3671 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3672 boardWidget, args, 1);
3673 for (i = 0; i < DROP_MENU_SIZE; i++) {
3674 String item = dropMenuStrings[i];
3676 if (strcmp(item, "----") == 0) {
3677 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3680 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3681 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3683 selection = dropMenuTranslation[i];
3684 XtAddCallback(entry, XtNcallback,
3685 (XtCallbackProc) DropMenuSelect,
3686 (caddr_t) selection);
3691 void SetupDropMenu()
3699 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3700 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3701 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3702 dmEnables[i].piece);
3703 XtSetSensitive(entry, p != NULL || !appData.testLegality
3704 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3705 && !appData.icsActive));
3707 while (p && *p++ == dmEnables[i].piece) count++;
3708 sprintf(label, "%s %d", dmEnables[i].widget, count);
3710 XtSetArg(args[j], XtNlabel, label); j++;
3711 XtSetValues(entry, args, j);
3715 void PieceMenuPopup(w, event, params, num_params)
3719 Cardinal *num_params;
3722 if (event->type != ButtonPress) return;
3723 if (errorUp) ErrorPopDown();
3727 whichMenu = params[0];
3729 case IcsPlayingWhite:
3730 case IcsPlayingBlack:
3732 case MachinePlaysWhite:
3733 case MachinePlaysBlack:
3734 if (appData.testLegality &&
3735 gameInfo.variant != VariantBughouse &&
3736 gameInfo.variant != VariantCrazyhouse) return;
3738 whichMenu = "menuD";
3744 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3745 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3746 pmFromX = pmFromY = -1;
3750 pmFromX = BOARD_SIZE - 1 - pmFromX;
3752 pmFromY = BOARD_SIZE - 1 - pmFromY;
3754 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3757 static void PieceMenuSelect(w, piece, junk)
3762 if (pmFromX < 0 || pmFromY < 0) return;
3763 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3766 static void DropMenuSelect(w, piece, junk)
3771 if (pmFromX < 0 || pmFromY < 0) return;
3772 DropMenuEvent(piece, pmFromX, pmFromY);
3775 void WhiteClock(w, event, prms, nprms)
3781 if (gameMode == EditPosition || gameMode == IcsExamining) {
3782 SetWhiteToPlayEvent();
3783 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3788 void BlackClock(w, event, prms, nprms)
3794 if (gameMode == EditPosition || gameMode == IcsExamining) {
3795 SetBlackToPlayEvent();
3796 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3803 * If the user selects on a border boundary, return -1; if off the board,
3804 * return -2. Otherwise map the event coordinate to the square.
3806 int EventToSquare(x, limit)
3814 if ((x % (squareSize + lineGap)) >= squareSize)
3816 x /= (squareSize + lineGap);
3822 static void do_flash_delay(msec)
3828 static void drawHighlight(file, rank, gc)
3834 if (lineGap == 0 || appData.blindfold) return;
3837 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3838 (squareSize + lineGap);
3839 y = lineGap/2 + rank * (squareSize + lineGap);
3841 x = lineGap/2 + file * (squareSize + lineGap);
3842 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3843 (squareSize + lineGap);
3846 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3847 squareSize+lineGap, squareSize+lineGap);
3850 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3851 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3854 SetHighlights(fromX, fromY, toX, toY)
3855 int fromX, fromY, toX, toY;
3857 if (hi1X != fromX || hi1Y != fromY) {
3858 if (hi1X >= 0 && hi1Y >= 0) {
3859 drawHighlight(hi1X, hi1Y, lineGC);
3861 if (fromX >= 0 && fromY >= 0) {
3862 drawHighlight(fromX, fromY, highlineGC);
3865 if (hi2X != toX || hi2Y != toY) {
3866 if (hi2X >= 0 && hi2Y >= 0) {
3867 drawHighlight(hi2X, hi2Y, lineGC);
3869 if (toX >= 0 && toY >= 0) {
3870 drawHighlight(toX, toY, highlineGC);
3882 SetHighlights(-1, -1, -1, -1);
3887 SetPremoveHighlights(fromX, fromY, toX, toY)
3888 int fromX, fromY, toX, toY;
3890 if (pm1X != fromX || pm1Y != fromY) {
3891 if (pm1X >= 0 && pm1Y >= 0) {
3892 drawHighlight(pm1X, pm1Y, lineGC);
3894 if (fromX >= 0 && fromY >= 0) {
3895 drawHighlight(fromX, fromY, prelineGC);
3898 if (pm2X != toX || pm2Y != toY) {
3899 if (pm2X >= 0 && pm2Y >= 0) {
3900 drawHighlight(pm2X, pm2Y, lineGC);
3902 if (toX >= 0 && toY >= 0) {
3903 drawHighlight(toX, toY, prelineGC);
3913 ClearPremoveHighlights()
3915 SetPremoveHighlights(-1, -1, -1, -1);
3918 static void BlankSquare(x, y, color, piece, dest)
3923 if (useImages && useImageSqs) {
3927 pm = xpmLightSquare;
3932 case 2: /* neutral */
3937 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3938 squareSize, squareSize, x, y);
3948 case 2: /* neutral */
3953 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3958 I split out the routines to draw a piece so that I could
3959 make a generic flash routine.
3961 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3963 int square_color, x, y;
3966 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3967 switch (square_color) {
3969 case 2: /* neutral */
3971 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3972 ? *pieceToOutline(piece)
3973 : *pieceToSolid(piece),
3974 dest, bwPieceGC, 0, 0,
3975 squareSize, squareSize, x, y);
3978 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3979 ? *pieceToSolid(piece)
3980 : *pieceToOutline(piece),
3981 dest, wbPieceGC, 0, 0,
3982 squareSize, squareSize, x, y);
3987 static void monoDrawPiece(piece, square_color, x, y, dest)
3989 int square_color, x, y;
3992 switch (square_color) {
3994 case 2: /* neutral */
3996 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3997 ? *pieceToOutline(piece)
3998 : *pieceToSolid(piece),
3999 dest, bwPieceGC, 0, 0,
4000 squareSize, squareSize, x, y, 1);
4003 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
4004 ? *pieceToSolid(piece)
4005 : *pieceToOutline(piece),
4006 dest, wbPieceGC, 0, 0,
4007 squareSize, squareSize, x, y, 1);
4012 static void colorDrawPiece(piece, square_color, x, y, dest)
4014 int square_color, x, y;
4017 switch (square_color) {
4019 XCopyPlane(xDisplay, *pieceToSolid(piece),
4020 dest, (int) piece < (int) BlackPawn
4021 ? wlPieceGC : blPieceGC, 0, 0,
4022 squareSize, squareSize, x, y, 1);
4025 XCopyPlane(xDisplay, *pieceToSolid(piece),
4026 dest, (int) piece < (int) BlackPawn
4027 ? wdPieceGC : bdPieceGC, 0, 0,
4028 squareSize, squareSize, x, y, 1);
4030 case 2: /* neutral */
4032 XCopyPlane(xDisplay, *pieceToSolid(piece),
4033 dest, (int) piece < (int) BlackPawn
4034 ? wjPieceGC : bjPieceGC, 0, 0,
4035 squareSize, squareSize, x, y, 1);
4040 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4042 int square_color, x, y;
4047 switch (square_color) {
4049 case 2: /* neutral */
4051 if ((int)piece < (int) BlackPawn) {
4059 if ((int)piece < (int) BlackPawn) {
4067 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4068 dest, wlPieceGC, 0, 0,
4069 squareSize, squareSize, x, y);
4072 typedef void (*DrawFunc)();
4074 DrawFunc ChooseDrawFunc()
4076 if (appData.monoMode) {
4077 if (DefaultDepth(xDisplay, xScreen) == 1) {
4078 return monoDrawPiece_1bit;
4080 return monoDrawPiece;
4084 return colorDrawPieceImage;
4086 return colorDrawPiece;
4090 void DrawSquare(row, column, piece, do_flash)
4091 int row, column, do_flash;
4094 int square_color, x, y, direction, font_ascent, font_descent;
4097 XCharStruct overall;
4101 /* Calculate delay in milliseconds (2-delays per complete flash) */
4102 flash_delay = 500 / appData.flashRate;
4105 x = lineGap + ((BOARD_SIZE-1)-column) *
4106 (squareSize + lineGap);
4107 y = lineGap + row * (squareSize + lineGap);
4109 x = lineGap + column * (squareSize + lineGap);
4110 y = lineGap + ((BOARD_SIZE-1)-row) *
4111 (squareSize + lineGap);
4114 square_color = ((column + row) % 2) == 1;
4116 if (piece == EmptySquare || appData.blindfold) {
4117 BlankSquare(x, y, square_color, piece, xBoardWindow);
4119 drawfunc = ChooseDrawFunc();
4120 if (do_flash && appData.flashCount > 0) {
4121 for (i=0; i<appData.flashCount; ++i) {
4123 drawfunc(piece, square_color, x, y, xBoardWindow);
4124 XSync(xDisplay, False);
4125 do_flash_delay(flash_delay);
4127 BlankSquare(x, y, square_color, piece, xBoardWindow);
4128 XSync(xDisplay, False);
4129 do_flash_delay(flash_delay);
4132 drawfunc(piece, square_color, x, y, xBoardWindow);
4135 string[1] = NULLCHAR;
4136 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4137 string[0] = 'a' + column;
4138 XTextExtents(coordFontStruct, string, 1, &direction,
4139 &font_ascent, &font_descent, &overall);
4140 if (appData.monoMode) {
4141 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4142 x + squareSize - overall.width - 2,
4143 y + squareSize - font_descent - 1, string, 1);
4145 XDrawString(xDisplay, xBoardWindow, coordGC,
4146 x + squareSize - overall.width - 2,
4147 y + squareSize - font_descent - 1, string, 1);
4150 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4151 string[0] = '1' + row;
4152 XTextExtents(coordFontStruct, string, 1, &direction,
4153 &font_ascent, &font_descent, &overall);
4154 if (appData.monoMode) {
4155 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4156 x + 2, y + font_ascent + 1, string, 1);
4158 XDrawString(xDisplay, xBoardWindow, coordGC,
4159 x + 2, y + font_ascent + 1, string, 1);
4165 /* Why is this needed on some versions of X? */
4166 void EventProc(widget, unused, event)
4171 if (!XtIsRealized(widget))
4174 switch (event->type) {
4176 if (event->xexpose.count > 0) return; /* no clipping is done */
4177 XDrawPosition(widget, True, NULL);
4185 void DrawPosition(fullRedraw, board)
4186 /*Boolean*/int fullRedraw;
4189 XDrawPosition(boardWidget, fullRedraw, board);
4192 /* Returns 1 if there are "too many" differences between b1 and b2
4193 (i.e. more than 1 move was made) */
4194 static int too_many_diffs(b1, b2)
4200 for (i=0; i<BOARD_SIZE; ++i) {
4201 for (j=0; j<BOARD_SIZE; ++j) {
4202 if (b1[i][j] != b2[i][j]) {
4203 if (++c > 4) /* Castling causes 4 diffs */
4212 /* Matrix describing castling maneuvers */
4213 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4214 static int castling_matrix[4][5] = {
4215 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4216 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4217 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4218 { 7, 7, 4, 5, 6 } /* 0-0, black */
4221 /* Checks whether castling occurred. If it did, *rrow and *rcol
4222 are set to the destination (row,col) of the rook that moved.
4224 Returns 1 if castling occurred, 0 if not.
4226 Note: Only handles a max of 1 castling move, so be sure
4227 to call too_many_diffs() first.
4229 static int check_castle_draw(newb, oldb, rrow, rcol)
4236 /* For each type of castling... */
4237 for (i=0; i<4; ++i) {
4238 r = castling_matrix[i];
4240 /* Check the 4 squares involved in the castling move */
4242 for (j=1; j<=4; ++j) {
4243 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4250 /* All 4 changed, so it must be a castling move */
4259 static int damage[BOARD_SIZE][BOARD_SIZE];
4262 * event handler for redrawing the board
4264 void XDrawPosition(w, repaint, board)
4266 /*Boolean*/int repaint;
4270 static int lastFlipView = 0;
4271 static int lastBoardValid = 0;
4272 static Board lastBoard;
4276 if (board == NULL) {
4277 if (!lastBoardValid) return;
4280 if (!lastBoardValid || lastFlipView != flipView) {
4281 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4282 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4287 * It would be simpler to clear the window with XClearWindow()
4288 * but this causes a very distracting flicker.
4291 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4293 /* If too much changes (begin observing new game, etc.), don't
4295 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4297 /* Special check for castling so we don't flash both the king
4298 and the rook (just flash the king). */
4300 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4301 /* Draw rook with NO flashing. King will be drawn flashing later */
4302 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4303 lastBoard[rrow][rcol] = board[rrow][rcol];
4307 /* First pass -- Draw (newly) empty squares and repair damage.
4308 This prevents you from having a piece show up twice while it
4309 is flashing on its new square */
4310 for (i = 0; i < BOARD_SIZE; i++)
4311 for (j = 0; j < BOARD_SIZE; j++)
4312 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4314 DrawSquare(i, j, board[i][j], 0);
4315 damage[i][j] = False;
4318 /* Second pass -- Draw piece(s) in new position and flash them */
4319 for (i = 0; i < BOARD_SIZE; i++)
4320 for (j = 0; j < BOARD_SIZE; j++)
4321 if (board[i][j] != lastBoard[i][j]) {
4322 DrawSquare(i, j, board[i][j], do_flash);
4326 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4327 gridSegments, (BOARD_SIZE + 1) * 2);
4329 for (i = 0; i < BOARD_SIZE; i++)
4330 for (j = 0; j < BOARD_SIZE; j++) {
4331 DrawSquare(i, j, board[i][j], 0);
4332 damage[i][j] = False;
4336 CopyBoard(lastBoard, board);
4338 lastFlipView = flipView;
4340 /* Draw highlights */
4341 if (pm1X >= 0 && pm1Y >= 0) {
4342 drawHighlight(pm1X, pm1Y, prelineGC);
4344 if (pm2X >= 0 && pm2Y >= 0) {
4345 drawHighlight(pm2X, pm2Y, prelineGC);
4347 if (hi1X >= 0 && hi1Y >= 0) {
4348 drawHighlight(hi1X, hi1Y, highlineGC);
4350 if (hi2X >= 0 && hi2Y >= 0) {
4351 drawHighlight(hi2X, hi2Y, highlineGC);
4354 /* If piece being dragged around board, must redraw that too */
4357 XSync(xDisplay, False);
4362 * event handler for redrawing the board
4364 void DrawPositionProc(w, event, prms, nprms)
4370 XDrawPosition(w, True, NULL);
4375 * event handler for parsing user moves
4377 void HandleUserMove(w, event, prms, nprms)
4384 Boolean saveAnimate;
4385 static int second = 0;
4387 if (w != boardWidget || errorExitStatus != -1) return;
4389 if (event->type == ButtonPress) ErrorPopDown();
4392 if (event->type == ButtonPress) {
4393 XtPopdown(promotionShell);
4394 XtDestroyWidget(promotionShell);
4395 promotionUp = False;
4403 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4404 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4405 if (!flipView && y >= 0) {
4406 y = BOARD_SIZE - 1 - y;
4408 if (flipView && x >= 0) {
4409 x = BOARD_SIZE - 1 - x;
4413 if (event->type == ButtonPress) {
4415 if (OKToStartUserMove(x, y)) {
4419 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4420 if (appData.highlightDragging) {
4421 SetHighlights(x, y, -1, -1);
4429 if (event->type == ButtonPress && gameMode != EditPosition &&
4433 /* Check if clicking again on the same color piece */
4434 fromP = boards[currentMove][fromY][fromX];
4435 toP = boards[currentMove][y][x];
4436 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4437 WhitePawn <= toP && toP <= WhiteKing) ||
4438 (BlackPawn <= fromP && fromP <= BlackKing &&
4439 BlackPawn <= toP && toP <= BlackKing)) {
4440 /* Clicked again on same color piece -- changed his mind */
4441 second = (x == fromX && y == fromY);
4442 if (appData.highlightDragging) {
4443 SetHighlights(x, y, -1, -1);
4447 if (OKToStartUserMove(x, y)) {
4450 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4456 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4457 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4458 if (appData.animateDragging) {
4459 /* Undo animation damage if any */
4460 DrawPosition(FALSE, NULL);
4463 /* Second up/down in same square; just abort move */
4468 ClearPremoveHighlights();
4470 /* First upclick in same square; start click-click mode */
4471 SetHighlights(x, y, -1, -1);
4476 /* Completed move */
4479 saveAnimate = appData.animate;
4480 if (event->type == ButtonPress) {
4481 /* Finish clickclick move */
4482 if (appData.animate || appData.highlightLastMove) {
4483 SetHighlights(fromX, fromY, toX, toY);
4488 /* Finish drag move */
4489 if (appData.highlightLastMove) {
4490 SetHighlights(fromX, fromY, toX, toY);
4494 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4495 /* Don't animate move and drag both */
4496 appData.animate = FALSE;
4498 if (IsPromotion(fromX, fromY, toX, toY)) {
4499 if (appData.alwaysPromoteToQueen) {
4500 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4501 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4502 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4505 SetHighlights(fromX, fromY, toX, toY);
4509 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4510 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4511 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4514 appData.animate = saveAnimate;
4515 if (appData.animate || appData.animateDragging) {
4516 /* Undo animation damage if needed */
4517 DrawPosition(FALSE, NULL);
4521 void AnimateUserMove (Widget w, XEvent * event,
4522 String * params, Cardinal * nParams)
4524 DragPieceMove(event->xmotion.x, event->xmotion.y);
4527 Widget CommentCreate(name, text, mutable, callback, lines)
4529 int /*Boolean*/ mutable;
4530 XtCallbackProc callback;
4534 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4539 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4540 XtGetValues(boardWidget, args, j);
4543 XtSetArg(args[j], XtNresizable, True); j++;
4546 XtCreatePopupShell(name, topLevelShellWidgetClass,
4547 shellWidget, args, j);
4550 XtCreatePopupShell(name, transientShellWidgetClass,
4551 shellWidget, args, j);
4554 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4555 layoutArgs, XtNumber(layoutArgs));
4557 XtCreateManagedWidget("form", formWidgetClass, layout,
4558 formArgs, XtNumber(formArgs));
4562 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4563 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4565 XtSetArg(args[j], XtNstring, text); j++;
4566 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4567 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4568 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4569 XtSetArg(args[j], XtNright, XtChainRight); j++;
4570 XtSetArg(args[j], XtNresizable, True); j++;
4571 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4573 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4575 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4576 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4578 XtSetArg(args[j], XtNautoFill, True); j++;
4579 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4581 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4585 XtSetArg(args[j], XtNfromVert, edit); j++;
4586 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4587 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4588 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4589 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4591 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4592 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4595 XtSetArg(args[j], XtNfromVert, edit); j++;
4596 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4597 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4598 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4599 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4600 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4602 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4603 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4606 XtSetArg(args[j], XtNfromVert, edit); j++;
4607 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4608 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4609 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4610 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4611 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4613 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4614 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4617 XtSetArg(args[j], XtNfromVert, edit); j++;
4618 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4619 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4620 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4621 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4623 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4624 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4627 XtSetArg(args[j], XtNfromVert, edit); j++;
4628 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4629 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4630 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4631 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4632 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4634 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4635 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4638 XtRealizeWidget(shell);
4640 if (commentX == -1) {
4643 Dimension pw_height;
4644 Dimension ew_height;
4647 XtSetArg(args[j], XtNheight, &ew_height); j++;
4648 XtGetValues(edit, args, j);
4651 XtSetArg(args[j], XtNheight, &pw_height); j++;
4652 XtGetValues(shell, args, j);
4653 commentH = pw_height + (lines - 1) * ew_height;
4654 commentW = bw_width - 16;
4656 XSync(xDisplay, False);
4658 /* This code seems to tickle an X bug if it is executed too soon
4659 after xboard starts up. The coordinates get transformed as if
4660 the main window was positioned at (0, 0).
4662 XtTranslateCoords(shellWidget,
4663 (bw_width - commentW) / 2, 0 - commentH / 2,
4664 &commentX, &commentY);
4666 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4667 RootWindowOfScreen(XtScreen(shellWidget)),
4668 (bw_width - commentW) / 2, 0 - commentH / 2,
4673 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4676 XtSetArg(args[j], XtNheight, commentH); j++;
4677 XtSetArg(args[j], XtNwidth, commentW); j++;
4678 XtSetArg(args[j], XtNx, commentX); j++;
4679 XtSetArg(args[j], XtNy, commentY); j++;
4680 XtSetValues(shell, args, j);
4681 XtSetKeyboardFocus(shell, edit);
4686 /* Used for analysis window and ICS input window */
4687 Widget MiscCreate(name, text, mutable, callback, lines)
4689 int /*Boolean*/ mutable;
4690 XtCallbackProc callback;
4694 Widget shell, layout, form, edit;
4696 Dimension bw_width, pw_height, ew_height, w, h;
4702 XtSetArg(args[j], XtNresizable, True); j++;
4705 XtCreatePopupShell(name, topLevelShellWidgetClass,
4706 shellWidget, args, j);
4709 XtCreatePopupShell(name, transientShellWidgetClass,
4710 shellWidget, args, j);
4713 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4714 layoutArgs, XtNumber(layoutArgs));
4716 XtCreateManagedWidget("form", formWidgetClass, layout,
4717 formArgs, XtNumber(formArgs));
4721 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4722 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4724 XtSetArg(args[j], XtNstring, text); j++;
4725 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4726 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4727 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4728 XtSetArg(args[j], XtNright, XtChainRight); j++;
4729 XtSetArg(args[j], XtNresizable, True); j++;
4731 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4733 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4734 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4736 XtSetArg(args[j], XtNautoFill, True); j++;
4737 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4739 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4741 XtRealizeWidget(shell);
4744 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4745 XtGetValues(boardWidget, args, j);
4748 XtSetArg(args[j], XtNheight, &ew_height); j++;
4749 XtGetValues(edit, args, j);
4752 XtSetArg(args[j], XtNheight, &pw_height); j++;
4753 XtGetValues(shell, args, j);
4754 h = pw_height + (lines - 1) * ew_height;
4757 XSync(xDisplay, False);
4759 /* This code seems to tickle an X bug if it is executed too soon
4760 after xboard starts up. The coordinates get transformed as if
4761 the main window was positioned at (0, 0).
4763 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4765 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4766 RootWindowOfScreen(XtScreen(shellWidget)),
4767 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4771 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4774 XtSetArg(args[j], XtNheight, h); j++;
4775 XtSetArg(args[j], XtNwidth, w); j++;
4776 XtSetArg(args[j], XtNx, x); j++;
4777 XtSetArg(args[j], XtNy, y); j++;
4778 XtSetValues(shell, args, j);
4784 static int savedIndex; /* gross that this is global */
4786 void EditCommentPopUp(index, title, text)
4795 if (text == NULL) text = "";
4797 if (editShell == NULL) {
4799 CommentCreate(title, text, True, EditCommentCallback, 4);
4800 XtRealizeWidget(editShell);
4801 CatchDeleteWindow(editShell, "EditCommentPopDown");
4803 edit = XtNameToWidget(editShell, "*form.text");
4805 XtSetArg(args[j], XtNstring, text); j++;
4806 XtSetValues(edit, args, j);
4808 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4809 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4810 XtSetValues(editShell, args, j);
4813 XtPopup(editShell, XtGrabNone);
4817 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4818 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4822 void EditCommentCallback(w, client_data, call_data)
4824 XtPointer client_data, call_data;
4832 XtSetArg(args[j], XtNlabel, &name); j++;
4833 XtGetValues(w, args, j);
4835 if (strcmp(name, _("ok")) == 0) {
4836 edit = XtNameToWidget(editShell, "*form.text");
4838 XtSetArg(args[j], XtNstring, &val); j++;
4839 XtGetValues(edit, args, j);
4840 ReplaceComment(savedIndex, val);
4841 EditCommentPopDown();
4842 } else if (strcmp(name, _("cancel")) == 0) {
4843 EditCommentPopDown();
4844 } else if (strcmp(name, _("clear")) == 0) {
4845 edit = XtNameToWidget(editShell, "*form.text");
4846 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4847 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4851 void EditCommentPopDown()
4856 if (!editUp) return;
4858 XtSetArg(args[j], XtNx, &commentX); j++;
4859 XtSetArg(args[j], XtNy, &commentY); j++;
4860 XtSetArg(args[j], XtNheight, &commentH); j++;
4861 XtSetArg(args[j], XtNwidth, &commentW); j++;
4862 XtGetValues(editShell, args, j);
4863 XtPopdown(editShell);
4866 XtSetArg(args[j], XtNleftBitmap, None); j++;
4867 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4871 void ICSInputBoxPopUp()
4876 char *title = _("ICS Input");
4879 if (ICSInputShell == NULL) {
4880 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4881 tr = XtParseTranslationTable(ICSInputTranslations);
4882 edit = XtNameToWidget(ICSInputShell, "*form.text");
4883 XtOverrideTranslations(edit, tr);
4884 XtRealizeWidget(ICSInputShell);
4885 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4888 edit = XtNameToWidget(ICSInputShell, "*form.text");
4890 XtSetArg(args[j], XtNstring, ""); j++;
4891 XtSetValues(edit, args, j);
4893 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4894 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4895 XtSetValues(ICSInputShell, args, j);
4898 XtPopup(ICSInputShell, XtGrabNone);
4899 XtSetKeyboardFocus(ICSInputShell, edit);
4901 ICSInputBoxUp = True;
4903 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4904 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4908 void ICSInputSendText()
4915 edit = XtNameToWidget(ICSInputShell, "*form.text");
4917 XtSetArg(args[j], XtNstring, &val); j++;
4918 XtGetValues(edit, args, j);
4919 SendMultiLineToICS(val);
4920 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4921 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4924 void ICSInputBoxPopDown()
4929 if (!ICSInputBoxUp) return;
4931 XtPopdown(ICSInputShell);
4932 ICSInputBoxUp = False;
4934 XtSetArg(args[j], XtNleftBitmap, None); j++;
4935 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4939 void CommentPopUp(title, text)
4946 if (commentShell == NULL) {
4948 CommentCreate(title, text, False, CommentCallback, 4);
4949 XtRealizeWidget(commentShell);
4950 CatchDeleteWindow(commentShell, "CommentPopDown");
4952 edit = XtNameToWidget(commentShell, "*form.text");
4954 XtSetArg(args[j], XtNstring, text); j++;
4955 XtSetValues(edit, args, j);
4957 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4958 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4959 XtSetValues(commentShell, args, j);
4962 XtPopup(commentShell, XtGrabNone);
4963 XSync(xDisplay, False);
4968 void AnalysisPopUp(title, text)
4975 if (analysisShell == NULL) {
4976 analysisShell = MiscCreate(title, text, False, NULL, 4);
4977 XtRealizeWidget(analysisShell);
4978 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4981 edit = XtNameToWidget(analysisShell, "*form.text");
4983 XtSetArg(args[j], XtNstring, text); j++;
4984 XtSetValues(edit, args, j);
4986 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4987 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4988 XtSetValues(analysisShell, args, j);
4992 XtPopup(analysisShell, XtGrabNone);
4994 XSync(xDisplay, False);
4999 void CommentCallback(w, client_data, call_data)
5001 XtPointer client_data, call_data;
5008 XtSetArg(args[j], XtNlabel, &name); j++;
5009 XtGetValues(w, args, j);
5011 if (strcmp(name, _("close")) == 0) {
5013 } else if (strcmp(name, _("edit")) == 0) {
5020 void CommentPopDown()
5025 if (!commentUp) return;
5027 XtSetArg(args[j], XtNx, &commentX); j++;
5028 XtSetArg(args[j], XtNy, &commentY); j++;
5029 XtSetArg(args[j], XtNwidth, &commentW); j++;
5030 XtSetArg(args[j], XtNheight, &commentH); j++;
5031 XtGetValues(commentShell, args, j);
5032 XtPopdown(commentShell);
5033 XSync(xDisplay, False);
5037 void AnalysisPopDown()
5039 if (!analysisUp) return;
5040 XtPopdown(analysisShell);
5041 XSync(xDisplay, False);
5043 /* icsEngineAnalyze */
5044 if (appData.icsEngineAnalyze) ExitAnalyzeMode();
5048 void FileNamePopUp(label, def, proc, openMode)
5055 Widget popup, layout, dialog, edit;
5061 fileProc = proc; /* I can't see a way not */
5062 fileOpenMode = openMode; /* to use globals here */
5065 XtSetArg(args[i], XtNresizable, True); i++;
5066 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5067 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5068 fileNameShell = popup =
5069 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5070 shellWidget, args, i);
5073 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5074 layoutArgs, XtNumber(layoutArgs));
5077 XtSetArg(args[i], XtNlabel, label); i++;
5078 XtSetArg(args[i], XtNvalue, def); i++;
5079 XtSetArg(args[i], XtNborderWidth, 0); i++;
5080 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5083 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5084 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5085 (XtPointer) dialog);
5087 XtRealizeWidget(popup);
5088 CatchDeleteWindow(popup, "FileNamePopDown");
5090 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5091 &x, &y, &win_x, &win_y, &mask);
5093 XtSetArg(args[0], XtNx, x - 10);
5094 XtSetArg(args[1], XtNy, y - 30);
5095 XtSetValues(popup, args, 2);
5097 XtPopup(popup, XtGrabExclusive);
5100 edit = XtNameToWidget(dialog, "*value");
5101 XtSetKeyboardFocus(popup, edit);
5104 void FileNamePopDown()
5106 if (!filenameUp) return;
5107 XtPopdown(fileNameShell);
5108 XtDestroyWidget(fileNameShell);
5113 void FileNameCallback(w, client_data, call_data)
5115 XtPointer client_data, call_data;
5120 XtSetArg(args[0], XtNlabel, &name);
5121 XtGetValues(w, args, 1);
5123 if (strcmp(name, _("cancel")) == 0) {
5128 FileNameAction(w, NULL, NULL, NULL);
5131 void FileNameAction(w, event, prms, nprms)
5143 name = XawDialogGetValueString(w = XtParent(w));
5145 if ((name != NULL) && (*name != NULLCHAR)) {
5147 XtPopdown(w = XtParent(XtParent(w)));
5151 p = strrchr(buf, ' ');
5158 fullname = ExpandPathName(buf);
5160 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5163 f = fopen(fullname, fileOpenMode);
5165 DisplayError(_("Failed to open file"), errno);
5167 (void) (*fileProc)(f, index, buf);
5174 XtPopdown(w = XtParent(XtParent(w)));
5180 void PromotionPopUp()
5183 Widget dialog, layout;
5185 Dimension bw_width, pw_width;
5189 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5190 XtGetValues(boardWidget, args, j);
5193 XtSetArg(args[j], XtNresizable, True); j++;
5194 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5196 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5197 shellWidget, args, j);
5199 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5200 layoutArgs, XtNumber(layoutArgs));
5203 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5204 XtSetArg(args[j], XtNborderWidth, 0); j++;
5205 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5208 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5209 (XtPointer) dialog);
5210 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5211 (XtPointer) dialog);
5212 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5213 (XtPointer) dialog);
5214 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5215 (XtPointer) dialog);
5216 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5217 gameInfo.variant == VariantGiveaway) {
5218 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5219 (XtPointer) dialog);
5221 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5222 (XtPointer) dialog);
5224 XtRealizeWidget(promotionShell);
5225 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5228 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5229 XtGetValues(promotionShell, args, j);
5231 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5232 lineGap + squareSize/3 +
5233 ((toY == 7) ^ (flipView) ?
5234 0 : 6*(squareSize + lineGap)), &x, &y);
5237 XtSetArg(args[j], XtNx, x); j++;
5238 XtSetArg(args[j], XtNy, y); j++;
5239 XtSetValues(promotionShell, args, j);
5241 XtPopup(promotionShell, XtGrabNone);
5246 void PromotionPopDown()
5248 if (!promotionUp) return;
5249 XtPopdown(promotionShell);
5250 XtDestroyWidget(promotionShell);
5251 promotionUp = False;
5254 void PromotionCallback(w, client_data, call_data)
5256 XtPointer client_data, call_data;
5262 XtSetArg(args[0], XtNlabel, &name);
5263 XtGetValues(w, args, 1);
5267 if (fromX == -1) return;
5269 if (strcmp(name, _("cancel")) == 0) {
5273 } else if (strcmp(name, _("Knight")) == 0) {
5276 promoChar = ToLower(name[0]);
5279 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5281 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5282 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5287 void ErrorCallback(w, client_data, call_data)
5289 XtPointer client_data, call_data;
5292 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5294 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5300 if (!errorUp) return;
5302 XtPopdown(errorShell);
5303 XtDestroyWidget(errorShell);
5304 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5307 void ErrorPopUp(title, label, modal)
5308 char *title, *label;
5312 Widget dialog, layout;
5316 Dimension bw_width, pw_width;
5317 Dimension pw_height;
5321 XtSetArg(args[i], XtNresizable, True); i++;
5322 XtSetArg(args[i], XtNtitle, title); i++;
5324 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5325 shellWidget, args, i);
5327 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5328 layoutArgs, XtNumber(layoutArgs));
5331 XtSetArg(args[i], XtNlabel, label); i++;
5332 XtSetArg(args[i], XtNborderWidth, 0); i++;
5333 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5336 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5338 XtRealizeWidget(errorShell);
5339 CatchDeleteWindow(errorShell, "ErrorPopDown");
5342 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5343 XtGetValues(boardWidget, args, i);
5345 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5346 XtSetArg(args[i], XtNheight, &pw_height); i++;
5347 XtGetValues(errorShell, args, i);
5350 /* This code seems to tickle an X bug if it is executed too soon
5351 after xboard starts up. The coordinates get transformed as if
5352 the main window was positioned at (0, 0).
5354 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5355 0 - pw_height + squareSize / 3, &x, &y);
5357 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5358 RootWindowOfScreen(XtScreen(boardWidget)),
5359 (bw_width - pw_width) / 2,
5360 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5364 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5367 XtSetArg(args[i], XtNx, x); i++;
5368 XtSetArg(args[i], XtNy, y); i++;
5369 XtSetValues(errorShell, args, i);
5372 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5375 /* Disable all user input other than deleting the window */
5376 static int frozen = 0;
5380 /* Grab by a widget that doesn't accept input */
5381 XtAddGrab(messageWidget, TRUE, FALSE);
5385 /* Undo a FreezeUI */
5388 if (!frozen) return;
5389 XtRemoveGrab(messageWidget);
5393 char *ModeToWidgetName(mode)
5397 case BeginningOfGame:
5398 if (appData.icsActive)
5399 return "menuMode.ICS Client";
5400 else if (appData.noChessProgram ||
5401 *appData.cmailGameName != NULLCHAR)
5402 return "menuMode.Edit Game";
5404 return "menuMode.Machine Black";
5405 case MachinePlaysBlack:
5406 return "menuMode.Machine Black";
5407 case MachinePlaysWhite:
5408 return "menuMode.Machine White";
5410 return "menuMode.Analysis Mode";
5412 return "menuMode.Analyze File";
5413 case TwoMachinesPlay:
5414 return "menuMode.Two Machines";
5416 return "menuMode.Edit Game";
5417 case PlayFromGameFile:
5418 return "menuFile.Load Game";
5420 return "menuMode.Edit Position";
5422 return "menuMode.Training";
5423 case IcsPlayingWhite:
5424 case IcsPlayingBlack:
5428 return "menuMode.ICS Client";
5435 void ModeHighlight()
5438 static int oldPausing = FALSE;
5439 static GameMode oldmode = (GameMode) -1;
5442 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5444 if (pausing != oldPausing) {
5445 oldPausing = pausing;
5447 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5449 XtSetArg(args[0], XtNleftBitmap, None);
5451 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5454 if (appData.showButtonBar) {
5457 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5458 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5460 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5461 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5464 /* Always toggle, don't set. Previous code messes up when
5465 invoked while the button is pressed, as releasing it
5466 toggles the state again. */
5469 XtSetArg(args[0], XtNbackground, &oldbg);
5470 XtSetArg(args[1], XtNforeground, &oldfg);
5471 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5473 XtSetArg(args[0], XtNbackground, oldfg);
5474 XtSetArg(args[1], XtNforeground, oldbg);
5477 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5481 wname = ModeToWidgetName(oldmode);
5482 if (wname != NULL) {
5483 XtSetArg(args[0], XtNleftBitmap, None);
5484 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5486 wname = ModeToWidgetName(gameMode);
5487 if (wname != NULL) {
5488 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5489 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5493 /* Maybe all the enables should be handled here, not just this one */
5494 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5495 gameMode == Training || gameMode == PlayFromGameFile);
5499 * Button/menu procedures
5501 void ResetProc(w, event, prms, nprms)
5511 int LoadGamePopUp(f, gameNumber, title)
5516 cmailMsgLoaded = FALSE;
5517 if (gameNumber == 0) {
5518 int error = GameListBuild(f);
5520 DisplayError(_("Cannot build game list"), error);
5521 } else if (!ListEmpty(&gameList) &&
5522 ((ListGame *) gameList.tailPred)->number > 1) {
5523 GameListPopUp(f, title);
5529 return LoadGame(f, gameNumber, title, FALSE);
5532 void LoadGameProc(w, event, prms, nprms)
5538 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5541 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
5544 void LoadNextGameProc(w, event, prms, nprms)
5553 void LoadPrevGameProc(w, event, prms, nprms)
5562 void ReloadGameProc(w, event, prms, nprms)
5571 void LoadNextPositionProc(w, event, prms, nprms)
5580 void LoadPrevPositionProc(w, event, prms, nprms)
5589 void ReloadPositionProc(w, event, prms, nprms)
5598 void LoadPositionProc(w, event, prms, nprms)
5604 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5607 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5610 void SaveGameProc(w, event, prms, nprms)
5616 FileNamePopUp(_("Save game file name?"),
5617 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5621 void SavePositionProc(w, event, prms, nprms)
5627 FileNamePopUp(_("Save position file name?"),
5628 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5632 void ReloadCmailMsgProc(w, event, prms, nprms)
5638 ReloadCmailMsgEvent(FALSE);
5641 void MailMoveProc(w, event, prms, nprms)
5650 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5651 static char *selected_fen_position=NULL;
5654 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5655 Atom *type_return, XtPointer *value_return,
5656 unsigned long *length_return, int *format_return)
5658 char *selection_tmp;
5660 if (!selected_fen_position) return False; /* should never happen */
5661 if (*target == XA_STRING){
5662 /* note: since no XtSelectionDoneProc was registered, Xt will
5663 * automatically call XtFree on the value returned. So have to
5664 * make a copy of it allocated with XtMalloc */
5665 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5666 strcpy(selection_tmp, selected_fen_position);
5668 *value_return=selection_tmp;
5669 *length_return=strlen(selection_tmp);
5670 *type_return=XA_STRING;
5671 *format_return = 8; /* bits per byte */
5678 /* note: when called from menu all parameters are NULL, so no clue what the
5679 * Widget which was clicked on was, or what the click event was
5681 void CopyPositionProc(w, event, prms, nprms)
5689 if (selected_fen_position) free(selected_fen_position);
5690 selected_fen_position = (char *)PositionToFEN(currentMove);
5691 if (!selected_fen_position) return;
5692 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5694 SendPositionSelection,
5695 NULL/* lose_ownership_proc */ ,
5696 NULL/* transfer_done_proc */);
5698 free(selected_fen_position);
5699 selected_fen_position=NULL;
5703 /* function called when the data to Paste is ready */
5705 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5706 Atom *type, XtPointer value, unsigned long *len, int *format)
5709 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5710 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5711 EditPositionPasteFEN(fenstr);
5715 /* called when Paste Position button is pressed,
5716 * all parameters will be NULL */
5717 void PastePositionProc(w, event, prms, nprms)
5723 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5724 /* (XtSelectionCallbackProc) */ PastePositionCB,
5725 NULL, /* client_data passed to PastePositionCB */
5727 /* better to use the time field from the event that triggered the
5728 * call to this function, but that isn't trivial to get
5736 SendGameSelection(Widget w, Atom *selection, Atom *target,
5737 Atom *type_return, XtPointer *value_return,
5738 unsigned long *length_return, int *format_return)
5740 char *selection_tmp;
5742 if (*target == XA_STRING){
5743 FILE* f = fopen(gameCopyFilename, "r");
5746 if (f == NULL) return False;
5750 selection_tmp = XtMalloc(len + 1);
5751 count = fread(selection_tmp, 1, len, f);
5753 XtFree(selection_tmp);
5756 selection_tmp[len] = NULLCHAR;
5757 *value_return = selection_tmp;
5758 *length_return = len;
5759 *type_return = XA_STRING;
5760 *format_return = 8; /* bits per byte */
5767 /* note: when called from menu all parameters are NULL, so no clue what the
5768 * Widget which was clicked on was, or what the click event was
5770 void CopyGameProc(w, event, prms, nprms)
5778 ret = SaveGameToFile(gameCopyFilename, FALSE);
5781 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5784 NULL/* lose_ownership_proc */ ,
5785 NULL/* transfer_done_proc */);
5788 /* function called when the data to Paste is ready */
5790 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5791 Atom *type, XtPointer value, unsigned long *len, int *format)
5794 if (value == NULL || *len == 0) {
5795 return; /* nothing had been selected to copy */
5797 f = fopen(gamePasteFilename, "w");
5799 DisplayError(_("Can't open temp file"), errno);
5802 fwrite(value, 1, *len, f);
5805 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5808 /* called when Paste Game button is pressed,
5809 * all parameters will be NULL */
5810 void PasteGameProc(w, event, prms, nprms)
5816 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5817 /* (XtSelectionCallbackProc) */ PasteGameCB,
5818 NULL, /* client_data passed to PasteGameCB */
5820 /* better to use the time field from the event that triggered the
5821 * call to this function, but that isn't trivial to get
5831 SaveGameProc(NULL, NULL, NULL, NULL);
5835 void QuitProc(w, event, prms, nprms)
5844 void PauseProc(w, event, prms, nprms)
5854 void MachineBlackProc(w, event, prms, nprms)
5860 MachineBlackEvent();
5863 void MachineWhiteProc(w, event, prms, nprms)
5869 MachineWhiteEvent();
5872 void AnalyzeModeProc(w, event, prms, nprms)
5880 if (!first.analysisSupport) {
5881 sprintf(buf, _("%s does not support analysis"), first.tidy);
5882 DisplayError(buf, 0);
5885 /* icsEngineAnalyze */
5886 if (appData.icsActive) {
5887 if (gameMode != IcsObserving) {
5888 sprintf(buf,_("You are not observing a game"));
5889 DisplayError(buf, 0);
5891 if (appData.icsEngineAnalyze) {
5892 if (appData.debugMode)
5893 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5900 /* if enable, use want disable icsEngineAnalyze */
5901 if (appData.icsEngineAnalyze) {
5906 appData.icsEngineAnalyze = TRUE;
5907 if (appData.debugMode)
5908 fprintf(debugFP, "ICS engine analyze starting... \n");
5911 if (!appData.showThinking)
5912 ShowThinkingProc(w,event,prms,nprms);
5916 void AnalyzeFileProc(w, event, prms, nprms)
5922 if (!first.analysisSupport) {
5924 sprintf(buf, _("%s does not support analysis"), first.tidy);
5925 DisplayError(buf, 0);
5930 if (!appData.showThinking)
5931 ShowThinkingProc(w,event,prms,nprms);
5934 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5935 AnalysisPeriodicEvent(1);
5938 void TwoMachinesProc(w, event, prms, nprms)
5947 void IcsClientProc(w, event, prms, nprms)
5956 void EditGameProc(w, event, prms, nprms)
5965 void EditPositionProc(w, event, prms, nprms)
5971 EditPositionEvent();
5974 void TrainingProc(w, event, prms, nprms)
5983 void EditCommentProc(w, event, prms, nprms)
5990 EditCommentPopDown();
5996 void IcsInputBoxProc(w, event, prms, nprms)
6002 if (ICSInputBoxUp) {
6003 ICSInputBoxPopDown();
6009 void AcceptProc(w, event, prms, nprms)
6018 void DeclineProc(w, event, prms, nprms)
6027 void RematchProc(w, event, prms, nprms)
6036 void CallFlagProc(w, event, prms, nprms)
6045 void DrawProc(w, event, prms, nprms)
6054 void AbortProc(w, event, prms, nprms)
6063 void AdjournProc(w, event, prms, nprms)
6072 void ResignProc(w, event, prms, nprms)
6081 void EnterKeyProc(w, event, prms, nprms)
6087 if (ICSInputBoxUp == True)
6091 void StopObservingProc(w, event, prms, nprms)
6097 StopObservingEvent();
6100 void StopExaminingProc(w, event, prms, nprms)
6106 StopExaminingEvent();
6110 void ForwardProc(w, event, prms, nprms)
6120 void BackwardProc(w, event, prms, nprms)
6129 void ToStartProc(w, event, prms, nprms)
6138 void ToEndProc(w, event, prms, nprms)
6147 void RevertProc(w, event, prms, nprms)
6156 void TruncateGameProc(w, event, prms, nprms)
6162 TruncateGameEvent();
6164 void RetractMoveProc(w, event, prms, nprms)
6173 void MoveNowProc(w, event, prms, nprms)
6183 void AlwaysQueenProc(w, event, prms, nprms)
6191 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6193 if (appData.alwaysPromoteToQueen) {
6194 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6196 XtSetArg(args[0], XtNleftBitmap, None);
6198 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6202 void AnimateDraggingProc(w, event, prms, nprms)
6210 appData.animateDragging = !appData.animateDragging;
6212 if (appData.animateDragging) {
6213 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6216 XtSetArg(args[0], XtNleftBitmap, None);
6218 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6222 void AnimateMovingProc(w, event, prms, nprms)
6230 appData.animate = !appData.animate;
6232 if (appData.animate) {
6233 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6236 XtSetArg(args[0], XtNleftBitmap, None);
6238 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6242 void AutocommProc(w, event, prms, nprms)
6250 appData.autoComment = !appData.autoComment;
6252 if (appData.autoComment) {
6253 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6255 XtSetArg(args[0], XtNleftBitmap, None);
6257 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6262 void AutoflagProc(w, event, prms, nprms)
6270 appData.autoCallFlag = !appData.autoCallFlag;
6272 if (appData.autoCallFlag) {
6273 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6275 XtSetArg(args[0], XtNleftBitmap, None);
6277 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6281 void AutoflipProc(w, event, prms, nprms)
6289 appData.autoFlipView = !appData.autoFlipView;
6291 if (appData.autoFlipView) {
6292 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6294 XtSetArg(args[0], XtNleftBitmap, None);
6296 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6300 void AutobsProc(w, event, prms, nprms)
6308 appData.autoObserve = !appData.autoObserve;
6310 if (appData.autoObserve) {
6311 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6313 XtSetArg(args[0], XtNleftBitmap, None);
6315 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6319 void AutoraiseProc(w, event, prms, nprms)
6327 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6329 if (appData.autoRaiseBoard) {
6330 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6332 XtSetArg(args[0], XtNleftBitmap, None);
6334 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6338 void AutosaveProc(w, event, prms, nprms)
6346 appData.autoSaveGames = !appData.autoSaveGames;
6348 if (appData.autoSaveGames) {
6349 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6351 XtSetArg(args[0], XtNleftBitmap, None);
6353 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6357 void BlindfoldProc(w, event, prms, nprms)
6365 appData.blindfold = !appData.blindfold;
6367 if (appData.blindfold) {
6368 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6370 XtSetArg(args[0], XtNleftBitmap, None);
6372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6375 DrawPosition(True, NULL);
6378 void TestLegalityProc(w, event, prms, nprms)
6386 appData.testLegality = !appData.testLegality;
6388 if (appData.testLegality) {
6389 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6391 XtSetArg(args[0], XtNleftBitmap, None);
6393 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6398 void FlashMovesProc(w, event, prms, nprms)
6406 if (appData.flashCount == 0) {
6407 appData.flashCount = 3;
6409 appData.flashCount = -appData.flashCount;
6412 if (appData.flashCount > 0) {
6413 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6415 XtSetArg(args[0], XtNleftBitmap, None);
6417 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6421 void FlipViewProc(w, event, prms, nprms)
6427 flipView = !flipView;
6428 DrawPosition(True, NULL);
6431 void GetMoveListProc(w, event, prms, nprms)
6439 appData.getMoveList = !appData.getMoveList;
6441 if (appData.getMoveList) {
6442 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6445 XtSetArg(args[0], XtNleftBitmap, None);
6447 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6452 void HighlightDraggingProc(w, event, prms, nprms)
6460 appData.highlightDragging = !appData.highlightDragging;
6462 if (appData.highlightDragging) {
6463 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6465 XtSetArg(args[0], XtNleftBitmap, None);
6467 XtSetValues(XtNameToWidget(menuBarWidget,
6468 "menuOptions.Highlight Dragging"), args, 1);
6472 void HighlightLastMoveProc(w, event, prms, nprms)
6480 appData.highlightLastMove = !appData.highlightLastMove;
6482 if (appData.highlightLastMove) {
6483 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6485 XtSetArg(args[0], XtNleftBitmap, None);
6487 XtSetValues(XtNameToWidget(menuBarWidget,
6488 "menuOptions.Highlight Last Move"), args, 1);
6491 void IcsAlarmProc(w, event, prms, nprms)
6499 appData.icsAlarm = !appData.icsAlarm;
6501 if (appData.icsAlarm) {
6502 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6504 XtSetArg(args[0], XtNleftBitmap, None);
6506 XtSetValues(XtNameToWidget(menuBarWidget,
6507 "menuOptions.ICS Alarm"), args, 1);
6510 void MoveSoundProc(w, event, prms, nprms)
6518 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6520 if (appData.ringBellAfterMoves) {
6521 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6523 XtSetArg(args[0], XtNleftBitmap, None);
6525 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6530 void OldSaveStyleProc(w, event, prms, nprms)
6538 appData.oldSaveStyle = !appData.oldSaveStyle;
6540 if (appData.oldSaveStyle) {
6541 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6543 XtSetArg(args[0], XtNleftBitmap, None);
6545 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6549 void PeriodicUpdatesProc(w, event, prms, nprms)
6557 PeriodicUpdatesEvent(!appData.periodicUpdates);
6559 if (appData.periodicUpdates) {
6560 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6562 XtSetArg(args[0], XtNleftBitmap, None);
6564 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6568 void PonderNextMoveProc(w, event, prms, nprms)
6576 PonderNextMoveEvent(!appData.ponderNextMove);
6578 if (appData.ponderNextMove) {
6579 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6581 XtSetArg(args[0], XtNleftBitmap, None);
6583 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6587 void PopupExitMessageProc(w, event, prms, nprms)
6595 appData.popupExitMessage = !appData.popupExitMessage;
6597 if (appData.popupExitMessage) {
6598 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6600 XtSetArg(args[0], XtNleftBitmap, None);
6602 XtSetValues(XtNameToWidget(menuBarWidget,
6603 "menuOptions.Popup Exit Message"), args, 1);
6606 void PopupMoveErrorsProc(w, event, prms, nprms)
6614 appData.popupMoveErrors = !appData.popupMoveErrors;
6616 if (appData.popupMoveErrors) {
6617 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6619 XtSetArg(args[0], XtNleftBitmap, None);
6621 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6625 void PremoveProc(w, event, prms, nprms)
6633 appData.premove = !appData.premove;
6635 if (appData.premove) {
6636 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6638 XtSetArg(args[0], XtNleftBitmap, None);
6640 XtSetValues(XtNameToWidget(menuBarWidget,
6641 "menuOptions.Premove"), args, 1);
6644 void QuietPlayProc(w, event, prms, nprms)
6652 appData.quietPlay = !appData.quietPlay;
6654 if (appData.quietPlay) {
6655 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6657 XtSetArg(args[0], XtNleftBitmap, None);
6659 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6663 void ShowCoordsProc(w, event, prms, nprms)
6671 appData.showCoords = !appData.showCoords;
6673 if (appData.showCoords) {
6674 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6676 XtSetArg(args[0], XtNleftBitmap, None);
6678 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6681 DrawPosition(True, NULL);
6684 void ShowThinkingProc(w, event, prms, nprms)
6692 ShowThinkingEvent(!appData.showThinking);
6694 if (appData.showThinking) {
6695 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6697 XtSetArg(args[0], XtNleftBitmap, None);
6699 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6703 void InfoProc(w, event, prms, nprms)
6710 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6715 void ManProc(w, event, prms, nprms)
6723 if (nprms && *nprms > 0)
6727 sprintf(buf, "xterm -e man %s &", name);
6731 void HintProc(w, event, prms, nprms)
6740 void BookProc(w, event, prms, nprms)
6749 void AboutProc(w, event, prms, nprms)
6757 char *zippy = " (with Zippy code)";
6761 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6762 programVersion, zippy,
6763 "Copyright 1991 Digital Equipment Corporation",
6764 "Enhancements Copyright 1992-2001 Free Software Foundation",
6765 PRODUCT, " is free software and carries NO WARRANTY;",
6766 "see the file COPYING for more information.");
6767 ErrorPopUp(_("About XBoard"), buf, FALSE);
6770 void DebugProc(w, event, prms, nprms)
6776 appData.debugMode = !appData.debugMode;
6779 void AboutGameProc(w, event, prms, nprms)
6788 void NothingProc(w, event, prms, nprms)
6797 void Iconify(w, event, prms, nprms)
6806 XtSetArg(args[0], XtNiconic, True);
6807 XtSetValues(shellWidget, args, 1);
6810 void DisplayMessage(message, extMessage)
6811 char *message, *extMessage;
6818 sprintf(buf, "%s %s", message, extMessage);
6821 message = extMessage;
6824 XtSetArg(arg, XtNlabel, message);
6825 XtSetValues(messageWidget, &arg, 1);
6828 void DisplayTitle(text)
6833 char title[MSG_SIZ];
6836 if (text == NULL) text = "";
6838 if (appData.titleInWindow) {
6840 XtSetArg(args[i], XtNlabel, text); i++;
6841 XtSetValues(titleWidget, args, i);
6844 if (*text != NULLCHAR) {
6846 strcpy(title, text);
6847 } else if (appData.icsActive) {
6848 sprintf(icon, "%s", appData.icsHost);
6849 sprintf(title, "%s: %s", programName, appData.icsHost);
6850 } else if (appData.cmailGameName[0] != NULLCHAR) {
6851 sprintf(icon, "%s", "CMail");
6852 sprintf(title, "%s: %s", programName, "CMail");
6853 } else if (appData.noChessProgram) {
6854 strcpy(icon, programName);
6855 strcpy(title, programName);
6857 strcpy(icon, first.tidy);
6858 sprintf(title, "%s: %s", programName, first.tidy);
6861 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6862 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6863 XtSetValues(shellWidget, args, i);
6867 void DisplayError(message, error)
6874 if (appData.debugMode || appData.matchMode) {
6875 fprintf(stderr, "%s: %s\n", programName, message);
6878 if (appData.debugMode || appData.matchMode) {
6879 fprintf(stderr, "%s: %s: %s\n",
6880 programName, message, strerror(error));
6882 sprintf(buf, "%s: %s", message, strerror(error));
6885 ErrorPopUp(_("Error"), message, FALSE);
6889 void DisplayMoveError(message)
6894 DrawPosition(FALSE, NULL);
6895 if (appData.debugMode || appData.matchMode) {
6896 fprintf(stderr, "%s: %s\n", programName, message);
6898 if (appData.popupMoveErrors) {
6899 ErrorPopUp(_("Error"), message, FALSE);
6901 DisplayMessage(message, "");
6906 void DisplayFatalError(message, error, status)
6912 errorExitStatus = status;
6914 fprintf(stderr, "%s: %s\n", programName, message);
6916 fprintf(stderr, "%s: %s: %s\n",
6917 programName, message, strerror(error));
6918 sprintf(buf, "%s: %s", message, strerror(error));
6921 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6922 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6928 void DisplayInformation(message)
6932 ErrorPopUp(_("Information"), message, TRUE);
6935 void DisplayNote(message)
6939 ErrorPopUp(_("Note"), message, FALSE);
6943 NullXErrorCheck(dpy, error_event)
6945 XErrorEvent *error_event;
6950 void DisplayIcsInteractionTitle(message)
6953 if (oldICSInteractionTitle == NULL) {
6954 /* Magic to find the old window title, adapted from vim */
6955 char *wina = getenv("WINDOWID");
6957 Window win = (Window) atoi(wina);
6958 Window root, parent, *children;
6959 unsigned int nchildren;
6960 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6962 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6963 if (!XQueryTree(xDisplay, win, &root, &parent,
6964 &children, &nchildren)) break;
6965 if (children) XFree((void *)children);
6966 if (parent == root || parent == 0) break;
6969 XSetErrorHandler(oldHandler);
6971 if (oldICSInteractionTitle == NULL) {
6972 oldICSInteractionTitle = "xterm";
6975 printf("\033]0;%s\007", message);
6979 char pendingReplyPrefix[MSG_SIZ];
6980 ProcRef pendingReplyPR;
6982 void AskQuestionProc(w, event, prms, nprms)
6989 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6993 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6996 void AskQuestionPopDown()
6998 if (!askQuestionUp) return;
6999 XtPopdown(askQuestionShell);
7000 XtDestroyWidget(askQuestionShell);
7001 askQuestionUp = False;
7004 void AskQuestionReplyAction(w, event, prms, nprms)
7014 reply = XawDialogGetValueString(w = XtParent(w));
7015 strcpy(buf, pendingReplyPrefix);
7016 if (*buf) strcat(buf, " ");
7019 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7020 AskQuestionPopDown();
7022 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7025 void AskQuestionCallback(w, client_data, call_data)
7027 XtPointer client_data, call_data;
7032 XtSetArg(args[0], XtNlabel, &name);
7033 XtGetValues(w, args, 1);
7035 if (strcmp(name, _("cancel")) == 0) {
7036 AskQuestionPopDown();
7038 AskQuestionReplyAction(w, NULL, NULL, NULL);
7042 void AskQuestion(title, question, replyPrefix, pr)
7043 char *title, *question, *replyPrefix;
7047 Widget popup, layout, dialog, edit;
7053 strcpy(pendingReplyPrefix, replyPrefix);
7054 pendingReplyPR = pr;
7057 XtSetArg(args[i], XtNresizable, True); i++;
7058 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7059 askQuestionShell = popup =
7060 XtCreatePopupShell(title, transientShellWidgetClass,
7061 shellWidget, args, i);
7064 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7065 layoutArgs, XtNumber(layoutArgs));
7068 XtSetArg(args[i], XtNlabel, question); i++;
7069 XtSetArg(args[i], XtNvalue, ""); i++;
7070 XtSetArg(args[i], XtNborderWidth, 0); i++;
7071 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7074 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7075 (XtPointer) dialog);
7076 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7077 (XtPointer) dialog);
7079 XtRealizeWidget(popup);
7080 CatchDeleteWindow(popup, "AskQuestionPopDown");
7082 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7083 &x, &y, &win_x, &win_y, &mask);
7085 XtSetArg(args[0], XtNx, x - 10);
7086 XtSetArg(args[1], XtNy, y - 30);
7087 XtSetValues(popup, args, 2);
7089 XtPopup(popup, XtGrabExclusive);
7090 askQuestionUp = True;
7092 edit = XtNameToWidget(dialog, "*value");
7093 XtSetKeyboardFocus(popup, edit);
7101 if (*name == NULLCHAR) {
7103 } else if (strcmp(name, "$") == 0) {
7104 putc(BELLCHAR, stderr);
7107 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7115 PlaySound(appData.soundMove);
7121 PlaySound(appData.soundIcsWin);
7127 PlaySound(appData.soundIcsLoss);
7133 PlaySound(appData.soundIcsDraw);
7137 PlayIcsUnfinishedSound()
7139 PlaySound(appData.soundIcsUnfinished);
7145 PlaySound(appData.soundIcsAlarm);
7151 system("stty echo");
7157 system("stty -echo");
7161 Colorize(cc, continuation)
7166 int count, outCount, error;
7168 if (textColors[(int)cc].bg > 0) {
7169 if (textColors[(int)cc].fg > 0) {
7170 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7171 textColors[(int)cc].fg, textColors[(int)cc].bg);
7173 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7174 textColors[(int)cc].bg);
7177 if (textColors[(int)cc].fg > 0) {
7178 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7179 textColors[(int)cc].fg);
7181 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7184 count = strlen(buf);
7185 outCount = OutputToProcess(NoProc, buf, count, &error);
7186 if (outCount < count) {
7187 DisplayFatalError(_("Error writing to display"), error, 1);
7190 if (continuation) return;
7193 PlaySound(appData.soundShout);
7196 PlaySound(appData.soundSShout);
7199 PlaySound(appData.soundChannel1);
7202 PlaySound(appData.soundChannel);
7205 PlaySound(appData.soundKibitz);
7208 PlaySound(appData.soundTell);
7210 case ColorChallenge:
7211 PlaySound(appData.soundChallenge);
7214 PlaySound(appData.soundRequest);
7217 PlaySound(appData.soundSeek);
7228 return getpwuid(getuid())->pw_name;
7231 static char *ExpandPathName(path)
7234 static char static_buf[2000];
7235 char *d, *s, buf[2000];
7241 while (*s && isspace(*s))
7250 if (*(s+1) == '/') {
7251 strcpy(d, getpwuid(getuid())->pw_dir);
7256 *strchr(buf, '/') = 0;
7257 pwd = getpwnam(buf);
7260 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7264 strcpy(d, pwd->pw_dir);
7265 strcat(d, strchr(s+1, '/'));
7276 static char host_name[MSG_SIZ];
7278 #if HAVE_GETHOSTNAME
7279 gethostname(host_name, MSG_SIZ);
7281 #else /* not HAVE_GETHOSTNAME */
7282 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7283 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7285 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7287 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7288 #endif /* not HAVE_GETHOSTNAME */
7291 XtIntervalId delayedEventTimerXID = 0;
7292 DelayedEventCallback delayedEventCallback = 0;
7297 delayedEventTimerXID = 0;
7298 delayedEventCallback();
7302 ScheduleDelayedEvent(cb, millisec)
7303 DelayedEventCallback cb; long millisec;
7305 delayedEventCallback = cb;
7306 delayedEventTimerXID =
7307 XtAppAddTimeOut(appContext, millisec,
7308 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7311 DelayedEventCallback
7314 if (delayedEventTimerXID) {
7315 return delayedEventCallback;
7322 CancelDelayedEvent()
7324 if (delayedEventTimerXID) {
7325 XtRemoveTimeOut(delayedEventTimerXID);
7326 delayedEventTimerXID = 0;
7330 XtIntervalId loadGameTimerXID = 0;
7332 int LoadGameTimerRunning()
7334 return loadGameTimerXID != 0;
7337 int StopLoadGameTimer()
7339 if (loadGameTimerXID != 0) {
7340 XtRemoveTimeOut(loadGameTimerXID);
7341 loadGameTimerXID = 0;
7349 LoadGameTimerCallback(arg, id)
7353 loadGameTimerXID = 0;
7358 StartLoadGameTimer(millisec)
7362 XtAppAddTimeOut(appContext, millisec,
7363 (XtTimerCallbackProc) LoadGameTimerCallback,
7367 XtIntervalId analysisClockXID = 0;
7370 AnalysisClockCallback(arg, id)
7374 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7375 || appData.icsEngineAnalyze) {
7376 AnalysisPeriodicEvent(0);
7377 StartAnalysisClock();
7382 StartAnalysisClock()
7385 XtAppAddTimeOut(appContext, 2000,
7386 (XtTimerCallbackProc) AnalysisClockCallback,
7390 XtIntervalId clockTimerXID = 0;
7392 int ClockTimerRunning()
7394 return clockTimerXID != 0;
7397 int StopClockTimer()
7399 if (clockTimerXID != 0) {
7400 XtRemoveTimeOut(clockTimerXID);
7409 ClockTimerCallback(arg, id)
7418 StartClockTimer(millisec)
7422 XtAppAddTimeOut(appContext, millisec,
7423 (XtTimerCallbackProc) ClockTimerCallback,
7428 DisplayTimerLabel(w, color, timer, highlight)
7437 if (appData.clockMode) {
7438 sprintf(buf, "%s: %s", color, TimeString(timer));
7439 XtSetArg(args[0], XtNlabel, buf);
7441 sprintf(buf, "%s ", color);
7442 XtSetArg(args[0], XtNlabel, buf);
7446 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7447 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7449 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7450 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7453 XtSetValues(w, args, 3);
7457 DisplayWhiteClock(timeRemaining, highlight)
7462 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
7463 if (highlight && iconPixmap == bIconPixmap) {
7464 iconPixmap = wIconPixmap;
7465 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7466 XtSetValues(shellWidget, args, 1);
7471 DisplayBlackClock(timeRemaining, highlight)
7476 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
7477 if (highlight && iconPixmap == wIconPixmap) {
7478 iconPixmap = bIconPixmap;
7479 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7480 XtSetValues(shellWidget, args, 1);
7498 int StartChildProcess(cmdLine, dir, pr)
7505 int to_prog[2], from_prog[2];
7509 if (appData.debugMode) {
7510 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7513 /* We do NOT feed the cmdLine to the shell; we just
7514 parse it into blank-separated arguments in the
7515 most simple-minded way possible.
7518 strcpy(buf, cmdLine);
7523 if (p == NULL) break;
7528 SetUpChildIO(to_prog, from_prog);
7530 if ((pid = fork()) == 0) {
7532 dup2(to_prog[0], 0);
7533 dup2(from_prog[1], 1);
7536 close(from_prog[0]);
7537 close(from_prog[1]);
7538 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7540 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7545 execvp(argv[0], argv);
7547 /* If we get here, exec failed */
7552 /* Parent process */
7554 close(from_prog[1]);
7556 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7559 cp->fdFrom = from_prog[0];
7560 cp->fdTo = to_prog[1];
7566 DestroyChildProcess(pr, signal)
7570 ChildProc *cp = (ChildProc *) pr;
7572 if (cp->kind != CPReal) return;
7575 kill(cp->pid, SIGTERM);
7577 /* Process is exiting either because of the kill or because of
7578 a quit command sent by the backend; either way, wait for it to die.
7586 InterruptChildProcess(pr)
7589 ChildProc *cp = (ChildProc *) pr;
7591 if (cp->kind != CPReal) return;
7592 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7595 int OpenTelnet(host, port, pr)
7600 char cmdLine[MSG_SIZ];
7602 if (port[0] == NULLCHAR) {
7603 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7605 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7607 return StartChildProcess(cmdLine, "", pr);
7610 int OpenTCP(host, port, pr)
7616 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7617 #else /* !OMIT_SOCKETS */
7619 struct sockaddr_in sa;
7621 unsigned short uport;
7624 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7628 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7629 sa.sin_family = AF_INET;
7630 sa.sin_addr.s_addr = INADDR_ANY;
7631 uport = (unsigned short) 0;
7632 sa.sin_port = htons(uport);
7633 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7637 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7638 if (!(hp = gethostbyname(host))) {
7640 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7641 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7642 hp->h_addrtype = AF_INET;
7644 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7645 hp->h_addr_list[0] = (char *) malloc(4);
7646 hp->h_addr_list[0][0] = b0;
7647 hp->h_addr_list[0][1] = b1;
7648 hp->h_addr_list[0][2] = b2;
7649 hp->h_addr_list[0][3] = b3;
7654 sa.sin_family = hp->h_addrtype;
7655 uport = (unsigned short) atoi(port);
7656 sa.sin_port = htons(uport);
7657 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7659 if (connect(s, (struct sockaddr *) &sa,
7660 sizeof(struct sockaddr_in)) < 0) {
7664 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7671 #endif /* !OMIT_SOCKETS */
7676 int OpenCommPort(name, pr)
7683 fd = open(name, 2, 0);
7684 if (fd < 0) return errno;
7686 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7696 int OpenLoopback(pr)
7702 SetUpChildIO(to, from);
7704 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7707 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7714 int OpenRcmd(host, user, cmd, pr)
7715 char *host, *user, *cmd;
7718 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7722 #define INPUT_SOURCE_BUF_SIZE 8192
7731 char buf[INPUT_SOURCE_BUF_SIZE];
7736 DoInputCallback(closure, source, xid)
7741 InputSource *is = (InputSource *) closure;
7746 if (is->lineByLine) {
7747 count = read(is->fd, is->unused,
7748 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7750 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7753 is->unused += count;
7755 while (p < is->unused) {
7756 q = memchr(p, '\n', is->unused - p);
7757 if (q == NULL) break;
7759 (is->func)(is, is->closure, p, q - p, 0);
7763 while (p < is->unused) {
7768 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7773 (is->func)(is, is->closure, is->buf, count, error);
7777 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7784 ChildProc *cp = (ChildProc *) pr;
7786 is = (InputSource *) calloc(1, sizeof(InputSource));
7787 is->lineByLine = lineByLine;
7791 is->fd = fileno(stdin);
7793 is->kind = cp->kind;
7794 is->fd = cp->fdFrom;
7797 is->unused = is->buf;
7800 is->xid = XtAppAddInput(appContext, is->fd,
7801 (XtPointer) (XtInputReadMask),
7802 (XtInputCallbackProc) DoInputCallback,
7804 is->closure = closure;
7805 return (InputSourceRef) is;
7809 RemoveInputSource(isr)
7812 InputSource *is = (InputSource *) isr;
7814 if (is->xid == 0) return;
7815 XtRemoveInput(is->xid);
7819 int OutputToProcess(pr, message, count, outError)
7825 ChildProc *cp = (ChildProc *) pr;
7829 outCount = fwrite(message, 1, count, stdout);
7831 outCount = write(cp->fdTo, message, count);
7841 /* Output message to process, with "ms" milliseconds of delay
7842 between each character. This is needed when sending the logon
7843 script to ICC, which for some reason doesn't like the
7844 instantaneous send. */
7845 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7852 ChildProc *cp = (ChildProc *) pr;
7857 r = write(cp->fdTo, message++, 1);
7870 /**** Animation code by Hugh Fisher, DCS, ANU.
7872 Known problem: if a window overlapping the board is
7873 moved away while a piece is being animated underneath,
7874 the newly exposed area won't be updated properly.
7875 I can live with this.
7877 Known problem: if you look carefully at the animation
7878 of pieces in mono mode, they are being drawn as solid
7879 shapes without interior detail while moving. Fixing
7880 this would be a major complication for minimal return.
7883 /* Masks for XPM pieces. Black and white pieces can have
7884 different shapes, but in the interest of retaining my
7885 sanity pieces must have the same outline on both light
7886 and dark squares, and all pieces must use the same
7887 background square colors/images. */
7890 CreateAnimMasks (pieceDepth)
7897 unsigned long plane;
7900 /* Need a bitmap just to get a GC with right depth */
7901 buf = XCreatePixmap(xDisplay, xBoardWindow,
7903 values.foreground = 1;
7904 values.background = 0;
7905 /* Don't use XtGetGC, not read only */
7906 maskGC = XCreateGC(xDisplay, buf,
7907 GCForeground | GCBackground, &values);
7908 XFreePixmap(xDisplay, buf);
7910 buf = XCreatePixmap(xDisplay, xBoardWindow,
7911 squareSize, squareSize, pieceDepth);
7912 values.foreground = XBlackPixel(xDisplay, xScreen);
7913 values.background = XWhitePixel(xDisplay, xScreen);
7914 bufGC = XCreateGC(xDisplay, buf,
7915 GCForeground | GCBackground, &values);
7917 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7918 /* Begin with empty mask */
7919 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7920 squareSize, squareSize, 1);
7921 XSetFunction(xDisplay, maskGC, GXclear);
7922 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7923 0, 0, squareSize, squareSize);
7925 /* Take a copy of the piece */
7930 XSetFunction(xDisplay, bufGC, GXcopy);
7931 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7933 0, 0, squareSize, squareSize, 0, 0);
7935 /* XOR the background (light) over the piece */
7936 XSetFunction(xDisplay, bufGC, GXxor);
7938 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7939 0, 0, squareSize, squareSize, 0, 0);
7941 XSetForeground(xDisplay, bufGC, lightSquareColor);
7942 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7945 /* We now have an inverted piece image with the background
7946 erased. Construct mask by just selecting all the non-zero
7947 pixels - no need to reconstruct the original image. */
7948 XSetFunction(xDisplay, maskGC, GXor);
7950 /* Might be quicker to download an XImage and create bitmap
7951 data from it rather than this N copies per piece, but it
7952 only takes a fraction of a second and there is a much
7953 longer delay for loading the pieces. */
7954 for (n = 0; n < pieceDepth; n ++) {
7955 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7956 0, 0, squareSize, squareSize,
7962 XFreePixmap(xDisplay, buf);
7963 XFreeGC(xDisplay, bufGC);
7964 XFreeGC(xDisplay, maskGC);
7968 InitAnimState (anim, info)
7970 XWindowAttributes * info;
7975 /* Each buffer is square size, same depth as window */
7976 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7977 squareSize, squareSize, info->depth);
7978 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7979 squareSize, squareSize, info->depth);
7981 /* Create a plain GC for blitting */
7982 mask = GCForeground | GCBackground | GCFunction |
7983 GCPlaneMask | GCGraphicsExposures;
7984 values.foreground = XBlackPixel(xDisplay, xScreen);
7985 values.background = XWhitePixel(xDisplay, xScreen);
7986 values.function = GXcopy;
7987 values.plane_mask = AllPlanes;
7988 values.graphics_exposures = False;
7989 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7991 /* Piece will be copied from an existing context at
7992 the start of each new animation/drag. */
7993 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7995 /* Outline will be a read-only copy of an existing */
7996 anim->outlineGC = None;
8002 static int done = 0;
8003 XWindowAttributes info;
8007 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
8009 InitAnimState(&game, &info);
8010 InitAnimState(&player, &info);
8012 /* For XPM pieces, we need bitmaps to use as masks. */
8014 CreateAnimMasks(info.depth);
8019 static Boolean frameWaiting;
8021 static RETSIGTYPE FrameAlarm (sig)
8024 frameWaiting = False;
8025 /* In case System-V style signals. Needed?? */
8026 signal(SIGALRM, FrameAlarm);
8033 struct itimerval delay;
8035 XSync(xDisplay, False);
8038 frameWaiting = True;
8039 signal(SIGALRM, FrameAlarm);
8040 delay.it_interval.tv_sec =
8041 delay.it_value.tv_sec = time / 1000;
8042 delay.it_interval.tv_usec =
8043 delay.it_value.tv_usec = (time % 1000) * 1000;
8044 setitimer(ITIMER_REAL, &delay, NULL);
8046 /* Ugh -- busy-wait! --tpm */
8047 while (frameWaiting);
8049 while (frameWaiting) pause();
8051 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8052 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8053 setitimer(ITIMER_REAL, &delay, NULL);
8063 XSync(xDisplay, False);
8065 usleep(time * 1000);
8070 /* Convert board position to corner of screen rect and color */
8073 ScreenSquare(column, row, pt, color)
8074 int column; int row; XPoint * pt; int * color;
8077 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
8078 pt->y = lineGap + row * (squareSize + lineGap);
8080 pt->x = lineGap + column * (squareSize + lineGap);
8081 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
8083 *color = ((column + row) % 2) == 1;
8086 /* Convert window coords to square */
8089 BoardSquare(x, y, column, row)
8090 int x; int y; int * column; int * row;
8092 *column = EventToSquare(x, BOARD_SIZE);
8093 if (flipView && *column >= 0)
8094 *column = BOARD_SIZE - 1 - *column;
8095 *row = EventToSquare(y, BOARD_SIZE);
8096 if (!flipView && *row >= 0)
8097 *row = BOARD_SIZE - 1 - *row;
8102 #undef Max /* just in case */
8104 #define Max(a, b) ((a) > (b) ? (a) : (b))
8105 #define Min(a, b) ((a) < (b) ? (a) : (b))
8108 SetRect(rect, x, y, width, height)
8109 XRectangle * rect; int x; int y; int width; int height;
8113 rect->width = width;
8114 rect->height = height;
8117 /* Test if two frames overlap. If they do, return
8118 intersection rect within old and location of
8119 that rect within new. */
8122 Intersect(old, new, size, area, pt)
8123 XPoint * old; XPoint * new;
8124 int size; XRectangle * area; XPoint * pt;
8126 if (old->x > new->x + size || new->x > old->x + size ||
8127 old->y > new->y + size || new->y > old->y + size) {
8130 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8131 size - abs(old->x - new->x), size - abs(old->y - new->y));
8132 pt->x = Max(old->x - new->x, 0);
8133 pt->y = Max(old->y - new->y, 0);
8138 /* For two overlapping frames, return the rect(s)
8139 in the old that do not intersect with the new. */
8142 CalcUpdateRects(old, new, size, update, nUpdates)
8143 XPoint * old; XPoint * new; int size;
8144 XRectangle update[]; int * nUpdates;
8148 /* If old = new (shouldn't happen) then nothing to draw */
8149 if (old->x == new->x && old->y == new->y) {
8153 /* Work out what bits overlap. Since we know the rects
8154 are the same size we don't need a full intersect calc. */
8156 /* Top or bottom edge? */
8157 if (new->y > old->y) {
8158 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8160 } else if (old->y > new->y) {
8161 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8162 size, old->y - new->y);
8165 /* Left or right edge - don't overlap any update calculated above. */
8166 if (new->x > old->x) {
8167 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8168 new->x - old->x, size - abs(new->y - old->y));
8170 } else if (old->x > new->x) {
8171 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8172 old->x - new->x, size - abs(new->y - old->y));
8179 /* Generate a series of frame coords from start->mid->finish.
8180 The movement rate doubles until the half way point is
8181 reached, then halves back down to the final destination,
8182 which gives a nice slow in/out effect. The algorithmn
8183 may seem to generate too many intermediates for short
8184 moves, but remember that the purpose is to attract the
8185 viewers attention to the piece about to be moved and
8186 then to where it ends up. Too few frames would be less
8190 Tween(start, mid, finish, factor, frames, nFrames)
8191 XPoint * start; XPoint * mid;
8192 XPoint * finish; int factor;
8193 XPoint frames[]; int * nFrames;
8195 int fraction, n, count;
8199 /* Slow in, stepping 1/16th, then 1/8th, ... */
8201 for (n = 0; n < factor; n++)
8203 for (n = 0; n < factor; n++) {
8204 frames[count].x = start->x + (mid->x - start->x) / fraction;
8205 frames[count].y = start->y + (mid->y - start->y) / fraction;
8207 fraction = fraction / 2;
8211 frames[count] = *mid;
8214 /* Slow out, stepping 1/2, then 1/4, ... */
8216 for (n = 0; n < factor; n++) {
8217 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8218 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8220 fraction = fraction * 2;
8225 /* Draw a piece on the screen without disturbing what's there */
8228 SelectGCMask(piece, clip, outline, mask)
8229 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8233 /* Bitmap for piece being moved. */
8234 if (appData.monoMode) {
8235 *mask = *pieceToSolid(piece);
8236 } else if (useImages) {
8238 *mask = xpmMask[piece];
8240 *mask = ximMaskPm[piece%6];
8243 *mask = *pieceToSolid(piece);
8246 /* GC for piece being moved. Square color doesn't matter, but
8247 since it gets modified we make a copy of the original. */
8249 if (appData.monoMode)
8254 if (appData.monoMode)
8259 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8261 /* Outline only used in mono mode and is not modified */
8263 *outline = bwPieceGC;
8265 *outline = wbPieceGC;
8269 OverlayPiece(piece, clip, outline, dest)
8270 ChessSquare piece; GC clip; GC outline; Drawable dest;
8275 /* Draw solid rectangle which will be clipped to shape of piece */
8276 XFillRectangle(xDisplay, dest, clip,
8277 0, 0, squareSize, squareSize);
8278 if (appData.monoMode)
8279 /* Also draw outline in contrasting color for black
8280 on black / white on white cases */
8281 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8282 0, 0, squareSize, squareSize, 0, 0, 1);
8284 /* Copy the piece */
8289 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8291 0, 0, squareSize, squareSize,
8296 /* Animate the movement of a single piece */
8299 BeginAnimation(anim, piece, startColor, start)
8307 /* The old buffer is initialised with the start square (empty) */
8308 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8309 anim->prevFrame = *start;
8311 /* The piece will be drawn using its own bitmap as a matte */
8312 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8313 XSetClipMask(xDisplay, anim->pieceGC, mask);
8317 AnimationFrame(anim, frame, piece)
8322 XRectangle updates[4];
8327 /* Save what we are about to draw into the new buffer */
8328 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8329 frame->x, frame->y, squareSize, squareSize,
8332 /* Erase bits of the previous frame */
8333 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8334 /* Where the new frame overlapped the previous,
8335 the contents in newBuf are wrong. */
8336 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8337 overlap.x, overlap.y,
8338 overlap.width, overlap.height,
8340 /* Repaint the areas in the old that don't overlap new */
8341 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8342 for (i = 0; i < count; i++)
8343 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8344 updates[i].x - anim->prevFrame.x,
8345 updates[i].y - anim->prevFrame.y,
8346 updates[i].width, updates[i].height,
8347 updates[i].x, updates[i].y);
8349 /* Easy when no overlap */
8350 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8351 0, 0, squareSize, squareSize,
8352 anim->prevFrame.x, anim->prevFrame.y);
8355 /* Save this frame for next time round */
8356 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8357 0, 0, squareSize, squareSize,
8359 anim->prevFrame = *frame;
8361 /* Draw piece over original screen contents, not current,
8362 and copy entire rect. Wipes out overlapping piece images. */
8363 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8364 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8365 0, 0, squareSize, squareSize,
8366 frame->x, frame->y);
8370 EndAnimation (anim, finish)
8374 XRectangle updates[4];
8379 /* The main code will redraw the final square, so we
8380 only need to erase the bits that don't overlap. */
8381 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8382 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8383 for (i = 0; i < count; i++)
8384 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8385 updates[i].x - anim->prevFrame.x,
8386 updates[i].y - anim->prevFrame.y,
8387 updates[i].width, updates[i].height,
8388 updates[i].x, updates[i].y);
8390 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8391 0, 0, squareSize, squareSize,
8392 anim->prevFrame.x, anim->prevFrame.y);
8397 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8399 ChessSquare piece; int startColor;
8400 XPoint * start; XPoint * finish;
8401 XPoint frames[]; int nFrames;
8405 BeginAnimation(anim, piece, startColor, start);
8406 for (n = 0; n < nFrames; n++) {
8407 AnimationFrame(anim, &(frames[n]), piece);
8408 FrameDelay(appData.animSpeed);
8410 EndAnimation(anim, finish);
8413 /* Main control logic for deciding what to animate and how */
8416 AnimateMove(board, fromX, fromY, toX, toY)
8425 XPoint start, finish, mid;
8426 XPoint frames[kFactor * 2 + 1];
8427 int nFrames, startColor, endColor;
8429 /* Are we animating? */
8430 if (!appData.animate || appData.blindfold)
8433 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8434 piece = board[fromY][fromX];
8435 if (piece >= EmptySquare) return;
8440 hop = (piece == WhiteKnight || piece == BlackKnight);
8443 if (appData.debugMode) {
8444 printf(hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8445 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8446 piece, fromX, fromY, toX, toY);
8449 ScreenSquare(fromX, fromY, &start, &startColor);
8450 ScreenSquare(toX, toY, &finish, &endColor);
8453 /* Knight: make diagonal movement then straight */
8454 if (abs(toY - fromY) < abs(toX - fromX)) {
8455 mid.x = start.x + (finish.x - start.x) / 2;
8459 mid.y = start.y + (finish.y - start.y) / 2;
8462 mid.x = start.x + (finish.x - start.x) / 2;
8463 mid.y = start.y + (finish.y - start.y) / 2;
8466 /* Don't use as many frames for very short moves */
8467 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8468 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8470 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8471 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8473 /* Be sure end square is redrawn */
8474 damage[toY][toX] = True;
8478 DragPieceBegin(x, y)
8481 int boardX, boardY, color;
8484 /* Are we animating? */
8485 if (!appData.animateDragging || appData.blindfold)
8488 /* Figure out which square we start in and the
8489 mouse position relative to top left corner. */
8490 BoardSquare(x, y, &boardX, &boardY);
8491 player.startBoardX = boardX;
8492 player.startBoardY = boardY;
8493 ScreenSquare(boardX, boardY, &corner, &color);
8494 player.startSquare = corner;
8495 player.startColor = color;
8497 /* Start from exactly where the piece is. This can be confusing
8498 if you start dragging far from the center of the square; most
8499 or all of the piece can be over a different square from the one
8500 the mouse pointer is in. */
8501 player.mouseDelta.x = x - corner.x;
8502 player.mouseDelta.y = y - corner.y;
8504 /* As soon as we start dragging, the piece will jump slightly to
8505 be centered over the mouse pointer. */
8506 player.mouseDelta.x = squareSize/2;
8507 player.mouseDelta.y = squareSize/2;
8509 /* Initialise animation */
8510 player.dragPiece = PieceForSquare(boardX, boardY);
8512 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8513 player.dragActive = True;
8514 BeginAnimation(&player, player.dragPiece, color, &corner);
8515 /* Mark this square as needing to be redrawn. Note that
8516 we don't remove the piece though, since logically (ie
8517 as seen by opponent) the move hasn't been made yet. */
8518 damage[boardY][boardX] = True;
8520 player.dragActive = False;
8530 /* Are we animating? */
8531 if (!appData.animateDragging || appData.blindfold)
8535 if (! player.dragActive)
8537 /* Move piece, maintaining same relative position
8538 of mouse within square */
8539 corner.x = x - player.mouseDelta.x;
8540 corner.y = y - player.mouseDelta.y;
8541 AnimationFrame(&player, &corner, player.dragPiece);
8543 if (appData.highlightDragging) {
8545 BoardSquare(x, y, &boardX, &boardY);
8546 SetHighlights(fromX, fromY, boardX, boardY);
8555 int boardX, boardY, color;
8558 /* Are we animating? */
8559 if (!appData.animateDragging || appData.blindfold)
8563 if (! player.dragActive)
8565 /* Last frame in sequence is square piece is
8566 placed on, which may not match mouse exactly. */
8567 BoardSquare(x, y, &boardX, &boardY);
8568 ScreenSquare(boardX, boardY, &corner, &color);
8569 EndAnimation(&player, &corner);
8571 /* Be sure end square is redrawn */
8572 damage[boardY][boardX] = True;
8574 /* This prevents weird things happening with fast successive
8575 clicks which on my Sun at least can cause motion events
8576 without corresponding press/release. */
8577 player.dragActive = False;
8580 /* Handle expose event while piece being dragged */
8585 if (!player.dragActive || appData.blindfold)
8588 /* What we're doing: logically, the move hasn't been made yet,
8589 so the piece is still in it's original square. But visually
8590 it's being dragged around the board. So we erase the square
8591 that the piece is on and draw it at the last known drag point. */
8592 BlankSquare(player.startSquare.x, player.startSquare.y,
8593 player.startColor, EmptySquare, xBoardWindow);
8594 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8595 damage[player.startBoardY][player.startBoardX] = TRUE;