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 - Currently not yet implemented in XBoard */
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);
2813 SetMenuEnables(ncpEnables);
2819 SetMenuEnables(gnuEnables);
2825 SetMenuEnables(cmailEnables);
2831 SetMenuEnables(trainingOnEnables);
2832 if (appData.showButtonBar) {
2833 XtSetSensitive(buttonBarWidget, False);
2839 SetTrainingModeOff()
2841 SetMenuEnables(trainingOffEnables);
2842 if (appData.showButtonBar) {
2843 XtSetSensitive(buttonBarWidget, True);
2848 SetUserThinkingEnables()
2850 if (appData.noChessProgram) return;
2851 SetMenuEnables(userThinkingEnables);
2855 SetMachineThinkingEnables()
2857 if (appData.noChessProgram) return;
2858 SetMenuEnables(machineThinkingEnables);
2860 case MachinePlaysBlack:
2861 case MachinePlaysWhite:
2862 case TwoMachinesPlay:
2863 XtSetSensitive(XtNameToWidget(menuBarWidget,
2864 ModeToWidgetName(gameMode)), True);
2871 #define Abs(n) ((n)<0 ? -(n) : (n))
2874 * Find a font that matches "pattern" that is as close as
2875 * possible to the targetPxlSize. Prefer fonts that are k
2876 * pixels smaller to fonts that are k pixels larger. The
2877 * pattern must be in the X Consortium standard format,
2878 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
2879 * The return value should be freed with XtFree when no
2882 char *FindFont(pattern, targetPxlSize)
2886 char **fonts, *p, *best, *scalable, *scalableTail;
2887 int i, j, nfonts, minerr, err, pxlSize;
2890 char **missing_list;
2892 char *def_string, *base_fnt_lst, strInt[3];
2894 XFontStruct **fnt_list;
2896 base_fnt_lst = calloc(1, strlen(pattern) + 3);
2897 sprintf(strInt, "%d", targetPxlSize);
2898 p = strstr(pattern, "--");
2899 strncpy(base_fnt_lst, pattern, p - pattern + 2);
2900 strcat(base_fnt_lst, strInt);
2901 strcat(base_fnt_lst, strchr(p + 2, '-'));
2903 if ((fntSet = XCreateFontSet(xDisplay,
2907 &def_string)) == NULL) {
2909 fprintf(stderr, _("Unable to create font set.\n"));
2913 nfonts = XFontsOfFontSet(fntSet, &fnt_list, &fonts);
2915 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
2917 fprintf(stderr, _("%s: no fonts match pattern %s\n"),
2918 programName, pattern);
2926 for (i=0; i<nfonts; i++) {
2929 if (*p != '-') continue;
2931 if (*p == NULLCHAR) break;
2932 if (*p++ == '-') j++;
2934 if (j < 7) continue;
2937 scalable = fonts[i];
2940 err = pxlSize - targetPxlSize;
2941 if (Abs(err) < Abs(minerr) ||
2942 (minerr > 0 && err < 0 && -err == minerr)) {
2948 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
2949 /* If the error is too big and there is a scalable font,
2950 use the scalable font. */
2951 int headlen = scalableTail - scalable;
2952 p = (char *) XtMalloc(strlen(scalable) + 10);
2953 while (isdigit(*scalableTail)) scalableTail++;
2954 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
2956 p = (char *) XtMalloc(strlen(best) + 1);
2959 if (appData.debugMode) {
2960 fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"),
2961 pattern, targetPxlSize, p);
2964 if (missing_count > 0)
2965 XFreeStringList(missing_list);
2966 XFreeFontSet(xDisplay, fntSet);
2968 XFreeFontNames(fonts);
2975 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
2976 | GCBackground | GCFunction | GCPlaneMask;
2977 XGCValues gc_values;
2980 gc_values.plane_mask = AllPlanes;
2981 gc_values.line_width = lineGap;
2982 gc_values.line_style = LineSolid;
2983 gc_values.function = GXcopy;
2985 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2986 gc_values.background = XBlackPixel(xDisplay, xScreen);
2987 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2989 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
2990 gc_values.background = XWhitePixel(xDisplay, xScreen);
2991 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
2992 XSetFont(xDisplay, coordGC, coordFontID);
2994 if (appData.monoMode) {
2995 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
2996 gc_values.background = XWhitePixel(xDisplay, xScreen);
2997 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
2999 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
3000 gc_values.background = XBlackPixel(xDisplay, xScreen);
3001 lightSquareGC = wbPieceGC
3002 = XtGetGC(shellWidget, value_mask, &gc_values);
3004 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
3005 gc_values.background = XWhitePixel(xDisplay, xScreen);
3006 darkSquareGC = bwPieceGC
3007 = XtGetGC(shellWidget, value_mask, &gc_values);
3009 if (DefaultDepth(xDisplay, xScreen) == 1) {
3010 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3011 gc_values.function = GXcopyInverted;
3012 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
3013 gc_values.function = GXcopy;
3014 if (XBlackPixel(xDisplay, xScreen) == 1) {
3015 bwPieceGC = darkSquareGC;
3016 wbPieceGC = copyInvertedGC;
3018 bwPieceGC = copyInvertedGC;
3019 wbPieceGC = lightSquareGC;
3023 gc_values.foreground = highlightSquareColor;
3024 gc_values.background = highlightSquareColor;
3025 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3027 gc_values.foreground = premoveHighlightColor;
3028 gc_values.background = premoveHighlightColor;
3029 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
3031 gc_values.foreground = lightSquareColor;
3032 gc_values.background = darkSquareColor;
3033 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3035 gc_values.foreground = darkSquareColor;
3036 gc_values.background = lightSquareColor;
3037 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3039 gc_values.foreground = jailSquareColor;
3040 gc_values.background = jailSquareColor;
3041 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
3043 gc_values.foreground = whitePieceColor;
3044 gc_values.background = darkSquareColor;
3045 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3047 gc_values.foreground = whitePieceColor;
3048 gc_values.background = lightSquareColor;
3049 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3051 gc_values.foreground = whitePieceColor;
3052 gc_values.background = jailSquareColor;
3053 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3055 gc_values.foreground = blackPieceColor;
3056 gc_values.background = darkSquareColor;
3057 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3059 gc_values.foreground = blackPieceColor;
3060 gc_values.background = lightSquareColor;
3061 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3063 gc_values.foreground = blackPieceColor;
3064 gc_values.background = jailSquareColor;
3065 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
3069 void loadXIM(xim, xmask, filename, dest, mask)
3082 fp = fopen(filename, "rb");
3084 fprintf(stderr, _("%s: error loading XIM!\n"), programName);
3091 for (y=0; y<h; ++y) {
3092 for (x=0; x<h; ++x) {
3097 XPutPixel(xim, x, y, blackPieceColor);
3099 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3102 XPutPixel(xim, x, y, darkSquareColor);
3104 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3107 XPutPixel(xim, x, y, whitePieceColor);
3109 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
3112 XPutPixel(xim, x, y, lightSquareColor);
3114 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
3120 /* create Pixmap of piece */
3121 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3123 XPutImage(xDisplay, *dest, lightSquareGC, xim,
3126 /* create Pixmap of clipmask
3127 Note: We assume the white/black pieces have the same
3128 outline, so we make only 6 masks. This is okay
3129 since the XPM clipmask routines do the same. */
3131 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3133 XPutImage(xDisplay, temp, lightSquareGC, xmask,
3136 /* now create the 1-bit version */
3137 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
3140 values.foreground = 1;
3141 values.background = 0;
3143 /* Don't use XtGetGC, not read only */
3144 maskGC = XCreateGC(xDisplay, *mask,
3145 GCForeground | GCBackground, &values);
3146 XCopyPlane(xDisplay, temp, *mask, maskGC,
3147 0, 0, squareSize, squareSize, 0, 0, 1);
3148 XFreePixmap(xDisplay, temp);
3152 void CreateXIMPieces()
3157 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
3162 /* The XSynchronize calls were copied from CreatePieces.
3163 Not sure if needed, but can't hurt */
3164 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3167 /* temp needed by loadXIM() */
3168 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3169 0, 0, ss, ss, AllPlanes, XYPixmap);
3171 if (strlen(appData.pixmapDirectory) == 0) {
3175 if (appData.monoMode) {
3176 DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
3180 fprintf(stderr, _("\nLoading XIMs...\n"));
3182 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3183 fprintf(stderr, "%d", piece+1);
3184 for (kind=0; kind<4; kind++) {
3185 fprintf(stderr, ".");
3186 sprintf(buf, "%s/%c%s%u.xim",
3187 ExpandPathName(appData.pixmapDirectory),
3188 ToLower(PieceToChar((ChessSquare)piece)),
3190 ximPieceBitmap[kind][piece] =
3191 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3192 0, 0, ss, ss, AllPlanes, XYPixmap);
3193 if (appData.debugMode)
3194 fprintf(stderr, _("(File:%s:) "), buf);
3195 loadXIM(ximPieceBitmap[kind][piece],
3197 &(xpmPieceBitmap[kind][piece]),
3198 &(ximMaskPm[piece%6]));
3200 fprintf(stderr," ");
3202 /* Load light and dark squares */
3203 /* If the LSQ and DSQ pieces don't exist, we will
3204 draw them with solid squares. */
3205 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
3206 if (access(buf, 0) != 0) {
3210 fprintf(stderr, _("light square "));
3212 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3213 0, 0, ss, ss, AllPlanes, XYPixmap);
3214 if (appData.debugMode)
3215 fprintf(stderr, _("(File:%s:) "), buf);
3217 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
3218 fprintf(stderr, _("dark square "));
3219 sprintf(buf, "%s/dsq%u.xim",
3220 ExpandPathName(appData.pixmapDirectory), ss);
3221 if (appData.debugMode)
3222 fprintf(stderr, _("(File:%s:) "), buf);
3224 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
3225 0, 0, ss, ss, AllPlanes, XYPixmap);
3226 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
3227 xpmJailSquare = xpmLightSquare;
3229 fprintf(stderr, _("Done.\n"));
3231 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
3235 void CreateXPMPieces()
3239 u_int ss = squareSize;
3241 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
3242 XpmColorSymbol symbols[4];
3245 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
3246 if (appData.debugMode) {
3247 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
3248 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
3252 /* The XSynchronize calls were copied from CreatePieces.
3253 Not sure if needed, but can't hurt */
3254 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
3256 /* Setup translations so piece colors match square colors */
3257 symbols[0].name = "light_piece";
3258 symbols[0].value = appData.whitePieceColor;
3259 symbols[1].name = "dark_piece";
3260 symbols[1].value = appData.blackPieceColor;
3261 symbols[2].name = "light_square";
3262 symbols[2].value = appData.lightSquareColor;
3263 symbols[3].name = "dark_square";
3264 symbols[3].value = appData.darkSquareColor;
3266 attr.valuemask = XpmColorSymbols;
3267 attr.colorsymbols = symbols;
3268 attr.numsymbols = 4;
3270 if (appData.monoMode) {
3271 DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
3275 if (strlen(appData.pixmapDirectory) == 0) {
3276 XpmPieces* pieces = builtInXpms;
3279 while (pieces->size != squareSize && pieces->size) pieces++;
3280 if (!pieces->size) {
3281 fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
3284 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3285 for (kind=0; kind<4; kind++) {
3287 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
3288 pieces->xpm[piece][kind],
3289 &(xpmPieceBitmap[kind][piece]),
3290 NULL, &attr)) != 0) {
3291 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
3298 xpmJailSquare = xpmLightSquare;
3302 fprintf(stderr, _("\nLoading XPMs...\n"));
3305 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3306 fprintf(stderr, "%d ", piece+1);
3307 for (kind=0; kind<4; kind++) {
3308 sprintf(buf, "%s/%c%s%u.xpm",
3309 ExpandPathName(appData.pixmapDirectory),
3310 ToLower(PieceToChar((ChessSquare)piece)),
3312 if (appData.debugMode) {
3313 fprintf(stderr, _("(File:%s:) "), buf);
3315 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3316 &(xpmPieceBitmap[kind][piece]),
3317 NULL, &attr)) != 0) {
3318 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
3324 /* Load light and dark squares */
3325 /* If the LSQ and DSQ pieces don't exist, we will
3326 draw them with solid squares. */
3327 fprintf(stderr, _("light square "));
3328 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
3329 if (access(buf, 0) != 0) {
3333 if (appData.debugMode)
3334 fprintf(stderr, _("(File:%s:) "), buf);
3336 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3337 &xpmLightSquare, NULL, &attr)) != 0) {
3338 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3341 fprintf(stderr, _("dark square "));
3342 sprintf(buf, "%s/dsq%u.xpm",
3343 ExpandPathName(appData.pixmapDirectory), ss);
3344 if (appData.debugMode) {
3345 fprintf(stderr, _("(File:%s:) "), buf);
3347 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
3348 &xpmDarkSquare, NULL, &attr)) != 0) {
3349 fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
3353 xpmJailSquare = xpmLightSquare;
3354 fprintf(stderr, _("Done.\n"));
3356 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3359 #endif /* HAVE_LIBXPM */
3362 /* No built-in bitmaps */
3367 u_int ss = squareSize;
3369 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3372 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3373 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3374 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3375 ss, kind == SOLID ? 's' : 'o');
3376 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
3380 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3384 /* With built-in bitmaps */
3387 BuiltInBits* bib = builtInBits;
3390 u_int ss = squareSize;
3392 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
3395 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
3397 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
3398 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
3399 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
3400 ss, kind == SOLID ? 's' : 'o');
3401 ReadBitmap(&pieceBitmap[kind][piece], buf,
3402 bib->bits[kind][piece], ss, ss);
3406 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
3411 void ReadBitmap(pm, name, bits, wreq, hreq)
3414 unsigned char bits[];
3420 char msg[MSG_SIZ], fullname[MSG_SIZ];
3422 if (*appData.bitmapDirectory != NULLCHAR) {
3423 strcpy(fullname, appData.bitmapDirectory);
3424 strcat(fullname, "/");
3425 strcat(fullname, name);
3426 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
3427 &w, &h, pm, &x_hot, &y_hot);
3428 if (errcode != BitmapSuccess) {
3430 case BitmapOpenFailed:
3431 sprintf(msg, _("Can't open bitmap file %s"), fullname);
3433 case BitmapFileInvalid:
3434 sprintf(msg, _("Invalid bitmap in file %s"), fullname);
3436 case BitmapNoMemory:
3437 sprintf(msg, _("Ran out of memory reading bitmap file %s"),
3441 sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
3445 fprintf(stderr, _("%s: %s...using built-in\n"),
3447 } else if (w != wreq || h != hreq) {
3449 _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
3450 programName, fullname, w, h, wreq, hreq);
3456 fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"),
3460 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
3469 if (lineGap == 0) return;
3470 for (i = 0; i < BOARD_SIZE + 1; i++) {
3471 gridSegments[i].x1 = 0;
3472 gridSegments[i].x2 =
3473 lineGap + BOARD_SIZE * (squareSize + lineGap);
3474 gridSegments[i].y1 = gridSegments[i].y2
3475 = lineGap / 2 + (i * (squareSize + lineGap));
3477 gridSegments[i + BOARD_SIZE + 1].y1 = 0;
3478 gridSegments[i + BOARD_SIZE + 1].y2 =
3479 BOARD_SIZE * (squareSize + lineGap);
3480 gridSegments[i + BOARD_SIZE + 1].x1 =
3481 gridSegments[i + BOARD_SIZE + 1].x2
3482 = lineGap / 2 + (i * (squareSize + lineGap));
3486 static void MenuBarSelect(w, addr, index)
3491 XtActionProc proc = (XtActionProc) addr;
3493 (proc)(NULL, NULL, NULL, NULL);
3496 void CreateMenuBarPopup(parent, name, mb)
3506 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3509 XtSetArg(args[j], XtNleftMargin, 20); j++;
3510 XtSetArg(args[j], XtNrightMargin, 20); j++;
3512 while (mi->string != NULL) {
3513 if (strcmp(mi->string, "----") == 0) {
3514 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
3517 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string)));
3518 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
3520 XtAddCallback(entry, XtNcallback,
3521 (XtCallbackProc) MenuBarSelect,
3522 (caddr_t) mi->proc);
3528 Widget CreateMenuBar(mb)
3532 Widget anchor, menuBar;
3534 char menuName[MSG_SIZ];
3537 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3538 XtSetArg(args[j], XtNvSpace, 0); j++;
3539 XtSetArg(args[j], XtNborderWidth, 0); j++;
3540 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
3541 formWidget, args, j);
3543 while (mb->name != NULL) {
3544 strcpy(menuName, "menu");
3545 strcat(menuName, mb->name);
3547 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
3550 shortName[0] = _(mb->name)[0];
3551 shortName[1] = NULLCHAR;
3552 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
3555 XtSetArg(args[j], XtNlabel, XtNewString(_(mb->name))); j++;
3558 XtSetArg(args[j], XtNborderWidth, 0); j++;
3559 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
3561 CreateMenuBarPopup(menuBar, menuName, mb);
3567 Widget CreateButtonBar(mi)
3571 Widget button, buttonBar;
3575 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
3577 XtSetArg(args[j], XtNhSpace, 0); j++;
3579 XtSetArg(args[j], XtNborderWidth, 0); j++;
3580 XtSetArg(args[j], XtNvSpace, 0); j++;
3581 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
3582 formWidget, args, j);
3584 while (mi->string != NULL) {
3587 XtSetArg(args[j], XtNinternalWidth, 2); j++;
3588 XtSetArg(args[j], XtNborderWidth, 0); j++;
3590 XtSetArg(args[j], XtNlabel, XtNewString(_(mi->string))); j++;
3591 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
3592 buttonBar, args, j);
3593 XtAddCallback(button, XtNcallback,
3594 (XtCallbackProc) MenuBarSelect,
3595 (caddr_t) mi->proc);
3602 CreatePieceMenu(name, color)
3609 ChessSquare selection;
3611 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
3612 boardWidget, args, 0);
3614 for (i = 0; i < PIECE_MENU_SIZE; i++) {
3615 String item = pieceMenuStrings[color][i];
3617 if (strcmp(item, "----") == 0) {
3618 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3621 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3622 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3624 selection = pieceMenuTranslation[color][i];
3625 XtAddCallback(entry, XtNcallback,
3626 (XtCallbackProc) PieceMenuSelect,
3627 (caddr_t) selection);
3628 if (selection == WhitePawn || selection == BlackPawn) {
3629 XtSetArg(args[0], XtNpopupOnEntry, entry);
3630 XtSetValues(menu, args, 1);
3643 ChessSquare selection;
3645 whitePieceMenu = CreatePieceMenu("menuW", 0);
3646 blackPieceMenu = CreatePieceMenu("menuB", 1);
3648 XtRegisterGrabAction(PieceMenuPopup, True,
3649 (unsigned)(ButtonPressMask|ButtonReleaseMask),
3650 GrabModeAsync, GrabModeAsync);
3652 XtSetArg(args[0], XtNlabel, _("Drop"));
3653 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
3654 boardWidget, args, 1);
3655 for (i = 0; i < DROP_MENU_SIZE; i++) {
3656 String item = dropMenuStrings[i];
3658 if (strcmp(item, "----") == 0) {
3659 entry = XtCreateManagedWidget(item, smeLineObjectClass,
3662 XtSetArg(args[0], XtNlabel, XtNewString(_(item)));
3663 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
3665 selection = dropMenuTranslation[i];
3666 XtAddCallback(entry, XtNcallback,
3667 (XtCallbackProc) DropMenuSelect,
3668 (caddr_t) selection);
3673 void SetupDropMenu()
3681 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
3682 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
3683 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
3684 dmEnables[i].piece);
3685 XtSetSensitive(entry, p != NULL || !appData.testLegality
3686 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
3687 && !appData.icsActive));
3689 while (p && *p++ == dmEnables[i].piece) count++;
3690 sprintf(label, "%s %d", dmEnables[i].widget, count);
3692 XtSetArg(args[j], XtNlabel, label); j++;
3693 XtSetValues(entry, args, j);
3697 void PieceMenuPopup(w, event, params, num_params)
3701 Cardinal *num_params;
3704 if (event->type != ButtonPress) return;
3705 if (errorUp) ErrorPopDown();
3709 whichMenu = params[0];
3711 case IcsPlayingWhite:
3712 case IcsPlayingBlack:
3714 case MachinePlaysWhite:
3715 case MachinePlaysBlack:
3716 if (appData.testLegality &&
3717 gameInfo.variant != VariantBughouse &&
3718 gameInfo.variant != VariantCrazyhouse) return;
3720 whichMenu = "menuD";
3726 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
3727 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
3728 pmFromX = pmFromY = -1;
3732 pmFromX = BOARD_SIZE - 1 - pmFromX;
3734 pmFromY = BOARD_SIZE - 1 - pmFromY;
3736 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
3739 static void PieceMenuSelect(w, piece, junk)
3744 if (pmFromX < 0 || pmFromY < 0) return;
3745 EditPositionMenuEvent(piece, pmFromX, pmFromY);
3748 static void DropMenuSelect(w, piece, junk)
3753 if (pmFromX < 0 || pmFromY < 0) return;
3754 DropMenuEvent(piece, pmFromX, pmFromY);
3757 void WhiteClock(w, event, prms, nprms)
3763 if (gameMode == EditPosition || gameMode == IcsExamining) {
3764 SetWhiteToPlayEvent();
3765 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
3770 void BlackClock(w, event, prms, nprms)
3776 if (gameMode == EditPosition || gameMode == IcsExamining) {
3777 SetBlackToPlayEvent();
3778 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
3785 * If the user selects on a border boundary, return -1; if off the board,
3786 * return -2. Otherwise map the event coordinate to the square.
3788 int EventToSquare(x, limit)
3796 if ((x % (squareSize + lineGap)) >= squareSize)
3798 x /= (squareSize + lineGap);
3804 static void do_flash_delay(msec)
3810 static void drawHighlight(file, rank, gc)
3816 if (lineGap == 0 || appData.blindfold) return;
3819 x = lineGap/2 + ((BOARD_SIZE-1)-file) *
3820 (squareSize + lineGap);
3821 y = lineGap/2 + rank * (squareSize + lineGap);
3823 x = lineGap/2 + file * (squareSize + lineGap);
3824 y = lineGap/2 + ((BOARD_SIZE-1)-rank) *
3825 (squareSize + lineGap);
3828 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
3829 squareSize+lineGap, squareSize+lineGap);
3832 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
3833 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
3836 SetHighlights(fromX, fromY, toX, toY)
3837 int fromX, fromY, toX, toY;
3839 if (hi1X != fromX || hi1Y != fromY) {
3840 if (hi1X >= 0 && hi1Y >= 0) {
3841 drawHighlight(hi1X, hi1Y, lineGC);
3843 if (fromX >= 0 && fromY >= 0) {
3844 drawHighlight(fromX, fromY, highlineGC);
3847 if (hi2X != toX || hi2Y != toY) {
3848 if (hi2X >= 0 && hi2Y >= 0) {
3849 drawHighlight(hi2X, hi2Y, lineGC);
3851 if (toX >= 0 && toY >= 0) {
3852 drawHighlight(toX, toY, highlineGC);
3864 SetHighlights(-1, -1, -1, -1);
3869 SetPremoveHighlights(fromX, fromY, toX, toY)
3870 int fromX, fromY, toX, toY;
3872 if (pm1X != fromX || pm1Y != fromY) {
3873 if (pm1X >= 0 && pm1Y >= 0) {
3874 drawHighlight(pm1X, pm1Y, lineGC);
3876 if (fromX >= 0 && fromY >= 0) {
3877 drawHighlight(fromX, fromY, prelineGC);
3880 if (pm2X != toX || pm2Y != toY) {
3881 if (pm2X >= 0 && pm2Y >= 0) {
3882 drawHighlight(pm2X, pm2Y, lineGC);
3884 if (toX >= 0 && toY >= 0) {
3885 drawHighlight(toX, toY, prelineGC);
3895 ClearPremoveHighlights()
3897 SetPremoveHighlights(-1, -1, -1, -1);
3900 static void BlankSquare(x, y, color, piece, dest)
3905 if (useImages && useImageSqs) {
3909 pm = xpmLightSquare;
3914 case 2: /* neutral */
3919 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
3920 squareSize, squareSize, x, y);
3930 case 2: /* neutral */
3935 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
3940 I split out the routines to draw a piece so that I could
3941 make a generic flash routine.
3943 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
3945 int square_color, x, y;
3948 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
3949 switch (square_color) {
3951 case 2: /* neutral */
3953 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3954 ? *pieceToOutline(piece)
3955 : *pieceToSolid(piece),
3956 dest, bwPieceGC, 0, 0,
3957 squareSize, squareSize, x, y);
3960 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
3961 ? *pieceToSolid(piece)
3962 : *pieceToOutline(piece),
3963 dest, wbPieceGC, 0, 0,
3964 squareSize, squareSize, x, y);
3969 static void monoDrawPiece(piece, square_color, x, y, dest)
3971 int square_color, x, y;
3974 switch (square_color) {
3976 case 2: /* neutral */
3978 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3979 ? *pieceToOutline(piece)
3980 : *pieceToSolid(piece),
3981 dest, bwPieceGC, 0, 0,
3982 squareSize, squareSize, x, y, 1);
3985 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
3986 ? *pieceToSolid(piece)
3987 : *pieceToOutline(piece),
3988 dest, wbPieceGC, 0, 0,
3989 squareSize, squareSize, x, y, 1);
3994 static void colorDrawPiece(piece, square_color, x, y, dest)
3996 int square_color, x, y;
3999 switch (square_color) {
4001 XCopyPlane(xDisplay, *pieceToSolid(piece),
4002 dest, (int) piece < (int) BlackPawn
4003 ? wlPieceGC : blPieceGC, 0, 0,
4004 squareSize, squareSize, x, y, 1);
4007 XCopyPlane(xDisplay, *pieceToSolid(piece),
4008 dest, (int) piece < (int) BlackPawn
4009 ? wdPieceGC : bdPieceGC, 0, 0,
4010 squareSize, squareSize, x, y, 1);
4012 case 2: /* neutral */
4014 XCopyPlane(xDisplay, *pieceToSolid(piece),
4015 dest, (int) piece < (int) BlackPawn
4016 ? wjPieceGC : bjPieceGC, 0, 0,
4017 squareSize, squareSize, x, y, 1);
4022 static void colorDrawPieceImage(piece, square_color, x, y, dest)
4024 int square_color, x, y;
4029 switch (square_color) {
4031 case 2: /* neutral */
4033 if ((int)piece < (int) BlackPawn) {
4041 if ((int)piece < (int) BlackPawn) {
4049 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
4050 dest, wlPieceGC, 0, 0,
4051 squareSize, squareSize, x, y);
4054 typedef void (*DrawFunc)();
4056 DrawFunc ChooseDrawFunc()
4058 if (appData.monoMode) {
4059 if (DefaultDepth(xDisplay, xScreen) == 1) {
4060 return monoDrawPiece_1bit;
4062 return monoDrawPiece;
4066 return colorDrawPieceImage;
4068 return colorDrawPiece;
4072 void DrawSquare(row, column, piece, do_flash)
4073 int row, column, do_flash;
4076 int square_color, x, y, direction, font_ascent, font_descent;
4079 XCharStruct overall;
4083 /* Calculate delay in milliseconds (2-delays per complete flash) */
4084 flash_delay = 500 / appData.flashRate;
4087 x = lineGap + ((BOARD_SIZE-1)-column) *
4088 (squareSize + lineGap);
4089 y = lineGap + row * (squareSize + lineGap);
4091 x = lineGap + column * (squareSize + lineGap);
4092 y = lineGap + ((BOARD_SIZE-1)-row) *
4093 (squareSize + lineGap);
4096 square_color = ((column + row) % 2) == 1;
4098 if (piece == EmptySquare || appData.blindfold) {
4099 BlankSquare(x, y, square_color, piece, xBoardWindow);
4101 drawfunc = ChooseDrawFunc();
4102 if (do_flash && appData.flashCount > 0) {
4103 for (i=0; i<appData.flashCount; ++i) {
4105 drawfunc(piece, square_color, x, y, xBoardWindow);
4106 XSync(xDisplay, False);
4107 do_flash_delay(flash_delay);
4109 BlankSquare(x, y, square_color, piece, xBoardWindow);
4110 XSync(xDisplay, False);
4111 do_flash_delay(flash_delay);
4114 drawfunc(piece, square_color, x, y, xBoardWindow);
4117 string[1] = NULLCHAR;
4118 if (appData.showCoords && row == (flipView ? 7 : 0)) {
4119 string[0] = 'a' + column;
4120 XTextExtents(coordFontStruct, string, 1, &direction,
4121 &font_ascent, &font_descent, &overall);
4122 if (appData.monoMode) {
4123 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4124 x + squareSize - overall.width - 2,
4125 y + squareSize - font_descent - 1, string, 1);
4127 XDrawString(xDisplay, xBoardWindow, coordGC,
4128 x + squareSize - overall.width - 2,
4129 y + squareSize - font_descent - 1, string, 1);
4132 if (appData.showCoords && column == (flipView ? 7 : 0)) {
4133 string[0] = '1' + row;
4134 XTextExtents(coordFontStruct, string, 1, &direction,
4135 &font_ascent, &font_descent, &overall);
4136 if (appData.monoMode) {
4137 XDrawImageString(xDisplay, xBoardWindow, coordGC,
4138 x + 2, y + font_ascent + 1, string, 1);
4140 XDrawString(xDisplay, xBoardWindow, coordGC,
4141 x + 2, y + font_ascent + 1, string, 1);
4147 /* Why is this needed on some versions of X? */
4148 void EventProc(widget, unused, event)
4153 if (!XtIsRealized(widget))
4156 switch (event->type) {
4158 if (event->xexpose.count > 0) return; /* no clipping is done */
4159 XDrawPosition(widget, True, NULL);
4167 void DrawPosition(fullRedraw, board)
4168 /*Boolean*/int fullRedraw;
4171 XDrawPosition(boardWidget, fullRedraw, board);
4174 /* Returns 1 if there are "too many" differences between b1 and b2
4175 (i.e. more than 1 move was made) */
4176 static int too_many_diffs(b1, b2)
4182 for (i=0; i<BOARD_SIZE; ++i) {
4183 for (j=0; j<BOARD_SIZE; ++j) {
4184 if (b1[i][j] != b2[i][j]) {
4185 if (++c > 4) /* Castling causes 4 diffs */
4194 /* Matrix describing castling maneuvers */
4195 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
4196 static int castling_matrix[4][5] = {
4197 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
4198 { 0, 7, 4, 5, 6 }, /* 0-0, white */
4199 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
4200 { 7, 7, 4, 5, 6 } /* 0-0, black */
4203 /* Checks whether castling occurred. If it did, *rrow and *rcol
4204 are set to the destination (row,col) of the rook that moved.
4206 Returns 1 if castling occurred, 0 if not.
4208 Note: Only handles a max of 1 castling move, so be sure
4209 to call too_many_diffs() first.
4211 static int check_castle_draw(newb, oldb, rrow, rcol)
4218 /* For each type of castling... */
4219 for (i=0; i<4; ++i) {
4220 r = castling_matrix[i];
4222 /* Check the 4 squares involved in the castling move */
4224 for (j=1; j<=4; ++j) {
4225 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
4232 /* All 4 changed, so it must be a castling move */
4241 static int damage[BOARD_SIZE][BOARD_SIZE];
4244 * event handler for redrawing the board
4246 void XDrawPosition(w, repaint, board)
4248 /*Boolean*/int repaint;
4252 static int lastFlipView = 0;
4253 static int lastBoardValid = 0;
4254 static Board lastBoard;
4258 if (board == NULL) {
4259 if (!lastBoardValid) return;
4262 if (!lastBoardValid || lastFlipView != flipView) {
4263 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
4264 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
4269 * It would be simpler to clear the window with XClearWindow()
4270 * but this causes a very distracting flicker.
4273 if (!repaint && lastBoardValid && lastFlipView == flipView) {
4275 /* If too much changes (begin observing new game, etc.), don't
4277 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
4279 /* Special check for castling so we don't flash both the king
4280 and the rook (just flash the king). */
4282 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
4283 /* Draw rook with NO flashing. King will be drawn flashing later */
4284 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
4285 lastBoard[rrow][rcol] = board[rrow][rcol];
4289 /* First pass -- Draw (newly) empty squares and repair damage.
4290 This prevents you from having a piece show up twice while it
4291 is flashing on its new square */
4292 for (i = 0; i < BOARD_SIZE; i++)
4293 for (j = 0; j < BOARD_SIZE; j++)
4294 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
4296 DrawSquare(i, j, board[i][j], 0);
4297 damage[i][j] = False;
4300 /* Second pass -- Draw piece(s) in new position and flash them */
4301 for (i = 0; i < BOARD_SIZE; i++)
4302 for (j = 0; j < BOARD_SIZE; j++)
4303 if (board[i][j] != lastBoard[i][j]) {
4304 DrawSquare(i, j, board[i][j], do_flash);
4308 XDrawSegments(xDisplay, xBoardWindow, lineGC,
4309 gridSegments, (BOARD_SIZE + 1) * 2);
4311 for (i = 0; i < BOARD_SIZE; i++)
4312 for (j = 0; j < BOARD_SIZE; j++) {
4313 DrawSquare(i, j, board[i][j], 0);
4314 damage[i][j] = False;
4318 CopyBoard(lastBoard, board);
4320 lastFlipView = flipView;
4322 /* Draw highlights */
4323 if (pm1X >= 0 && pm1Y >= 0) {
4324 drawHighlight(pm1X, pm1Y, prelineGC);
4326 if (pm2X >= 0 && pm2Y >= 0) {
4327 drawHighlight(pm2X, pm2Y, prelineGC);
4329 if (hi1X >= 0 && hi1Y >= 0) {
4330 drawHighlight(hi1X, hi1Y, highlineGC);
4332 if (hi2X >= 0 && hi2Y >= 0) {
4333 drawHighlight(hi2X, hi2Y, highlineGC);
4336 /* If piece being dragged around board, must redraw that too */
4339 XSync(xDisplay, False);
4344 * event handler for redrawing the board
4346 void DrawPositionProc(w, event, prms, nprms)
4352 XDrawPosition(w, True, NULL);
4357 * event handler for parsing user moves
4359 void HandleUserMove(w, event, prms, nprms)
4366 Boolean saveAnimate;
4367 static int second = 0;
4369 if (w != boardWidget || errorExitStatus != -1) return;
4371 if (event->type == ButtonPress) ErrorPopDown();
4374 if (event->type == ButtonPress) {
4375 XtPopdown(promotionShell);
4376 XtDestroyWidget(promotionShell);
4377 promotionUp = False;
4385 x = EventToSquare(event->xbutton.x, BOARD_SIZE);
4386 y = EventToSquare(event->xbutton.y, BOARD_SIZE);
4387 if (!flipView && y >= 0) {
4388 y = BOARD_SIZE - 1 - y;
4390 if (flipView && x >= 0) {
4391 x = BOARD_SIZE - 1 - x;
4395 if (event->type == ButtonPress) {
4397 if (OKToStartUserMove(x, y)) {
4401 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4402 if (appData.highlightDragging) {
4403 SetHighlights(x, y, -1, -1);
4411 if (event->type == ButtonPress && gameMode != EditPosition &&
4415 /* Check if clicking again on the same color piece */
4416 fromP = boards[currentMove][fromY][fromX];
4417 toP = boards[currentMove][y][x];
4418 if ((WhitePawn <= fromP && fromP <= WhiteKing &&
4419 WhitePawn <= toP && toP <= WhiteKing) ||
4420 (BlackPawn <= fromP && fromP <= BlackKing &&
4421 BlackPawn <= toP && toP <= BlackKing)) {
4422 /* Clicked again on same color piece -- changed his mind */
4423 second = (x == fromX && y == fromY);
4424 if (appData.highlightDragging) {
4425 SetHighlights(x, y, -1, -1);
4429 if (OKToStartUserMove(x, y)) {
4432 DragPieceBegin(event->xbutton.x, event->xbutton.y);
4438 if (event->type == ButtonRelease && x == fromX && y == fromY) {
4439 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4440 if (appData.animateDragging) {
4441 /* Undo animation damage if any */
4442 DrawPosition(FALSE, NULL);
4445 /* Second up/down in same square; just abort move */
4450 ClearPremoveHighlights();
4452 /* First upclick in same square; start click-click mode */
4453 SetHighlights(x, y, -1, -1);
4458 /* Completed move */
4461 saveAnimate = appData.animate;
4462 if (event->type == ButtonPress) {
4463 /* Finish clickclick move */
4464 if (appData.animate || appData.highlightLastMove) {
4465 SetHighlights(fromX, fromY, toX, toY);
4470 /* Finish drag move */
4471 if (appData.highlightLastMove) {
4472 SetHighlights(fromX, fromY, toX, toY);
4476 DragPieceEnd(event->xbutton.x, event->xbutton.y);
4477 /* Don't animate move and drag both */
4478 appData.animate = FALSE;
4480 if (IsPromotion(fromX, fromY, toX, toY)) {
4481 if (appData.alwaysPromoteToQueen) {
4482 UserMoveEvent(fromX, fromY, toX, toY, 'q');
4483 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4484 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4487 SetHighlights(fromX, fromY, toX, toY);
4491 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
4492 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
4493 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
4496 appData.animate = saveAnimate;
4497 if (appData.animate || appData.animateDragging) {
4498 /* Undo animation damage if needed */
4499 DrawPosition(FALSE, NULL);
4503 void AnimateUserMove (Widget w, XEvent * event,
4504 String * params, Cardinal * nParams)
4506 DragPieceMove(event->xmotion.x, event->xmotion.y);
4509 Widget CommentCreate(name, text, mutable, callback, lines)
4511 int /*Boolean*/ mutable;
4512 XtCallbackProc callback;
4516 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
4521 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4522 XtGetValues(boardWidget, args, j);
4525 XtSetArg(args[j], XtNresizable, True); j++;
4528 XtCreatePopupShell(name, topLevelShellWidgetClass,
4529 shellWidget, args, j);
4532 XtCreatePopupShell(name, transientShellWidgetClass,
4533 shellWidget, args, j);
4536 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4537 layoutArgs, XtNumber(layoutArgs));
4539 XtCreateManagedWidget("form", formWidgetClass, layout,
4540 formArgs, XtNumber(formArgs));
4544 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4545 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4547 XtSetArg(args[j], XtNstring, text); j++;
4548 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4549 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4550 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4551 XtSetArg(args[j], XtNright, XtChainRight); j++;
4552 XtSetArg(args[j], XtNresizable, True); j++;
4553 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
4555 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4557 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4558 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4560 XtSetArg(args[j], XtNautoFill, True); j++;
4561 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4563 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4567 XtSetArg(args[j], XtNfromVert, edit); j++;
4568 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4569 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4570 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4571 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4573 XtCreateManagedWidget(_("ok"), commandWidgetClass, form, args, j);
4574 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
4577 XtSetArg(args[j], XtNfromVert, edit); j++;
4578 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
4579 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4580 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4581 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4582 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4584 XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
4585 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
4588 XtSetArg(args[j], XtNfromVert, edit); j++;
4589 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
4590 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4591 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4592 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4593 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4595 XtCreateManagedWidget(_("clear"), commandWidgetClass, form, args, j);
4596 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
4599 XtSetArg(args[j], XtNfromVert, edit); j++;
4600 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4601 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4602 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4603 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4605 XtCreateManagedWidget(_("close"), commandWidgetClass, form, args, j);
4606 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
4609 XtSetArg(args[j], XtNfromVert, edit); j++;
4610 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
4611 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
4612 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4613 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4614 XtSetArg(args[j], XtNright, XtChainLeft); j++;
4616 XtCreateManagedWidget(_("edit"), commandWidgetClass, form, args, j);
4617 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
4620 XtRealizeWidget(shell);
4622 if (commentX == -1) {
4625 Dimension pw_height;
4626 Dimension ew_height;
4629 XtSetArg(args[j], XtNheight, &ew_height); j++;
4630 XtGetValues(edit, args, j);
4633 XtSetArg(args[j], XtNheight, &pw_height); j++;
4634 XtGetValues(shell, args, j);
4635 commentH = pw_height + (lines - 1) * ew_height;
4636 commentW = bw_width - 16;
4638 XSync(xDisplay, False);
4640 /* This code seems to tickle an X bug if it is executed too soon
4641 after xboard starts up. The coordinates get transformed as if
4642 the main window was positioned at (0, 0).
4644 XtTranslateCoords(shellWidget,
4645 (bw_width - commentW) / 2, 0 - commentH / 2,
4646 &commentX, &commentY);
4648 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4649 RootWindowOfScreen(XtScreen(shellWidget)),
4650 (bw_width - commentW) / 2, 0 - commentH / 2,
4655 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
4658 XtSetArg(args[j], XtNheight, commentH); j++;
4659 XtSetArg(args[j], XtNwidth, commentW); j++;
4660 XtSetArg(args[j], XtNx, commentX); j++;
4661 XtSetArg(args[j], XtNy, commentY); j++;
4662 XtSetValues(shell, args, j);
4663 XtSetKeyboardFocus(shell, edit);
4668 /* Used for analysis window and ICS input window */
4669 Widget MiscCreate(name, text, mutable, callback, lines)
4671 int /*Boolean*/ mutable;
4672 XtCallbackProc callback;
4676 Widget shell, layout, form, edit;
4678 Dimension bw_width, pw_height, ew_height, w, h;
4684 XtSetArg(args[j], XtNresizable, True); j++;
4687 XtCreatePopupShell(name, topLevelShellWidgetClass,
4688 shellWidget, args, j);
4691 XtCreatePopupShell(name, transientShellWidgetClass,
4692 shellWidget, args, j);
4695 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
4696 layoutArgs, XtNumber(layoutArgs));
4698 XtCreateManagedWidget("form", formWidgetClass, layout,
4699 formArgs, XtNumber(formArgs));
4703 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
4704 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
4706 XtSetArg(args[j], XtNstring, text); j++;
4707 XtSetArg(args[j], XtNtop, XtChainTop); j++;
4708 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
4709 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
4710 XtSetArg(args[j], XtNright, XtChainRight); j++;
4711 XtSetArg(args[j], XtNresizable, True); j++;
4713 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
4715 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
4716 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
4718 XtSetArg(args[j], XtNautoFill, True); j++;
4719 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
4721 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
4723 XtRealizeWidget(shell);
4726 XtSetArg(args[j], XtNwidth, &bw_width); j++;
4727 XtGetValues(boardWidget, args, j);
4730 XtSetArg(args[j], XtNheight, &ew_height); j++;
4731 XtGetValues(edit, args, j);
4734 XtSetArg(args[j], XtNheight, &pw_height); j++;
4735 XtGetValues(shell, args, j);
4736 h = pw_height + (lines - 1) * ew_height;
4739 XSync(xDisplay, False);
4741 /* This code seems to tickle an X bug if it is executed too soon
4742 after xboard starts up. The coordinates get transformed as if
4743 the main window was positioned at (0, 0).
4745 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
4747 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
4748 RootWindowOfScreen(XtScreen(shellWidget)),
4749 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
4753 if (y < 0) y = 0; /*avoid positioning top offscreen*/
4756 XtSetArg(args[j], XtNheight, h); j++;
4757 XtSetArg(args[j], XtNwidth, w); j++;
4758 XtSetArg(args[j], XtNx, x); j++;
4759 XtSetArg(args[j], XtNy, y); j++;
4760 XtSetValues(shell, args, j);
4766 static int savedIndex; /* gross that this is global */
4768 void EditCommentPopUp(index, title, text)
4777 if (text == NULL) text = "";
4779 if (editShell == NULL) {
4781 CommentCreate(title, text, True, EditCommentCallback, 4);
4782 XtRealizeWidget(editShell);
4783 CatchDeleteWindow(editShell, "EditCommentPopDown");
4785 edit = XtNameToWidget(editShell, "*form.text");
4787 XtSetArg(args[j], XtNstring, text); j++;
4788 XtSetValues(edit, args, j);
4790 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4791 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4792 XtSetValues(editShell, args, j);
4795 XtPopup(editShell, XtGrabNone);
4799 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4800 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4804 void EditCommentCallback(w, client_data, call_data)
4806 XtPointer client_data, call_data;
4814 XtSetArg(args[j], XtNlabel, &name); j++;
4815 XtGetValues(w, args, j);
4817 if (strcmp(name, _("ok")) == 0) {
4818 edit = XtNameToWidget(editShell, "*form.text");
4820 XtSetArg(args[j], XtNstring, &val); j++;
4821 XtGetValues(edit, args, j);
4822 ReplaceComment(savedIndex, val);
4823 EditCommentPopDown();
4824 } else if (strcmp(name, _("cancel")) == 0) {
4825 EditCommentPopDown();
4826 } else if (strcmp(name, _("clear")) == 0) {
4827 edit = XtNameToWidget(editShell, "*form.text");
4828 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4829 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4833 void EditCommentPopDown()
4838 if (!editUp) return;
4840 XtSetArg(args[j], XtNx, &commentX); j++;
4841 XtSetArg(args[j], XtNy, &commentY); j++;
4842 XtSetArg(args[j], XtNheight, &commentH); j++;
4843 XtSetArg(args[j], XtNwidth, &commentW); j++;
4844 XtGetValues(editShell, args, j);
4845 XtPopdown(editShell);
4848 XtSetArg(args[j], XtNleftBitmap, None); j++;
4849 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
4853 void ICSInputBoxPopUp()
4858 char *title = _("ICS Input");
4861 if (ICSInputShell == NULL) {
4862 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
4863 tr = XtParseTranslationTable(ICSInputTranslations);
4864 edit = XtNameToWidget(ICSInputShell, "*form.text");
4865 XtOverrideTranslations(edit, tr);
4866 XtRealizeWidget(ICSInputShell);
4867 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
4870 edit = XtNameToWidget(ICSInputShell, "*form.text");
4872 XtSetArg(args[j], XtNstring, ""); j++;
4873 XtSetValues(edit, args, j);
4875 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4876 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4877 XtSetValues(ICSInputShell, args, j);
4880 XtPopup(ICSInputShell, XtGrabNone);
4881 XtSetKeyboardFocus(ICSInputShell, edit);
4883 ICSInputBoxUp = True;
4885 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
4886 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4890 void ICSInputSendText()
4897 edit = XtNameToWidget(ICSInputShell, "*form.text");
4899 XtSetArg(args[j], XtNstring, &val); j++;
4900 XtGetValues(edit, args, j);
4901 SendMultiLineToICS(val);
4902 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
4903 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
4906 void ICSInputBoxPopDown()
4911 if (!ICSInputBoxUp) return;
4913 XtPopdown(ICSInputShell);
4914 ICSInputBoxUp = False;
4916 XtSetArg(args[j], XtNleftBitmap, None); j++;
4917 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
4921 void CommentPopUp(title, text)
4928 if (commentShell == NULL) {
4930 CommentCreate(title, text, False, CommentCallback, 4);
4931 XtRealizeWidget(commentShell);
4932 CatchDeleteWindow(commentShell, "CommentPopDown");
4934 edit = XtNameToWidget(commentShell, "*form.text");
4936 XtSetArg(args[j], XtNstring, text); j++;
4937 XtSetValues(edit, args, j);
4939 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4940 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4941 XtSetValues(commentShell, args, j);
4944 XtPopup(commentShell, XtGrabNone);
4945 XSync(xDisplay, False);
4950 void AnalysisPopUp(title, text)
4957 if (analysisShell == NULL) {
4958 analysisShell = MiscCreate(title, text, False, NULL, 4);
4959 XtRealizeWidget(analysisShell);
4960 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
4963 edit = XtNameToWidget(analysisShell, "*form.text");
4965 XtSetArg(args[j], XtNstring, text); j++;
4966 XtSetValues(edit, args, j);
4968 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
4969 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
4970 XtSetValues(analysisShell, args, j);
4974 XtPopup(analysisShell, XtGrabNone);
4976 XSync(xDisplay, False);
4981 void CommentCallback(w, client_data, call_data)
4983 XtPointer client_data, call_data;
4990 XtSetArg(args[j], XtNlabel, &name); j++;
4991 XtGetValues(w, args, j);
4993 if (strcmp(name, _("close")) == 0) {
4995 } else if (strcmp(name, _("edit")) == 0) {
5002 void CommentPopDown()
5007 if (!commentUp) return;
5009 XtSetArg(args[j], XtNx, &commentX); j++;
5010 XtSetArg(args[j], XtNy, &commentY); j++;
5011 XtSetArg(args[j], XtNwidth, &commentW); j++;
5012 XtSetArg(args[j], XtNheight, &commentH); j++;
5013 XtGetValues(commentShell, args, j);
5014 XtPopdown(commentShell);
5015 XSync(xDisplay, False);
5019 void AnalysisPopDown()
5021 if (!analysisUp) return;
5022 XtPopdown(analysisShell);
5023 XSync(xDisplay, False);
5028 void FileNamePopUp(label, def, proc, openMode)
5035 Widget popup, layout, dialog, edit;
5041 fileProc = proc; /* I can't see a way not */
5042 fileOpenMode = openMode; /* to use globals here */
5045 XtSetArg(args[i], XtNresizable, True); i++;
5046 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
5047 XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++;
5048 fileNameShell = popup =
5049 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
5050 shellWidget, args, i);
5053 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
5054 layoutArgs, XtNumber(layoutArgs));
5057 XtSetArg(args[i], XtNlabel, label); i++;
5058 XtSetArg(args[i], XtNvalue, def); i++;
5059 XtSetArg(args[i], XtNborderWidth, 0); i++;
5060 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
5063 XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog);
5064 XawDialogAddButton(dialog, _("cancel"), FileNameCallback,
5065 (XtPointer) dialog);
5067 XtRealizeWidget(popup);
5068 CatchDeleteWindow(popup, "FileNamePopDown");
5070 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
5071 &x, &y, &win_x, &win_y, &mask);
5073 XtSetArg(args[0], XtNx, x - 10);
5074 XtSetArg(args[1], XtNy, y - 30);
5075 XtSetValues(popup, args, 2);
5077 XtPopup(popup, XtGrabExclusive);
5080 edit = XtNameToWidget(dialog, "*value");
5081 XtSetKeyboardFocus(popup, edit);
5084 void FileNamePopDown()
5086 if (!filenameUp) return;
5087 XtPopdown(fileNameShell);
5088 XtDestroyWidget(fileNameShell);
5093 void FileNameCallback(w, client_data, call_data)
5095 XtPointer client_data, call_data;
5100 XtSetArg(args[0], XtNlabel, &name);
5101 XtGetValues(w, args, 1);
5103 if (strcmp(name, _("cancel")) == 0) {
5108 FileNameAction(w, NULL, NULL, NULL);
5111 void FileNameAction(w, event, prms, nprms)
5123 name = XawDialogGetValueString(w = XtParent(w));
5125 if ((name != NULL) && (*name != NULLCHAR)) {
5127 XtPopdown(w = XtParent(XtParent(w)));
5131 p = strrchr(buf, ' ');
5138 fullname = ExpandPathName(buf);
5140 ErrorPopUp(_("Error"), _("Can't open file"), FALSE);
5143 f = fopen(fullname, fileOpenMode);
5145 DisplayError(_("Failed to open file"), errno);
5147 (void) (*fileProc)(f, index, buf);
5154 XtPopdown(w = XtParent(XtParent(w)));
5160 void PromotionPopUp()
5163 Widget dialog, layout;
5165 Dimension bw_width, pw_width;
5169 XtSetArg(args[j], XtNwidth, &bw_width); j++;
5170 XtGetValues(boardWidget, args, j);
5173 XtSetArg(args[j], XtNresizable, True); j++;
5174 XtSetArg(args[j], XtNtitle, XtNewString(_("Promotion"))); j++;
5176 XtCreatePopupShell("Promotion", transientShellWidgetClass,
5177 shellWidget, args, j);
5179 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
5180 layoutArgs, XtNumber(layoutArgs));
5183 XtSetArg(args[j], XtNlabel, _("Promote pawn to what?")); j++;
5184 XtSetArg(args[j], XtNborderWidth, 0); j++;
5185 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
5188 XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
5189 (XtPointer) dialog);
5190 XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
5191 (XtPointer) dialog);
5192 XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
5193 (XtPointer) dialog);
5194 XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
5195 (XtPointer) dialog);
5196 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
5197 gameInfo.variant == VariantGiveaway) {
5198 XawDialogAddButton(dialog, _("King"), PromotionCallback,
5199 (XtPointer) dialog);
5201 XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
5202 (XtPointer) dialog);
5204 XtRealizeWidget(promotionShell);
5205 CatchDeleteWindow(promotionShell, "PromotionPopDown");
5208 XtSetArg(args[j], XtNwidth, &pw_width); j++;
5209 XtGetValues(promotionShell, args, j);
5211 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5212 lineGap + squareSize/3 +
5213 ((toY == 7) ^ (flipView) ?
5214 0 : 6*(squareSize + lineGap)), &x, &y);
5217 XtSetArg(args[j], XtNx, x); j++;
5218 XtSetArg(args[j], XtNy, y); j++;
5219 XtSetValues(promotionShell, args, j);
5221 XtPopup(promotionShell, XtGrabNone);
5226 void PromotionPopDown()
5228 if (!promotionUp) return;
5229 XtPopdown(promotionShell);
5230 XtDestroyWidget(promotionShell);
5231 promotionUp = False;
5234 void PromotionCallback(w, client_data, call_data)
5236 XtPointer client_data, call_data;
5242 XtSetArg(args[0], XtNlabel, &name);
5243 XtGetValues(w, args, 1);
5247 if (fromX == -1) return;
5249 if (strcmp(name, _("cancel")) == 0) {
5253 } else if (strcmp(name, _("Knight")) == 0) {
5256 promoChar = ToLower(name[0]);
5259 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
5261 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
5262 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
5267 void ErrorCallback(w, client_data, call_data)
5269 XtPointer client_data, call_data;
5272 XtPopdown(w = XtParent(XtParent(XtParent(w))));
5274 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5280 if (!errorUp) return;
5282 XtPopdown(errorShell);
5283 XtDestroyWidget(errorShell);
5284 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
5287 void ErrorPopUp(title, label, modal)
5288 char *title, *label;
5292 Widget dialog, layout;
5296 Dimension bw_width, pw_width;
5297 Dimension pw_height;
5301 XtSetArg(args[i], XtNresizable, True); i++;
5302 XtSetArg(args[i], XtNtitle, title); i++;
5304 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
5305 shellWidget, args, i);
5307 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
5308 layoutArgs, XtNumber(layoutArgs));
5311 XtSetArg(args[i], XtNlabel, label); i++;
5312 XtSetArg(args[i], XtNborderWidth, 0); i++;
5313 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
5316 XawDialogAddButton(dialog, _("ok"), ErrorCallback, (XtPointer) dialog);
5318 XtRealizeWidget(errorShell);
5319 CatchDeleteWindow(errorShell, "ErrorPopDown");
5322 XtSetArg(args[i], XtNwidth, &bw_width); i++;
5323 XtGetValues(boardWidget, args, i);
5325 XtSetArg(args[i], XtNwidth, &pw_width); i++;
5326 XtSetArg(args[i], XtNheight, &pw_height); i++;
5327 XtGetValues(errorShell, args, i);
5330 /* This code seems to tickle an X bug if it is executed too soon
5331 after xboard starts up. The coordinates get transformed as if
5332 the main window was positioned at (0, 0).
5334 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
5335 0 - pw_height + squareSize / 3, &x, &y);
5337 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
5338 RootWindowOfScreen(XtScreen(boardWidget)),
5339 (bw_width - pw_width) / 2,
5340 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
5344 if (y < 0) y = 0; /*avoid positioning top offscreen*/
5347 XtSetArg(args[i], XtNx, x); i++;
5348 XtSetArg(args[i], XtNy, y); i++;
5349 XtSetValues(errorShell, args, i);
5352 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
5355 /* Disable all user input other than deleting the window */
5356 static int frozen = 0;
5360 /* Grab by a widget that doesn't accept input */
5361 XtAddGrab(messageWidget, TRUE, FALSE);
5365 /* Undo a FreezeUI */
5368 if (!frozen) return;
5369 XtRemoveGrab(messageWidget);
5373 char *ModeToWidgetName(mode)
5377 case BeginningOfGame:
5378 if (appData.icsActive)
5379 return "menuMode.ICS Client";
5380 else if (appData.noChessProgram ||
5381 *appData.cmailGameName != NULLCHAR)
5382 return "menuMode.Edit Game";
5384 return "menuMode.Machine Black";
5385 case MachinePlaysBlack:
5386 return "menuMode.Machine Black";
5387 case MachinePlaysWhite:
5388 return "menuMode.Machine White";
5390 return "menuMode.Analysis Mode";
5392 return "menuMode.Analyze File";
5393 case TwoMachinesPlay:
5394 return "menuMode.Two Machines";
5396 return "menuMode.Edit Game";
5397 case PlayFromGameFile:
5398 return "menuFile.Load Game";
5400 return "menuMode.Edit Position";
5402 return "menuMode.Training";
5403 case IcsPlayingWhite:
5404 case IcsPlayingBlack:
5408 return "menuMode.ICS Client";
5415 void ModeHighlight()
5418 static int oldPausing = FALSE;
5419 static GameMode oldmode = (GameMode) -1;
5422 if (!boardWidget || !XtIsRealized(boardWidget)) return;
5424 if (pausing != oldPausing) {
5425 oldPausing = pausing;
5427 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5429 XtSetArg(args[0], XtNleftBitmap, None);
5431 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
5434 if (appData.showButtonBar) {
5437 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
5438 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
5440 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
5441 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
5444 /* Always toggle, don't set. Previous code messes up when
5445 invoked while the button is pressed, as releasing it
5446 toggles the state again. */
5449 XtSetArg(args[0], XtNbackground, &oldbg);
5450 XtSetArg(args[1], XtNforeground, &oldfg);
5451 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
5453 XtSetArg(args[0], XtNbackground, oldfg);
5454 XtSetArg(args[1], XtNforeground, oldbg);
5457 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
5461 wname = ModeToWidgetName(oldmode);
5462 if (wname != NULL) {
5463 XtSetArg(args[0], XtNleftBitmap, None);
5464 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5466 wname = ModeToWidgetName(gameMode);
5467 if (wname != NULL) {
5468 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
5469 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
5473 /* Maybe all the enables should be handled here, not just this one */
5474 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
5475 gameMode == Training || gameMode == PlayFromGameFile);
5480 * Button/menu procedures
5482 void ResetProc(w, event, prms, nprms)
5492 int LoadGamePopUp(f, gameNumber, title)
5497 cmailMsgLoaded = FALSE;
5498 if (gameNumber == 0) {
5499 int error = GameListBuild(f);
5501 DisplayError(_("Cannot build game list"), error);
5502 } else if (!ListEmpty(&gameList) &&
5503 ((ListGame *) gameList.tailPred)->number > 1) {
5504 GameListPopUp(f, title);
5510 return LoadGame(f, gameNumber, title, FALSE);
5513 void LoadGameProc(w, event, prms, nprms)
5519 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5522 FileNamePopUp(_("Load game file name?"), "", LoadGamePopUp, "rb");
5525 void LoadNextGameProc(w, event, prms, nprms)
5534 void LoadPrevGameProc(w, event, prms, nprms)
5543 void ReloadGameProc(w, event, prms, nprms)
5552 void LoadNextPositionProc(w, event, prms, nprms)
5561 void LoadPrevPositionProc(w, event, prms, nprms)
5570 void ReloadPositionProc(w, event, prms, nprms)
5579 void LoadPositionProc(w, event, prms, nprms)
5585 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
5588 FileNamePopUp(_("Load position file name?"), "", LoadPosition, "rb");
5591 void SaveGameProc(w, event, prms, nprms)
5597 FileNamePopUp(_("Save game file name?"),
5598 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
5602 void SavePositionProc(w, event, prms, nprms)
5608 FileNamePopUp(_("Save position file name?"),
5609 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
5613 void ReloadCmailMsgProc(w, event, prms, nprms)
5619 ReloadCmailMsgEvent(FALSE);
5622 void MailMoveProc(w, event, prms, nprms)
5631 /* this variable is shared between CopyPositionProc and SendPositionSelection */
5632 static char *selected_fen_position=NULL;
5635 SendPositionSelection(Widget w, Atom *selection, Atom *target,
5636 Atom *type_return, XtPointer *value_return,
5637 unsigned long *length_return, int *format_return)
5639 char *selection_tmp;
5641 if (!selected_fen_position) return False; /* should never happen */
5642 if (*target == XA_STRING){
5643 /* note: since no XtSelectionDoneProc was registered, Xt will
5644 * automatically call XtFree on the value returned. So have to
5645 * make a copy of it allocated with XtMalloc */
5646 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
5647 strcpy(selection_tmp, selected_fen_position);
5649 *value_return=selection_tmp;
5650 *length_return=strlen(selection_tmp);
5651 *type_return=XA_STRING;
5652 *format_return = 8; /* bits per byte */
5659 /* note: when called from menu all parameters are NULL, so no clue what the
5660 * Widget which was clicked on was, or what the click event was
5662 void CopyPositionProc(w, event, prms, nprms)
5670 if (selected_fen_position) free(selected_fen_position);
5671 selected_fen_position = (char *)PositionToFEN(currentMove);
5672 if (!selected_fen_position) return;
5673 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5675 SendPositionSelection,
5676 NULL/* lose_ownership_proc */ ,
5677 NULL/* transfer_done_proc */);
5679 free(selected_fen_position);
5680 selected_fen_position=NULL;
5684 /* function called when the data to Paste is ready */
5686 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
5687 Atom *type, XtPointer value, unsigned long *len, int *format)
5690 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
5691 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
5692 EditPositionPasteFEN(fenstr);
5696 /* called when Paste Position button is pressed,
5697 * all parameters will be NULL */
5698 void PastePositionProc(w, event, prms, nprms)
5704 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5705 /* (XtSelectionCallbackProc) */ PastePositionCB,
5706 NULL, /* client_data passed to PastePositionCB */
5708 /* better to use the time field from the event that triggered the
5709 * call to this function, but that isn't trivial to get
5717 SendGameSelection(Widget w, Atom *selection, Atom *target,
5718 Atom *type_return, XtPointer *value_return,
5719 unsigned long *length_return, int *format_return)
5721 char *selection_tmp;
5723 if (*target == XA_STRING){
5724 FILE* f = fopen(gameCopyFilename, "r");
5727 if (f == NULL) return False;
5731 selection_tmp = XtMalloc(len + 1);
5732 count = fread(selection_tmp, 1, len, f);
5734 XtFree(selection_tmp);
5737 selection_tmp[len] = NULLCHAR;
5738 *value_return = selection_tmp;
5739 *length_return = len;
5740 *type_return = XA_STRING;
5741 *format_return = 8; /* bits per byte */
5748 /* note: when called from menu all parameters are NULL, so no clue what the
5749 * Widget which was clicked on was, or what the click event was
5751 void CopyGameProc(w, event, prms, nprms)
5759 ret = SaveGameToFile(gameCopyFilename, FALSE);
5762 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
5765 NULL/* lose_ownership_proc */ ,
5766 NULL/* transfer_done_proc */);
5769 /* function called when the data to Paste is ready */
5771 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
5772 Atom *type, XtPointer value, unsigned long *len, int *format)
5775 if (value == NULL || *len == 0) {
5776 return; /* nothing had been selected to copy */
5778 f = fopen(gamePasteFilename, "w");
5780 DisplayError(_("Can't open temp file"), errno);
5783 fwrite(value, 1, *len, f);
5786 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
5789 /* called when Paste Game button is pressed,
5790 * all parameters will be NULL */
5791 void PasteGameProc(w, event, prms, nprms)
5797 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
5798 /* (XtSelectionCallbackProc) */ PasteGameCB,
5799 NULL, /* client_data passed to PasteGameCB */
5801 /* better to use the time field from the event that triggered the
5802 * call to this function, but that isn't trivial to get
5812 SaveGameProc(NULL, NULL, NULL, NULL);
5816 void QuitProc(w, event, prms, nprms)
5825 void PauseProc(w, event, prms, nprms)
5835 void MachineBlackProc(w, event, prms, nprms)
5841 MachineBlackEvent();
5844 void MachineWhiteProc(w, event, prms, nprms)
5850 MachineWhiteEvent();
5853 void AnalyzeModeProc(w, event, prms, nprms)
5859 if (!first.analysisSupport) {
5861 sprintf(buf, _("%s does not support analysis"), first.tidy);
5862 DisplayError(buf, 0);
5865 if (!appData.showThinking)
5866 ShowThinkingProc(w,event,prms,nprms);
5871 void AnalyzeFileProc(w, event, prms, nprms)
5877 if (!first.analysisSupport) {
5879 sprintf(buf, _("%s does not support analysis"), first.tidy);
5880 DisplayError(buf, 0);
5885 if (!appData.showThinking)
5886 ShowThinkingProc(w,event,prms,nprms);
5889 FileNamePopUp(_("File to analyze"), "", LoadGamePopUp, "rb");
5890 AnalysisPeriodicEvent(1);
5893 void TwoMachinesProc(w, event, prms, nprms)
5902 void IcsClientProc(w, event, prms, nprms)
5911 void EditGameProc(w, event, prms, nprms)
5920 void EditPositionProc(w, event, prms, nprms)
5926 EditPositionEvent();
5929 void TrainingProc(w, event, prms, nprms)
5938 void EditCommentProc(w, event, prms, nprms)
5945 EditCommentPopDown();
5951 void IcsInputBoxProc(w, event, prms, nprms)
5957 if (ICSInputBoxUp) {
5958 ICSInputBoxPopDown();
5964 void AcceptProc(w, event, prms, nprms)
5973 void DeclineProc(w, event, prms, nprms)
5982 void RematchProc(w, event, prms, nprms)
5991 void CallFlagProc(w, event, prms, nprms)
6000 void DrawProc(w, event, prms, nprms)
6009 void AbortProc(w, event, prms, nprms)
6018 void AdjournProc(w, event, prms, nprms)
6027 void ResignProc(w, event, prms, nprms)
6036 void EnterKeyProc(w, event, prms, nprms)
6042 if (ICSInputBoxUp == True)
6046 void StopObservingProc(w, event, prms, nprms)
6052 StopObservingEvent();
6055 void StopExaminingProc(w, event, prms, nprms)
6061 StopExaminingEvent();
6065 void ForwardProc(w, event, prms, nprms)
6075 void BackwardProc(w, event, prms, nprms)
6084 void ToStartProc(w, event, prms, nprms)
6093 void ToEndProc(w, event, prms, nprms)
6102 void RevertProc(w, event, prms, nprms)
6111 void TruncateGameProc(w, event, prms, nprms)
6117 TruncateGameEvent();
6119 void RetractMoveProc(w, event, prms, nprms)
6128 void MoveNowProc(w, event, prms, nprms)
6138 void AlwaysQueenProc(w, event, prms, nprms)
6146 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
6148 if (appData.alwaysPromoteToQueen) {
6149 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6151 XtSetArg(args[0], XtNleftBitmap, None);
6153 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
6157 void AnimateDraggingProc(w, event, prms, nprms)
6165 appData.animateDragging = !appData.animateDragging;
6167 if (appData.animateDragging) {
6168 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6171 XtSetArg(args[0], XtNleftBitmap, None);
6173 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
6177 void AnimateMovingProc(w, event, prms, nprms)
6185 appData.animate = !appData.animate;
6187 if (appData.animate) {
6188 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6191 XtSetArg(args[0], XtNleftBitmap, None);
6193 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
6197 void AutocommProc(w, event, prms, nprms)
6205 appData.autoComment = !appData.autoComment;
6207 if (appData.autoComment) {
6208 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6210 XtSetArg(args[0], XtNleftBitmap, None);
6212 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
6217 void AutoflagProc(w, event, prms, nprms)
6225 appData.autoCallFlag = !appData.autoCallFlag;
6227 if (appData.autoCallFlag) {
6228 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6230 XtSetArg(args[0], XtNleftBitmap, None);
6232 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
6236 void AutoflipProc(w, event, prms, nprms)
6244 appData.autoFlipView = !appData.autoFlipView;
6246 if (appData.autoFlipView) {
6247 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6249 XtSetArg(args[0], XtNleftBitmap, None);
6251 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
6255 void AutobsProc(w, event, prms, nprms)
6263 appData.autoObserve = !appData.autoObserve;
6265 if (appData.autoObserve) {
6266 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6268 XtSetArg(args[0], XtNleftBitmap, None);
6270 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
6274 void AutoraiseProc(w, event, prms, nprms)
6282 appData.autoRaiseBoard = !appData.autoRaiseBoard;
6284 if (appData.autoRaiseBoard) {
6285 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6287 XtSetArg(args[0], XtNleftBitmap, None);
6289 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
6293 void AutosaveProc(w, event, prms, nprms)
6301 appData.autoSaveGames = !appData.autoSaveGames;
6303 if (appData.autoSaveGames) {
6304 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6306 XtSetArg(args[0], XtNleftBitmap, None);
6308 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
6312 void BlindfoldProc(w, event, prms, nprms)
6320 appData.blindfold = !appData.blindfold;
6322 if (appData.blindfold) {
6323 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6325 XtSetArg(args[0], XtNleftBitmap, None);
6327 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
6330 DrawPosition(True, NULL);
6333 void TestLegalityProc(w, event, prms, nprms)
6341 appData.testLegality = !appData.testLegality;
6343 if (appData.testLegality) {
6344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6346 XtSetArg(args[0], XtNleftBitmap, None);
6348 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
6353 void FlashMovesProc(w, event, prms, nprms)
6361 if (appData.flashCount == 0) {
6362 appData.flashCount = 3;
6364 appData.flashCount = -appData.flashCount;
6367 if (appData.flashCount > 0) {
6368 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6370 XtSetArg(args[0], XtNleftBitmap, None);
6372 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
6376 void FlipViewProc(w, event, prms, nprms)
6382 flipView = !flipView;
6383 DrawPosition(True, NULL);
6386 void GetMoveListProc(w, event, prms, nprms)
6394 appData.getMoveList = !appData.getMoveList;
6396 if (appData.getMoveList) {
6397 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6400 XtSetArg(args[0], XtNleftBitmap, None);
6402 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
6407 void HighlightDraggingProc(w, event, prms, nprms)
6415 appData.highlightDragging = !appData.highlightDragging;
6417 if (appData.highlightDragging) {
6418 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6420 XtSetArg(args[0], XtNleftBitmap, None);
6422 XtSetValues(XtNameToWidget(menuBarWidget,
6423 "menuOptions.Highlight Dragging"), args, 1);
6427 void HighlightLastMoveProc(w, event, prms, nprms)
6435 appData.highlightLastMove = !appData.highlightLastMove;
6437 if (appData.highlightLastMove) {
6438 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6440 XtSetArg(args[0], XtNleftBitmap, None);
6442 XtSetValues(XtNameToWidget(menuBarWidget,
6443 "menuOptions.Highlight Last Move"), args, 1);
6446 void IcsAlarmProc(w, event, prms, nprms)
6454 appData.icsAlarm = !appData.icsAlarm;
6456 if (appData.icsAlarm) {
6457 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6459 XtSetArg(args[0], XtNleftBitmap, None);
6461 XtSetValues(XtNameToWidget(menuBarWidget,
6462 "menuOptions.ICS Alarm"), args, 1);
6465 void MoveSoundProc(w, event, prms, nprms)
6473 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
6475 if (appData.ringBellAfterMoves) {
6476 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6478 XtSetArg(args[0], XtNleftBitmap, None);
6480 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
6485 void OldSaveStyleProc(w, event, prms, nprms)
6493 appData.oldSaveStyle = !appData.oldSaveStyle;
6495 if (appData.oldSaveStyle) {
6496 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6498 XtSetArg(args[0], XtNleftBitmap, None);
6500 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
6504 void PeriodicUpdatesProc(w, event, prms, nprms)
6512 PeriodicUpdatesEvent(!appData.periodicUpdates);
6514 if (appData.periodicUpdates) {
6515 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6517 XtSetArg(args[0], XtNleftBitmap, None);
6519 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
6523 void PonderNextMoveProc(w, event, prms, nprms)
6531 PonderNextMoveEvent(!appData.ponderNextMove);
6533 if (appData.ponderNextMove) {
6534 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6536 XtSetArg(args[0], XtNleftBitmap, None);
6538 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
6542 void PopupExitMessageProc(w, event, prms, nprms)
6550 appData.popupExitMessage = !appData.popupExitMessage;
6552 if (appData.popupExitMessage) {
6553 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6555 XtSetArg(args[0], XtNleftBitmap, None);
6557 XtSetValues(XtNameToWidget(menuBarWidget,
6558 "menuOptions.Popup Exit Message"), args, 1);
6561 void PopupMoveErrorsProc(w, event, prms, nprms)
6569 appData.popupMoveErrors = !appData.popupMoveErrors;
6571 if (appData.popupMoveErrors) {
6572 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6574 XtSetArg(args[0], XtNleftBitmap, None);
6576 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
6580 void PremoveProc(w, event, prms, nprms)
6588 appData.premove = !appData.premove;
6590 if (appData.premove) {
6591 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6593 XtSetArg(args[0], XtNleftBitmap, None);
6595 XtSetValues(XtNameToWidget(menuBarWidget,
6596 "menuOptions.Premove"), args, 1);
6599 void QuietPlayProc(w, event, prms, nprms)
6607 appData.quietPlay = !appData.quietPlay;
6609 if (appData.quietPlay) {
6610 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6612 XtSetArg(args[0], XtNleftBitmap, None);
6614 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
6618 void ShowCoordsProc(w, event, prms, nprms)
6626 appData.showCoords = !appData.showCoords;
6628 if (appData.showCoords) {
6629 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6631 XtSetArg(args[0], XtNleftBitmap, None);
6633 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
6636 DrawPosition(True, NULL);
6639 void ShowThinkingProc(w, event, prms, nprms)
6647 ShowThinkingEvent(!appData.showThinking);
6649 if (appData.showThinking) {
6650 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
6652 XtSetArg(args[0], XtNleftBitmap, None);
6654 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
6658 void InfoProc(w, event, prms, nprms)
6665 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
6670 void ManProc(w, event, prms, nprms)
6678 if (nprms && *nprms > 0)
6682 sprintf(buf, "xterm -e man %s &", name);
6686 void HintProc(w, event, prms, nprms)
6695 void BookProc(w, event, prms, nprms)
6704 void AboutProc(w, event, prms, nprms)
6712 char *zippy = " (with Zippy code)";
6716 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
6717 programVersion, zippy,
6718 "Copyright 1991 Digital Equipment Corporation",
6719 "Enhancements Copyright 1992-2001 Free Software Foundation",
6720 PRODUCT, " is free software and carries NO WARRANTY;",
6721 "see the file COPYING for more information.");
6722 ErrorPopUp(_("About XBoard"), buf, FALSE);
6725 void DebugProc(w, event, prms, nprms)
6731 appData.debugMode = !appData.debugMode;
6734 void AboutGameProc(w, event, prms, nprms)
6743 void NothingProc(w, event, prms, nprms)
6752 void Iconify(w, event, prms, nprms)
6761 XtSetArg(args[0], XtNiconic, True);
6762 XtSetValues(shellWidget, args, 1);
6765 void DisplayMessage(message, extMessage)
6766 char *message, *extMessage;
6773 sprintf(buf, "%s %s", message, extMessage);
6776 message = extMessage;
6779 XtSetArg(arg, XtNlabel, message);
6780 XtSetValues(messageWidget, &arg, 1);
6783 void DisplayTitle(text)
6788 char title[MSG_SIZ];
6791 if (text == NULL) text = "";
6793 if (appData.titleInWindow) {
6795 XtSetArg(args[i], XtNlabel, text); i++;
6796 XtSetValues(titleWidget, args, i);
6799 if (*text != NULLCHAR) {
6801 strcpy(title, text);
6802 } else if (appData.icsActive) {
6803 sprintf(icon, "%s", appData.icsHost);
6804 sprintf(title, "%s: %s", programName, appData.icsHost);
6805 } else if (appData.cmailGameName[0] != NULLCHAR) {
6806 sprintf(icon, "%s", "CMail");
6807 sprintf(title, "%s: %s", programName, "CMail");
6808 } else if (appData.noChessProgram) {
6809 strcpy(icon, programName);
6810 strcpy(title, programName);
6812 strcpy(icon, first.tidy);
6813 sprintf(title, "%s: %s", programName, first.tidy);
6816 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
6817 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
6818 XtSetValues(shellWidget, args, i);
6822 void DisplayError(message, error)
6829 if (appData.debugMode || appData.matchMode) {
6830 fprintf(stderr, "%s: %s\n", programName, message);
6833 if (appData.debugMode || appData.matchMode) {
6834 fprintf(stderr, "%s: %s: %s\n",
6835 programName, message, strerror(error));
6837 sprintf(buf, "%s: %s", message, strerror(error));
6840 ErrorPopUp(_("Error"), message, FALSE);
6844 void DisplayMoveError(message)
6849 DrawPosition(FALSE, NULL);
6850 if (appData.debugMode || appData.matchMode) {
6851 fprintf(stderr, "%s: %s\n", programName, message);
6853 if (appData.popupMoveErrors) {
6854 ErrorPopUp(_("Error"), message, FALSE);
6856 DisplayMessage(message, "");
6861 void DisplayFatalError(message, error, status)
6867 errorExitStatus = status;
6869 fprintf(stderr, "%s: %s\n", programName, message);
6871 fprintf(stderr, "%s: %s: %s\n",
6872 programName, message, strerror(error));
6873 sprintf(buf, "%s: %s", message, strerror(error));
6876 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
6877 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
6883 void DisplayInformation(message)
6887 ErrorPopUp(_("Information"), message, TRUE);
6890 void DisplayNote(message)
6894 ErrorPopUp(_("Note"), message, FALSE);
6898 NullXErrorCheck(dpy, error_event)
6900 XErrorEvent *error_event;
6905 void DisplayIcsInteractionTitle(message)
6908 if (oldICSInteractionTitle == NULL) {
6909 /* Magic to find the old window title, adapted from vim */
6910 char *wina = getenv("WINDOWID");
6912 Window win = (Window) atoi(wina);
6913 Window root, parent, *children;
6914 unsigned int nchildren;
6915 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
6917 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
6918 if (!XQueryTree(xDisplay, win, &root, &parent,
6919 &children, &nchildren)) break;
6920 if (children) XFree((void *)children);
6921 if (parent == root || parent == 0) break;
6924 XSetErrorHandler(oldHandler);
6926 if (oldICSInteractionTitle == NULL) {
6927 oldICSInteractionTitle = "xterm";
6930 printf("\033]0;%s\007", message);
6934 char pendingReplyPrefix[MSG_SIZ];
6935 ProcRef pendingReplyPR;
6937 void AskQuestionProc(w, event, prms, nprms)
6944 fprintf(stderr, _("AskQuestionProc needed 4 parameters, got %d\n"),
6948 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
6951 void AskQuestionPopDown()
6953 if (!askQuestionUp) return;
6954 XtPopdown(askQuestionShell);
6955 XtDestroyWidget(askQuestionShell);
6956 askQuestionUp = False;
6959 void AskQuestionReplyAction(w, event, prms, nprms)
6969 reply = XawDialogGetValueString(w = XtParent(w));
6970 strcpy(buf, pendingReplyPrefix);
6971 if (*buf) strcat(buf, " ");
6974 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
6975 AskQuestionPopDown();
6977 if (err) DisplayFatalError(_("Error writing to chess program"), err, 0);
6980 void AskQuestionCallback(w, client_data, call_data)
6982 XtPointer client_data, call_data;
6987 XtSetArg(args[0], XtNlabel, &name);
6988 XtGetValues(w, args, 1);
6990 if (strcmp(name, _("cancel")) == 0) {
6991 AskQuestionPopDown();
6993 AskQuestionReplyAction(w, NULL, NULL, NULL);
6997 void AskQuestion(title, question, replyPrefix, pr)
6998 char *title, *question, *replyPrefix;
7002 Widget popup, layout, dialog, edit;
7008 strcpy(pendingReplyPrefix, replyPrefix);
7009 pendingReplyPR = pr;
7012 XtSetArg(args[i], XtNresizable, True); i++;
7013 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
7014 askQuestionShell = popup =
7015 XtCreatePopupShell(title, transientShellWidgetClass,
7016 shellWidget, args, i);
7019 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
7020 layoutArgs, XtNumber(layoutArgs));
7023 XtSetArg(args[i], XtNlabel, question); i++;
7024 XtSetArg(args[i], XtNvalue, ""); i++;
7025 XtSetArg(args[i], XtNborderWidth, 0); i++;
7026 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
7029 XawDialogAddButton(dialog, _("enter"), AskQuestionCallback,
7030 (XtPointer) dialog);
7031 XawDialogAddButton(dialog, _("cancel"), AskQuestionCallback,
7032 (XtPointer) dialog);
7034 XtRealizeWidget(popup);
7035 CatchDeleteWindow(popup, "AskQuestionPopDown");
7037 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
7038 &x, &y, &win_x, &win_y, &mask);
7040 XtSetArg(args[0], XtNx, x - 10);
7041 XtSetArg(args[1], XtNy, y - 30);
7042 XtSetValues(popup, args, 2);
7044 XtPopup(popup, XtGrabExclusive);
7045 askQuestionUp = True;
7047 edit = XtNameToWidget(dialog, "*value");
7048 XtSetKeyboardFocus(popup, edit);
7056 if (*name == NULLCHAR) {
7058 } else if (strcmp(name, "$") == 0) {
7059 putc(BELLCHAR, stderr);
7062 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
7070 PlaySound(appData.soundMove);
7076 PlaySound(appData.soundIcsWin);
7082 PlaySound(appData.soundIcsLoss);
7088 PlaySound(appData.soundIcsDraw);
7092 PlayIcsUnfinishedSound()
7094 PlaySound(appData.soundIcsUnfinished);
7100 PlaySound(appData.soundIcsAlarm);
7106 system("stty echo");
7112 system("stty -echo");
7116 Colorize(cc, continuation)
7121 int count, outCount, error;
7123 if (textColors[(int)cc].bg > 0) {
7124 if (textColors[(int)cc].fg > 0) {
7125 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
7126 textColors[(int)cc].fg, textColors[(int)cc].bg);
7128 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7129 textColors[(int)cc].bg);
7132 if (textColors[(int)cc].fg > 0) {
7133 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
7134 textColors[(int)cc].fg);
7136 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
7139 count = strlen(buf);
7140 outCount = OutputToProcess(NoProc, buf, count, &error);
7141 if (outCount < count) {
7142 DisplayFatalError(_("Error writing to display"), error, 1);
7145 if (continuation) return;
7148 PlaySound(appData.soundShout);
7151 PlaySound(appData.soundSShout);
7154 PlaySound(appData.soundChannel1);
7157 PlaySound(appData.soundChannel);
7160 PlaySound(appData.soundKibitz);
7163 PlaySound(appData.soundTell);
7165 case ColorChallenge:
7166 PlaySound(appData.soundChallenge);
7169 PlaySound(appData.soundRequest);
7172 PlaySound(appData.soundSeek);
7183 return getpwuid(getuid())->pw_name;
7186 static char *ExpandPathName(path)
7189 static char static_buf[2000];
7190 char *d, *s, buf[2000];
7196 while (*s && isspace(*s))
7205 if (*(s+1) == '/') {
7206 strcpy(d, getpwuid(getuid())->pw_dir);
7211 *strchr(buf, '/') = 0;
7212 pwd = getpwnam(buf);
7215 fprintf(stderr, _("ERROR: Unknown user %s (in path %s)\n"),
7219 strcpy(d, pwd->pw_dir);
7220 strcat(d, strchr(s+1, '/'));
7231 static char host_name[MSG_SIZ];
7233 #if HAVE_GETHOSTNAME
7234 gethostname(host_name, MSG_SIZ);
7236 #else /* not HAVE_GETHOSTNAME */
7237 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
7238 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
7240 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7242 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
7243 #endif /* not HAVE_GETHOSTNAME */
7246 XtIntervalId delayedEventTimerXID = 0;
7247 DelayedEventCallback delayedEventCallback = 0;
7252 delayedEventTimerXID = 0;
7253 delayedEventCallback();
7257 ScheduleDelayedEvent(cb, millisec)
7258 DelayedEventCallback cb; long millisec;
7260 delayedEventCallback = cb;
7261 delayedEventTimerXID =
7262 XtAppAddTimeOut(appContext, millisec,
7263 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
7266 DelayedEventCallback
7269 if (delayedEventTimerXID) {
7270 return delayedEventCallback;
7277 CancelDelayedEvent()
7279 if (delayedEventTimerXID) {
7280 XtRemoveTimeOut(delayedEventTimerXID);
7281 delayedEventTimerXID = 0;
7285 XtIntervalId loadGameTimerXID = 0;
7287 int LoadGameTimerRunning()
7289 return loadGameTimerXID != 0;
7292 int StopLoadGameTimer()
7294 if (loadGameTimerXID != 0) {
7295 XtRemoveTimeOut(loadGameTimerXID);
7296 loadGameTimerXID = 0;
7304 LoadGameTimerCallback(arg, id)
7308 loadGameTimerXID = 0;
7313 StartLoadGameTimer(millisec)
7317 XtAppAddTimeOut(appContext, millisec,
7318 (XtTimerCallbackProc) LoadGameTimerCallback,
7322 XtIntervalId analysisClockXID = 0;
7325 AnalysisClockCallback(arg, id)
7329 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
7330 AnalysisPeriodicEvent(0);
7331 StartAnalysisClock();
7336 StartAnalysisClock()
7339 XtAppAddTimeOut(appContext, 2000,
7340 (XtTimerCallbackProc) AnalysisClockCallback,
7344 XtIntervalId clockTimerXID = 0;
7346 int ClockTimerRunning()
7348 return clockTimerXID != 0;
7351 int StopClockTimer()
7353 if (clockTimerXID != 0) {
7354 XtRemoveTimeOut(clockTimerXID);
7363 ClockTimerCallback(arg, id)
7372 StartClockTimer(millisec)
7376 XtAppAddTimeOut(appContext, millisec,
7377 (XtTimerCallbackProc) ClockTimerCallback,
7382 DisplayTimerLabel(w, color, timer, highlight)
7391 if (appData.clockMode) {
7392 sprintf(buf, "%s: %s", color, TimeString(timer));
7393 XtSetArg(args[0], XtNlabel, buf);
7395 sprintf(buf, "%s ", color);
7396 XtSetArg(args[0], XtNlabel, buf);
7400 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
7401 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
7403 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
7404 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
7407 XtSetValues(w, args, 3);
7411 DisplayWhiteClock(timeRemaining, highlight)
7416 DisplayTimerLabel(whiteTimerWidget, _("White"), timeRemaining, highlight);
7417 if (highlight && iconPixmap == bIconPixmap) {
7418 iconPixmap = wIconPixmap;
7419 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7420 XtSetValues(shellWidget, args, 1);
7425 DisplayBlackClock(timeRemaining, highlight)
7430 DisplayTimerLabel(blackTimerWidget, _("Black"), timeRemaining, highlight);
7431 if (highlight && iconPixmap == wIconPixmap) {
7432 iconPixmap = bIconPixmap;
7433 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
7434 XtSetValues(shellWidget, args, 1);
7452 int StartChildProcess(cmdLine, dir, pr)
7459 int to_prog[2], from_prog[2];
7463 if (appData.debugMode) {
7464 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
7467 /* We do NOT feed the cmdLine to the shell; we just
7468 parse it into blank-separated arguments in the
7469 most simple-minded way possible.
7472 strcpy(buf, cmdLine);
7477 if (p == NULL) break;
7482 SetUpChildIO(to_prog, from_prog);
7484 if ((pid = fork()) == 0) {
7486 dup2(to_prog[0], 0);
7487 dup2(from_prog[1], 1);
7490 close(from_prog[0]);
7491 close(from_prog[1]);
7492 dup2(1, fileno(stderr)); /* force stderr to the pipe */
7494 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
7499 execvp(argv[0], argv);
7501 /* If we get here, exec failed */
7506 /* Parent process */
7508 close(from_prog[1]);
7510 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7513 cp->fdFrom = from_prog[0];
7514 cp->fdTo = to_prog[1];
7520 DestroyChildProcess(pr, signal)
7524 ChildProc *cp = (ChildProc *) pr;
7526 if (cp->kind != CPReal) return;
7529 kill(cp->pid, SIGTERM);
7531 /* Process is exiting either because of the kill or because of
7532 a quit command sent by the backend; either way, wait for it to die.
7540 InterruptChildProcess(pr)
7543 ChildProc *cp = (ChildProc *) pr;
7545 if (cp->kind != CPReal) return;
7546 (void) kill(cp->pid, SIGINT); /* stop it thinking */
7549 int OpenTelnet(host, port, pr)
7554 char cmdLine[MSG_SIZ];
7556 if (port[0] == NULLCHAR) {
7557 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
7559 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
7561 return StartChildProcess(cmdLine, "", pr);
7564 int OpenTCP(host, port, pr)
7570 DisplayFatalError(_("Socket support is not configured in"), 0, 2);
7571 #else /* !OMIT_SOCKETS */
7573 struct sockaddr_in sa;
7575 unsigned short uport;
7578 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
7582 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7583 sa.sin_family = AF_INET;
7584 sa.sin_addr.s_addr = INADDR_ANY;
7585 uport = (unsigned short) 0;
7586 sa.sin_port = htons(uport);
7587 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
7591 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
7592 if (!(hp = gethostbyname(host))) {
7594 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
7595 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
7596 hp->h_addrtype = AF_INET;
7598 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
7599 hp->h_addr_list[0] = (char *) malloc(4);
7600 hp->h_addr_list[0][0] = b0;
7601 hp->h_addr_list[0][1] = b1;
7602 hp->h_addr_list[0][2] = b2;
7603 hp->h_addr_list[0][3] = b3;
7608 sa.sin_family = hp->h_addrtype;
7609 uport = (unsigned short) atoi(port);
7610 sa.sin_port = htons(uport);
7611 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
7613 if (connect(s, (struct sockaddr *) &sa,
7614 sizeof(struct sockaddr_in)) < 0) {
7618 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7625 #endif /* !OMIT_SOCKETS */
7630 int OpenCommPort(name, pr)
7637 fd = open(name, 2, 0);
7638 if (fd < 0) return errno;
7640 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7650 int OpenLoopback(pr)
7656 SetUpChildIO(to, from);
7658 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
7661 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
7668 int OpenRcmd(host, user, cmd, pr)
7669 char *host, *user, *cmd;
7672 DisplayFatalError(_("internal rcmd not implemented for Unix"), 0, 1);
7676 #define INPUT_SOURCE_BUF_SIZE 8192
7685 char buf[INPUT_SOURCE_BUF_SIZE];
7690 DoInputCallback(closure, source, xid)
7695 InputSource *is = (InputSource *) closure;
7700 if (is->lineByLine) {
7701 count = read(is->fd, is->unused,
7702 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
7704 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
7707 is->unused += count;
7709 while (p < is->unused) {
7710 q = memchr(p, '\n', is->unused - p);
7711 if (q == NULL) break;
7713 (is->func)(is, is->closure, p, q - p, 0);
7717 while (p < is->unused) {
7722 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
7727 (is->func)(is, is->closure, is->buf, count, error);
7731 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
7738 ChildProc *cp = (ChildProc *) pr;
7740 is = (InputSource *) calloc(1, sizeof(InputSource));
7741 is->lineByLine = lineByLine;
7745 is->fd = fileno(stdin);
7747 is->kind = cp->kind;
7748 is->fd = cp->fdFrom;
7751 is->unused = is->buf;
7754 is->xid = XtAppAddInput(appContext, is->fd,
7755 (XtPointer) (XtInputReadMask),
7756 (XtInputCallbackProc) DoInputCallback,
7758 is->closure = closure;
7759 return (InputSourceRef) is;
7763 RemoveInputSource(isr)
7766 InputSource *is = (InputSource *) isr;
7768 if (is->xid == 0) return;
7769 XtRemoveInput(is->xid);
7773 int OutputToProcess(pr, message, count, outError)
7779 ChildProc *cp = (ChildProc *) pr;
7783 outCount = fwrite(message, 1, count, stdout);
7785 outCount = write(cp->fdTo, message, count);
7795 /* Output message to process, with "ms" milliseconds of delay
7796 between each character. This is needed when sending the logon
7797 script to ICC, which for some reason doesn't like the
7798 instantaneous send. */
7799 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
7806 ChildProc *cp = (ChildProc *) pr;
7811 r = write(cp->fdTo, message++, 1);
7824 /**** Animation code by Hugh Fisher, DCS, ANU.
7826 Known problem: if a window overlapping the board is
7827 moved away while a piece is being animated underneath,
7828 the newly exposed area won't be updated properly.
7829 I can live with this.
7831 Known problem: if you look carefully at the animation
7832 of pieces in mono mode, they are being drawn as solid
7833 shapes without interior detail while moving. Fixing
7834 this would be a major complication for minimal return.
7837 /* Masks for XPM pieces. Black and white pieces can have
7838 different shapes, but in the interest of retaining my
7839 sanity pieces must have the same outline on both light
7840 and dark squares, and all pieces must use the same
7841 background square colors/images. */
7844 CreateAnimMasks (pieceDepth)
7851 unsigned long plane;
7854 /* Need a bitmap just to get a GC with right depth */
7855 buf = XCreatePixmap(xDisplay, xBoardWindow,
7857 values.foreground = 1;
7858 values.background = 0;
7859 /* Don't use XtGetGC, not read only */
7860 maskGC = XCreateGC(xDisplay, buf,
7861 GCForeground | GCBackground, &values);
7862 XFreePixmap(xDisplay, buf);
7864 buf = XCreatePixmap(xDisplay, xBoardWindow,
7865 squareSize, squareSize, pieceDepth);
7866 values.foreground = XBlackPixel(xDisplay, xScreen);
7867 values.background = XWhitePixel(xDisplay, xScreen);
7868 bufGC = XCreateGC(xDisplay, buf,
7869 GCForeground | GCBackground, &values);
7871 for (piece = WhitePawn; piece <= BlackKing; piece++) {
7872 /* Begin with empty mask */
7873 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
7874 squareSize, squareSize, 1);
7875 XSetFunction(xDisplay, maskGC, GXclear);
7876 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
7877 0, 0, squareSize, squareSize);
7879 /* Take a copy of the piece */
7884 XSetFunction(xDisplay, bufGC, GXcopy);
7885 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
7887 0, 0, squareSize, squareSize, 0, 0);
7889 /* XOR the background (light) over the piece */
7890 XSetFunction(xDisplay, bufGC, GXxor);
7892 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
7893 0, 0, squareSize, squareSize, 0, 0);
7895 XSetForeground(xDisplay, bufGC, lightSquareColor);
7896 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
7899 /* We now have an inverted piece image with the background
7900 erased. Construct mask by just selecting all the non-zero
7901 pixels - no need to reconstruct the original image. */
7902 XSetFunction(xDisplay, maskGC, GXor);
7904 /* Might be quicker to download an XImage and create bitmap
7905 data from it rather than this N copies per piece, but it
7906 only takes a fraction of a second and there is a much
7907 longer delay for loading the pieces. */
7908 for (n = 0; n < pieceDepth; n ++) {
7909 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
7910 0, 0, squareSize, squareSize,
7916 XFreePixmap(xDisplay, buf);
7917 XFreeGC(xDisplay, bufGC);
7918 XFreeGC(xDisplay, maskGC);
7922 InitAnimState (anim, info)
7924 XWindowAttributes * info;
7929 /* Each buffer is square size, same depth as window */
7930 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
7931 squareSize, squareSize, info->depth);
7932 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
7933 squareSize, squareSize, info->depth);
7935 /* Create a plain GC for blitting */
7936 mask = GCForeground | GCBackground | GCFunction |
7937 GCPlaneMask | GCGraphicsExposures;
7938 values.foreground = XBlackPixel(xDisplay, xScreen);
7939 values.background = XWhitePixel(xDisplay, xScreen);
7940 values.function = GXcopy;
7941 values.plane_mask = AllPlanes;
7942 values.graphics_exposures = False;
7943 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
7945 /* Piece will be copied from an existing context at
7946 the start of each new animation/drag. */
7947 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
7949 /* Outline will be a read-only copy of an existing */
7950 anim->outlineGC = None;
7956 static int done = 0;
7957 XWindowAttributes info;
7961 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
7963 InitAnimState(&game, &info);
7964 InitAnimState(&player, &info);
7966 /* For XPM pieces, we need bitmaps to use as masks. */
7968 CreateAnimMasks(info.depth);
7973 static Boolean frameWaiting;
7975 static RETSIGTYPE FrameAlarm (sig)
7978 frameWaiting = False;
7979 /* In case System-V style signals. Needed?? */
7980 signal(SIGALRM, FrameAlarm);
7987 struct itimerval delay;
7989 XSync(xDisplay, False);
7992 frameWaiting = True;
7993 signal(SIGALRM, FrameAlarm);
7994 delay.it_interval.tv_sec =
7995 delay.it_value.tv_sec = time / 1000;
7996 delay.it_interval.tv_usec =
7997 delay.it_value.tv_usec = (time % 1000) * 1000;
7998 setitimer(ITIMER_REAL, &delay, NULL);
8000 /* Ugh -- busy-wait! --tpm */
8001 while (frameWaiting);
8003 while (frameWaiting) pause();
8005 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
8006 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
8007 setitimer(ITIMER_REAL, &delay, NULL);
8017 XSync(xDisplay, False);
8019 usleep(time * 1000);
8024 /* Convert board position to corner of screen rect and color */
8027 ScreenSquare(column, row, pt, color)
8028 int column; int row; XPoint * pt; int * color;
8031 pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
8032 pt->y = lineGap + row * (squareSize + lineGap);
8034 pt->x = lineGap + column * (squareSize + lineGap);
8035 pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
8037 *color = ((column + row) % 2) == 1;
8040 /* Convert window coords to square */
8043 BoardSquare(x, y, column, row)
8044 int x; int y; int * column; int * row;
8046 *column = EventToSquare(x, BOARD_SIZE);
8047 if (flipView && *column >= 0)
8048 *column = BOARD_SIZE - 1 - *column;
8049 *row = EventToSquare(y, BOARD_SIZE);
8050 if (!flipView && *row >= 0)
8051 *row = BOARD_SIZE - 1 - *row;
8056 #undef Max /* just in case */
8058 #define Max(a, b) ((a) > (b) ? (a) : (b))
8059 #define Min(a, b) ((a) < (b) ? (a) : (b))
8062 SetRect(rect, x, y, width, height)
8063 XRectangle * rect; int x; int y; int width; int height;
8067 rect->width = width;
8068 rect->height = height;
8071 /* Test if two frames overlap. If they do, return
8072 intersection rect within old and location of
8073 that rect within new. */
8076 Intersect(old, new, size, area, pt)
8077 XPoint * old; XPoint * new;
8078 int size; XRectangle * area; XPoint * pt;
8080 if (old->x > new->x + size || new->x > old->x + size ||
8081 old->y > new->y + size || new->y > old->y + size) {
8084 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
8085 size - abs(old->x - new->x), size - abs(old->y - new->y));
8086 pt->x = Max(old->x - new->x, 0);
8087 pt->y = Max(old->y - new->y, 0);
8092 /* For two overlapping frames, return the rect(s)
8093 in the old that do not intersect with the new. */
8096 CalcUpdateRects(old, new, size, update, nUpdates)
8097 XPoint * old; XPoint * new; int size;
8098 XRectangle update[]; int * nUpdates;
8102 /* If old = new (shouldn't happen) then nothing to draw */
8103 if (old->x == new->x && old->y == new->y) {
8107 /* Work out what bits overlap. Since we know the rects
8108 are the same size we don't need a full intersect calc. */
8110 /* Top or bottom edge? */
8111 if (new->y > old->y) {
8112 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
8114 } else if (old->y > new->y) {
8115 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
8116 size, old->y - new->y);
8119 /* Left or right edge - don't overlap any update calculated above. */
8120 if (new->x > old->x) {
8121 SetRect(&(update[count]), old->x, Max(new->y, old->y),
8122 new->x - old->x, size - abs(new->y - old->y));
8124 } else if (old->x > new->x) {
8125 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
8126 old->x - new->x, size - abs(new->y - old->y));
8133 /* Generate a series of frame coords from start->mid->finish.
8134 The movement rate doubles until the half way point is
8135 reached, then halves back down to the final destination,
8136 which gives a nice slow in/out effect. The algorithmn
8137 may seem to generate too many intermediates for short
8138 moves, but remember that the purpose is to attract the
8139 viewers attention to the piece about to be moved and
8140 then to where it ends up. Too few frames would be less
8144 Tween(start, mid, finish, factor, frames, nFrames)
8145 XPoint * start; XPoint * mid;
8146 XPoint * finish; int factor;
8147 XPoint frames[]; int * nFrames;
8149 int fraction, n, count;
8153 /* Slow in, stepping 1/16th, then 1/8th, ... */
8155 for (n = 0; n < factor; n++)
8157 for (n = 0; n < factor; n++) {
8158 frames[count].x = start->x + (mid->x - start->x) / fraction;
8159 frames[count].y = start->y + (mid->y - start->y) / fraction;
8161 fraction = fraction / 2;
8165 frames[count] = *mid;
8168 /* Slow out, stepping 1/2, then 1/4, ... */
8170 for (n = 0; n < factor; n++) {
8171 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
8172 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
8174 fraction = fraction * 2;
8179 /* Draw a piece on the screen without disturbing what's there */
8182 SelectGCMask(piece, clip, outline, mask)
8183 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
8187 /* Bitmap for piece being moved. */
8188 if (appData.monoMode) {
8189 *mask = *pieceToSolid(piece);
8190 } else if (useImages) {
8192 *mask = xpmMask[piece];
8194 *mask = ximMaskPm[piece%6];
8197 *mask = *pieceToSolid(piece);
8200 /* GC for piece being moved. Square color doesn't matter, but
8201 since it gets modified we make a copy of the original. */
8203 if (appData.monoMode)
8208 if (appData.monoMode)
8213 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
8215 /* Outline only used in mono mode and is not modified */
8217 *outline = bwPieceGC;
8219 *outline = wbPieceGC;
8223 OverlayPiece(piece, clip, outline, dest)
8224 ChessSquare piece; GC clip; GC outline; Drawable dest;
8229 /* Draw solid rectangle which will be clipped to shape of piece */
8230 XFillRectangle(xDisplay, dest, clip,
8231 0, 0, squareSize, squareSize);
8232 if (appData.monoMode)
8233 /* Also draw outline in contrasting color for black
8234 on black / white on white cases */
8235 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
8236 0, 0, squareSize, squareSize, 0, 0, 1);
8238 /* Copy the piece */
8243 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % 6],
8245 0, 0, squareSize, squareSize,
8250 /* Animate the movement of a single piece */
8253 BeginAnimation(anim, piece, startColor, start)
8261 /* The old buffer is initialised with the start square (empty) */
8262 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
8263 anim->prevFrame = *start;
8265 /* The piece will be drawn using its own bitmap as a matte */
8266 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
8267 XSetClipMask(xDisplay, anim->pieceGC, mask);
8271 AnimationFrame(anim, frame, piece)
8276 XRectangle updates[4];
8281 /* Save what we are about to draw into the new buffer */
8282 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
8283 frame->x, frame->y, squareSize, squareSize,
8286 /* Erase bits of the previous frame */
8287 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
8288 /* Where the new frame overlapped the previous,
8289 the contents in newBuf are wrong. */
8290 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
8291 overlap.x, overlap.y,
8292 overlap.width, overlap.height,
8294 /* Repaint the areas in the old that don't overlap new */
8295 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
8296 for (i = 0; i < count; i++)
8297 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8298 updates[i].x - anim->prevFrame.x,
8299 updates[i].y - anim->prevFrame.y,
8300 updates[i].width, updates[i].height,
8301 updates[i].x, updates[i].y);
8303 /* Easy when no overlap */
8304 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8305 0, 0, squareSize, squareSize,
8306 anim->prevFrame.x, anim->prevFrame.y);
8309 /* Save this frame for next time round */
8310 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
8311 0, 0, squareSize, squareSize,
8313 anim->prevFrame = *frame;
8315 /* Draw piece over original screen contents, not current,
8316 and copy entire rect. Wipes out overlapping piece images. */
8317 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
8318 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
8319 0, 0, squareSize, squareSize,
8320 frame->x, frame->y);
8324 EndAnimation (anim, finish)
8328 XRectangle updates[4];
8333 /* The main code will redraw the final square, so we
8334 only need to erase the bits that don't overlap. */
8335 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
8336 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
8337 for (i = 0; i < count; i++)
8338 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8339 updates[i].x - anim->prevFrame.x,
8340 updates[i].y - anim->prevFrame.y,
8341 updates[i].width, updates[i].height,
8342 updates[i].x, updates[i].y);
8344 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
8345 0, 0, squareSize, squareSize,
8346 anim->prevFrame.x, anim->prevFrame.y);
8351 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
8353 ChessSquare piece; int startColor;
8354 XPoint * start; XPoint * finish;
8355 XPoint frames[]; int nFrames;
8359 BeginAnimation(anim, piece, startColor, start);
8360 for (n = 0; n < nFrames; n++) {
8361 AnimationFrame(anim, &(frames[n]), piece);
8362 FrameDelay(appData.animSpeed);
8364 EndAnimation(anim, finish);
8367 /* Main control logic for deciding what to animate and how */
8370 AnimateMove(board, fromX, fromY, toX, toY)
8379 XPoint start, finish, mid;
8380 XPoint frames[kFactor * 2 + 1];
8381 int nFrames, startColor, endColor;
8383 /* Are we animating? */
8384 if (!appData.animate || appData.blindfold)
8387 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
8388 piece = board[fromY][fromX];
8389 if (piece >= EmptySquare) return;
8394 hop = (piece == WhiteKnight || piece == BlackKnight);
8397 if (appData.debugMode) {
8398 printf(hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") :
8399 _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"),
8400 piece, fromX, fromY, toX, toY);
8403 ScreenSquare(fromX, fromY, &start, &startColor);
8404 ScreenSquare(toX, toY, &finish, &endColor);
8407 /* Knight: make diagonal movement then straight */
8408 if (abs(toY - fromY) < abs(toX - fromX)) {
8409 mid.x = start.x + (finish.x - start.x) / 2;
8413 mid.y = start.y + (finish.y - start.y) / 2;
8416 mid.x = start.x + (finish.x - start.x) / 2;
8417 mid.y = start.y + (finish.y - start.y) / 2;
8420 /* Don't use as many frames for very short moves */
8421 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
8422 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
8424 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
8425 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
8427 /* Be sure end square is redrawn */
8428 damage[toY][toX] = True;
8432 DragPieceBegin(x, y)
8435 int boardX, boardY, color;
8438 /* Are we animating? */
8439 if (!appData.animateDragging || appData.blindfold)
8442 /* Figure out which square we start in and the
8443 mouse position relative to top left corner. */
8444 BoardSquare(x, y, &boardX, &boardY);
8445 player.startBoardX = boardX;
8446 player.startBoardY = boardY;
8447 ScreenSquare(boardX, boardY, &corner, &color);
8448 player.startSquare = corner;
8449 player.startColor = color;
8451 /* Start from exactly where the piece is. This can be confusing
8452 if you start dragging far from the center of the square; most
8453 or all of the piece can be over a different square from the one
8454 the mouse pointer is in. */
8455 player.mouseDelta.x = x - corner.x;
8456 player.mouseDelta.y = y - corner.y;
8458 /* As soon as we start dragging, the piece will jump slightly to
8459 be centered over the mouse pointer. */
8460 player.mouseDelta.x = squareSize/2;
8461 player.mouseDelta.y = squareSize/2;
8463 /* Initialise animation */
8464 player.dragPiece = PieceForSquare(boardX, boardY);
8466 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
8467 player.dragActive = True;
8468 BeginAnimation(&player, player.dragPiece, color, &corner);
8469 /* Mark this square as needing to be redrawn. Note that
8470 we don't remove the piece though, since logically (ie
8471 as seen by opponent) the move hasn't been made yet. */
8472 damage[boardY][boardX] = True;
8474 player.dragActive = False;
8484 /* Are we animating? */
8485 if (!appData.animateDragging || appData.blindfold)
8489 if (! player.dragActive)
8491 /* Move piece, maintaining same relative position
8492 of mouse within square */
8493 corner.x = x - player.mouseDelta.x;
8494 corner.y = y - player.mouseDelta.y;
8495 AnimationFrame(&player, &corner, player.dragPiece);
8497 if (appData.highlightDragging) {
8499 BoardSquare(x, y, &boardX, &boardY);
8500 SetHighlights(fromX, fromY, boardX, boardY);
8509 int boardX, boardY, color;
8512 /* Are we animating? */
8513 if (!appData.animateDragging || appData.blindfold)
8517 if (! player.dragActive)
8519 /* Last frame in sequence is square piece is
8520 placed on, which may not match mouse exactly. */
8521 BoardSquare(x, y, &boardX, &boardY);
8522 ScreenSquare(boardX, boardY, &corner, &color);
8523 EndAnimation(&player, &corner);
8525 /* Be sure end square is redrawn */
8526 damage[boardY][boardX] = True;
8528 /* This prevents weird things happening with fast successive
8529 clicks which on my Sun at least can cause motion events
8530 without corresponding press/release. */
8531 player.dragActive = False;
8534 /* Handle expose event while piece being dragged */
8539 if (!player.dragActive || appData.blindfold)
8542 /* What we're doing: logically, the move hasn't been made yet,
8543 so the piece is still in it's original square. But visually
8544 it's being dragged around the board. So we erase the square
8545 that the piece is on and draw it at the last known drag point. */
8546 BlankSquare(player.startSquare.x, player.startSquare.y,
8547 player.startColor, EmptySquare, xBoardWindow);
8548 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
8549 damage[player.startBoardY][player.startBoardX] = TRUE;