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 },
1152 XrmOptionDescRec shellOptions[] = {
1153 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
1154 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
1155 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
1156 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
1157 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
1158 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
1159 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
1160 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
1161 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
1162 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
1163 { "-initString", "initString", XrmoptionSepArg, NULL },
1164 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
1165 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
1166 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
1167 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
1168 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
1169 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
1170 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
1171 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
1172 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
1173 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
1174 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
1175 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
1176 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
1177 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
1178 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
1179 { "-fh", "firstHost", XrmoptionSepArg, NULL },
1180 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
1181 { "-sh", "secondHost", XrmoptionSepArg, NULL },
1182 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
1183 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
1184 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
1185 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
1186 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
1187 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
1188 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
1189 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
1190 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
1191 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
1192 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
1193 { "-td", "timeDelay", XrmoptionSepArg, NULL },
1194 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
1195 { "-tc", "timeControl", XrmoptionSepArg, NULL },
1196 { "-internetChessServerMode", "internetChessServerMode",
1197 XrmoptionSepArg, NULL },
1198 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
1199 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
1200 { "-internetChessServerHost", "internetChessServerHost",
1201 XrmoptionSepArg, NULL },
1202 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
1203 { "-internetChessServerPort", "internetChessServerPort",
1204 XrmoptionSepArg, NULL },
1205 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
1206 { "-internetChessServerCommPort", "internetChessServerCommPort",
1207 XrmoptionSepArg, NULL },
1208 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
1209 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
1210 XrmoptionSepArg, NULL },
1211 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
1212 { "-internetChessServerHelper", "internetChessServerHelper",
1213 XrmoptionSepArg, NULL },
1214 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
1215 { "-internetChessServerInputBox", "internetChessServerInputBox",
1216 XrmoptionSepArg, NULL },
1217 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
1218 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
1219 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
1220 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
1221 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
1222 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
1223 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
1224 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
1225 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
1226 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
1227 { "-gateway", "gateway", XrmoptionSepArg, NULL },
1228 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
1229 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
1230 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
1231 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
1232 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
1233 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
1234 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
1235 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
1236 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
1237 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
1238 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
1239 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
1240 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
1241 { "-blind", "blindfold", XrmoptionNoArg, "True" },
1242 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
1243 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
1244 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
1245 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
1246 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
1247 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
1248 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
1249 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
1250 { "-mm", "matchMode", XrmoptionNoArg, "True" },
1251 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
1252 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
1253 { "-mg", "matchGames", XrmoptionSepArg, NULL },
1254 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
1255 { "-mono", "monoMode", XrmoptionNoArg, "True" },
1256 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
1257 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
1258 { "-debug", "debugMode", XrmoptionNoArg, "True" },
1259 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
1260 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
1261 { "-clock", "clockMode", XrmoptionNoArg, "True" },
1262 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
1263 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
1264 { "-size", "boardSize", XrmoptionSepArg, NULL },
1265 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
1266 { "-st", "searchTime", XrmoptionSepArg, NULL },
1267 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
1268 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
1269 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
1270 { "-coords", "showCoords", XrmoptionNoArg, "True" },
1271 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
1273 { "-showJail", "showJail", XrmoptionSepArg, NULL },
1274 { "-jail", "showJail", XrmoptionNoArg, "1" },
1275 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
1276 { "-xjail", "showJail", XrmoptionNoArg, "0" },
1278 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
1279 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
1280 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
1281 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
1282 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
1283 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
1284 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
1285 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
1286 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
1287 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
1288 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
1289 { "-font", "font", XrmoptionSepArg, NULL },
1290 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
1291 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1292 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1293 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
1294 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
1295 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
1296 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
1297 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
1298 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
1299 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
1300 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
1301 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
1302 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
1303 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
1304 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
1305 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
1306 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
1307 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
1308 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
1309 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
1311 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
1312 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
1313 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
1315 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
1316 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
1317 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
1318 { "-premove", "premove", XrmoptionSepArg, NULL },
1319 { "-pre", "premove", XrmoptionNoArg, "True" },
1320 { "-xpre", "premove", XrmoptionNoArg, "False" },
1321 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
1322 { "-legal", "testLegality", XrmoptionNoArg, "True" },
1323 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
1324 { "-flipView", "flipView", XrmoptionSepArg, NULL },
1325 { "-flip", "flipView", XrmoptionNoArg, "True" },
1326 { "-xflip", "flipView", XrmoptionNoArg, "False" },
1327 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
1328 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
1329 XrmoptionSepArg, NULL },
1330 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
1331 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
1332 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
1333 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
1334 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
1335 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
1336 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
1337 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
1338 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
1339 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
1340 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
1342 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
1343 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
1344 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
1345 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
1346 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
1347 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
1348 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
1349 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
1350 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
1351 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
1352 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
1353 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
1354 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
1355 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
1356 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
1357 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
1358 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
1359 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
1360 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
1361 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
1362 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
1363 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
1364 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
1365 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
1366 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
1367 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
1368 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
1369 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
1370 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
1371 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
1373 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
1374 { "-flash", "flashCount", XrmoptionNoArg, "3" },
1375 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
1376 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
1377 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
1378 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
1379 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
1380 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
1381 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
1382 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
1383 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
1384 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
1385 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1386 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
1387 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
1388 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
1389 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
1390 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
1391 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
1392 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
1393 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
1394 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
1395 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
1396 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
1397 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
1398 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
1399 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
1400 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
1401 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
1402 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
1403 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
1404 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
1405 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
1406 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
1407 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
1408 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
1409 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
1410 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
1411 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
1412 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
1413 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
1414 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
1415 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
1416 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
1417 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
1418 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
1419 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
1420 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
1421 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
1422 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
1423 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
1424 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
1425 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
1426 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
1427 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
1428 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
1429 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
1430 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
1431 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
1432 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
1433 { "-mode", "initialMode", XrmoptionSepArg, NULL },
1434 { "-variant", "variant", XrmoptionSepArg, NULL },
1435 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
1436 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
1437 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
1438 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
1439 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
1443 XtActionsRec boardActions[] = {
1444 { "DrawPosition", DrawPositionProc },
1445 { "HandleUserMove", HandleUserMove },
1446 { "AnimateUserMove", AnimateUserMove },
1447 { "FileNameAction", FileNameAction },
1448 { "AskQuestionProc", AskQuestionProc },
1449 { "AskQuestionReplyAction", AskQuestionReplyAction },
1450 { "PieceMenuPopup", PieceMenuPopup },
1451 { "WhiteClock", WhiteClock },
1452 { "BlackClock", BlackClock },
1453 { "Iconify", Iconify },
1454 { "ResetProc", ResetProc },
1455 { "LoadGameProc", LoadGameProc },
1456 { "LoadNextGameProc", LoadNextGameProc },
1457 { "LoadPrevGameProc", LoadPrevGameProc },
1458 { "LoadSelectedProc", LoadSelectedProc },
1459 { "ReloadGameProc", ReloadGameProc },
1460 { "LoadPositionProc", LoadPositionProc },
1461 { "LoadNextPositionProc", LoadNextPositionProc },
1462 { "LoadPrevPositionProc", LoadPrevPositionProc },
1463 { "ReloadPositionProc", ReloadPositionProc },
1464 { "CopyPositionProc", CopyPositionProc },
1465 { "PastePositionProc", PastePositionProc },
1466 { "CopyGameProc", CopyGameProc },
1467 { "PasteGameProc", PasteGameProc },
1468 { "SaveGameProc", SaveGameProc },
1469 { "SavePositionProc", SavePositionProc },
1470 { "MailMoveProc", MailMoveProc },
1471 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
1472 { "QuitProc", QuitProc },
1473 { "MachineWhiteProc", MachineWhiteProc },
1474 { "MachineBlackProc", MachineBlackProc },
1475 { "AnalysisModeProc", AnalyzeModeProc },
1476 { "AnalyzeFileProc", AnalyzeFileProc },
1477 { "TwoMachinesProc", TwoMachinesProc },
1478 { "IcsClientProc", IcsClientProc },
1479 { "EditGameProc", EditGameProc },
1480 { "EditPositionProc", EditPositionProc },
1481 { "TrainingProc", EditPositionProc },
1482 { "ShowGameListProc", ShowGameListProc },
1483 { "ShowMoveListProc", HistoryShowProc},
1484 { "EditTagsProc", EditCommentProc },
1485 { "EditCommentProc", EditCommentProc },
1486 { "IcsAlarmProc", IcsAlarmProc },
1487 { "IcsInputBoxProc", IcsInputBoxProc },
1488 { "PauseProc", PauseProc },
1489 { "AcceptProc", AcceptProc },
1490 { "DeclineProc", DeclineProc },
1491 { "RematchProc", RematchProc },
1492 { "CallFlagProc", CallFlagProc },
1493 { "DrawProc", DrawProc },
1494 { "AdjournProc", AdjournProc },
1495 { "AbortProc", AbortProc },
1496 { "ResignProc", ResignProc },
1497 { "EnterKeyProc", EnterKeyProc },
1498 { "StopObservingProc", StopObservingProc },
1499 { "StopExaminingProc", StopExaminingProc },
1500 { "BackwardProc", BackwardProc },
1501 { "ForwardProc", ForwardProc },
1502 { "ToStartProc", ToStartProc },
1503 { "ToEndProc", ToEndProc },
1504 { "RevertProc", RevertProc },
1505 { "TruncateGameProc", TruncateGameProc },
1506 { "MoveNowProc", MoveNowProc },
1507 { "RetractMoveProc", RetractMoveProc },
1508 { "AlwaysQueenProc", AlwaysQueenProc },
1509 { "AnimateDraggingProc", AnimateDraggingProc },
1510 { "AnimateMovingProc", AnimateMovingProc },
1511 { "AutoflagProc", AutoflagProc },
1512 { "AutoflipProc", AutoflipProc },
1513 { "AutobsProc", AutobsProc },
1514 { "AutoraiseProc", AutoraiseProc },
1515 { "AutosaveProc", AutosaveProc },
1516 { "BlindfoldProc", BlindfoldProc },
1517 { "FlashMovesProc", FlashMovesProc },
1518 { "FlipViewProc", FlipViewProc },
1519 { "GetMoveListProc", GetMoveListProc },
1521 { "HighlightDraggingProc", HighlightDraggingProc },
1523 { "HighlightLastMoveProc", HighlightLastMoveProc },
1524 { "IcsAlarmProc", IcsAlarmProc },
1525 { "MoveSoundProc", MoveSoundProc },
1526 { "OldSaveStyleProc", OldSaveStyleProc },
1527 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
1528 { "PonderNextMoveProc", PonderNextMoveProc },
1529 { "PopupExitMessageProc", PopupExitMessageProc },
1530 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
1531 { "PremoveProc", PremoveProc },
1532 { "QuietPlayProc", QuietPlayProc },
1533 { "ShowCoordsProc", ShowCoordsProc },
1534 { "ShowThinkingProc", ShowThinkingProc },
1535 { "TestLegalityProc", TestLegalityProc },
1536 { "InfoProc", InfoProc },
1537 { "ManProc", ManProc },
1538 { "HintProc", HintProc },
1539 { "BookProc", BookProc },
1540 { "AboutGameProc", AboutGameProc },
1541 { "AboutProc", AboutProc },
1542 { "DebugProc", DebugProc },
1543 { "NothingProc", NothingProc },
1544 { "CommentPopDown", (XtActionProc) CommentPopDown },
1545 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
1546 { "TagsPopDown", (XtActionProc) TagsPopDown },
1547 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
1548 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
1549 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
1550 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
1551 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
1552 { "GameListPopDown", (XtActionProc) GameListPopDown },
1553 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
1554 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
1557 char globalTranslations[] =
1558 ":<Key>R: ResignProc() \n \
1559 :<Key>r: ResetProc() \n \
1560 :<Key>g: LoadGameProc() \n \
1561 :<Key>N: LoadNextGameProc() \n \
1562 :<Key>P: LoadPrevGameProc() \n \
1563 :<Key>Q: QuitProc() \n \
1564 :<Key>F: ToEndProc() \n \
1565 :<Key>f: ForwardProc() \n \
1566 :<Key>B: ToStartProc() \n \
1567 :<Key>b: BackwardProc() \n \
1568 :<Key>p: PauseProc() \n \
1569 :<Key>d: DrawProc() \n \
1570 :<Key>t: CallFlagProc() \n \
1571 :<Key>i: Iconify() \n \
1572 :<Key>c: Iconify() \n \
1573 :<Key>v: FlipViewProc() \n \
1574 <KeyDown>Control_L: BackwardProc() \n \
1575 <KeyUp>Control_L: ForwardProc() \n \
1576 <KeyDown>Control_R: BackwardProc() \n \
1577 <KeyUp>Control_R: ForwardProc() \n \
1578 Shift<Key>1: AskQuestionProc(\"Direct command\",\
1579 \"Send to chess program:\",,1) \n \
1580 Shift<Key>2: AskQuestionProc(\"Direct command\",\
1581 \"Send to second chess program:\",,2) \n";
1583 char boardTranslations[] =
1584 "<Btn1Down>: HandleUserMove() \n \
1585 <Btn1Up>: HandleUserMove() \n \
1586 <Btn1Motion>: AnimateUserMove() \n \
1587 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
1588 PieceMenuPopup(menuB) \n \
1589 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
1590 PieceMenuPopup(menuW) \n \
1591 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
1592 PieceMenuPopup(menuW) \n \
1593 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
1594 PieceMenuPopup(menuB) \n";
1596 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
1597 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
1599 char ICSInputTranslations[] =
1600 "<Key>Return: EnterKeyProc() \n";
1602 String xboardResources[] = {
1603 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
1604 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
1605 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
1610 /* Max possible square size */
1611 #define MAXSQSIZE 256
1613 static int xpm_avail[MAXSQSIZE];
1615 #ifdef HAVE_DIR_STRUCT
1617 /* Extract piece size from filename */
1619 xpm_getsize(name, len, ext)
1630 if ((p=strchr(name, '.')) == NULL ||
1631 StrCaseCmp(p+1, ext) != 0)
1637 while (*p && isdigit(*p))
1644 /* Setup xpm_avail */
1646 xpm_getavail(dirname, ext)
1654 for (i=0; i<MAXSQSIZE; ++i)
1657 if (appData.debugMode)
1658 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
1660 dir = opendir(dirname);
1663 fprintf(stderr, _("%s: Can't access XPM directory %s\n"),
1664 programName, dirname);
1668 while ((ent=readdir(dir)) != NULL) {
1669 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
1670 if (i > 0 && i < MAXSQSIZE)
1680 xpm_print_avail(fp, ext)
1686 fprintf(fp, _("Available `%s' sizes:\n"), ext);
1687 for (i=1; i<MAXSQSIZE; ++i) {
1693 /* Return XPM piecesize closest to size */
1695 xpm_closest_to(dirname, size, ext)
1701 int sm_diff = MAXSQSIZE;
1705 xpm_getavail(dirname, ext);
1707 if (appData.debugMode)
1708 xpm_print_avail(stderr, ext);
1710 for (i=1; i<MAXSQSIZE; ++i) {
1713 diff = (diff<0) ? -diff : diff;
1714 if (diff < sm_diff) {
1722 fprintf(stderr, _("Error: No `%s' files!\n"), ext);
1728 #else /* !HAVE_DIR_STRUCT */
1729 /* If we are on a system without a DIR struct, we can't
1730 read the directory, so we can't collect a list of
1731 filenames, etc., so we can't do any size-fitting. */
1733 xpm_closest_to(dirname, size, ext)
1738 fprintf(stderr, _("\
1739 Warning: No DIR structure found on this system --\n\
1740 Unable to autosize for XPM/XIM pieces.\n\
1741 Please report this error to frankm@hiwaay.net.\n\
1742 Include system type & operating system in message.\n"));
1745 #endif /* HAVE_DIR_STRUCT */
1747 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
1748 "magenta", "cyan", "white" };
1752 TextColors textColors[(int)NColorClasses];
1754 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
1756 parse_color(str, which)
1760 char *p, buf[100], *d;
1763 if (strlen(str) > 99) /* watch bounds on buf */
1768 for (i=0; i<which; ++i) {
1775 /* Could be looking at something like:
1777 .. in which case we want to stop on a comma also */
1778 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
1782 return -1; /* Use default for empty field */
1785 if (which == 2 || isdigit(*p))
1788 while (*p && isalpha(*p))
1793 for (i=0; i<8; ++i) {
1794 if (!StrCaseCmp(buf, cnames[i]))
1795 return which? (i+40) : (i+30);
1797 if (!StrCaseCmp(buf, "default")) return -1;
1799 fprintf(stderr, _("%s: unrecognized color %s\n"), programName, buf);
1804 parse_cpair(cc, str)
1808 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
1809 fprintf(stderr, _("%s: can't parse foreground color in `%s'\n"),
1814 /* bg and attr are optional */
1815 textColors[(int)cc].bg = parse_color(str, 1);
1816 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
1817 textColors[(int)cc].attr = 0;
1823 /* Arrange to catch delete-window events */
1824 Atom wm_delete_window;
1826 CatchDeleteWindow(Widget w, String procname)
1829 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
1830 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
1831 XtAugmentTranslations(w, XtParseTranslationTable(buf));
1838 XtSetArg(args[0], XtNiconic, False);
1839 XtSetValues(shellWidget, args, 1);
1841 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
1849 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
1850 XSetWindowAttributes window_attributes;
1852 Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
1853 XrmValue vFrom, vTo;
1854 XtGeometryResult gres;
1857 int forceMono = False;
1859 setbuf(stdout, NULL);
1860 setbuf(stderr, NULL);
1863 programName = strrchr(argv[0], '/');
1864 if (programName == NULL)
1865 programName = argv[0];
1870 XtSetLanguageProc(NULL, NULL, NULL);
1871 bindtextdomain(PRODUCT, LOCALEDIR);
1872 textdomain(PRODUCT);
1876 XtAppInitialize(&appContext, "XBoard", shellOptions,
1877 XtNumber(shellOptions),
1878 &argc, argv, xboardResources, NULL, 0);
1880 fprintf(stderr, _("%s: unrecognized argument %s\n"),
1881 programName, argv[1]);
1885 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
1888 if (chdir(chessDir) != 0) {
1889 fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
1896 if (p == NULL) p = "/tmp";
1897 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
1898 gameCopyFilename = (char*) malloc(i);
1899 gamePasteFilename = (char*) malloc(i);
1900 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
1901 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
1903 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
1904 clientResources, XtNumber(clientResources),
1908 /* This feature does not work; animation needs a rewrite */
1909 appData.highlightDragging = FALSE;
1913 xDisplay = XtDisplay(shellWidget);
1914 xScreen = DefaultScreen(xDisplay);
1915 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
1918 * Determine boardSize
1920 if (isdigit(appData.boardSize[0])) {
1921 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
1922 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
1923 &fontPxlSize, &smallLayout, &tinyLayout);
1925 fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
1926 programName, appData.boardSize);
1930 /* Find some defaults; use the nearest known size */
1931 SizeDefaults *szd, *nearest;
1932 int distance = 99999;
1933 nearest = szd = sizeDefaults;
1934 while (szd->name != NULL) {
1935 if (abs(szd->squareSize - squareSize) < distance) {
1937 distance = abs(szd->squareSize - squareSize);
1938 if (distance == 0) break;
1942 if (i < 2) lineGap = nearest->lineGap;
1943 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
1944 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
1945 if (i < 5) fontPxlSize = nearest->fontPxlSize;
1946 if (i < 6) smallLayout = nearest->smallLayout;
1947 if (i < 7) tinyLayout = nearest->tinyLayout;
1950 SizeDefaults *szd = sizeDefaults;
1951 if (*appData.boardSize == NULLCHAR) {
1952 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
1953 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
1956 if (szd->name == NULL) szd--;
1958 while (szd->name != NULL &&
1959 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
1960 if (szd->name == NULL) {
1961 fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
1962 programName, appData.boardSize);
1966 squareSize = szd->squareSize;
1967 lineGap = szd->lineGap;
1968 clockFontPxlSize = szd->clockFontPxlSize;
1969 coordFontPxlSize = szd->coordFontPxlSize;
1970 fontPxlSize = szd->fontPxlSize;
1971 smallLayout = szd->smallLayout;
1972 tinyLayout = szd->tinyLayout;
1975 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
1976 if (strlen(appData.pixmapDirectory) > 0) {
1977 p = ExpandPathName(appData.pixmapDirectory);
1979 fprintf(stderr, _("Error expanding path name \"%s\"\n"),
1980 appData.pixmapDirectory);
1983 if (appData.debugMode) {
1984 fprintf(stderr, _("\
1985 XBoard square size (hint): %d\n\
1986 %s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
1988 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
1989 if (appData.debugMode) {
1990 fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
1994 boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
1995 if (appData.showJail == 1) {
1996 /* Jail on top and bottom */
1997 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
1998 XtSetArg(boardArgs[2], XtNheight,
1999 boardWidth + 2*(lineGap + squareSize));
2000 } else if (appData.showJail == 2) {
2002 XtSetArg(boardArgs[1], XtNwidth,
2003 boardWidth + 2*(lineGap + squareSize));
2004 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2007 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
2008 XtSetArg(boardArgs[2], XtNheight, boardWidth);
2012 * Determine what fonts to use.
2014 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
2015 clockFontID = XLoadFont(xDisplay, appData.clockFont);
2016 clockFontStruct = XQueryFont(xDisplay, clockFontID);
2017 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
2018 coordFontID = XLoadFont(xDisplay, appData.coordFont);
2019 coordFontStruct = XQueryFont(xDisplay, coordFontID);
2020 appData.font = FindFont(appData.font, fontPxlSize);
2022 xdb = XtDatabase(xDisplay);
2023 XrmPutStringResource(&xdb, "*font", appData.font);
2026 * Detect if there are not enough colors available and adapt.
2028 if (DefaultDepth(xDisplay, xScreen) <= 2) {
2029 appData.monoMode = True;
2032 if (!appData.monoMode) {
2033 vFrom.addr = (caddr_t) appData.lightSquareColor;
2034 vFrom.size = strlen(appData.lightSquareColor);
2035 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2036 if (vTo.addr == NULL) {
2037 appData.monoMode = True;
2040 lightSquareColor = *(Pixel *) vTo.addr;
2043 if (!appData.monoMode) {
2044 vFrom.addr = (caddr_t) appData.darkSquareColor;
2045 vFrom.size = strlen(appData.darkSquareColor);
2046 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2047 if (vTo.addr == NULL) {
2048 appData.monoMode = True;
2051 darkSquareColor = *(Pixel *) vTo.addr;
2054 if (!appData.monoMode) {
2055 vFrom.addr = (caddr_t) appData.whitePieceColor;
2056 vFrom.size = strlen(appData.whitePieceColor);
2057 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2058 if (vTo.addr == NULL) {
2059 appData.monoMode = True;
2062 whitePieceColor = *(Pixel *) vTo.addr;
2065 if (!appData.monoMode) {
2066 vFrom.addr = (caddr_t) appData.blackPieceColor;
2067 vFrom.size = strlen(appData.blackPieceColor);
2068 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2069 if (vTo.addr == NULL) {
2070 appData.monoMode = True;
2073 blackPieceColor = *(Pixel *) vTo.addr;
2077 if (!appData.monoMode) {
2078 vFrom.addr = (caddr_t) appData.highlightSquareColor;
2079 vFrom.size = strlen(appData.highlightSquareColor);
2080 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2081 if (vTo.addr == NULL) {
2082 appData.monoMode = True;
2085 highlightSquareColor = *(Pixel *) vTo.addr;
2089 if (!appData.monoMode) {
2090 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
2091 vFrom.size = strlen(appData.premoveHighlightColor);
2092 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
2093 if (vTo.addr == NULL) {
2094 appData.monoMode = True;
2097 premoveHighlightColor = *(Pixel *) vTo.addr;
2102 fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
2106 if (appData.monoMode && appData.debugMode) {
2107 fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
2108 (unsigned long) XWhitePixel(xDisplay, xScreen),
2109 (unsigned long) XBlackPixel(xDisplay, xScreen));
2112 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
2113 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
2114 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
2115 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
2116 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
2117 parse_cpair(ColorTell, appData.colorTell) < 0 ||
2118 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
2119 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
2120 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
2121 parse_cpair(ColorNormal, appData.colorNormal) < 0)
2123 if (appData.colorize) {
2125 _("%s: can't parse color names; disabling colorization\n"),
2128 appData.colorize = FALSE;
2130 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
2131 textColors[ColorNone].attr = 0;
2133 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
2139 layoutName = "tinyLayout";
2140 } else if (smallLayout) {
2141 layoutName = "smallLayout";
2143 layoutName = "normalLayout";
2145 /* Outer layoutWidget is there only to provide a name for use in
2146 resources that depend on the layout style */
2148 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
2149 layoutArgs, XtNumber(layoutArgs));
2151 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
2152 formArgs, XtNumber(formArgs));
2153 XtSetArg(args[0], XtNdefaultDistance, &sep);
2154 XtGetValues(formWidget, args, 1);
2157 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
2159 widgetList[j++] = whiteTimerWidget =
2160 XtCreateWidget("whiteTime", labelWidgetClass,
2161 formWidget, timerArgs, XtNumber(timerArgs));
2162 XtSetArg(args[0], XtNfont, clockFontStruct);
2163 XtSetValues(whiteTimerWidget, args, 1);
2165 widgetList[j++] = blackTimerWidget =
2166 XtCreateWidget("blackTime", labelWidgetClass,
2167 formWidget, timerArgs, XtNumber(timerArgs));
2168 XtSetArg(args[0], XtNfont, clockFontStruct);
2169 XtSetValues(blackTimerWidget, args, 1);
2171 if (appData.titleInWindow) {
2172 widgetList[j++] = titleWidget =
2173 XtCreateWidget("title", labelWidgetClass, formWidget,
2174 titleArgs, XtNumber(titleArgs));
2177 if (appData.showButtonBar) {
2178 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
2181 widgetList[j++] = messageWidget =
2182 XtCreateWidget("message", labelWidgetClass, formWidget,
2183 messageArgs, XtNumber(messageArgs));
2185 widgetList[j++] = boardWidget =
2186 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
2187 XtNumber(boardArgs));
2189 XtManageChildren(widgetList, j);
2191 timerWidth = (boardWidth - sep) / 2;
2192 XtSetArg(args[0], XtNwidth, timerWidth);
2193 XtSetValues(whiteTimerWidget, args, 1);
2194 XtSetValues(blackTimerWidget, args, 1);
2196 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
2197 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
2198 XtGetValues(whiteTimerWidget, args, 2);
2200 if (appData.showButtonBar) {
2201 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
2202 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
2203 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
2207 * formWidget uses these constraints but they are stored
2211 XtSetArg(args[i], XtNfromHoriz, 0); i++;
2212 XtSetValues(menuBarWidget, args, i);
2213 if (appData.titleInWindow) {
2216 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2217 XtSetValues(whiteTimerWidget, args, i);
2219 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2220 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2221 XtSetValues(blackTimerWidget, args, i);
2223 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2224 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
2225 XtSetValues(titleWidget, args, i);
2227 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2228 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2229 XtSetValues(messageWidget, args, i);
2230 if (appData.showButtonBar) {
2232 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2233 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2234 XtSetValues(buttonBarWidget, args, i);
2238 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2239 XtSetValues(whiteTimerWidget, args, i);
2241 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
2242 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2243 XtSetValues(blackTimerWidget, args, i);
2245 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
2246 XtSetValues(titleWidget, args, i);
2248 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2249 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2250 XtSetValues(messageWidget, args, i);
2251 if (appData.showButtonBar) {
2253 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2254 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2255 XtSetValues(buttonBarWidget, args, i);
2260 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2261 XtSetValues(whiteTimerWidget, args, i);
2263 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
2264 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
2265 XtSetValues(blackTimerWidget, args, i);
2267 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2268 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
2269 XtSetValues(messageWidget, args, i);
2270 if (appData.showButtonBar) {
2272 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
2273 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
2274 XtSetValues(buttonBarWidget, args, i);
2278 XtSetArg(args[0], XtNfromVert, messageWidget);
2279 XtSetValues(boardWidget, args, 1);
2281 XtRealizeWidget(shellWidget);
2284 * Correct the width of the message and title widgets.
2285 * It is not known why some systems need the extra fudge term.
2286 * The value "2" is probably larger than needed.
2288 XawFormDoLayout(formWidget, False);
2289 #define WIDTH_FUDGE 2
2291 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2292 XtSetArg(args[i], XtNheight, &h); i++;
2293 XtGetValues(messageWidget, args, i);
2294 if (appData.showButtonBar) {
2296 XtSetArg(args[i], XtNwidth, &w); i++;
2297 XtGetValues(buttonBarWidget, args, i);
2298 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2300 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
2303 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2304 if (gres != XtGeometryYes && appData.debugMode) {
2305 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2306 programName, gres, w, h, wr, hr);
2309 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
2310 /* The size used for the child widget in layout lags one resize behind
2311 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
2313 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
2314 if (gres != XtGeometryYes && appData.debugMode) {
2315 fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"),
2316 programName, gres, w, h, wr, hr);
2320 if (appData.titleInWindow) {
2322 XtSetArg(args[i], XtNborderWidth, &bor); i++;
2323 XtSetArg(args[i], XtNheight, &h); i++;
2324 XtGetValues(titleWidget, args, i);
2326 w = boardWidth - 2*bor;
2328 XtSetArg(args[0], XtNwidth, &w);
2329 XtGetValues(menuBarWidget, args, 1);
2330 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
2333 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
2334 if (gres != XtGeometryYes && appData.debugMode) {
2336 _("%s: titleWidget geometry error %d %d %d %d %d\n"),
2337 programName, gres, w, h, wr, hr);
2340 XawFormDoLayout(formWidget, True);
2342 xBoardWindow = XtWindow(boardWidget);
2345 * Create X checkmark bitmap and initialize option menu checks.
2347 ReadBitmap(&xMarkPixmap, "checkmark.bm",
2348 checkmark_bits, checkmark_width, checkmark_height);
2349 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
2350 if (appData.alwaysPromoteToQueen) {
2351 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
2354 if (appData.animateDragging) {
2355 XtSetValues(XtNameToWidget(menuBarWidget,
2356 "menuOptions.Animate Dragging"),
2359 if (appData.animate) {
2360 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
2363 if (appData.autoComment) {
2364 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
2367 if (appData.autoCallFlag) {
2368 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
2371 if (appData.autoFlipView) {
2372 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
2375 if (appData.autoObserve) {
2376 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
2379 if (appData.autoRaiseBoard) {
2380 XtSetValues(XtNameToWidget(menuBarWidget,
2381 "menuOptions.Auto Raise Board"), args, 1);
2383 if (appData.autoSaveGames) {
2384 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2387 if (appData.saveGameFile[0] != NULLCHAR) {
2388 /* Can't turn this off from menu */
2389 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2391 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
2395 if (appData.blindfold) {
2396 XtSetValues(XtNameToWidget(menuBarWidget,
2397 "menuOptions.Blindfold"), args, 1);
2399 if (appData.flashCount > 0) {
2400 XtSetValues(XtNameToWidget(menuBarWidget,
2401 "menuOptions.Flash Moves"),
2404 if (appData.getMoveList) {
2405 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
2409 if (appData.highlightDragging) {
2410 XtSetValues(XtNameToWidget(menuBarWidget,
2411 "menuOptions.Highlight Dragging"),
2415 if (appData.highlightLastMove) {
2416 XtSetValues(XtNameToWidget(menuBarWidget,
2417 "menuOptions.Highlight Last Move"),
2420 if (appData.icsAlarm) {
2421 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
2424 if (appData.ringBellAfterMoves) {
2425 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
2428 if (appData.oldSaveStyle) {
2429 XtSetValues(XtNameToWidget(menuBarWidget,
2430 "menuOptions.Old Save Style"), args, 1);
2432 if (appData.periodicUpdates) {
2433 XtSetValues(XtNameToWidget(menuBarWidget,
2434 "menuOptions.Periodic Updates"), args, 1);
2436 if (appData.ponderNextMove) {
2437 XtSetValues(XtNameToWidget(menuBarWidget,
2438 "menuOptions.Ponder Next Move"), args, 1);
2440 if (appData.popupExitMessage) {
2441 XtSetValues(XtNameToWidget(menuBarWidget,
2442 "menuOptions.Popup Exit Message"), args, 1);
2444 if (appData.popupMoveErrors) {
2445 XtSetValues(XtNameToWidget(menuBarWidget,
2446 "menuOptions.Popup Move Errors"), args, 1);
2448 if (appData.premove) {
2449 XtSetValues(XtNameToWidget(menuBarWidget,
2450 "menuOptions.Premove"), args, 1);
2452 if (appData.quietPlay) {
2453 XtSetValues(XtNameToWidget(menuBarWidget,
2454 "menuOptions.Quiet Play"), args, 1);
2456 if (appData.showCoords) {
2457 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
2460 if (appData.showThinking) {
2461 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
2464 if (appData.testLegality) {
2465 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
2469 /* icsEngineAnalyze - default init */
2470 appData.icsEngineAnalyze = FALSE;
2475 ReadBitmap(&wIconPixmap, "icon_white.bm",
2476 icon_white_bits, icon_white_width, icon_white_height);
2477 ReadBitmap(&bIconPixmap, "icon_black.bm",
2478 icon_black_bits, icon_black_width, icon_black_height);
2479 iconPixmap = wIconPixmap;
2481 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
2482 XtSetValues(shellWidget, args, i);
2485 * Create a cursor for the board widget.
2487 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
2488 XChangeWindowAttributes(xDisplay, xBoardWindow,
2489 CWCursor, &window_attributes);
2492 * Inhibit shell resizing.
2494 shellArgs[0].value = (XtArgVal) &w;
2495 shellArgs[1].value = (XtArgVal) &h;
2496 XtGetValues(shellWidget, shellArgs, 2);
2497 shellArgs[4].value = shellArgs[2].value = w;
2498 shellArgs[5].value = shellArgs[3].value = h;
2499 XtSetValues(shellWidget, &shellArgs[2], 4);
2501 CatchDeleteWindow(shellWidget, "QuitProc");
2506 if (appData.bitmapDirectory[0] != NULLCHAR) {
2513 /* Create regular pieces */
2514 if (!useImages) CreatePieces();
2519 if (appData.animate || appData.animateDragging)
2522 XtAugmentTranslations(formWidget,
2523 XtParseTranslationTable(globalTranslations));
2524 XtAugmentTranslations(boardWidget,
2525 XtParseTranslationTable(boardTranslations));
2526 XtAugmentTranslations(whiteTimerWidget,
2527 XtParseTranslationTable(whiteTranslations));
2528 XtAugmentTranslations(blackTimerWidget,
2529 XtParseTranslationTable(blackTranslations));
2531 /* Why is the following needed on some versions of X instead
2532 * of a translation? */
2533 XtAddEventHandler(boardWidget, ExposureMask, False,
2534 (XtEventHandler) EventProc, NULL);
2539 if (errorExitStatus == -1) {
2540 if (appData.icsActive) {
2541 /* We now wait until we see "login:" from the ICS before
2542 sending the logon script (problems with timestamp otherwise) */
2543 /*ICSInitScript();*/
2544 if (appData.icsInputBox) ICSInputBoxPopUp();
2547 signal(SIGINT, IntSigHandler);
2548 signal(SIGTERM, IntSigHandler);
2549 if (*appData.cmailGameName != NULLCHAR) {
2550 signal(SIGUSR1, CmailSigHandler);
2554 XtAppMainLoop(appContext);
2561 if (appData.icsActive && oldICSInteractionTitle != NULL) {
2562 DisplayIcsInteractionTitle(oldICSInteractionTitle);
2564 unlink(gameCopyFilename);
2565 unlink(gamePasteFilename);
2576 CmailSigHandler(sig)
2582 signal(SIGUSR1, SIG_IGN); /* suspend handler */
2584 /* Activate call-back function CmailSigHandlerCallBack() */
2585 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
2587 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
2591 CmailSigHandlerCallBack(isr, closure, message, count, error)
2599 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
2601 /**** end signal code ****/
2611 f = fopen(appData.icsLogon, "r");
2617 strcat(buf, appData.icsLogon);
2618 f = fopen(buf, "r");
2622 ProcessICSInitScript(f);
2629 EditCommentPopDown();
2640 SetMenuEnables(enab)
2644 if (!menuBarWidget) return;
2645 while (enab->name != NULL) {
2646 w = XtNameToWidget(menuBarWidget, enab->name);
2648 DisplayError(enab->name, 0);
2650 XtSetSensitive(w, enab->value);
2656 Enables icsEnables[] = {
2657 { "menuFile.Mail Move", False },
2658 { "menuFile.Reload CMail Message", False },
2659 { "menuMode.Machine Black", False },
2660 { "menuMode.Machine White", False },
2661 { "menuMode.Analysis Mode", False },
2662 { "menuMode.Analyze File", False },
2663 { "menuMode.Two Machines", False },
2665 { "menuHelp.Hint", False },
2666 { "menuHelp.Book", False },
2667 { "menuStep.Move Now", False },
2668 { "menuOptions.Periodic Updates", False },
2669 { "menuOptions.Show Thinking", False },
2670 { "menuOptions.Ponder Next Move", False },
2675 Enables ncpEnables[] = {
2676 { "menuFile.Mail Move", False },
2677 { "menuFile.Reload CMail Message", False },
2678 { "menuMode.Machine White", False },
2679 { "menuMode.Machine Black", False },
2680 { "menuMode.Analysis Mode", False },
2681 { "menuMode.Analyze File", False },
2682 { "menuMode.Two Machines", False },
2683 { "menuMode.ICS Client", False },
2684 { "menuMode.ICS Input Box", False },
2685 { "Action", False },
2686 { "menuStep.Revert", False },
2687 { "menuStep.Move Now", False },
2688 { "menuStep.Retract Move", False },
2689 { "menuOptions.Auto Comment", False },
2690 { "menuOptions.Auto Flag", False },
2691 { "menuOptions.Auto Flip View", False },
2692 { "menuOptions.Auto Observe", False },
2693 { "menuOptions.Auto Raise Board", False },
2694 { "menuOptions.Get Move List", False },
2695 { "menuOptions.ICS Alarm", False },
2696 { "menuOptions.Move Sound", False },
2697 { "menuOptions.Quiet Play", False },
2698 { "menuOptions.Show Thinking", False },
2699 { "menuOptions.Periodic Updates", False },
2700 { "menuOptions.Ponder Next Move", False },
2701 { "menuHelp.Hint", False },
2702 { "menuHelp.Book", False },
2706 Enables gnuEnables[] = {
2707 { "menuMode.ICS Client", False },
2708 { "menuMode.ICS Input Box", False },
2709 { "menuAction.Accept", False },
2710 { "menuAction.Decline", False },
2711 { "menuAction.Rematch", False },
2712 { "menuAction.Adjourn", False },
2713 { "menuAction.Stop Examining", False },
2714 { "menuAction.Stop Observing", False },
2715 { "menuStep.Revert", False },
2716 { "menuOptions.Auto Comment", False },
2717 { "menuOptions.Auto Observe", False },
2718 { "menuOptions.Auto Raise Board", False },
2719 { "menuOptions.Get Move List", False },
2720 { "menuOptions.Premove", False },
2721 { "menuOptions.Quiet Play", False },
2723 /* The next two options rely on SetCmailMode being called *after* */
2724 /* SetGNUMode so that when GNU is being used to give hints these */
2725 /* menu options are still available */
2727 { "menuFile.Mail Move", False },
2728 { "menuFile.Reload CMail Message", False },
2732 Enables cmailEnables[] = {
2734 { "menuAction.Call Flag", False },
2735 { "menuAction.Draw", True },
2736 { "menuAction.Adjourn", False },
2737 { "menuAction.Abort", False },
2738 { "menuAction.Stop Observing", False },
2739 { "menuAction.Stop Examining", False },
2740 { "menuFile.Mail Move", True },
2741 { "menuFile.Reload CMail Message", True },
2745 Enables trainingOnEnables[] = {
2746 { "menuMode.Edit Comment", False },
2747 { "menuMode.Pause", False },
2748 { "menuStep.Forward", False },
2749 { "menuStep.Backward", False },
2750 { "menuStep.Forward to End", False },
2751 { "menuStep.Back to Start", False },
2752 { "menuStep.Move Now", False },
2753 { "menuStep.Truncate Game", False },
2757 Enables trainingOffEnables[] = {
2758 { "menuMode.Edit Comment", True },
2759 { "menuMode.Pause", True },
2760 { "menuStep.Forward", True },
2761 { "menuStep.Backward", True },
2762 { "menuStep.Forward to End", True },
2763 { "menuStep.Back to Start", True },
2764 { "menuStep.Move Now", True },
2765 { "menuStep.Truncate Game", True },
2769 Enables machineThinkingEnables[] = {
2770 { "menuFile.Load Game", False },
2771 { "menuFile.Load Next Game", False },
2772 { "menuFile.Load Previous Game", False },
2773 { "menuFile.Reload Same Game", False },
2774 { "menuFile.Paste Game", False },
2775 { "menuFile.Load Position", False },
2776 { "menuFile.Load Next Position", False },
2777 { "menuFile.Load Previous Position", False },
2778 { "menuFile.Reload Same Position", False },
2779 { "menuFile.Paste Position", False },
2780 { "menuMode.Machine White", False },
2781 { "menuMode.Machine Black", False },
2782 { "menuMode.Two Machines", False },
2783 { "menuStep.Retract Move", False },
2787 Enables userThinkingEnables[] = {
2788 { "menuFile.Load Game", True },
2789 { "menuFile.Load Next Game", True },
2790 { "menuFile.Load Previous Game", True },
2791 { "menuFile.Reload Same Game", True },
2792 { "menuFile.Paste Game", True },
2793 { "menuFile.Load Position", True },
2794 { "menuFile.Load Next Position", True },
2795 { "menuFile.Load Previous Position", True },
2796 { "menuFile.Reload Same Position", True },
2797 { "menuFile.Paste Position", True },
2798 { "menuMode.Machine White", True },
2799 { "menuMode.Machine Black", True },
2800 { "menuMode.Two Machines", True },
2801 { "menuStep.Retract Move", True },
2807 SetMenuEnables(icsEnables);
2810 /* icsEngineAnalyze */
2811 if (appData.zippyPlay && !appData.noChessProgram)
2812 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True);
2819 SetMenuEnables(ncpEnables);
2825 SetMenuEnables(gnuEnables);
2831 SetMenuEnables(cmailEnables);
2837 SetMenuEnables(trainingOnEnables);
2838 if (appData.showButtonBar) {
2839 XtSetSensitive(buttonBarWidget, False);
2845 SetTrainingModeOff()
2847 SetMenuEnables(trainingOffEnables);
2848 if (appData.showButtonBar) {
2849 XtSetSensitive(buttonBarWidget, True);
2854 SetUserThinkingEnables()
2856 if (appData.noChessProgram) return;
2857 SetMenuEnables(userThinkingEnables);
2861 SetMachineThinkingEnables()
2863 if (appData.noChessProgram) return;
2864 SetMenuEnables(machineThinkingEnables);
2866 case MachinePlaysBlack:
2867 case MachinePlaysWhite:
2868 case TwoMachinesPlay:
2869 XtSetSensitive(XtNameToWidget(menuBarWidget,
2870 ModeToWidgetName(gameMode)), True);
2877 #define Abs(n) ((n)<0 ? -(n) : (n))
2880 * Find a font that matches "pattern" that is as close as
2881 * possible to the targetPxlSize. Prefer fonts that are k
2882 * pixels smaller to fonts that are k pixels larger. The
2883 * pattern must be in the X Consortium standard format,
2884 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2885 * The return value should be freed with XtFree when no
2888 char *FindFont(pattern, targetPxlSize)
2892 char **fonts, *p, *best, *scalable, *scalableTail;
2893 int i, j, nfonts, minerr, err, pxlSize;
2896 char **missing_list;
2898 char *def_string, *base_fnt_lst, strInt[3];
2900 XFontStruct **fnt_list;
2902 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2903 sprintf(strInt, "%d", targetPxlSize);
2904 p = strstr(pattern, "--");
2905 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2906 strcat(base_fnt_lst, strInt);
2907 strcat(base_fnt_lst, strchr(p + 2, '-'));
2909 if ((fntSet = XCreateFontSet(xDisplay,
2913 &def_string)) == NULL) {
2915 fprintf(stderr, _("Unable to create font set.\n"));
2919 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2921 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2923 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2924 programName, pattern);
2932 for (i=0; i<nfonts; i++) {
2935 if (*p != '-') continue;
2937 if (*p == NULLCHAR) break;
2938 if (*p++ == '-') j++;
2940 if (j < 7) continue;
2943 scalable = fonts[i];
2946 err = pxlSize - targetPxlSize;
2947 if (Abs(err) < Abs(minerr) ||
2948 (minerr > 0 && err < 0 && -err == minerr)) {
2954 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2955 /* If the error is too big and there is a scalable font,
2956 use the scalable font. */
2957 int headlen = scalableTail - scalable;
2958 p = (char *) XtMalloc(strlen(scalable) + 10);
2959 while (isdigit(*scalableTail)) scalableTail++;
2960 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2962 p = (char *) XtMalloc(strlen(best) + 1);
2965 if (appData.debugMode) {
2966 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2967 pattern, targetPxlSize, p);
2970 if (missing_count > 0)
2971 XFreeStringList(missing_list);
2972 XFreeFontSet(xDisplay, fntSet);
2974 XFreeFontNames(fonts);
2981 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2982 | GCBackground | GCFunction | GCPlaneMask;
2983 XGCValues gc_values;
2986 gc_values.plane_mask = AllPlanes;
2987 gc_values.line_width = lineGap;
2988 gc_values.line_style = LineSolid;
2989 gc_values.function = GXcopy;
2991 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2992 gc_values.background = XBlackPixel(xDisplay, xScreen);
2993 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2995 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2996 gc_values.background = XWhitePixel(xDisplay, xScreen);
2997 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2998 XSetFont(xDisplay, coordGC, coordFontID);
3000 if (appData.monoMode) {
3001 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3002 gc_values.background = XWhitePixel(xDisplay, xScreen);
3003 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3005 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3006 gc_values.background = XBlackPixel(xDisplay, xScreen);
3007 lightSquareGC = wbPieceGC
3008 = XtGetGC(shellWidget, value_mask, &gc_values);
3010 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3011 gc_values.background = XWhitePixel(xDisplay, xScreen);
3012 darkSquareGC = bwPieceGC
3013 = XtGetGC(shellWidget, value_mask, &gc_values);
3015 if (DefaultDepth(xDisplay, xScreen) == 1) {
3016 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3017 gc_values.function = GXcopyInverted;
3018 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3019 gc_values.function = GXcopy;
3020 if (XBlackPixel(xDisplay, xScreen) == 1) {
3021 bwPieceGC = darkSquareGC;
3022 wbPieceGC = copyInvertedGC;
3024 bwPieceGC = copyInvertedGC;
3025 wbPieceGC = lightSquareGC;
3029 gc_values.foreground = highlightSquareColor;
3030 gc_values.background = highlightSquareColor;
3031 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3033 gc_values.foreground = premoveHighlightColor;
3034 gc_values.background = premoveHighlightColor;
3035 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3037 gc_values.foreground = lightSquareColor;
3038 gc_values.background = darkSquareColor;
3039 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3041 gc_values.foreground = darkSquareColor;
3042 gc_values.background = lightSquareColor;
3043 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3045 gc_values.foreground = jailSquareColor;
3046 gc_values.background = jailSquareColor;
3047 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3049 gc_values.foreground = whitePieceColor;
3050 gc_values.background = darkSquareColor;
3051 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3053 gc_values.foreground = whitePieceColor;
3054 gc_values.background = lightSquareColor;
3055 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3057 gc_values.foreground = whitePieceColor;
3058 gc_values.background = jailSquareColor;
3059 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3061 gc_values.foreground = blackPieceColor;
3062 gc_values.background = darkSquareColor;
3063 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3065 gc_values.foreground = blackPieceColor;
3066 gc_values.background = lightSquareColor;
3067 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3069 gc_values.foreground = blackPieceColor;
3070 gc_values.background = jailSquareColor;
3071 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3075 void loadXIM(xim, xmask, filename, dest, mask)
3088 fp = fopen(filename, "rb");
3090 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3097 for (y=0; y<h; ++y) {
3098 for (x=0; x<h; ++x) {
3103 XPutPixel(xim, x, y, blackPieceColor);
3105 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3108 XPutPixel(xim, x, y, darkSquareColor);
3110 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3113 XPutPixel(xim, x, y, whitePieceColor);
3115 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3118 XPutPixel(xim, x, y, lightSquareColor);
3120 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3126 /* create Pixmap of piece */
3127 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3129 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3132 /* create Pixmap of clipmask
3133 Note: We assume the white/black pieces have the same
3134 outline, so we make only 6 masks. This is okay
3135 since the XPM clipmask routines do the same. */
3137 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3139 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3142 /* now create the 1-bit version */
3143 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3146 values.foreground = 1;
3147 values.background = 0;
3149 /* Don't use XtGetGC, not read only */
3150 maskGC = XCreateGC(xDisplay, *mask,
3151 GCForeground | GCBackground, &values);
3152 XCopyPlane(xDisplay, temp, *mask, maskGC,
3153 0, 0, squareSize, squareSize, 0, 0, 1);
3154 XFreePixmap(xDisplay, temp);
3158 void CreateXIMPieces()
3163 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3168 /* The XSynchronize calls were copied from CreatePieces.
3169 Not sure if needed, but can't hurt */
3170 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3173 /* temp needed by loadXIM() */
3174 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3175 0, 0, ss, ss, AllPlanes, XYPixmap);
3177 if (strlen(appData.pixmapDirectory) == 0) {
3181 if (appData.monoMode) {
3182 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3186 fprintf(stderr, _("\nLoading XIMs...\n"));
3188 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3189 fprintf(stderr, "%d", piece+1);
3190 for (kind=0; kind<4; kind++) {
3191 fprintf(stderr, ".");
3192 sprintf(buf, "%s/%c%s%u.xim",
3193 ExpandPathName(appData.pixmapDirectory),
3194 ToLower(PieceToChar((ChessSquare)piece)),
3196 ximPieceBitmap[kind][piece] =
3197 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3198 0, 0, ss, ss, AllPlanes, XYPixmap);
3199 if (appData.debugMode)
3200 fprintf(stderr, _("(File:%s:) "), buf);
3201 loadXIM(ximPieceBitmap[kind][piece],
3203 &(xpmPieceBitmap[kind][piece]),
3204 &(ximMaskPm[piece%6]));
3206 fprintf(stderr," ");
3208 /* Load light and dark squares */
3209 /* If the LSQ and DSQ pieces don't exist, we will
3210 draw them with solid squares. */
3211 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3212 if (access(buf, 0) != 0) {
3216 fprintf(stderr, _("light square "));
3218 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3219 0, 0, ss, ss, AllPlanes, XYPixmap);
3220 if (appData.debugMode)
3221 fprintf(stderr, _("(File:%s:) "), buf);
3223 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3224 fprintf(stderr, _("dark square "));
3225 sprintf(buf, "%s/dsq%u.xim",
3226 ExpandPathName(appData.pixmapDirectory), ss);
3227 if (appData.debugMode)
3228 fprintf(stderr, _("(File:%s:) "), buf);
3230 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3231 0, 0, ss, ss, AllPlanes, XYPixmap);
3232 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3233 xpmJailSquare = xpmLightSquare;
3235 fprintf(stderr, _("Done.\n"));
3237 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3241 void CreateXPMPieces()
3245 u_int ss = squareSize;
3247 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3248 XpmColorSymbol symbols[4];
3251 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3252 if (appData.debugMode) {
3253 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3254 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3258 /* The XSynchronize calls were copied from CreatePieces.
3259 Not sure if needed, but can't hurt */
3260 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3262 /* Setup translations so piece colors match square colors */
3263 symbols[0].name = "light_piece";
3264 symbols[0].value = appData.whitePieceColor;
3265 symbols[1].name = "dark_piece";
3266 symbols[1].value = appData.blackPieceColor;
3267 symbols[2].name = "light_square";
3268 symbols[2].value = appData.lightSquareColor;
3269 symbols[3].name = "dark_square";
3270 symbols[3].value = appData.darkSquareColor;
3272 attr.valuemask = XpmColorSymbols;
3273 attr.colorsymbols = symbols;
3274 attr.numsymbols = 4;
3276 if (appData.monoMode) {
3277 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3281 if (strlen(appData.pixmapDirectory) == 0) {
3282 XpmPieces* pieces = builtInXpms;
3285 while (pieces->size != squareSize && pieces->size) pieces++;
3286 if (!pieces->size) {
3287 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3290 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3291 for (kind=0; kind<4; kind++) {
3293 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3294 pieces->xpm[piece][kind],
3295 &(xpmPieceBitmap[kind][piece]),
3296 NULL, &attr)) != 0) {
3297 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3304 xpmJailSquare = xpmLightSquare;
3308 fprintf(stderr, _("\nLoading XPMs...\n"));
3311 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3312 fprintf(stderr, "%d ", piece+1);
3313 for (kind=0; kind<4; kind++) {
3314 sprintf(buf, "%s/%c%s%u.xpm",
3315 ExpandPathName(appData.pixmapDirectory),
3316 ToLower(PieceToChar((ChessSquare)piece)),
3318 if (appData.debugMode) {
3319 fprintf(stderr, _("(File:%s:) "), buf);
3321 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3322 &(xpmPieceBitmap[kind][piece]),
3323 NULL, &attr)) != 0) {
3324 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3330 /* Load light and dark squares */
3331 /* If the LSQ and DSQ pieces don't exist, we will
3332 draw them with solid squares. */
3333 fprintf(stderr, _("light square "));
3334 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3335 if (access(buf, 0) != 0) {
3339 if (appData.debugMode)
3340 fprintf(stderr, _("(File:%s:) "), buf);
3342 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3343 &xpmLightSquare, NULL, &attr)) != 0) {
3344 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3347 fprintf(stderr, _("dark square "));
3348 sprintf(buf, "%s/dsq%u.xpm",
3349 ExpandPathName(appData.pixmapDirectory), ss);
3350 if (appData.debugMode) {
3351 fprintf(stderr, _("(File:%s:) "), buf);
3353 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3354 &xpmDarkSquare, NULL, &attr)) != 0) {
3355 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3359 xpmJailSquare = xpmLightSquare;
3360 fprintf(stderr, _("Done.\n"));
3362 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3365 #endif /* HAVE_LIBXPM */
3368 /* No built-in bitmaps */
3373 u_int ss = squareSize;
3375 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3378 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3379 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3380 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3381 ss, kind == SOLID ? 's' : 'o');
3382 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3386 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3390 /* With built-in bitmaps */
3393 BuiltInBits* bib = builtInBits;
3396 u_int ss = squareSize;
3398 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3401 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3403 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3404 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3405 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3406 ss, kind == SOLID ? 's' : 'o');
3407 ReadBitmap(&pieceBitmap[kind][piece], buf,
3408 bib->bits[kind][piece], ss, ss);
3412 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3417 void ReadBitmap(pm, name, bits, wreq, hreq)
3420 unsigned char bits[];
3426 char msg[MSG_SIZ], fullname[MSG_SIZ];
3428 if (*appData.bitmapDirectory != NULLCHAR) {
3429 strcpy(fullname, appData.bitmapDirectory);
3430 strcat(fullname, "/");
3431 strcat(fullname, name);
3432 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3433 &w, &h, pm, &x_hot, &y_hot);
3434 if (errcode != BitmapSuccess) {
3436 case BitmapOpenFailed:
3437 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3439 case BitmapFileInvalid:
3440 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3442 case BitmapNoMemory:
3443 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3447 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3451 fprintf(stderr, _("%s: %s...using built-in\n"),
3453 } else if (w != wreq || h != hreq) {
3455 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3456 programName, fullname, w, h, wreq, hreq);
3462 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3466 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3475 if (lineGap == 0) return;
3476 for (i = 0; i < BOARD_SIZE + 1; i++) {
3477 gridSegments[i].x1 = 0;
3478 gridSegments[i].x2 =
3479 lineGap + BOARD_SIZE * (squareSize + lineGap);
3480 gridSegments[i].y1 = gridSegments[i].y2
3481 = lineGap / 2 + (i * (squareSize + lineGap));
3483 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3484 gridSegments[i + BOARD_SIZE + 1].y2 =
3485 BOARD_SIZE * (squareSize + lineGap);
3486 gridSegments[i + BOARD_SIZE + 1].x1 =
3487 gridSegments[i + BOARD_SIZE + 1].x2
3488 = lineGap / 2 + (i * (squareSize + lineGap));
3492 static void MenuBarSelect(w, addr, index)
3497 XtActionProc proc = (XtActionProc) addr;
3499 (proc)(NULL, NULL, NULL, NULL);
3502 void CreateMenuBarPopup(parent, name, mb)
3512 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3515 XtSetArg(args[j], XtNleftMargin, 20); j++;
3516 XtSetArg(args[j], XtNrightMargin, 20); j++;
3518 while (mi->string != NULL) {
3519 if (strcmp(mi->string, "----") == 0) {
3520 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3523 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3524 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3526 XtAddCallback(entry, XtNcallback,
3527 (XtCallbackProc) MenuBarSelect,
3528 (caddr_t) mi->proc);
3534 Widget CreateMenuBar(mb)
3538 Widget anchor, menuBar;
3540 char menuName[MSG_SIZ];
3543 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3544 XtSetArg(args[j], XtNvSpace, 0); j++;
3545 XtSetArg(args[j], XtNborderWidth, 0); j++;
3546 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3547 formWidget, args, j);
3549 while (mb->name != NULL) {
3550 strcpy(menuName, "menu");
3551 strcat(menuName, mb->name);
3553 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3556 shortName[0] = _(mb->name)[0];
3557 shortName[1] = NULLCHAR;
3558 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3561 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3564 XtSetArg(args[j], XtNborderWidth, 0); j++;
3565 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3567 CreateMenuBarPopup(menuBar, menuName, mb);
3573 Widget CreateButtonBar(mi)
3577 Widget button, buttonBar;
3581 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3583 XtSetArg(args[j], XtNhSpace, 0); j++;
3585 XtSetArg(args[j], XtNborderWidth, 0); j++;
3586 XtSetArg(args[j], XtNvSpace, 0); j++;
3587 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3588 formWidget, args, j);
3590 while (mi->string != NULL) {
3593 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3594 XtSetArg(args[j], XtNborderWidth, 0); j++;
3596 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3597 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3598 buttonBar, args, j);
3599 XtAddCallback(button, XtNcallback,
3600 (XtCallbackProc) MenuBarSelect,
3601 (caddr_t) mi->proc);
3608 CreatePieceMenu(name, color)
3615 ChessSquare selection;
3617 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3618 boardWidget, args, 0);
3620 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3621 String item = pieceMenuStrings[color][i];
3623 if (strcmp(item, "----") == 0) {
3624 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3627 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3628 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3630 selection = pieceMenuTranslation[color][i];
3631 XtAddCallback(entry, XtNcallback,
3632 (XtCallbackProc) PieceMenuSelect,
3633 (caddr_t) selection);
3634 if (selection == WhitePawn || selection == BlackPawn) {
3635 XtSetArg(args[0], XtNpopupOnEntry, entry);
3636 XtSetValues(menu, args, 1);
3649 ChessSquare selection;
3651 whitePieceMenu = CreatePieceMenu("menuW", 0);
3652 blackPieceMenu = CreatePieceMenu("menuB", 1);
3654 XtRegisterGrabAction(PieceMenuPopup, True,
3655 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3656 GrabModeAsync, GrabModeAsync);
3658 XtSetArg(args[0], XtNlabel, _("Drop"));
3659 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3660 boardWidget, args, 1);
3661 for (i = 0; i < DROP_MENU_SIZE; i++) {
3662 String item = dropMenuStrings[i];
3664 if (strcmp(item, "----") == 0) {
3665 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3668 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3669 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3671 selection = dropMenuTranslation[i];
3672 XtAddCallback(entry, XtNcallback,
3673 (XtCallbackProc) DropMenuSelect,
3674 (caddr_t) selection);
3679 void SetupDropMenu()
3687 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3688 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3689 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3690 dmEnables[i].piece);
3691 XtSetSensitive(entry, p != NULL || !appData.testLegality
3692 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3693 && !appData.icsActive));
3695 while (p && *p++ == dmEnables[i].piece) count++;
3696 sprintf(label, "%s %d", dmEnables[i].widget, count);
3698 XtSetArg(args[j], XtNlabel, label); j++;
3699 XtSetValues(entry, args, j);
3703 void PieceMenuPopup(w, event, params, num_params)
3707 Cardinal *num_params;
3710 if (event->type != ButtonPress) return;
3711 if (errorUp) ErrorPopDown();
3715 whichMenu = params[0];
3717 case IcsPlayingWhite:
3718 case IcsPlayingBlack:
3720 case MachinePlaysWhite:
3721 case MachinePlaysBlack:
3722 if (appData.testLegality &&
3723 gameInfo.variant != VariantBughouse &&
3724 gameInfo.variant != VariantCrazyhouse) return;
3726 whichMenu = "menuD";
3732 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3733 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3734 pmFromX = pmFromY = -1;
3738 pmFromX = BOARD_SIZE - 1 - pmFromX;
3740 pmFromY = BOARD_SIZE - 1 - pmFromY;
3742 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3745 static void PieceMenuSelect(w, piece, junk)
3750 if (pmFromX < 0 || pmFromY < 0) return;
3751 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3754 static void DropMenuSelect(w, piece, junk)
3759 if (pmFromX < 0 || pmFromY < 0) return;
3760 DropMenuEvent(piece, pmFromX, pmFromY);
3763 void WhiteClock(w, event, prms, nprms)
3769 if (gameMode == EditPosition || gameMode == IcsExamining) {
3770 SetWhiteToPlayEvent();
3771 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3776 void BlackClock(w, event, prms, nprms)
3782 if (gameMode == EditPosition || gameMode == IcsExamining) {
3783 SetBlackToPlayEvent();
3784 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3791 * If the user selects on a border boundary, return -1; if off the board,
3792 * return -2. Otherwise map the event coordinate to the square.
3794 int EventToSquare(x, limit)
3802 if ((x % (squareSize + lineGap)) >= squareSize)
3804 x /= (squareSize + lineGap);
3810 static void do_flash_delay(msec)
3816 static void drawHighlight(file, rank, gc)
3822 if (lineGap == 0 || appData.blindfold) return;
3825 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3826 (squareSize + lineGap);
3827 y = lineGap/2 + rank * (squareSize + lineGap);
3829 x = lineGap/2 + file * (squareSize + lineGap);
3830 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3831 (squareSize + lineGap);
3834 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3835 squareSize+lineGap, squareSize+lineGap);
3838 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3839 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3842 SetHighlights(fromX, fromY, toX, toY)
3843 int fromX, fromY, toX, toY;
3845 if (hi1X != fromX || hi1Y != fromY) {
3846 if (hi1X >= 0 && hi1Y >= 0) {
3847 drawHighlight(hi1X, hi1Y, lineGC);
3849 if (fromX >= 0 && fromY >= 0) {
3850 drawHighlight(fromX, fromY, highlineGC);
3853 if (hi2X != toX || hi2Y != toY) {
3854 if (hi2X >= 0 && hi2Y >= 0) {
3855 drawHighlight(hi2X, hi2Y, lineGC);
3857 if (toX >= 0 && toY >= 0) {
3858 drawHighlight(toX, toY, highlineGC);
3870 SetHighlights(-1, -1, -1, -1);
3875 SetPremoveHighlights(fromX, fromY, toX, toY)
3876 int fromX, fromY, toX, toY;
3878 if (pm1X != fromX || pm1Y != fromY) {
3879 if (pm1X >= 0 && pm1Y >= 0) {
3880 drawHighlight(pm1X, pm1Y, lineGC);
3882 if (fromX >= 0 && fromY >= 0) {
3883 drawHighlight(fromX, fromY, prelineGC);
3886 if (pm2X != toX || pm2Y != toY) {
3887 if (pm2X >= 0 && pm2Y >= 0) {
3888 drawHighlight(pm2X, pm2Y, lineGC);
3890 if (toX >= 0 && toY >= 0) {
3891 drawHighlight(toX, toY, prelineGC);
3901 ClearPremoveHighlights()
3903 SetPremoveHighlights(-1, -1, -1, -1);
3906 static void BlankSquare(x, y, color, piece, dest)
3911 if (useImages && useImageSqs) {
3915 pm = xpmLightSquare;
3920 case 2: /* neutral */
3925 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3926 squareSize, squareSize, x, y);
3936 case 2: /* neutral */
3941 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3946 I split out the routines to draw a piece so that I could
3947 make a generic flash routine.
3949 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3951 int square_color, x, y;
3954 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3955 switch (square_color) {
3957 case 2: /* neutral */
3959 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3960 ? *pieceToOutline(piece)
3961 : *pieceToSolid(piece),
3962 dest, bwPieceGC, 0, 0,
3963 squareSize, squareSize, x, y);
3966 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3967 ? *pieceToSolid(piece)
3968 : *pieceToOutline(piece),
3969 dest, wbPieceGC, 0, 0,
3970 squareSize, squareSize, x, y);
3975 static void monoDrawPiece(piece, square_color, x, y, dest)
3977 int square_color, x, y;
3980 switch (square_color) {
3982 case 2: /* neutral */
3984 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3985 ? *pieceToOutline(piece)
3986 : *pieceToSolid(piece),
3987 dest, bwPieceGC, 0, 0,
3988 squareSize, squareSize, x, y, 1);
3991 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3992 ? *pieceToSolid(piece)
3993 : *pieceToOutline(piece),
3994 dest, wbPieceGC, 0, 0,
3995 squareSize, squareSize, x, y, 1);
4000 static void colorDrawPiece(piece, square_color, x, y, dest)
4002 int square_color, x, y;
4005 switch (square_color) {
4007 XCopyPlane(xDisplay, *pieceToSolid(piece),
4008 dest, (int) piece < (int) BlackPawn
4009 ? wlPieceGC : blPieceGC, 0, 0,
4010 squareSize, squareSize, x, y, 1);
4013 XCopyPlane(xDisplay, *pieceToSolid(piece),
4014 dest, (int) piece < (int) BlackPawn
4015 ? wdPieceGC : bdPieceGC, 0, 0,
4016 squareSize, squareSize, x, y, 1);
4018 case 2: /* neutral */
4020 XCopyPlane(xDisplay, *pieceToSolid(piece),
4021 dest, (int) piece < (int) BlackPawn
4022 ? wjPieceGC : bjPieceGC, 0, 0,
4023 squareSize, squareSize, x, y, 1);
4028 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4030 int square_color, x, y;
4035 switch (square_color) {
4037 case 2: /* neutral */
4039 if ((int)piece < (int) BlackPawn) {
4047 if ((int)piece < (int) BlackPawn) {
4055 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4056 dest, wlPieceGC, 0, 0,
4057 squareSize, squareSize, x, y);
4060 typedef void (*DrawFunc)();
4062 DrawFunc ChooseDrawFunc()
4064 if (appData.monoMode) {
4065 if (DefaultDepth(xDisplay, xScreen) == 1) {
4066 return monoDrawPiece_1bit;
4068 return monoDrawPiece;
4072 return colorDrawPieceImage;
4074 return colorDrawPiece;
4078 void DrawSquare(row, column, piece, do_flash)
4079 int row, column, do_flash;
4082 int square_color, x, y, direction, font_ascent, font_descent;
4085 XCharStruct overall;
4089 /* Calculate delay in milliseconds (2-delays per complete flash) */
4090 flash_delay = 500 / appData.flashRate;
4093 x = lineGap + ((BOARD_SIZE-1)-column) *
4094 (squareSize + lineGap);
4095 y = lineGap + row * (squareSize + lineGap);
4097 x = lineGap + column * (squareSize + lineGap);
4098 y = lineGap + ((BOARD_SIZE-1)-row) *
4099 (squareSize + lineGap);
4102 square_color = ((column + row) % 2) == 1;
4104 if (piece == EmptySquare || appData.blindfold) {
4105 BlankSquare(x, y, square_color, piece, xBoardWindow);
4107 drawfunc = ChooseDrawFunc();
4108 if (do_flash && appData.flashCount > 0) {
4109 for (i=0; i<appData.flashCount; ++i) {
4111 drawfunc(piece, square_color, x, y, xBoardWindow);
4112 XSync(xDisplay, False);
4113 do_flash_delay(flash_delay);
4115 BlankSquare(x, y, square_color, piece, xBoardWindow);
4116 XSync(xDisplay, False);
4117 do_flash_delay(flash_delay);
4120 drawfunc(piece, square_color, x, y, xBoardWindow);
4123 string[1] = NULLCHAR;
4124 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4125 string[0] = 'a' + column;
4126 XTextExtents(coordFontStruct, string, 1, &direction,
4127 &font_ascent, &font_descent, &overall);
4128 if (appData.monoMode) {
4129 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4130 x + squareSize - overall.width - 2,
4131 y + squareSize - font_descent - 1, string, 1);
4133 XDrawString(xDisplay, xBoardWindow, coordGC,
4134 x + squareSize - overall.width - 2,
4135 y + squareSize - font_descent - 1, string, 1);
4138 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4139 string[0] = '1' + row;
4140 XTextExtents(coordFontStruct, string, 1, &direction,
4141 &font_ascent, &font_descent, &overall);
4142 if (appData.monoMode) {
4143 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4144 x + 2, y + font_ascent + 1, string, 1);
4146 XDrawString(xDisplay, xBoardWindow, coordGC,
4147 x + 2, y + font_ascent + 1, string, 1);
4153 /* Why is this needed on some versions of X? */
4154 void EventProc(widget, unused, event)
4159 if (!XtIsRealized(widget))
4162 switch (event->type) {
4164 if (event->xexpose.count > 0) return; /* no clipping is done */
4165 XDrawPosition(widget, True, NULL);
4173 void DrawPosition(fullRedraw, board)
4174 /*Boolean*/int fullRedraw;
4177 XDrawPosition(boardWidget, fullRedraw, board);
4180 /* Returns 1 if there are "too many" differences between b1 and b2
4181 (i.e. more than 1 move was made) */
4182 static int too_many_diffs(b1, b2)
4188 for (i=0; i<BOARD_SIZE; ++i) {
4189 for (j=0; j<BOARD_SIZE; ++j) {
4190 if (b1[i][j] != b2[i][j]) {
4191 if (++c > 4) /* Castling causes 4 diffs */
4200 /* Matrix describing castling maneuvers */
4201 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4202 static int castling_matrix[4][5] = {
4203 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4204 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4205 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4206 { 7, 7, 4, 5, 6 } /* 0-0, black */
4209 /* Checks whether castling occurred. If it did, *rrow and *rcol
4210 are set to the destination (row,col) of the rook that moved.
4212 Returns 1 if castling occurred, 0 if not.
4214 Note: Only handles a max of 1 castling move, so be sure
4215 to call too_many_diffs() first.
4217 static int check_castle_draw(newb, oldb, rrow, rcol)
4224 /* For each type of castling... */
4225 for (i=0; i<4; ++i) {
4226 r = castling_matrix[i];
4228 /* Check the 4 squares involved in the castling move */
4230 for (j=1; j<=4; ++j) {
4231 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4238 /* All 4 changed, so it must be a castling move */
4247 static int damage[BOARD_SIZE][BOARD_SIZE];
4250 * event handler for redrawing the board
4252 void XDrawPosition(w, repaint, board)
4254 /*Boolean*/int repaint;
4258 static int lastFlipView = 0;
4259 static int lastBoardValid = 0;
4260 static Board lastBoard;
4264 if (board == NULL) {
4265 if (!lastBoardValid) return;
4268 if (!lastBoardValid || lastFlipView != flipView) {
4269 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4270 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4275 * It would be simpler to clear the window with XClearWindow()
4276 * but this causes a very distracting flicker.
4279 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4281 /* If too much changes (begin observing new game, etc.), don't
4283 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4285 /* Special check for castling so we don't flash both the king
4286 and the rook (just flash the king). */
4288 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4289 /* Draw rook with NO flashing. King will be drawn flashing later */
4290 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4291 lastBoard[rrow][rcol] = board[rrow][rcol];
4295 /* First pass -- Draw (newly) empty squares and repair damage.
4296 This prevents you from having a piece show up twice while it
4297 is flashing on its new square */
4298 for (i = 0; i < BOARD_SIZE; i++)
4299 for (j = 0; j < BOARD_SIZE; j++)
4300 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4302 DrawSquare(i, j, board[i][j], 0);
4303 damage[i][j] = False;
4306 /* Second pass -- Draw piece(s) in new position and flash them */
4307 for (i = 0; i < BOARD_SIZE; i++)
4308 for (j = 0; j < BOARD_SIZE; j++)
4309 if (board[i][j] != lastBoard[i][j]) {
4310 DrawSquare(i, j, board[i][j], do_flash);
4314 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4315 gridSegments, (BOARD_SIZE + 1) * 2);
4317 for (i = 0; i < BOARD_SIZE; i++)
4318 for (j = 0; j < BOARD_SIZE; j++) {
4319 DrawSquare(i, j, board[i][j], 0);
4320 damage[i][j] = False;
4324 CopyBoard(lastBoard, board);
4326 lastFlipView = flipView;
4328 /* Draw highlights */
4329 if (pm1X >= 0 && pm1Y >= 0) {
4330 drawHighlight(pm1X, pm1Y, prelineGC);
4332 if (pm2X >= 0 && pm2Y >= 0) {
4333 drawHighlight(pm2X, pm2Y, prelineGC);
4335 if (hi1X >= 0 && hi1Y >= 0) {
4336 drawHighlight(hi1X, hi1Y, highlineGC);
4338 if (hi2X >= 0 && hi2Y >= 0) {
4339 drawHighlight(hi2X, hi2Y, highlineGC);
4342 /* If piece being dragged around board, must redraw that too */
4345 XSync(xDisplay, False);
4350 * event handler for redrawing the board
4352 void DrawPositionProc(w, event, prms, nprms)
4358 XDrawPosition(w, True, NULL);
4363 * event handler for parsing user moves
4365 void HandleUserMove(w, event, prms, nprms)
4372 Boolean saveAnimate;
4373 static int second = 0;
4375 if (w != boardWidget || errorExitStatus != -1) return;
4377 if (event->type == ButtonPress) ErrorPopDown();
4380 if (event->type == ButtonPress) {
4381 XtPopdown(promotionShell);
4382 XtDestroyWidget(promotionShell);
4383 promotionUp = False;
4391 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4392 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4393 if (!flipView && y >= 0) {
4394 y = BOARD_SIZE - 1 - y;
4396 if (flipView && x >= 0) {
4397 x = BOARD_SIZE - 1 - x;
4401 if (event->type == ButtonPress) {
4403 if (OKToStartUserMove(x, y)) {
4407 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4408 if (appData.highlightDragging) {
4409 SetHighlights(x, y, -1, -1);
4417 if (event->type == ButtonPress && gameMode != EditPosition &&
4421 /* Check if clicking again on the same color piece */
4422 fromP = boards[currentMove][fromY][fromX];
4423 toP = boards[currentMove][y][x];
4424 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4425 WhitePawn <= toP && toP <= WhiteKing) ||
4426 (BlackPawn <= fromP && fromP <= BlackKing &&
4427 BlackPawn <= toP && toP <= BlackKing)) {
4428 /* Clicked again on same color piece -- changed his mind */
4429 second = (x == fromX && y == fromY);
4430 if (appData.highlightDragging) {
4431 SetHighlights(x, y, -1, -1);
4435 if (OKToStartUserMove(x, y)) {
4438 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4444 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4445 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4446 if (appData.animateDragging) {
4447 /* Undo animation damage if any */
4448 DrawPosition(FALSE, NULL);
4451 /* Second up/down in same square; just abort move */
4456 ClearPremoveHighlights();
4458 /* First upclick in same square; start click-click mode */
4459 SetHighlights(x, y, -1, -1);
4464 /* Completed move */
4467 saveAnimate = appData.animate;
4468 if (event->type == ButtonPress) {
4469 /* Finish clickclick move */
4470 if (appData.animate || appData.highlightLastMove) {
4471 SetHighlights(fromX, fromY, toX, toY);
4476 /* Finish drag move */
4477 if (appData.highlightLastMove) {
4478 SetHighlights(fromX, fromY, toX, toY);
4482 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4483 /* Don't animate move and drag both */
4484 appData.animate = FALSE;
4486 if (IsPromotion(fromX, fromY, toX, toY)) {
4487 if (appData.alwaysPromoteToQueen) {
4488 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4489 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4490 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4493 SetHighlights(fromX, fromY, toX, toY);
4497 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4498 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4499 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4502 appData.animate = saveAnimate;
4503 if (appData.animate || appData.animateDragging) {
4504 /* Undo animation damage if needed */
4505 DrawPosition(FALSE, NULL);
4509 void AnimateUserMove (Widget w, XEvent * event,
4510 String * params, Cardinal * nParams)
4512 DragPieceMove(event->xmotion.x, event->xmotion.y);
4515 Widget CommentCreate(name, text, mutable, callback, lines)
4517 int /*Boolean*/ mutable;
4518 XtCallbackProc callback;
4522 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4527 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4528 XtGetValues(boardWidget, args, j);
4531 XtSetArg(args[j], XtNresizable, True); j++;
4534 XtCreatePopupShell(name, topLevelShellWidgetClass,
4535 shellWidget, args, j);
4538 XtCreatePopupShell(name, transientShellWidgetClass,
4539 shellWidget, args, j);
4542 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4543 layoutArgs, XtNumber(layoutArgs));
4545 XtCreateManagedWidget("form", formWidgetClass, layout,
4546 formArgs, XtNumber(formArgs));
4550 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4551 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4553 XtSetArg(args[j], XtNstring, text); j++;
4554 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4555 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4556 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4557 XtSetArg(args[j], XtNright, XtChainRight); j++;
4558 XtSetArg(args[j], XtNresizable, True); j++;
4559 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4561 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4563 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4564 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4566 XtSetArg(args[j], XtNautoFill, True); j++;
4567 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4569 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4573 XtSetArg(args[j], XtNfromVert, edit); j++;
4574 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4575 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4576 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4577 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4579 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4580 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4583 XtSetArg(args[j], XtNfromVert, edit); j++;
4584 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4585 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4586 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4587 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4588 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4590 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4591 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4594 XtSetArg(args[j], XtNfromVert, edit); j++;
4595 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4596 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4597 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4598 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4599 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4601 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4602 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4605 XtSetArg(args[j], XtNfromVert, edit); j++;
4606 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4607 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4608 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4609 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4611 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4612 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4615 XtSetArg(args[j], XtNfromVert, edit); j++;
4616 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4617 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4618 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4619 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4620 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4622 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4623 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4626 XtRealizeWidget(shell);
4628 if (commentX == -1) {
4631 Dimension pw_height;
4632 Dimension ew_height;
4635 XtSetArg(args[j], XtNheight, &ew_height); j++;
4636 XtGetValues(edit, args, j);
4639 XtSetArg(args[j], XtNheight, &pw_height); j++;
4640 XtGetValues(shell, args, j);
4641 commentH = pw_height + (lines - 1) * ew_height;
4642 commentW = bw_width - 16;
4644 XSync(xDisplay, False);
4646 /* This code seems to tickle an X bug if it is executed too soon
4647 after xboard starts up. The coordinates get transformed as if
4648 the main window was positioned at (0, 0).
4650 XtTranslateCoords(shellWidget,
4651 (bw_width - commentW) / 2, 0 - commentH / 2,
4652 &commentX, &commentY);
4654 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4655 RootWindowOfScreen(XtScreen(shellWidget)),
4656 (bw_width - commentW) / 2, 0 - commentH / 2,
4661 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4664 XtSetArg(args[j], XtNheight, commentH); j++;
4665 XtSetArg(args[j], XtNwidth, commentW); j++;
4666 XtSetArg(args[j], XtNx, commentX); j++;
4667 XtSetArg(args[j], XtNy, commentY); j++;
4668 XtSetValues(shell, args, j);
4669 XtSetKeyboardFocus(shell, edit);
4674 /* Used for analysis window and ICS input window */
4675 Widget MiscCreate(name, text, mutable, callback, lines)
4677 int /*Boolean*/ mutable;
4678 XtCallbackProc callback;
4682 Widget shell, layout, form, edit;
4684 Dimension bw_width, pw_height, ew_height, w, h;
4690 XtSetArg(args[j], XtNresizable, True); j++;
4693 XtCreatePopupShell(name, topLevelShellWidgetClass,
4694 shellWidget, args, j);
4697 XtCreatePopupShell(name, transientShellWidgetClass,
4698 shellWidget, args, j);
4701 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4702 layoutArgs, XtNumber(layoutArgs));
4704 XtCreateManagedWidget("form", formWidgetClass, layout,
4705 formArgs, XtNumber(formArgs));
4709 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4710 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4712 XtSetArg(args[j], XtNstring, text); j++;
4713 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4714 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4715 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4716 XtSetArg(args[j], XtNright, XtChainRight); j++;
4717 XtSetArg(args[j], XtNresizable, True); j++;
4719 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4721 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4722 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4724 XtSetArg(args[j], XtNautoFill, True); j++;
4725 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4727 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4729 XtRealizeWidget(shell);
4732 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4733 XtGetValues(boardWidget, args, j);
4736 XtSetArg(args[j], XtNheight, &ew_height); j++;
4737 XtGetValues(edit, args, j);
4740 XtSetArg(args[j], XtNheight, &pw_height); j++;
4741 XtGetValues(shell, args, j);
4742 h = pw_height + (lines - 1) * ew_height;
4745 XSync(xDisplay, False);
4747 /* This code seems to tickle an X bug if it is executed too soon
4748 after xboard starts up. The coordinates get transformed as if
4749 the main window was positioned at (0, 0).
4751 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4753 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4754 RootWindowOfScreen(XtScreen(shellWidget)),
4755 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4759 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4762 XtSetArg(args[j], XtNheight, h); j++;
4763 XtSetArg(args[j], XtNwidth, w); j++;
4764 XtSetArg(args[j], XtNx, x); j++;
4765 XtSetArg(args[j], XtNy, y); j++;
4766 XtSetValues(shell, args, j);
4772 static int savedIndex; /* gross that this is global */
4774 void EditCommentPopUp(index, title, text)
4783 if (text == NULL) text = "";
4785 if (editShell == NULL) {
4787 CommentCreate(title, text, True, EditCommentCallback, 4);
4788 XtRealizeWidget(editShell);
4789 CatchDeleteWindow(editShell, "EditCommentPopDown");
4791 edit = XtNameToWidget(editShell, "*form.text");
4793 XtSetArg(args[j], XtNstring, text); j++;
4794 XtSetValues(edit, args, j);
4796 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4797 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4798 XtSetValues(editShell, args, j);
4801 XtPopup(editShell, XtGrabNone);
4805 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4806 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4810 void EditCommentCallback(w, client_data, call_data)
4812 XtPointer client_data, call_data;
4820 XtSetArg(args[j], XtNlabel, &name); j++;
4821 XtGetValues(w, args, j);
4823 if (strcmp(name, _("ok")) == 0) {
4824 edit = XtNameToWidget(editShell, "*form.text");
4826 XtSetArg(args[j], XtNstring, &val); j++;
4827 XtGetValues(edit, args, j);
4828 ReplaceComment(savedIndex, val);
4829 EditCommentPopDown();
4830 } else if (strcmp(name, _("cancel")) == 0) {
4831 EditCommentPopDown();
4832 } else if (strcmp(name, _("clear")) == 0) {
4833 edit = XtNameToWidget(editShell, "*form.text");
4834 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4835 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4839 void EditCommentPopDown()
4844 if (!editUp) return;
4846 XtSetArg(args[j], XtNx, &commentX); j++;
4847 XtSetArg(args[j], XtNy, &commentY); j++;
4848 XtSetArg(args[j], XtNheight, &commentH); j++;
4849 XtSetArg(args[j], XtNwidth, &commentW); j++;
4850 XtGetValues(editShell, args, j);
4851 XtPopdown(editShell);
4854 XtSetArg(args[j], XtNleftBitmap, None); j++;
4855 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4859 void ICSInputBoxPopUp()
4864 char *title = _("ICS Input");
4867 if (ICSInputShell == NULL) {
4868 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4869 tr = XtParseTranslationTable(ICSInputTranslations);
4870 edit = XtNameToWidget(ICSInputShell, "*form.text");
4871 XtOverrideTranslations(edit, tr);
4872 XtRealizeWidget(ICSInputShell);
4873 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4876 edit = XtNameToWidget(ICSInputShell, "*form.text");
4878 XtSetArg(args[j], XtNstring, ""); j++;
4879 XtSetValues(edit, args, j);
4881 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4882 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4883 XtSetValues(ICSInputShell, args, j);
4886 XtPopup(ICSInputShell, XtGrabNone);
4887 XtSetKeyboardFocus(ICSInputShell, edit);
4889 ICSInputBoxUp = True;
4891 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4892 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4896 void ICSInputSendText()
4903 edit = XtNameToWidget(ICSInputShell, "*form.text");
4905 XtSetArg(args[j], XtNstring, &val); j++;
4906 XtGetValues(edit, args, j);
4907 SendMultiLineToICS(val);
4908 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4909 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4912 void ICSInputBoxPopDown()
4917 if (!ICSInputBoxUp) return;
4919 XtPopdown(ICSInputShell);
4920 ICSInputBoxUp = False;
4922 XtSetArg(args[j], XtNleftBitmap, None); j++;
4923 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4927 void CommentPopUp(title, text)
4934 if (commentShell == NULL) {
4936 CommentCreate(title, text, False, CommentCallback, 4);
4937 XtRealizeWidget(commentShell);
4938 CatchDeleteWindow(commentShell, "CommentPopDown");
4940 edit = XtNameToWidget(commentShell, "*form.text");
4942 XtSetArg(args[j], XtNstring, text); j++;
4943 XtSetValues(edit, args, j);
4945 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4946 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4947 XtSetValues(commentShell, args, j);
4950 XtPopup(commentShell, XtGrabNone);
4951 XSync(xDisplay, False);
4956 void AnalysisPopUp(title, text)
4963 if (analysisShell == NULL) {
4964 analysisShell = MiscCreate(title, text, False, NULL, 4);
4965 XtRealizeWidget(analysisShell);
4966 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4969 edit = XtNameToWidget(analysisShell, "*form.text");
4971 XtSetArg(args[j], XtNstring, text); j++;
4972 XtSetValues(edit, args, j);
4974 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4975 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4976 XtSetValues(analysisShell, args, j);
4980 XtPopup(analysisShell, XtGrabNone);
4982 XSync(xDisplay, False);
4987 void CommentCallback(w, client_data, call_data)
4989 XtPointer client_data, call_data;
4996 XtSetArg(args[j], XtNlabel, &name); j++;
4997 XtGetValues(w, args, j);
4999 if (strcmp(name, _("close")) == 0) {
5001 } else if (strcmp(name, _("edit")) == 0) {
5008 void CommentPopDown()
5013 if (!commentUp) return;
5015 XtSetArg(args[j], XtNx, &commentX); j++;
5016 XtSetArg(args[j], XtNy, &commentY); j++;
5017 XtSetArg(args[j], XtNwidth, &commentW); j++;
5018 XtSetArg(args[j], XtNheight, &commentH); j++;
5019 XtGetValues(commentShell, args, j);
5020 XtPopdown(commentShell);
5021 XSync(xDisplay, False);
5025 void AnalysisPopDown()
5027 if (!analysisUp) return;
5028 XtPopdown(analysisShell);
5029 XSync(xDisplay, False);
5034 void FileNamePopUp(label, def, proc, openMode)
5041 Widget popup, layout, dialog, edit;
5047 fileProc = proc; /* I can't see a way not */
5048 fileOpenMode = openMode; /* to use globals here */
5051 XtSetArg(args[i], XtNresizable, True); i++;
5052 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5053 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5054 fileNameShell = popup =
5055 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5056 shellWidget, args, i);
5059 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5060 layoutArgs, XtNumber(layoutArgs));
5063 XtSetArg(args[i], XtNlabel, label); i++;
5064 XtSetArg(args[i], XtNvalue, def); i++;
5065 XtSetArg(args[i], XtNborderWidth, 0); i++;
5066 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5069 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5070 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5071 (XtPointer) dialog);
5073 XtRealizeWidget(popup);
5074 CatchDeleteWindow(popup, "FileNamePopDown");
5076 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5077 &x, &y, &win_x, &win_y, &mask);
5079 XtSetArg(args[0], XtNx, x - 10);
5080 XtSetArg(args[1], XtNy, y - 30);
5081 XtSetValues(popup, args, 2);
5083 XtPopup(popup, XtGrabExclusive);
5086 edit = XtNameToWidget(dialog, "*value");
5087 XtSetKeyboardFocus(popup, edit);
5090 void FileNamePopDown()
5092 if (!filenameUp) return;
5093 XtPopdown(fileNameShell);
5094 XtDestroyWidget(fileNameShell);
5099 void FileNameCallback(w, client_data, call_data)
5101 XtPointer client_data, call_data;
5106 XtSetArg(args[0], XtNlabel, &name);
5107 XtGetValues(w, args, 1);
5109 if (strcmp(name, _("cancel")) == 0) {
5114 FileNameAction(w, NULL, NULL, NULL);
5117 void FileNameAction(w, event, prms, nprms)
5129 name = XawDialogGetValueString(w = XtParent(w));
5131 if ((name != NULL) && (*name != NULLCHAR)) {
5133 XtPopdown(w = XtParent(XtParent(w)));
5137 p = strrchr(buf, ' ');
5144 fullname = ExpandPathName(buf);
5146 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5149 f = fopen(fullname, fileOpenMode);
5151 DisplayError(_("Failed to open file"), errno);
5153 (void) (*fileProc)(f, index, buf);
5160 XtPopdown(w = XtParent(XtParent(w)));
5166 void PromotionPopUp()
5169 Widget dialog, layout;
5171 Dimension bw_width, pw_width;
5175 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5176 XtGetValues(boardWidget, args, j);
5179 XtSetArg(args[j], XtNresizable, True); j++;
5180 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5182 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5183 shellWidget, args, j);
5185 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5186 layoutArgs, XtNumber(layoutArgs));
5189 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5190 XtSetArg(args[j], XtNborderWidth, 0); j++;
5191 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5194 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5195 (XtPointer) dialog);
5196 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5197 (XtPointer) dialog);
5198 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5199 (XtPointer) dialog);
5200 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5201 (XtPointer) dialog);
5202 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5203 gameInfo.variant == VariantGiveaway) {
5204 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5205 (XtPointer) dialog);
5207 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5208 (XtPointer) dialog);
5210 XtRealizeWidget(promotionShell);
5211 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5214 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5215 XtGetValues(promotionShell, args, j);
5217 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5218 lineGap + squareSize/3 +
5219 ((toY == 7) ^ (flipView) ?
5220 0 : 6*(squareSize + lineGap)), &x, &y);
5223 XtSetArg(args[j], XtNx, x); j++;
5224 XtSetArg(args[j], XtNy, y); j++;
5225 XtSetValues(promotionShell, args, j);
5227 XtPopup(promotionShell, XtGrabNone);
5232 void PromotionPopDown()
5234 if (!promotionUp) return;
5235 XtPopdown(promotionShell);
5236 XtDestroyWidget(promotionShell);
5237 promotionUp = False;
5240 void PromotionCallback(w, client_data, call_data)
5242 XtPointer client_data, call_data;
5248 XtSetArg(args[0], XtNlabel, &name);
5249 XtGetValues(w, args, 1);
5253 if (fromX == -1) return;
5255 if (strcmp(name, _("cancel")) == 0) {
5259 } else if (strcmp(name, _("Knight")) == 0) {
5262 promoChar = ToLower(name[0]);
5265 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5267 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5268 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5273 void ErrorCallback(w, client_data, call_data)
5275 XtPointer client_data, call_data;
5278 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5280 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5286 if (!errorUp) return;
5288 XtPopdown(errorShell);
5289 XtDestroyWidget(errorShell);
5290 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5293 void ErrorPopUp(title, label, modal)
5294 char *title, *label;
5298 Widget dialog, layout;
5302 Dimension bw_width, pw_width;
5303 Dimension pw_height;
5307 XtSetArg(args[i], XtNresizable, True); i++;
5308 XtSetArg(args[i], XtNtitle, title); i++;
5310 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5311 shellWidget, args, i);
5313 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5314 layoutArgs, XtNumber(layoutArgs));
5317 XtSetArg(args[i], XtNlabel, label); i++;
5318 XtSetArg(args[i], XtNborderWidth, 0); i++;
5319 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5322 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5324 XtRealizeWidget(errorShell);
5325 CatchDeleteWindow(errorShell, "ErrorPopDown");
5328 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5329 XtGetValues(boardWidget, args, i);
5331 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5332 XtSetArg(args[i], XtNheight, &pw_height); i++;
5333 XtGetValues(errorShell, args, i);
5336 /* This code seems to tickle an X bug if it is executed too soon
5337 after xboard starts up. The coordinates get transformed as if
5338 the main window was positioned at (0, 0).
5340 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5341 0 - pw_height + squareSize / 3, &x, &y);
5343 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5344 RootWindowOfScreen(XtScreen(boardWidget)),
5345 (bw_width - pw_width) / 2,
5346 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5350 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5353 XtSetArg(args[i], XtNx, x); i++;
5354 XtSetArg(args[i], XtNy, y); i++;
5355 XtSetValues(errorShell, args, i);
5358 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5361 /* Disable all user input other than deleting the window */
5362 static int frozen = 0;
5366 /* Grab by a widget that doesn't accept input */
5367 XtAddGrab(messageWidget, TRUE, FALSE);
5371 /* Undo a FreezeUI */
5374 if (!frozen) return;
5375 XtRemoveGrab(messageWidget);
5379 char *ModeToWidgetName(mode)
5383 case BeginningOfGame:
5384 if (appData.icsActive)
5385 return "menuMode.ICS Client";
5386 else if (appData.noChessProgram ||
5387 *appData.cmailGameName != NULLCHAR)
5388 return "menuMode.Edit Game";
5390 return "menuMode.Machine Black";
5391 case MachinePlaysBlack:
5392 return "menuMode.Machine Black";
5393 case MachinePlaysWhite:
5394 return "menuMode.Machine White";
5396 return "menuMode.Analysis Mode";
5398 return "menuMode.Analyze File";
5399 case TwoMachinesPlay:
5400 return "menuMode.Two Machines";
5402 return "menuMode.Edit Game";
5403 case PlayFromGameFile:
5404 return "menuFile.Load Game";
5406 return "menuMode.Edit Position";
5408 return "menuMode.Training";
5409 case IcsPlayingWhite:
5410 case IcsPlayingBlack:
5414 return "menuMode.ICS Client";
5421 void ModeHighlight()
5424 static int oldPausing = FALSE;
5425 static GameMode oldmode = (GameMode) -1;
5428 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5430 if (pausing != oldPausing) {
5431 oldPausing = pausing;
5433 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5435 XtSetArg(args[0], XtNleftBitmap, None);
5437 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5440 if (appData.showButtonBar) {
5443 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5444 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5446 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5447 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5450 /* Always toggle, don't set. Previous code messes up when
5451 invoked while the button is pressed, as releasing it
5452 toggles the state again. */
5455 XtSetArg(args[0], XtNbackground, &oldbg);
5456 XtSetArg(args[1], XtNforeground, &oldfg);
5457 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5459 XtSetArg(args[0], XtNbackground, oldfg);
5460 XtSetArg(args[1], XtNforeground, oldbg);
5463 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5467 wname = ModeToWidgetName(oldmode);
5468 if (wname != NULL) {
5469 XtSetArg(args[0], XtNleftBitmap, None);
5470 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5472 wname = ModeToWidgetName(gameMode);
5473 if (wname != NULL) {
5474 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5475 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5479 /* Maybe all the enables should be handled here, not just this one */
5480 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5481 gameMode == Training || gameMode == PlayFromGameFile);
5485 * Button/menu procedures
5487 void ResetProc(w, event, prms, nprms)
5497 int LoadGamePopUp(f, gameNumber, title)
5502 cmailMsgLoaded = FALSE;
5503 if (gameNumber == 0) {
5504 int error = GameListBuild(f);
5506 DisplayError(_("Cannot build game list"), error);
5507 } else if (!ListEmpty(&gameList) &&
5508 ((ListGame *) gameList.tailPred)->number > 1) {
5509 GameListPopUp(f, title);
5515 return LoadGame(f, gameNumber, title, FALSE);
5518 void LoadGameProc(w, event, prms, nprms)
5524 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5527 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
5530 void LoadNextGameProc(w, event, prms, nprms)
5539 void LoadPrevGameProc(w, event, prms, nprms)
5548 void ReloadGameProc(w, event, prms, nprms)
5557 void LoadNextPositionProc(w, event, prms, nprms)
5566 void LoadPrevPositionProc(w, event, prms, nprms)
5575 void ReloadPositionProc(w, event, prms, nprms)
5584 void LoadPositionProc(w, event, prms, nprms)
5590 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5593 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5596 void SaveGameProc(w, event, prms, nprms)
5602 FileNamePopUp(_("Save game file name?"),
5603 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5607 void SavePositionProc(w, event, prms, nprms)
5613 FileNamePopUp(_("Save position file name?"),
5614 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5618 void ReloadCmailMsgProc(w, event, prms, nprms)
5624 ReloadCmailMsgEvent(FALSE);
5627 void MailMoveProc(w, event, prms, nprms)
5636 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5637 static char *selected_fen_position=NULL;
5640 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5641 Atom *type_return, XtPointer *value_return,
5642 unsigned long *length_return, int *format_return)
5644 char *selection_tmp;
5646 if (!selected_fen_position) return False; /* should never happen */
5647 if (*target == XA_STRING){
5648 /* note: since no XtSelectionDoneProc was registered, Xt will
5649 * automatically call XtFree on the value returned. So have to
5650 * make a copy of it allocated with XtMalloc */
5651 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5652 strcpy(selection_tmp, selected_fen_position);
5654 *value_return=selection_tmp;
5655 *length_return=strlen(selection_tmp);
5656 *type_return=XA_STRING;
5657 *format_return = 8; /* bits per byte */
5664 /* note: when called from menu all parameters are NULL, so no clue what the
5665 * Widget which was clicked on was, or what the click event was
5667 void CopyPositionProc(w, event, prms, nprms)
5675 if (selected_fen_position) free(selected_fen_position);
5676 selected_fen_position = (char *)PositionToFEN(currentMove);
5677 if (!selected_fen_position) return;
5678 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5680 SendPositionSelection,
5681 NULL/* lose_ownership_proc */ ,
5682 NULL/* transfer_done_proc */);
5684 free(selected_fen_position);
5685 selected_fen_position=NULL;
5689 /* function called when the data to Paste is ready */
5691 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5692 Atom *type, XtPointer value, unsigned long *len, int *format)
5695 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5696 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5697 EditPositionPasteFEN(fenstr);
5701 /* called when Paste Position button is pressed,
5702 * all parameters will be NULL */
5703 void PastePositionProc(w, event, prms, nprms)
5709 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5710 /* (XtSelectionCallbackProc) */ PastePositionCB,
5711 NULL, /* client_data passed to PastePositionCB */
5713 /* better to use the time field from the event that triggered the
5714 * call to this function, but that isn't trivial to get
5722 SendGameSelection(Widget w, Atom *selection, Atom *target,
5723 Atom *type_return, XtPointer *value_return,
5724 unsigned long *length_return, int *format_return)
5726 char *selection_tmp;
5728 if (*target == XA_STRING){
5729 FILE* f = fopen(gameCopyFilename, "r");
5732 if (f == NULL) return False;
5736 selection_tmp = XtMalloc(len + 1);
5737 count = fread(selection_tmp, 1, len, f);
5739 XtFree(selection_tmp);
5742 selection_tmp[len] = NULLCHAR;
5743 *value_return = selection_tmp;
5744 *length_return = len;
5745 *type_return = XA_STRING;
5746 *format_return = 8; /* bits per byte */
5753 /* note: when called from menu all parameters are NULL, so no clue what the
5754 * Widget which was clicked on was, or what the click event was
5756 void CopyGameProc(w, event, prms, nprms)
5764 ret = SaveGameToFile(gameCopyFilename, FALSE);
5767 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5770 NULL/* lose_ownership_proc */ ,
5771 NULL/* transfer_done_proc */);
5774 /* function called when the data to Paste is ready */
5776 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5777 Atom *type, XtPointer value, unsigned long *len, int *format)
5780 if (value == NULL || *len == 0) {
5781 return; /* nothing had been selected to copy */
5783 f = fopen(gamePasteFilename, "w");
5785 DisplayError(_("Can't open temp file"), errno);
5788 fwrite(value, 1, *len, f);
5791 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5794 /* called when Paste Game button is pressed,
5795 * all parameters will be NULL */
5796 void PasteGameProc(w, event, prms, nprms)
5802 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5803 /* (XtSelectionCallbackProc) */ PasteGameCB,
5804 NULL, /* client_data passed to PasteGameCB */
5806 /* better to use the time field from the event that triggered the
5807 * call to this function, but that isn't trivial to get
5817 SaveGameProc(NULL, NULL, NULL, NULL);
5821 void QuitProc(w, event, prms, nprms)
5830 void PauseProc(w, event, prms, nprms)
5840 void MachineBlackProc(w, event, prms, nprms)
5846 MachineBlackEvent();
5849 void MachineWhiteProc(w, event, prms, nprms)
5855 MachineWhiteEvent();
5858 void AnalyzeModeProc(w, event, prms, nprms)
5866 if (!first.analysisSupport) {
5867 sprintf(buf, _("%s does not support analysis"), first.tidy);
5868 DisplayError(buf, 0);
5871 /* icsEngineAnalyze */
5872 if (appData.icsActive) {
5873 if (gameMode != IcsObserving) {
5874 sprintf(buf,_("You are not observing a game"));
5875 DisplayError(buf, 0);
5877 if (appData.icsEngineAnalyze) {
5878 if (appData.debugMode)
5879 fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
5880 appData.icsEngineAnalyze = FALSE;
5887 /* if enable, use want disable icsEngineAnalyze */
5888 if (appData.icsEngineAnalyze) {
5889 appData.icsEngineAnalyze = FALSE;
5894 appData.icsEngineAnalyze = TRUE;
5895 if (appData.debugMode)
5896 fprintf(debugFP, "ICS engine analyze starting... \n");
5899 if (!appData.showThinking)
5900 ShowThinkingProc(w,event,prms,nprms);
5904 void AnalyzeFileProc(w, event, prms, nprms)
5910 if (!first.analysisSupport) {
5912 sprintf(buf, _("%s does not support analysis"), first.tidy);
5913 DisplayError(buf, 0);
5918 if (!appData.showThinking)
5919 ShowThinkingProc(w,event,prms,nprms);
5922 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5923 AnalysisPeriodicEvent(1);
5926 void TwoMachinesProc(w, event, prms, nprms)
5935 void IcsClientProc(w, event, prms, nprms)
5944 void EditGameProc(w, event, prms, nprms)
5953 void EditPositionProc(w, event, prms, nprms)
5959 EditPositionEvent();
5962 void TrainingProc(w, event, prms, nprms)
5971 void EditCommentProc(w, event, prms, nprms)
5978 EditCommentPopDown();
5984 void IcsInputBoxProc(w, event, prms, nprms)
5990 if (ICSInputBoxUp) {
5991 ICSInputBoxPopDown();
5997 void AcceptProc(w, event, prms, nprms)
6006 void DeclineProc(w, event, prms, nprms)
6015 void RematchProc(w, event, prms, nprms)
6024 void CallFlagProc(w, event, prms, nprms)
6033 void DrawProc(w, event, prms, nprms)
6042 void AbortProc(w, event, prms, nprms)
6051 void AdjournProc(w, event, prms, nprms)
6060 void ResignProc(w, event, prms, nprms)
6069 void EnterKeyProc(w, event, prms, nprms)
6075 if (ICSInputBoxUp == True)
6079 void StopObservingProc(w, event, prms, nprms)
6085 StopObservingEvent();
6088 void StopExaminingProc(w, event, prms, nprms)
6094 StopExaminingEvent();
6098 void ForwardProc(w, event, prms, nprms)
6108 void BackwardProc(w, event, prms, nprms)
6117 void ToStartProc(w, event, prms, nprms)
6126 void ToEndProc(w, event, prms, nprms)
6135 void RevertProc(w, event, prms, nprms)
6144 void TruncateGameProc(w, event, prms, nprms)
6150 TruncateGameEvent();
6152 void RetractMoveProc(w, event, prms, nprms)
6161 void MoveNowProc(w, event, prms, nprms)
6171 void AlwaysQueenProc(w, event, prms, nprms)
6179 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6181 if (appData.alwaysPromoteToQueen) {
6182 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6184 XtSetArg(args[0], XtNleftBitmap, None);
6186 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6190 void AnimateDraggingProc(w, event, prms, nprms)
6198 appData.animateDragging = !appData.animateDragging;
6200 if (appData.animateDragging) {
6201 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6204 XtSetArg(args[0], XtNleftBitmap, None);
6206 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6210 void AnimateMovingProc(w, event, prms, nprms)
6218 appData.animate = !appData.animate;
6220 if (appData.animate) {
6221 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6224 XtSetArg(args[0], XtNleftBitmap, None);
6226 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6230 void AutocommProc(w, event, prms, nprms)
6238 appData.autoComment = !appData.autoComment;
6240 if (appData.autoComment) {
6241 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6243 XtSetArg(args[0], XtNleftBitmap, None);
6245 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6250 void AutoflagProc(w, event, prms, nprms)
6258 appData.autoCallFlag = !appData.autoCallFlag;
6260 if (appData.autoCallFlag) {
6261 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6263 XtSetArg(args[0], XtNleftBitmap, None);
6265 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6269 void AutoflipProc(w, event, prms, nprms)
6277 appData.autoFlipView = !appData.autoFlipView;
6279 if (appData.autoFlipView) {
6280 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6282 XtSetArg(args[0], XtNleftBitmap, None);
6284 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6288 void AutobsProc(w, event, prms, nprms)
6296 appData.autoObserve = !appData.autoObserve;
6298 if (appData.autoObserve) {
6299 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6301 XtSetArg(args[0], XtNleftBitmap, None);
6303 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6307 void AutoraiseProc(w, event, prms, nprms)
6315 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6317 if (appData.autoRaiseBoard) {
6318 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6320 XtSetArg(args[0], XtNleftBitmap, None);
6322 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6326 void AutosaveProc(w, event, prms, nprms)
6334 appData.autoSaveGames = !appData.autoSaveGames;
6336 if (appData.autoSaveGames) {
6337 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6339 XtSetArg(args[0], XtNleftBitmap, None);
6341 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6345 void BlindfoldProc(w, event, prms, nprms)
6353 appData.blindfold = !appData.blindfold;
6355 if (appData.blindfold) {
6356 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6358 XtSetArg(args[0], XtNleftBitmap, None);
6360 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6363 DrawPosition(True, NULL);
6366 void TestLegalityProc(w, event, prms, nprms)
6374 appData.testLegality = !appData.testLegality;
6376 if (appData.testLegality) {
6377 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6379 XtSetArg(args[0], XtNleftBitmap, None);
6381 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6386 void FlashMovesProc(w, event, prms, nprms)
6394 if (appData.flashCount == 0) {
6395 appData.flashCount = 3;
6397 appData.flashCount = -appData.flashCount;
6400 if (appData.flashCount > 0) {
6401 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6403 XtSetArg(args[0], XtNleftBitmap, None);
6405 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6409 void FlipViewProc(w, event, prms, nprms)
6415 flipView = !flipView;
6416 DrawPosition(True, NULL);
6419 void GetMoveListProc(w, event, prms, nprms)
6427 appData.getMoveList = !appData.getMoveList;
6429 if (appData.getMoveList) {
6430 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6433 XtSetArg(args[0], XtNleftBitmap, None);
6435 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6440 void HighlightDraggingProc(w, event, prms, nprms)
6448 appData.highlightDragging = !appData.highlightDragging;
6450 if (appData.highlightDragging) {
6451 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6453 XtSetArg(args[0], XtNleftBitmap, None);
6455 XtSetValues(XtNameToWidget(menuBarWidget,
6456 "menuOptions.Highlight Dragging"), args, 1);
6460 void HighlightLastMoveProc(w, event, prms, nprms)
6468 appData.highlightLastMove = !appData.highlightLastMove;
6470 if (appData.highlightLastMove) {
6471 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6473 XtSetArg(args[0], XtNleftBitmap, None);
6475 XtSetValues(XtNameToWidget(menuBarWidget,
6476 "menuOptions.Highlight Last Move"), args, 1);
6479 void IcsAlarmProc(w, event, prms, nprms)
6487 appData.icsAlarm = !appData.icsAlarm;
6489 if (appData.icsAlarm) {
6490 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6492 XtSetArg(args[0], XtNleftBitmap, None);
6494 XtSetValues(XtNameToWidget(menuBarWidget,
6495 "menuOptions.ICS Alarm"), args, 1);
6498 void MoveSoundProc(w, event, prms, nprms)
6506 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6508 if (appData.ringBellAfterMoves) {
6509 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6511 XtSetArg(args[0], XtNleftBitmap, None);
6513 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6518 void OldSaveStyleProc(w, event, prms, nprms)
6526 appData.oldSaveStyle = !appData.oldSaveStyle;
6528 if (appData.oldSaveStyle) {
6529 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6531 XtSetArg(args[0], XtNleftBitmap, None);
6533 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6537 void PeriodicUpdatesProc(w, event, prms, nprms)
6545 PeriodicUpdatesEvent(!appData.periodicUpdates);
6547 if (appData.periodicUpdates) {
6548 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6550 XtSetArg(args[0], XtNleftBitmap, None);
6552 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6556 void PonderNextMoveProc(w, event, prms, nprms)
6564 PonderNextMoveEvent(!appData.ponderNextMove);
6566 if (appData.ponderNextMove) {
6567 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6569 XtSetArg(args[0], XtNleftBitmap, None);
6571 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6575 void PopupExitMessageProc(w, event, prms, nprms)
6583 appData.popupExitMessage = !appData.popupExitMessage;
6585 if (appData.popupExitMessage) {
6586 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6588 XtSetArg(args[0], XtNleftBitmap, None);
6590 XtSetValues(XtNameToWidget(menuBarWidget,
6591 "menuOptions.Popup Exit Message"), args, 1);
6594 void PopupMoveErrorsProc(w, event, prms, nprms)
6602 appData.popupMoveErrors = !appData.popupMoveErrors;
6604 if (appData.popupMoveErrors) {
6605 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6607 XtSetArg(args[0], XtNleftBitmap, None);
6609 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6613 void PremoveProc(w, event, prms, nprms)
6621 appData.premove = !appData.premove;
6623 if (appData.premove) {
6624 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6626 XtSetArg(args[0], XtNleftBitmap, None);
6628 XtSetValues(XtNameToWidget(menuBarWidget,
6629 "menuOptions.Premove"), args, 1);
6632 void QuietPlayProc(w, event, prms, nprms)
6640 appData.quietPlay = !appData.quietPlay;
6642 if (appData.quietPlay) {
6643 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6645 XtSetArg(args[0], XtNleftBitmap, None);
6647 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6651 void ShowCoordsProc(w, event, prms, nprms)
6659 appData.showCoords = !appData.showCoords;
6661 if (appData.showCoords) {
6662 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6664 XtSetArg(args[0], XtNleftBitmap, None);
6666 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6669 DrawPosition(True, NULL);
6672 void ShowThinkingProc(w, event, prms, nprms)
6680 ShowThinkingEvent(!appData.showThinking);
6682 if (appData.showThinking) {
6683 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6685 XtSetArg(args[0], XtNleftBitmap, None);
6687 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6691 void InfoProc(w, event, prms, nprms)
6698 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6703 void ManProc(w, event, prms, nprms)
6711 if (nprms && *nprms > 0)
6715 sprintf(buf, "xterm -e man %s &", name);
6719 void HintProc(w, event, prms, nprms)
6728 void BookProc(w, event, prms, nprms)
6737 void AboutProc(w, event, prms, nprms)
6745 char *zippy = " (with Zippy code)";
6749 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6750 programVersion, zippy,
6751 "Copyright 1991 Digital Equipment Corporation",
6752 "Enhancements Copyright 1992-2001 Free Software Foundation",
6753 PRODUCT, " is free software and carries NO WARRANTY;",
6754 "see the file COPYING for more information.");
6755 ErrorPopUp(_("About XBoard"), buf, FALSE);
6758 void DebugProc(w, event, prms, nprms)
6764 appData.debugMode = !appData.debugMode;
6767 void AboutGameProc(w, event, prms, nprms)
6776 void NothingProc(w, event, prms, nprms)
6785 void Iconify(w, event, prms, nprms)
6794 XtSetArg(args[0], XtNiconic, True);
6795 XtSetValues(shellWidget, args, 1);
6798 void DisplayMessage(message, extMessage)
6799 char *message, *extMessage;
6806 sprintf(buf, "%s %s", message, extMessage);
6809 message = extMessage;
6812 XtSetArg(arg, XtNlabel, message);
6813 XtSetValues(messageWidget, &arg, 1);
6816 void DisplayTitle(text)
6821 char title[MSG_SIZ];
6824 if (text == NULL) text = "";
6826 if (appData.titleInWindow) {
6828 XtSetArg(args[i], XtNlabel, text); i++;
6829 XtSetValues(titleWidget, args, i);
6832 if (*text != NULLCHAR) {
6834 strcpy(title, text);
6835 } else if (appData.icsActive) {
6836 sprintf(icon, "%s", appData.icsHost);
6837 sprintf(title, "%s: %s", programName, appData.icsHost);
6838 } else if (appData.cmailGameName[0] != NULLCHAR) {
6839 sprintf(icon, "%s", "CMail");
6840 sprintf(title, "%s: %s", programName, "CMail");
6841 } else if (appData.noChessProgram) {
6842 strcpy(icon, programName);
6843 strcpy(title, programName);
6845 strcpy(icon, first.tidy);
6846 sprintf(title, "%s: %s", programName, first.tidy);
6849 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6850 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6851 XtSetValues(shellWidget, args, i);
6855 void DisplayError(message, error)
6862 if (appData.debugMode || appData.matchMode) {
6863 fprintf(stderr, "%s: %s\n", programName, message);
6866 if (appData.debugMode || appData.matchMode) {
6867 fprintf(stderr, "%s: %s: %s\n",
6868 programName, message, strerror(error));
6870 sprintf(buf, "%s: %s", message, strerror(error));
6873 ErrorPopUp(_("Error"), message, FALSE);
6877 void DisplayMoveError(message)
6882 DrawPosition(FALSE, NULL);
6883 if (appData.debugMode || appData.matchMode) {
6884 fprintf(stderr, "%s: %s\n", programName, message);
6886 if (appData.popupMoveErrors) {
6887 ErrorPopUp(_("Error"), message, FALSE);
6889 DisplayMessage(message, "");
6894 void DisplayFatalError(message, error, status)
6900 errorExitStatus = status;
6902 fprintf(stderr, "%s: %s\n", programName, message);
6904 fprintf(stderr, "%s: %s: %s\n",
6905 programName, message, strerror(error));
6906 sprintf(buf, "%s: %s", message, strerror(error));
6909 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6910 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6916 void DisplayInformation(message)
6920 ErrorPopUp(_("Information"), message, TRUE);
6923 void DisplayNote(message)
6927 ErrorPopUp(_("Note"), message, FALSE);
6931 NullXErrorCheck(dpy, error_event)
6933 XErrorEvent *error_event;
6938 void DisplayIcsInteractionTitle(message)
6941 if (oldICSInteractionTitle == NULL) {
6942 /* Magic to find the old window title, adapted from vim */
6943 char *wina = getenv("WINDOWID");
6945 Window win = (Window) atoi(wina);
6946 Window root, parent, *children;
6947 unsigned int nchildren;
6948 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6950 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6951 if (!XQueryTree(xDisplay, win, &root, &parent,
6952 &children, &nchildren)) break;
6953 if (children) XFree((void *)children);
6954 if (parent == root || parent == 0) break;
6957 XSetErrorHandler(oldHandler);
6959 if (oldICSInteractionTitle == NULL) {
6960 oldICSInteractionTitle = "xterm";
6963 printf("\033]0;%s\007", message);
6967 char pendingReplyPrefix[MSG_SIZ];
6968 ProcRef pendingReplyPR;
6970 void AskQuestionProc(w, event, prms, nprms)
6977 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6981 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6984 void AskQuestionPopDown()
6986 if (!askQuestionUp) return;
6987 XtPopdown(askQuestionShell);
6988 XtDestroyWidget(askQuestionShell);
6989 askQuestionUp = False;
6992 void AskQuestionReplyAction(w, event, prms, nprms)
7002 reply = XawDialogGetValueString(w = XtParent(w));
7003 strcpy(buf, pendingReplyPrefix);
7004 if (*buf) strcat(buf, " ");
7007 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
7008 AskQuestionPopDown();
7010 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
7013 void AskQuestionCallback(w, client_data, call_data)
7015 XtPointer client_data, call_data;
7020 XtSetArg(args[0], XtNlabel, &name);
7021 XtGetValues(w, args, 1);
7023 if (strcmp(name, _("cancel")) == 0) {
7024 AskQuestionPopDown();
7026 AskQuestionReplyAction(w, NULL, NULL, NULL);
7030 void AskQuestion(title, question, replyPrefix, pr)
7031 char *title, *question, *replyPrefix;
7035 Widget popup, layout, dialog, edit;
7041 strcpy(pendingReplyPrefix, replyPrefix);
7042 pendingReplyPR = pr;
7045 XtSetArg(args[i], XtNresizable, True); i++;
7046 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7047 askQuestionShell = popup =
7048 XtCreatePopupShell(title, transientShellWidgetClass,
7049 shellWidget, args, i);
7052 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7053 layoutArgs, XtNumber(layoutArgs));
7056 XtSetArg(args[i], XtNlabel, question); i++;
7057 XtSetArg(args[i], XtNvalue, ""); i++;
7058 XtSetArg(args[i], XtNborderWidth, 0); i++;
7059 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7062 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7063 (XtPointer) dialog);
7064 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7065 (XtPointer) dialog);
7067 XtRealizeWidget(popup);
7068 CatchDeleteWindow(popup, "AskQuestionPopDown");
7070 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7071 &x, &y, &win_x, &win_y, &mask);
7073 XtSetArg(args[0], XtNx, x - 10);
7074 XtSetArg(args[1], XtNy, y - 30);
7075 XtSetValues(popup, args, 2);
7077 XtPopup(popup, XtGrabExclusive);
7078 askQuestionUp = True;
7080 edit = XtNameToWidget(dialog, "*value");
7081 XtSetKeyboardFocus(popup, edit);
7089 if (*name == NULLCHAR) {
7091 } else if (strcmp(name, "$") == 0) {
7092 putc(BELLCHAR, stderr);
7095 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7103 PlaySound(appData.soundMove);
7109 PlaySound(appData.soundIcsWin);
7115 PlaySound(appData.soundIcsLoss);
7121 PlaySound(appData.soundIcsDraw);
7125 PlayIcsUnfinishedSound()
7127 PlaySound(appData.soundIcsUnfinished);
7133 PlaySound(appData.soundIcsAlarm);
7139 system("stty echo");
7145 system("stty -echo");
7149 Colorize(cc, continuation)
7154 int count, outCount, error;
7156 if (textColors[(int)cc].bg > 0) {
7157 if (textColors[(int)cc].fg > 0) {
7158 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7159 textColors[(int)cc].fg, textColors[(int)cc].bg);
7161 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7162 textColors[(int)cc].bg);
7165 if (textColors[(int)cc].fg > 0) {
7166 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7167 textColors[(int)cc].fg);
7169 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7172 count = strlen(buf);
7173 outCount = OutputToProcess(NoProc, buf, count, &error);
7174 if (outCount < count) {
7175 DisplayFatalError(_("Error writing to display"), error, 1);
7178 if (continuation) return;
7181 PlaySound(appData.soundShout);
7184 PlaySound(appData.soundSShout);
7187 PlaySound(appData.soundChannel1);
7190 PlaySound(appData.soundChannel);
7193 PlaySound(appData.soundKibitz);
7196 PlaySound(appData.soundTell);
7198 case ColorChallenge:
7199 PlaySound(appData.soundChallenge);
7202 PlaySound(appData.soundRequest);
7205 PlaySound(appData.soundSeek);
7216 return getpwuid(getuid())->pw_name;
7219 static char *ExpandPathName(path)
7222 static char static_buf[2000];
7223 char *d, *s, buf[2000];
7229 while (*s && isspace(*s))
7238 if (*(s+1) == '/') {
7239 strcpy(d, getpwuid(getuid())->pw_dir);
7244 *strchr(buf, '/') = 0;
7245 pwd = getpwnam(buf);
7248 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7252 strcpy(d, pwd->pw_dir);
7253 strcat(d, strchr(s+1, '/'));
7264 static char host_name[MSG_SIZ];
7266 #if HAVE_GETHOSTNAME
7267 gethostname(host_name, MSG_SIZ);
7269 #else /* not HAVE_GETHOSTNAME */
7270 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7271 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7273 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7275 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7276 #endif /* not HAVE_GETHOSTNAME */
7279 XtIntervalId delayedEventTimerXID = 0;
7280 DelayedEventCallback delayedEventCallback = 0;
7285 delayedEventTimerXID = 0;
7286 delayedEventCallback();
7290 ScheduleDelayedEvent(cb, millisec)
7291 DelayedEventCallback cb; long millisec;
7293 delayedEventCallback = cb;
7294 delayedEventTimerXID =
7295 XtAppAddTimeOut(appContext, millisec,
7296 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7299 DelayedEventCallback
7302 if (delayedEventTimerXID) {
7303 return delayedEventCallback;
7310 CancelDelayedEvent()
7312 if (delayedEventTimerXID) {
7313 XtRemoveTimeOut(delayedEventTimerXID);
7314 delayedEventTimerXID = 0;
7318 XtIntervalId loadGameTimerXID = 0;
7320 int LoadGameTimerRunning()
7322 return loadGameTimerXID != 0;
7325 int StopLoadGameTimer()
7327 if (loadGameTimerXID != 0) {
7328 XtRemoveTimeOut(loadGameTimerXID);
7329 loadGameTimerXID = 0;
7337 LoadGameTimerCallback(arg, id)
7341 loadGameTimerXID = 0;
7346 StartLoadGameTimer(millisec)
7350 XtAppAddTimeOut(appContext, millisec,
7351 (XtTimerCallbackProc) LoadGameTimerCallback,
7355 XtIntervalId analysisClockXID = 0;
7358 AnalysisClockCallback(arg, id)
7362 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
7363 || appData.icsEngineAnalyze) {
7364 AnalysisPeriodicEvent(0);
7365 StartAnalysisClock();
7370 StartAnalysisClock()
7373 XtAppAddTimeOut(appContext, 2000,
7374 (XtTimerCallbackProc) AnalysisClockCallback,
7378 XtIntervalId clockTimerXID = 0;
7380 int ClockTimerRunning()
7382 return clockTimerXID != 0;
7385 int StopClockTimer()
7387 if (clockTimerXID != 0) {
7388 XtRemoveTimeOut(clockTimerXID);
7397 ClockTimerCallback(arg, id)
7406 StartClockTimer(millisec)
7410 XtAppAddTimeOut(appContext, millisec,
7411 (XtTimerCallbackProc) ClockTimerCallback,
7416 DisplayTimerLabel(w, color, timer, highlight)
7425 if (appData.clockMode) {
7426 sprintf(buf, "%s: %s", color, TimeString(timer));
7427 XtSetArg(args[0], XtNlabel, buf);
7429 sprintf(buf, "%s ", color);
7430 XtSetArg(args[0], XtNlabel, buf);
7434 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7435 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7437 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7438 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7441 XtSetValues(w, args, 3);
7445 DisplayWhiteClock(timeRemaining, highlight)
7450 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
7451 if (highlight && iconPixmap == bIconPixmap) {
7452 iconPixmap = wIconPixmap;
7453 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7454 XtSetValues(shellWidget, args, 1);
7459 DisplayBlackClock(timeRemaining, highlight)
7464 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
7465 if (highlight && iconPixmap == wIconPixmap) {
7466 iconPixmap = bIconPixmap;
7467 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7468 XtSetValues(shellWidget, args, 1);
7486 int StartChildProcess(cmdLine, dir, pr)
7493 int to_prog[2], from_prog[2];
7497 if (appData.debugMode) {
7498 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7501 /* We do NOT feed the cmdLine to the shell; we just
7502 parse it into blank-separated arguments in the
7503 most simple-minded way possible.
7506 strcpy(buf, cmdLine);
7511 if (p == NULL) break;
7516 SetUpChildIO(to_prog, from_prog);
7518 if ((pid = fork()) == 0) {
7520 dup2(to_prog[0], 0);
7521 dup2(from_prog[1], 1);
7524 close(from_prog[0]);
7525 close(from_prog[1]);
7526 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7528 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7533 execvp(argv[0], argv);
7535 /* If we get here, exec failed */
7540 /* Parent process */
7542 close(from_prog[1]);
7544 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7547 cp->fdFrom = from_prog[0];
7548 cp->fdTo = to_prog[1];
7554 DestroyChildProcess(pr, signal)
7558 ChildProc *cp = (ChildProc *) pr;
7560 if (cp->kind != CPReal) return;
7563 kill(cp->pid, SIGTERM);
7565 /* Process is exiting either because of the kill or because of
7566 a quit command sent by the backend; either way, wait for it to die.
7574 InterruptChildProcess(pr)
7577 ChildProc *cp = (ChildProc *) pr;
7579 if (cp->kind != CPReal) return;
7580 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7583 int OpenTelnet(host, port, pr)
7588 char cmdLine[MSG_SIZ];
7590 if (port[0] == NULLCHAR) {
7591 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7593 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7595 return StartChildProcess(cmdLine, "", pr);
7598 int OpenTCP(host, port, pr)
7604 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7605 #else /* !OMIT_SOCKETS */
7607 struct sockaddr_in sa;
7609 unsigned short uport;
7612 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7616 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7617 sa.sin_family = AF_INET;
7618 sa.sin_addr.s_addr = INADDR_ANY;
7619 uport = (unsigned short) 0;
7620 sa.sin_port = htons(uport);
7621 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7625 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7626 if (!(hp = gethostbyname(host))) {
7628 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7629 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7630 hp->h_addrtype = AF_INET;
7632 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7633 hp->h_addr_list[0] = (char *) malloc(4);
7634 hp->h_addr_list[0][0] = b0;
7635 hp->h_addr_list[0][1] = b1;
7636 hp->h_addr_list[0][2] = b2;
7637 hp->h_addr_list[0][3] = b3;
7642 sa.sin_family = hp->h_addrtype;
7643 uport = (unsigned short) atoi(port);
7644 sa.sin_port = htons(uport);
7645 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7647 if (connect(s, (struct sockaddr *) &sa,
7648 sizeof(struct sockaddr_in)) < 0) {
7652 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7659 #endif /* !OMIT_SOCKETS */
7664 int OpenCommPort(name, pr)
7671 fd = open(name, 2, 0);
7672 if (fd < 0) return errno;
7674 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7684 int OpenLoopback(pr)
7690 SetUpChildIO(to, from);
7692 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7695 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7702 int OpenRcmd(host, user, cmd, pr)
7703 char *host, *user, *cmd;
7706 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7710 #define INPUT_SOURCE_BUF_SIZE 8192
7719 char buf[INPUT_SOURCE_BUF_SIZE];
7724 DoInputCallback(closure, source, xid)
7729 InputSource *is = (InputSource *) closure;
7734 if (is->lineByLine) {
7735 count = read(is->fd, is->unused,
7736 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7738 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7741 is->unused += count;
7743 while (p < is->unused) {
7744 q = memchr(p, '\n', is->unused - p);
7745 if (q == NULL) break;
7747 (is->func)(is, is->closure, p, q - p, 0);
7751 while (p < is->unused) {
7756 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7761 (is->func)(is, is->closure, is->buf, count, error);
7765 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7772 ChildProc *cp = (ChildProc *) pr;
7774 is = (InputSource *) calloc(1, sizeof(InputSource));
7775 is->lineByLine = lineByLine;
7779 is->fd = fileno(stdin);
7781 is->kind = cp->kind;
7782 is->fd = cp->fdFrom;
7785 is->unused = is->buf;
7788 is->xid = XtAppAddInput(appContext, is->fd,
7789 (XtPointer) (XtInputReadMask),
7790 (XtInputCallbackProc) DoInputCallback,
7792 is->closure = closure;
7793 return (InputSourceRef) is;
7797 RemoveInputSource(isr)
7800 InputSource *is = (InputSource *) isr;
7802 if (is->xid == 0) return;
7803 XtRemoveInput(is->xid);
7807 int OutputToProcess(pr, message, count, outError)
7813 ChildProc *cp = (ChildProc *) pr;
7817 outCount = fwrite(message, 1, count, stdout);
7819 outCount = write(cp->fdTo, message, count);
7829 /* Output message to process, with "ms" milliseconds of delay
7830 between each character. This is needed when sending the logon
7831 script to ICC, which for some reason doesn't like the
7832 instantaneous send. */
7833 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7840 ChildProc *cp = (ChildProc *) pr;
7845 r = write(cp->fdTo, message++, 1);
7858 /**** Animation code by Hugh Fisher, DCS, ANU.
7860 Known problem: if a window overlapping the board is
7861 moved away while a piece is being animated underneath,
7862 the newly exposed area won't be updated properly.
7863 I can live with this.
7865 Known problem: if you look carefully at the animation
7866 of pieces in mono mode, they are being drawn as solid
7867 shapes without interior detail while moving. Fixing
7868 this would be a major complication for minimal return.
7871 /* Masks for XPM pieces. Black and white pieces can have
7872 different shapes, but in the interest of retaining my
7873 sanity pieces must have the same outline on both light
7874 and dark squares, and all pieces must use the same
7875 background square colors/images. */
7878 CreateAnimMasks (pieceDepth)
7885 unsigned long plane;
7888 /* Need a bitmap just to get a GC with right depth */
7889 buf = XCreatePixmap(xDisplay, xBoardWindow,
7891 values.foreground = 1;
7892 values.background = 0;
7893 /* Don't use XtGetGC, not read only */
7894 maskGC = XCreateGC(xDisplay, buf,
7895 GCForeground | GCBackground, &values);
7896 XFreePixmap(xDisplay, buf);
7898 buf = XCreatePixmap(xDisplay, xBoardWindow,
7899 squareSize, squareSize, pieceDepth);
7900 values.foreground = XBlackPixel(xDisplay, xScreen);
7901 values.background = XWhitePixel(xDisplay, xScreen);
7902 bufGC = XCreateGC(xDisplay, buf,
7903 GCForeground | GCBackground, &values);
7905 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7906 /* Begin with empty mask */
7907 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7908 squareSize, squareSize, 1);
7909 XSetFunction(xDisplay, maskGC, GXclear);
7910 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7911 0, 0, squareSize, squareSize);
7913 /* Take a copy of the piece */
7918 XSetFunction(xDisplay, bufGC, GXcopy);
7919 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7921 0, 0, squareSize, squareSize, 0, 0);
7923 /* XOR the background (light) over the piece */
7924 XSetFunction(xDisplay, bufGC, GXxor);
7926 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7927 0, 0, squareSize, squareSize, 0, 0);
7929 XSetForeground(xDisplay, bufGC, lightSquareColor);
7930 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7933 /* We now have an inverted piece image with the background
7934 erased. Construct mask by just selecting all the non-zero
7935 pixels - no need to reconstruct the original image. */
7936 XSetFunction(xDisplay, maskGC, GXor);
7938 /* Might be quicker to download an XImage and create bitmap
7939 data from it rather than this N copies per piece, but it
7940 only takes a fraction of a second and there is a much
7941 longer delay for loading the pieces. */
7942 for (n = 0; n < pieceDepth; n ++) {
7943 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7944 0, 0, squareSize, squareSize,
7950 XFreePixmap(xDisplay, buf);
7951 XFreeGC(xDisplay, bufGC);
7952 XFreeGC(xDisplay, maskGC);
7956 InitAnimState (anim, info)
7958 XWindowAttributes * info;
7963 /* Each buffer is square size, same depth as window */
7964 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7965 squareSize, squareSize, info->depth);
7966 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7967 squareSize, squareSize, info->depth);
7969 /* Create a plain GC for blitting */
7970 mask = GCForeground | GCBackground | GCFunction |
7971 GCPlaneMask | GCGraphicsExposures;
7972 values.foreground = XBlackPixel(xDisplay, xScreen);
7973 values.background = XWhitePixel(xDisplay, xScreen);
7974 values.function = GXcopy;
7975 values.plane_mask = AllPlanes;
7976 values.graphics_exposures = False;
7977 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7979 /* Piece will be copied from an existing context at
7980 the start of each new animation/drag. */
7981 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7983 /* Outline will be a read-only copy of an existing */
7984 anim->outlineGC = None;
7990 static int done = 0;
7991 XWindowAttributes info;
7995 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7997 InitAnimState(&game, &info);
7998 InitAnimState(&player, &info);
8000 /* For XPM pieces, we need bitmaps to use as masks. */
8002 CreateAnimMasks(info.depth);
8007 static Boolean frameWaiting;
8009 static RETSIGTYPE FrameAlarm (sig)
8012 frameWaiting = False;
8013 /* In case System-V style signals. Needed?? */
8014 signal(SIGALRM, FrameAlarm);
8021 struct itimerval delay;
8023 XSync(xDisplay, False);
8026 frameWaiting = True;
8027 signal(SIGALRM, FrameAlarm);
8028 delay.it_interval.tv_sec =
8029 delay.it_value.tv_sec = time / 1000;
8030 delay.it_interval.tv_usec =
8031 delay.it_value.tv_usec = (time % 1000) * 1000;
8032 setitimer(ITIMER_REAL, &delay, NULL);
8034 /* Ugh -- busy-wait! --tpm */
8035 while (frameWaiting);
8037 while (frameWaiting) pause();
8039 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8040 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8041 setitimer(ITIMER_REAL, &delay, NULL);
8051 XSync(xDisplay, False);
8053 usleep(time * 1000);
8058 /* Convert board position to corner of screen rect and color */
8061 ScreenSquare(column, row, pt, color)
8062 int column; int row; XPoint * pt; int * color;
8065 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
8066 pt->y = lineGap + row * (squareSize + lineGap);
8068 pt->x = lineGap + column * (squareSize + lineGap);
8069 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
8071 *color = ((column + row) % 2) == 1;
8074 /* Convert window coords to square */
8077 BoardSquare(x, y, column, row)
8078 int x; int y; int * column; int * row;
8080 *column = EventToSquare(x, BOARD_SIZE);
8081 if (flipView && *column >= 0)
8082 *column = BOARD_SIZE - 1 - *column;
8083 *row = EventToSquare(y, BOARD_SIZE);
8084 if (!flipView && *row >= 0)
8085 *row = BOARD_SIZE - 1 - *row;
8090 #undef Max /* just in case */
8092 #define Max(a, b) ((a) > (b) ? (a) : (b))
8093 #define Min(a, b) ((a) < (b) ? (a) : (b))
8096 SetRect(rect, x, y, width, height)
8097 XRectangle * rect; int x; int y; int width; int height;
8101 rect->width = width;
8102 rect->height = height;
8105 /* Test if two frames overlap. If they do, return
8106 intersection rect within old and location of
8107 that rect within new. */
8110 Intersect(old, new, size, area, pt)
8111 XPoint * old; XPoint * new;
8112 int size; XRectangle * area; XPoint * pt;
8114 if (old->x > new->x + size || new->x > old->x + size ||
8115 old->y > new->y + size || new->y > old->y + size) {
8118 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8119 size - abs(old->x - new->x), size - abs(old->y - new->y));
8120 pt->x = Max(old->x - new->x, 0);
8121 pt->y = Max(old->y - new->y, 0);
8126 /* For two overlapping frames, return the rect(s)
8127 in the old that do not intersect with the new. */
8130 CalcUpdateRects(old, new, size, update, nUpdates)
8131 XPoint * old; XPoint * new; int size;
8132 XRectangle update[]; int * nUpdates;
8136 /* If old = new (shouldn't happen) then nothing to draw */
8137 if (old->x == new->x && old->y == new->y) {
8141 /* Work out what bits overlap. Since we know the rects
8142 are the same size we don't need a full intersect calc. */
8144 /* Top or bottom edge? */
8145 if (new->y > old->y) {
8146 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8148 } else if (old->y > new->y) {
8149 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8150 size, old->y - new->y);
8153 /* Left or right edge - don't overlap any update calculated above. */
8154 if (new->x > old->x) {
8155 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8156 new->x - old->x, size - abs(new->y - old->y));
8158 } else if (old->x > new->x) {
8159 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8160 old->x - new->x, size - abs(new->y - old->y));
8167 /* Generate a series of frame coords from start->mid->finish.
8168 The movement rate doubles until the half way point is
8169 reached, then halves back down to the final destination,
8170 which gives a nice slow in/out effect. The algorithmn
8171 may seem to generate too many intermediates for short
8172 moves, but remember that the purpose is to attract the
8173 viewers attention to the piece about to be moved and
8174 then to where it ends up. Too few frames would be less
8178 Tween(start, mid, finish, factor, frames, nFrames)
8179 XPoint * start; XPoint * mid;
8180 XPoint * finish; int factor;
8181 XPoint frames[]; int * nFrames;
8183 int fraction, n, count;
8187 /* Slow in, stepping 1/16th, then 1/8th, ... */
8189 for (n = 0; n < factor; n++)
8191 for (n = 0; n < factor; n++) {
8192 frames[count].x = start->x + (mid->x - start->x) / fraction;
8193 frames[count].y = start->y + (mid->y - start->y) / fraction;
8195 fraction = fraction / 2;
8199 frames[count] = *mid;
8202 /* Slow out, stepping 1/2, then 1/4, ... */
8204 for (n = 0; n < factor; n++) {
8205 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8206 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8208 fraction = fraction * 2;
8213 /* Draw a piece on the screen without disturbing what's there */
8216 SelectGCMask(piece, clip, outline, mask)
8217 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8221 /* Bitmap for piece being moved. */
8222 if (appData.monoMode) {
8223 *mask = *pieceToSolid(piece);
8224 } else if (useImages) {
8226 *mask = xpmMask[piece];
8228 *mask = ximMaskPm[piece%6];
8231 *mask = *pieceToSolid(piece);
8234 /* GC for piece being moved. Square color doesn't matter, but
8235 since it gets modified we make a copy of the original. */
8237 if (appData.monoMode)
8242 if (appData.monoMode)
8247 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8249 /* Outline only used in mono mode and is not modified */
8251 *outline = bwPieceGC;
8253 *outline = wbPieceGC;
8257 OverlayPiece(piece, clip, outline, dest)
8258 ChessSquare piece; GC clip; GC outline; Drawable dest;
8263 /* Draw solid rectangle which will be clipped to shape of piece */
8264 XFillRectangle(xDisplay, dest, clip,
8265 0, 0, squareSize, squareSize);
8266 if (appData.monoMode)
8267 /* Also draw outline in contrasting color for black
8268 on black / white on white cases */
8269 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8270 0, 0, squareSize, squareSize, 0, 0, 1);
8272 /* Copy the piece */
8277 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8279 0, 0, squareSize, squareSize,
8284 /* Animate the movement of a single piece */
8287 BeginAnimation(anim, piece, startColor, start)
8295 /* The old buffer is initialised with the start square (empty) */
8296 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8297 anim->prevFrame = *start;
8299 /* The piece will be drawn using its own bitmap as a matte */
8300 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8301 XSetClipMask(xDisplay, anim->pieceGC, mask);
8305 AnimationFrame(anim, frame, piece)
8310 XRectangle updates[4];
8315 /* Save what we are about to draw into the new buffer */
8316 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8317 frame->x, frame->y, squareSize, squareSize,
8320 /* Erase bits of the previous frame */
8321 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8322 /* Where the new frame overlapped the previous,
8323 the contents in newBuf are wrong. */
8324 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8325 overlap.x, overlap.y,
8326 overlap.width, overlap.height,
8328 /* Repaint the areas in the old that don't overlap new */
8329 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8330 for (i = 0; i < count; i++)
8331 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8332 updates[i].x - anim->prevFrame.x,
8333 updates[i].y - anim->prevFrame.y,
8334 updates[i].width, updates[i].height,
8335 updates[i].x, updates[i].y);
8337 /* Easy when no overlap */
8338 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8339 0, 0, squareSize, squareSize,
8340 anim->prevFrame.x, anim->prevFrame.y);
8343 /* Save this frame for next time round */
8344 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8345 0, 0, squareSize, squareSize,
8347 anim->prevFrame = *frame;
8349 /* Draw piece over original screen contents, not current,
8350 and copy entire rect. Wipes out overlapping piece images. */
8351 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8352 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8353 0, 0, squareSize, squareSize,
8354 frame->x, frame->y);
8358 EndAnimation (anim, finish)
8362 XRectangle updates[4];
8367 /* The main code will redraw the final square, so we
8368 only need to erase the bits that don't overlap. */
8369 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8370 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8371 for (i = 0; i < count; i++)
8372 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8373 updates[i].x - anim->prevFrame.x,
8374 updates[i].y - anim->prevFrame.y,
8375 updates[i].width, updates[i].height,
8376 updates[i].x, updates[i].y);
8378 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8379 0, 0, squareSize, squareSize,
8380 anim->prevFrame.x, anim->prevFrame.y);
8385 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8387 ChessSquare piece; int startColor;
8388 XPoint * start; XPoint * finish;
8389 XPoint frames[]; int nFrames;
8393 BeginAnimation(anim, piece, startColor, start);
8394 for (n = 0; n < nFrames; n++) {
8395 AnimationFrame(anim, &(frames[n]), piece);
8396 FrameDelay(appData.animSpeed);
8398 EndAnimation(anim, finish);
8401 /* Main control logic for deciding what to animate and how */
8404 AnimateMove(board, fromX, fromY, toX, toY)
8413 XPoint start, finish, mid;
8414 XPoint frames[kFactor * 2 + 1];
8415 int nFrames, startColor, endColor;
8417 /* Are we animating? */
8418 if (!appData.animate || appData.blindfold)
8421 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8422 piece = board[fromY][fromX];
8423 if (piece >= EmptySquare) return;
8428 hop = (piece == WhiteKnight || piece == BlackKnight);
8431 if (appData.debugMode) {
8432 printf(hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8433 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8434 piece, fromX, fromY, toX, toY);
8437 ScreenSquare(fromX, fromY, &start, &startColor);
8438 ScreenSquare(toX, toY, &finish, &endColor);
8441 /* Knight: make diagonal movement then straight */
8442 if (abs(toY - fromY) < abs(toX - fromX)) {
8443 mid.x = start.x + (finish.x - start.x) / 2;
8447 mid.y = start.y + (finish.y - start.y) / 2;
8450 mid.x = start.x + (finish.x - start.x) / 2;
8451 mid.y = start.y + (finish.y - start.y) / 2;
8454 /* Don't use as many frames for very short moves */
8455 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8456 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8458 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8459 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8461 /* Be sure end square is redrawn */
8462 damage[toY][toX] = True;
8466 DragPieceBegin(x, y)
8469 int boardX, boardY, color;
8472 /* Are we animating? */
8473 if (!appData.animateDragging || appData.blindfold)
8476 /* Figure out which square we start in and the
8477 mouse position relative to top left corner. */
8478 BoardSquare(x, y, &boardX, &boardY);
8479 player.startBoardX = boardX;
8480 player.startBoardY = boardY;
8481 ScreenSquare(boardX, boardY, &corner, &color);
8482 player.startSquare = corner;
8483 player.startColor = color;
8485 /* Start from exactly where the piece is. This can be confusing
8486 if you start dragging far from the center of the square; most
8487 or all of the piece can be over a different square from the one
8488 the mouse pointer is in. */
8489 player.mouseDelta.x = x - corner.x;
8490 player.mouseDelta.y = y - corner.y;
8492 /* As soon as we start dragging, the piece will jump slightly to
8493 be centered over the mouse pointer. */
8494 player.mouseDelta.x = squareSize/2;
8495 player.mouseDelta.y = squareSize/2;
8497 /* Initialise animation */
8498 player.dragPiece = PieceForSquare(boardX, boardY);
8500 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8501 player.dragActive = True;
8502 BeginAnimation(&player, player.dragPiece, color, &corner);
8503 /* Mark this square as needing to be redrawn. Note that
8504 we don't remove the piece though, since logically (ie
8505 as seen by opponent) the move hasn't been made yet. */
8506 damage[boardY][boardX] = True;
8508 player.dragActive = False;
8518 /* Are we animating? */
8519 if (!appData.animateDragging || appData.blindfold)
8523 if (! player.dragActive)
8525 /* Move piece, maintaining same relative position
8526 of mouse within square */
8527 corner.x = x - player.mouseDelta.x;
8528 corner.y = y - player.mouseDelta.y;
8529 AnimationFrame(&player, &corner, player.dragPiece);
8531 if (appData.highlightDragging) {
8533 BoardSquare(x, y, &boardX, &boardY);
8534 SetHighlights(fromX, fromY, boardX, boardY);
8543 int boardX, boardY, color;
8546 /* Are we animating? */
8547 if (!appData.animateDragging || appData.blindfold)
8551 if (! player.dragActive)
8553 /* Last frame in sequence is square piece is
8554 placed on, which may not match mouse exactly. */
8555 BoardSquare(x, y, &boardX, &boardY);
8556 ScreenSquare(boardX, boardY, &corner, &color);
8557 EndAnimation(&player, &corner);
8559 /* Be sure end square is redrawn */
8560 damage[boardY][boardX] = True;
8562 /* This prevents weird things happening with fast successive
8563 clicks which on my Sun at least can cause motion events
8564 without corresponding press/release. */
8565 player.dragActive = False;
8568 /* Handle expose event while piece being dragged */
8573 if (!player.dragActive || appData.blindfold)
8576 /* What we're doing: logically, the move hasn't been made yet,
8577 so the piece is still in it's original square. But visually
8578 it's being dragged around the board. So we erase the square
8579 that the piece is on and draw it at the last known drag point. */
8580 BlankSquare(player.startSquare.x, player.startSquare.y,
8581 player.startColor, EmptySquare, xBoardWindow);
8582 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8583 damage[player.startBoardY][player.startBoardX] = TRUE;