2 * xboard.c -- X front end for XBoard
5 * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
6 * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
8 * The following terms apply to Digital Equipment Corporation's copyright
10 * ------------------------------------------------------------------------
13 * Permission to use, copy, modify, and distribute this software and its
14 * documentation for any purpose and without fee is hereby granted,
15 * provided that the above copyright notice appear in all copies and that
16 * both that copyright notice and this permission notice appear in
17 * supporting documentation, and that the name of Digital not be
18 * used in advertising or publicity pertaining to distribution of the
19 * software without specific, written prior permission.
21 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28 * ------------------------------------------------------------------------
30 * The following terms apply to the enhanced version of XBoard distributed
31 * by the Free Software Foundation:
32 * ------------------------------------------------------------------------
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
43 * You should have received a copy of the GNU General Public License
44 * along with this program; if not, write to the Free Software
45 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 * ------------------------------------------------------------------------
48 * See the file ChangeLog for a revision history.
57 #include <sys/types.h>
62 # if HAVE_SYS_SOCKET_H
63 # include <sys/socket.h>
64 # include <netinet/in.h>
66 # else /* not HAVE_SYS_SOCKET_H */
67 # if HAVE_LAN_SOCKET_H
68 # include <lan/socket.h>
70 # include <lan/netdb.h>
71 # else /* not HAVE_LAN_SOCKET_H */
72 # define OMIT_SOCKETS 1
73 # endif /* not HAVE_LAN_SOCKET_H */
74 # endif /* not HAVE_SYS_SOCKET_H */
75 #endif /* !OMIT_SOCKETS */
80 #else /* not STDC_HEADERS */
81 extern char *getenv();
84 # else /* not HAVE_STRING_H */
86 # endif /* not HAVE_STRING_H */
87 #endif /* not STDC_HEADERS */
90 # include <sys/fcntl.h>
91 #else /* not HAVE_SYS_FCNTL_H */
94 # endif /* HAVE_FCNTL_H */
95 #endif /* not HAVE_SYS_FCNTL_H */
97 #if HAVE_SYS_SYSTEMINFO_H
98 # include <sys/systeminfo.h>
99 #endif /* HAVE_SYS_SYSTEMINFO_H */
101 #if TIME_WITH_SYS_TIME
102 # include <sys/time.h>
106 # include <sys/time.h>
117 # include <sys/wait.h>
122 # define NAMLEN(dirent) strlen((dirent)->d_name)
123 # define HAVE_DIR_STRUCT
125 # define dirent direct
126 # define NAMLEN(dirent) (dirent)->d_namlen
128 # include <sys/ndir.h>
129 # define HAVE_DIR_STRUCT
132 # include <sys/dir.h>
133 # define HAVE_DIR_STRUCT
137 # define HAVE_DIR_STRUCT
141 #include <X11/Intrinsic.h>
142 #include <X11/StringDefs.h>
143 #include <X11/Shell.h>
144 #include <X11/cursorfont.h>
145 #include <X11/Xatom.h>
147 #include <X11/Xaw3d/Dialog.h>
148 #include <X11/Xaw3d/Form.h>
149 #include <X11/Xaw3d/List.h>
150 #include <X11/Xaw3d/Label.h>
151 #include <X11/Xaw3d/SimpleMenu.h>
152 #include <X11/Xaw3d/SmeBSB.h>
153 #include <X11/Xaw3d/SmeLine.h>
154 #include <X11/Xaw3d/Box.h>
155 #include <X11/Xaw3d/MenuButton.h>
156 #include <X11/Xaw3d/Text.h>
157 #include <X11/Xaw3d/AsciiText.h>
159 #include <X11/Xaw/Dialog.h>
160 #include <X11/Xaw/Form.h>
161 #include <X11/Xaw/List.h>
162 #include <X11/Xaw/Label.h>
163 #include <X11/Xaw/SimpleMenu.h>
164 #include <X11/Xaw/SmeBSB.h>
165 #include <X11/Xaw/SmeLine.h>
166 #include <X11/Xaw/Box.h>
167 #include <X11/Xaw/MenuButton.h>
168 #include <X11/Xaw/Text.h>
169 #include <X11/Xaw/AsciiText.h>
174 #include "pixmaps/pixmaps.h"
175 #define IMAGE_EXT "xpm"
177 #define IMAGE_EXT "xim"
178 #include "bitmaps/bitmaps.h"
181 #include "bitmaps/icon_white.bm"
182 #include "bitmaps/icon_black.bm"
183 #include "bitmaps/checkmark.bm"
186 #include "frontend.h"
191 #include "xgamelist.h"
192 #include "xhistory.h"
193 #include "xedittags.h"
200 #define usleep(t) _sleep2(((t)+500)/1000)
204 # define _(s) gettext (s)
205 # define N_(s) gettext_noop (s)
221 int main P((int argc, char **argv));
222 RETSIGTYPE CmailSigHandler P((int sig));
223 RETSIGTYPE IntSigHandler P((int sig));
224 void CreateGCs P((void));
225 void CreateXIMPieces P((void));
226 void CreateXPMPieces P((void));
227 void CreatePieces P((void));
228 void CreatePieceMenus P((void));
229 Widget CreateMenuBar P((Menu *mb));
230 Widget CreateButtonBar P ((MenuItem *mi));
231 char *FindFont P((char *pattern, int targetPxlSize));
232 void PieceMenuPopup P((Widget w, XEvent *event,
233 String *params, Cardinal *num_params));
234 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
235 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
236 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
237 u_int wreq, u_int hreq));
238 void CreateGrid P((void));
239 int EventToSquare P((int x, int limit));
240 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
241 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
242 void HandleUserMove P((Widget w, XEvent *event,
243 String *prms, Cardinal *nprms));
244 void AnimateUserMove P((Widget w, XEvent * event,
245 String * params, Cardinal * nParams));
246 void WhiteClock P((Widget w, XEvent *event,
247 String *prms, Cardinal *nprms));
248 void BlackClock P((Widget w, XEvent *event,
249 String *prms, Cardinal *nprms));
250 void DrawPositionProc P((Widget w, XEvent *event,
251 String *prms, Cardinal *nprms));
252 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
254 void CommentPopUp P((char *title, char *label));
255 void CommentPopDown P((void));
256 void CommentCallback P((Widget w, XtPointer client_data,
257 XtPointer call_data));
258 void ICSInputBoxPopUp P((void));
259 void ICSInputBoxPopDown P((void));
260 void FileNamePopUp P((char *label, char *def,
261 FileProc proc, char *openMode));
262 void FileNamePopDown P((void));
263 void FileNameCallback P((Widget w, XtPointer client_data,
264 XtPointer call_data));
265 void FileNameAction P((Widget w, XEvent *event,
266 String *prms, Cardinal *nprms));
267 void AskQuestionReplyAction P((Widget w, XEvent *event,
268 String *prms, Cardinal *nprms));
269 void AskQuestionProc P((Widget w, XEvent *event,
270 String *prms, Cardinal *nprms));
271 void AskQuestionPopDown P((void));
272 void PromotionPopUp P((void));
273 void PromotionPopDown P((void));
274 void PromotionCallback P((Widget w, XtPointer client_data,
275 XtPointer call_data));
276 void EditCommentPopDown P((void));
277 void EditCommentCallback P((Widget w, XtPointer client_data,
278 XtPointer call_data));
279 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
280 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
281 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
282 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
284 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
286 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
288 void LoadPositionProc P((Widget w, XEvent *event,
289 String *prms, Cardinal *nprms));
290 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
292 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
294 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
296 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
298 void PastePositionProc P((Widget w, XEvent *event, String *prms,
300 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
301 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
302 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
303 void SavePositionProc P((Widget w, XEvent *event,
304 String *prms, Cardinal *nprms));
305 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
306 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
308 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
309 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
310 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
312 void MachineWhiteProc P((Widget w, XEvent *event,
313 String *prms, Cardinal *nprms));
314 void AnalyzeModeProc P((Widget w, XEvent *event,
315 String *prms, Cardinal *nprms));
316 void AnalyzeFileProc P((Widget w, XEvent *event,
317 String *prms, Cardinal *nprms));
318 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
320 void IcsClientProc P((Widget w, XEvent *event, String *prms,
322 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
323 void EditPositionProc P((Widget w, XEvent *event,
324 String *prms, Cardinal *nprms));
325 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
326 void EditCommentProc P((Widget w, XEvent *event,
327 String *prms, Cardinal *nprms));
328 void IcsInputBoxProc P((Widget w, XEvent *event,
329 String *prms, Cardinal *nprms));
330 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
331 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
332 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
333 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
334 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
335 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
336 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
337 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
338 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
339 void StopObservingProc P((Widget w, XEvent *event, String *prms,
341 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
343 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
344 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
345 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
346 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
347 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
348 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
350 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
352 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
353 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
355 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
357 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
359 void AutocommProc P((Widget w, XEvent *event, String *prms,
361 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
362 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
363 void AutobsProc P((Widget w, XEvent *event, String *prms,
365 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
366 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
367 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
368 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
370 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
371 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
373 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
375 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
377 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
378 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
379 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
381 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
383 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
385 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
387 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
389 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
390 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
391 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
393 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
395 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
397 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
398 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
399 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
400 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
401 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
402 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
403 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
404 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
405 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
406 void DisplayMove P((int moveNumber));
407 void DisplayTitle P((char *title));
408 void ICSInitScript P((void));
409 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
410 void ErrorPopUp P((char *title, char *text, int modal));
411 void ErrorPopDown P((void));
412 static char *ExpandPathName P((char *path));
413 static void CreateAnimVars P((void));
414 static void DragPieceBegin P((int x, int y));
415 static void DragPieceMove P((int x, int y));
416 static void DragPieceEnd P((int x, int y));
417 static void DrawDragPiece P((void));
418 char *ModeToWidgetName P((GameMode mode));
421 * XBoard depends on Xt R4 or higher
423 int xtVersion = XtSpecificationRelease;
428 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
429 jailSquareColor, highlightSquareColor, premoveHighlightColor;
430 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
431 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
432 wjPieceGC, bjPieceGC, prelineGC;
433 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
434 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
435 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
436 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
437 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
438 ICSInputShell, fileNameShell, askQuestionShell;
439 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
440 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
441 Font clockFontID, coordFontID;
442 XFontStruct *clockFontStruct, *coordFontStruct;
443 XtAppContext appContext;
445 char *oldICSInteractionTitle;
450 Position commentX = -1, commentY = -1;
451 Dimension commentW, commentH;
453 int squareSize, smallLayout = 0, tinyLayout = 0,
454 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
455 ICSInputBoxUp = False, askQuestionUp = False,
456 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
457 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
458 Pixel timerForegroundPixel, timerBackgroundPixel;
459 Pixel buttonForegroundPixel, buttonBackgroundPixel;
460 char *chessDir, *programName, *programVersion,
461 *gameCopyFilename, *gamePasteFilename;
465 Pixmap pieceBitmap[2][6];
466 Pixmap xpmPieceBitmap[4][6]; /* LL, LD, DL, DD */
467 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
468 int useImages, useImageSqs;
469 XImage *ximPieceBitmap[4][6]; /* LL, LD, DL, DD */
470 Pixmap ximMaskPm[6]; /* clipmasks, used for XIM pieces */
471 XImage *ximLightSquare, *ximDarkSquare;
474 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % 6]
475 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % 6]
477 #define White(piece) ((int)(piece) < (int)BlackPawn)
479 /* Variables for doing smooth animation. This whole thing
480 would be much easier if the board was double-buffered,
481 but that would require a fairly major rewrite. */
486 GC blitGC, pieceGC, outlineGC;
487 XPoint startSquare, prevFrame, mouseDelta;
491 int startBoardX, startBoardY;
494 /* There can be two pieces being animated at once: a player
495 can begin dragging a piece before the remote opponent has moved. */
497 static AnimState game, player;
499 /* Bitmaps for use as masks when drawing XPM pieces.
500 Need one for each black and white piece. */
501 static Pixmap xpmMask[BlackKing + 1];
503 /* This magic number is the number of intermediate frames used
504 in each half of the animation. For short moves it's reduced
505 by 1. The total number of frames will be factor * 2 + 1. */
508 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
510 MenuItem fileMenu[] = {
511 {N_("Reset Game"), ResetProc},
512 {"----", NothingProc},
513 {N_("Load Game"), LoadGameProc},
514 {N_("Load Next Game"), LoadNextGameProc},
515 {N_("Load Previous Game"), LoadPrevGameProc},
516 {N_("Reload Same Game"), ReloadGameProc},
517 {N_("Save Game"), SaveGameProc},
518 {"----", NothingProc},
519 {N_("Copy Game"), CopyGameProc},
520 {N_("Paste Game"), PasteGameProc},
521 {"----", NothingProc},
522 {N_("Load Position"), LoadPositionProc},
523 {N_("Load Next Position"), LoadNextPositionProc},
524 {N_("Load Previous Position"), LoadPrevPositionProc},
525 {N_("Reload Same Position"), ReloadPositionProc},
526 {N_("Save Position"), SavePositionProc},
527 {"----", NothingProc},
528 {N_("Copy Position"), CopyPositionProc},
529 {N_("Paste Position"), PastePositionProc},
530 {"----", NothingProc},
531 {N_("Mail Move"), MailMoveProc},
532 {N_("Reload CMail Message"), ReloadCmailMsgProc},
533 {"----", NothingProc},
534 {N_("Exit"), QuitProc},
538 MenuItem modeMenu[] = {
539 {N_("Machine White"), MachineWhiteProc},
540 {N_("Machine Black"), MachineBlackProc},
541 {N_("Two Machines"), TwoMachinesProc},
542 {N_("Analysis Mode"), AnalyzeModeProc},
543 {N_("Analyze File"), AnalyzeFileProc },
544 {N_("ICS Client"), IcsClientProc},
545 {N_("Edit Game"), EditGameProc},
546 {N_("Edit Position"), EditPositionProc},
547 {N_("Training"), TrainingProc},
548 {"----", NothingProc},
549 {N_("Show Game List"), ShowGameListProc},
550 {N_("Show Move List"), HistoryShowProc},
551 {N_("Edit Tags"), EditTagsProc},
552 {N_("Edit Comment"), EditCommentProc},
553 {N_("ICS Input Box"), IcsInputBoxProc},
554 {N_("Pause"), PauseProc},
558 MenuItem actionMenu[] = {
559 {N_("Accept"), AcceptProc},
560 {N_("Decline"), DeclineProc},
561 {N_("Rematch"), RematchProc},
562 {"----", NothingProc},
563 {N_("Call Flag"), CallFlagProc},
564 {N_("Draw"), DrawProc},
565 {N_("Adjourn"), AdjournProc},
566 {N_("Abort"), AbortProc},
567 {N_("Resign"), ResignProc},
568 {"----", NothingProc},
569 {N_("Stop Observing"), StopObservingProc},
570 {N_("Stop Examining"), StopExaminingProc},
574 MenuItem stepMenu[] = {
575 {N_("Backward"), BackwardProc},
576 {N_("Forward"), ForwardProc},
577 {N_("Back to Start"), ToStartProc},
578 {N_("Forward to End"), ToEndProc},
579 {N_("Revert"), RevertProc},
580 {N_("Truncate Game"), TruncateGameProc},
581 {"----", NothingProc},
582 {N_("Move Now"), MoveNowProc},
583 {N_("Retract Move"), RetractMoveProc},
587 MenuItem optionsMenu[] = {
588 {N_("Always Queen"), AlwaysQueenProc},
589 {N_("Animate Dragging"), AnimateDraggingProc},
590 {N_("Animate Moving"), AnimateMovingProc},
591 {N_("Auto Comment"), AutocommProc},
592 {N_("Auto Flag"), AutoflagProc},
593 {N_("Auto Flip View"), AutoflipProc},
594 {N_("Auto Observe"), AutobsProc},
595 {N_("Auto Raise Board"), AutoraiseProc},
596 {N_("Auto Save"), AutosaveProc},
597 {N_("Blindfold"), BlindfoldProc},
598 {N_("Flash Moves"), FlashMovesProc},
599 {N_("Flip View"), FlipViewProc},
600 {N_("Get Move List"), GetMoveListProc},
602 {N_("Highlight Dragging"), HighlightDraggingProc},
604 {N_("Highlight Last Move"), HighlightLastMoveProc},
605 {N_("Move Sound"), MoveSoundProc},
606 {N_("ICS Alarm"), IcsAlarmProc},
607 {N_("Old Save Style"), OldSaveStyleProc},
608 {N_("Periodic Updates"), PeriodicUpdatesProc},
609 {N_("Ponder Next Move"), PonderNextMoveProc},
610 {N_("Popup Exit Message"), PopupExitMessageProc},
611 {N_("Popup Move Errors"), PopupMoveErrorsProc},
612 {N_("Premove"), PremoveProc},
613 {N_("Quiet Play"), QuietPlayProc},
614 {N_("Show Coords"), ShowCoordsProc},
615 {N_("Show Thinking"), ShowThinkingProc},
616 {N_("Test Legality"), TestLegalityProc},
620 MenuItem helpMenu[] = {
621 {N_("Info XBoard"), InfoProc},
622 {N_("Man XBoard"), ManProc},
623 {"----", NothingProc},
624 {N_("Hint"), HintProc},
625 {N_("Book"), BookProc},
626 {"----", NothingProc},
627 {N_("About XBoard"), AboutProc},
632 {N_("File"), fileMenu},
633 {N_("Mode"), modeMenu},
634 {N_("Action"), actionMenu},
635 {N_("Step"), stepMenu},
636 {N_("Options"), optionsMenu},
637 {N_("Help"), helpMenu},
642 /* Label on pause button */
643 #define PAUSE_BUTTON N_("P")
644 MenuItem buttonBar[] = {
647 {PAUSE_BUTTON, PauseProc},
653 #define PIECE_MENU_SIZE 11
654 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
655 { N_("White"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
656 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
657 { N_("Black"), "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"),
658 N_("Queen"), N_("King"), "----", N_("Empty square"), N_("Clear board") },
660 /* must be in same order as PieceMenuStrings! */
661 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
662 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
663 WhiteRook, WhiteQueen, WhiteKing,
664 (ChessSquare) 0, EmptySquare, ClearBoard },
665 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
666 BlackRook, BlackQueen, BlackKing,
667 (ChessSquare) 0, EmptySquare, ClearBoard },
670 #define DROP_MENU_SIZE 6
671 String dropMenuStrings[DROP_MENU_SIZE] = {
672 "----", N_("Pawn"), N_("Knight"), N_("Bishop"), N_("Rook"), N_("Queen")
674 /* must be in same order as PieceMenuStrings! */
675 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
676 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
677 WhiteRook, WhiteQueen
685 DropMenuEnables dmEnables[] = {
703 { XtNborderWidth, 0 },
704 { XtNdefaultDistance, 0 },
708 { XtNborderWidth, 0 },
709 { XtNresizable, (XtArgVal) True },
713 { XtNborderWidth, 0 },
719 { XtNjustify, (XtArgVal) XtJustifyRight },
720 { XtNlabel, (XtArgVal) "..." },
721 { XtNresizable, (XtArgVal) True },
722 { XtNresize, (XtArgVal) False }
725 Arg messageArgs[] = {
726 { XtNjustify, (XtArgVal) XtJustifyLeft },
727 { XtNlabel, (XtArgVal) "..." },
728 { XtNresizable, (XtArgVal) True },
729 { XtNresize, (XtArgVal) False }
733 { XtNborderWidth, 0 },
734 { XtNjustify, (XtArgVal) XtJustifyLeft }
737 XtResource clientResources[] = {
738 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
739 XtOffset(AppDataPtr, whitePieceColor), XtRString,
741 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
742 XtOffset(AppDataPtr, blackPieceColor), XtRString,
744 { "lightSquareColor", "lightSquareColor", XtRString,
745 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
746 XtRString, LIGHT_SQUARE_COLOR },
747 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
748 XtOffset(AppDataPtr, darkSquareColor), XtRString,
750 { "highlightSquareColor", "highlightSquareColor", XtRString,
751 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
752 XtRString, HIGHLIGHT_SQUARE_COLOR },
753 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
754 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
755 XtRString, PREMOVE_HIGHLIGHT_COLOR },
756 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
757 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
758 (XtPointer) MOVES_PER_SESSION },
759 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
760 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
761 (XtPointer) TIME_INCREMENT },
762 { "initString", "initString", XtRString, sizeof(String),
763 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
764 { "secondInitString", "secondInitString", XtRString, sizeof(String),
765 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
766 { "firstComputerString", "firstComputerString", XtRString,
767 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
769 { "secondComputerString", "secondComputerString", XtRString,
770 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
772 { "firstChessProgram", "firstChessProgram", XtRString,
773 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
774 XtRString, FIRST_CHESS_PROGRAM },
775 { "secondChessProgram", "secondChessProgram", XtRString,
776 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
777 XtRString, SECOND_CHESS_PROGRAM },
778 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
779 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
780 XtRImmediate, (XtPointer) False },
781 { "noChessProgram", "noChessProgram", XtRBoolean,
782 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
783 XtRImmediate, (XtPointer) False },
784 { "firstHost", "firstHost", XtRString, sizeof(String),
785 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
786 { "secondHost", "secondHost", XtRString, sizeof(String),
787 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
788 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
789 XtOffset(AppDataPtr, firstDirectory), XtRString, "" },
790 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
791 XtOffset(AppDataPtr, secondDirectory), XtRString, "" },
792 { "bitmapDirectory", "bitmapDirectory", XtRString,
793 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
795 { "remoteShell", "remoteShell", XtRString, sizeof(String),
796 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
797 { "remoteUser", "remoteUser", XtRString, sizeof(String),
798 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
799 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
800 XtOffset(AppDataPtr, timeDelay), XtRString,
801 (XtPointer) TIME_DELAY_QUOTE },
802 { "timeControl", "timeControl", XtRString, sizeof(String),
803 XtOffset(AppDataPtr, timeControl), XtRString,
804 (XtPointer) TIME_CONTROL },
805 { "internetChessServerMode", "internetChessServerMode",
806 XtRBoolean, sizeof(Boolean),
807 XtOffset(AppDataPtr, icsActive), XtRImmediate,
809 { "internetChessServerHost", "internetChessServerHost",
810 XtRString, sizeof(String),
811 XtOffset(AppDataPtr, icsHost),
812 XtRString, (XtPointer) ICS_HOST },
813 { "internetChessServerPort", "internetChessServerPort",
814 XtRString, sizeof(String),
815 XtOffset(AppDataPtr, icsPort), XtRString,
816 (XtPointer) ICS_PORT },
817 { "internetChessServerCommPort", "internetChessServerCommPort",
818 XtRString, sizeof(String),
819 XtOffset(AppDataPtr, icsCommPort), XtRString,
821 { "internetChessServerLogonScript", "internetChessServerLogonScript",
822 XtRString, sizeof(String),
823 XtOffset(AppDataPtr, icsLogon), XtRString,
825 { "internetChessServerHelper", "internetChessServerHelper",
826 XtRString, sizeof(String),
827 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
828 { "internetChessServerInputBox", "internetChessServerInputBox",
829 XtRBoolean, sizeof(Boolean),
830 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
832 { "icsAlarm", "icsAlarm",
833 XtRBoolean, sizeof(Boolean),
834 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
836 { "icsAlarmTime", "icsAlarmTime",
838 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
840 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
841 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
843 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
844 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
845 { "gateway", "gateway", XtRString, sizeof(String),
846 XtOffset(AppDataPtr, gateway), XtRString, "" },
847 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
848 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
849 { "loadGameIndex", "loadGameIndex",
851 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
853 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
854 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
855 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
856 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
857 XtRImmediate, (XtPointer) True },
858 { "autoSaveGames", "autoSaveGames", XtRBoolean,
859 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
860 XtRImmediate, (XtPointer) False },
861 { "blindfold", "blindfold", XtRBoolean,
862 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
863 XtRImmediate, (XtPointer) False },
864 { "loadPositionFile", "loadPositionFile", XtRString,
865 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
867 { "loadPositionIndex", "loadPositionIndex",
869 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
871 { "savePositionFile", "savePositionFile", XtRString,
872 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
874 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
875 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
876 { "matchGames", "matchGames", XtRInt, sizeof(int),
877 XtOffset(AppDataPtr, matchGames), XtRImmediate,
879 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
880 XtOffset(AppDataPtr, monoMode), XtRImmediate,
882 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
883 XtOffset(AppDataPtr, debugMode), XtRImmediate,
885 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
886 XtOffset(AppDataPtr, clockMode), XtRImmediate,
888 { "boardSize", "boardSize", XtRString, sizeof(String),
889 XtOffset(AppDataPtr, boardSize), XtRString, "" },
890 { "searchTime", "searchTime", XtRString, sizeof(String),
891 XtOffset(AppDataPtr, searchTime), XtRString,
893 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
894 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
896 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
897 XtOffset(AppDataPtr, showCoords), XtRImmediate,
899 { "showJail", "showJail", XtRInt, sizeof(int),
900 XtOffset(AppDataPtr, showJail), XtRImmediate,
902 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
903 XtOffset(AppDataPtr, showThinking), XtRImmediate,
905 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
906 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
908 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
909 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
911 { "clockFont", "clockFont", XtRString, sizeof(String),
912 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
913 { "coordFont", "coordFont", XtRString, sizeof(String),
914 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
915 { "font", "font", XtRString, sizeof(String),
916 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
917 { "ringBellAfterMoves", "ringBellAfterMoves",
918 XtRBoolean, sizeof(Boolean),
919 XtOffset(AppDataPtr, ringBellAfterMoves),
920 XtRImmediate, (XtPointer) False },
921 { "autoCallFlag", "autoCallFlag", XtRBoolean,
922 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
923 XtRImmediate, (XtPointer) False },
924 { "autoFlipView", "autoFlipView", XtRBoolean,
925 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
926 XtRImmediate, (XtPointer) True },
927 { "autoObserve", "autoObserve", XtRBoolean,
928 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
929 XtRImmediate, (XtPointer) False },
930 { "autoComment", "autoComment", XtRBoolean,
931 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
932 XtRImmediate, (XtPointer) False },
933 { "getMoveList", "getMoveList", XtRBoolean,
934 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
935 XtRImmediate, (XtPointer) True },
937 { "highlightDragging", "highlightDragging", XtRBoolean,
938 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
939 XtRImmediate, (XtPointer) False },
941 { "highlightLastMove", "highlightLastMove", XtRBoolean,
942 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
943 XtRImmediate, (XtPointer) False },
944 { "premove", "premove", XtRBoolean,
945 sizeof(Boolean), XtOffset(AppDataPtr, premove),
946 XtRImmediate, (XtPointer) True },
947 { "testLegality", "testLegality", XtRBoolean,
948 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
949 XtRImmediate, (XtPointer) True },
950 { "flipView", "flipView", XtRBoolean,
951 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
952 XtRImmediate, (XtPointer) False },
953 { "cmail", "cmailGameName", XtRString, sizeof(String),
954 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
955 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
956 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
957 XtRImmediate, (XtPointer) False },
958 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
959 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
960 XtRImmediate, (XtPointer) False },
961 { "quietPlay", "quietPlay", XtRBoolean,
962 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
963 XtRImmediate, (XtPointer) False },
964 { "titleInWindow", "titleInWindow", XtRBoolean,
965 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
966 XtRImmediate, (XtPointer) False },
967 { "localLineEditing", "localLineEditing", XtRBoolean,
968 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
969 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
971 { "zippyTalk", "zippyTalk", XtRBoolean,
972 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
973 XtRImmediate, (XtPointer) ZIPPY_TALK },
974 { "zippyPlay", "zippyPlay", XtRBoolean,
975 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
976 XtRImmediate, (XtPointer) ZIPPY_PLAY },
977 { "zippyLines", "zippyLines", XtRString, sizeof(String),
978 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
979 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
980 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
981 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
982 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
983 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
984 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
985 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
986 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
987 ZIPPY_WRONG_PASSWORD },
988 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
989 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
990 { "zippyUseI", "zippyUseI", XtRBoolean,
991 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
992 XtRImmediate, (XtPointer) ZIPPY_USE_I },
993 { "zippyBughouse", "zippyBughouse", XtRInt,
994 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
995 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
996 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
997 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
998 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
999 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
1000 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
1001 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
1002 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
1003 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
1004 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
1005 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
1006 { "zippyAbort", "zippyAbort", XtRBoolean,
1007 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
1008 XtRImmediate, (XtPointer) ZIPPY_ABORT },
1009 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
1010 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
1011 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
1012 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
1013 (XtPointer) ZIPPY_MAX_GAMES },
1014 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
1015 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
1016 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
1018 { "flashCount", "flashCount", XtRInt, sizeof(int),
1019 XtOffset(AppDataPtr, flashCount), XtRImmediate,
1020 (XtPointer) FLASH_COUNT },
1021 { "flashRate", "flashRate", XtRInt, sizeof(int),
1022 XtOffset(AppDataPtr, flashRate), XtRImmediate,
1023 (XtPointer) FLASH_RATE },
1024 { "pixmapDirectory", "pixmapDirectory", XtRString,
1025 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
1027 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
1028 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
1029 (XtPointer) MS_LOGIN_DELAY },
1030 { "colorizeMessages", "colorizeMessages", XtRBoolean,
1031 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
1032 XtRImmediate, (XtPointer) False },
1033 { "colorShout", "colorShout", XtRString,
1034 sizeof(String), XtOffset(AppDataPtr, colorShout),
1035 XtRString, COLOR_SHOUT },
1036 { "colorSShout", "colorSShout", XtRString,
1037 sizeof(String), XtOffset(AppDataPtr, colorSShout),
1038 XtRString, COLOR_SSHOUT },
1039 { "colorChannel1", "colorChannel1", XtRString,
1040 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
1041 XtRString, COLOR_CHANNEL1 },
1042 { "colorChannel", "colorChannel", XtRString,
1043 sizeof(String), XtOffset(AppDataPtr, colorChannel),
1044 XtRString, COLOR_CHANNEL },
1045 { "colorKibitz", "colorKibitz", XtRString,
1046 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
1047 XtRString, COLOR_KIBITZ },
1048 { "colorTell", "colorTell", XtRString,
1049 sizeof(String), XtOffset(AppDataPtr, colorTell),
1050 XtRString, COLOR_TELL },
1051 { "colorChallenge", "colorChallenge", XtRString,
1052 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
1053 XtRString, COLOR_CHALLENGE },
1054 { "colorRequest", "colorRequest", XtRString,
1055 sizeof(String), XtOffset(AppDataPtr, colorRequest),
1056 XtRString, COLOR_REQUEST },
1057 { "colorSeek", "colorSeek", XtRString,
1058 sizeof(String), XtOffset(AppDataPtr, colorSeek),
1059 XtRString, COLOR_SEEK },
1060 { "colorNormal", "colorNormal", XtRString,
1061 sizeof(String), XtOffset(AppDataPtr, colorNormal),
1062 XtRString, COLOR_NORMAL },
1063 { "soundProgram", "soundProgram", XtRString,
1064 sizeof(String), XtOffset(AppDataPtr, soundProgram),
1065 XtRString, "play" },
1066 { "soundShout", "soundShout", XtRString,
1067 sizeof(String), XtOffset(AppDataPtr, soundShout),
1069 { "soundSShout", "soundSShout", XtRString,
1070 sizeof(String), XtOffset(AppDataPtr, soundSShout),
1072 { "soundChannel1", "soundChannel1", XtRString,
1073 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
1075 { "soundChannel", "soundChannel", XtRString,
1076 sizeof(String), XtOffset(AppDataPtr, soundChannel),
1078 { "soundKibitz", "soundKibitz", XtRString,
1079 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
1081 { "soundTell", "soundTell", XtRString,
1082 sizeof(String), XtOffset(AppDataPtr, soundTell),
1084 { "soundChallenge", "soundChallenge", XtRString,
1085 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
1087 { "soundRequest", "soundRequest", XtRString,
1088 sizeof(String), XtOffset(AppDataPtr, soundRequest),
1090 { "soundSeek", "soundSeek", XtRString,
1091 sizeof(String), XtOffset(AppDataPtr, soundSeek),
1093 { "soundMove", "soundMove", XtRString,
1094 sizeof(String), XtOffset(AppDataPtr, soundMove),
1096 { "soundIcsWin", "soundIcsWin", XtRString,
1097 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
1099 { "soundIcsLoss", "soundIcsLoss", XtRString,
1100 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
1102 { "soundIcsDraw", "soundIcsDraw", XtRString,
1103 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
1105 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
1106 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
1108 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
1109 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
1111 { "reuseFirst", "reuseFirst", XtRBoolean,
1112 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
1113 XtRImmediate, (XtPointer) True },
1114 { "reuseSecond", "reuseSecond", XtRBoolean,
1115 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
1116 XtRImmediate, (XtPointer) True },
1117 { "animateDragging", "animateDragging", XtRBoolean,
1118 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
1119 XtRImmediate, (XtPointer) True },
1120 { "animateMoving", "animateMoving", XtRBoolean,
1121 sizeof(Boolean), XtOffset(AppDataPtr, animate),
1122 XtRImmediate, (XtPointer) True },
1123 { "animateSpeed", "animateSpeed", XtRInt,
1124 sizeof(int), XtOffset(AppDataPtr, animSpeed),
1125 XtRImmediate, (XtPointer)10 },
1126 { "popupExitMessage", "popupExitMessage", XtRBoolean,
1127 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
1128 XtRImmediate, (XtPointer) True },
1129 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
1130 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
1131 XtRImmediate, (XtPointer) False },
1132 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
1133 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
1134 XtRImmediate, (XtPointer)4 },
1135 { "initialMode", "initialMode", XtRString,
1136 sizeof(String), XtOffset(AppDataPtr, initialMode),
1137 XtRImmediate, (XtPointer) "" },
1138 { "variant", "variant", XtRString,
1139 sizeof(String), XtOffset(AppDataPtr, variant),
1140 XtRImmediate, (XtPointer) "normal" },
1141 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
1142 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
1143 XtRImmediate, (XtPointer)PROTOVER },
1144 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
1145 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
1146 XtRImmediate, (XtPointer)PROTOVER },
1147 { "showButtonBar", "showButtonBar", XtRBoolean,
1148 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
1149 XtRImmediate, (XtPointer) True },
1150 /* icsEngineAnalyze */
1151 {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean,
1152 sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
1153 XtRImmediate, (XtPointer) False },
1156 XrmOptionDescRec shellOptions[] = {
1157 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1158 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1159 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1160 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1161 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1162 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1163 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1164 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1165 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1166 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1167 { "-initString", "initString", XrmoptionSepArg, NULL },
1168 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1169 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1170 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1171 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1172 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1173 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1174 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1175 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1176 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1177 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1178 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1179 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1180 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1181 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1182 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1183 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1184 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1185 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1186 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1187 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1188 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1189 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1190 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1191 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1192 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1193 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1194 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1195 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1196 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1197 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1198 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1199 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1200 { "-internetChessServerMode", "internetChessServerMode",
1201 XrmoptionSepArg, NULL },
1202 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1203 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1204 { "-internetChessServerHost", "internetChessServerHost",
1205 XrmoptionSepArg, NULL },
1206 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1207 { "-internetChessServerPort", "internetChessServerPort",
1208 XrmoptionSepArg, NULL },
1209 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1210 { "-internetChessServerCommPort", "internetChessServerCommPort",
1211 XrmoptionSepArg, NULL },
1212 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1213 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1214 XrmoptionSepArg, NULL },
1215 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1216 { "-internetChessServerHelper", "internetChessServerHelper",
1217 XrmoptionSepArg, NULL },
1218 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1219 { "-internetChessServerInputBox", "internetChessServerInputBox",
1220 XrmoptionSepArg, NULL },
1221 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1222 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1223 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1224 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1225 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1226 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1227 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1228 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1229 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1230 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1231 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1232 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1233 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1234 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1235 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1236 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1237 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1238 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1239 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1240 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1241 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1242 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1243 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1244 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1245 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1246 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1247 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1248 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1249 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1250 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1251 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1252 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1253 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1254 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1255 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1256 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1257 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1258 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1259 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1260 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1261 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1262 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1263 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1264 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1265 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1266 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1267 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1268 { "-size", "boardSize", XrmoptionSepArg, NULL },
1269 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1270 { "-st", "searchTime", XrmoptionSepArg, NULL },
1271 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1272 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1273 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1274 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1275 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1277 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1278 { "-jail", "showJail", XrmoptionNoArg, "1" },
1279 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1280 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1282 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1283 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1284 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1285 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1286 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1287 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1288 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1289 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1290 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1291 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1292 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1293 { "-font", "font", XrmoptionSepArg, NULL },
1294 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1295 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1296 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1297 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1298 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1299 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1300 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1301 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1302 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1303 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1304 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1305 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1306 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1307 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1308 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1309 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1310 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1311 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1312 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1313 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1315 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1316 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1317 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1319 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1320 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1321 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1322 { "-premove", "premove", XrmoptionSepArg, NULL },
1323 { "-pre", "premove", XrmoptionNoArg, "True" },
1324 { "-xpre", "premove", XrmoptionNoArg, "False" },
1325 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1326 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1327 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1328 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1329 { "-flip", "flipView", XrmoptionNoArg, "True" },
1330 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1331 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1332 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1333 XrmoptionSepArg, NULL },
1334 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1335 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1336 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1337 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1338 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1339 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1340 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1341 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1342 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1343 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1344 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1346 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1347 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1348 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1349 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1350 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1351 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1352 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1353 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1354 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1355 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1356 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1357 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1358 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1359 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1360 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1361 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1362 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1363 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1364 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1365 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1366 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1367 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1368 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1369 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1370 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1371 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1372 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1373 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1374 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1375 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1377 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1378 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1379 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1380 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1381 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1382 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1383 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1384 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1385 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1386 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1387 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1388 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1389 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1390 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1391 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1392 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1393 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1394 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1395 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1396 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1397 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1398 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1399 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1400 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1401 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1402 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1403 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1404 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1405 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1406 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1407 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1408 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1409 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1410 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1411 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1412 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1413 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1414 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1415 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1416 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1417 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1418 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1419 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1420 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1421 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1422 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1423 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1424 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1425 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1426 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1427 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1428 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1429 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1430 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1431 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1432 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1433 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1434 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1435 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1436 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1437 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1438 { "-variant", "variant", XrmoptionSepArg, NULL },
1439 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1440 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1441 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1442 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1443 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1447 XtActionsRec boardActions[] = {
1448 { "DrawPosition", DrawPositionProc },
1449 { "HandleUserMove", HandleUserMove },
1450 { "AnimateUserMove", AnimateUserMove },
1451 { "FileNameAction", FileNameAction },
1452 { "AskQuestionProc", AskQuestionProc },
1453 { "AskQuestionReplyAction", AskQuestionReplyAction },
1454 { "PieceMenuPopup", PieceMenuPopup },
1455 { "WhiteClock", WhiteClock },
1456 { "BlackClock", BlackClock },
1457 { "Iconify", Iconify },
1458 { "ResetProc", ResetProc },
1459 { "LoadGameProc", LoadGameProc },
1460 { "LoadNextGameProc", LoadNextGameProc },
1461 { "LoadPrevGameProc", LoadPrevGameProc },
1462 { "LoadSelectedProc", LoadSelectedProc },
1463 { "ReloadGameProc", ReloadGameProc },
1464 { "LoadPositionProc", LoadPositionProc },
1465 { "LoadNextPositionProc", LoadNextPositionProc },
1466 { "LoadPrevPositionProc", LoadPrevPositionProc },
1467 { "ReloadPositionProc", ReloadPositionProc },
1468 { "CopyPositionProc", CopyPositionProc },
1469 { "PastePositionProc", PastePositionProc },
1470 { "CopyGameProc", CopyGameProc },
1471 { "PasteGameProc", PasteGameProc },
1472 { "SaveGameProc", SaveGameProc },
1473 { "SavePositionProc", SavePositionProc },
1474 { "MailMoveProc", MailMoveProc },
1475 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1476 { "QuitProc", QuitProc },
1477 { "MachineWhiteProc", MachineWhiteProc },
1478 { "MachineBlackProc", MachineBlackProc },
1479 { "AnalysisModeProc", AnalyzeModeProc },
1480 { "AnalyzeFileProc", AnalyzeFileProc },
1481 { "TwoMachinesProc", TwoMachinesProc },
1482 { "IcsClientProc", IcsClientProc },
1483 { "EditGameProc", EditGameProc },
1484 { "EditPositionProc", EditPositionProc },
1485 { "TrainingProc", EditPositionProc },
1486 { "ShowGameListProc", ShowGameListProc },
1487 { "ShowMoveListProc", HistoryShowProc},
1488 { "EditTagsProc", EditCommentProc },
1489 { "EditCommentProc", EditCommentProc },
1490 { "IcsAlarmProc", IcsAlarmProc },
1491 { "IcsInputBoxProc", IcsInputBoxProc },
1492 { "PauseProc", PauseProc },
1493 { "AcceptProc", AcceptProc },
1494 { "DeclineProc", DeclineProc },
1495 { "RematchProc", RematchProc },
1496 { "CallFlagProc", CallFlagProc },
1497 { "DrawProc", DrawProc },
1498 { "AdjournProc", AdjournProc },
1499 { "AbortProc", AbortProc },
1500 { "ResignProc", ResignProc },
1501 { "EnterKeyProc", EnterKeyProc },
1502 { "StopObservingProc", StopObservingProc },
1503 { "StopExaminingProc", StopExaminingProc },
1504 { "BackwardProc", BackwardProc },
1505 { "ForwardProc", ForwardProc },
1506 { "ToStartProc", ToStartProc },
1507 { "ToEndProc", ToEndProc },
1508 { "RevertProc", RevertProc },
1509 { "TruncateGameProc", TruncateGameProc },
1510 { "MoveNowProc", MoveNowProc },
1511 { "RetractMoveProc", RetractMoveProc },
1512 { "AlwaysQueenProc", AlwaysQueenProc },
1513 { "AnimateDraggingProc", AnimateDraggingProc },
1514 { "AnimateMovingProc", AnimateMovingProc },
1515 { "AutoflagProc", AutoflagProc },
1516 { "AutoflipProc", AutoflipProc },
1517 { "AutobsProc", AutobsProc },
1518 { "AutoraiseProc", AutoraiseProc },
1519 { "AutosaveProc", AutosaveProc },
1520 { "BlindfoldProc", BlindfoldProc },
1521 { "FlashMovesProc", FlashMovesProc },
1522 { "FlipViewProc", FlipViewProc },
1523 { "GetMoveListProc", GetMoveListProc },
1525 { "HighlightDraggingProc", HighlightDraggingProc },
1527 { "HighlightLastMoveProc", HighlightLastMoveProc },
1528 { "IcsAlarmProc", IcsAlarmProc },
1529 { "MoveSoundProc", MoveSoundProc },
1530 { "OldSaveStyleProc", OldSaveStyleProc },
1531 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1532 { "PonderNextMoveProc", PonderNextMoveProc },
1533 { "PopupExitMessageProc", PopupExitMessageProc },
1534 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1535 { "PremoveProc", PremoveProc },
1536 { "QuietPlayProc", QuietPlayProc },
1537 { "ShowCoordsProc", ShowCoordsProc },
1538 { "ShowThinkingProc", ShowThinkingProc },
1539 { "TestLegalityProc", TestLegalityProc },
1540 { "InfoProc", InfoProc },
1541 { "ManProc", ManProc },
1542 { "HintProc", HintProc },
1543 { "BookProc", BookProc },
1544 { "AboutGameProc", AboutGameProc },
1545 { "AboutProc", AboutProc },
1546 { "DebugProc", DebugProc },
1547 { "NothingProc", NothingProc },
1548 { "CommentPopDown", (XtActionProc) CommentPopDown },
1549 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1550 { "TagsPopDown", (XtActionProc) TagsPopDown },
1551 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1552 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1553 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1554 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1555 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1556 { "GameListPopDown", (XtActionProc) GameListPopDown },
1557 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1558 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1561 char globalTranslations[] =
1562 ":<Key>R: ResignProc() \n \
1563 :<Key>r: ResetProc() \n \
1564 :<Key>g: LoadGameProc() \n \
1565 :<Key>N: LoadNextGameProc() \n \
1566 :<Key>P: LoadPrevGameProc() \n \
1567 :<Key>Q: QuitProc() \n \
1568 :<Key>F: ToEndProc() \n \
1569 :<Key>f: ForwardProc() \n \
1570 :<Key>B: ToStartProc() \n \
1571 :<Key>b: BackwardProc() \n \
1572 :<Key>p: PauseProc() \n \
1573 :<Key>d: DrawProc() \n \
1574 :<Key>t: CallFlagProc() \n \
1575 :<Key>i: Iconify() \n \
1576 :<Key>c: Iconify() \n \
1577 :<Key>v: FlipViewProc() \n \
1578 <KeyDown>Control_L: BackwardProc() \n \
1579 <KeyUp>Control_L: ForwardProc() \n \
1580 <KeyDown>Control_R: BackwardProc() \n \
1581 <KeyUp>Control_R: ForwardProc() \n \
1582 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1583 \"Send to chess program:\",,1) \n \
1584 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1585 \"Send to second chess program:\",,2) \n";
1587 char boardTranslations[] =
1588 "<Btn1Down>: HandleUserMove() \n \
1589 <Btn1Up>: HandleUserMove() \n \
1590 <Btn1Motion>: AnimateUserMove() \n \
1591 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1592 PieceMenuPopup(menuB) \n \
1593 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1594 PieceMenuPopup(menuW) \n \
1595 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1596 PieceMenuPopup(menuW) \n \
1597 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1598 PieceMenuPopup(menuB) \n";
1600 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1601 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1603 char ICSInputTranslations[] =
1604 "<Key>Return: EnterKeyProc() \n";
1606 String xboardResources[] = {
1607 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1608 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1609 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1614 /* Max possible square size */
1615 #define MAXSQSIZE 256
1617 static int xpm_avail[MAXSQSIZE];
1619 #ifdef HAVE_DIR_STRUCT
1621 /* Extract piece size from filename */
1623 xpm_getsize(name, len, ext)
1634 if ((p=strchr(name, '.')) == NULL ||
1635 StrCaseCmp(p+1, ext) != 0)
1641 while (*p && isdigit(*p))
1648 /* Setup xpm_avail */
1650 xpm_getavail(dirname, ext)
1658 for (i=0; i<MAXSQSIZE; ++i)
1661 if (appData.debugMode)
1662 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1664 dir = opendir(dirname);
1667 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1668 programName, dirname);
1672 while ((ent=readdir(dir)) != NULL) {
1673 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1674 if (i > 0 && i < MAXSQSIZE)
1684 xpm_print_avail(fp, ext)
1690 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1691 for (i=1; i<MAXSQSIZE; ++i) {
1697 /* Return XPM piecesize closest to size */
1699 xpm_closest_to(dirname, size, ext)
1705 int sm_diff = MAXSQSIZE;
1709 xpm_getavail(dirname, ext);
1711 if (appData.debugMode)
1712 xpm_print_avail(stderr, ext);
1714 for (i=1; i<MAXSQSIZE; ++i) {
1717 diff = (diff<0) ? -diff : diff;
1718 if (diff < sm_diff) {
1726 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1732 #else /* !HAVE_DIR_STRUCT */
1733 /* If we are on a system without a DIR struct, we can't
1734 read the directory, so we can't collect a list of
1735 filenames, etc., so we can't do any size-fitting. */
1737 xpm_closest_to(dirname, size, ext)
1742 fprintf(stderr, _("\
1743 Warning: No DIR structure found on this system --\n\
1744 Unable to autosize for XPM/XIM pieces.\n\
1745 Please report this error to frankm@hiwaay.net.\n\
1746 Include system type & operating system in message.\n"));
1749 #endif /* HAVE_DIR_STRUCT */
1751 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1752 "magenta", "cyan", "white" };
1756 TextColors textColors[(int)NColorClasses];
1758 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1760 parse_color(str, which)
1764 char *p, buf[100], *d;
1767 if (strlen(str) > 99) /* watch bounds on buf */
1772 for (i=0; i<which; ++i) {
1779 /* Could be looking at something like:
1781 .. in which case we want to stop on a comma also */
1782 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1786 return -1; /* Use default for empty field */
1789 if (which == 2 || isdigit(*p))
1792 while (*p && isalpha(*p))
1797 for (i=0; i<8; ++i) {
1798 if (!StrCaseCmp(buf, cnames[i]))
1799 return which? (i+40) : (i+30);
1801 if (!StrCaseCmp(buf, "default")) return -1;
1803 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1808 parse_cpair(cc, str)
1812 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1813 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1818 /* bg and attr are optional */
1819 textColors[(int)cc].bg = parse_color(str, 1);
1820 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1821 textColors[(int)cc].attr = 0;
1827 /* Arrange to catch delete-window events */
1828 Atom wm_delete_window;
1830 CatchDeleteWindow(Widget w, String procname)
1833 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1834 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
1835 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1842 XtSetArg(args[0], XtNiconic, False);
1843 XtSetValues(shellWidget, args, 1);
1845 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1853 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1854 XSetWindowAttributes window_attributes;
1856 Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
1857 XrmValue vFrom, vTo;
1858 XtGeometryResult gres;
1861 int forceMono = False;
1863 setbuf(stdout, NULL);
1864 setbuf(stderr, NULL);
1867 programName = strrchr(argv[0], '/');
1868 if (programName == NULL)
1869 programName = argv[0];
1874 XtSetLanguageProc(NULL, NULL, NULL);
1875 bindtextdomain(PRODUCT, LOCALEDIR);
1876 textdomain(PRODUCT);
1880 XtAppInitialize(&appContext, "XBoard", shellOptions,
1881 XtNumber(shellOptions),
1882 &argc, argv, xboardResources, NULL, 0);
1884 fprintf(stderr, _("%s: unrecognized argument %s\n"),
1885 programName, argv[1]);
1889 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1892 if (chdir(chessDir) != 0) {
1893 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1900 if (p == NULL) p = "/tmp";
1901 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1902 gameCopyFilename = (char*) malloc(i);
1903 gamePasteFilename = (char*) malloc(i);
1904 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1905 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1907 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1908 clientResources, XtNumber(clientResources),
1912 /* This feature does not work; animation needs a rewrite */
1913 appData.highlightDragging = FALSE;
1917 xDisplay = XtDisplay(shellWidget);
1918 xScreen = DefaultScreen(xDisplay);
1919 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1922 * Determine boardSize
1924 if (isdigit(appData.boardSize[0])) {
1925 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1926 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1927 &fontPxlSize, &smallLayout, &tinyLayout);
1929 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1930 programName, appData.boardSize);
1934 /* Find some defaults; use the nearest known size */
1935 SizeDefaults *szd, *nearest;
1936 int distance = 99999;
1937 nearest = szd = sizeDefaults;
1938 while (szd->name != NULL) {
1939 if (abs(szd->squareSize - squareSize) < distance) {
1941 distance = abs(szd->squareSize - squareSize);
1942 if (distance == 0) break;
1946 if (i < 2) lineGap = nearest->lineGap;
1947 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1948 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1949 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1950 if (i < 6) smallLayout = nearest->smallLayout;
1951 if (i < 7) tinyLayout = nearest->tinyLayout;
1954 SizeDefaults *szd = sizeDefaults;
1955 if (*appData.boardSize == NULLCHAR) {
1956 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1957 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1960 if (szd->name == NULL) szd--;
1962 while (szd->name != NULL &&
1963 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1964 if (szd->name == NULL) {
1965 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1966 programName, appData.boardSize);
1970 squareSize = szd->squareSize;
1971 lineGap = szd->lineGap;
1972 clockFontPxlSize = szd->clockFontPxlSize;
1973 coordFontPxlSize = szd->coordFontPxlSize;
1974 fontPxlSize = szd->fontPxlSize;
1975 smallLayout = szd->smallLayout;
1976 tinyLayout = szd->tinyLayout;
1979 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1980 if (strlen(appData.pixmapDirectory) > 0) {
1981 p = ExpandPathName(appData.pixmapDirectory);
1983 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1984 appData.pixmapDirectory);
1987 if (appData.debugMode) {
1988 fprintf(stderr, _("\
1989 XBoard square size (hint): %d\n\
1990 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1992 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1993 if (appData.debugMode) {
1994 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1998 boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
1999 if (appData.showJail == 1) {
2000 /* Jail on top and bottom */
2001 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2002 XtSetArg(boardArgs[2], XtNheight,
2003 boardWidth + 2*(lineGap + squareSize));
2004 } else if (appData.showJail == 2) {
2006 XtSetArg(boardArgs[1], XtNwidth,
2007 boardWidth + 2*(lineGap + squareSize));
2008 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2011 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2012 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2016 * Determine what fonts to use.
2018 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2019 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2020 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2021 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2022 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2023 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2024 appData.font = FindFont(appData.font, fontPxlSize);
2026 xdb = XtDatabase(xDisplay);
2027 XrmPutStringResource(&xdb, "*font", appData.font);
2030 * Detect if there are not enough colors available and adapt.
2032 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2033 appData.monoMode = True;
2036 if (!appData.monoMode) {
2037 vFrom.addr = (caddr_t) appData.lightSquareColor;
2038 vFrom.size = strlen(appData.lightSquareColor);
2039 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2040 if (vTo.addr == NULL) {
2041 appData.monoMode = True;
2044 lightSquareColor = *(Pixel *) vTo.addr;
2047 if (!appData.monoMode) {
2048 vFrom.addr = (caddr_t) appData.darkSquareColor;
2049 vFrom.size = strlen(appData.darkSquareColor);
2050 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2051 if (vTo.addr == NULL) {
2052 appData.monoMode = True;
2055 darkSquareColor = *(Pixel *) vTo.addr;
2058 if (!appData.monoMode) {
2059 vFrom.addr = (caddr_t) appData.whitePieceColor;
2060 vFrom.size = strlen(appData.whitePieceColor);
2061 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2062 if (vTo.addr == NULL) {
2063 appData.monoMode = True;
2066 whitePieceColor = *(Pixel *) vTo.addr;
2069 if (!appData.monoMode) {
2070 vFrom.addr = (caddr_t) appData.blackPieceColor;
2071 vFrom.size = strlen(appData.blackPieceColor);
2072 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2073 if (vTo.addr == NULL) {
2074 appData.monoMode = True;
2077 blackPieceColor = *(Pixel *) vTo.addr;
2081 if (!appData.monoMode) {
2082 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2083 vFrom.size = strlen(appData.highlightSquareColor);
2084 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2085 if (vTo.addr == NULL) {
2086 appData.monoMode = True;
2089 highlightSquareColor = *(Pixel *) vTo.addr;
2093 if (!appData.monoMode) {
2094 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2095 vFrom.size = strlen(appData.premoveHighlightColor);
2096 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2097 if (vTo.addr == NULL) {
2098 appData.monoMode = True;
2101 premoveHighlightColor = *(Pixel *) vTo.addr;
2106 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2110 if (appData.monoMode && appData.debugMode) {
2111 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2112 (unsigned long) XWhitePixel(xDisplay, xScreen),
2113 (unsigned long) XBlackPixel(xDisplay, xScreen));
2116 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2117 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2118 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2119 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2120 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2121 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2122 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2123 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2124 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2125 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2127 if (appData.colorize) {
2129 _("%s: can't parse color names; disabling colorization\n"),
2132 appData.colorize = FALSE;
2134 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2135 textColors[ColorNone].attr = 0;
2137 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2143 layoutName = "tinyLayout";
2144 } else if (smallLayout) {
2145 layoutName = "smallLayout";
2147 layoutName = "normalLayout";
2149 /* Outer layoutWidget is there only to provide a name for use in
2150 resources that depend on the layout style */
2152 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2153 layoutArgs, XtNumber(layoutArgs));
2155 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2156 formArgs, XtNumber(formArgs));
2157 XtSetArg(args[0], XtNdefaultDistance, &sep);
2158 XtGetValues(formWidget, args, 1);
2161 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2163 widgetList[j++] = whiteTimerWidget =
2164 XtCreateWidget("whiteTime", labelWidgetClass,
2165 formWidget, timerArgs, XtNumber(timerArgs));
2166 XtSetArg(args[0], XtNfont, clockFontStruct);
2167 XtSetValues(whiteTimerWidget, args, 1);
2169 widgetList[j++] = blackTimerWidget =
2170 XtCreateWidget("blackTime", labelWidgetClass,
2171 formWidget, timerArgs, XtNumber(timerArgs));
2172 XtSetArg(args[0], XtNfont, clockFontStruct);
2173 XtSetValues(blackTimerWidget, args, 1);
2175 if (appData.titleInWindow) {
2176 widgetList[j++] = titleWidget =
2177 XtCreateWidget("title", labelWidgetClass, formWidget,
2178 titleArgs, XtNumber(titleArgs));
2181 if (appData.showButtonBar) {
2182 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2185 widgetList[j++] = messageWidget =
2186 XtCreateWidget("message", labelWidgetClass, formWidget,
2187 messageArgs, XtNumber(messageArgs));
2189 widgetList[j++] = boardWidget =
2190 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2191 XtNumber(boardArgs));
2193 XtManageChildren(widgetList, j);
2195 timerWidth = (boardWidth - sep) / 2;
2196 XtSetArg(args[0], XtNwidth, timerWidth);
2197 XtSetValues(whiteTimerWidget, args, 1);
2198 XtSetValues(blackTimerWidget, args, 1);
2200 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2201 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2202 XtGetValues(whiteTimerWidget, args, 2);
2204 if (appData.showButtonBar) {
2205 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2206 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2207 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2211 * formWidget uses these constraints but they are stored
2215 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2216 XtSetValues(menuBarWidget, args, i);
2217 if (appData.titleInWindow) {
2220 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2221 XtSetValues(whiteTimerWidget, args, i);
2223 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2224 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2225 XtSetValues(blackTimerWidget, args, i);
2227 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2228 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2229 XtSetValues(titleWidget, args, i);
2231 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2232 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2233 XtSetValues(messageWidget, args, i);
2234 if (appData.showButtonBar) {
2236 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2237 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2238 XtSetValues(buttonBarWidget, args, i);
2242 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2243 XtSetValues(whiteTimerWidget, args, i);
2245 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2246 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2247 XtSetValues(blackTimerWidget, args, i);
2249 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2250 XtSetValues(titleWidget, args, i);
2252 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2253 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2254 XtSetValues(messageWidget, args, i);
2255 if (appData.showButtonBar) {
2257 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2258 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2259 XtSetValues(buttonBarWidget, args, i);
2264 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2265 XtSetValues(whiteTimerWidget, args, i);
2267 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2268 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2269 XtSetValues(blackTimerWidget, args, i);
2271 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2272 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2273 XtSetValues(messageWidget, args, i);
2274 if (appData.showButtonBar) {
2276 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2277 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2278 XtSetValues(buttonBarWidget, args, i);
2282 XtSetArg(args[0], XtNfromVert, messageWidget);
2283 XtSetValues(boardWidget, args, 1);
2285 XtRealizeWidget(shellWidget);
2288 * Correct the width of the message and title widgets.
2289 * It is not known why some systems need the extra fudge term.
2290 * The value "2" is probably larger than needed.
2292 XawFormDoLayout(formWidget, False);
2293 #define WIDTH_FUDGE 2
2295 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2296 XtSetArg(args[i], XtNheight, &h); i++;
2297 XtGetValues(messageWidget, args, i);
2298 if (appData.showButtonBar) {
2300 XtSetArg(args[i], XtNwidth, &w); i++;
2301 XtGetValues(buttonBarWidget, args, i);
2302 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2304 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2307 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2308 if (gres != XtGeometryYes && appData.debugMode) {
2309 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2310 programName, gres, w, h, wr, hr);
2313 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2314 /* The size used for the child widget in layout lags one resize behind
2315 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2317 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2318 if (gres != XtGeometryYes && appData.debugMode) {
2319 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2320 programName, gres, w, h, wr, hr);
2324 if (appData.titleInWindow) {
2326 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2327 XtSetArg(args[i], XtNheight, &h); i++;
2328 XtGetValues(titleWidget, args, i);
2330 w = boardWidth - 2*bor;
2332 XtSetArg(args[0], XtNwidth, &w);
2333 XtGetValues(menuBarWidget, args, 1);
2334 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2337 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2338 if (gres != XtGeometryYes && appData.debugMode) {
2340 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2341 programName, gres, w, h, wr, hr);
2344 XawFormDoLayout(formWidget, True);
2346 xBoardWindow = XtWindow(boardWidget);
2349 * Create X checkmark bitmap and initialize option menu checks.
2351 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2352 checkmark_bits, checkmark_width, checkmark_height);
2353 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2354 if (appData.alwaysPromoteToQueen) {
2355 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2358 if (appData.animateDragging) {
2359 XtSetValues(XtNameToWidget(menuBarWidget,
2360 "menuOptions.Animate Dragging"),
2363 if (appData.animate) {
2364 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2367 if (appData.autoComment) {
2368 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2371 if (appData.autoCallFlag) {
2372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2375 if (appData.autoFlipView) {
2376 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2379 if (appData.autoObserve) {
2380 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2383 if (appData.autoRaiseBoard) {
2384 XtSetValues(XtNameToWidget(menuBarWidget,
2385 "menuOptions.Auto Raise Board"), args, 1);
2387 if (appData.autoSaveGames) {
2388 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2391 if (appData.saveGameFile[0] != NULLCHAR) {
2392 /* Can't turn this off from menu */
2393 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2395 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2399 if (appData.blindfold) {
2400 XtSetValues(XtNameToWidget(menuBarWidget,
2401 "menuOptions.Blindfold"), args, 1);
2403 if (appData.flashCount > 0) {
2404 XtSetValues(XtNameToWidget(menuBarWidget,
2405 "menuOptions.Flash Moves"),
2408 if (appData.getMoveList) {
2409 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2413 if (appData.highlightDragging) {
2414 XtSetValues(XtNameToWidget(menuBarWidget,
2415 "menuOptions.Highlight Dragging"),
2419 if (appData.highlightLastMove) {
2420 XtSetValues(XtNameToWidget(menuBarWidget,
2421 "menuOptions.Highlight Last Move"),
2424 if (appData.icsAlarm) {
2425 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2428 if (appData.ringBellAfterMoves) {
2429 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2432 if (appData.oldSaveStyle) {
2433 XtSetValues(XtNameToWidget(menuBarWidget,
2434 "menuOptions.Old Save Style"), args, 1);
2436 if (appData.periodicUpdates) {
2437 XtSetValues(XtNameToWidget(menuBarWidget,
2438 "menuOptions.Periodic Updates"), args, 1);
2440 if (appData.ponderNextMove) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Ponder Next Move"), args, 1);
2444 if (appData.popupExitMessage) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Popup Exit Message"), args, 1);
2448 if (appData.popupMoveErrors) {
2449 XtSetValues(XtNameToWidget(menuBarWidget,
2450 "menuOptions.Popup Move Errors"), args, 1);
2452 if (appData.premove) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,
2454 "menuOptions.Premove"), args, 1);
2456 if (appData.quietPlay) {
2457 XtSetValues(XtNameToWidget(menuBarWidget,
2458 "menuOptions.Quiet Play"), args, 1);
2460 if (appData.showCoords) {
2461 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2464 if (appData.showThinking) {
2465 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2468 if (appData.testLegality) {
2469 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2476 ReadBitmap(&wIconPixmap, "icon_white.bm",
2477 icon_white_bits, icon_white_width, icon_white_height);
2478 ReadBitmap(&bIconPixmap, "icon_black.bm",
2479 icon_black_bits, icon_black_width, icon_black_height);
2480 iconPixmap = wIconPixmap;
2482 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2483 XtSetValues(shellWidget, args, i);
2486 * Create a cursor for the board widget.
2488 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2489 XChangeWindowAttributes(xDisplay, xBoardWindow,
2490 CWCursor, &window_attributes);
2493 * Inhibit shell resizing.
2495 shellArgs[0].value = (XtArgVal) &w;
2496 shellArgs[1].value = (XtArgVal) &h;
2497 XtGetValues(shellWidget, shellArgs, 2);
2498 shellArgs[4].value = shellArgs[2].value = w;
2499 shellArgs[5].value = shellArgs[3].value = h;
2500 XtSetValues(shellWidget, &shellArgs[2], 4);
2502 CatchDeleteWindow(shellWidget, "QuitProc");
2507 if (appData.bitmapDirectory[0] != NULLCHAR) {
2514 /* Create regular pieces */
2515 if (!useImages) CreatePieces();
2520 if (appData.animate || appData.animateDragging)
2523 XtAugmentTranslations(formWidget,
2524 XtParseTranslationTable(globalTranslations));
2525 XtAugmentTranslations(boardWidget,
2526 XtParseTranslationTable(boardTranslations));
2527 XtAugmentTranslations(whiteTimerWidget,
2528 XtParseTranslationTable(whiteTranslations));
2529 XtAugmentTranslations(blackTimerWidget,
2530 XtParseTranslationTable(blackTranslations));
2532 /* Why is the following needed on some versions of X instead
2533 * of a translation? */
2534 XtAddEventHandler(boardWidget, ExposureMask, False,
2535 (XtEventHandler) EventProc, NULL);
2540 if (errorExitStatus == -1) {
2541 if (appData.icsActive) {
2542 /* We now wait until we see "login:" from the ICS before
2543 sending the logon script (problems with timestamp otherwise) */
2544 /*ICSInitScript();*/
2545 if (appData.icsInputBox) ICSInputBoxPopUp();
2548 signal(SIGINT, IntSigHandler);
2549 signal(SIGTERM, IntSigHandler);
2550 if (*appData.cmailGameName != NULLCHAR) {
2551 signal(SIGUSR1, CmailSigHandler);
2555 XtAppMainLoop(appContext);
2562 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2563 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2565 unlink(gameCopyFilename);
2566 unlink(gamePasteFilename);
2577 CmailSigHandler(sig)
2583 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2585 /* Activate call-back function CmailSigHandlerCallBack() */
2586 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2588 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2592 CmailSigHandlerCallBack(isr, closure, message, count, error)
2600 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2602 /**** end signal code ****/
2612 f = fopen(appData.icsLogon, "r");
2618 strcat(buf, appData.icsLogon);
2619 f = fopen(buf, "r");
2623 ProcessICSInitScript(f);
2630 EditCommentPopDown();
2641 SetMenuEnables(enab)
2645 if (!menuBarWidget) return;
2646 while (enab->name != NULL) {
2647 w = XtNameToWidget(menuBarWidget, enab->name);
2649 DisplayError(enab->name, 0);
2651 XtSetSensitive(w, enab->value);
2657 Enables icsEnables[] = {
2658 { "menuFile.Mail Move", False },
2659 { "menuFile.Reload CMail Message", False },
2660 { "menuMode.Machine Black", False },
2661 { "menuMode.Machine White", False },
2662 { "menuMode.Analysis Mode", False },
2663 { "menuMode.Analyze File", False },
2664 { "menuMode.Two Machines", False },
2666 { "menuHelp.Hint", False },
2667 { "menuHelp.Book", False },
2668 { "menuStep.Move Now", False },
2669 { "menuOptions.Periodic Updates", False },
2670 { "menuOptions.Show Thinking", False },
2671 { "menuOptions.Ponder Next Move", False },
2676 Enables ncpEnables[] = {
2677 { "menuFile.Mail Move", False },
2678 { "menuFile.Reload CMail Message", False },
2679 { "menuMode.Machine White", False },
2680 { "menuMode.Machine Black", False },
2681 { "menuMode.Analysis Mode", False },
2682 { "menuMode.Analyze File", False },
2683 { "menuMode.Two Machines", False },
2684 { "menuMode.ICS Client", False },
2685 { "menuMode.ICS Input Box", False },
2686 { "Action", False },
2687 { "menuStep.Revert", False },
2688 { "menuStep.Move Now", False },
2689 { "menuStep.Retract Move", False },
2690 { "menuOptions.Auto Comment", False },
2691 { "menuOptions.Auto Flag", False },
2692 { "menuOptions.Auto Flip View", False },
2693 { "menuOptions.Auto Observe", False },
2694 { "menuOptions.Auto Raise Board", False },
2695 { "menuOptions.Get Move List", False },
2696 { "menuOptions.ICS Alarm", False },
2697 { "menuOptions.Move Sound", False },
2698 { "menuOptions.Quiet Play", False },
2699 { "menuOptions.Show Thinking", False },
2700 { "menuOptions.Periodic Updates", False },
2701 { "menuOptions.Ponder Next Move", False },
2702 { "menuHelp.Hint", False },
2703 { "menuHelp.Book", False },
2707 Enables gnuEnables[] = {
2708 { "menuMode.ICS Client", False },
2709 { "menuMode.ICS Input Box", False },
2710 { "menuAction.Accept", False },
2711 { "menuAction.Decline", False },
2712 { "menuAction.Rematch", False },
2713 { "menuAction.Adjourn", False },
2714 { "menuAction.Stop Examining", False },
2715 { "menuAction.Stop Observing", False },
2716 { "menuStep.Revert", False },
2717 { "menuOptions.Auto Comment", False },
2718 { "menuOptions.Auto Observe", False },
2719 { "menuOptions.Auto Raise Board", False },
2720 { "menuOptions.Get Move List", False },
2721 { "menuOptions.Premove", False },
2722 { "menuOptions.Quiet Play", False },
2724 /* The next two options rely on SetCmailMode being called *after* */
2725 /* SetGNUMode so that when GNU is being used to give hints these */
2726 /* menu options are still available */
2728 { "menuFile.Mail Move", False },
2729 { "menuFile.Reload CMail Message", False },
2733 Enables cmailEnables[] = {
2735 { "menuAction.Call Flag", False },
2736 { "menuAction.Draw", True },
2737 { "menuAction.Adjourn", False },
2738 { "menuAction.Abort", False },
2739 { "menuAction.Stop Observing", False },
2740 { "menuAction.Stop Examining", False },
2741 { "menuFile.Mail Move", True },
2742 { "menuFile.Reload CMail Message", True },
2746 Enables trainingOnEnables[] = {
2747 { "menuMode.Edit Comment", False },
2748 { "menuMode.Pause", False },
2749 { "menuStep.Forward", False },
2750 { "menuStep.Backward", False },
2751 { "menuStep.Forward to End", False },
2752 { "menuStep.Back to Start", False },
2753 { "menuStep.Move Now", False },
2754 { "menuStep.Truncate Game", False },
2758 Enables trainingOffEnables[] = {
2759 { "menuMode.Edit Comment", True },
2760 { "menuMode.Pause", True },
2761 { "menuStep.Forward", True },
2762 { "menuStep.Backward", True },
2763 { "menuStep.Forward to End", True },
2764 { "menuStep.Back to Start", True },
2765 { "menuStep.Move Now", True },
2766 { "menuStep.Truncate Game", True },
2770 Enables machineThinkingEnables[] = {
2771 { "menuFile.Load Game", False },
2772 { "menuFile.Load Next Game", False },
2773 { "menuFile.Load Previous Game", False },
2774 { "menuFile.Reload Same Game", False },
2775 { "menuFile.Paste Game", False },
2776 { "menuFile.Load Position", False },
2777 { "menuFile.Load Next Position", False },
2778 { "menuFile.Load Previous Position", False },
2779 { "menuFile.Reload Same Position", False },
2780 { "menuFile.Paste Position", False },
2781 { "menuMode.Machine White", False },
2782 { "menuMode.Machine Black", False },
2783 { "menuMode.Two Machines", False },
2784 { "menuStep.Retract Move", False },
2788 Enables userThinkingEnables[] = {
2789 { "menuFile.Load Game", True },
2790 { "menuFile.Load Next Game", True },
2791 { "menuFile.Load Previous Game", True },
2792 { "menuFile.Reload Same Game", True },
2793 { "menuFile.Paste Game", True },
2794 { "menuFile.Load Position", True },
2795 { "menuFile.Load Next Position", True },
2796 { "menuFile.Load Previous Position", True },
2797 { "menuFile.Reload Same Position", True },
2798 { "menuFile.Paste Position", True },
2799 { "menuMode.Machine White", True },
2800 { "menuMode.Machine Black", True },
2801 { "menuMode.Two Machines", True },
2802 { "menuStep.Retract Move", True },
2808 SetMenuEnables(icsEnables);
2811 /* icsEngineAnalyze */
2812 if (appData.zippyPlay && !appData.noChessProgram)
2813 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2820 SetMenuEnables(ncpEnables);
2826 SetMenuEnables(gnuEnables);
2832 SetMenuEnables(cmailEnables);
2838 SetMenuEnables(trainingOnEnables);
2839 if (appData.showButtonBar) {
2840 XtSetSensitive(buttonBarWidget, False);
2846 SetTrainingModeOff()
2848 SetMenuEnables(trainingOffEnables);
2849 if (appData.showButtonBar) {
2850 XtSetSensitive(buttonBarWidget, True);
2855 SetUserThinkingEnables()
2857 if (appData.noChessProgram) return;
2858 SetMenuEnables(userThinkingEnables);
2862 SetMachineThinkingEnables()
2864 if (appData.noChessProgram) return;
2865 SetMenuEnables(machineThinkingEnables);
2867 case MachinePlaysBlack:
2868 case MachinePlaysWhite:
2869 case TwoMachinesPlay:
2870 XtSetSensitive(XtNameToWidget(menuBarWidget,
2871 ModeToWidgetName(gameMode)), True);
2878 #define Abs(n) ((n)<0 ? -(n) : (n))
2881 * Find a font that matches "pattern" that is as close as
2882 * possible to the targetPxlSize. Prefer fonts that are k
2883 * pixels smaller to fonts that are k pixels larger. The
2884 * pattern must be in the X Consortium standard format,
2885 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2886 * The return value should be freed with XtFree when no
2889 char *FindFont(pattern, targetPxlSize)
2893 char **fonts, *p, *best, *scalable, *scalableTail;
2894 int i, j, nfonts, minerr, err, pxlSize;
2897 char **missing_list;
2899 char *def_string, *base_fnt_lst, strInt[3];
2901 XFontStruct **fnt_list;
2903 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2904 sprintf(strInt, "%d", targetPxlSize);
2905 p = strstr(pattern, "--");
2906 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2907 strcat(base_fnt_lst, strInt);
2908 strcat(base_fnt_lst, strchr(p + 2, '-'));
2910 if ((fntSet = XCreateFontSet(xDisplay,
2914 &def_string)) == NULL) {
2916 fprintf(stderr, _("Unable to create font set.\n"));
2920 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2922 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2924 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2925 programName, pattern);
2933 for (i=0; i<nfonts; i++) {
2936 if (*p != '-') continue;
2938 if (*p == NULLCHAR) break;
2939 if (*p++ == '-') j++;
2941 if (j < 7) continue;
2944 scalable = fonts[i];
2947 err = pxlSize - targetPxlSize;
2948 if (Abs(err) < Abs(minerr) ||
2949 (minerr > 0 && err < 0 && -err == minerr)) {
2955 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2956 /* If the error is too big and there is a scalable font,
2957 use the scalable font. */
2958 int headlen = scalableTail - scalable;
2959 p = (char *) XtMalloc(strlen(scalable) + 10);
2960 while (isdigit(*scalableTail)) scalableTail++;
2961 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2963 p = (char *) XtMalloc(strlen(best) + 1);
2966 if (appData.debugMode) {
2967 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2968 pattern, targetPxlSize, p);
2971 if (missing_count > 0)
2972 XFreeStringList(missing_list);
2973 XFreeFontSet(xDisplay, fntSet);
2975 XFreeFontNames(fonts);
2982 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2983 | GCBackground | GCFunction | GCPlaneMask;
2984 XGCValues gc_values;
2987 gc_values.plane_mask = AllPlanes;
2988 gc_values.line_width = lineGap;
2989 gc_values.line_style = LineSolid;
2990 gc_values.function = GXcopy;
2992 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2993 gc_values.background = XBlackPixel(xDisplay, xScreen);
2994 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2996 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2997 gc_values.background = XWhitePixel(xDisplay, xScreen);
2998 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2999 XSetFont(xDisplay, coordGC, coordFontID);
3001 if (appData.monoMode) {
3002 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3003 gc_values.background = XWhitePixel(xDisplay, xScreen);
3004 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3006 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3007 gc_values.background = XBlackPixel(xDisplay, xScreen);
3008 lightSquareGC = wbPieceGC
3009 = XtGetGC(shellWidget, value_mask, &gc_values);
3011 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3012 gc_values.background = XWhitePixel(xDisplay, xScreen);
3013 darkSquareGC = bwPieceGC
3014 = XtGetGC(shellWidget, value_mask, &gc_values);
3016 if (DefaultDepth(xDisplay, xScreen) == 1) {
3017 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3018 gc_values.function = GXcopyInverted;
3019 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3020 gc_values.function = GXcopy;
3021 if (XBlackPixel(xDisplay, xScreen) == 1) {
3022 bwPieceGC = darkSquareGC;
3023 wbPieceGC = copyInvertedGC;
3025 bwPieceGC = copyInvertedGC;
3026 wbPieceGC = lightSquareGC;
3030 gc_values.foreground = highlightSquareColor;
3031 gc_values.background = highlightSquareColor;
3032 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3034 gc_values.foreground = premoveHighlightColor;
3035 gc_values.background = premoveHighlightColor;
3036 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3038 gc_values.foreground = lightSquareColor;
3039 gc_values.background = darkSquareColor;
3040 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3042 gc_values.foreground = darkSquareColor;
3043 gc_values.background = lightSquareColor;
3044 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3046 gc_values.foreground = jailSquareColor;
3047 gc_values.background = jailSquareColor;
3048 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3050 gc_values.foreground = whitePieceColor;
3051 gc_values.background = darkSquareColor;
3052 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3054 gc_values.foreground = whitePieceColor;
3055 gc_values.background = lightSquareColor;
3056 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3058 gc_values.foreground = whitePieceColor;
3059 gc_values.background = jailSquareColor;
3060 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3062 gc_values.foreground = blackPieceColor;
3063 gc_values.background = darkSquareColor;
3064 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3066 gc_values.foreground = blackPieceColor;
3067 gc_values.background = lightSquareColor;
3068 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3070 gc_values.foreground = blackPieceColor;
3071 gc_values.background = jailSquareColor;
3072 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3076 void loadXIM(xim, xmask, filename, dest, mask)
3089 fp = fopen(filename, "rb");
3091 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3098 for (y=0; y<h; ++y) {
3099 for (x=0; x<h; ++x) {
3104 XPutPixel(xim, x, y, blackPieceColor);
3106 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3109 XPutPixel(xim, x, y, darkSquareColor);
3111 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3114 XPutPixel(xim, x, y, whitePieceColor);
3116 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3119 XPutPixel(xim, x, y, lightSquareColor);
3121 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3127 /* create Pixmap of piece */
3128 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3130 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3133 /* create Pixmap of clipmask
3134 Note: We assume the white/black pieces have the same
3135 outline, so we make only 6 masks. This is okay
3136 since the XPM clipmask routines do the same. */
3138 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3140 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3143 /* now create the 1-bit version */
3144 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3147 values.foreground = 1;
3148 values.background = 0;
3150 /* Don't use XtGetGC, not read only */
3151 maskGC = XCreateGC(xDisplay, *mask,
3152 GCForeground | GCBackground, &values);
3153 XCopyPlane(xDisplay, temp, *mask, maskGC,
3154 0, 0, squareSize, squareSize, 0, 0, 1);
3155 XFreePixmap(xDisplay, temp);
3159 void CreateXIMPieces()
3164 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3169 /* The XSynchronize calls were copied from CreatePieces.
3170 Not sure if needed, but can't hurt */
3171 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3174 /* temp needed by loadXIM() */
3175 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3176 0, 0, ss, ss, AllPlanes, XYPixmap);
3178 if (strlen(appData.pixmapDirectory) == 0) {
3182 if (appData.monoMode) {
3183 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3187 fprintf(stderr, _("\nLoading XIMs...\n"));
3189 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3190 fprintf(stderr, "%d", piece+1);
3191 for (kind=0; kind<4; kind++) {
3192 fprintf(stderr, ".");
3193 sprintf(buf, "%s/%c%s%u.xim",
3194 ExpandPathName(appData.pixmapDirectory),
3195 ToLower(PieceToChar((ChessSquare)piece)),
3197 ximPieceBitmap[kind][piece] =
3198 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3199 0, 0, ss, ss, AllPlanes, XYPixmap);
3200 if (appData.debugMode)
3201 fprintf(stderr, _("(File:%s:) "), buf);
3202 loadXIM(ximPieceBitmap[kind][piece],
3204 &(xpmPieceBitmap[kind][piece]),
3205 &(ximMaskPm[piece%6]));
3207 fprintf(stderr," ");
3209 /* Load light and dark squares */
3210 /* If the LSQ and DSQ pieces don't exist, we will
3211 draw them with solid squares. */
3212 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3213 if (access(buf, 0) != 0) {
3217 fprintf(stderr, _("light square "));
3219 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3220 0, 0, ss, ss, AllPlanes, XYPixmap);
3221 if (appData.debugMode)
3222 fprintf(stderr, _("(File:%s:) "), buf);
3224 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3225 fprintf(stderr, _("dark square "));
3226 sprintf(buf, "%s/dsq%u.xim",
3227 ExpandPathName(appData.pixmapDirectory), ss);
3228 if (appData.debugMode)
3229 fprintf(stderr, _("(File:%s:) "), buf);
3231 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3232 0, 0, ss, ss, AllPlanes, XYPixmap);
3233 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3234 xpmJailSquare = xpmLightSquare;
3236 fprintf(stderr, _("Done.\n"));
3238 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3242 void CreateXPMPieces()
3246 u_int ss = squareSize;
3248 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3249 XpmColorSymbol symbols[4];
3252 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3253 if (appData.debugMode) {
3254 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3255 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3259 /* The XSynchronize calls were copied from CreatePieces.
3260 Not sure if needed, but can't hurt */
3261 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3263 /* Setup translations so piece colors match square colors */
3264 symbols[0].name = "light_piece";
3265 symbols[0].value = appData.whitePieceColor;
3266 symbols[1].name = "dark_piece";
3267 symbols[1].value = appData.blackPieceColor;
3268 symbols[2].name = "light_square";
3269 symbols[2].value = appData.lightSquareColor;
3270 symbols[3].name = "dark_square";
3271 symbols[3].value = appData.darkSquareColor;
3273 attr.valuemask = XpmColorSymbols;
3274 attr.colorsymbols = symbols;
3275 attr.numsymbols = 4;
3277 if (appData.monoMode) {
3278 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3282 if (strlen(appData.pixmapDirectory) == 0) {
3283 XpmPieces* pieces = builtInXpms;
3286 while (pieces->size != squareSize && pieces->size) pieces++;
3287 if (!pieces->size) {
3288 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3291 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3292 for (kind=0; kind<4; kind++) {
3294 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3295 pieces->xpm[piece][kind],
3296 &(xpmPieceBitmap[kind][piece]),
3297 NULL, &attr)) != 0) {
3298 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3305 xpmJailSquare = xpmLightSquare;
3309 fprintf(stderr, _("\nLoading XPMs...\n"));
3312 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3313 fprintf(stderr, "%d ", piece+1);
3314 for (kind=0; kind<4; kind++) {
3315 sprintf(buf, "%s/%c%s%u.xpm",
3316 ExpandPathName(appData.pixmapDirectory),
3317 ToLower(PieceToChar((ChessSquare)piece)),
3319 if (appData.debugMode) {
3320 fprintf(stderr, _("(File:%s:) "), buf);
3322 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3323 &(xpmPieceBitmap[kind][piece]),
3324 NULL, &attr)) != 0) {
3325 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3331 /* Load light and dark squares */
3332 /* If the LSQ and DSQ pieces don't exist, we will
3333 draw them with solid squares. */
3334 fprintf(stderr, _("light square "));
3335 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3336 if (access(buf, 0) != 0) {
3340 if (appData.debugMode)
3341 fprintf(stderr, _("(File:%s:) "), buf);
3343 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3344 &xpmLightSquare, NULL, &attr)) != 0) {
3345 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3348 fprintf(stderr, _("dark square "));
3349 sprintf(buf, "%s/dsq%u.xpm",
3350 ExpandPathName(appData.pixmapDirectory), ss);
3351 if (appData.debugMode) {
3352 fprintf(stderr, _("(File:%s:) "), buf);
3354 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3355 &xpmDarkSquare, NULL, &attr)) != 0) {
3356 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3360 xpmJailSquare = xpmLightSquare;
3361 fprintf(stderr, _("Done.\n"));
3363 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3366 #endif /* HAVE_LIBXPM */
3369 /* No built-in bitmaps */
3374 u_int ss = squareSize;
3376 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3379 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3380 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3381 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3382 ss, kind == SOLID ? 's' : 'o');
3383 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3387 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3391 /* With built-in bitmaps */
3394 BuiltInBits* bib = builtInBits;
3397 u_int ss = squareSize;
3399 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3402 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3404 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3405 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3406 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3407 ss, kind == SOLID ? 's' : 'o');
3408 ReadBitmap(&pieceBitmap[kind][piece], buf,
3409 bib->bits[kind][piece], ss, ss);
3413 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3418 void ReadBitmap(pm, name, bits, wreq, hreq)
3421 unsigned char bits[];
3427 char msg[MSG_SIZ], fullname[MSG_SIZ];
3429 if (*appData.bitmapDirectory != NULLCHAR) {
3430 strcpy(fullname, appData.bitmapDirectory);
3431 strcat(fullname, "/");
3432 strcat(fullname, name);
3433 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3434 &w, &h, pm, &x_hot, &y_hot);
3435 if (errcode != BitmapSuccess) {
3437 case BitmapOpenFailed:
3438 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3440 case BitmapFileInvalid:
3441 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3443 case BitmapNoMemory:
3444 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3448 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3452 fprintf(stderr, _("%s: %s...using built-in\n"),
3454 } else if (w != wreq || h != hreq) {
3456 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3457 programName, fullname, w, h, wreq, hreq);
3463 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3467 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3476 if (lineGap == 0) return;
3477 for (i = 0; i < BOARD_SIZE + 1; i++) {
3478 gridSegments[i].x1 = 0;
3479 gridSegments[i].x2 =
3480 lineGap + BOARD_SIZE * (squareSize + lineGap);
3481 gridSegments[i].y1 = gridSegments[i].y2
3482 = lineGap / 2 + (i * (squareSize + lineGap));
3484 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3485 gridSegments[i + BOARD_SIZE + 1].y2 =
3486 BOARD_SIZE * (squareSize + lineGap);
3487 gridSegments[i + BOARD_SIZE + 1].x1 =
3488 gridSegments[i + BOARD_SIZE + 1].x2
3489 = lineGap / 2 + (i * (squareSize + lineGap));
3493 static void MenuBarSelect(w, addr, index)
3498 XtActionProc proc = (XtActionProc) addr;
3500 (proc)(NULL, NULL, NULL, NULL);
3503 void CreateMenuBarPopup(parent, name, mb)
3513 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3516 XtSetArg(args[j], XtNleftMargin, 20); j++;
3517 XtSetArg(args[j], XtNrightMargin, 20); j++;
3519 while (mi->string != NULL) {
3520 if (strcmp(mi->string, "----") == 0) {
3521 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3524 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3525 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3527 XtAddCallback(entry, XtNcallback,
3528 (XtCallbackProc) MenuBarSelect,
3529 (caddr_t) mi->proc);
3535 Widget CreateMenuBar(mb)
3539 Widget anchor, menuBar;
3541 char menuName[MSG_SIZ];
3544 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3545 XtSetArg(args[j], XtNvSpace, 0); j++;
3546 XtSetArg(args[j], XtNborderWidth, 0); j++;
3547 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3548 formWidget, args, j);
3550 while (mb->name != NULL) {
3551 strcpy(menuName, "menu");
3552 strcat(menuName, mb->name);
3554 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3557 shortName[0] = _(mb->name)[0];
3558 shortName[1] = NULLCHAR;
3559 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3562 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3565 XtSetArg(args[j], XtNborderWidth, 0); j++;
3566 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3568 CreateMenuBarPopup(menuBar, menuName, mb);
3574 Widget CreateButtonBar(mi)
3578 Widget button, buttonBar;
3582 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3584 XtSetArg(args[j], XtNhSpace, 0); j++;
3586 XtSetArg(args[j], XtNborderWidth, 0); j++;
3587 XtSetArg(args[j], XtNvSpace, 0); j++;
3588 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3589 formWidget, args, j);
3591 while (mi->string != NULL) {
3594 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3595 XtSetArg(args[j], XtNborderWidth, 0); j++;
3597 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3598 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3599 buttonBar, args, j);
3600 XtAddCallback(button, XtNcallback,
3601 (XtCallbackProc) MenuBarSelect,
3602 (caddr_t) mi->proc);
3609 CreatePieceMenu(name, color)
3616 ChessSquare selection;
3618 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3619 boardWidget, args, 0);
3621 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3622 String item = pieceMenuStrings[color][i];
3624 if (strcmp(item, "----") == 0) {
3625 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3628 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3629 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3631 selection = pieceMenuTranslation[color][i];
3632 XtAddCallback(entry, XtNcallback,
3633 (XtCallbackProc) PieceMenuSelect,
3634 (caddr_t) selection);
3635 if (selection == WhitePawn || selection == BlackPawn) {
3636 XtSetArg(args[0], XtNpopupOnEntry, entry);
3637 XtSetValues(menu, args, 1);
3650 ChessSquare selection;
3652 whitePieceMenu = CreatePieceMenu("menuW", 0);
3653 blackPieceMenu = CreatePieceMenu("menuB", 1);
3655 XtRegisterGrabAction(PieceMenuPopup, True,
3656 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3657 GrabModeAsync, GrabModeAsync);
3659 XtSetArg(args[0], XtNlabel, _("Drop"));
3660 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3661 boardWidget, args, 1);
3662 for (i = 0; i < DROP_MENU_SIZE; i++) {
3663 String item = dropMenuStrings[i];
3665 if (strcmp(item, "----") == 0) {
3666 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3669 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3670 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3672 selection = dropMenuTranslation[i];
3673 XtAddCallback(entry, XtNcallback,
3674 (XtCallbackProc) DropMenuSelect,
3675 (caddr_t) selection);
3680 void SetupDropMenu()
3688 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3689 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3690 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3691 dmEnables[i].piece);
3692 XtSetSensitive(entry, p != NULL || !appData.testLegality
3693 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3694 && !appData.icsActive));
3696 while (p && *p++ == dmEnables[i].piece) count++;
3697 sprintf(label, "%s %d", dmEnables[i].widget, count);
3699 XtSetArg(args[j], XtNlabel, label); j++;
3700 XtSetValues(entry, args, j);
3704 void PieceMenuPopup(w, event, params, num_params)
3708 Cardinal *num_params;
3711 if (event->type != ButtonPress) return;
3712 if (errorUp) ErrorPopDown();
3716 whichMenu = params[0];
3718 case IcsPlayingWhite:
3719 case IcsPlayingBlack:
3721 case MachinePlaysWhite:
3722 case MachinePlaysBlack:
3723 if (appData.testLegality &&
3724 gameInfo.variant != VariantBughouse &&
3725 gameInfo.variant != VariantCrazyhouse) return;
3727 whichMenu = "menuD";
3733 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3734 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3735 pmFromX = pmFromY = -1;
3739 pmFromX = BOARD_SIZE - 1 - pmFromX;
3741 pmFromY = BOARD_SIZE - 1 - pmFromY;
3743 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3746 static void PieceMenuSelect(w, piece, junk)
3751 if (pmFromX < 0 || pmFromY < 0) return;
3752 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3755 static void DropMenuSelect(w, piece, junk)
3760 if (pmFromX < 0 || pmFromY < 0) return;
3761 DropMenuEvent(piece, pmFromX, pmFromY);
3764 void WhiteClock(w, event, prms, nprms)
3770 if (gameMode == EditPosition || gameMode == IcsExamining) {
3771 SetWhiteToPlayEvent();
3772 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3777 void BlackClock(w, event, prms, nprms)
3783 if (gameMode == EditPosition || gameMode == IcsExamining) {
3784 SetBlackToPlayEvent();
3785 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3792 * If the user selects on a border boundary, return -1; if off the board,
3793 * return -2. Otherwise map the event coordinate to the square.
3795 int EventToSquare(x, limit)
3803 if ((x % (squareSize + lineGap)) >= squareSize)
3805 x /= (squareSize + lineGap);
3811 static void do_flash_delay(msec)
3817 static void drawHighlight(file, rank, gc)
3823 if (lineGap == 0 || appData.blindfold) return;
3826 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3827 (squareSize + lineGap);
3828 y = lineGap/2 + rank * (squareSize + lineGap);
3830 x = lineGap/2 + file * (squareSize + lineGap);
3831 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3832 (squareSize + lineGap);
3835 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3836 squareSize+lineGap, squareSize+lineGap);
3839 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3840 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3843 SetHighlights(fromX, fromY, toX, toY)
3844 int fromX, fromY, toX, toY;
3846 if (hi1X != fromX || hi1Y != fromY) {
3847 if (hi1X >= 0 && hi1Y >= 0) {
3848 drawHighlight(hi1X, hi1Y, lineGC);
3850 if (fromX >= 0 && fromY >= 0) {
3851 drawHighlight(fromX, fromY, highlineGC);
3854 if (hi2X != toX || hi2Y != toY) {
3855 if (hi2X >= 0 && hi2Y >= 0) {
3856 drawHighlight(hi2X, hi2Y, lineGC);
3858 if (toX >= 0 && toY >= 0) {
3859 drawHighlight(toX, toY, highlineGC);
3871 SetHighlights(-1, -1, -1, -1);
3876 SetPremoveHighlights(fromX, fromY, toX, toY)
3877 int fromX, fromY, toX, toY;
3879 if (pm1X != fromX || pm1Y != fromY) {
3880 if (pm1X >= 0 && pm1Y >= 0) {
3881 drawHighlight(pm1X, pm1Y, lineGC);
3883 if (fromX >= 0 && fromY >= 0) {
3884 drawHighlight(fromX, fromY, prelineGC);
3887 if (pm2X != toX || pm2Y != toY) {
3888 if (pm2X >= 0 && pm2Y >= 0) {
3889 drawHighlight(pm2X, pm2Y, lineGC);
3891 if (toX >= 0 && toY >= 0) {
3892 drawHighlight(toX, toY, prelineGC);
3902 ClearPremoveHighlights()
3904 SetPremoveHighlights(-1, -1, -1, -1);
3907 static void BlankSquare(x, y, color, piece, dest)
3912 if (useImages && useImageSqs) {
3916 pm = xpmLightSquare;
3921 case 2: /* neutral */
3926 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3927 squareSize, squareSize, x, y);
3937 case 2: /* neutral */
3942 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3947 I split out the routines to draw a piece so that I could
3948 make a generic flash routine.
3950 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3952 int square_color, x, y;
3955 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3956 switch (square_color) {
3958 case 2: /* neutral */
3960 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3961 ? *pieceToOutline(piece)
3962 : *pieceToSolid(piece),
3963 dest, bwPieceGC, 0, 0,
3964 squareSize, squareSize, x, y);
3967 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3968 ? *pieceToSolid(piece)
3969 : *pieceToOutline(piece),
3970 dest, wbPieceGC, 0, 0,
3971 squareSize, squareSize, x, y);
3976 static void monoDrawPiece(piece, square_color, x, y, dest)
3978 int square_color, x, y;
3981 switch (square_color) {
3983 case 2: /* neutral */
3985 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3986 ? *pieceToOutline(piece)
3987 : *pieceToSolid(piece),
3988 dest, bwPieceGC, 0, 0,
3989 squareSize, squareSize, x, y, 1);
3992 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3993 ? *pieceToSolid(piece)
3994 : *pieceToOutline(piece),
3995 dest, wbPieceGC, 0, 0,
3996 squareSize, squareSize, x, y, 1);
4001 static void colorDrawPiece(piece, square_color, x, y, dest)
4003 int square_color, x, y;
4006 switch (square_color) {
4008 XCopyPlane(xDisplay, *pieceToSolid(piece),
4009 dest, (int) piece < (int) BlackPawn
4010 ? wlPieceGC : blPieceGC, 0, 0,
4011 squareSize, squareSize, x, y, 1);
4014 XCopyPlane(xDisplay, *pieceToSolid(piece),
4015 dest, (int) piece < (int) BlackPawn
4016 ? wdPieceGC : bdPieceGC, 0, 0,
4017 squareSize, squareSize, x, y, 1);
4019 case 2: /* neutral */
4021 XCopyPlane(xDisplay, *pieceToSolid(piece),
4022 dest, (int) piece < (int) BlackPawn
4023 ? wjPieceGC : bjPieceGC, 0, 0,
4024 squareSize, squareSize, x, y, 1);
4029 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4031 int square_color, x, y;
4036 switch (square_color) {
4038 case 2: /* neutral */
4040 if ((int)piece < (int) BlackPawn) {
4048 if ((int)piece < (int) BlackPawn) {
4056 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4057 dest, wlPieceGC, 0, 0,
4058 squareSize, squareSize, x, y);
4061 typedef void (*DrawFunc)();
4063 DrawFunc ChooseDrawFunc()
4065 if (appData.monoMode) {
4066 if (DefaultDepth(xDisplay, xScreen) == 1) {
4067 return monoDrawPiece_1bit;
4069 return monoDrawPiece;
4073 return colorDrawPieceImage;
4075 return colorDrawPiece;
4079 void DrawSquare(row, column, piece, do_flash)
4080 int row, column, do_flash;
4083 int square_color, x, y, direction, font_ascent, font_descent;
4086 XCharStruct overall;
4090 /* Calculate delay in milliseconds (2-delays per complete flash) */
4091 flash_delay = 500 / appData.flashRate;
4094 x = lineGap + ((BOARD_SIZE-1)-column) *
4095 (squareSize + lineGap);
4096 y = lineGap + row * (squareSize + lineGap);
4098 x = lineGap + column * (squareSize + lineGap);
4099 y = lineGap + ((BOARD_SIZE-1)-row) *
4100 (squareSize + lineGap);
4103 square_color = ((column + row) % 2) == 1;
4105 if (piece == EmptySquare || appData.blindfold) {
4106 BlankSquare(x, y, square_color, piece, xBoardWindow);
4108 drawfunc = ChooseDrawFunc();
4109 if (do_flash && appData.flashCount > 0) {
4110 for (i=0; i<appData.flashCount; ++i) {
4112 drawfunc(piece, square_color, x, y, xBoardWindow);
4113 XSync(xDisplay, False);
4114 do_flash_delay(flash_delay);
4116 BlankSquare(x, y, square_color, piece, xBoardWindow);
4117 XSync(xDisplay, False);
4118 do_flash_delay(flash_delay);
4121 drawfunc(piece, square_color, x, y, xBoardWindow);
4124 string[1] = NULLCHAR;
4125 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4126 string[0] = 'a' + column;
4127 XTextExtents(coordFontStruct, string, 1, &direction,
4128 &font_ascent, &font_descent, &overall);
4129 if (appData.monoMode) {
4130 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4131 x + squareSize - overall.width - 2,
4132 y + squareSize - font_descent - 1, string, 1);
4134 XDrawString(xDisplay, xBoardWindow, coordGC,
4135 x + squareSize - overall.width - 2,
4136 y + squareSize - font_descent - 1, string, 1);
4139 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4140 string[0] = '1' + row;
4141 XTextExtents(coordFontStruct, string, 1, &direction,
4142 &font_ascent, &font_descent, &overall);
4143 if (appData.monoMode) {
4144 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4145 x + 2, y + font_ascent + 1, string, 1);
4147 XDrawString(xDisplay, xBoardWindow, coordGC,
4148 x + 2, y + font_ascent + 1, string, 1);
4154 /* Why is this needed on some versions of X? */
4155 void EventProc(widget, unused, event)
4160 if (!XtIsRealized(widget))
4163 switch (event->type) {
4165 if (event->xexpose.count > 0) return; /* no clipping is done */
4166 XDrawPosition(widget, True, NULL);
4174 void DrawPosition(fullRedraw, board)
4175 /*Boolean*/int fullRedraw;
4178 XDrawPosition(boardWidget, fullRedraw, board);
4181 /* Returns 1 if there are "too many" differences between b1 and b2
4182 (i.e. more than 1 move was made) */
4183 static int too_many_diffs(b1, b2)
4189 for (i=0; i<BOARD_SIZE; ++i) {
4190 for (j=0; j<BOARD_SIZE; ++j) {
4191 if (b1[i][j] != b2[i][j]) {
4192 if (++c > 4) /* Castling causes 4 diffs */
4201 /* Matrix describing castling maneuvers */
4202 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4203 static int castling_matrix[4][5] = {
4204 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4205 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4206 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4207 { 7, 7, 4, 5, 6 } /* 0-0, black */
4210 /* Checks whether castling occurred. If it did, *rrow and *rcol
4211 are set to the destination (row,col) of the rook that moved.
4213 Returns 1 if castling occurred, 0 if not.
4215 Note: Only handles a max of 1 castling move, so be sure
4216 to call too_many_diffs() first.
4218 static int check_castle_draw(newb, oldb, rrow, rcol)
4225 /* For each type of castling... */
4226 for (i=0; i<4; ++i) {
4227 r = castling_matrix[i];
4229 /* Check the 4 squares involved in the castling move */
4231 for (j=1; j<=4; ++j) {
4232 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4239 /* All 4 changed, so it must be a castling move */
4248 static int damage[BOARD_SIZE][BOARD_SIZE];
4251 * event handler for redrawing the board
4253 void XDrawPosition(w, repaint, board)
4255 /*Boolean*/int repaint;
4259 static int lastFlipView = 0;
4260 static int lastBoardValid = 0;
4261 static Board lastBoard;
4265 if (board == NULL) {
4266 if (!lastBoardValid) return;
4269 if (!lastBoardValid || lastFlipView != flipView) {
4270 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4271 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4276 * It would be simpler to clear the window with XClearWindow()
4277 * but this causes a very distracting flicker.
4280 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4282 /* If too much changes (begin observing new game, etc.), don't
4284 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4286 /* Special check for castling so we don't flash both the king
4287 and the rook (just flash the king). */
4289 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4290 /* Draw rook with NO flashing. King will be drawn flashing later */
4291 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4292 lastBoard[rrow][rcol] = board[rrow][rcol];
4296 /* First pass -- Draw (newly) empty squares and repair damage.
4297 This prevents you from having a piece show up twice while it
4298 is flashing on its new square */
4299 for (i = 0; i < BOARD_SIZE; i++)
4300 for (j = 0; j < BOARD_SIZE; j++)
4301 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4303 DrawSquare(i, j, board[i][j], 0);
4304 damage[i][j] = False;
4307 /* Second pass -- Draw piece(s) in new position and flash them */
4308 for (i = 0; i < BOARD_SIZE; i++)
4309 for (j = 0; j < BOARD_SIZE; j++)
4310 if (board[i][j] != lastBoard[i][j]) {
4311 DrawSquare(i, j, board[i][j], do_flash);
4315 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4316 gridSegments, (BOARD_SIZE + 1) * 2);
4318 for (i = 0; i < BOARD_SIZE; i++)
4319 for (j = 0; j < BOARD_SIZE; j++) {
4320 DrawSquare(i, j, board[i][j], 0);
4321 damage[i][j] = False;
4325 CopyBoard(lastBoard, board);
4327 lastFlipView = flipView;
4329 /* Draw highlights */
4330 if (pm1X >= 0 && pm1Y >= 0) {
4331 drawHighlight(pm1X, pm1Y, prelineGC);
4333 if (pm2X >= 0 && pm2Y >= 0) {
4334 drawHighlight(pm2X, pm2Y, prelineGC);
4336 if (hi1X >= 0 && hi1Y >= 0) {
4337 drawHighlight(hi1X, hi1Y, highlineGC);
4339 if (hi2X >= 0 && hi2Y >= 0) {
4340 drawHighlight(hi2X, hi2Y, highlineGC);
4343 /* If piece being dragged around board, must redraw that too */
4346 XSync(xDisplay, False);
4351 * event handler for redrawing the board
4353 void DrawPositionProc(w, event, prms, nprms)
4359 XDrawPosition(w, True, NULL);
4364 * event handler for parsing user moves
4366 void HandleUserMove(w, event, prms, nprms)
4373 Boolean saveAnimate;
4374 static int second = 0;
4376 if (w != boardWidget || errorExitStatus != -1) return;
4378 if (event->type == ButtonPress) ErrorPopDown();
4381 if (event->type == ButtonPress) {
4382 XtPopdown(promotionShell);
4383 XtDestroyWidget(promotionShell);
4384 promotionUp = False;
4392 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4393 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4394 if (!flipView && y >= 0) {
4395 y = BOARD_SIZE - 1 - y;
4397 if (flipView && x >= 0) {
4398 x = BOARD_SIZE - 1 - x;
4402 if (event->type == ButtonPress) {
4404 if (OKToStartUserMove(x, y)) {
4408 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4409 if (appData.highlightDragging) {
4410 SetHighlights(x, y, -1, -1);
4418 if (event->type == ButtonPress && gameMode != EditPosition &&
4422 /* Check if clicking again on the same color piece */
4423 fromP = boards[currentMove][fromY][fromX];
4424 toP = boards[currentMove][y][x];
4425 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4426 WhitePawn <= toP && toP <= WhiteKing) ||
4427 (BlackPawn <= fromP && fromP <= BlackKing &&
4428 BlackPawn <= toP && toP <= BlackKing)) {
4429 /* Clicked again on same color piece -- changed his mind */
4430 second = (x == fromX && y == fromY);
4431 if (appData.highlightDragging) {
4432 SetHighlights(x, y, -1, -1);
4436 if (OKToStartUserMove(x, y)) {
4439 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4445 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4446 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4447 if (appData.animateDragging) {
4448 /* Undo animation damage if any */
4449 DrawPosition(FALSE, NULL);
4452 /* Second up/down in same square; just abort move */
4457 ClearPremoveHighlights();
4459 /* First upclick in same square; start click-click mode */
4460 SetHighlights(x, y, -1, -1);
4465 /* Completed move */
4468 saveAnimate = appData.animate;
4469 if (event->type == ButtonPress) {
4470 /* Finish clickclick move */
4471 if (appData.animate || appData.highlightLastMove) {
4472 SetHighlights(fromX, fromY, toX, toY);
4477 /* Finish drag move */
4478 if (appData.highlightLastMove) {
4479 SetHighlights(fromX, fromY, toX, toY);
4483 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4484 /* Don't animate move and drag both */
4485 appData.animate = FALSE;
4487 if (IsPromotion(fromX, fromY, toX, toY)) {
4488 if (appData.alwaysPromoteToQueen) {
4489 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4490 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4491 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4494 SetHighlights(fromX, fromY, toX, toY);
4498 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4499 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4500 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4503 appData.animate = saveAnimate;
4504 if (appData.animate || appData.animateDragging) {
4505 /* Undo animation damage if needed */
4506 DrawPosition(FALSE, NULL);
4510 void AnimateUserMove (Widget w, XEvent * event,
4511 String * params, Cardinal * nParams)
4513 DragPieceMove(event->xmotion.x, event->xmotion.y);
4516 Widget CommentCreate(name, text, mutable, callback, lines)
4518 int /*Boolean*/ mutable;
4519 XtCallbackProc callback;
4523 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4528 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4529 XtGetValues(boardWidget, args, j);
4532 XtSetArg(args[j], XtNresizable, True); j++;
4535 XtCreatePopupShell(name, topLevelShellWidgetClass,
4536 shellWidget, args, j);
4539 XtCreatePopupShell(name, transientShellWidgetClass,
4540 shellWidget, args, j);
4543 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4544 layoutArgs, XtNumber(layoutArgs));
4546 XtCreateManagedWidget("form", formWidgetClass, layout,
4547 formArgs, XtNumber(formArgs));
4551 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4552 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4554 XtSetArg(args[j], XtNstring, text); j++;
4555 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4556 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4557 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4558 XtSetArg(args[j], XtNright, XtChainRight); j++;
4559 XtSetArg(args[j], XtNresizable, True); j++;
4560 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4562 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4564 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4565 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4567 XtSetArg(args[j], XtNautoFill, True); j++;
4568 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4570 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4574 XtSetArg(args[j], XtNfromVert, edit); j++;
4575 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4576 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4577 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4578 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4580 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4581 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4584 XtSetArg(args[j], XtNfromVert, edit); j++;
4585 XtSetArg(args[j], XtNfromHoriz, b_ok); 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(_("cancel"), commandWidgetClass, form, args, j);
4592 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4595 XtSetArg(args[j], XtNfromVert, edit); j++;
4596 XtSetArg(args[j], XtNfromHoriz, b_cancel); 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(_("clear"), commandWidgetClass, form, args, j);
4603 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4606 XtSetArg(args[j], XtNfromVert, edit); j++;
4607 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4608 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4609 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4610 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4612 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4613 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4616 XtSetArg(args[j], XtNfromVert, edit); j++;
4617 XtSetArg(args[j], XtNfromHoriz, b_close); 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(_("edit"), commandWidgetClass, form, args, j);
4624 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4627 XtRealizeWidget(shell);
4629 if (commentX == -1) {
4632 Dimension pw_height;
4633 Dimension ew_height;
4636 XtSetArg(args[j], XtNheight, &ew_height); j++;
4637 XtGetValues(edit, args, j);
4640 XtSetArg(args[j], XtNheight, &pw_height); j++;
4641 XtGetValues(shell, args, j);
4642 commentH = pw_height + (lines - 1) * ew_height;
4643 commentW = bw_width - 16;
4645 XSync(xDisplay, False);
4647 /* This code seems to tickle an X bug if it is executed too soon
4648 after xboard starts up. The coordinates get transformed as if
4649 the main window was positioned at (0, 0).
4651 XtTranslateCoords(shellWidget,
4652 (bw_width - commentW) / 2, 0 - commentH / 2,
4653 &commentX, &commentY);
4655 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4656 RootWindowOfScreen(XtScreen(shellWidget)),
4657 (bw_width - commentW) / 2, 0 - commentH / 2,
4662 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4665 XtSetArg(args[j], XtNheight, commentH); j++;
4666 XtSetArg(args[j], XtNwidth, commentW); j++;
4667 XtSetArg(args[j], XtNx, commentX); j++;
4668 XtSetArg(args[j], XtNy, commentY); j++;
4669 XtSetValues(shell, args, j);
4670 XtSetKeyboardFocus(shell, edit);
4675 /* Used for analysis window and ICS input window */
4676 Widget MiscCreate(name, text, mutable, callback, lines)
4678 int /*Boolean*/ mutable;
4679 XtCallbackProc callback;
4683 Widget shell, layout, form, edit;
4685 Dimension bw_width, pw_height, ew_height, w, h;
4691 XtSetArg(args[j], XtNresizable, True); j++;
4694 XtCreatePopupShell(name, topLevelShellWidgetClass,
4695 shellWidget, args, j);
4698 XtCreatePopupShell(name, transientShellWidgetClass,
4699 shellWidget, args, j);
4702 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4703 layoutArgs, XtNumber(layoutArgs));
4705 XtCreateManagedWidget("form", formWidgetClass, layout,
4706 formArgs, XtNumber(formArgs));
4710 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4711 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4713 XtSetArg(args[j], XtNstring, text); j++;
4714 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4715 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4716 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4717 XtSetArg(args[j], XtNright, XtChainRight); j++;
4718 XtSetArg(args[j], XtNresizable, True); j++;
4720 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4722 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4723 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4725 XtSetArg(args[j], XtNautoFill, True); j++;
4726 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4728 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4730 XtRealizeWidget(shell);
4733 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4734 XtGetValues(boardWidget, args, j);
4737 XtSetArg(args[j], XtNheight, &ew_height); j++;
4738 XtGetValues(edit, args, j);
4741 XtSetArg(args[j], XtNheight, &pw_height); j++;
4742 XtGetValues(shell, args, j);
4743 h = pw_height + (lines - 1) * ew_height;
4746 XSync(xDisplay, False);
4748 /* This code seems to tickle an X bug if it is executed too soon
4749 after xboard starts up. The coordinates get transformed as if
4750 the main window was positioned at (0, 0).
4752 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4754 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4755 RootWindowOfScreen(XtScreen(shellWidget)),
4756 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4760 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4763 XtSetArg(args[j], XtNheight, h); j++;
4764 XtSetArg(args[j], XtNwidth, w); j++;
4765 XtSetArg(args[j], XtNx, x); j++;
4766 XtSetArg(args[j], XtNy, y); j++;
4767 XtSetValues(shell, args, j);
4773 static int savedIndex; /* gross that this is global */
4775 void EditCommentPopUp(index, title, text)
4784 if (text == NULL) text = "";
4786 if (editShell == NULL) {
4788 CommentCreate(title, text, True, EditCommentCallback, 4);
4789 XtRealizeWidget(editShell);
4790 CatchDeleteWindow(editShell, "EditCommentPopDown");
4792 edit = XtNameToWidget(editShell, "*form.text");
4794 XtSetArg(args[j], XtNstring, text); j++;
4795 XtSetValues(edit, args, j);
4797 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4798 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4799 XtSetValues(editShell, args, j);
4802 XtPopup(editShell, XtGrabNone);
4806 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4807 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4811 void EditCommentCallback(w, client_data, call_data)
4813 XtPointer client_data, call_data;
4821 XtSetArg(args[j], XtNlabel, &name); j++;
4822 XtGetValues(w, args, j);
4824 if (strcmp(name, _("ok")) == 0) {
4825 edit = XtNameToWidget(editShell, "*form.text");
4827 XtSetArg(args[j], XtNstring, &val); j++;
4828 XtGetValues(edit, args, j);
4829 ReplaceComment(savedIndex, val);
4830 EditCommentPopDown();
4831 } else if (strcmp(name, _("cancel")) == 0) {
4832 EditCommentPopDown();
4833 } else if (strcmp(name, _("clear")) == 0) {
4834 edit = XtNameToWidget(editShell, "*form.text");
4835 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4836 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4840 void EditCommentPopDown()
4845 if (!editUp) return;
4847 XtSetArg(args[j], XtNx, &commentX); j++;
4848 XtSetArg(args[j], XtNy, &commentY); j++;
4849 XtSetArg(args[j], XtNheight, &commentH); j++;
4850 XtSetArg(args[j], XtNwidth, &commentW); j++;
4851 XtGetValues(editShell, args, j);
4852 XtPopdown(editShell);
4855 XtSetArg(args[j], XtNleftBitmap, None); j++;
4856 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4860 void ICSInputBoxPopUp()
4865 char *title = _("ICS Input");
4868 if (ICSInputShell == NULL) {
4869 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4870 tr = XtParseTranslationTable(ICSInputTranslations);
4871 edit = XtNameToWidget(ICSInputShell, "*form.text");
4872 XtOverrideTranslations(edit, tr);
4873 XtRealizeWidget(ICSInputShell);
4874 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4877 edit = XtNameToWidget(ICSInputShell, "*form.text");
4879 XtSetArg(args[j], XtNstring, ""); j++;
4880 XtSetValues(edit, args, j);
4882 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4883 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4884 XtSetValues(ICSInputShell, args, j);
4887 XtPopup(ICSInputShell, XtGrabNone);
4888 XtSetKeyboardFocus(ICSInputShell, edit);
4890 ICSInputBoxUp = True;
4892 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4893 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4897 void ICSInputSendText()
4904 edit = XtNameToWidget(ICSInputShell, "*form.text");
4906 XtSetArg(args[j], XtNstring, &val); j++;
4907 XtGetValues(edit, args, j);
4908 SendMultiLineToICS(val);
4909 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4910 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4913 void ICSInputBoxPopDown()
4918 if (!ICSInputBoxUp) return;
4920 XtPopdown(ICSInputShell);
4921 ICSInputBoxUp = False;
4923 XtSetArg(args[j], XtNleftBitmap, None); j++;
4924 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4928 void CommentPopUp(title, text)
4935 if (commentShell == NULL) {
4937 CommentCreate(title, text, False, CommentCallback, 4);
4938 XtRealizeWidget(commentShell);
4939 CatchDeleteWindow(commentShell, "CommentPopDown");
4941 edit = XtNameToWidget(commentShell, "*form.text");
4943 XtSetArg(args[j], XtNstring, text); j++;
4944 XtSetValues(edit, args, j);
4946 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4947 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4948 XtSetValues(commentShell, args, j);
4951 XtPopup(commentShell, XtGrabNone);
4952 XSync(xDisplay, False);
4957 void AnalysisPopUp(title, text)
4964 if (analysisShell == NULL) {
4965 analysisShell = MiscCreate(title, text, False, NULL, 4);
4966 XtRealizeWidget(analysisShell);
4967 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4970 edit = XtNameToWidget(analysisShell, "*form.text");
4972 XtSetArg(args[j], XtNstring, text); j++;
4973 XtSetValues(edit, args, j);
4975 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4976 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4977 XtSetValues(analysisShell, args, j);
4981 XtPopup(analysisShell, XtGrabNone);
4983 XSync(xDisplay, False);
4988 void CommentCallback(w, client_data, call_data)
4990 XtPointer client_data, call_data;
4997 XtSetArg(args[j], XtNlabel, &name); j++;
4998 XtGetValues(w, args, j);
5000 if (strcmp(name, _("close")) == 0) {
5002 } else if (strcmp(name, _("edit")) == 0) {
5009 void CommentPopDown()
5014 if (!commentUp) return;
5016 XtSetArg(args[j], XtNx, &commentX); j++;
5017 XtSetArg(args[j], XtNy, &commentY); j++;
5018 XtSetArg(args[j], XtNwidth, &commentW); j++;
5019 XtSetArg(args[j], XtNheight, &commentH); j++;
5020 XtGetValues(commentShell, args, j);
5021 XtPopdown(commentShell);
5022 XSync(xDisplay, False);
5026 void AnalysisPopDown()
5028 if (!analysisUp) return;
5029 XtPopdown(analysisShell);
5030 XSync(xDisplay, False);
5035 void FileNamePopUp(label, def, proc, openMode)
5042 Widget popup, layout, dialog, edit;
5048 fileProc = proc; /* I can't see a way not */
5049 fileOpenMode = openMode; /* to use globals here */
5052 XtSetArg(args[i], XtNresizable, True); i++;
5053 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5054 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5055 fileNameShell = popup =
5056 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5057 shellWidget, args, i);
5060 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5061 layoutArgs, XtNumber(layoutArgs));
5064 XtSetArg(args[i], XtNlabel, label); i++;
5065 XtSetArg(args[i], XtNvalue, def); i++;
5066 XtSetArg(args[i], XtNborderWidth, 0); i++;
5067 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5070 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5071 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5072 (XtPointer) dialog);
5074 XtRealizeWidget(popup);
5075 CatchDeleteWindow(popup, "FileNamePopDown");
5077 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5078 &x, &y, &win_x, &win_y, &mask);
5080 XtSetArg(args[0], XtNx, x - 10);
5081 XtSetArg(args[1], XtNy, y - 30);
5082 XtSetValues(popup, args, 2);
5084 XtPopup(popup, XtGrabExclusive);
5087 edit = XtNameToWidget(dialog, "*value");
5088 XtSetKeyboardFocus(popup, edit);
5091 void FileNamePopDown()
5093 if (!filenameUp) return;
5094 XtPopdown(fileNameShell);
5095 XtDestroyWidget(fileNameShell);
5100 void FileNameCallback(w, client_data, call_data)
5102 XtPointer client_data, call_data;
5107 XtSetArg(args[0], XtNlabel, &name);
5108 XtGetValues(w, args, 1);
5110 if (strcmp(name, _("cancel")) == 0) {
5115 FileNameAction(w, NULL, NULL, NULL);
5118 void FileNameAction(w, event, prms, nprms)
5130 name = XawDialogGetValueString(w = XtParent(w));
5132 if ((name != NULL) && (*name != NULLCHAR)) {
5134 XtPopdown(w = XtParent(XtParent(w)));
5138 p = strrchr(buf, ' ');
5145 fullname = ExpandPathName(buf);
5147 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5150 f = fopen(fullname, fileOpenMode);
5152 DisplayError(_("Failed to open file"), errno);
5154 (void) (*fileProc)(f, index, buf);
5161 XtPopdown(w = XtParent(XtParent(w)));
5167 void PromotionPopUp()
5170 Widget dialog, layout;
5172 Dimension bw_width, pw_width;
5176 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5177 XtGetValues(boardWidget, args, j);
5180 XtSetArg(args[j], XtNresizable, True); j++;
5181 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5183 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5184 shellWidget, args, j);
5186 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5187 layoutArgs, XtNumber(layoutArgs));
5190 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5191 XtSetArg(args[j], XtNborderWidth, 0); j++;
5192 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5195 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5196 (XtPointer) dialog);
5197 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5198 (XtPointer) dialog);
5199 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5200 (XtPointer) dialog);
5201 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5202 (XtPointer) dialog);
5203 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5204 gameInfo.variant == VariantGiveaway) {
5205 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5206 (XtPointer) dialog);
5208 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5209 (XtPointer) dialog);
5211 XtRealizeWidget(promotionShell);
5212 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5215 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5216 XtGetValues(promotionShell, args, j);
5218 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5219 lineGap + squareSize/3 +
5220 ((toY == 7) ^ (flipView) ?
5221 0 : 6*(squareSize + lineGap)), &x, &y);
5224 XtSetArg(args[j], XtNx, x); j++;
5225 XtSetArg(args[j], XtNy, y); j++;
5226 XtSetValues(promotionShell, args, j);
5228 XtPopup(promotionShell, XtGrabNone);
5233 void PromotionPopDown()
5235 if (!promotionUp) return;
5236 XtPopdown(promotionShell);
5237 XtDestroyWidget(promotionShell);
5238 promotionUp = False;
5241 void PromotionCallback(w, client_data, call_data)
5243 XtPointer client_data, call_data;
5249 XtSetArg(args[0], XtNlabel, &name);
5250 XtGetValues(w, args, 1);
5254 if (fromX == -1) return;
5256 if (strcmp(name, _("cancel")) == 0) {
5260 } else if (strcmp(name, _("Knight")) == 0) {
5263 promoChar = ToLower(name[0]);
5266 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5268 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5269 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5274 void ErrorCallback(w, client_data, call_data)
5276 XtPointer client_data, call_data;
5279 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5281 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5287 if (!errorUp) return;
5289 XtPopdown(errorShell);
5290 XtDestroyWidget(errorShell);
5291 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5294 void ErrorPopUp(title, label, modal)
5295 char *title, *label;
5299 Widget dialog, layout;
5303 Dimension bw_width, pw_width;
5304 Dimension pw_height;
5308 XtSetArg(args[i], XtNresizable, True); i++;
5309 XtSetArg(args[i], XtNtitle, title); i++;
5311 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5312 shellWidget, args, i);
5314 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5315 layoutArgs, XtNumber(layoutArgs));
5318 XtSetArg(args[i], XtNlabel, label); i++;
5319 XtSetArg(args[i], XtNborderWidth, 0); i++;
5320 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5323 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5325 XtRealizeWidget(errorShell);
5326 CatchDeleteWindow(errorShell, "ErrorPopDown");
5329 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5330 XtGetValues(boardWidget, args, i);
5332 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5333 XtSetArg(args[i], XtNheight, &pw_height); i++;
5334 XtGetValues(errorShell, args, i);
5337 /* This code seems to tickle an X bug if it is executed too soon
5338 after xboard starts up. The coordinates get transformed as if
5339 the main window was positioned at (0, 0).
5341 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5342 0 - pw_height + squareSize / 3, &x, &y);
5344 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5345 RootWindowOfScreen(XtScreen(boardWidget)),
5346 (bw_width - pw_width) / 2,
5347 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5351 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5354 XtSetArg(args[i], XtNx, x); i++;
5355 XtSetArg(args[i], XtNy, y); i++;
5356 XtSetValues(errorShell, args, i);
5359 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5362 /* Disable all user input other than deleting the window */
5363 static int frozen = 0;
5367 /* Grab by a widget that doesn't accept input */
5368 XtAddGrab(messageWidget, TRUE, FALSE);
5372 /* Undo a FreezeUI */
5375 if (!frozen) return;
5376 XtRemoveGrab(messageWidget);
5380 char *ModeToWidgetName(mode)
5384 case BeginningOfGame:
5385 if (appData.icsActive)
5386 return "menuMode.ICS Client";
5387 else if (appData.noChessProgram ||
5388 *appData.cmailGameName != NULLCHAR)
5389 return "menuMode.Edit Game";
5391 return "menuMode.Machine Black";
5392 case MachinePlaysBlack:
5393 return "menuMode.Machine Black";
5394 case MachinePlaysWhite:
5395 return "menuMode.Machine White";
5397 return "menuMode.Analysis Mode";
5399 return "menuMode.Analyze File";
5400 case TwoMachinesPlay:
5401 return "menuMode.Two Machines";
5403 return "menuMode.Edit Game";
5404 case PlayFromGameFile:
5405 return "menuFile.Load Game";
5407 return "menuMode.Edit Position";
5409 return "menuMode.Training";
5410 case IcsPlayingWhite:
5411 case IcsPlayingBlack:
5415 return "menuMode.ICS Client";
5422 void ModeHighlight()
5425 static int oldPausing = FALSE;
5426 static GameMode oldmode = (GameMode) -1;
5429 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5431 if (pausing != oldPausing) {
5432 oldPausing = pausing;
5434 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5436 XtSetArg(args[0], XtNleftBitmap, None);
5438 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5441 if (appData.showButtonBar) {
5444 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5445 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5447 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5448 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5451 /* Always toggle, don't set. Previous code messes up when
5452 invoked while the button is pressed, as releasing it
5453 toggles the state again. */
5456 XtSetArg(args[0], XtNbackground, &oldbg);
5457 XtSetArg(args[1], XtNforeground, &oldfg);
5458 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5460 XtSetArg(args[0], XtNbackground, oldfg);
5461 XtSetArg(args[1], XtNforeground, oldbg);
5464 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5468 wname = ModeToWidgetName(oldmode);
5469 if (wname != NULL) {
5470 XtSetArg(args[0], XtNleftBitmap, None);
5471 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5473 wname = ModeToWidgetName(gameMode);
5474 if (wname != NULL) {
5475 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5476 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5480 /* Maybe all the enables should be handled here, not just this one */
5481 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5482 gameMode == Training || gameMode == PlayFromGameFile);
5486 * Button/menu procedures
5488 void ResetProc(w, event, prms, nprms)
5498 int LoadGamePopUp(f, gameNumber, title)
5503 cmailMsgLoaded = FALSE;
5504 if (gameNumber == 0) {
5505 int error = GameListBuild(f);
5507 DisplayError(_("Cannot build game list"), error);
5508 } else if (!ListEmpty(&gameList) &&
5509 ((ListGame *) gameList.tailPred)->number > 1) {
5510 GameListPopUp(f, title);
5516 return LoadGame(f, gameNumber, title, FALSE);
5519 void LoadGameProc(w, event, prms, nprms)
5525 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5528 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
5531 void LoadNextGameProc(w, event, prms, nprms)
5540 void LoadPrevGameProc(w, event, prms, nprms)
5549 void ReloadGameProc(w, event, prms, nprms)
5558 void LoadNextPositionProc(w, event, prms, nprms)
5567 void LoadPrevPositionProc(w, event, prms, nprms)
5576 void ReloadPositionProc(w, event, prms, nprms)
5585 void LoadPositionProc(w, event, prms, nprms)
5591 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5594 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5597 void SaveGameProc(w, event, prms, nprms)
5603 FileNamePopUp(_("Save game file name?"),
5604 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5608 void SavePositionProc(w, event, prms, nprms)
5614 FileNamePopUp(_("Save position file name?"),
5615 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5619 void ReloadCmailMsgProc(w, event, prms, nprms)
5625 ReloadCmailMsgEvent(FALSE);
5628 void MailMoveProc(w, event, prms, nprms)
5637 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5638 static char *selected_fen_position=NULL;
5641 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5642 Atom *type_return, XtPointer *value_return,
5643 unsigned long *length_return, int *format_return)
5645 char *selection_tmp;
5647 if (!selected_fen_position) return False; /* should never happen */
5648 if (*target == XA_STRING){
5649 /* note: since no XtSelectionDoneProc was registered, Xt will
5650 * automatically call XtFree on the value returned. So have to
5651 * make a copy of it allocated with XtMalloc */
5652 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5653 strcpy(selection_tmp, selected_fen_position);
5655 *value_return=selection_tmp;
5656 *length_return=strlen(selection_tmp);
5657 *type_return=XA_STRING;
5658 *format_return = 8; /* bits per byte */
5665 /* note: when called from menu all parameters are NULL, so no clue what the
5666 * Widget which was clicked on was, or what the click event was
5668 void CopyPositionProc(w, event, prms, nprms)
5676 if (selected_fen_position) free(selected_fen_position);
5677 selected_fen_position = (char *)PositionToFEN(currentMove);
5678 if (!selected_fen_position) return;
5679 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5681 SendPositionSelection,
5682 NULL/* lose_ownership_proc */ ,
5683 NULL/* transfer_done_proc */);
5685 free(selected_fen_position);
5686 selected_fen_position=NULL;
5690 /* function called when the data to Paste is ready */
5692 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5693 Atom *type, XtPointer value, unsigned long *len, int *format)
5696 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5697 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5698 EditPositionPasteFEN(fenstr);
5702 /* called when Paste Position button is pressed,
5703 * all parameters will be NULL */
5704 void PastePositionProc(w, event, prms, nprms)
5710 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5711 /* (XtSelectionCallbackProc) */ PastePositionCB,
5712 NULL, /* client_data passed to PastePositionCB */
5714 /* better to use the time field from the event that triggered the
5715 * call to this function, but that isn't trivial to get
5723 SendGameSelection(Widget w, Atom *selection, Atom *target,
5724 Atom *type_return, XtPointer *value_return,
5725 unsigned long *length_return, int *format_return)
5727 char *selection_tmp;
5729 if (*target == XA_STRING){
5730 FILE* f = fopen(gameCopyFilename, "r");
5733 if (f == NULL) return False;
5737 selection_tmp = XtMalloc(len + 1);
5738 count = fread(selection_tmp, 1, len, f);
5740 XtFree(selection_tmp);
5743 selection_tmp[len] = NULLCHAR;
5744 *value_return = selection_tmp;
5745 *length_return = len;
5746 *type_return = XA_STRING;
5747 *format_return = 8; /* bits per byte */
5754 /* note: when called from menu all parameters are NULL, so no clue what the
5755 * Widget which was clicked on was, or what the click event was
5757 void CopyGameProc(w, event, prms, nprms)
5765 ret = SaveGameToFile(gameCopyFilename, FALSE);
5768 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5771 NULL/* lose_ownership_proc */ ,
5772 NULL/* transfer_done_proc */);
5775 /* function called when the data to Paste is ready */
5777 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5778 Atom *type, XtPointer value, unsigned long *len, int *format)
5781 if (value == NULL || *len == 0) {
5782 return; /* nothing had been selected to copy */
5784 f = fopen(gamePasteFilename, "w");
5786 DisplayError(_("Can't open temp file"), errno);
5789 fwrite(value, 1, *len, f);
5792 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5795 /* called when Paste Game button is pressed,
5796 * all parameters will be NULL */
5797 void PasteGameProc(w, event, prms, nprms)
5803 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5804 /* (XtSelectionCallbackProc) */ PasteGameCB,
5805 NULL, /* client_data passed to PasteGameCB */
5807 /* better to use the time field from the event that triggered the
5808 * call to this function, but that isn't trivial to get
5818 SaveGameProc(NULL, NULL, NULL, NULL);
5822 void QuitProc(w, event, prms, nprms)
5831 void PauseProc(w, event, prms, nprms)
5841 void MachineBlackProc(w, event, prms, nprms)
5847 MachineBlackEvent();
5850 void MachineWhiteProc(w, event, prms, nprms)
5856 MachineWhiteEvent();
5859 void AnalyzeModeProc(w, event, prms, nprms)
5867 if (!first.analysisSupport) {
5868 sprintf(buf, _("%s does not support analysis"), first.tidy);
5869 DisplayError(buf, 0);
5872 /* icsEngineAnalyze */
5873 if (appData.icsActive) {
5874 if (gameMode != IcsObserving) {
5875 sprintf(buf,_("You are not observing a game"));
5876 DisplayError(buf, 0);
5878 if (appData.icsEngineAnalyze) {
5879 if (appData.debugMode)
5880 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5881 appData.icsEngineAnalyze = FALSE;
5888 /* if enable, use want disable icsEngineAnalyze */
5889 if (appData.icsEngineAnalyze) {
5890 appData.icsEngineAnalyze = FALSE;
5895 appData.icsEngineAnalyze = TRUE;
5896 if (appData.debugMode)
5897 fprintf(debugFP, "ICS engine analyze starting... \n");
5900 if (!appData.showThinking)
5901 ShowThinkingProc(w,event,prms,nprms);
5905 void AnalyzeFileProc(w, event, prms, nprms)
5911 if (!first.analysisSupport) {
5913 sprintf(buf, _("%s does not support analysis"), first.tidy);
5914 DisplayError(buf, 0);
5919 if (!appData.showThinking)
5920 ShowThinkingProc(w,event,prms,nprms);
5923 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5924 AnalysisPeriodicEvent(1);
5927 void TwoMachinesProc(w, event, prms, nprms)
5936 void IcsClientProc(w, event, prms, nprms)
5945 void EditGameProc(w, event, prms, nprms)
5954 void EditPositionProc(w, event, prms, nprms)
5960 EditPositionEvent();
5963 void TrainingProc(w, event, prms, nprms)
5972 void EditCommentProc(w, event, prms, nprms)
5979 EditCommentPopDown();
5985 void IcsInputBoxProc(w, event, prms, nprms)
5991 if (ICSInputBoxUp) {
5992 ICSInputBoxPopDown();
5998 void AcceptProc(w, event, prms, nprms)
6007 void DeclineProc(w, event, prms, nprms)
6016 void RematchProc(w, event, prms, nprms)
6025 void CallFlagProc(w, event, prms, nprms)
6034 void DrawProc(w, event, prms, nprms)
6043 void AbortProc(w, event, prms, nprms)
6052 void AdjournProc(w, event, prms, nprms)
6061 void ResignProc(w, event, prms, nprms)
6070 void EnterKeyProc(w, event, prms, nprms)
6076 if (ICSInputBoxUp == True)
6080 void StopObservingProc(w, event, prms, nprms)
6086 StopObservingEvent();
6089 void StopExaminingProc(w, event, prms, nprms)
6095 StopExaminingEvent();
6099 void ForwardProc(w, event, prms, nprms)
6109 void BackwardProc(w, event, prms, nprms)
6118 void ToStartProc(w, event, prms, nprms)
6127 void ToEndProc(w, event, prms, nprms)
6136 void RevertProc(w, event, prms, nprms)
6145 void TruncateGameProc(w, event, prms, nprms)
6151 TruncateGameEvent();
6153 void RetractMoveProc(w, event, prms, nprms)
6162 void MoveNowProc(w, event, prms, nprms)
6172 void AlwaysQueenProc(w, event, prms, nprms)
6180 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6182 if (appData.alwaysPromoteToQueen) {
6183 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6185 XtSetArg(args[0], XtNleftBitmap, None);
6187 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6191 void AnimateDraggingProc(w, event, prms, nprms)
6199 appData.animateDragging = !appData.animateDragging;
6201 if (appData.animateDragging) {
6202 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6205 XtSetArg(args[0], XtNleftBitmap, None);
6207 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6211 void AnimateMovingProc(w, event, prms, nprms)
6219 appData.animate = !appData.animate;
6221 if (appData.animate) {
6222 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6225 XtSetArg(args[0], XtNleftBitmap, None);
6227 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6231 void AutocommProc(w, event, prms, nprms)
6239 appData.autoComment = !appData.autoComment;
6241 if (appData.autoComment) {
6242 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6244 XtSetArg(args[0], XtNleftBitmap, None);
6246 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6251 void AutoflagProc(w, event, prms, nprms)
6259 appData.autoCallFlag = !appData.autoCallFlag;
6261 if (appData.autoCallFlag) {
6262 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6264 XtSetArg(args[0], XtNleftBitmap, None);
6266 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6270 void AutoflipProc(w, event, prms, nprms)
6278 appData.autoFlipView = !appData.autoFlipView;
6280 if (appData.autoFlipView) {
6281 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6283 XtSetArg(args[0], XtNleftBitmap, None);
6285 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6289 void AutobsProc(w, event, prms, nprms)
6297 appData.autoObserve = !appData.autoObserve;
6299 if (appData.autoObserve) {
6300 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6302 XtSetArg(args[0], XtNleftBitmap, None);
6304 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6308 void AutoraiseProc(w, event, prms, nprms)
6316 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6318 if (appData.autoRaiseBoard) {
6319 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6321 XtSetArg(args[0], XtNleftBitmap, None);
6323 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6327 void AutosaveProc(w, event, prms, nprms)
6335 appData.autoSaveGames = !appData.autoSaveGames;
6337 if (appData.autoSaveGames) {
6338 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6340 XtSetArg(args[0], XtNleftBitmap, None);
6342 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6346 void BlindfoldProc(w, event, prms, nprms)
6354 appData.blindfold = !appData.blindfold;
6356 if (appData.blindfold) {
6357 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6359 XtSetArg(args[0], XtNleftBitmap, None);
6361 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6364 DrawPosition(True, NULL);
6367 void TestLegalityProc(w, event, prms, nprms)
6375 appData.testLegality = !appData.testLegality;
6377 if (appData.testLegality) {
6378 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6380 XtSetArg(args[0], XtNleftBitmap, None);
6382 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6387 void FlashMovesProc(w, event, prms, nprms)
6395 if (appData.flashCount == 0) {
6396 appData.flashCount = 3;
6398 appData.flashCount = -appData.flashCount;
6401 if (appData.flashCount > 0) {
6402 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6404 XtSetArg(args[0], XtNleftBitmap, None);
6406 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6410 void FlipViewProc(w, event, prms, nprms)
6416 flipView = !flipView;
6417 DrawPosition(True, NULL);
6420 void GetMoveListProc(w, event, prms, nprms)
6428 appData.getMoveList = !appData.getMoveList;
6430 if (appData.getMoveList) {
6431 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6434 XtSetArg(args[0], XtNleftBitmap, None);
6436 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6441 void HighlightDraggingProc(w, event, prms, nprms)
6449 appData.highlightDragging = !appData.highlightDragging;
6451 if (appData.highlightDragging) {
6452 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6454 XtSetArg(args[0], XtNleftBitmap, None);
6456 XtSetValues(XtNameToWidget(menuBarWidget,
6457 "menuOptions.Highlight Dragging"), args, 1);
6461 void HighlightLastMoveProc(w, event, prms, nprms)
6469 appData.highlightLastMove = !appData.highlightLastMove;
6471 if (appData.highlightLastMove) {
6472 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6474 XtSetArg(args[0], XtNleftBitmap, None);
6476 XtSetValues(XtNameToWidget(menuBarWidget,
6477 "menuOptions.Highlight Last Move"), args, 1);
6480 void IcsAlarmProc(w, event, prms, nprms)
6488 appData.icsAlarm = !appData.icsAlarm;
6490 if (appData.icsAlarm) {
6491 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6493 XtSetArg(args[0], XtNleftBitmap, None);
6495 XtSetValues(XtNameToWidget(menuBarWidget,
6496 "menuOptions.ICS Alarm"), args, 1);
6499 void MoveSoundProc(w, event, prms, nprms)
6507 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6509 if (appData.ringBellAfterMoves) {
6510 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6512 XtSetArg(args[0], XtNleftBitmap, None);
6514 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6519 void OldSaveStyleProc(w, event, prms, nprms)
6527 appData.oldSaveStyle = !appData.oldSaveStyle;
6529 if (appData.oldSaveStyle) {
6530 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6532 XtSetArg(args[0], XtNleftBitmap, None);
6534 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6538 void PeriodicUpdatesProc(w, event, prms, nprms)
6546 PeriodicUpdatesEvent(!appData.periodicUpdates);
6548 if (appData.periodicUpdates) {
6549 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6551 XtSetArg(args[0], XtNleftBitmap, None);
6553 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6557 void PonderNextMoveProc(w, event, prms, nprms)
6565 PonderNextMoveEvent(!appData.ponderNextMove);
6567 if (appData.ponderNextMove) {
6568 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6570 XtSetArg(args[0], XtNleftBitmap, None);
6572 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6576 void PopupExitMessageProc(w, event, prms, nprms)
6584 appData.popupExitMessage = !appData.popupExitMessage;
6586 if (appData.popupExitMessage) {
6587 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6589 XtSetArg(args[0], XtNleftBitmap, None);
6591 XtSetValues(XtNameToWidget(menuBarWidget,
6592 "menuOptions.Popup Exit Message"), args, 1);
6595 void PopupMoveErrorsProc(w, event, prms, nprms)
6603 appData.popupMoveErrors = !appData.popupMoveErrors;
6605 if (appData.popupMoveErrors) {
6606 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6608 XtSetArg(args[0], XtNleftBitmap, None);
6610 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6614 void PremoveProc(w, event, prms, nprms)
6622 appData.premove = !appData.premove;
6624 if (appData.premove) {
6625 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6627 XtSetArg(args[0], XtNleftBitmap, None);
6629 XtSetValues(XtNameToWidget(menuBarWidget,
6630 "menuOptions.Premove"), args, 1);
6633 void QuietPlayProc(w, event, prms, nprms)
6641 appData.quietPlay = !appData.quietPlay;
6643 if (appData.quietPlay) {
6644 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6646 XtSetArg(args[0], XtNleftBitmap, None);
6648 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6652 void ShowCoordsProc(w, event, prms, nprms)
6660 appData.showCoords = !appData.showCoords;
6662 if (appData.showCoords) {
6663 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6665 XtSetArg(args[0], XtNleftBitmap, None);
6667 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6670 DrawPosition(True, NULL);
6673 void ShowThinkingProc(w, event, prms, nprms)
6681 ShowThinkingEvent(!appData.showThinking);
6683 if (appData.showThinking) {
6684 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6686 XtSetArg(args[0], XtNleftBitmap, None);
6688 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6692 void InfoProc(w, event, prms, nprms)
6699 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6704 void ManProc(w, event, prms, nprms)
6712 if (nprms && *nprms > 0)
6716 sprintf(buf, "xterm -e man %s &", name);
6720 void HintProc(w, event, prms, nprms)
6729 void BookProc(w, event, prms, nprms)
6738 void AboutProc(w, event, prms, nprms)
6746 char *zippy = " (with Zippy code)";
6750 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6751 programVersion, zippy,
6752 "Copyright 1991 Digital Equipment Corporation",
6753 "Enhancements Copyright 1992-2001 Free Software Foundation",
6754 PRODUCT, " is free software and carries NO WARRANTY;",
6755 "see the file COPYING for more information.");
6756 ErrorPopUp(_("About XBoard"), buf, FALSE);
6759 void DebugProc(w, event, prms, nprms)
6765 appData.debugMode = !appData.debugMode;
6768 void AboutGameProc(w, event, prms, nprms)
6777 void NothingProc(w, event, prms, nprms)
6786 void Iconify(w, event, prms, nprms)
6795 XtSetArg(args[0], XtNiconic, True);
6796 XtSetValues(shellWidget, args, 1);
6799 void DisplayMessage(message, extMessage)
6800 char *message, *extMessage;
6807 sprintf(buf, "%s %s", message, extMessage);
6810 message = extMessage;
6813 XtSetArg(arg, XtNlabel, message);
6814 XtSetValues(messageWidget, &arg, 1);
6817 void DisplayTitle(text)
6822 char title[MSG_SIZ];
6825 if (text == NULL) text = "";
6827 if (appData.titleInWindow) {
6829 XtSetArg(args[i], XtNlabel, text); i++;
6830 XtSetValues(titleWidget, args, i);
6833 if (*text != NULLCHAR) {
6835 strcpy(title, text);
6836 } else if (appData.icsActive) {
6837 sprintf(icon, "%s", appData.icsHost);
6838 sprintf(title, "%s: %s", programName, appData.icsHost);
6839 } else if (appData.cmailGameName[0] != NULLCHAR) {
6840 sprintf(icon, "%s", "CMail");
6841 sprintf(title, "%s: %s", programName, "CMail");
6842 } else if (appData.noChessProgram) {
6843 strcpy(icon, programName);
6844 strcpy(title, programName);
6846 strcpy(icon, first.tidy);
6847 sprintf(title, "%s: %s", programName, first.tidy);
6850 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6851 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6852 XtSetValues(shellWidget, args, i);
6856 void DisplayError(message, error)
6863 if (appData.debugMode || appData.matchMode) {
6864 fprintf(stderr, "%s: %s\n", programName, message);
6867 if (appData.debugMode || appData.matchMode) {
6868 fprintf(stderr, "%s: %s: %s\n",
6869 programName, message, strerror(error));
6871 sprintf(buf, "%s: %s", message, strerror(error));
6874 ErrorPopUp(_("Error"), message, FALSE);
6878 void DisplayMoveError(message)
6883 DrawPosition(FALSE, NULL);
6884 if (appData.debugMode || appData.matchMode) {
6885 fprintf(stderr, "%s: %s\n", programName, message);
6887 if (appData.popupMoveErrors) {
6888 ErrorPopUp(_("Error"), message, FALSE);
6890 DisplayMessage(message, "");
6895 void DisplayFatalError(message, error, status)
6901 errorExitStatus = status;
6903 fprintf(stderr, "%s: %s\n", programName, message);
6905 fprintf(stderr, "%s: %s: %s\n",
6906 programName, message, strerror(error));
6907 sprintf(buf, "%s: %s", message, strerror(error));
6910 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6911 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6917 void DisplayInformation(message)
6921 ErrorPopUp(_("Information"), message, TRUE);
6924 void DisplayNote(message)
6928 ErrorPopUp(_("Note"), message, FALSE);
6932 NullXErrorCheck(dpy, error_event)
6934 XErrorEvent *error_event;
6939 void DisplayIcsInteractionTitle(message)
6942 if (oldICSInteractionTitle == NULL) {
6943 /* Magic to find the old window title, adapted from vim */
6944 char *wina = getenv("WINDOWID");
6946 Window win = (Window) atoi(wina);
6947 Window root, parent, *children;
6948 unsigned int nchildren;
6949 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6951 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6952 if (!XQueryTree(xDisplay, win, &root, &parent,
6953 &children, &nchildren)) break;
6954 if (children) XFree((void *)children);
6955 if (parent == root || parent == 0) break;
6958 XSetErrorHandler(oldHandler);
6960 if (oldICSInteractionTitle == NULL) {
6961 oldICSInteractionTitle = "xterm";
6964 printf("\033]0;%s\007", message);
6968 char pendingReplyPrefix[MSG_SIZ];
6969 ProcRef pendingReplyPR;
6971 void AskQuestionProc(w, event, prms, nprms)
6978 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6982 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6985 void AskQuestionPopDown()
6987 if (!askQuestionUp) return;
6988 XtPopdown(askQuestionShell);
6989 XtDestroyWidget(askQuestionShell);
6990 askQuestionUp = False;
6993 void AskQuestionReplyAction(w, event, prms, nprms)
7003 reply = XawDialogGetValueString(w = XtParent(w));
7004 strcpy(buf, pendingReplyPrefix);
7005 if (*buf) strcat(buf, " ");
7008 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7009 AskQuestionPopDown();
7011 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7014 void AskQuestionCallback(w, client_data, call_data)
7016 XtPointer client_data, call_data;
7021 XtSetArg(args[0], XtNlabel, &name);
7022 XtGetValues(w, args, 1);
7024 if (strcmp(name, _("cancel")) == 0) {
7025 AskQuestionPopDown();
7027 AskQuestionReplyAction(w, NULL, NULL, NULL);
7031 void AskQuestion(title, question, replyPrefix, pr)
7032 char *title, *question, *replyPrefix;
7036 Widget popup, layout, dialog, edit;
7042 strcpy(pendingReplyPrefix, replyPrefix);
7043 pendingReplyPR = pr;
7046 XtSetArg(args[i], XtNresizable, True); i++;
7047 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7048 askQuestionShell = popup =
7049 XtCreatePopupShell(title, transientShellWidgetClass,
7050 shellWidget, args, i);
7053 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7054 layoutArgs, XtNumber(layoutArgs));
7057 XtSetArg(args[i], XtNlabel, question); i++;
7058 XtSetArg(args[i], XtNvalue, ""); i++;
7059 XtSetArg(args[i], XtNborderWidth, 0); i++;
7060 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7063 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7064 (XtPointer) dialog);
7065 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7066 (XtPointer) dialog);
7068 XtRealizeWidget(popup);
7069 CatchDeleteWindow(popup, "AskQuestionPopDown");
7071 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7072 &x, &y, &win_x, &win_y, &mask);
7074 XtSetArg(args[0], XtNx, x - 10);
7075 XtSetArg(args[1], XtNy, y - 30);
7076 XtSetValues(popup, args, 2);
7078 XtPopup(popup, XtGrabExclusive);
7079 askQuestionUp = True;
7081 edit = XtNameToWidget(dialog, "*value");
7082 XtSetKeyboardFocus(popup, edit);
7090 if (*name == NULLCHAR) {
7092 } else if (strcmp(name, "$") == 0) {
7093 putc(BELLCHAR, stderr);
7096 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7104 PlaySound(appData.soundMove);
7110 PlaySound(appData.soundIcsWin);
7116 PlaySound(appData.soundIcsLoss);
7122 PlaySound(appData.soundIcsDraw);
7126 PlayIcsUnfinishedSound()
7128 PlaySound(appData.soundIcsUnfinished);
7134 PlaySound(appData.soundIcsAlarm);
7140 system("stty echo");
7146 system("stty -echo");
7150 Colorize(cc, continuation)
7155 int count, outCount, error;
7157 if (textColors[(int)cc].bg > 0) {
7158 if (textColors[(int)cc].fg > 0) {
7159 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7160 textColors[(int)cc].fg, textColors[(int)cc].bg);
7162 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7163 textColors[(int)cc].bg);
7166 if (textColors[(int)cc].fg > 0) {
7167 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7168 textColors[(int)cc].fg);
7170 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7173 count = strlen(buf);
7174 outCount = OutputToProcess(NoProc, buf, count, &error);
7175 if (outCount < count) {
7176 DisplayFatalError(_("Error writing to display"), error, 1);
7179 if (continuation) return;
7182 PlaySound(appData.soundShout);
7185 PlaySound(appData.soundSShout);
7188 PlaySound(appData.soundChannel1);
7191 PlaySound(appData.soundChannel);
7194 PlaySound(appData.soundKibitz);
7197 PlaySound(appData.soundTell);
7199 case ColorChallenge:
7200 PlaySound(appData.soundChallenge);
7203 PlaySound(appData.soundRequest);
7206 PlaySound(appData.soundSeek);
7217 return getpwuid(getuid())->pw_name;
7220 static char *ExpandPathName(path)
7223 static char static_buf[2000];
7224 char *d, *s, buf[2000];
7230 while (*s && isspace(*s))
7239 if (*(s+1) == '/') {
7240 strcpy(d, getpwuid(getuid())->pw_dir);
7245 *strchr(buf, '/') = 0;
7246 pwd = getpwnam(buf);
7249 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7253 strcpy(d, pwd->pw_dir);
7254 strcat(d, strchr(s+1, '/'));
7265 static char host_name[MSG_SIZ];
7267 #if HAVE_GETHOSTNAME
7268 gethostname(host_name, MSG_SIZ);
7270 #else /* not HAVE_GETHOSTNAME */
7271 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7272 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7274 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7276 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7277 #endif /* not HAVE_GETHOSTNAME */
7280 XtIntervalId delayedEventTimerXID = 0;
7281 DelayedEventCallback delayedEventCallback = 0;
7286 delayedEventTimerXID = 0;
7287 delayedEventCallback();
7291 ScheduleDelayedEvent(cb, millisec)
7292 DelayedEventCallback cb; long millisec;
7294 delayedEventCallback = cb;
7295 delayedEventTimerXID =
7296 XtAppAddTimeOut(appContext, millisec,
7297 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7300 DelayedEventCallback
7303 if (delayedEventTimerXID) {
7304 return delayedEventCallback;
7311 CancelDelayedEvent()
7313 if (delayedEventTimerXID) {
7314 XtRemoveTimeOut(delayedEventTimerXID);
7315 delayedEventTimerXID = 0;
7319 XtIntervalId loadGameTimerXID = 0;
7321 int LoadGameTimerRunning()
7323 return loadGameTimerXID != 0;
7326 int StopLoadGameTimer()
7328 if (loadGameTimerXID != 0) {
7329 XtRemoveTimeOut(loadGameTimerXID);
7330 loadGameTimerXID = 0;
7338 LoadGameTimerCallback(arg, id)
7342 loadGameTimerXID = 0;
7347 StartLoadGameTimer(millisec)
7351 XtAppAddTimeOut(appContext, millisec,
7352 (XtTimerCallbackProc) LoadGameTimerCallback,
7356 XtIntervalId analysisClockXID = 0;
7359 AnalysisClockCallback(arg, id)
7363 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7364 || appData.icsEngineAnalyze) {
7365 AnalysisPeriodicEvent(0);
7366 StartAnalysisClock();
7371 StartAnalysisClock()
7374 XtAppAddTimeOut(appContext, 2000,
7375 (XtTimerCallbackProc) AnalysisClockCallback,
7379 XtIntervalId clockTimerXID = 0;
7381 int ClockTimerRunning()
7383 return clockTimerXID != 0;
7386 int StopClockTimer()
7388 if (clockTimerXID != 0) {
7389 XtRemoveTimeOut(clockTimerXID);
7398 ClockTimerCallback(arg, id)
7407 StartClockTimer(millisec)
7411 XtAppAddTimeOut(appContext, millisec,
7412 (XtTimerCallbackProc) ClockTimerCallback,
7417 DisplayTimerLabel(w, color, timer, highlight)
7426 if (appData.clockMode) {
7427 sprintf(buf, "%s: %s", color, TimeString(timer));
7428 XtSetArg(args[0], XtNlabel, buf);
7430 sprintf(buf, "%s ", color);
7431 XtSetArg(args[0], XtNlabel, buf);
7435 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7436 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7438 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7439 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7442 XtSetValues(w, args, 3);
7446 DisplayWhiteClock(timeRemaining, highlight)
7451 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
7452 if (highlight && iconPixmap == bIconPixmap) {
7453 iconPixmap = wIconPixmap;
7454 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7455 XtSetValues(shellWidget, args, 1);
7460 DisplayBlackClock(timeRemaining, highlight)
7465 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
7466 if (highlight && iconPixmap == wIconPixmap) {
7467 iconPixmap = bIconPixmap;
7468 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7469 XtSetValues(shellWidget, args, 1);
7487 int StartChildProcess(cmdLine, dir, pr)
7494 int to_prog[2], from_prog[2];
7498 if (appData.debugMode) {
7499 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7502 /* We do NOT feed the cmdLine to the shell; we just
7503 parse it into blank-separated arguments in the
7504 most simple-minded way possible.
7507 strcpy(buf, cmdLine);
7512 if (p == NULL) break;
7517 SetUpChildIO(to_prog, from_prog);
7519 if ((pid = fork()) == 0) {
7521 dup2(to_prog[0], 0);
7522 dup2(from_prog[1], 1);
7525 close(from_prog[0]);
7526 close(from_prog[1]);
7527 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7529 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7534 execvp(argv[0], argv);
7536 /* If we get here, exec failed */
7541 /* Parent process */
7543 close(from_prog[1]);
7545 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7548 cp->fdFrom = from_prog[0];
7549 cp->fdTo = to_prog[1];
7555 DestroyChildProcess(pr, signal)
7559 ChildProc *cp = (ChildProc *) pr;
7561 if (cp->kind != CPReal) return;
7564 kill(cp->pid, SIGTERM);
7566 /* Process is exiting either because of the kill or because of
7567 a quit command sent by the backend; either way, wait for it to die.
7575 InterruptChildProcess(pr)
7578 ChildProc *cp = (ChildProc *) pr;
7580 if (cp->kind != CPReal) return;
7581 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7584 int OpenTelnet(host, port, pr)
7589 char cmdLine[MSG_SIZ];
7591 if (port[0] == NULLCHAR) {
7592 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7594 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7596 return StartChildProcess(cmdLine, "", pr);
7599 int OpenTCP(host, port, pr)
7605 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7606 #else /* !OMIT_SOCKETS */
7608 struct sockaddr_in sa;
7610 unsigned short uport;
7613 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7617 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7618 sa.sin_family = AF_INET;
7619 sa.sin_addr.s_addr = INADDR_ANY;
7620 uport = (unsigned short) 0;
7621 sa.sin_port = htons(uport);
7622 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7626 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7627 if (!(hp = gethostbyname(host))) {
7629 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7630 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7631 hp->h_addrtype = AF_INET;
7633 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7634 hp->h_addr_list[0] = (char *) malloc(4);
7635 hp->h_addr_list[0][0] = b0;
7636 hp->h_addr_list[0][1] = b1;
7637 hp->h_addr_list[0][2] = b2;
7638 hp->h_addr_list[0][3] = b3;
7643 sa.sin_family = hp->h_addrtype;
7644 uport = (unsigned short) atoi(port);
7645 sa.sin_port = htons(uport);
7646 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7648 if (connect(s, (struct sockaddr *) &sa,
7649 sizeof(struct sockaddr_in)) < 0) {
7653 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7660 #endif /* !OMIT_SOCKETS */
7665 int OpenCommPort(name, pr)
7672 fd = open(name, 2, 0);
7673 if (fd < 0) return errno;
7675 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7685 int OpenLoopback(pr)
7691 SetUpChildIO(to, from);
7693 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7696 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7703 int OpenRcmd(host, user, cmd, pr)
7704 char *host, *user, *cmd;
7707 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7711 #define INPUT_SOURCE_BUF_SIZE 8192
7720 char buf[INPUT_SOURCE_BUF_SIZE];
7725 DoInputCallback(closure, source, xid)
7730 InputSource *is = (InputSource *) closure;
7735 if (is->lineByLine) {
7736 count = read(is->fd, is->unused,
7737 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7739 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7742 is->unused += count;
7744 while (p < is->unused) {
7745 q = memchr(p, '\n', is->unused - p);
7746 if (q == NULL) break;
7748 (is->func)(is, is->closure, p, q - p, 0);
7752 while (p < is->unused) {
7757 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7762 (is->func)(is, is->closure, is->buf, count, error);
7766 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7773 ChildProc *cp = (ChildProc *) pr;
7775 is = (InputSource *) calloc(1, sizeof(InputSource));
7776 is->lineByLine = lineByLine;
7780 is->fd = fileno(stdin);
7782 is->kind = cp->kind;
7783 is->fd = cp->fdFrom;
7786 is->unused = is->buf;
7789 is->xid = XtAppAddInput(appContext, is->fd,
7790 (XtPointer) (XtInputReadMask),
7791 (XtInputCallbackProc) DoInputCallback,
7793 is->closure = closure;
7794 return (InputSourceRef) is;
7798 RemoveInputSource(isr)
7801 InputSource *is = (InputSource *) isr;
7803 if (is->xid == 0) return;
7804 XtRemoveInput(is->xid);
7808 int OutputToProcess(pr, message, count, outError)
7814 ChildProc *cp = (ChildProc *) pr;
7818 outCount = fwrite(message, 1, count, stdout);
7820 outCount = write(cp->fdTo, message, count);
7830 /* Output message to process, with "ms" milliseconds of delay
7831 between each character. This is needed when sending the logon
7832 script to ICC, which for some reason doesn't like the
7833 instantaneous send. */
7834 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7841 ChildProc *cp = (ChildProc *) pr;
7846 r = write(cp->fdTo, message++, 1);
7859 /**** Animation code by Hugh Fisher, DCS, ANU.
7861 Known problem: if a window overlapping the board is
7862 moved away while a piece is being animated underneath,
7863 the newly exposed area won't be updated properly.
7864 I can live with this.
7866 Known problem: if you look carefully at the animation
7867 of pieces in mono mode, they are being drawn as solid
7868 shapes without interior detail while moving. Fixing
7869 this would be a major complication for minimal return.
7872 /* Masks for XPM pieces. Black and white pieces can have
7873 different shapes, but in the interest of retaining my
7874 sanity pieces must have the same outline on both light
7875 and dark squares, and all pieces must use the same
7876 background square colors/images. */
7879 CreateAnimMasks (pieceDepth)
7886 unsigned long plane;
7889 /* Need a bitmap just to get a GC with right depth */
7890 buf = XCreatePixmap(xDisplay, xBoardWindow,
7892 values.foreground = 1;
7893 values.background = 0;
7894 /* Don't use XtGetGC, not read only */
7895 maskGC = XCreateGC(xDisplay, buf,
7896 GCForeground | GCBackground, &values);
7897 XFreePixmap(xDisplay, buf);
7899 buf = XCreatePixmap(xDisplay, xBoardWindow,
7900 squareSize, squareSize, pieceDepth);
7901 values.foreground = XBlackPixel(xDisplay, xScreen);
7902 values.background = XWhitePixel(xDisplay, xScreen);
7903 bufGC = XCreateGC(xDisplay, buf,
7904 GCForeground | GCBackground, &values);
7906 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7907 /* Begin with empty mask */
7908 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7909 squareSize, squareSize, 1);
7910 XSetFunction(xDisplay, maskGC, GXclear);
7911 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7912 0, 0, squareSize, squareSize);
7914 /* Take a copy of the piece */
7919 XSetFunction(xDisplay, bufGC, GXcopy);
7920 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7922 0, 0, squareSize, squareSize, 0, 0);
7924 /* XOR the background (light) over the piece */
7925 XSetFunction(xDisplay, bufGC, GXxor);
7927 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7928 0, 0, squareSize, squareSize, 0, 0);
7930 XSetForeground(xDisplay, bufGC, lightSquareColor);
7931 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7934 /* We now have an inverted piece image with the background
7935 erased. Construct mask by just selecting all the non-zero
7936 pixels - no need to reconstruct the original image. */
7937 XSetFunction(xDisplay, maskGC, GXor);
7939 /* Might be quicker to download an XImage and create bitmap
7940 data from it rather than this N copies per piece, but it
7941 only takes a fraction of a second and there is a much
7942 longer delay for loading the pieces. */
7943 for (n = 0; n < pieceDepth; n ++) {
7944 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7945 0, 0, squareSize, squareSize,
7951 XFreePixmap(xDisplay, buf);
7952 XFreeGC(xDisplay, bufGC);
7953 XFreeGC(xDisplay, maskGC);
7957 InitAnimState (anim, info)
7959 XWindowAttributes * info;
7964 /* Each buffer is square size, same depth as window */
7965 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7966 squareSize, squareSize, info->depth);
7967 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7968 squareSize, squareSize, info->depth);
7970 /* Create a plain GC for blitting */
7971 mask = GCForeground | GCBackground | GCFunction |
7972 GCPlaneMask | GCGraphicsExposures;
7973 values.foreground = XBlackPixel(xDisplay, xScreen);
7974 values.background = XWhitePixel(xDisplay, xScreen);
7975 values.function = GXcopy;
7976 values.plane_mask = AllPlanes;
7977 values.graphics_exposures = False;
7978 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7980 /* Piece will be copied from an existing context at
7981 the start of each new animation/drag. */
7982 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7984 /* Outline will be a read-only copy of an existing */
7985 anim->outlineGC = None;
7991 static int done = 0;
7992 XWindowAttributes info;
7996 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7998 InitAnimState(&game, &info);
7999 InitAnimState(&player, &info);
8001 /* For XPM pieces, we need bitmaps to use as masks. */
8003 CreateAnimMasks(info.depth);
8008 static Boolean frameWaiting;
8010 static RETSIGTYPE FrameAlarm (sig)
8013 frameWaiting = False;
8014 /* In case System-V style signals. Needed?? */
8015 signal(SIGALRM, FrameAlarm);
8022 struct itimerval delay;
8024 XSync(xDisplay, False);
8027 frameWaiting = True;
8028 signal(SIGALRM, FrameAlarm);
8029 delay.it_interval.tv_sec =
8030 delay.it_value.tv_sec = time / 1000;
8031 delay.it_interval.tv_usec =
8032 delay.it_value.tv_usec = (time % 1000) * 1000;
8033 setitimer(ITIMER_REAL, &delay, NULL);
8035 /* Ugh -- busy-wait! --tpm */
8036 while (frameWaiting);
8038 while (frameWaiting) pause();
8040 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8041 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8042 setitimer(ITIMER_REAL, &delay, NULL);
8052 XSync(xDisplay, False);
8054 usleep(time * 1000);
8059 /* Convert board position to corner of screen rect and color */
8062 ScreenSquare(column, row, pt, color)
8063 int column; int row; XPoint * pt; int * color;
8066 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
8067 pt->y = lineGap + row * (squareSize + lineGap);
8069 pt->x = lineGap + column * (squareSize + lineGap);
8070 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
8072 *color = ((column + row) % 2) == 1;
8075 /* Convert window coords to square */
8078 BoardSquare(x, y, column, row)
8079 int x; int y; int * column; int * row;
8081 *column = EventToSquare(x, BOARD_SIZE);
8082 if (flipView && *column >= 0)
8083 *column = BOARD_SIZE - 1 - *column;
8084 *row = EventToSquare(y, BOARD_SIZE);
8085 if (!flipView && *row >= 0)
8086 *row = BOARD_SIZE - 1 - *row;
8091 #undef Max /* just in case */
8093 #define Max(a, b) ((a) > (b) ? (a) : (b))
8094 #define Min(a, b) ((a) < (b) ? (a) : (b))
8097 SetRect(rect, x, y, width, height)
8098 XRectangle * rect; int x; int y; int width; int height;
8102 rect->width = width;
8103 rect->height = height;
8106 /* Test if two frames overlap. If they do, return
8107 intersection rect within old and location of
8108 that rect within new. */
8111 Intersect(old, new, size, area, pt)
8112 XPoint * old; XPoint * new;
8113 int size; XRectangle * area; XPoint * pt;
8115 if (old->x > new->x + size || new->x > old->x + size ||
8116 old->y > new->y + size || new->y > old->y + size) {
8119 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8120 size - abs(old->x - new->x), size - abs(old->y - new->y));
8121 pt->x = Max(old->x - new->x, 0);
8122 pt->y = Max(old->y - new->y, 0);
8127 /* For two overlapping frames, return the rect(s)
8128 in the old that do not intersect with the new. */
8131 CalcUpdateRects(old, new, size, update, nUpdates)
8132 XPoint * old; XPoint * new; int size;
8133 XRectangle update[]; int * nUpdates;
8137 /* If old = new (shouldn't happen) then nothing to draw */
8138 if (old->x == new->x && old->y == new->y) {
8142 /* Work out what bits overlap. Since we know the rects
8143 are the same size we don't need a full intersect calc. */
8145 /* Top or bottom edge? */
8146 if (new->y > old->y) {
8147 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8149 } else if (old->y > new->y) {
8150 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8151 size, old->y - new->y);
8154 /* Left or right edge - don't overlap any update calculated above. */
8155 if (new->x > old->x) {
8156 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8157 new->x - old->x, size - abs(new->y - old->y));
8159 } else if (old->x > new->x) {
8160 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8161 old->x - new->x, size - abs(new->y - old->y));
8168 /* Generate a series of frame coords from start->mid->finish.
8169 The movement rate doubles until the half way point is
8170 reached, then halves back down to the final destination,
8171 which gives a nice slow in/out effect. The algorithmn
8172 may seem to generate too many intermediates for short
8173 moves, but remember that the purpose is to attract the
8174 viewers attention to the piece about to be moved and
8175 then to where it ends up. Too few frames would be less
8179 Tween(start, mid, finish, factor, frames, nFrames)
8180 XPoint * start; XPoint * mid;
8181 XPoint * finish; int factor;
8182 XPoint frames[]; int * nFrames;
8184 int fraction, n, count;
8188 /* Slow in, stepping 1/16th, then 1/8th, ... */
8190 for (n = 0; n < factor; n++)
8192 for (n = 0; n < factor; n++) {
8193 frames[count].x = start->x + (mid->x - start->x) / fraction;
8194 frames[count].y = start->y + (mid->y - start->y) / fraction;
8196 fraction = fraction / 2;
8200 frames[count] = *mid;
8203 /* Slow out, stepping 1/2, then 1/4, ... */
8205 for (n = 0; n < factor; n++) {
8206 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8207 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8209 fraction = fraction * 2;
8214 /* Draw a piece on the screen without disturbing what's there */
8217 SelectGCMask(piece, clip, outline, mask)
8218 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8222 /* Bitmap for piece being moved. */
8223 if (appData.monoMode) {
8224 *mask = *pieceToSolid(piece);
8225 } else if (useImages) {
8227 *mask = xpmMask[piece];
8229 *mask = ximMaskPm[piece%6];
8232 *mask = *pieceToSolid(piece);
8235 /* GC for piece being moved. Square color doesn't matter, but
8236 since it gets modified we make a copy of the original. */
8238 if (appData.monoMode)
8243 if (appData.monoMode)
8248 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8250 /* Outline only used in mono mode and is not modified */
8252 *outline = bwPieceGC;
8254 *outline = wbPieceGC;
8258 OverlayPiece(piece, clip, outline, dest)
8259 ChessSquare piece; GC clip; GC outline; Drawable dest;
8264 /* Draw solid rectangle which will be clipped to shape of piece */
8265 XFillRectangle(xDisplay, dest, clip,
8266 0, 0, squareSize, squareSize);
8267 if (appData.monoMode)
8268 /* Also draw outline in contrasting color for black
8269 on black / white on white cases */
8270 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8271 0, 0, squareSize, squareSize, 0, 0, 1);
8273 /* Copy the piece */
8278 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8280 0, 0, squareSize, squareSize,
8285 /* Animate the movement of a single piece */
8288 BeginAnimation(anim, piece, startColor, start)
8296 /* The old buffer is initialised with the start square (empty) */
8297 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8298 anim->prevFrame = *start;
8300 /* The piece will be drawn using its own bitmap as a matte */
8301 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8302 XSetClipMask(xDisplay, anim->pieceGC, mask);
8306 AnimationFrame(anim, frame, piece)
8311 XRectangle updates[4];
8316 /* Save what we are about to draw into the new buffer */
8317 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8318 frame->x, frame->y, squareSize, squareSize,
8321 /* Erase bits of the previous frame */
8322 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8323 /* Where the new frame overlapped the previous,
8324 the contents in newBuf are wrong. */
8325 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8326 overlap.x, overlap.y,
8327 overlap.width, overlap.height,
8329 /* Repaint the areas in the old that don't overlap new */
8330 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8331 for (i = 0; i < count; i++)
8332 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8333 updates[i].x - anim->prevFrame.x,
8334 updates[i].y - anim->prevFrame.y,
8335 updates[i].width, updates[i].height,
8336 updates[i].x, updates[i].y);
8338 /* Easy when no overlap */
8339 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8340 0, 0, squareSize, squareSize,
8341 anim->prevFrame.x, anim->prevFrame.y);
8344 /* Save this frame for next time round */
8345 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8346 0, 0, squareSize, squareSize,
8348 anim->prevFrame = *frame;
8350 /* Draw piece over original screen contents, not current,
8351 and copy entire rect. Wipes out overlapping piece images. */
8352 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8353 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8354 0, 0, squareSize, squareSize,
8355 frame->x, frame->y);
8359 EndAnimation (anim, finish)
8363 XRectangle updates[4];
8368 /* The main code will redraw the final square, so we
8369 only need to erase the bits that don't overlap. */
8370 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8371 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8372 for (i = 0; i < count; i++)
8373 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8374 updates[i].x - anim->prevFrame.x,
8375 updates[i].y - anim->prevFrame.y,
8376 updates[i].width, updates[i].height,
8377 updates[i].x, updates[i].y);
8379 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8380 0, 0, squareSize, squareSize,
8381 anim->prevFrame.x, anim->prevFrame.y);
8386 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8388 ChessSquare piece; int startColor;
8389 XPoint * start; XPoint * finish;
8390 XPoint frames[]; int nFrames;
8394 BeginAnimation(anim, piece, startColor, start);
8395 for (n = 0; n < nFrames; n++) {
8396 AnimationFrame(anim, &(frames[n]), piece);
8397 FrameDelay(appData.animSpeed);
8399 EndAnimation(anim, finish);
8402 /* Main control logic for deciding what to animate and how */
8405 AnimateMove(board, fromX, fromY, toX, toY)
8414 XPoint start, finish, mid;
8415 XPoint frames[kFactor * 2 + 1];
8416 int nFrames, startColor, endColor;
8418 /* Are we animating? */
8419 if (!appData.animate || appData.blindfold)
8422 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8423 piece = board[fromY][fromX];
8424 if (piece >= EmptySquare) return;
8429 hop = (piece == WhiteKnight || piece == BlackKnight);
8432 if (appData.debugMode) {
8433 printf(hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8434 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8435 piece, fromX, fromY, toX, toY);
8438 ScreenSquare(fromX, fromY, &start, &startColor);
8439 ScreenSquare(toX, toY, &finish, &endColor);
8442 /* Knight: make diagonal movement then straight */
8443 if (abs(toY - fromY) < abs(toX - fromX)) {
8444 mid.x = start.x + (finish.x - start.x) / 2;
8448 mid.y = start.y + (finish.y - start.y) / 2;
8451 mid.x = start.x + (finish.x - start.x) / 2;
8452 mid.y = start.y + (finish.y - start.y) / 2;
8455 /* Don't use as many frames for very short moves */
8456 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8457 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8459 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8460 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8462 /* Be sure end square is redrawn */
8463 damage[toY][toX] = True;
8467 DragPieceBegin(x, y)
8470 int boardX, boardY, color;
8473 /* Are we animating? */
8474 if (!appData.animateDragging || appData.blindfold)
8477 /* Figure out which square we start in and the
8478 mouse position relative to top left corner. */
8479 BoardSquare(x, y, &boardX, &boardY);
8480 player.startBoardX = boardX;
8481 player.startBoardY = boardY;
8482 ScreenSquare(boardX, boardY, &corner, &color);
8483 player.startSquare = corner;
8484 player.startColor = color;
8486 /* Start from exactly where the piece is. This can be confusing
8487 if you start dragging far from the center of the square; most
8488 or all of the piece can be over a different square from the one
8489 the mouse pointer is in. */
8490 player.mouseDelta.x = x - corner.x;
8491 player.mouseDelta.y = y - corner.y;
8493 /* As soon as we start dragging, the piece will jump slightly to
8494 be centered over the mouse pointer. */
8495 player.mouseDelta.x = squareSize/2;
8496 player.mouseDelta.y = squareSize/2;
8498 /* Initialise animation */
8499 player.dragPiece = PieceForSquare(boardX, boardY);
8501 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8502 player.dragActive = True;
8503 BeginAnimation(&player, player.dragPiece, color, &corner);
8504 /* Mark this square as needing to be redrawn. Note that
8505 we don't remove the piece though, since logically (ie
8506 as seen by opponent) the move hasn't been made yet. */
8507 damage[boardY][boardX] = True;
8509 player.dragActive = False;
8519 /* Are we animating? */
8520 if (!appData.animateDragging || appData.blindfold)
8524 if (! player.dragActive)
8526 /* Move piece, maintaining same relative position
8527 of mouse within square */
8528 corner.x = x - player.mouseDelta.x;
8529 corner.y = y - player.mouseDelta.y;
8530 AnimationFrame(&player, &corner, player.dragPiece);
8532 if (appData.highlightDragging) {
8534 BoardSquare(x, y, &boardX, &boardY);
8535 SetHighlights(fromX, fromY, boardX, boardY);
8544 int boardX, boardY, color;
8547 /* Are we animating? */
8548 if (!appData.animateDragging || appData.blindfold)
8552 if (! player.dragActive)
8554 /* Last frame in sequence is square piece is
8555 placed on, which may not match mouse exactly. */
8556 BoardSquare(x, y, &boardX, &boardY);
8557 ScreenSquare(boardX, boardY, &corner, &color);
8558 EndAnimation(&player, &corner);
8560 /* Be sure end square is redrawn */
8561 damage[boardY][boardX] = True;
8563 /* This prevents weird things happening with fast successive
8564 clicks which on my Sun at least can cause motion events
8565 without corresponding press/release. */
8566 player.dragActive = False;
8569 /* Handle expose event while piece being dragged */
8574 if (!player.dragActive || appData.blindfold)
8577 /* What we're doing: logically, the move hasn't been made yet,
8578 so the piece is still in it's original square. But visually
8579 it's being dragged around the board. So we erase the square
8580 that the piece is on and draw it at the last known drag point. */
8581 BlankSquare(player.startSquare.x, player.startSquare.y,
8582 player.startColor, EmptySquare, xBoardWindow);
8583 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8584 damage[player.startBoardY][player.startBoardX] = TRUE;