2 * xboard.c -- X front end for XBoard
\r
3 * $Id: xboard.c,v 2.2 2003/11/06 07:22:14 mann Exp $
\r
5 * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
\r
6 * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
\r
8 * The following terms apply to Digital Equipment Corporation's copyright
\r
9 * interest in XBoard:
\r
10 * ------------------------------------------------------------------------
\r
11 * All Rights Reserved
\r
13 * Permission to use, copy, modify, and distribute this software and its
\r
14 * documentation for any purpose and without fee is hereby granted,
\r
15 * provided that the above copyright notice appear in all copies and that
\r
16 * both that copyright notice and this permission notice appear in
\r
17 * supporting documentation, and that the name of Digital not be
\r
18 * used in advertising or publicity pertaining to distribution of the
\r
19 * software without specific, written prior permission.
\r
21 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
\r
22 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
\r
23 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
\r
24 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
\r
25 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
\r
26 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
\r
28 * ------------------------------------------------------------------------
\r
30 * The following terms apply to the enhanced version of XBoard distributed
\r
31 * by the Free Software Foundation:
\r
32 * ------------------------------------------------------------------------
\r
33 * This program is free software; you can redistribute it and/or modify
\r
34 * it under the terms of the GNU General Public License as published by
\r
35 * the Free Software Foundation; either version 2 of the License, or
\r
36 * (at your option) any later version.
\r
38 * This program is distributed in the hope that it will be useful,
\r
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
41 * GNU General Public License for more details.
\r
43 * You should have received a copy of the GNU General Public License
\r
44 * along with this program; if not, write to the Free Software
\r
45 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
46 * ------------------------------------------------------------------------
\r
48 * See the file ChangeLog for a revision history.
\r
57 #include <sys/types.h>
\r
58 #include <sys/stat.h>
\r
62 # if HAVE_SYS_SOCKET_H
\r
63 # include <sys/socket.h>
\r
64 # include <netinet/in.h>
\r
66 # else /* not HAVE_SYS_SOCKET_H */
\r
67 # if HAVE_LAN_SOCKET_H
\r
68 # include <lan/socket.h>
\r
69 # include <lan/in.h>
\r
70 # include <lan/netdb.h>
\r
71 # else /* not HAVE_LAN_SOCKET_H */
\r
72 # define OMIT_SOCKETS 1
\r
73 # endif /* not HAVE_LAN_SOCKET_H */
\r
74 # endif /* not HAVE_SYS_SOCKET_H */
\r
75 #endif /* !OMIT_SOCKETS */
\r
78 # include <stdlib.h>
\r
79 # include <string.h>
\r
80 #else /* not STDC_HEADERS */
\r
81 extern char *getenv();
\r
83 # include <string.h>
\r
84 # else /* not HAVE_STRING_H */
\r
85 # include <strings.h>
\r
86 # endif /* not HAVE_STRING_H */
\r
87 #endif /* not STDC_HEADERS */
\r
89 #if HAVE_SYS_FCNTL_H
\r
90 # include <sys/fcntl.h>
\r
91 #else /* not HAVE_SYS_FCNTL_H */
\r
94 # endif /* HAVE_FCNTL_H */
\r
95 #endif /* not HAVE_SYS_FCNTL_H */
\r
97 #if HAVE_SYS_SYSTEMINFO_H
\r
98 # include <sys/systeminfo.h>
\r
99 #endif /* HAVE_SYS_SYSTEMINFO_H */
\r
101 #if TIME_WITH_SYS_TIME
\r
102 # include <sys/time.h>
\r
105 # if HAVE_SYS_TIME_H
\r
106 # include <sys/time.h>
\r
113 # include <unistd.h>
\r
116 #if HAVE_SYS_WAIT_H
\r
117 # include <sys/wait.h>
\r
121 # include <dirent.h>
\r
122 # define NAMLEN(dirent) strlen((dirent)->d_name)
\r
123 # define HAVE_DIR_STRUCT
\r
125 # define dirent direct
\r
126 # define NAMLEN(dirent) (dirent)->d_namlen
\r
127 # if HAVE_SYS_NDIR_H
\r
128 # include <sys/ndir.h>
\r
129 # define HAVE_DIR_STRUCT
\r
131 # if HAVE_SYS_DIR_H
\r
132 # include <sys/dir.h>
\r
133 # define HAVE_DIR_STRUCT
\r
137 # define HAVE_DIR_STRUCT
\r
141 #include <X11/Intrinsic.h>
\r
142 #include <X11/StringDefs.h>
\r
143 #include <X11/Shell.h>
\r
144 #include <X11/cursorfont.h>
\r
145 #include <X11/Xatom.h>
\r
147 #include <X11/Xaw3d/Dialog.h>
\r
148 #include <X11/Xaw3d/Form.h>
\r
149 #include <X11/Xaw3d/List.h>
\r
150 #include <X11/Xaw3d/Label.h>
\r
151 #include <X11/Xaw3d/SimpleMenu.h>
\r
152 #include <X11/Xaw3d/SmeBSB.h>
\r
153 #include <X11/Xaw3d/SmeLine.h>
\r
154 #include <X11/Xaw3d/Box.h>
\r
155 #include <X11/Xaw3d/MenuButton.h>
\r
156 #include <X11/Xaw3d/Text.h>
\r
157 #include <X11/Xaw3d/AsciiText.h>
\r
159 #include <X11/Xaw/Dialog.h>
\r
160 #include <X11/Xaw/Form.h>
\r
161 #include <X11/Xaw/List.h>
\r
162 #include <X11/Xaw/Label.h>
\r
163 #include <X11/Xaw/SimpleMenu.h>
\r
164 #include <X11/Xaw/SmeBSB.h>
\r
165 #include <X11/Xaw/SmeLine.h>
\r
166 #include <X11/Xaw/Box.h>
\r
167 #include <X11/Xaw/MenuButton.h>
\r
168 #include <X11/Xaw/Text.h>
\r
169 #include <X11/Xaw/AsciiText.h>
\r
172 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
\r
173 #include "common.h"
\r
176 #include <X11/xpm.h>
\r
177 #include "pixmaps/pixmaps.h"
\r
178 #define IMAGE_EXT "xpm"
\r
180 #define IMAGE_EXT "xim"
\r
181 #include "bitmaps/bitmaps.h"
\r
184 #include "bitmaps/icon_white.bm"
\r
185 #include "bitmaps/icon_black.bm"
\r
186 #include "bitmaps/checkmark.bm"
\r
188 #include "frontend.h"
\r
189 #include "backend.h"
\r
191 #include "xboard.h"
\r
192 #include "childio.h"
\r
193 #include "xgamelist.h"
\r
194 #include "xhistory.h"
\r
195 #include "xedittags.h"
\r
198 #ifndef HAVE_USLEEP
\r
199 #define HAVE_USLEEP
\r
201 #define usleep(t) _sleep2(((t)+500)/1000)
\r
214 int main P((int argc, char **argv));
\r
215 RETSIGTYPE CmailSigHandler P((int sig));
\r
216 RETSIGTYPE IntSigHandler P((int sig));
\r
217 void CreateGCs P((void));
\r
218 void CreateXIMPieces P((void));
\r
219 void CreateXPMPieces P((void));
\r
220 void CreatePieces P((void));
\r
221 void CreatePieceMenus P((void));
\r
222 Widget CreateMenuBar P((Menu *mb));
\r
223 Widget CreateButtonBar P ((MenuItem *mi));
\r
224 char *FindFont P((char *pattern, int targetPxlSize));
\r
225 void PieceMenuPopup P((Widget w, XEvent *event,
\r
226 String *params, Cardinal *num_params));
\r
227 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
\r
228 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
\r
229 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
\r
230 u_int wreq, u_int hreq));
\r
231 void CreateGrid P((void));
\r
232 int EventToSquare P((int x, int limit));
\r
233 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
\r
234 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
\r
235 void HandleUserMove P((Widget w, XEvent *event,
\r
236 String *prms, Cardinal *nprms));
\r
237 void AnimateUserMove P((Widget w, XEvent * event,
\r
238 String * params, Cardinal * nParams));
\r
239 void WhiteClock P((Widget w, XEvent *event,
\r
240 String *prms, Cardinal *nprms));
\r
241 void BlackClock P((Widget w, XEvent *event,
\r
242 String *prms, Cardinal *nprms));
\r
243 void DrawPositionProc P((Widget w, XEvent *event,
\r
244 String *prms, Cardinal *nprms));
\r
245 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
\r
247 void CommentPopUp P((char *title, char *label));
\r
248 void CommentPopDown P((void));
\r
249 void CommentCallback P((Widget w, XtPointer client_data,
\r
250 XtPointer call_data));
\r
251 void ICSInputBoxPopUp P((void));
\r
252 void ICSInputBoxPopDown P((void));
\r
253 void FileNamePopUp P((char *label, char *def,
\r
254 FileProc proc, char *openMode));
\r
255 void FileNamePopDown P((void));
\r
256 void FileNameCallback P((Widget w, XtPointer client_data,
\r
257 XtPointer call_data));
\r
258 void FileNameAction P((Widget w, XEvent *event,
\r
259 String *prms, Cardinal *nprms));
\r
260 void AskQuestionReplyAction P((Widget w, XEvent *event,
\r
261 String *prms, Cardinal *nprms));
\r
262 void AskQuestionProc P((Widget w, XEvent *event,
\r
263 String *prms, Cardinal *nprms));
\r
264 void AskQuestionPopDown P((void));
\r
265 void PromotionPopUp P((void));
\r
266 void PromotionPopDown P((void));
\r
267 void PromotionCallback P((Widget w, XtPointer client_data,
\r
268 XtPointer call_data));
\r
269 void EditCommentPopDown P((void));
\r
270 void EditCommentCallback P((Widget w, XtPointer client_data,
\r
271 XtPointer call_data));
\r
272 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
\r
273 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
274 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
275 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
\r
277 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
\r
279 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
\r
281 void LoadPositionProc P((Widget w, XEvent *event,
\r
282 String *prms, Cardinal *nprms));
\r
283 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
\r
285 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
\r
287 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
\r
289 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
\r
291 void PastePositionProc P((Widget w, XEvent *event, String *prms,
\r
293 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
294 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
295 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
296 void SavePositionProc P((Widget w, XEvent *event,
\r
297 String *prms, Cardinal *nprms));
\r
298 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
299 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
\r
301 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
302 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
303 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
\r
305 void MachineWhiteProc P((Widget w, XEvent *event,
\r
306 String *prms, Cardinal *nprms));
\r
307 void AnalyzeModeProc P((Widget w, XEvent *event,
\r
308 String *prms, Cardinal *nprms));
\r
309 void AnalyzeFileProc P((Widget w, XEvent *event,
\r
310 String *prms, Cardinal *nprms));
\r
311 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
\r
313 void IcsClientProc P((Widget w, XEvent *event, String *prms,
\r
315 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
316 void EditPositionProc P((Widget w, XEvent *event,
\r
317 String *prms, Cardinal *nprms));
\r
318 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
319 void EditCommentProc P((Widget w, XEvent *event,
\r
320 String *prms, Cardinal *nprms));
\r
321 void IcsInputBoxProc P((Widget w, XEvent *event,
\r
322 String *prms, Cardinal *nprms));
\r
323 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
324 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
325 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
326 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
327 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
328 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
329 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
330 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
331 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
332 void StopObservingProc P((Widget w, XEvent *event, String *prms,
\r
334 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
\r
336 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
337 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
338 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
339 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
340 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
341 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
\r
343 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
\r
345 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
346 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
\r
348 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
\r
350 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
\r
352 void AutocommProc P((Widget w, XEvent *event, String *prms,
\r
354 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
355 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
356 void AutobsProc P((Widget w, XEvent *event, String *prms,
\r
358 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
359 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
360 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
361 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
\r
363 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
364 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
\r
366 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
\r
368 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
\r
370 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
371 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
372 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
\r
374 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
\r
376 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
\r
378 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
\r
380 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
\r
382 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
383 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
384 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
\r
386 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
\r
388 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
\r
390 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
391 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
392 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
393 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
394 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
395 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
396 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
397 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
398 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
399 void DisplayMove P((int moveNumber));
\r
400 void DisplayTitle P((char *title));
\r
401 void ICSInitScript P((void));
\r
402 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
\r
403 void ErrorPopUp P((char *title, char *text, int modal));
\r
404 void ErrorPopDown P((void));
\r
405 static char *ExpandPathName P((char *path));
\r
406 static void CreateAnimVars P((void));
\r
407 static void DragPieceBegin P((int x, int y));
\r
408 static void DragPieceMove P((int x, int y));
\r
409 static void DragPieceEnd P((int x, int y));
\r
410 static void DrawDragPiece P((void));
\r
411 char *ModeToWidgetName P((GameMode mode));
\r
414 * XBoard depends on Xt R4 or higher
\r
416 int xtVersion = XtSpecificationRelease;
\r
420 Window xBoardWindow;
\r
421 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
\r
422 jailSquareColor, highlightSquareColor, premoveHighlightColor;
\r
423 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
\r
424 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
\r
425 wjPieceGC, bjPieceGC, prelineGC;
\r
426 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
\r
427 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
\r
428 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
\r
429 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
\r
430 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
\r
431 ICSInputShell, fileNameShell, askQuestionShell;
\r
432 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
\r
433 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
\r
434 Font clockFontID, coordFontID;
\r
435 XFontStruct *clockFontStruct, *coordFontStruct;
\r
436 XtAppContext appContext;
\r
438 char *oldICSInteractionTitle;
\r
441 char *fileOpenMode;
\r
443 Position commentX = -1, commentY = -1;
\r
444 Dimension commentW, commentH;
\r
446 int squareSize, smallLayout = 0, tinyLayout = 0,
\r
447 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
\r
448 ICSInputBoxUp = False, askQuestionUp = False,
\r
449 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
\r
450 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
\r
451 Pixel timerForegroundPixel, timerBackgroundPixel;
\r
452 Pixel buttonForegroundPixel, buttonBackgroundPixel;
\r
453 char *chessDir, *programName, *programVersion,
\r
454 *gameCopyFilename, *gamePasteFilename;
\r
458 Pixmap pieceBitmap[2][(int)BlackPawn];
\r
459 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
\r
460 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
\r
461 int useImages, useImageSqs;
\r
462 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
\r
463 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
\r
464 XImage *ximLightSquare, *ximDarkSquare;
\r
467 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
\r
468 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
\r
470 #define White(piece) ((int)(piece) < (int)BlackPawn)
\r
472 /* Variables for doing smooth animation. This whole thing
\r
473 would be much easier if the board was double-buffered,
\r
474 but that would require a fairly major rewrite. */
\r
479 GC blitGC, pieceGC, outlineGC;
\r
480 XPoint startSquare, prevFrame, mouseDelta;
\r
483 Boolean dragActive;
\r
484 int startBoardX, startBoardY;
\r
487 /* There can be two pieces being animated at once: a player
\r
488 can begin dragging a piece before the remote opponent has moved. */
\r
490 static AnimState game, player;
\r
492 /* Bitmaps for use as masks when drawing XPM pieces.
\r
493 Need one for each black and white piece. */
\r
494 static Pixmap xpmMask[BlackKing + 1];
\r
496 /* This magic number is the number of intermediate frames used
\r
497 in each half of the animation. For short moves it's reduced
\r
498 by 1. The total number of frames will be factor * 2 + 1. */
\r
501 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
\r
503 MenuItem fileMenu[] = {
\r
504 {"Reset Game", ResetProc},
\r
505 {"----", NothingProc},
\r
506 {"Load Game", LoadGameProc},
\r
507 {"Load Next Game", LoadNextGameProc},
\r
508 {"Load Previous Game", LoadPrevGameProc},
\r
509 {"Reload Same Game", ReloadGameProc},
\r
510 {"Save Game", SaveGameProc},
\r
511 {"----", NothingProc},
\r
512 {"Copy Game", CopyGameProc},
\r
513 {"Paste Game", PasteGameProc},
\r
514 {"----", NothingProc},
\r
515 {"Load Position", LoadPositionProc},
\r
516 {"Load Next Position", LoadNextPositionProc},
\r
517 {"Load Previous Position", LoadPrevPositionProc},
\r
518 {"Reload Same Position", ReloadPositionProc},
\r
519 {"Save Position", SavePositionProc},
\r
520 {"----", NothingProc},
\r
521 {"Copy Position", CopyPositionProc},
\r
522 {"Paste Position", PastePositionProc},
\r
523 {"----", NothingProc},
\r
524 {"Mail Move", MailMoveProc},
\r
525 {"Reload CMail Message", ReloadCmailMsgProc},
\r
526 {"----", NothingProc},
\r
527 {"Exit", QuitProc},
\r
531 MenuItem modeMenu[] = {
\r
532 {"Machine White", MachineWhiteProc},
\r
533 {"Machine Black", MachineBlackProc},
\r
534 {"Two Machines", TwoMachinesProc},
\r
535 {"Analysis Mode", AnalyzeModeProc},
\r
536 {"Analyze File", AnalyzeFileProc },
\r
537 {"ICS Client", IcsClientProc},
\r
538 {"Edit Game", EditGameProc},
\r
539 {"Edit Position", EditPositionProc},
\r
540 {"Training", TrainingProc},
\r
541 {"----", NothingProc},
\r
542 {"Show Game List", ShowGameListProc},
\r
543 {"Show Move List", HistoryShowProc},
\r
544 {"Edit Tags", EditTagsProc},
\r
545 {"Edit Comment", EditCommentProc},
\r
546 {"ICS Input Box", IcsInputBoxProc},
\r
547 {"Pause", PauseProc},
\r
551 MenuItem actionMenu[] = {
\r
552 {"Accept", AcceptProc},
\r
553 {"Decline", DeclineProc},
\r
554 {"Rematch", RematchProc},
\r
555 {"----", NothingProc},
\r
556 {"Call Flag", CallFlagProc},
\r
557 {"Draw", DrawProc},
\r
558 {"Adjourn", AdjournProc},
\r
559 {"Abort", AbortProc},
\r
560 {"Resign", ResignProc},
\r
561 {"----", NothingProc},
\r
562 {"Stop Observing", StopObservingProc},
\r
563 {"Stop Examining", StopExaminingProc},
\r
567 MenuItem stepMenu[] = {
\r
568 {"Backward", BackwardProc},
\r
569 {"Forward", ForwardProc},
\r
570 {"Back to Start", ToStartProc},
\r
571 {"Forward to End", ToEndProc},
\r
572 {"Revert", RevertProc},
\r
573 {"Truncate Game", TruncateGameProc},
\r
574 {"----", NothingProc},
\r
575 {"Move Now", MoveNowProc},
\r
576 {"Retract Move", RetractMoveProc},
\r
580 MenuItem optionsMenu[] = {
\r
581 {"Always Queen", AlwaysQueenProc},
\r
582 {"Animate Dragging", AnimateDraggingProc},
\r
583 {"Animate Moving", AnimateMovingProc},
\r
584 {"Auto Comment", AutocommProc},
\r
585 {"Auto Flag", AutoflagProc},
\r
586 {"Auto Flip View", AutoflipProc},
\r
587 {"Auto Observe", AutobsProc},
\r
588 {"Auto Raise Board", AutoraiseProc},
\r
589 {"Auto Save", AutosaveProc},
\r
590 {"Blindfold", BlindfoldProc},
\r
591 {"Flash Moves", FlashMovesProc},
\r
592 {"Flip View", FlipViewProc},
\r
593 {"Get Move List", GetMoveListProc},
\r
595 {"Highlight Dragging", HighlightDraggingProc},
\r
597 {"Highlight Last Move", HighlightLastMoveProc},
\r
598 {"Move Sound", MoveSoundProc},
\r
599 {"ICS Alarm", IcsAlarmProc},
\r
600 {"Old Save Style", OldSaveStyleProc},
\r
601 {"Periodic Updates", PeriodicUpdatesProc},
\r
602 {"Ponder Next Move", PonderNextMoveProc},
\r
603 {"Popup Exit Message", PopupExitMessageProc},
\r
604 {"Popup Move Errors", PopupMoveErrorsProc},
\r
605 {"Premove", PremoveProc},
\r
606 {"Quiet Play", QuietPlayProc},
\r
607 {"Show Coords", ShowCoordsProc},
\r
608 {"Show Thinking", ShowThinkingProc},
\r
609 {"Test Legality", TestLegalityProc},
\r
613 MenuItem helpMenu[] = {
\r
614 {"Info XBoard", InfoProc},
\r
615 {"Man XBoard", ManProc},
\r
616 {"----", NothingProc},
\r
617 {"Hint", HintProc},
\r
618 {"Book", BookProc},
\r
619 {"----", NothingProc},
\r
620 {"About XBoard", AboutProc},
\r
625 {"File", fileMenu},
\r
626 {"Mode", modeMenu},
\r
627 {"Action", actionMenu},
\r
628 {"Step", stepMenu},
\r
629 {"Options", optionsMenu},
\r
630 {"Help", helpMenu},
\r
634 #define PAUSE_BUTTON "P"
\r
635 MenuItem buttonBar[] = {
\r
636 {"<<", ToStartProc},
\r
637 {"<", BackwardProc},
\r
638 {PAUSE_BUTTON, PauseProc},
\r
639 {">", ForwardProc},
\r
644 #define PIECE_MENU_SIZE 11
\r
645 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
\r
646 { "White", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
\r
647 "----", "Empty square", "Clear board" },
\r
648 { "Black", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
\r
649 "----", "Empty square", "Clear board" },
\r
651 /* must be in same order as PieceMenuStrings! */
\r
652 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
\r
653 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
\r
654 WhiteRook, WhiteQueen, WhiteKing,
\r
655 (ChessSquare) 0, EmptySquare, ClearBoard },
\r
656 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
\r
657 BlackRook, BlackQueen, BlackKing,
\r
658 (ChessSquare) 0, EmptySquare, ClearBoard },
\r
661 #define DROP_MENU_SIZE 6
\r
662 String dropMenuStrings[DROP_MENU_SIZE] = {
\r
663 "----", "Pawn", "Knight", "Bishop", "Rook", "Queen"
\r
665 /* must be in same order as PieceMenuStrings! */
\r
666 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
\r
667 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
\r
668 WhiteRook, WhiteQueen
\r
676 DropMenuEnables dmEnables[] = {
\r
684 Arg shellArgs[] = {
\r
687 { XtNminWidth, 0 },
\r
688 { XtNminHeight, 0 },
\r
689 { XtNmaxWidth, 0 },
\r
690 { XtNmaxHeight, 0 }
\r
693 Arg layoutArgs[] = {
\r
694 { XtNborderWidth, 0 },
\r
695 { XtNdefaultDistance, 0 },
\r
699 { XtNborderWidth, 0 },
\r
700 { XtNresizable, (XtArgVal) True },
\r
703 Arg boardArgs[] = {
\r
704 { XtNborderWidth, 0 },
\r
709 Arg titleArgs[] = {
\r
710 { XtNjustify, (XtArgVal) XtJustifyRight },
\r
711 { XtNlabel, (XtArgVal) "..." },
\r
712 { XtNresizable, (XtArgVal) True },
\r
713 { XtNresize, (XtArgVal) False }
\r
716 Arg messageArgs[] = {
\r
717 { XtNjustify, (XtArgVal) XtJustifyLeft },
\r
718 { XtNlabel, (XtArgVal) "..." },
\r
719 { XtNresizable, (XtArgVal) True },
\r
720 { XtNresize, (XtArgVal) False }
\r
723 Arg timerArgs[] = {
\r
724 { XtNborderWidth, 0 },
\r
725 { XtNjustify, (XtArgVal) XtJustifyLeft }
\r
728 XtResource clientResources[] = {
\r
729 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
\r
730 XtOffset(AppDataPtr, whitePieceColor), XtRString,
\r
731 WHITE_PIECE_COLOR },
\r
732 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
\r
733 XtOffset(AppDataPtr, blackPieceColor), XtRString,
\r
734 BLACK_PIECE_COLOR },
\r
735 { "lightSquareColor", "lightSquareColor", XtRString,
\r
736 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
\r
737 XtRString, LIGHT_SQUARE_COLOR },
\r
738 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
\r
739 XtOffset(AppDataPtr, darkSquareColor), XtRString,
\r
740 DARK_SQUARE_COLOR },
\r
741 { "highlightSquareColor", "highlightSquareColor", XtRString,
\r
742 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
\r
743 XtRString, HIGHLIGHT_SQUARE_COLOR },
\r
744 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
\r
745 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
\r
746 XtRString, PREMOVE_HIGHLIGHT_COLOR },
\r
747 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
\r
748 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
\r
749 (XtPointer) MOVES_PER_SESSION },
\r
750 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
\r
751 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
\r
752 (XtPointer) TIME_INCREMENT },
\r
753 { "initString", "initString", XtRString, sizeof(String),
\r
754 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
\r
755 { "secondInitString", "secondInitString", XtRString, sizeof(String),
\r
756 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
\r
757 { "firstComputerString", "firstComputerString", XtRString,
\r
758 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
\r
760 { "secondComputerString", "secondComputerString", XtRString,
\r
761 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
\r
763 { "firstChessProgram", "firstChessProgram", XtRString,
\r
764 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
\r
765 XtRString, FIRST_CHESS_PROGRAM },
\r
766 { "secondChessProgram", "secondChessProgram", XtRString,
\r
767 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
\r
768 XtRString, SECOND_CHESS_PROGRAM },
\r
769 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
\r
770 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
\r
771 XtRImmediate, (XtPointer) False },
\r
772 { "noChessProgram", "noChessProgram", XtRBoolean,
\r
773 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
\r
774 XtRImmediate, (XtPointer) False },
\r
775 { "firstHost", "firstHost", XtRString, sizeof(String),
\r
776 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
\r
777 { "secondHost", "secondHost", XtRString, sizeof(String),
\r
778 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
\r
779 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
\r
780 XtOffset(AppDataPtr, firstDirectory), XtRString, FIRST_DIRECTORY },
\r
781 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
\r
782 XtOffset(AppDataPtr, secondDirectory), XtRString, SECOND_DIRECTORY },
\r
783 { "bitmapDirectory", "bitmapDirectory", XtRString,
\r
784 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
\r
786 { "remoteShell", "remoteShell", XtRString, sizeof(String),
\r
787 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
\r
788 { "remoteUser", "remoteUser", XtRString, sizeof(String),
\r
789 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
\r
790 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
\r
791 XtOffset(AppDataPtr, timeDelay), XtRString,
\r
792 (XtPointer) TIME_DELAY_QUOTE },
\r
793 { "timeControl", "timeControl", XtRString, sizeof(String),
\r
794 XtOffset(AppDataPtr, timeControl), XtRString,
\r
795 (XtPointer) TIME_CONTROL },
\r
796 { "internetChessServerMode", "internetChessServerMode",
\r
797 XtRBoolean, sizeof(Boolean),
\r
798 XtOffset(AppDataPtr, icsActive), XtRImmediate,
\r
799 (XtPointer) False },
\r
800 { "internetChessServerHost", "internetChessServerHost",
\r
801 XtRString, sizeof(String),
\r
802 XtOffset(AppDataPtr, icsHost),
\r
803 XtRString, (XtPointer) ICS_HOST },
\r
804 { "internetChessServerPort", "internetChessServerPort",
\r
805 XtRString, sizeof(String),
\r
806 XtOffset(AppDataPtr, icsPort), XtRString,
\r
807 (XtPointer) ICS_PORT },
\r
808 { "internetChessServerCommPort", "internetChessServerCommPort",
\r
809 XtRString, sizeof(String),
\r
810 XtOffset(AppDataPtr, icsCommPort), XtRString,
\r
812 { "internetChessServerLogonScript", "internetChessServerLogonScript",
\r
813 XtRString, sizeof(String),
\r
814 XtOffset(AppDataPtr, icsLogon), XtRString,
\r
816 { "internetChessServerHelper", "internetChessServerHelper",
\r
817 XtRString, sizeof(String),
\r
818 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
\r
819 { "internetChessServerInputBox", "internetChessServerInputBox",
\r
820 XtRBoolean, sizeof(Boolean),
\r
821 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
\r
822 (XtPointer) False },
\r
823 { "icsAlarm", "icsAlarm",
\r
824 XtRBoolean, sizeof(Boolean),
\r
825 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
\r
826 (XtPointer) True },
\r
827 { "icsAlarmTime", "icsAlarmTime",
\r
828 XtRInt, sizeof(int),
\r
829 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
\r
830 (XtPointer) 5000 },
\r
831 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
\r
832 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
\r
833 (XtPointer) False },
\r
834 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
\r
835 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
\r
836 { "gateway", "gateway", XtRString, sizeof(String),
\r
837 XtOffset(AppDataPtr, gateway), XtRString, "" },
\r
838 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
\r
839 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
\r
840 { "loadGameIndex", "loadGameIndex",
\r
841 XtRInt, sizeof(int),
\r
842 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
\r
844 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
\r
845 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
\r
846 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
\r
847 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
\r
848 XtRImmediate, (XtPointer) True },
\r
849 { "autoSaveGames", "autoSaveGames", XtRBoolean,
\r
850 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
\r
851 XtRImmediate, (XtPointer) False },
\r
852 { "blindfold", "blindfold", XtRBoolean,
\r
853 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
\r
854 XtRImmediate, (XtPointer) False },
\r
855 { "loadPositionFile", "loadPositionFile", XtRString,
\r
856 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
\r
858 { "loadPositionIndex", "loadPositionIndex",
\r
859 XtRInt, sizeof(int),
\r
860 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
\r
862 { "savePositionFile", "savePositionFile", XtRString,
\r
863 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
\r
865 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
\r
866 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
\r
867 { "matchGames", "matchGames", XtRInt, sizeof(int),
\r
868 XtOffset(AppDataPtr, matchGames), XtRImmediate,
\r
870 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
\r
871 XtOffset(AppDataPtr, monoMode), XtRImmediate,
\r
872 (XtPointer) False },
\r
873 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
\r
874 XtOffset(AppDataPtr, debugMode), XtRImmediate,
\r
875 (XtPointer) False },
\r
876 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
\r
877 XtOffset(AppDataPtr, clockMode), XtRImmediate,
\r
878 (XtPointer) True },
\r
879 { "boardSize", "boardSize", XtRString, sizeof(String),
\r
880 XtOffset(AppDataPtr, boardSize), XtRString, "" },
\r
881 { "searchTime", "searchTime", XtRString, sizeof(String),
\r
882 XtOffset(AppDataPtr, searchTime), XtRString,
\r
884 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
\r
885 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
\r
887 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
\r
888 XtOffset(AppDataPtr, showCoords), XtRImmediate,
\r
889 (XtPointer) False },
\r
890 { "showJail", "showJail", XtRInt, sizeof(int),
\r
891 XtOffset(AppDataPtr, showJail), XtRImmediate,
\r
893 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
\r
894 XtOffset(AppDataPtr, showThinking), XtRImmediate,
\r
895 (XtPointer) False },
\r
896 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
\r
897 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
\r
898 (XtPointer) True },
\r
899 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
\r
900 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
\r
901 (XtPointer) True },
\r
902 { "clockFont", "clockFont", XtRString, sizeof(String),
\r
903 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
\r
904 { "coordFont", "coordFont", XtRString, sizeof(String),
\r
905 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
\r
906 { "font", "font", XtRString, sizeof(String),
\r
907 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
\r
908 { "ringBellAfterMoves", "ringBellAfterMoves",
\r
909 XtRBoolean, sizeof(Boolean),
\r
910 XtOffset(AppDataPtr, ringBellAfterMoves),
\r
911 XtRImmediate, (XtPointer) False },
\r
912 { "autoCallFlag", "autoCallFlag", XtRBoolean,
\r
913 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
\r
914 XtRImmediate, (XtPointer) False },
\r
915 { "autoFlipView", "autoFlipView", XtRBoolean,
\r
916 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
\r
917 XtRImmediate, (XtPointer) True },
\r
918 { "autoObserve", "autoObserve", XtRBoolean,
\r
919 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
\r
920 XtRImmediate, (XtPointer) False },
\r
921 { "autoComment", "autoComment", XtRBoolean,
\r
922 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
\r
923 XtRImmediate, (XtPointer) False },
\r
924 { "getMoveList", "getMoveList", XtRBoolean,
\r
925 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
\r
926 XtRImmediate, (XtPointer) True },
\r
928 { "highlightDragging", "highlightDragging", XtRBoolean,
\r
929 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
\r
930 XtRImmediate, (XtPointer) False },
\r
932 { "highlightLastMove", "highlightLastMove", XtRBoolean,
\r
933 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
\r
934 XtRImmediate, (XtPointer) False },
\r
935 { "premove", "premove", XtRBoolean,
\r
936 sizeof(Boolean), XtOffset(AppDataPtr, premove),
\r
937 XtRImmediate, (XtPointer) True },
\r
938 { "testLegality", "testLegality", XtRBoolean,
\r
939 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
\r
940 XtRImmediate, (XtPointer) True },
\r
941 { "flipView", "flipView", XtRBoolean,
\r
942 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
\r
943 XtRImmediate, (XtPointer) False },
\r
944 { "cmail", "cmailGameName", XtRString, sizeof(String),
\r
945 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
\r
946 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
\r
947 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
\r
948 XtRImmediate, (XtPointer) False },
\r
949 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
\r
950 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
\r
951 XtRImmediate, (XtPointer) False },
\r
952 { "quietPlay", "quietPlay", XtRBoolean,
\r
953 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
\r
954 XtRImmediate, (XtPointer) False },
\r
955 { "titleInWindow", "titleInWindow", XtRBoolean,
\r
956 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
\r
957 XtRImmediate, (XtPointer) False },
\r
958 { "localLineEditing", "localLineEditing", XtRBoolean,
\r
959 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
\r
960 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
\r
962 { "zippyTalk", "zippyTalk", XtRBoolean,
\r
963 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
\r
964 XtRImmediate, (XtPointer) ZIPPY_TALK },
\r
965 { "zippyPlay", "zippyPlay", XtRBoolean,
\r
966 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
\r
967 XtRImmediate, (XtPointer) ZIPPY_PLAY },
\r
968 { "zippyLines", "zippyLines", XtRString, sizeof(String),
\r
969 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
\r
970 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
\r
971 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
\r
972 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
\r
973 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
\r
974 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
\r
975 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
\r
976 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
\r
977 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
\r
978 ZIPPY_WRONG_PASSWORD },
\r
979 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
\r
980 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
\r
981 { "zippyUseI", "zippyUseI", XtRBoolean,
\r
982 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
\r
983 XtRImmediate, (XtPointer) ZIPPY_USE_I },
\r
984 { "zippyBughouse", "zippyBughouse", XtRInt,
\r
985 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
\r
986 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
\r
987 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
\r
988 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
\r
989 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
\r
990 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
\r
991 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
\r
992 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
\r
993 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
\r
994 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
\r
995 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
\r
996 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
\r
997 { "zippyAbort", "zippyAbort", XtRBoolean,
\r
998 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
\r
999 XtRImmediate, (XtPointer) ZIPPY_ABORT },
\r
1000 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
\r
1001 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
\r
1002 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
\r
1003 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
\r
1004 (XtPointer) ZIPPY_MAX_GAMES },
\r
1005 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
\r
1006 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
\r
1007 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
\r
1009 { "flashCount", "flashCount", XtRInt, sizeof(int),
\r
1010 XtOffset(AppDataPtr, flashCount), XtRImmediate,
\r
1011 (XtPointer) FLASH_COUNT },
\r
1012 { "flashRate", "flashRate", XtRInt, sizeof(int),
\r
1013 XtOffset(AppDataPtr, flashRate), XtRImmediate,
\r
1014 (XtPointer) FLASH_RATE },
\r
1015 { "pixmapDirectory", "pixmapDirectory", XtRString,
\r
1016 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
\r
1018 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
\r
1019 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
\r
1020 (XtPointer) MS_LOGIN_DELAY },
\r
1021 { "colorizeMessages", "colorizeMessages", XtRBoolean,
\r
1022 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
\r
1023 XtRImmediate, (XtPointer) False },
\r
1024 { "colorShout", "colorShout", XtRString,
\r
1025 sizeof(String), XtOffset(AppDataPtr, colorShout),
\r
1026 XtRString, COLOR_SHOUT },
\r
1027 { "colorSShout", "colorSShout", XtRString,
\r
1028 sizeof(String), XtOffset(AppDataPtr, colorSShout),
\r
1029 XtRString, COLOR_SSHOUT },
\r
1030 { "colorChannel1", "colorChannel1", XtRString,
\r
1031 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
\r
1032 XtRString, COLOR_CHANNEL1 },
\r
1033 { "colorChannel", "colorChannel", XtRString,
\r
1034 sizeof(String), XtOffset(AppDataPtr, colorChannel),
\r
1035 XtRString, COLOR_CHANNEL },
\r
1036 { "colorKibitz", "colorKibitz", XtRString,
\r
1037 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
\r
1038 XtRString, COLOR_KIBITZ },
\r
1039 { "colorTell", "colorTell", XtRString,
\r
1040 sizeof(String), XtOffset(AppDataPtr, colorTell),
\r
1041 XtRString, COLOR_TELL },
\r
1042 { "colorChallenge", "colorChallenge", XtRString,
\r
1043 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
\r
1044 XtRString, COLOR_CHALLENGE },
\r
1045 { "colorRequest", "colorRequest", XtRString,
\r
1046 sizeof(String), XtOffset(AppDataPtr, colorRequest),
\r
1047 XtRString, COLOR_REQUEST },
\r
1048 { "colorSeek", "colorSeek", XtRString,
\r
1049 sizeof(String), XtOffset(AppDataPtr, colorSeek),
\r
1050 XtRString, COLOR_SEEK },
\r
1051 { "colorNormal", "colorNormal", XtRString,
\r
1052 sizeof(String), XtOffset(AppDataPtr, colorNormal),
\r
1053 XtRString, COLOR_NORMAL },
\r
1054 { "soundProgram", "soundProgram", XtRString,
\r
1055 sizeof(String), XtOffset(AppDataPtr, soundProgram),
\r
1056 XtRString, "play" },
\r
1057 { "soundShout", "soundShout", XtRString,
\r
1058 sizeof(String), XtOffset(AppDataPtr, soundShout),
\r
1060 { "soundSShout", "soundSShout", XtRString,
\r
1061 sizeof(String), XtOffset(AppDataPtr, soundSShout),
\r
1063 { "soundChannel1", "soundChannel1", XtRString,
\r
1064 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
\r
1066 { "soundChannel", "soundChannel", XtRString,
\r
1067 sizeof(String), XtOffset(AppDataPtr, soundChannel),
\r
1069 { "soundKibitz", "soundKibitz", XtRString,
\r
1070 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
\r
1072 { "soundTell", "soundTell", XtRString,
\r
1073 sizeof(String), XtOffset(AppDataPtr, soundTell),
\r
1075 { "soundChallenge", "soundChallenge", XtRString,
\r
1076 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
\r
1078 { "soundRequest", "soundRequest", XtRString,
\r
1079 sizeof(String), XtOffset(AppDataPtr, soundRequest),
\r
1081 { "soundSeek", "soundSeek", XtRString,
\r
1082 sizeof(String), XtOffset(AppDataPtr, soundSeek),
\r
1084 { "soundMove", "soundMove", XtRString,
\r
1085 sizeof(String), XtOffset(AppDataPtr, soundMove),
\r
1087 { "soundIcsWin", "soundIcsWin", XtRString,
\r
1088 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
\r
1090 { "soundIcsLoss", "soundIcsLoss", XtRString,
\r
1091 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
\r
1093 { "soundIcsDraw", "soundIcsDraw", XtRString,
\r
1094 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
\r
1096 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
\r
1097 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
\r
1099 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
\r
1100 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
\r
1102 { "reuseFirst", "reuseFirst", XtRBoolean,
\r
1103 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
\r
1104 XtRImmediate, (XtPointer) True },
\r
1105 { "reuseSecond", "reuseSecond", XtRBoolean,
\r
1106 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
\r
1107 XtRImmediate, (XtPointer) True },
\r
1108 { "animateDragging", "animateDragging", XtRBoolean,
\r
1109 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
\r
1110 XtRImmediate, (XtPointer) True },
\r
1111 { "animateMoving", "animateMoving", XtRBoolean,
\r
1112 sizeof(Boolean), XtOffset(AppDataPtr, animate),
\r
1113 XtRImmediate, (XtPointer) True },
\r
1114 { "animateSpeed", "animateSpeed", XtRInt,
\r
1115 sizeof(int), XtOffset(AppDataPtr, animSpeed),
\r
1116 XtRImmediate, (XtPointer)10 },
\r
1117 { "popupExitMessage", "popupExitMessage", XtRBoolean,
\r
1118 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
\r
1119 XtRImmediate, (XtPointer) True },
\r
1120 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
\r
1121 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
\r
1122 XtRImmediate, (XtPointer) False },
\r
1123 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
\r
1124 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
\r
1125 XtRImmediate, (XtPointer)4 },
\r
1126 { "initialMode", "initialMode", XtRString,
\r
1127 sizeof(String), XtOffset(AppDataPtr, initialMode),
\r
1128 XtRImmediate, (XtPointer) "" },
\r
1129 { "variant", "variant", XtRString,
\r
1130 sizeof(String), XtOffset(AppDataPtr, variant),
\r
1131 XtRImmediate, (XtPointer) "normal" },
\r
1132 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
\r
1133 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
\r
1134 XtRImmediate, (XtPointer)PROTOVER },
\r
1135 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
\r
1136 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
\r
1137 XtRImmediate, (XtPointer)PROTOVER },
\r
1138 { "showButtonBar", "showButtonBar", XtRBoolean,
\r
1139 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
\r
1140 XtRImmediate, (XtPointer) True },
\r
1141 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
\r
1142 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
\r
1143 XtRImmediate, (XtPointer) False },
\r
1144 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
\r
1145 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
\r
1146 XtRImmediate, (XtPointer) False },
\r
1147 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
\r
1148 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
\r
1149 XtRImmediate, (XtPointer) False },
\r
1150 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
\r
1151 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
\r
1152 XtRImmediate, (XtPointer) False },
\r
1153 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
\r
1154 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
\r
1155 XtRImmediate, (XtPointer) 0},
\r
1156 { "pgnEventHeader", "pgnEventHeader", XtRString,
\r
1157 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
\r
1158 XtRImmediate, (XtPointer) "Computer Chess Game" },
\r
1159 { "defaultFrcPosition", "defaultFrcPosition", XtRInt,
\r
1160 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
\r
1161 XtRImmediate, (XtPointer) -1 },
\r
1163 // [HGM] 4.3.xx options
\r
1164 { "boardWidth", "boardWidth", XtRInt,
\r
1165 sizeof(int), XtOffset(AppDataPtr, NrFiles),
\r
1166 XtRImmediate, (XtPointer) -1},
\r
1167 { "boardHeight", "boardHeight", XtRInt,
\r
1168 sizeof(int), XtOffset(AppDataPtr, NrRanks),
\r
1169 XtRImmediate, (XtPointer) -1},
\r
1170 { "matchPause", "matchPause", XtRInt,
\r
1171 sizeof(int), XtOffset(AppDataPtr, matchPause),
\r
1172 XtRImmediate, (XtPointer) 10000},
\r
1173 { "holdingsSize", "holdingsSize", XtRInt,
\r
1174 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
\r
1175 XtRImmediate, (XtPointer) -1},
\r
1176 { "flipBlack", "flipBlack", XtRBoolean,
\r
1177 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
\r
1178 XtRImmediate, (XtPointer) False},
\r
1179 { "allWhite", "allWhite", XtRBoolean,
\r
1180 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
\r
1181 XtRImmediate, (XtPointer) False},
\r
1182 { "pieceToCharTable", "pieceToCharTable", XtRString,
\r
1183 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
\r
1184 XtRImmediate, (XtPointer) 0},
\r
1185 { "alphaRank", "alphaRank", XtRBoolean,
\r
1186 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
\r
1187 XtRImmediate, (XtPointer) False},
\r
1188 { "testClaims", "testClaims", XtRBoolean,
\r
1189 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
\r
1190 XtRImmediate, (XtPointer) False},
\r
1191 { "checkMates", "checkMates", XtRBoolean,
\r
1192 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
\r
1193 XtRImmediate, (XtPointer) False},
\r
1194 { "materialDraws", "materialDraws", XtRBoolean,
\r
1195 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
\r
1196 XtRImmediate, (XtPointer) False},
\r
1197 { "trivialDraws", "trivialDraws", XtRBoolean,
\r
1198 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
\r
1199 XtRImmediate, (XtPointer) False},
\r
1200 { "ruleMoves", "ruleMoves", XtRInt,
\r
1201 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
\r
1202 XtRImmediate, (XtPointer) 51},
\r
1203 { "repeatsToDraw", "repeatsToDraw", XtRInt,
\r
1204 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
\r
1205 XtRImmediate, (XtPointer) 6},
\r
1206 { "engineDebugOutput", "engineDebugOutput", XtRInt,
\r
1207 sizeof(int), XtOffset(AppDataPtr, engineComments),
\r
1208 XtRImmediate, (XtPointer) 1},
\r
1209 { "userName", "userName", XtRString,
\r
1210 sizeof(int), XtOffset(AppDataPtr, userName),
\r
1211 XtRImmediate, (XtPointer) 0},
\r
1212 { "autoKibitz", "autoKibitz", XtRBoolean,
\r
1213 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
\r
1214 XtRImmediate, (XtPointer) False},
\r
1215 { "firstTimeOdds", "firstTimeOdds", XtRInt,
\r
1216 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
\r
1217 XtRImmediate, (XtPointer) 1},
\r
1218 { "secondTimeOdds", "secondTimeOdds", XtRInt,
\r
1219 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
\r
1220 XtRImmediate, (XtPointer) 1},
\r
1221 { "timeOddsMode", "timeOddsMode", XtRInt,
\r
1222 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
\r
1223 XtRImmediate, (XtPointer) 0},
\r
1224 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
\r
1225 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
\r
1226 XtRImmediate, (XtPointer) 1},
\r
1227 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
\r
1228 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
\r
1229 XtRImmediate, (XtPointer) 1},
\r
1230 { "firstNPS", "firstNPS", XtRInt,
\r
1231 sizeof(int), XtOffset(AppDataPtr, firstNPS),
\r
1232 XtRImmediate, (XtPointer) -1},
\r
1233 { "secondNPS", "secondNPS", XtRInt,
\r
1234 sizeof(int), XtOffset(AppDataPtr, secondNPS),
\r
1235 XtRImmediate, (XtPointer) -1},
\r
1236 { "serverMoves", "serverMoves", XtRString,
\r
1237 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
\r
1238 XtRImmediate, (XtPointer) 0},
\r
1239 { "serverPause", "serverPause", XtRInt,
\r
1240 sizeof(int), XtOffset(AppDataPtr, serverPause),
\r
1241 XtRImmediate, (XtPointer) 0},
\r
1242 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
\r
1243 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
\r
1244 XtRImmediate, (XtPointer) False},
\r
1247 XrmOptionDescRec shellOptions[] = {
\r
1248 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
\r
1249 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
\r
1250 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
\r
1251 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
\r
1252 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
\r
1253 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
\r
1254 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
\r
1255 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
\r
1256 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
\r
1257 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
\r
1258 { "-initString", "initString", XrmoptionSepArg, NULL },
\r
1259 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
\r
1260 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
\r
1261 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
\r
1262 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
\r
1263 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
\r
1264 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
\r
1265 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
\r
1266 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
\r
1267 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
\r
1268 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
\r
1269 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
\r
1270 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
\r
1271 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
\r
1272 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
\r
1273 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
\r
1274 { "-fh", "firstHost", XrmoptionSepArg, NULL },
\r
1275 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
\r
1276 { "-sh", "secondHost", XrmoptionSepArg, NULL },
\r
1277 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
\r
1278 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
\r
1279 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
\r
1280 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
\r
1281 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
\r
1282 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
\r
1283 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
\r
1284 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
\r
1285 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
\r
1286 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
\r
1287 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
\r
1288 { "-td", "timeDelay", XrmoptionSepArg, NULL },
\r
1289 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
\r
1290 { "-tc", "timeControl", XrmoptionSepArg, NULL },
\r
1291 { "-internetChessServerMode", "internetChessServerMode",
\r
1292 XrmoptionSepArg, NULL },
\r
1293 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
\r
1294 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
\r
1295 { "-internetChessServerHost", "internetChessServerHost",
\r
1296 XrmoptionSepArg, NULL },
\r
1297 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
\r
1298 { "-internetChessServerPort", "internetChessServerPort",
\r
1299 XrmoptionSepArg, NULL },
\r
1300 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
\r
1301 { "-internetChessServerCommPort", "internetChessServerCommPort",
\r
1302 XrmoptionSepArg, NULL },
\r
1303 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
\r
1304 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
\r
1305 XrmoptionSepArg, NULL },
\r
1306 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
\r
1307 { "-internetChessServerHelper", "internetChessServerHelper",
\r
1308 XrmoptionSepArg, NULL },
\r
1309 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
\r
1310 { "-internetChessServerInputBox", "internetChessServerInputBox",
\r
1311 XrmoptionSepArg, NULL },
\r
1312 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
\r
1313 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
\r
1314 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
\r
1315 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
\r
1316 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
\r
1317 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
\r
1318 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
\r
1319 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
\r
1320 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
\r
1321 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
\r
1322 { "-gateway", "gateway", XrmoptionSepArg, NULL },
\r
1323 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
\r
1324 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
\r
1325 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
\r
1326 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
\r
1327 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
\r
1328 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
\r
1329 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
\r
1330 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
\r
1331 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
\r
1332 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
\r
1333 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
\r
1334 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
\r
1335 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
\r
1336 { "-blind", "blindfold", XrmoptionNoArg, "True" },
\r
1337 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
\r
1338 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
\r
1339 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
\r
1340 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
\r
1341 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
\r
1342 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
\r
1343 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
\r
1344 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
\r
1345 { "-mm", "matchMode", XrmoptionNoArg, "True" },
\r
1346 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
\r
1347 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
\r
1348 { "-mg", "matchGames", XrmoptionSepArg, NULL },
\r
1349 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
\r
1350 { "-mono", "monoMode", XrmoptionNoArg, "True" },
\r
1351 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
\r
1352 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
\r
1353 { "-debug", "debugMode", XrmoptionNoArg, "True" },
\r
1354 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
\r
1355 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
\r
1356 { "-clock", "clockMode", XrmoptionNoArg, "True" },
\r
1357 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
\r
1358 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
\r
1359 { "-size", "boardSize", XrmoptionSepArg, NULL },
\r
1360 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
\r
1361 { "-st", "searchTime", XrmoptionSepArg, NULL },
\r
1362 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
\r
1363 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
\r
1364 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
\r
1365 { "-coords", "showCoords", XrmoptionNoArg, "True" },
\r
1366 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
\r
1368 { "-showJail", "showJail", XrmoptionSepArg, NULL },
\r
1369 { "-jail", "showJail", XrmoptionNoArg, "1" },
\r
1370 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
\r
1371 { "-xjail", "showJail", XrmoptionNoArg, "0" },
\r
1373 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
\r
1374 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
\r
1375 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
\r
1376 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
\r
1377 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
\r
1378 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
\r
1379 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
\r
1380 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
\r
1381 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
\r
1382 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
\r
1383 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
\r
1384 { "-font", "font", XrmoptionSepArg, NULL },
\r
1385 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
\r
1386 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
\r
1387 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
\r
1388 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
\r
1389 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
\r
1390 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
\r
1391 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
\r
1392 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
\r
1393 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
\r
1394 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
\r
1395 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
\r
1396 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
\r
1397 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
\r
1398 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
\r
1399 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
\r
1400 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
\r
1401 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
\r
1402 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
\r
1403 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
\r
1404 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
\r
1406 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
\r
1407 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
\r
1408 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
\r
1410 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
\r
1411 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
\r
1412 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
\r
1413 { "-premove", "premove", XrmoptionSepArg, NULL },
\r
1414 { "-pre", "premove", XrmoptionNoArg, "True" },
\r
1415 { "-xpre", "premove", XrmoptionNoArg, "False" },
\r
1416 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
\r
1417 { "-legal", "testLegality", XrmoptionNoArg, "True" },
\r
1418 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
\r
1419 { "-flipView", "flipView", XrmoptionSepArg, NULL },
\r
1420 { "-flip", "flipView", XrmoptionNoArg, "True" },
\r
1421 { "-xflip", "flipView", XrmoptionNoArg, "False" },
\r
1422 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
\r
1423 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
\r
1424 XrmoptionSepArg, NULL },
\r
1425 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
\r
1426 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
\r
1427 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
\r
1428 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
\r
1429 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
\r
1430 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
\r
1431 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
\r
1432 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
\r
1433 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
\r
1434 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
\r
1435 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
\r
1437 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
\r
1438 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
\r
1439 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
\r
1440 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
\r
1441 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
\r
1442 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
\r
1443 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
\r
1444 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
\r
1445 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
\r
1446 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
\r
1447 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
\r
1448 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
\r
1449 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
\r
1450 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
\r
1451 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
\r
1452 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
\r
1453 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
\r
1454 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
\r
1455 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
\r
1456 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
\r
1457 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
\r
1458 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
\r
1459 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
\r
1460 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
\r
1461 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
\r
1462 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
\r
1463 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
\r
1464 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
\r
1465 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
\r
1466 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
\r
1468 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
\r
1469 { "-flash", "flashCount", XrmoptionNoArg, "3" },
\r
1470 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
\r
1471 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
\r
1472 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
\r
1473 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
\r
1474 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
\r
1475 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
\r
1476 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
\r
1477 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
\r
1478 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
\r
1479 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
\r
1480 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
\r
1481 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
\r
1482 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
\r
1483 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
\r
1484 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
\r
1485 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
\r
1486 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
\r
1487 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
\r
1488 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
\r
1489 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
\r
1490 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
\r
1491 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
\r
1492 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
\r
1493 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
\r
1494 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
\r
1495 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
\r
1496 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
\r
1497 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
\r
1498 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
\r
1499 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
\r
1500 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
\r
1501 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
\r
1502 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
\r
1503 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
\r
1504 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
\r
1505 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
\r
1506 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
\r
1507 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
\r
1508 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
\r
1509 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
\r
1510 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
\r
1511 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
\r
1512 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
\r
1513 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
\r
1514 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
\r
1515 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
\r
1516 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
\r
1517 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
\r
1518 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
\r
1519 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
\r
1520 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
\r
1521 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
\r
1522 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
\r
1523 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
\r
1524 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
\r
1525 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
\r
1526 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
\r
1527 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
\r
1528 { "-mode", "initialMode", XrmoptionSepArg, NULL },
\r
1529 { "-variant", "variant", XrmoptionSepArg, NULL },
\r
1530 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
\r
1531 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
\r
1532 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
\r
1533 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
\r
1534 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
\r
1535 /* [AS,HR] New features */
\r
1536 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
\r
1537 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
\r
1538 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
\r
1539 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
\r
1540 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
\r
1541 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
\r
1542 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
\r
1543 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
\r
1545 /* [HGM,HR] User-selectable board size */
\r
1546 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
\r
1547 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
\r
1548 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
\r
1550 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
\r
1551 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
\r
1552 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
\r
1553 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
\r
1554 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
\r
1555 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
\r
1556 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
\r
1557 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
\r
1558 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
\r
1559 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
\r
1560 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
\r
1561 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
\r
1562 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
\r
1563 { "-userName", "userName", XrmoptionSepArg, NULL },
\r
1564 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
\r
1565 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
\r
1566 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
\r
1567 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
\r
1568 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
\r
1569 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
\r
1570 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
\r
1571 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
\r
1572 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
\r
1573 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
\r
1574 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
\r
1578 XtActionsRec boardActions[] = {
\r
1579 { "DrawPosition", DrawPositionProc },
\r
1580 { "HandleUserMove", HandleUserMove },
\r
1581 { "AnimateUserMove", AnimateUserMove },
\r
1582 { "FileNameAction", FileNameAction },
\r
1583 { "AskQuestionProc", AskQuestionProc },
\r
1584 { "AskQuestionReplyAction", AskQuestionReplyAction },
\r
1585 { "PieceMenuPopup", PieceMenuPopup },
\r
1586 { "WhiteClock", WhiteClock },
\r
1587 { "BlackClock", BlackClock },
\r
1588 { "Iconify", Iconify },
\r
1589 { "ResetProc", ResetProc },
\r
1590 { "LoadGameProc", LoadGameProc },
\r
1591 { "LoadNextGameProc", LoadNextGameProc },
\r
1592 { "LoadPrevGameProc", LoadPrevGameProc },
\r
1593 { "LoadSelectedProc", LoadSelectedProc },
\r
1594 { "ReloadGameProc", ReloadGameProc },
\r
1595 { "LoadPositionProc", LoadPositionProc },
\r
1596 { "LoadNextPositionProc", LoadNextPositionProc },
\r
1597 { "LoadPrevPositionProc", LoadPrevPositionProc },
\r
1598 { "ReloadPositionProc", ReloadPositionProc },
\r
1599 { "CopyPositionProc", CopyPositionProc },
\r
1600 { "PastePositionProc", PastePositionProc },
\r
1601 { "CopyGameProc", CopyGameProc },
\r
1602 { "PasteGameProc", PasteGameProc },
\r
1603 { "SaveGameProc", SaveGameProc },
\r
1604 { "SavePositionProc", SavePositionProc },
\r
1605 { "MailMoveProc", MailMoveProc },
\r
1606 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
\r
1607 { "QuitProc", QuitProc },
\r
1608 { "MachineWhiteProc", MachineWhiteProc },
\r
1609 { "MachineBlackProc", MachineBlackProc },
\r
1610 { "AnalysisModeProc", AnalyzeModeProc },
\r
1611 { "AnalyzeFileProc", AnalyzeFileProc },
\r
1612 { "TwoMachinesProc", TwoMachinesProc },
\r
1613 { "IcsClientProc", IcsClientProc },
\r
1614 { "EditGameProc", EditGameProc },
\r
1615 { "EditPositionProc", EditPositionProc },
\r
1616 { "TrainingProc", EditPositionProc },
\r
1617 { "ShowGameListProc", ShowGameListProc },
\r
1618 { "ShowMoveListProc", HistoryShowProc},
\r
1619 { "EditTagsProc", EditCommentProc },
\r
1620 { "EditCommentProc", EditCommentProc },
\r
1621 { "IcsAlarmProc", IcsAlarmProc },
\r
1622 { "IcsInputBoxProc", IcsInputBoxProc },
\r
1623 { "PauseProc", PauseProc },
\r
1624 { "AcceptProc", AcceptProc },
\r
1625 { "DeclineProc", DeclineProc },
\r
1626 { "RematchProc", RematchProc },
\r
1627 { "CallFlagProc", CallFlagProc },
\r
1628 { "DrawProc", DrawProc },
\r
1629 { "AdjournProc", AdjournProc },
\r
1630 { "AbortProc", AbortProc },
\r
1631 { "ResignProc", ResignProc },
\r
1632 { "EnterKeyProc", EnterKeyProc },
\r
1633 { "StopObservingProc", StopObservingProc },
\r
1634 { "StopExaminingProc", StopExaminingProc },
\r
1635 { "BackwardProc", BackwardProc },
\r
1636 { "ForwardProc", ForwardProc },
\r
1637 { "ToStartProc", ToStartProc },
\r
1638 { "ToEndProc", ToEndProc },
\r
1639 { "RevertProc", RevertProc },
\r
1640 { "TruncateGameProc", TruncateGameProc },
\r
1641 { "MoveNowProc", MoveNowProc },
\r
1642 { "RetractMoveProc", RetractMoveProc },
\r
1643 { "AlwaysQueenProc", AlwaysQueenProc },
\r
1644 { "AnimateDraggingProc", AnimateDraggingProc },
\r
1645 { "AnimateMovingProc", AnimateMovingProc },
\r
1646 { "AutoflagProc", AutoflagProc },
\r
1647 { "AutoflipProc", AutoflipProc },
\r
1648 { "AutobsProc", AutobsProc },
\r
1649 { "AutoraiseProc", AutoraiseProc },
\r
1650 { "AutosaveProc", AutosaveProc },
\r
1651 { "BlindfoldProc", BlindfoldProc },
\r
1652 { "FlashMovesProc", FlashMovesProc },
\r
1653 { "FlipViewProc", FlipViewProc },
\r
1654 { "GetMoveListProc", GetMoveListProc },
\r
1656 { "HighlightDraggingProc", HighlightDraggingProc },
\r
1658 { "HighlightLastMoveProc", HighlightLastMoveProc },
\r
1659 { "IcsAlarmProc", IcsAlarmProc },
\r
1660 { "MoveSoundProc", MoveSoundProc },
\r
1661 { "OldSaveStyleProc", OldSaveStyleProc },
\r
1662 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
\r
1663 { "PonderNextMoveProc", PonderNextMoveProc },
\r
1664 { "PopupExitMessageProc", PopupExitMessageProc },
\r
1665 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
\r
1666 { "PremoveProc", PremoveProc },
\r
1667 { "QuietPlayProc", QuietPlayProc },
\r
1668 { "ShowCoordsProc", ShowCoordsProc },
\r
1669 { "ShowThinkingProc", ShowThinkingProc },
\r
1670 { "TestLegalityProc", TestLegalityProc },
\r
1671 { "InfoProc", InfoProc },
\r
1672 { "ManProc", ManProc },
\r
1673 { "HintProc", HintProc },
\r
1674 { "BookProc", BookProc },
\r
1675 { "AboutGameProc", AboutGameProc },
\r
1676 { "AboutProc", AboutProc },
\r
1677 { "DebugProc", DebugProc },
\r
1678 { "NothingProc", NothingProc },
\r
1679 { "CommentPopDown", (XtActionProc) CommentPopDown },
\r
1680 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
\r
1681 { "TagsPopDown", (XtActionProc) TagsPopDown },
\r
1682 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
\r
1683 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
\r
1684 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
\r
1685 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
\r
1686 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
\r
1687 { "GameListPopDown", (XtActionProc) GameListPopDown },
\r
1688 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
\r
1689 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
\r
1692 char globalTranslations[] =
\r
1693 ":<Key>R: ResignProc() \n \
\r
1694 :<Key>r: ResetProc() \n \
\r
1695 :<Key>g: LoadGameProc() \n \
\r
1696 :<Key>N: LoadNextGameProc() \n \
\r
1697 :<Key>P: LoadPrevGameProc() \n \
\r
1698 :<Key>Q: QuitProc() \n \
\r
1699 :<Key>F: ToEndProc() \n \
\r
1700 :<Key>f: ForwardProc() \n \
\r
1701 :<Key>B: ToStartProc() \n \
\r
1702 :<Key>b: BackwardProc() \n \
\r
1703 :<Key>p: PauseProc() \n \
\r
1704 :<Key>d: DrawProc() \n \
\r
1705 :<Key>t: CallFlagProc() \n \
\r
1706 :<Key>i: Iconify() \n \
\r
1707 :<Key>c: Iconify() \n \
\r
1708 :<Key>v: FlipViewProc() \n \
\r
1709 <KeyDown>Control_L: BackwardProc() \n \
\r
1710 <KeyUp>Control_L: ForwardProc() \n \
\r
1711 <KeyDown>Control_R: BackwardProc() \n \
\r
1712 <KeyUp>Control_R: ForwardProc() \n \
\r
1713 Shift<Key>1: AskQuestionProc(\"Direct command\",\
\r
1714 \"Send to chess program:\",,1) \n \
\r
1715 Shift<Key>2: AskQuestionProc(\"Direct command\",\
\r
1716 \"Send to second chess program:\",,2) \n";
\r
1718 char boardTranslations[] =
\r
1719 "<Btn1Down>: HandleUserMove() \n \
\r
1720 <Btn1Up>: HandleUserMove() \n \
\r
1721 <Btn1Motion>: AnimateUserMove() \n \
\r
1722 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
\r
1723 PieceMenuPopup(menuB) \n \
\r
1724 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
\r
1725 PieceMenuPopup(menuW) \n \
\r
1726 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
\r
1727 PieceMenuPopup(menuW) \n \
\r
1728 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
\r
1729 PieceMenuPopup(menuB) \n";
\r
1731 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
\r
1732 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
\r
1734 char ICSInputTranslations[] =
\r
1735 "<Key>Return: EnterKeyProc() \n";
\r
1737 String xboardResources[] = {
\r
1738 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
\r
1739 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
\r
1740 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
\r
1745 /* Max possible square size */
\r
1746 #define MAXSQSIZE 256
\r
1748 static int xpm_avail[MAXSQSIZE];
\r
1750 #ifdef HAVE_DIR_STRUCT
\r
1752 /* Extract piece size from filename */
\r
1754 xpm_getsize(name, len, ext)
\r
1765 if ((p=strchr(name, '.')) == NULL ||
\r
1766 StrCaseCmp(p+1, ext) != 0)
\r
1772 while (*p && isdigit(*p))
\r
1779 /* Setup xpm_avail */
\r
1781 xpm_getavail(dirname, ext)
\r
1786 struct dirent *ent;
\r
1789 for (i=0; i<MAXSQSIZE; ++i)
\r
1792 if (appData.debugMode)
\r
1793 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
\r
1795 dir = opendir(dirname);
\r
1798 fprintf(stderr, "%s: Can't access XPM directory %s\n",
\r
1799 programName, dirname);
\r
1803 while ((ent=readdir(dir)) != NULL) {
\r
1804 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
\r
1805 if (i > 0 && i < MAXSQSIZE)
\r
1815 xpm_print_avail(fp, ext)
\r
1821 fprintf(fp, "Available `%s' sizes:\n", ext);
\r
1822 for (i=1; i<MAXSQSIZE; ++i) {
\r
1824 printf("%d\n", i);
\r
1828 /* Return XPM piecesize closest to size */
\r
1830 xpm_closest_to(dirname, size, ext)
\r
1836 int sm_diff = MAXSQSIZE;
\r
1840 xpm_getavail(dirname, ext);
\r
1842 if (appData.debugMode)
\r
1843 xpm_print_avail(stderr, ext);
\r
1845 for (i=1; i<MAXSQSIZE; ++i) {
\r
1846 if (xpm_avail[i]) {
\r
1848 diff = (diff<0) ? -diff : diff;
\r
1849 if (diff < sm_diff) {
\r
1857 fprintf(stderr, "Error: No `%s' files!\n", ext);
\r
1863 #else /* !HAVE_DIR_STRUCT */
\r
1864 /* If we are on a system without a DIR struct, we can't
\r
1865 read the directory, so we can't collect a list of
\r
1866 filenames, etc., so we can't do any size-fitting. */
\r
1868 xpm_closest_to(dirname, size, ext)
\r
1873 fprintf(stderr, "Warning: No DIR structure found on this system --\n");
\r
1874 fprintf(stderr, " Unable to autosize for XPM/XIM pieces.\n");
\r
1875 fprintf(stderr, " Please report this error to frankm@hiwaay.net.\n");
\r
1876 fprintf(stderr, " Include system type & operating system in message.\n");
\r
1879 #endif /* HAVE_DIR_STRUCT */
\r
1881 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
\r
1882 "magenta", "cyan", "white" };
\r
1886 TextColors textColors[(int)NColorClasses];
\r
1888 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
\r
1890 parse_color(str, which)
\r
1894 char *p, buf[100], *d;
\r
1897 if (strlen(str) > 99) /* watch bounds on buf */
\r
1902 for (i=0; i<which; ++i) {
\r
1903 p = strchr(p, ',');
\r
1909 /* Could be looking at something like:
\r
1911 .. in which case we want to stop on a comma also */
\r
1912 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
\r
1916 return -1; /* Use default for empty field */
\r
1919 if (which == 2 || isdigit(*p))
\r
1922 while (*p && isalpha(*p))
\r
1927 for (i=0; i<8; ++i) {
\r
1928 if (!StrCaseCmp(buf, cnames[i]))
\r
1929 return which? (i+40) : (i+30);
\r
1931 if (!StrCaseCmp(buf, "default")) return -1;
\r
1933 fprintf(stderr, "%s: unrecognized color %s\n", programName, buf);
\r
1938 parse_cpair(cc, str)
\r
1942 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
\r
1943 fprintf(stderr, "%s: can't parse foreground color in `%s'\n",
\r
1944 programName, str);
\r
1948 /* bg and attr are optional */
\r
1949 textColors[(int)cc].bg = parse_color(str, 1);
\r
1950 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
\r
1951 textColors[(int)cc].attr = 0;
\r
1957 /* Arrange to catch delete-window events */
\r
1958 Atom wm_delete_window;
\r
1960 CatchDeleteWindow(Widget w, String procname)
\r
1962 char buf[MSG_SIZ];
\r
1963 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
\r
1964 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
\r
1965 XtAugmentTranslations(w, XtParseTranslationTable(buf));
\r
1972 XtSetArg(args[0], XtNiconic, False);
\r
1973 XtSetValues(shellWidget, args, 1);
\r
1975 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
\r
1979 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
\r
1981 void InitDrawingSizes(BoardSize boardSize, int flags)
\r
1982 { // [HGM] Dummy routine to be able to link with backend files from 4.3.xx, which call it
\r
1992 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
\r
1993 XSetWindowAttributes window_attributes;
\r
1995 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
\r
1996 XrmValue vFrom, vTo;
\r
1997 XtGeometryResult gres;
\r
2000 int forceMono = False;
\r
2002 setbuf(stdout, NULL);
\r
2003 setbuf(stderr, NULL);
\r
2006 programName = strrchr(argv[0], '/');
\r
2007 if (programName == NULL)
\r
2008 programName = argv[0];
\r
2013 XtAppInitialize(&appContext, "XBoard", shellOptions,
\r
2014 XtNumber(shellOptions),
\r
2015 &argc, argv, xboardResources, NULL, 0);
\r
2017 fprintf(stderr, "%s: unrecognized argument %s\n",
\r
2018 programName, argv[1]);
\r
2022 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
\r
2025 if (chdir(chessDir) != 0) {
\r
2026 fprintf(stderr, "%s: can't cd to CHESSDIR: ", programName);
\r
2032 p = getenv("HOME");
\r
2033 if (p == NULL) p = "/tmp";
\r
2034 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
\r
2035 gameCopyFilename = (char*) malloc(i);
\r
2036 gamePasteFilename = (char*) malloc(i);
\r
2037 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
\r
2038 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
\r
2040 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
\r
2041 clientResources, XtNumber(clientResources),
\r
2044 /* [HGM,HR] make sure board size is acceptable */
\r
2045 if(appData.NrFiles > BOARD_SIZE ||
\r
2046 appData.NrRanks > BOARD_SIZE )
\r
2047 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2049 /* [HGM] The following line must be moved to the "New Shuffle Game" menu as soon as there is one! */
\r
2050 if(appData.defaultFrcPosition != -1) shuffleOpenings = TRUE;
\r
2053 /* This feature does not work; animation needs a rewrite */
\r
2054 appData.highlightDragging = FALSE;
\r
2058 xDisplay = XtDisplay(shellWidget);
\r
2059 xScreen = DefaultScreen(xDisplay);
\r
2060 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
\r
2062 gameInfo.variant = StringToVariant(appData.variant);
\r
2063 InitPosition(FALSE);
\r
2066 * Determine boardSize
\r
2068 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
\r
2071 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
\r
2072 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
\r
2073 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
\r
2074 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
\r
2079 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
\r
2081 if (isdigit(appData.boardSize[0])) {
\r
2082 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
\r
2083 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
\r
2084 &fontPxlSize, &smallLayout, &tinyLayout);
\r
2086 fprintf(stderr, "%s: bad boardSize syntax %s\n",
\r
2087 programName, appData.boardSize);
\r
2091 /* Find some defaults; use the nearest known size */
\r
2092 SizeDefaults *szd, *nearest;
\r
2093 int distance = 99999;
\r
2094 nearest = szd = sizeDefaults;
\r
2095 while (szd->name != NULL) {
\r
2096 if (abs(szd->squareSize - squareSize) < distance) {
\r
2098 distance = abs(szd->squareSize - squareSize);
\r
2099 if (distance == 0) break;
\r
2103 if (i < 2) lineGap = nearest->lineGap;
\r
2104 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
\r
2105 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
\r
2106 if (i < 5) fontPxlSize = nearest->fontPxlSize;
\r
2107 if (i < 6) smallLayout = nearest->smallLayout;
\r
2108 if (i < 7) tinyLayout = nearest->tinyLayout;
\r
2111 SizeDefaults *szd = sizeDefaults;
\r
2112 if (*appData.boardSize == NULLCHAR) {
\r
2113 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
\r
2114 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
\r
2117 if (szd->name == NULL) szd--;
\r
2119 while (szd->name != NULL &&
\r
2120 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
\r
2121 if (szd->name == NULL) {
\r
2122 fprintf(stderr, "%s: unrecognized boardSize name %s\n",
\r
2123 programName, appData.boardSize);
\r
2127 squareSize = szd->squareSize;
\r
2128 lineGap = szd->lineGap;
\r
2129 clockFontPxlSize = szd->clockFontPxlSize;
\r
2130 coordFontPxlSize = szd->coordFontPxlSize;
\r
2131 fontPxlSize = szd->fontPxlSize;
\r
2132 smallLayout = szd->smallLayout;
\r
2133 tinyLayout = szd->tinyLayout;
\r
2136 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
\r
2137 if (strlen(appData.pixmapDirectory) > 0) {
\r
2138 p = ExpandPathName(appData.pixmapDirectory);
\r
2140 fprintf(stderr, "Error expanding path name \"%s\"\n",
\r
2141 appData.pixmapDirectory);
\r
2144 if (appData.debugMode) {
\r
2145 fprintf(stderr, "XBoard square size (hint): %d\n", squareSize);
\r
2146 fprintf(stderr, "%s fulldir:%s:\n", IMAGE_EXT, p);
\r
2148 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
\r
2149 if (appData.debugMode) {
\r
2150 fprintf(stderr, "Closest %s size: %d\n", IMAGE_EXT, squareSize);
\r
2154 /* [HR] height treated separately (hacked) */
\r
2155 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
2156 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
\r
2157 if (appData.showJail == 1) {
\r
2158 /* Jail on top and bottom */
\r
2159 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
\r
2160 XtSetArg(boardArgs[2], XtNheight,
\r
2161 boardHeight + 2*(lineGap + squareSize));
\r
2162 } else if (appData.showJail == 2) {
\r
2163 /* Jail on sides */
\r
2164 XtSetArg(boardArgs[1], XtNwidth,
\r
2165 boardWidth + 2*(lineGap + squareSize));
\r
2166 XtSetArg(boardArgs[2], XtNheight, boardHeight);
\r
2169 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
\r
2170 XtSetArg(boardArgs[2], XtNheight, boardHeight);
\r
2174 * Determine what fonts to use.
\r
2176 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
\r
2177 clockFontID = XLoadFont(xDisplay, appData.clockFont);
\r
2178 clockFontStruct = XQueryFont(xDisplay, clockFontID);
\r
2179 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
\r
2180 coordFontID = XLoadFont(xDisplay, appData.coordFont);
\r
2181 coordFontStruct = XQueryFont(xDisplay, coordFontID);
\r
2182 appData.font = FindFont(appData.font, fontPxlSize);
\r
2184 xdb = XtDatabase(xDisplay);
\r
2185 XrmPutStringResource(&xdb, "*font", appData.font);
\r
2188 * Detect if there are not enough colors available and adapt.
\r
2190 if (DefaultDepth(xDisplay, xScreen) <= 2) {
\r
2191 appData.monoMode = True;
\r
2194 if (!appData.monoMode) {
\r
2195 vFrom.addr = (caddr_t) appData.lightSquareColor;
\r
2196 vFrom.size = strlen(appData.lightSquareColor);
\r
2197 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2198 if (vTo.addr == NULL) {
\r
2199 appData.monoMode = True;
\r
2202 lightSquareColor = *(Pixel *) vTo.addr;
\r
2205 if (!appData.monoMode) {
\r
2206 vFrom.addr = (caddr_t) appData.darkSquareColor;
\r
2207 vFrom.size = strlen(appData.darkSquareColor);
\r
2208 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2209 if (vTo.addr == NULL) {
\r
2210 appData.monoMode = True;
\r
2213 darkSquareColor = *(Pixel *) vTo.addr;
\r
2216 if (!appData.monoMode) {
\r
2217 vFrom.addr = (caddr_t) appData.whitePieceColor;
\r
2218 vFrom.size = strlen(appData.whitePieceColor);
\r
2219 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2220 if (vTo.addr == NULL) {
\r
2221 appData.monoMode = True;
\r
2224 whitePieceColor = *(Pixel *) vTo.addr;
\r
2227 if (!appData.monoMode) {
\r
2228 vFrom.addr = (caddr_t) appData.blackPieceColor;
\r
2229 vFrom.size = strlen(appData.blackPieceColor);
\r
2230 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2231 if (vTo.addr == NULL) {
\r
2232 appData.monoMode = True;
\r
2235 blackPieceColor = *(Pixel *) vTo.addr;
\r
2239 if (!appData.monoMode) {
\r
2240 vFrom.addr = (caddr_t) appData.highlightSquareColor;
\r
2241 vFrom.size = strlen(appData.highlightSquareColor);
\r
2242 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2243 if (vTo.addr == NULL) {
\r
2244 appData.monoMode = True;
\r
2247 highlightSquareColor = *(Pixel *) vTo.addr;
\r
2251 if (!appData.monoMode) {
\r
2252 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
\r
2253 vFrom.size = strlen(appData.premoveHighlightColor);
\r
2254 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2255 if (vTo.addr == NULL) {
\r
2256 appData.monoMode = True;
\r
2259 premoveHighlightColor = *(Pixel *) vTo.addr;
\r
2264 fprintf(stderr, "%s: too few colors available; trying monochrome mode\n",
\r
2268 if (appData.monoMode && appData.debugMode) {
\r
2269 fprintf(stderr, "white pixel = 0x%lx, black pixel = 0x%lx\n",
\r
2270 (unsigned long) XWhitePixel(xDisplay, xScreen),
\r
2271 (unsigned long) XBlackPixel(xDisplay, xScreen));
\r
2274 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
\r
2275 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
\r
2276 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
\r
2277 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
\r
2278 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
\r
2279 parse_cpair(ColorTell, appData.colorTell) < 0 ||
\r
2280 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
\r
2281 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
\r
2282 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
\r
2283 parse_cpair(ColorNormal, appData.colorNormal) < 0)
\r
2285 if (appData.colorize) {
\r
2287 "%s: can't parse color names; disabling colorization\n",
\r
2290 appData.colorize = FALSE;
\r
2292 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
\r
2293 textColors[ColorNone].attr = 0;
\r
2295 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
\r
2298 * widget hierarchy
\r
2301 layoutName = "tinyLayout";
\r
2302 } else if (smallLayout) {
\r
2303 layoutName = "smallLayout";
\r
2305 layoutName = "normalLayout";
\r
2307 /* Outer layoutWidget is there only to provide a name for use in
\r
2308 resources that depend on the layout style */
\r
2310 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
\r
2311 layoutArgs, XtNumber(layoutArgs));
\r
2313 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
\r
2314 formArgs, XtNumber(formArgs));
\r
2315 XtSetArg(args[0], XtNdefaultDistance, &sep);
\r
2316 XtGetValues(formWidget, args, 1);
\r
2319 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
\r
2321 widgetList[j++] = whiteTimerWidget =
\r
2322 XtCreateWidget("whiteTime", labelWidgetClass,
\r
2323 formWidget, timerArgs, XtNumber(timerArgs));
\r
2324 XtSetArg(args[0], XtNfont, clockFontStruct);
\r
2325 XtSetValues(whiteTimerWidget, args, 1);
\r
2327 widgetList[j++] = blackTimerWidget =
\r
2328 XtCreateWidget("blackTime", labelWidgetClass,
\r
2329 formWidget, timerArgs, XtNumber(timerArgs));
\r
2330 XtSetArg(args[0], XtNfont, clockFontStruct);
\r
2331 XtSetValues(blackTimerWidget, args, 1);
\r
2333 if (appData.titleInWindow) {
\r
2334 widgetList[j++] = titleWidget =
\r
2335 XtCreateWidget("title", labelWidgetClass, formWidget,
\r
2336 titleArgs, XtNumber(titleArgs));
\r
2339 if (appData.showButtonBar) {
\r
2340 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
\r
2343 widgetList[j++] = messageWidget =
\r
2344 XtCreateWidget("message", labelWidgetClass, formWidget,
\r
2345 messageArgs, XtNumber(messageArgs));
\r
2347 widgetList[j++] = boardWidget =
\r
2348 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
\r
2349 XtNumber(boardArgs));
\r
2351 XtManageChildren(widgetList, j);
\r
2353 timerWidth = (boardWidth - sep) / 2;
\r
2354 XtSetArg(args[0], XtNwidth, timerWidth);
\r
2355 XtSetValues(whiteTimerWidget, args, 1);
\r
2356 XtSetValues(blackTimerWidget, args, 1);
\r
2358 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
\r
2359 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
\r
2360 XtGetValues(whiteTimerWidget, args, 2);
\r
2362 if (appData.showButtonBar) {
\r
2363 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
\r
2364 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
\r
2365 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
\r
2369 * formWidget uses these constraints but they are stored
\r
2370 * in the children.
\r
2373 XtSetArg(args[i], XtNfromHoriz, 0); i++;
\r
2374 XtSetValues(menuBarWidget, args, i);
\r
2375 if (appData.titleInWindow) {
\r
2376 if (smallLayout) {
\r
2378 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2379 XtSetValues(whiteTimerWidget, args, i);
\r
2381 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2382 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2383 XtSetValues(blackTimerWidget, args, i);
\r
2385 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2386 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
\r
2387 XtSetValues(titleWidget, args, i);
\r
2389 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2390 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2391 XtSetValues(messageWidget, args, i);
\r
2392 if (appData.showButtonBar) {
\r
2394 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2395 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2396 XtSetValues(buttonBarWidget, args, i);
\r
2400 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2401 XtSetValues(whiteTimerWidget, args, i);
\r
2403 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2404 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2405 XtSetValues(blackTimerWidget, args, i);
\r
2407 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
\r
2408 XtSetValues(titleWidget, args, i);
\r
2410 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2411 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2412 XtSetValues(messageWidget, args, i);
\r
2413 if (appData.showButtonBar) {
\r
2415 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2416 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2417 XtSetValues(buttonBarWidget, args, i);
\r
2422 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2423 XtSetValues(whiteTimerWidget, args, i);
\r
2425 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2426 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2427 XtSetValues(blackTimerWidget, args, i);
\r
2429 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2430 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2431 XtSetValues(messageWidget, args, i);
\r
2432 if (appData.showButtonBar) {
\r
2434 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2435 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2436 XtSetValues(buttonBarWidget, args, i);
\r
2440 XtSetArg(args[0], XtNfromVert, messageWidget);
\r
2441 XtSetValues(boardWidget, args, 1);
\r
2443 XtRealizeWidget(shellWidget);
\r
2446 * Correct the width of the message and title widgets.
\r
2447 * It is not known why some systems need the extra fudge term.
\r
2448 * The value "2" is probably larger than needed.
\r
2450 XawFormDoLayout(formWidget, False);
\r
2451 #define WIDTH_FUDGE 2
\r
2453 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2454 XtSetArg(args[i], XtNheight, &h); i++;
\r
2455 XtGetValues(messageWidget, args, i);
\r
2456 if (appData.showButtonBar) {
\r
2458 XtSetArg(args[i], XtNwidth, &w); i++;
\r
2459 XtGetValues(buttonBarWidget, args, i);
\r
2460 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
\r
2462 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
\r
2465 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
\r
2466 if (gres != XtGeometryYes && appData.debugMode) {
\r
2467 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
\r
2468 programName, gres, w, h, wr, hr);
\r
2471 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
\r
2472 /* The size used for the child widget in layout lags one resize behind
\r
2473 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
\r
2475 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
\r
2476 if (gres != XtGeometryYes && appData.debugMode) {
\r
2477 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
\r
2478 programName, gres, w, h, wr, hr);
\r
2482 if (appData.titleInWindow) {
\r
2484 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2485 XtSetArg(args[i], XtNheight, &h); i++;
\r
2486 XtGetValues(titleWidget, args, i);
\r
2487 if (smallLayout) {
\r
2488 w = boardWidth - 2*bor;
\r
2490 XtSetArg(args[0], XtNwidth, &w);
\r
2491 XtGetValues(menuBarWidget, args, 1);
\r
2492 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
\r
2495 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
\r
2496 if (gres != XtGeometryYes && appData.debugMode) {
\r
2498 "%s: titleWidget geometry error %d %d %d %d %d\n",
\r
2499 programName, gres, w, h, wr, hr);
\r
2502 XawFormDoLayout(formWidget, True);
\r
2504 xBoardWindow = XtWindow(boardWidget);
\r
2506 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
\r
2507 // not need to go into InitDrawingSizes().
\r
2511 * Create X checkmark bitmap and initialize option menu checks.
\r
2513 ReadBitmap(&xMarkPixmap, "checkmark.bm",
\r
2514 checkmark_bits, checkmark_width, checkmark_height);
\r
2515 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
2516 if (appData.alwaysPromoteToQueen) {
\r
2517 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
\r
2520 if (appData.animateDragging) {
\r
2521 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2522 "menuOptions.Animate Dragging"),
\r
2525 if (appData.animate) {
\r
2526 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
\r
2529 if (appData.autoComment) {
\r
2530 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
\r
2533 if (appData.autoCallFlag) {
\r
2534 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
\r
2537 if (appData.autoFlipView) {
\r
2538 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
\r
2541 if (appData.autoObserve) {
\r
2542 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
\r
2545 if (appData.autoRaiseBoard) {
\r
2546 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2547 "menuOptions.Auto Raise Board"), args, 1);
\r
2549 if (appData.autoSaveGames) {
\r
2550 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2553 if (appData.saveGameFile[0] != NULLCHAR) {
\r
2554 /* Can't turn this off from menu */
\r
2555 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2557 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2561 if (appData.blindfold) {
\r
2562 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2563 "menuOptions.Blindfold"), args, 1);
\r
2565 if (appData.flashCount > 0) {
\r
2566 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2567 "menuOptions.Flash Moves"),
\r
2570 if (appData.getMoveList) {
\r
2571 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
\r
2575 if (appData.highlightDragging) {
\r
2576 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2577 "menuOptions.Highlight Dragging"),
\r
2581 if (appData.highlightLastMove) {
\r
2582 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2583 "menuOptions.Highlight Last Move"),
\r
2586 if (appData.icsAlarm) {
\r
2587 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
\r
2590 if (appData.ringBellAfterMoves) {
\r
2591 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
\r
2594 if (appData.oldSaveStyle) {
\r
2595 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2596 "menuOptions.Old Save Style"), args, 1);
\r
2598 if (appData.periodicUpdates) {
\r
2599 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2600 "menuOptions.Periodic Updates"), args, 1);
\r
2602 if (appData.ponderNextMove) {
\r
2603 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2604 "menuOptions.Ponder Next Move"), args, 1);
\r
2606 if (appData.popupExitMessage) {
\r
2607 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2608 "menuOptions.Popup Exit Message"), args, 1);
\r
2610 if (appData.popupMoveErrors) {
\r
2611 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2612 "menuOptions.Popup Move Errors"), args, 1);
\r
2614 if (appData.premove) {
\r
2615 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2616 "menuOptions.Premove"), args, 1);
\r
2618 if (appData.quietPlay) {
\r
2619 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2620 "menuOptions.Quiet Play"), args, 1);
\r
2622 if (appData.showCoords) {
\r
2623 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
\r
2626 if (appData.showThinking) {
\r
2627 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
\r
2630 if (appData.testLegality) {
\r
2631 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
\r
2638 ReadBitmap(&wIconPixmap, "icon_white.bm",
\r
2639 icon_white_bits, icon_white_width, icon_white_height);
\r
2640 ReadBitmap(&bIconPixmap, "icon_black.bm",
\r
2641 icon_black_bits, icon_black_width, icon_black_height);
\r
2642 iconPixmap = wIconPixmap;
\r
2644 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
\r
2645 XtSetValues(shellWidget, args, i);
\r
2648 * Create a cursor for the board widget.
\r
2650 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
\r
2651 XChangeWindowAttributes(xDisplay, xBoardWindow,
\r
2652 CWCursor, &window_attributes);
\r
2655 * Inhibit shell resizing.
\r
2657 shellArgs[0].value = (XtArgVal) &w;
\r
2658 shellArgs[1].value = (XtArgVal) &h;
\r
2659 XtGetValues(shellWidget, shellArgs, 2);
\r
2660 shellArgs[4].value = shellArgs[2].value = w;
\r
2661 shellArgs[5].value = shellArgs[3].value = h;
\r
2662 XtSetValues(shellWidget, &shellArgs[2], 4);
\r
2664 CatchDeleteWindow(shellWidget, "QuitProc");
\r
2669 if (appData.bitmapDirectory[0] != NULLCHAR) {
\r
2672 CreateXPMPieces();
\r
2675 CreateXIMPieces();
\r
2676 /* Create regular pieces */
\r
2677 if (!useImages) CreatePieces();
\r
2680 CreatePieceMenus();
\r
2682 if (appData.animate || appData.animateDragging)
\r
2685 XtAugmentTranslations(formWidget,
\r
2686 XtParseTranslationTable(globalTranslations));
\r
2687 XtAugmentTranslations(boardWidget,
\r
2688 XtParseTranslationTable(boardTranslations));
\r
2689 XtAugmentTranslations(whiteTimerWidget,
\r
2690 XtParseTranslationTable(whiteTranslations));
\r
2691 XtAugmentTranslations(blackTimerWidget,
\r
2692 XtParseTranslationTable(blackTranslations));
\r
2694 /* Why is the following needed on some versions of X instead
\r
2695 * of a translation? */
\r
2696 XtAddEventHandler(boardWidget, ExposureMask, False,
\r
2697 (XtEventHandler) EventProc, NULL);
\r
2702 if (errorExitStatus == -1) {
\r
2703 if (appData.icsActive) {
\r
2704 /* We now wait until we see "login:" from the ICS before
\r
2705 sending the logon script (problems with timestamp otherwise) */
\r
2706 /*ICSInitScript();*/
\r
2707 if (appData.icsInputBox) ICSInputBoxPopUp();
\r
2710 signal(SIGINT, IntSigHandler);
\r
2711 signal(SIGTERM, IntSigHandler);
\r
2712 if (*appData.cmailGameName != NULLCHAR) {
\r
2713 signal(SIGUSR1, CmailSigHandler);
\r
2716 InitPosition(TRUE);
\r
2718 XtAppMainLoop(appContext);
\r
2723 ShutDownFrontEnd()
\r
2725 if (appData.icsActive && oldICSInteractionTitle != NULL) {
\r
2726 DisplayIcsInteractionTitle(oldICSInteractionTitle);
\r
2728 unlink(gameCopyFilename);
\r
2729 unlink(gamePasteFilename);
\r
2733 IntSigHandler(sig)
\r
2740 CmailSigHandler(sig)
\r
2746 signal(SIGUSR1, SIG_IGN); /* suspend handler */
\r
2748 /* Activate call-back function CmailSigHandlerCallBack() */
\r
2749 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
\r
2751 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
\r
2755 CmailSigHandlerCallBack(isr, closure, message, count, error)
\r
2756 InputSourceRef isr;
\r
2763 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
\r
2765 /**** end signal code ****/
\r
2772 char buf[MSG_SIZ];
\r
2775 f = fopen(appData.icsLogon, "r");
\r
2777 p = getenv("HOME");
\r
2781 strcat(buf, appData.icsLogon);
\r
2782 f = fopen(buf, "r");
\r
2786 ProcessICSInitScript(f);
\r
2793 EditCommentPopDown();
\r
2804 SetMenuEnables(enab)
\r
2808 if (!menuBarWidget) return;
\r
2809 while (enab->name != NULL) {
\r
2810 w = XtNameToWidget(menuBarWidget, enab->name);
\r
2812 DisplayError(enab->name, 0);
\r
2814 XtSetSensitive(w, enab->value);
\r
2820 Enables icsEnables[] = {
\r
2821 { "menuFile.Mail Move", False },
\r
2822 { "menuFile.Reload CMail Message", False },
\r
2823 { "menuMode.Machine Black", False },
\r
2824 { "menuMode.Machine White", False },
\r
2825 { "menuMode.Analysis Mode", False },
\r
2826 { "menuMode.Analyze File", False },
\r
2827 { "menuMode.Two Machines", False },
\r
2829 { "menuHelp.Hint", False },
\r
2830 { "menuHelp.Book", False },
\r
2831 { "menuStep.Move Now", False },
\r
2832 { "menuOptions.Periodic Updates", False },
\r
2833 { "menuOptions.Show Thinking", False },
\r
2834 { "menuOptions.Ponder Next Move", False },
\r
2839 Enables ncpEnables[] = {
\r
2840 { "menuFile.Mail Move", False },
\r
2841 { "menuFile.Reload CMail Message", False },
\r
2842 { "menuMode.Machine White", False },
\r
2843 { "menuMode.Machine Black", False },
\r
2844 { "menuMode.Analysis Mode", False },
\r
2845 { "menuMode.Analyze File", False },
\r
2846 { "menuMode.Two Machines", False },
\r
2847 { "menuMode.ICS Client", False },
\r
2848 { "menuMode.ICS Input Box", False },
\r
2849 { "Action", False },
\r
2850 { "menuStep.Revert", False },
\r
2851 { "menuStep.Move Now", False },
\r
2852 { "menuStep.Retract Move", False },
\r
2853 { "menuOptions.Auto Comment", False },
\r
2854 { "menuOptions.Auto Flag", False },
\r
2855 { "menuOptions.Auto Flip View", False },
\r
2856 { "menuOptions.Auto Observe", False },
\r
2857 { "menuOptions.Auto Raise Board", False },
\r
2858 { "menuOptions.Get Move List", False },
\r
2859 { "menuOptions.ICS Alarm", False },
\r
2860 { "menuOptions.Move Sound", False },
\r
2861 { "menuOptions.Quiet Play", False },
\r
2862 { "menuOptions.Show Thinking", False },
\r
2863 { "menuOptions.Periodic Updates", False },
\r
2864 { "menuOptions.Ponder Next Move", False },
\r
2865 { "menuHelp.Hint", False },
\r
2866 { "menuHelp.Book", False },
\r
2870 Enables gnuEnables[] = {
\r
2871 { "menuMode.ICS Client", False },
\r
2872 { "menuMode.ICS Input Box", False },
\r
2873 { "menuAction.Accept", False },
\r
2874 { "menuAction.Decline", False },
\r
2875 { "menuAction.Rematch", False },
\r
2876 { "menuAction.Adjourn", False },
\r
2877 { "menuAction.Stop Examining", False },
\r
2878 { "menuAction.Stop Observing", False },
\r
2879 { "menuStep.Revert", False },
\r
2880 { "menuOptions.Auto Comment", False },
\r
2881 { "menuOptions.Auto Observe", False },
\r
2882 { "menuOptions.Auto Raise Board", False },
\r
2883 { "menuOptions.Get Move List", False },
\r
2884 { "menuOptions.Premove", False },
\r
2885 { "menuOptions.Quiet Play", False },
\r
2887 /* The next two options rely on SetCmailMode being called *after* */
\r
2888 /* SetGNUMode so that when GNU is being used to give hints these */
\r
2889 /* menu options are still available */
\r
2891 { "menuFile.Mail Move", False },
\r
2892 { "menuFile.Reload CMail Message", False },
\r
2896 Enables cmailEnables[] = {
\r
2897 { "Action", True },
\r
2898 { "menuAction.Call Flag", False },
\r
2899 { "menuAction.Draw", True },
\r
2900 { "menuAction.Adjourn", False },
\r
2901 { "menuAction.Abort", False },
\r
2902 { "menuAction.Stop Observing", False },
\r
2903 { "menuAction.Stop Examining", False },
\r
2904 { "menuFile.Mail Move", True },
\r
2905 { "menuFile.Reload CMail Message", True },
\r
2909 Enables trainingOnEnables[] = {
\r
2910 { "menuMode.Edit Comment", False },
\r
2911 { "menuMode.Pause", False },
\r
2912 { "menuStep.Forward", False },
\r
2913 { "menuStep.Backward", False },
\r
2914 { "menuStep.Forward to End", False },
\r
2915 { "menuStep.Back to Start", False },
\r
2916 { "menuStep.Move Now", False },
\r
2917 { "menuStep.Truncate Game", False },
\r
2921 Enables trainingOffEnables[] = {
\r
2922 { "menuMode.Edit Comment", True },
\r
2923 { "menuMode.Pause", True },
\r
2924 { "menuStep.Forward", True },
\r
2925 { "menuStep.Backward", True },
\r
2926 { "menuStep.Forward to End", True },
\r
2927 { "menuStep.Back to Start", True },
\r
2928 { "menuStep.Move Now", True },
\r
2929 { "menuStep.Truncate Game", True },
\r
2933 Enables machineThinkingEnables[] = {
\r
2934 { "menuFile.Load Game", False },
\r
2935 { "menuFile.Load Next Game", False },
\r
2936 { "menuFile.Load Previous Game", False },
\r
2937 { "menuFile.Reload Same Game", False },
\r
2938 { "menuFile.Paste Game", False },
\r
2939 { "menuFile.Load Position", False },
\r
2940 { "menuFile.Load Next Position", False },
\r
2941 { "menuFile.Load Previous Position", False },
\r
2942 { "menuFile.Reload Same Position", False },
\r
2943 { "menuFile.Paste Position", False },
\r
2944 { "menuMode.Machine White", False },
\r
2945 { "menuMode.Machine Black", False },
\r
2946 { "menuMode.Two Machines", False },
\r
2947 { "menuStep.Retract Move", False },
\r
2951 Enables userThinkingEnables[] = {
\r
2952 { "menuFile.Load Game", True },
\r
2953 { "menuFile.Load Next Game", True },
\r
2954 { "menuFile.Load Previous Game", True },
\r
2955 { "menuFile.Reload Same Game", True },
\r
2956 { "menuFile.Paste Game", True },
\r
2957 { "menuFile.Load Position", True },
\r
2958 { "menuFile.Load Next Position", True },
\r
2959 { "menuFile.Load Previous Position", True },
\r
2960 { "menuFile.Reload Same Position", True },
\r
2961 { "menuFile.Paste Position", True },
\r
2962 { "menuMode.Machine White", True },
\r
2963 { "menuMode.Machine Black", True },
\r
2964 { "menuMode.Two Machines", True },
\r
2965 { "menuStep.Retract Move", True },
\r
2971 SetMenuEnables(icsEnables);
\r
2977 SetMenuEnables(ncpEnables);
\r
2983 SetMenuEnables(gnuEnables);
\r
2989 SetMenuEnables(cmailEnables);
\r
2993 SetTrainingModeOn()
\r
2995 SetMenuEnables(trainingOnEnables);
\r
2996 if (appData.showButtonBar) {
\r
2997 XtSetSensitive(buttonBarWidget, False);
\r
3003 SetTrainingModeOff()
\r
3005 SetMenuEnables(trainingOffEnables);
\r
3006 if (appData.showButtonBar) {
\r
3007 XtSetSensitive(buttonBarWidget, True);
\r
3012 SetUserThinkingEnables()
\r
3014 if (appData.noChessProgram) return;
\r
3015 SetMenuEnables(userThinkingEnables);
\r
3019 SetMachineThinkingEnables()
\r
3021 if (appData.noChessProgram) return;
\r
3022 SetMenuEnables(machineThinkingEnables);
\r
3023 switch (gameMode) {
\r
3024 case MachinePlaysBlack:
\r
3025 case MachinePlaysWhite:
\r
3026 case TwoMachinesPlay:
\r
3027 XtSetSensitive(XtNameToWidget(menuBarWidget,
\r
3028 ModeToWidgetName(gameMode)), True);
\r
3035 #define Abs(n) ((n)<0 ? -(n) : (n))
\r
3038 * Find a font that matches "pattern" that is as close as
\r
3039 * possible to the targetPxlSize. Prefer fonts that are k
\r
3040 * pixels smaller to fonts that are k pixels larger. The
\r
3041 * pattern must be in the X Consortium standard format,
\r
3042 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
\r
3043 * The return value should be freed with XtFree when no
\r
3046 char *FindFont(pattern, targetPxlSize)
\r
3048 int targetPxlSize;
\r
3050 char **fonts, *p, *best, *scalable, *scalableTail;
\r
3051 int i, j, nfonts, minerr, err, pxlSize;
\r
3053 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
\r
3055 fprintf(stderr, "%s: no fonts match pattern %s\n",
\r
3056 programName, pattern);
\r
3062 for (i=0; i<nfonts; i++) {
\r
3065 if (*p != '-') continue;
\r
3067 if (*p == NULLCHAR) break;
\r
3068 if (*p++ == '-') j++;
\r
3070 if (j < 7) continue;
\r
3071 pxlSize = atoi(p);
\r
3072 if (pxlSize == 0) {
\r
3073 scalable = fonts[i];
\r
3076 err = pxlSize - targetPxlSize;
\r
3077 if (Abs(err) < Abs(minerr) ||
\r
3078 (minerr > 0 && err < 0 && -err == minerr)) {
\r
3084 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
\r
3085 /* If the error is too big and there is a scalable font,
\r
3086 use the scalable font. */
\r
3087 int headlen = scalableTail - scalable;
\r
3088 p = (char *) XtMalloc(strlen(scalable) + 10);
\r
3089 while (isdigit(*scalableTail)) scalableTail++;
\r
3090 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
\r
3092 p = (char *) XtMalloc(strlen(best) + 1);
\r
3095 if (appData.debugMode) {
\r
3096 fprintf(debugFP, "resolved %s at pixel size %d\n to %s\n",
\r
3097 pattern, targetPxlSize, p);
\r
3099 XFreeFontNames(fonts);
\r
3105 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
\r
3106 | GCBackground | GCFunction | GCPlaneMask;
\r
3107 XGCValues gc_values;
\r
3108 GC copyInvertedGC;
\r
3110 gc_values.plane_mask = AllPlanes;
\r
3111 gc_values.line_width = lineGap;
\r
3112 gc_values.line_style = LineSolid;
\r
3113 gc_values.function = GXcopy;
\r
3115 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3116 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3117 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3119 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3120 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3121 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3122 XSetFont(xDisplay, coordGC, coordFontID);
\r
3124 if (appData.monoMode) {
\r
3125 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3126 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3127 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3129 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3130 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3131 lightSquareGC = wbPieceGC
\r
3132 = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3134 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3135 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3136 darkSquareGC = bwPieceGC
\r
3137 = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3139 if (DefaultDepth(xDisplay, xScreen) == 1) {
\r
3140 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
\r
3141 gc_values.function = GXcopyInverted;
\r
3142 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3143 gc_values.function = GXcopy;
\r
3144 if (XBlackPixel(xDisplay, xScreen) == 1) {
\r
3145 bwPieceGC = darkSquareGC;
\r
3146 wbPieceGC = copyInvertedGC;
\r
3148 bwPieceGC = copyInvertedGC;
\r
3149 wbPieceGC = lightSquareGC;
\r
3153 gc_values.foreground = highlightSquareColor;
\r
3154 gc_values.background = highlightSquareColor;
\r
3155 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3157 gc_values.foreground = premoveHighlightColor;
\r
3158 gc_values.background = premoveHighlightColor;
\r
3159 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3161 gc_values.foreground = lightSquareColor;
\r
3162 gc_values.background = darkSquareColor;
\r
3163 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3165 gc_values.foreground = darkSquareColor;
\r
3166 gc_values.background = lightSquareColor;
\r
3167 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3169 gc_values.foreground = jailSquareColor;
\r
3170 gc_values.background = jailSquareColor;
\r
3171 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3173 gc_values.foreground = whitePieceColor;
\r
3174 gc_values.background = darkSquareColor;
\r
3175 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3177 gc_values.foreground = whitePieceColor;
\r
3178 gc_values.background = lightSquareColor;
\r
3179 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3181 gc_values.foreground = whitePieceColor;
\r
3182 gc_values.background = jailSquareColor;
\r
3183 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3185 gc_values.foreground = blackPieceColor;
\r
3186 gc_values.background = darkSquareColor;
\r
3187 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3189 gc_values.foreground = blackPieceColor;
\r
3190 gc_values.background = lightSquareColor;
\r
3191 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3193 gc_values.foreground = blackPieceColor;
\r
3194 gc_values.background = jailSquareColor;
\r
3195 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3199 void loadXIM(xim, xmask, filename, dest, mask)
\r
3206 int x, y, w, h, p;
\r
3212 fp = fopen(filename, "rb");
\r
3214 fprintf(stderr, "%s: error loading XIM!\n", programName);
\r
3221 for (y=0; y<h; ++y) {
\r
3222 for (x=0; x<h; ++x) {
\r
3227 XPutPixel(xim, x, y, blackPieceColor);
\r
3229 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
\r
3232 XPutPixel(xim, x, y, darkSquareColor);
\r
3234 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
\r
3237 XPutPixel(xim, x, y, whitePieceColor);
\r
3239 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
\r
3242 XPutPixel(xim, x, y, lightSquareColor);
\r
3244 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
\r
3250 /* create Pixmap of piece */
\r
3251 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3252 w, h, xim->depth);
\r
3253 XPutImage(xDisplay, *dest, lightSquareGC, xim,
\r
3254 0, 0, 0, 0, w, h);
\r
3256 /* create Pixmap of clipmask
\r
3257 Note: We assume the white/black pieces have the same
\r
3258 outline, so we make only 6 masks. This is okay
\r
3259 since the XPM clipmask routines do the same. */
\r
3261 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3262 w, h, xim->depth);
\r
3263 XPutImage(xDisplay, temp, lightSquareGC, xmask,
\r
3264 0, 0, 0, 0, w, h);
\r
3266 /* now create the 1-bit version */
\r
3267 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3270 values.foreground = 1;
\r
3271 values.background = 0;
\r
3273 /* Don't use XtGetGC, not read only */
\r
3274 maskGC = XCreateGC(xDisplay, *mask,
\r
3275 GCForeground | GCBackground, &values);
\r
3276 XCopyPlane(xDisplay, temp, *mask, maskGC,
\r
3277 0, 0, squareSize, squareSize, 0, 0, 1);
\r
3278 XFreePixmap(xDisplay, temp);
\r
3282 void CreateXIMPieces()
\r
3285 char buf[MSG_SIZ];
\r
3287 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
\r
3292 /* The XSynchronize calls were copied from CreatePieces.
\r
3293 Not sure if needed, but can't hurt */
\r
3294 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3297 /* temp needed by loadXIM() */
\r
3298 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3299 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3301 if (strlen(appData.pixmapDirectory) == 0) {
\r
3305 if (appData.monoMode) {
\r
3306 DisplayFatalError("XIM pieces cannot be used in monochrome mode",
\r
3310 fprintf(stderr, "\nLoading XIMs...\n");
\r
3312 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3313 fprintf(stderr, "%d", piece+1);
\r
3314 for (kind=0; kind<4; kind++) {
\r
3315 fprintf(stderr, ".");
\r
3316 sprintf(buf, "%s/%c%s%u.xim",
\r
3317 ExpandPathName(appData.pixmapDirectory),
\r
3318 ToLower(PieceToChar((ChessSquare)piece)),
\r
3319 ximkind[kind], ss);
\r
3320 ximPieceBitmap[kind][piece] =
\r
3321 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3322 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3323 if (appData.debugMode)
\r
3324 fprintf(stderr, "(File:%s:) ", buf);
\r
3325 loadXIM(ximPieceBitmap[kind][piece],
\r
3327 &(xpmPieceBitmap[kind][piece]),
\r
3328 &(ximMaskPm[piece%(int)BlackPawn]));
\r
3330 fprintf(stderr," ");
\r
3332 /* Load light and dark squares */
\r
3333 /* If the LSQ and DSQ pieces don't exist, we will
\r
3334 draw them with solid squares. */
\r
3335 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
\r
3336 if (access(buf, 0) != 0) {
\r
3340 fprintf(stderr, "light square ");
\r
3342 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3343 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3344 if (appData.debugMode)
\r
3345 fprintf(stderr, "(File:%s:) ", buf);
\r
3347 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
\r
3348 fprintf(stderr, "dark square ");
\r
3349 sprintf(buf, "%s/dsq%u.xim",
\r
3350 ExpandPathName(appData.pixmapDirectory), ss);
\r
3351 if (appData.debugMode)
\r
3352 fprintf(stderr, "(File:%s:) ", buf);
\r
3354 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3355 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3356 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
\r
3357 xpmJailSquare = xpmLightSquare;
\r
3359 fprintf(stderr, "Done.\n");
\r
3361 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
\r
3365 void CreateXPMPieces()
\r
3367 int piece, kind, r;
\r
3368 char buf[MSG_SIZ];
\r
3369 u_int ss = squareSize;
\r
3370 XpmAttributes attr;
\r
3371 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
\r
3372 XpmColorSymbol symbols[4];
\r
3375 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
\r
3376 if (appData.debugMode) {
\r
3377 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
\r
3378 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
\r
3382 /* The XSynchronize calls were copied from CreatePieces.
\r
3383 Not sure if needed, but can't hurt */
\r
3384 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
\r
3386 /* Setup translations so piece colors match square colors */
\r
3387 symbols[0].name = "light_piece";
\r
3388 symbols[0].value = appData.whitePieceColor;
\r
3389 symbols[1].name = "dark_piece";
\r
3390 symbols[1].value = appData.blackPieceColor;
\r
3391 symbols[2].name = "light_square";
\r
3392 symbols[2].value = appData.lightSquareColor;
\r
3393 symbols[3].name = "dark_square";
\r
3394 symbols[3].value = appData.darkSquareColor;
\r
3396 attr.valuemask = XpmColorSymbols;
\r
3397 attr.colorsymbols = symbols;
\r
3398 attr.numsymbols = 4;
\r
3400 if (appData.monoMode) {
\r
3401 DisplayFatalError("XPM pieces cannot be used in monochrome mode",
\r
3405 if (strlen(appData.pixmapDirectory) == 0) {
\r
3406 XpmPieces* pieces = builtInXpms;
\r
3409 while (pieces->size != squareSize && pieces->size) pieces++;
\r
3410 if (!pieces->size) {
\r
3411 fprintf(stderr, "No builtin XPM pieces of size %d\n", squareSize);
\r
3414 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3415 for (kind=0; kind<4; kind++) {
\r
3417 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
\r
3418 pieces->xpm[piece][kind],
\r
3419 &(xpmPieceBitmap[kind][piece]),
\r
3420 NULL, &attr)) != 0) {
\r
3421 fprintf(stderr, "Error %d loading XPM image \"%s\"\n",
\r
3428 xpmJailSquare = xpmLightSquare;
\r
3432 fprintf(stderr, "\nLoading XPMs...\n");
\r
3435 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3436 fprintf(stderr, "%d ", piece+1);
\r
3437 for (kind=0; kind<4; kind++) {
\r
3438 sprintf(buf, "%s/%c%s%u.xpm",
\r
3439 ExpandPathName(appData.pixmapDirectory),
\r
3440 ToLower(PieceToChar((ChessSquare)piece)),
\r
3441 xpmkind[kind], ss);
\r
3442 if (appData.debugMode) {
\r
3443 fprintf(stderr, "(File:%s:) ", buf);
\r
3445 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3446 &(xpmPieceBitmap[kind][piece]),
\r
3447 NULL, &attr)) != 0) {
\r
3448 fprintf(stderr, "Error %d loading XPM file \"%s\"\n",
\r
3454 /* Load light and dark squares */
\r
3455 /* If the LSQ and DSQ pieces don't exist, we will
\r
3456 draw them with solid squares. */
\r
3457 fprintf(stderr, "light square ");
\r
3458 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
\r
3459 if (access(buf, 0) != 0) {
\r
3463 if (appData.debugMode)
\r
3464 fprintf(stderr, "(File:%s:) ", buf);
\r
3466 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3467 &xpmLightSquare, NULL, &attr)) != 0) {
\r
3468 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
\r
3471 fprintf(stderr, "dark square ");
\r
3472 sprintf(buf, "%s/dsq%u.xpm",
\r
3473 ExpandPathName(appData.pixmapDirectory), ss);
\r
3474 if (appData.debugMode) {
\r
3475 fprintf(stderr, "(File:%s:) ", buf);
\r
3477 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3478 &xpmDarkSquare, NULL, &attr)) != 0) {
\r
3479 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
\r
3483 xpmJailSquare = xpmLightSquare;
\r
3484 fprintf(stderr, "Done.\n");
\r
3486 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3489 #endif /* HAVE_LIBXPM */
\r
3492 /* No built-in bitmaps */
\r
3493 void CreatePieces()
\r
3496 char buf[MSG_SIZ];
\r
3497 u_int ss = squareSize;
\r
3499 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3502 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
\r
3503 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3504 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
\r
3505 ss, kind == SOLID ? 's' : 'o');
\r
3506 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
\r
3510 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3514 /* With built-in bitmaps */
\r
3515 void CreatePieces()
\r
3517 BuiltInBits* bib = builtInBits;
\r
3519 char buf[MSG_SIZ];
\r
3520 u_int ss = squareSize;
\r
3522 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3525 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
\r
3527 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
\r
3528 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3529 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
\r
3530 ss, kind == SOLID ? 's' : 'o');
\r
3531 ReadBitmap(&pieceBitmap[kind][piece], buf,
\r
3532 bib->bits[kind][piece], ss, ss);
\r
3536 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3541 void ReadBitmap(pm, name, bits, wreq, hreq)
\r
3544 unsigned char bits[];
\r
3550 char msg[MSG_SIZ], fullname[MSG_SIZ];
\r
3552 if (*appData.bitmapDirectory != NULLCHAR) {
\r
3553 strcpy(fullname, appData.bitmapDirectory);
\r
3554 strcat(fullname, "/");
\r
3555 strcat(fullname, name);
\r
3556 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
\r
3557 &w, &h, pm, &x_hot, &y_hot);
\r
3558 if (errcode != BitmapSuccess) {
\r
3559 switch (errcode) {
\r
3560 case BitmapOpenFailed:
\r
3561 sprintf(msg, "Can't open bitmap file %s", fullname);
\r
3563 case BitmapFileInvalid:
\r
3564 sprintf(msg, "Invalid bitmap in file %s", fullname);
\r
3566 case BitmapNoMemory:
\r
3567 sprintf(msg, "Ran out of memory reading bitmap file %s",
\r
3571 sprintf(msg, "Unknown XReadBitmapFile error %d on file %s",
\r
3572 errcode, fullname);
\r
3575 fprintf(stderr, "%s: %s...using built-in\n",
\r
3576 programName, msg);
\r
3577 } else if (w != wreq || h != hreq) {
\r
3579 "%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n",
\r
3580 programName, fullname, w, h, wreq, hreq);
\r
3585 if (bits == NULL) {
\r
3587 fprintf(stderr, "%s: No built-in bitmap for %s; giving up\n",
\r
3588 programName, name);
\r
3591 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
\r
3593 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
\r
3602 if (lineGap == 0) return;
\r
3604 /* [HR] Split this into 2 loops for non-square boards. */
\r
3606 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3607 gridSegments[i].x1 = 0;
\r
3608 gridSegments[i].x2 =
\r
3609 lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
3610 gridSegments[i].y1 = gridSegments[i].y2
\r
3611 = lineGap / 2 + (i * (squareSize + lineGap));
\r
3614 for (j = 0; j < BOARD_WIDTH + 1; j++) {
\r
3615 gridSegments[j + i].y1 = 0;
\r
3616 gridSegments[j + i].y2 =
\r
3617 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
\r
3618 gridSegments[j + i].x1 = gridSegments[j + i].x2
\r
3619 = lineGap / 2 + (j * (squareSize + lineGap));
\r
3623 static void MenuBarSelect(w, addr, index)
\r
3628 XtActionProc proc = (XtActionProc) addr;
\r
3630 (proc)(NULL, NULL, NULL, NULL);
\r
3633 void CreateMenuBarPopup(parent, name, mb)
\r
3639 Widget menu, entry;
\r
3643 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
\r
3646 XtSetArg(args[j], XtNleftMargin, 20); j++;
\r
3647 XtSetArg(args[j], XtNrightMargin, 20); j++;
\r
3649 while (mi->string != NULL) {
\r
3650 if (strcmp(mi->string, "----") == 0) {
\r
3651 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
\r
3654 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
\r
3656 XtAddCallback(entry, XtNcallback,
\r
3657 (XtCallbackProc) MenuBarSelect,
\r
3658 (caddr_t) mi->proc);
\r
3664 Widget CreateMenuBar(mb)
\r
3668 Widget anchor, menuBar;
\r
3670 char menuName[MSG_SIZ];
\r
3673 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
\r
3674 XtSetArg(args[j], XtNvSpace, 0); j++;
\r
3675 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3676 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
\r
3677 formWidget, args, j);
\r
3679 while (mb->name != NULL) {
\r
3680 strcpy(menuName, "menu");
\r
3681 strcat(menuName, mb->name);
\r
3683 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
\r
3685 char shortName[2];
\r
3686 shortName[0] = mb->name[0];
\r
3687 shortName[1] = NULLCHAR;
\r
3688 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
\r
3690 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3691 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
\r
3692 menuBar, args, j);
\r
3693 CreateMenuBarPopup(menuBar, menuName, mb);
\r
3699 Widget CreateButtonBar(mi)
\r
3703 Widget button, buttonBar;
\r
3707 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
\r
3709 XtSetArg(args[j], XtNhSpace, 0); j++;
\r
3711 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3712 XtSetArg(args[j], XtNvSpace, 0); j++;
\r
3713 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
\r
3714 formWidget, args, j);
\r
3716 while (mi->string != NULL) {
\r
3719 XtSetArg(args[j], XtNinternalWidth, 2); j++;
\r
3720 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3722 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
\r
3723 buttonBar, args, j);
\r
3724 XtAddCallback(button, XtNcallback,
\r
3725 (XtCallbackProc) MenuBarSelect,
\r
3726 (caddr_t) mi->proc);
\r
3733 CreatePieceMenu(name, color)
\r
3738 Widget entry, menu;
\r
3740 ChessSquare selection;
\r
3742 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
\r
3743 boardWidget, args, 0);
\r
3745 for (i = 0; i < PIECE_MENU_SIZE; i++) {
\r
3746 String item = pieceMenuStrings[color][i];
\r
3748 if (strcmp(item, "----") == 0) {
\r
3749 entry = XtCreateManagedWidget(item, smeLineObjectClass,
\r
3752 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
\r
3754 selection = pieceMenuTranslation[color][i];
\r
3755 XtAddCallback(entry, XtNcallback,
\r
3756 (XtCallbackProc) PieceMenuSelect,
\r
3757 (caddr_t) selection);
\r
3758 if (selection == WhitePawn || selection == BlackPawn) {
\r
3759 XtSetArg(args[0], XtNpopupOnEntry, entry);
\r
3760 XtSetValues(menu, args, 1);
\r
3768 CreatePieceMenus()
\r
3773 ChessSquare selection;
\r
3775 whitePieceMenu = CreatePieceMenu("menuW", 0);
\r
3776 blackPieceMenu = CreatePieceMenu("menuB", 1);
\r
3778 XtRegisterGrabAction(PieceMenuPopup, True,
\r
3779 (unsigned)(ButtonPressMask|ButtonReleaseMask),
\r
3780 GrabModeAsync, GrabModeAsync);
\r
3782 XtSetArg(args[0], XtNlabel, "Drop");
\r
3783 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
\r
3784 boardWidget, args, 1);
\r
3785 for (i = 0; i < DROP_MENU_SIZE; i++) {
\r
3786 String item = dropMenuStrings[i];
\r
3788 if (strcmp(item, "----") == 0) {
\r
3789 entry = XtCreateManagedWidget(item, smeLineObjectClass,
\r
3790 dropMenu, NULL, 0);
\r
3792 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
\r
3793 dropMenu, NULL, 0);
\r
3794 selection = dropMenuTranslation[i];
\r
3795 XtAddCallback(entry, XtNcallback,
\r
3796 (XtCallbackProc) DropMenuSelect,
\r
3797 (caddr_t) selection);
\r
3802 void SetupDropMenu()
\r
3810 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
\r
3811 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
\r
3812 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
\r
3813 dmEnables[i].piece);
\r
3814 XtSetSensitive(entry, p != NULL || !appData.testLegality
\r
3815 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
\r
3816 && !appData.icsActive));
\r
3818 while (p && *p++ == dmEnables[i].piece) count++;
\r
3819 sprintf(label, "%s %d", dmEnables[i].widget, count);
\r
3821 XtSetArg(args[j], XtNlabel, label); j++;
\r
3822 XtSetValues(entry, args, j);
\r
3826 void PieceMenuPopup(w, event, params, num_params)
\r
3830 Cardinal *num_params;
\r
3833 if (event->type != ButtonPress) return;
\r
3834 if (errorUp) ErrorPopDown();
\r
3835 switch (gameMode) {
\r
3836 case EditPosition:
\r
3837 case IcsExamining:
\r
3838 whichMenu = params[0];
\r
3840 case IcsPlayingWhite:
\r
3841 case IcsPlayingBlack:
\r
3843 case MachinePlaysWhite:
\r
3844 case MachinePlaysBlack:
\r
3845 if (appData.testLegality &&
\r
3846 gameInfo.variant != VariantBughouse &&
\r
3847 gameInfo.variant != VariantCrazyhouse) return;
\r
3849 whichMenu = "menuD";
\r
3855 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
\r
3856 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
\r
3857 pmFromX = pmFromY = -1;
\r
3861 pmFromX = BOARD_WIDTH - 1 - pmFromX;
\r
3863 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
\r
3865 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
\r
3868 static void PieceMenuSelect(w, piece, junk)
\r
3870 ChessSquare piece;
\r
3873 if (pmFromX < 0 || pmFromY < 0) return;
\r
3874 EditPositionMenuEvent(piece, pmFromX, pmFromY);
\r
3877 static void DropMenuSelect(w, piece, junk)
\r
3879 ChessSquare piece;
\r
3882 if (pmFromX < 0 || pmFromY < 0) return;
\r
3883 DropMenuEvent(piece, pmFromX, pmFromY);
\r
3886 void WhiteClock(w, event, prms, nprms)
\r
3892 if (gameMode == EditPosition || gameMode == IcsExamining) {
\r
3893 SetWhiteToPlayEvent();
\r
3894 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
\r
3899 void BlackClock(w, event, prms, nprms)
\r
3905 if (gameMode == EditPosition || gameMode == IcsExamining) {
\r
3906 SetBlackToPlayEvent();
\r
3907 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
\r
3914 * If the user selects on a border boundary, return -1; if off the board,
\r
3915 * return -2. Otherwise map the event coordinate to the square.
\r
3917 int EventToSquare(x, limit)
\r
3925 if ((x % (squareSize + lineGap)) >= squareSize)
\r
3927 x /= (squareSize + lineGap);
\r
3933 static void do_flash_delay(msec)
\r
3934 unsigned long msec;
\r
3939 static void drawHighlight(file, rank, gc)
\r
3945 if (lineGap == 0 || appData.blindfold) return;
\r
3948 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
\r
3949 (squareSize + lineGap);
\r
3950 y = lineGap/2 + rank * (squareSize + lineGap);
\r
3952 x = lineGap/2 + file * (squareSize + lineGap);
\r
3953 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
\r
3954 (squareSize + lineGap);
\r
3957 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
\r
3958 squareSize+lineGap, squareSize+lineGap);
\r
3961 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
\r
3962 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
\r
3965 SetHighlights(fromX, fromY, toX, toY)
\r
3966 int fromX, fromY, toX, toY;
\r
3968 if (hi1X != fromX || hi1Y != fromY) {
\r
3969 if (hi1X >= 0 && hi1Y >= 0) {
\r
3970 drawHighlight(hi1X, hi1Y, lineGC);
\r
3972 if (fromX >= 0 && fromY >= 0) {
\r
3973 drawHighlight(fromX, fromY, highlineGC);
\r
3976 if (hi2X != toX || hi2Y != toY) {
\r
3977 if (hi2X >= 0 && hi2Y >= 0) {
\r
3978 drawHighlight(hi2X, hi2Y, lineGC);
\r
3980 if (toX >= 0 && toY >= 0) {
\r
3981 drawHighlight(toX, toY, highlineGC);
\r
3993 SetHighlights(-1, -1, -1, -1);
\r
3998 SetPremoveHighlights(fromX, fromY, toX, toY)
\r
3999 int fromX, fromY, toX, toY;
\r
4001 if (pm1X != fromX || pm1Y != fromY) {
\r
4002 if (pm1X >= 0 && pm1Y >= 0) {
\r
4003 drawHighlight(pm1X, pm1Y, lineGC);
\r
4005 if (fromX >= 0 && fromY >= 0) {
\r
4006 drawHighlight(fromX, fromY, prelineGC);
\r
4009 if (pm2X != toX || pm2Y != toY) {
\r
4010 if (pm2X >= 0 && pm2Y >= 0) {
\r
4011 drawHighlight(pm2X, pm2Y, lineGC);
\r
4013 if (toX >= 0 && toY >= 0) {
\r
4014 drawHighlight(toX, toY, prelineGC);
\r
4024 ClearPremoveHighlights()
\r
4026 SetPremoveHighlights(-1, -1, -1, -1);
\r
4029 static void BlankSquare(x, y, color, piece, dest)
\r
4031 ChessSquare piece;
\r
4034 if (useImages && useImageSqs) {
\r
4037 case 1: /* light */
\r
4038 pm = xpmLightSquare;
\r
4040 case 0: /* dark */
\r
4041 pm = xpmDarkSquare;
\r
4043 case 2: /* neutral */
\r
4045 pm = xpmJailSquare;
\r
4048 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
\r
4049 squareSize, squareSize, x, y);
\r
4053 case 1: /* light */
\r
4054 gc = lightSquareGC;
\r
4056 case 0: /* dark */
\r
4057 gc = darkSquareGC;
\r
4059 case 2: /* neutral */
\r
4061 gc = jailSquareGC;
\r
4064 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
\r
4069 I split out the routines to draw a piece so that I could
\r
4070 make a generic flash routine.
\r
4072 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
\r
4073 ChessSquare piece;
\r
4074 int square_color, x, y;
\r
4077 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
\r
4078 switch (square_color) {
\r
4079 case 1: /* light */
\r
4080 case 2: /* neutral */
\r
4082 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
\r
4083 ? *pieceToOutline(piece)
\r
4084 : *pieceToSolid(piece),
\r
4085 dest, bwPieceGC, 0, 0,
\r
4086 squareSize, squareSize, x, y);
\r
4088 case 0: /* dark */
\r
4089 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
\r
4090 ? *pieceToSolid(piece)
\r
4091 : *pieceToOutline(piece),
\r
4092 dest, wbPieceGC, 0, 0,
\r
4093 squareSize, squareSize, x, y);
\r
4098 static void monoDrawPiece(piece, square_color, x, y, dest)
\r
4099 ChessSquare piece;
\r
4100 int square_color, x, y;
\r
4103 switch (square_color) {
\r
4104 case 1: /* light */
\r
4105 case 2: /* neutral */
\r
4107 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
\r
4108 ? *pieceToOutline(piece)
\r
4109 : *pieceToSolid(piece),
\r
4110 dest, bwPieceGC, 0, 0,
\r
4111 squareSize, squareSize, x, y, 1);
\r
4113 case 0: /* dark */
\r
4114 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
\r
4115 ? *pieceToSolid(piece)
\r
4116 : *pieceToOutline(piece),
\r
4117 dest, wbPieceGC, 0, 0,
\r
4118 squareSize, squareSize, x, y, 1);
\r
4123 static void colorDrawPiece(piece, square_color, x, y, dest)
\r
4124 ChessSquare piece;
\r
4125 int square_color, x, y;
\r
4128 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
\r
4129 switch (square_color) {
\r
4130 case 1: /* light */
\r
4131 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4132 dest, (int) piece < (int) BlackPawn
\r
4133 ? wlPieceGC : blPieceGC, 0, 0,
\r
4134 squareSize, squareSize, x, y, 1);
\r
4136 case 0: /* dark */
\r
4137 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4138 dest, (int) piece < (int) BlackPawn
\r
4139 ? wdPieceGC : bdPieceGC, 0, 0,
\r
4140 squareSize, squareSize, x, y, 1);
\r
4142 case 2: /* neutral */
\r
4144 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4145 dest, (int) piece < (int) BlackPawn
\r
4146 ? wjPieceGC : bjPieceGC, 0, 0,
\r
4147 squareSize, squareSize, x, y, 1);
\r
4152 static void colorDrawPieceImage(piece, square_color, x, y, dest)
\r
4153 ChessSquare piece;
\r
4154 int square_color, x, y;
\r
4159 switch (square_color) {
\r
4160 case 1: /* light */
\r
4161 case 2: /* neutral */
\r
4163 if ((int)piece < (int) BlackPawn) {
\r
4167 piece -= BlackPawn;
\r
4170 case 0: /* dark */
\r
4171 if ((int)piece < (int) BlackPawn) {
\r
4175 piece -= BlackPawn;
\r
4179 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
\r
4180 dest, wlPieceGC, 0, 0,
\r
4181 squareSize, squareSize, x, y);
\r
4184 typedef void (*DrawFunc)();
\r
4186 DrawFunc ChooseDrawFunc()
\r
4188 if (appData.monoMode) {
\r
4189 if (DefaultDepth(xDisplay, xScreen) == 1) {
\r
4190 return monoDrawPiece_1bit;
\r
4192 return monoDrawPiece;
\r
4196 return colorDrawPieceImage;
\r
4198 return colorDrawPiece;
\r
4202 /* [HR] determine square color depending on chess variant. */
\r
4203 static int SquareColor(row, column)
\r
4208 if (gameInfo.variant == VariantXiangqi) {
\r
4209 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
\r
4211 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
\r
4213 } else if (row <= 4) {
\r
4219 square_color = ((column + row) % 2) == 1;
\r
4222 /* [hgm] holdings: next line makes all holdings squares light */
\r
4223 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 0;
\r
4225 return square_color;
\r
4228 void DrawSquare(row, column, piece, do_flash)
\r
4229 int row, column, do_flash;
\r
4230 ChessSquare piece;
\r
4232 int square_color, x, y, direction, font_ascent, font_descent;
\r
4235 XCharStruct overall;
\r
4236 DrawFunc drawfunc;
\r
4239 /* Calculate delay in milliseconds (2-delays per complete flash) */
\r
4240 flash_delay = 500 / appData.flashRate;
\r
4243 x = lineGap + ((BOARD_WIDTH-1)-column) *
\r
4244 (squareSize + lineGap);
\r
4245 y = lineGap + row * (squareSize + lineGap);
\r
4247 x = lineGap + column * (squareSize + lineGap);
\r
4248 y = lineGap + ((BOARD_HEIGHT-1)-row) *
\r
4249 (squareSize + lineGap);
\r
4252 square_color = SquareColor(row, column);
\r
4254 if ( // [HGM] holdings: next 5 lines blank out area between board and holdings
\r
4255 column == BOARD_LEFT-1 || column == BOARD_RGHT
\r
4256 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
\r
4257 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
\r
4258 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
\r
4260 if (piece == EmptySquare || appData.blindfold) {
\r
4261 BlankSquare(x, y, square_color, piece, xBoardWindow);
\r
4263 drawfunc = ChooseDrawFunc();
\r
4264 if (do_flash && appData.flashCount > 0) {
\r
4265 for (i=0; i<appData.flashCount; ++i) {
\r
4267 drawfunc(piece, square_color, x, y, xBoardWindow);
\r
4268 XSync(xDisplay, False);
\r
4269 do_flash_delay(flash_delay);
\r
4271 BlankSquare(x, y, square_color, piece, xBoardWindow);
\r
4272 XSync(xDisplay, False);
\r
4273 do_flash_delay(flash_delay);
\r
4276 drawfunc(piece, square_color, x, y, xBoardWindow);
\r
4280 string[1] = NULLCHAR;
\r
4281 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)) {
\r
4282 string[0] = 'a' + column;
\r
4283 XTextExtents(coordFontStruct, string, 1, &direction,
\r
4284 &font_ascent, &font_descent, &overall);
\r
4285 if (appData.monoMode) {
\r
4286 XDrawImageString(xDisplay, xBoardWindow, coordGC,
\r
4287 x + squareSize - overall.width - 2,
\r
4288 y + squareSize - font_descent - 1, string, 1);
\r
4290 XDrawString(xDisplay, xBoardWindow, coordGC,
\r
4291 x + squareSize - overall.width - 2,
\r
4292 y + squareSize - font_descent - 1, string, 1);
\r
4295 if (appData.showCoords && column == (flipView ? BOARD_WIDTH-1 : 0)) {
\r
4296 string[0] = ONE + row;
\r
4297 XTextExtents(coordFontStruct, string, 1, &direction,
\r
4298 &font_ascent, &font_descent, &overall);
\r
4299 if (appData.monoMode) {
\r
4300 XDrawImageString(xDisplay, xBoardWindow, coordGC,
\r
4301 x + 2, y + font_ascent + 1, string, 1);
\r
4303 XDrawString(xDisplay, xBoardWindow, coordGC,
\r
4304 x + 2, y + font_ascent + 1, string, 1);
\r
4310 /* Why is this needed on some versions of X? */
\r
4311 void EventProc(widget, unused, event)
\r
4316 if (!XtIsRealized(widget))
\r
4319 switch (event->type) {
\r
4321 if (event->xexpose.count > 0) return; /* no clipping is done */
\r
4322 XDrawPosition(widget, True, NULL);
\r
4330 void DrawPosition(fullRedraw, board)
\r
4331 /*Boolean*/int fullRedraw;
\r
4334 XDrawPosition(boardWidget, fullRedraw, board);
\r
4337 /* Returns 1 if there are "too many" differences between b1 and b2
\r
4338 (i.e. more than 1 move was made) */
\r
4339 static int too_many_diffs(b1, b2)
\r
4345 for (i=0; i<BOARD_HEIGHT; ++i) {
\r
4346 for (j=0; j<BOARD_WIDTH; ++j) {
\r
4347 if (b1[i][j] != b2[i][j]) {
\r
4348 if (++c > 4) /* Castling causes 4 diffs */
\r
4357 /* Matrix describing castling maneuvers */
\r
4358 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
\r
4359 static int castling_matrix[4][5] = {
\r
4360 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
\r
4361 { 0, 7, 4, 5, 6 }, /* 0-0, white */
\r
4362 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
\r
4363 { 7, 7, 4, 5, 6 } /* 0-0, black */
\r
4366 /* Checks whether castling occurred. If it did, *rrow and *rcol
\r
4367 are set to the destination (row,col) of the rook that moved.
\r
4369 Returns 1 if castling occurred, 0 if not.
\r
4371 Note: Only handles a max of 1 castling move, so be sure
\r
4372 to call too_many_diffs() first.
\r
4374 static int check_castle_draw(newb, oldb, rrow, rcol)
\r
4381 /* For each type of castling... */
\r
4382 for (i=0; i<4; ++i) {
\r
4383 r = castling_matrix[i];
\r
4385 /* Check the 4 squares involved in the castling move */
\r
4387 for (j=1; j<=4; ++j) {
\r
4388 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
\r
4395 /* All 4 changed, so it must be a castling move */
\r
4404 static int damage[BOARD_SIZE][BOARD_SIZE];
\r
4407 * event handler for redrawing the board
\r
4409 void XDrawPosition(w, repaint, board)
\r
4411 /*Boolean*/int repaint;
\r
4414 int i, j, do_flash;
\r
4415 static int lastFlipView = 0;
\r
4416 static int lastBoardValid = 0;
\r
4417 static Board lastBoard;
\r
4421 if (board == NULL) {
\r
4422 if (!lastBoardValid) return;
\r
4423 board = lastBoard;
\r
4425 if (!lastBoardValid || lastFlipView != flipView) {
\r
4426 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
\r
4427 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
\r
4432 * It would be simpler to clear the window with XClearWindow()
\r
4433 * but this causes a very distracting flicker.
\r
4436 if (!repaint && lastBoardValid && lastFlipView == flipView) {
\r
4438 /* If too much changes (begin observing new game, etc.), don't
\r
4440 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
\r
4442 /* Special check for castling so we don't flash both the king
\r
4443 and the rook (just flash the king). */
\r
4445 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
\r
4446 /* Draw rook with NO flashing. King will be drawn flashing later */
\r
4447 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
\r
4448 lastBoard[rrow][rcol] = board[rrow][rcol];
\r
4452 /* First pass -- Draw (newly) empty squares and repair damage.
\r
4453 This prevents you from having a piece show up twice while it
\r
4454 is flashing on its new square */
\r
4455 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4456 for (j = 0; j < BOARD_WIDTH; j++)
\r
4457 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
\r
4458 || damage[i][j]) {
\r
4459 DrawSquare(i, j, board[i][j], 0);
\r
4460 damage[i][j] = False;
\r
4463 /* Second pass -- Draw piece(s) in new position and flash them */
\r
4464 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4465 for (j = 0; j < BOARD_WIDTH; j++)
\r
4466 if (board[i][j] != lastBoard[i][j]) {
\r
4467 DrawSquare(i, j, board[i][j], do_flash);
\r
4471 XDrawSegments(xDisplay, xBoardWindow, lineGC,
\r
4472 gridSegments, (BOARD_SIZE + 1) * 2);
\r
4474 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4475 for (j = 0; j < BOARD_WIDTH; j++) {
\r
4476 DrawSquare(i, j, board[i][j], 0);
\r
4477 damage[i][j] = False;
\r
4481 CopyBoard(lastBoard, board);
\r
4482 lastBoardValid = 1;
\r
4483 lastFlipView = flipView;
\r
4485 /* Draw highlights */
\r
4486 if (pm1X >= 0 && pm1Y >= 0) {
\r
4487 drawHighlight(pm1X, pm1Y, prelineGC);
\r
4489 if (pm2X >= 0 && pm2Y >= 0) {
\r
4490 drawHighlight(pm2X, pm2Y, prelineGC);
\r
4492 if (hi1X >= 0 && hi1Y >= 0) {
\r
4493 drawHighlight(hi1X, hi1Y, highlineGC);
\r
4495 if (hi2X >= 0 && hi2Y >= 0) {
\r
4496 drawHighlight(hi2X, hi2Y, highlineGC);
\r
4499 /* If piece being dragged around board, must redraw that too */
\r
4502 XSync(xDisplay, False);
\r
4507 * event handler for redrawing the board
\r
4509 void DrawPositionProc(w, event, prms, nprms)
\r
4515 XDrawPosition(w, True, NULL);
\r
4520 * event handler for parsing user moves
\r
4522 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
\r
4523 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
\r
4524 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
\r
4525 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
\r
4526 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
\r
4527 // and at the end FinishMove() to perform the move after optional promotion popups.
\r
4528 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
\r
4529 void HandleUserMove(w, event, prms, nprms)
\r
4536 Boolean saveAnimate;
\r
4537 static int second = 0;
\r
4539 if (w != boardWidget || errorExitStatus != -1) return;
\r
4541 if (event->type == ButtonPress) ErrorPopDown();
\r
4543 if (promotionUp) {
\r
4544 if (event->type == ButtonPress) {
\r
4545 XtPopdown(promotionShell);
\r
4546 XtDestroyWidget(promotionShell);
\r
4547 promotionUp = False;
\r
4548 ClearHighlights();
\r
4549 fromX = fromY = -1;
\r
4555 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
\r
4556 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
\r
4557 if (!flipView && y >= 0) {
\r
4558 y = BOARD_HEIGHT - 1 - y;
\r
4560 if (flipView && x >= 0) {
\r
4561 x = BOARD_WIDTH - 1 - x;
\r
4564 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
\r
4565 if(event->type == ButtonPress
\r
4566 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
\r
4567 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
\r
4568 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
\r
4571 if (fromX == -1) {
\r
4572 if (event->type == ButtonPress) {
\r
4573 /* First square */
\r
4574 if (OKToStartUserMove(x, y)) {
\r
4578 DragPieceBegin(event->xbutton.x, event->xbutton.y);
\r
4579 if (appData.highlightDragging) {
\r
4580 SetHighlights(x, y, -1, -1);
\r
4588 if (event->type == ButtonPress && gameMode != EditPosition &&
\r
4589 x >= 0 && y >= 0) {
\r
4590 ChessSquare fromP;
\r
4593 /* Check if clicking again on the same color piece */
\r
4594 fromP = boards[currentMove][fromY][fromX];
\r
4595 toP = boards[currentMove][y][x];
\r
4596 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
\r
4597 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
\r
4598 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
\r
4599 BlackPawn <= toP && toP <= BlackKing)) {
\r
4600 /* Clicked again on same color piece -- changed his mind */
\r
4601 second = (x == fromX && y == fromY);
\r
4602 if (appData.highlightDragging) {
\r
4603 SetHighlights(x, y, -1, -1);
\r
4605 ClearHighlights();
\r
4607 if (OKToStartUserMove(x, y)) {
\r
4610 DragPieceBegin(event->xbutton.x, event->xbutton.y);
\r
4616 if (event->type == ButtonRelease && x == fromX && y == fromY) {
\r
4617 DragPieceEnd(event->xbutton.x, event->xbutton.y);
\r
4618 if (appData.animateDragging) {
\r
4619 /* Undo animation damage if any */
\r
4620 DrawPosition(FALSE, NULL);
\r
4623 /* Second up/down in same square; just abort move */
\r
4625 fromX = fromY = -1;
\r
4626 ClearHighlights();
\r
4628 ClearPremoveHighlights();
\r
4630 /* First upclick in same square; start click-click mode */
\r
4631 SetHighlights(x, y, -1, -1);
\r
4636 /* Completed move */
\r
4639 saveAnimate = appData.animate;
\r
4640 if (event->type == ButtonPress) {
\r
4641 /* Finish clickclick move */
\r
4642 if (appData.animate || appData.highlightLastMove) {
\r
4643 SetHighlights(fromX, fromY, toX, toY);
\r
4645 ClearHighlights();
\r
4648 /* Finish drag move */
\r
4649 if (appData.highlightLastMove) {
\r
4650 SetHighlights(fromX, fromY, toX, toY);
\r
4652 ClearHighlights();
\r
4654 DragPieceEnd(event->xbutton.x, event->xbutton.y);
\r
4655 /* Don't animate move and drag both */
\r
4656 appData.animate = FALSE;
\r
4658 if (IsPromotion(fromX, fromY, toX, toY)) {
\r
4659 if (appData.alwaysPromoteToQueen) {
\r
4660 UserMoveEvent(fromX, fromY, toX, toY, 'q');
\r
4661 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
4662 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
4663 fromX = fromY = -1;
\r
4665 SetHighlights(fromX, fromY, toX, toY);
\r
4669 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
\r
4670 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
4671 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
4672 fromX = fromY = -1;
\r
4674 appData.animate = saveAnimate;
\r
4675 if (appData.animate || appData.animateDragging) {
\r
4676 /* Undo animation damage if needed */
\r
4677 DrawPosition(FALSE, NULL);
\r
4681 void AnimateUserMove (Widget w, XEvent * event,
\r
4682 String * params, Cardinal * nParams)
\r
4684 DragPieceMove(event->xmotion.x, event->xmotion.y);
\r
4687 Widget CommentCreate(name, text, mutable, callback, lines)
\r
4688 char *name, *text;
\r
4689 int /*Boolean*/ mutable;
\r
4690 XtCallbackProc callback;
\r
4694 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
\r
4695 Dimension bw_width;
\r
4699 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
4700 XtGetValues(boardWidget, args, j);
\r
4703 XtSetArg(args[j], XtNresizable, True); j++;
\r
4706 XtCreatePopupShell(name, topLevelShellWidgetClass,
\r
4707 shellWidget, args, j);
\r
4710 XtCreatePopupShell(name, transientShellWidgetClass,
\r
4711 shellWidget, args, j);
\r
4714 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
\r
4715 layoutArgs, XtNumber(layoutArgs));
\r
4717 XtCreateManagedWidget("form", formWidgetClass, layout,
\r
4718 formArgs, XtNumber(formArgs));
\r
4722 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
\r
4723 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
\r
4725 XtSetArg(args[j], XtNstring, text); j++;
\r
4726 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
4727 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
4728 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
4729 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r
4730 XtSetArg(args[j], XtNresizable, True); j++;
\r
4731 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
\r
4733 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
\r
4735 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
\r
4736 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
\r
4738 XtSetArg(args[j], XtNautoFill, True); j++;
\r
4739 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
\r
4741 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
\r
4745 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
4746 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
4747 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
4748 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
4749 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
4751 XtCreateManagedWidget("ok", commandWidgetClass, form, args, j);
\r
4752 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
\r
4755 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
4756 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
\r
4757 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
4758 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
4759 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
4760 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
4762 XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);
\r
4763 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
\r
4766 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
4767 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
\r
4768 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
4769 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
4770 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
4771 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
4773 XtCreateManagedWidget("clear", commandWidgetClass, form, args, j);
\r
4774 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
\r
4777 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
4778 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
4779 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
4780 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
4781 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
4783 XtCreateManagedWidget("close", commandWidgetClass, form, args, j);
\r
4784 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
\r
4787 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
4788 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
\r
4789 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
4790 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
4791 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
4792 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
4794 XtCreateManagedWidget("edit", commandWidgetClass, form, args, j);
\r
4795 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
\r
4798 XtRealizeWidget(shell);
\r
4800 if (commentX == -1) {
\r
4803 Dimension pw_height;
\r
4804 Dimension ew_height;
\r
4807 XtSetArg(args[j], XtNheight, &ew_height); j++;
\r
4808 XtGetValues(edit, args, j);
\r
4811 XtSetArg(args[j], XtNheight, &pw_height); j++;
\r
4812 XtGetValues(shell, args, j);
\r
4813 commentH = pw_height + (lines - 1) * ew_height;
\r
4814 commentW = bw_width - 16;
\r
4816 XSync(xDisplay, False);
\r
4818 /* This code seems to tickle an X bug if it is executed too soon
\r
4819 after xboard starts up. The coordinates get transformed as if
\r
4820 the main window was positioned at (0, 0).
\r
4822 XtTranslateCoords(shellWidget,
\r
4823 (bw_width - commentW) / 2, 0 - commentH / 2,
\r
4824 &commentX, &commentY);
\r
4826 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
\r
4827 RootWindowOfScreen(XtScreen(shellWidget)),
\r
4828 (bw_width - commentW) / 2, 0 - commentH / 2,
\r
4832 #endif /*!NOTDEF*/
\r
4833 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
\r
4836 XtSetArg(args[j], XtNheight, commentH); j++;
\r
4837 XtSetArg(args[j], XtNwidth, commentW); j++;
\r
4838 XtSetArg(args[j], XtNx, commentX); j++;
\r
4839 XtSetArg(args[j], XtNy, commentY); j++;
\r
4840 XtSetValues(shell, args, j);
\r
4841 XtSetKeyboardFocus(shell, edit);
\r
4846 /* Used for analysis window and ICS input window */
\r
4847 Widget MiscCreate(name, text, mutable, callback, lines)
\r
4848 char *name, *text;
\r
4849 int /*Boolean*/ mutable;
\r
4850 XtCallbackProc callback;
\r
4854 Widget shell, layout, form, edit;
\r
4856 Dimension bw_width, pw_height, ew_height, w, h;
\r
4862 XtSetArg(args[j], XtNresizable, True); j++;
\r
4865 XtCreatePopupShell(name, topLevelShellWidgetClass,
\r
4866 shellWidget, args, j);
\r
4869 XtCreatePopupShell(name, transientShellWidgetClass,
\r
4870 shellWidget, args, j);
\r
4873 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
\r
4874 layoutArgs, XtNumber(layoutArgs));
\r
4876 XtCreateManagedWidget("form", formWidgetClass, layout,
\r
4877 formArgs, XtNumber(formArgs));
\r
4881 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
\r
4882 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
\r
4884 XtSetArg(args[j], XtNstring, text); j++;
\r
4885 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
4886 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
4887 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
4888 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r
4889 XtSetArg(args[j], XtNresizable, True); j++;
\r
4891 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
\r
4893 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
\r
4894 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
\r
4896 XtSetArg(args[j], XtNautoFill, True); j++;
\r
4897 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
\r
4899 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
\r
4901 XtRealizeWidget(shell);
\r
4904 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
4905 XtGetValues(boardWidget, args, j);
\r
4908 XtSetArg(args[j], XtNheight, &ew_height); j++;
\r
4909 XtGetValues(edit, args, j);
\r
4912 XtSetArg(args[j], XtNheight, &pw_height); j++;
\r
4913 XtGetValues(shell, args, j);
\r
4914 h = pw_height + (lines - 1) * ew_height;
\r
4915 w = bw_width - 16;
\r
4917 XSync(xDisplay, False);
\r
4919 /* This code seems to tickle an X bug if it is executed too soon
\r
4920 after xboard starts up. The coordinates get transformed as if
\r
4921 the main window was positioned at (0, 0).
\r
4923 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
\r
4925 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
\r
4926 RootWindowOfScreen(XtScreen(shellWidget)),
\r
4927 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
\r
4928 #endif /*!NOTDEF*/
\r
4931 if (y < 0) y = 0; /*avoid positioning top offscreen*/
\r
4934 XtSetArg(args[j], XtNheight, h); j++;
\r
4935 XtSetArg(args[j], XtNwidth, w); j++;
\r
4936 XtSetArg(args[j], XtNx, x); j++;
\r
4937 XtSetArg(args[j], XtNy, y); j++;
\r
4938 XtSetValues(shell, args, j);
\r
4944 static int savedIndex; /* gross that this is global */
\r
4946 void EditCommentPopUp(index, title, text)
\r
4948 char *title, *text;
\r
4954 savedIndex = index;
\r
4955 if (text == NULL) text = "";
\r
4957 if (editShell == NULL) {
\r
4959 CommentCreate(title, text, True, EditCommentCallback, 4);
\r
4960 XtRealizeWidget(editShell);
\r
4961 CatchDeleteWindow(editShell, "EditCommentPopDown");
\r
4963 edit = XtNameToWidget(editShell, "*form.text");
\r
4965 XtSetArg(args[j], XtNstring, text); j++;
\r
4966 XtSetValues(edit, args, j);
\r
4968 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
4969 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
4970 XtSetValues(editShell, args, j);
\r
4973 XtPopup(editShell, XtGrabNone);
\r
4977 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
\r
4978 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
\r
4982 void EditCommentCallback(w, client_data, call_data)
\r
4984 XtPointer client_data, call_data;
\r
4992 XtSetArg(args[j], XtNlabel, &name); j++;
\r
4993 XtGetValues(w, args, j);
\r
4995 if (strcmp(name, "ok") == 0) {
\r
4996 edit = XtNameToWidget(editShell, "*form.text");
\r
4998 XtSetArg(args[j], XtNstring, &val); j++;
\r
4999 XtGetValues(edit, args, j);
\r
5000 ReplaceComment(savedIndex, val);
\r
5001 EditCommentPopDown();
\r
5002 } else if (strcmp(name, "cancel") == 0) {
\r
5003 EditCommentPopDown();
\r
5004 } else if (strcmp(name, "clear") == 0) {
\r
5005 edit = XtNameToWidget(editShell, "*form.text");
\r
5006 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
\r
5007 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
\r
5011 void EditCommentPopDown()
\r
5016 if (!editUp) return;
\r
5018 XtSetArg(args[j], XtNx, &commentX); j++;
\r
5019 XtSetArg(args[j], XtNy, &commentY); j++;
\r
5020 XtSetArg(args[j], XtNheight, &commentH); j++;
\r
5021 XtSetArg(args[j], XtNwidth, &commentW); j++;
\r
5022 XtGetValues(editShell, args, j);
\r
5023 XtPopdown(editShell);
\r
5026 XtSetArg(args[j], XtNleftBitmap, None); j++;
\r
5027 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
\r
5031 void ICSInputBoxPopUp()
\r
5036 char *title = "ICS Input";
\r
5037 XtTranslations tr;
\r
5039 if (ICSInputShell == NULL) {
\r
5040 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
\r
5041 tr = XtParseTranslationTable(ICSInputTranslations);
\r
5042 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5043 XtOverrideTranslations(edit, tr);
\r
5044 XtRealizeWidget(ICSInputShell);
\r
5045 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
\r
5048 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5050 XtSetArg(args[j], XtNstring, ""); j++;
\r
5051 XtSetValues(edit, args, j);
\r
5053 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5054 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5055 XtSetValues(ICSInputShell, args, j);
\r
5058 XtPopup(ICSInputShell, XtGrabNone);
\r
5059 XtSetKeyboardFocus(ICSInputShell, edit);
\r
5061 ICSInputBoxUp = True;
\r
5063 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
\r
5064 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
\r
5068 void ICSInputSendText()
\r
5075 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5077 XtSetArg(args[j], XtNstring, &val); j++;
\r
5078 XtGetValues(edit, args, j);
\r
5079 SendMultiLineToICS(val);
\r
5080 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
\r
5081 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
\r
5084 void ICSInputBoxPopDown()
\r
5089 if (!ICSInputBoxUp) return;
\r
5091 XtPopdown(ICSInputShell);
\r
5092 ICSInputBoxUp = False;
\r
5094 XtSetArg(args[j], XtNleftBitmap, None); j++;
\r
5095 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
\r
5099 void CommentPopUp(title, text)
\r
5100 char *title, *text;
\r
5106 if (commentShell == NULL) {
\r
5108 CommentCreate(title, text, False, CommentCallback, 4);
\r
5109 XtRealizeWidget(commentShell);
\r
5110 CatchDeleteWindow(commentShell, "CommentPopDown");
\r
5112 edit = XtNameToWidget(commentShell, "*form.text");
\r
5114 XtSetArg(args[j], XtNstring, text); j++;
\r
5115 XtSetValues(edit, args, j);
\r
5117 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5118 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5119 XtSetValues(commentShell, args, j);
\r
5122 XtPopup(commentShell, XtGrabNone);
\r
5123 XSync(xDisplay, False);
\r
5128 void AnalysisPopUp(title, text)
\r
5129 char *title, *text;
\r
5135 if (analysisShell == NULL) {
\r
5136 analysisShell = MiscCreate(title, text, False, NULL, 4);
\r
5137 XtRealizeWidget(analysisShell);
\r
5138 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
\r
5141 edit = XtNameToWidget(analysisShell, "*form.text");
\r
5143 XtSetArg(args[j], XtNstring, text); j++;
\r
5144 XtSetValues(edit, args, j);
\r
5146 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5147 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5148 XtSetValues(analysisShell, args, j);
\r
5151 if (!analysisUp) {
\r
5152 XtPopup(analysisShell, XtGrabNone);
\r
5154 XSync(xDisplay, False);
\r
5156 analysisUp = True;
\r
5159 void CommentCallback(w, client_data, call_data)
\r
5161 XtPointer client_data, call_data;
\r
5168 XtSetArg(args[j], XtNlabel, &name); j++;
\r
5169 XtGetValues(w, args, j);
\r
5171 if (strcmp(name, "close") == 0) {
\r
5173 } else if (strcmp(name, "edit") == 0) {
\r
5175 EditCommentEvent();
\r
5180 void CommentPopDown()
\r
5185 if (!commentUp) return;
\r
5187 XtSetArg(args[j], XtNx, &commentX); j++;
\r
5188 XtSetArg(args[j], XtNy, &commentY); j++;
\r
5189 XtSetArg(args[j], XtNwidth, &commentW); j++;
\r
5190 XtSetArg(args[j], XtNheight, &commentH); j++;
\r
5191 XtGetValues(commentShell, args, j);
\r
5192 XtPopdown(commentShell);
\r
5193 XSync(xDisplay, False);
\r
5194 commentUp = False;
\r
5197 void AnalysisPopDown()
\r
5199 if (!analysisUp) return;
\r
5200 XtPopdown(analysisShell);
\r
5201 XSync(xDisplay, False);
\r
5202 analysisUp = False;
\r
5206 void FileNamePopUp(label, def, proc, openMode)
\r
5213 Widget popup, layout, dialog, edit;
\r
5214 Window root, child;
\r
5217 unsigned int mask;
\r
5219 fileProc = proc; /* I can't see a way not */
\r
5220 fileOpenMode = openMode; /* to use globals here */
\r
5223 XtSetArg(args[i], XtNresizable, True); i++;
\r
5224 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
\r
5225 fileNameShell = popup =
\r
5226 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
\r
5227 shellWidget, args, i);
\r
5230 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
\r
5231 layoutArgs, XtNumber(layoutArgs));
\r
5234 XtSetArg(args[i], XtNlabel, label); i++;
\r
5235 XtSetArg(args[i], XtNvalue, def); i++;
\r
5236 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
5237 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
\r
5240 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
\r
5241 XawDialogAddButton(dialog, "cancel", FileNameCallback,
\r
5242 (XtPointer) dialog);
\r
5244 XtRealizeWidget(popup);
\r
5245 CatchDeleteWindow(popup, "FileNamePopDown");
\r
5247 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
\r
5248 &x, &y, &win_x, &win_y, &mask);
\r
5250 XtSetArg(args[0], XtNx, x - 10);
\r
5251 XtSetArg(args[1], XtNy, y - 30);
\r
5252 XtSetValues(popup, args, 2);
\r
5254 XtPopup(popup, XtGrabExclusive);
\r
5255 filenameUp = True;
\r
5257 edit = XtNameToWidget(dialog, "*value");
\r
5258 XtSetKeyboardFocus(popup, edit);
\r
5261 void FileNamePopDown()
\r
5263 if (!filenameUp) return;
\r
5264 XtPopdown(fileNameShell);
\r
5265 XtDestroyWidget(fileNameShell);
\r
5266 filenameUp = False;
\r
5270 void FileNameCallback(w, client_data, call_data)
\r
5272 XtPointer client_data, call_data;
\r
5277 XtSetArg(args[0], XtNlabel, &name);
\r
5278 XtGetValues(w, args, 1);
\r
5280 if (strcmp(name, "cancel") == 0) {
\r
5281 FileNamePopDown();
\r
5285 FileNameAction(w, NULL, NULL, NULL);
\r
5288 void FileNameAction(w, event, prms, nprms)
\r
5294 char buf[MSG_SIZ];
\r
5297 char *p, *fullname;
\r
5300 name = XawDialogGetValueString(w = XtParent(w));
\r
5302 if ((name != NULL) && (*name != NULLCHAR)) {
\r
5303 strcpy(buf, name);
\r
5304 XtPopdown(w = XtParent(XtParent(w)));
\r
5305 XtDestroyWidget(w);
\r
5306 filenameUp = False;
\r
5308 p = strrchr(buf, ' ');
\r
5315 fullname = ExpandPathName(buf);
\r
5317 ErrorPopUp("Error", "Can't open file", FALSE);
\r
5320 f = fopen(fullname, fileOpenMode);
\r
5322 DisplayError("Failed to open file", errno);
\r
5324 (void) (*fileProc)(f, index, buf);
\r
5331 XtPopdown(w = XtParent(XtParent(w)));
\r
5332 XtDestroyWidget(w);
\r
5333 filenameUp = False;
\r
5337 void PromotionPopUp()
\r
5340 Widget dialog, layout;
\r
5342 Dimension bw_width, pw_width;
\r
5346 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
5347 XtGetValues(boardWidget, args, j);
\r
5350 XtSetArg(args[j], XtNresizable, True); j++;
\r
5352 XtCreatePopupShell("Promotion", transientShellWidgetClass,
\r
5353 shellWidget, args, j);
\r
5355 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
\r
5356 layoutArgs, XtNumber(layoutArgs));
\r
5359 XtSetArg(args[j], XtNlabel, "Promote pawn to what?"); j++;
\r
5360 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
5361 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
\r
5364 XawDialogAddButton(dialog, "Queen", PromotionCallback,
\r
5365 (XtPointer) dialog);
\r
5366 XawDialogAddButton(dialog, "Rook", PromotionCallback,
\r
5367 (XtPointer) dialog);
\r
5368 XawDialogAddButton(dialog, "Bishop", PromotionCallback,
\r
5369 (XtPointer) dialog);
\r
5370 XawDialogAddButton(dialog, "Knight", PromotionCallback,
\r
5371 (XtPointer) dialog);
\r
5372 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
\r
5373 gameInfo.variant == VariantGiveaway) {
\r
5374 XawDialogAddButton(dialog, "King", PromotionCallback,
\r
5375 (XtPointer) dialog);
\r
5377 XawDialogAddButton(dialog, "cancel", PromotionCallback,
\r
5378 (XtPointer) dialog);
\r
5380 XtRealizeWidget(promotionShell);
\r
5381 CatchDeleteWindow(promotionShell, "PromotionPopDown");
\r
5384 XtSetArg(args[j], XtNwidth, &pw_width); j++;
\r
5385 XtGetValues(promotionShell, args, j);
\r
5387 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
\r
5388 lineGap + squareSize/3 +
\r
5389 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
\r
5390 0 : 6*(squareSize + lineGap)), &x, &y);
\r
5393 XtSetArg(args[j], XtNx, x); j++;
\r
5394 XtSetArg(args[j], XtNy, y); j++;
\r
5395 XtSetValues(promotionShell, args, j);
\r
5397 XtPopup(promotionShell, XtGrabNone);
\r
5399 promotionUp = True;
\r
5402 void PromotionPopDown()
\r
5404 if (!promotionUp) return;
\r
5405 XtPopdown(promotionShell);
\r
5406 XtDestroyWidget(promotionShell);
\r
5407 promotionUp = False;
\r
5410 void PromotionCallback(w, client_data, call_data)
\r
5412 XtPointer client_data, call_data;
\r
5418 XtSetArg(args[0], XtNlabel, &name);
\r
5419 XtGetValues(w, args, 1);
\r
5421 PromotionPopDown();
\r
5423 if (fromX == -1) return;
\r
5425 if (strcmp(name, "cancel") == 0) {
\r
5426 fromX = fromY = -1;
\r
5427 ClearHighlights();
\r
5429 } else if (strcmp(name, "Knight") == 0) {
\r
5432 promoChar = ToLower(name[0]);
\r
5435 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
\r
5437 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
5438 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
5439 fromX = fromY = -1;
\r
5443 void ErrorCallback(w, client_data, call_data)
\r
5445 XtPointer client_data, call_data;
\r
5448 XtPopdown(w = XtParent(XtParent(XtParent(w))));
\r
5449 XtDestroyWidget(w);
\r
5450 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
\r
5454 void ErrorPopDown()
\r
5456 if (!errorUp) return;
\r
5458 XtPopdown(errorShell);
\r
5459 XtDestroyWidget(errorShell);
\r
5460 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
\r
5463 void ErrorPopUp(title, label, modal)
\r
5464 char *title, *label;
\r
5468 Widget dialog, layout;
\r
5472 Dimension bw_width, pw_width;
\r
5473 Dimension pw_height;
\r
5477 XtSetArg(args[i], XtNresizable, True); i++;
\r
5478 XtSetArg(args[i], XtNtitle, title); i++;
\r
5480 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
\r
5481 shellWidget, args, i);
\r
5483 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
\r
5484 layoutArgs, XtNumber(layoutArgs));
\r
5487 XtSetArg(args[i], XtNlabel, label); i++;
\r
5488 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
5489 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
\r
5492 XawDialogAddButton(dialog, "ok", ErrorCallback, (XtPointer) dialog);
\r
5494 XtRealizeWidget(errorShell);
\r
5495 CatchDeleteWindow(errorShell, "ErrorPopDown");
\r
5498 XtSetArg(args[i], XtNwidth, &bw_width); i++;
\r
5499 XtGetValues(boardWidget, args, i);
\r
5501 XtSetArg(args[i], XtNwidth, &pw_width); i++;
\r
5502 XtSetArg(args[i], XtNheight, &pw_height); i++;
\r
5503 XtGetValues(errorShell, args, i);
\r
5506 /* This code seems to tickle an X bug if it is executed too soon
\r
5507 after xboard starts up. The coordinates get transformed as if
\r
5508 the main window was positioned at (0, 0).
\r
5510 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
\r
5511 0 - pw_height + squareSize / 3, &x, &y);
\r
5513 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
\r
5514 RootWindowOfScreen(XtScreen(boardWidget)),
\r
5515 (bw_width - pw_width) / 2,
\r
5516 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
\r
5520 if (y < 0) y = 0; /*avoid positioning top offscreen*/
\r
5523 XtSetArg(args[i], XtNx, x); i++;
\r
5524 XtSetArg(args[i], XtNy, y); i++;
\r
5525 XtSetValues(errorShell, args, i);
\r
5528 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
\r
5531 /* Disable all user input other than deleting the window */
\r
5532 static int frozen = 0;
\r
5535 if (frozen) return;
\r
5536 /* Grab by a widget that doesn't accept input */
\r
5537 XtAddGrab(messageWidget, TRUE, FALSE);
\r
5541 /* Undo a FreezeUI */
\r
5544 if (!frozen) return;
\r
5545 XtRemoveGrab(messageWidget);
\r
5549 char *ModeToWidgetName(mode)
\r
5553 case BeginningOfGame:
\r
5554 if (appData.icsActive)
\r
5555 return "menuMode.ICS Client";
\r
5556 else if (appData.noChessProgram ||
\r
5557 *appData.cmailGameName != NULLCHAR)
\r
5558 return "menuMode.Edit Game";
\r
5560 return "menuMode.Machine Black";
\r
5561 case MachinePlaysBlack:
\r
5562 return "menuMode.Machine Black";
\r
5563 case MachinePlaysWhite:
\r
5564 return "menuMode.Machine White";
\r
5566 return "menuMode.Analysis Mode";
\r
5568 return "menuMode.Analyze File";
\r
5569 case TwoMachinesPlay:
\r
5570 return "menuMode.Two Machines";
\r
5572 return "menuMode.Edit Game";
\r
5573 case PlayFromGameFile:
\r
5574 return "menuFile.Load Game";
\r
5575 case EditPosition:
\r
5576 return "menuMode.Edit Position";
\r
5578 return "menuMode.Training";
\r
5579 case IcsPlayingWhite:
\r
5580 case IcsPlayingBlack:
\r
5581 case IcsObserving:
\r
5583 case IcsExamining:
\r
5584 return "menuMode.ICS Client";
\r
5591 void ModeHighlight()
\r
5594 static int oldPausing = FALSE;
\r
5595 static GameMode oldmode = (GameMode) -1;
\r
5598 if (!boardWidget || !XtIsRealized(boardWidget)) return;
\r
5600 if (pausing != oldPausing) {
\r
5601 oldPausing = pausing;
\r
5603 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
5605 XtSetArg(args[0], XtNleftBitmap, None);
\r
5607 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
\r
5610 if (appData.showButtonBar) {
\r
5613 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
\r
5614 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
\r
5616 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
\r
5617 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
\r
5620 /* Always toggle, don't set. Previous code messes up when
\r
5621 invoked while the button is pressed, as releasing it
\r
5622 toggles the state again. */
\r
5624 Pixel oldbg, oldfg;
\r
5625 XtSetArg(args[0], XtNbackground, &oldbg);
\r
5626 XtSetArg(args[1], XtNforeground, &oldfg);
\r
5627 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
\r
5629 XtSetArg(args[0], XtNbackground, oldfg);
\r
5630 XtSetArg(args[1], XtNforeground, oldbg);
\r
5633 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
\r
5637 wname = ModeToWidgetName(oldmode);
\r
5638 if (wname != NULL) {
\r
5639 XtSetArg(args[0], XtNleftBitmap, None);
\r
5640 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
\r
5642 wname = ModeToWidgetName(gameMode);
\r
5643 if (wname != NULL) {
\r
5644 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
5645 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
\r
5647 oldmode = gameMode;
\r
5649 /* Maybe all the enables should be handled here, not just this one */
\r
5650 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
\r
5651 gameMode == Training || gameMode == PlayFromGameFile);
\r
5656 * Button/menu procedures
\r
5658 void ResetProc(w, event, prms, nprms)
\r
5665 AnalysisPopDown();
\r
5668 int LoadGamePopUp(f, gameNumber, title)
\r
5673 cmailMsgLoaded = FALSE;
\r
5674 if (gameNumber == 0) {
\r
5675 int error = GameListBuild(f);
\r
5677 DisplayError("Cannot build game list", error);
\r
5678 } else if (!ListEmpty(&gameList) &&
\r
5679 ((ListGame *) gameList.tailPred)->number > 1) {
\r
5680 GameListPopUp(f, title);
\r
5683 GameListDestroy();
\r
5686 return LoadGame(f, gameNumber, title, FALSE);
\r
5689 void LoadGameProc(w, event, prms, nprms)
\r
5695 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
5696 Reset(FALSE, TRUE);
\r
5698 FileNamePopUp("Load game file name?", "", LoadGamePopUp, "rb");
\r
5701 void LoadNextGameProc(w, event, prms, nprms)
\r
5710 void LoadPrevGameProc(w, event, prms, nprms)
\r
5719 void ReloadGameProc(w, event, prms, nprms)
\r
5728 void LoadNextPositionProc(w, event, prms, nprms)
\r
5734 ReloadPosition(1);
\r
5737 void LoadPrevPositionProc(w, event, prms, nprms)
\r
5743 ReloadPosition(-1);
\r
5746 void ReloadPositionProc(w, event, prms, nprms)
\r
5752 ReloadPosition(0);
\r
5755 void LoadPositionProc(w, event, prms, nprms)
\r
5761 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
5762 Reset(FALSE, TRUE);
\r
5764 FileNamePopUp("Load position file name?", "", LoadPosition, "rb");
\r
5767 void SaveGameProc(w, event, prms, nprms)
\r
5773 FileNamePopUp("Save game file name?",
\r
5774 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
\r
5778 void SavePositionProc(w, event, prms, nprms)
\r
5784 FileNamePopUp("Save position file name?",
\r
5785 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
\r
5786 SavePosition, "a");
\r
5789 void ReloadCmailMsgProc(w, event, prms, nprms)
\r
5795 ReloadCmailMsgEvent(FALSE);
\r
5798 void MailMoveProc(w, event, prms, nprms)
\r
5807 /* this variable is shared between CopyPositionProc and SendPositionSelection */
\r
5808 static char *selected_fen_position=NULL;
\r
5811 SendPositionSelection(Widget w, Atom *selection, Atom *target,
\r
5812 Atom *type_return, XtPointer *value_return,
\r
5813 unsigned long *length_return, int *format_return)
\r
5815 char *selection_tmp;
\r
5817 if (!selected_fen_position) return False; /* should never happen */
\r
5818 if (*target == XA_STRING){
\r
5819 /* note: since no XtSelectionDoneProc was registered, Xt will
\r
5820 * automatically call XtFree on the value returned. So have to
\r
5821 * make a copy of it allocated with XtMalloc */
\r
5822 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
\r
5823 strcpy(selection_tmp, selected_fen_position);
\r
5825 *value_return=selection_tmp;
\r
5826 *length_return=strlen(selection_tmp);
\r
5827 *type_return=XA_STRING;
\r
5828 *format_return = 8; /* bits per byte */
\r
5835 /* note: when called from menu all parameters are NULL, so no clue what the
\r
5836 * Widget which was clicked on was, or what the click event was
\r
5838 void CopyPositionProc(w, event, prms, nprms)
\r
5846 if (selected_fen_position) free(selected_fen_position);
\r
5847 selected_fen_position = (char *)PositionToFEN(currentMove,1);
\r
5848 if (!selected_fen_position) return;
\r
5849 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
\r
5851 SendPositionSelection,
\r
5852 NULL/* lose_ownership_proc */ ,
\r
5853 NULL/* transfer_done_proc */);
\r
5855 free(selected_fen_position);
\r
5856 selected_fen_position=NULL;
\r
5860 /* function called when the data to Paste is ready */
\r
5862 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
\r
5863 Atom *type, XtPointer value, unsigned long *len, int *format)
\r
5865 char *fenstr=value;
\r
5866 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
\r
5867 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
\r
5868 EditPositionPasteFEN(fenstr);
\r
5872 /* called when Paste Position button is pressed,
\r
5873 * all parameters will be NULL */
\r
5874 void PastePositionProc(w, event, prms, nprms)
\r
5880 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
\r
5881 /* (XtSelectionCallbackProc) */ PastePositionCB,
\r
5882 NULL, /* client_data passed to PastePositionCB */
\r
5884 /* better to use the time field from the event that triggered the
\r
5885 * call to this function, but that isn't trivial to get
\r
5893 SendGameSelection(Widget w, Atom *selection, Atom *target,
\r
5894 Atom *type_return, XtPointer *value_return,
\r
5895 unsigned long *length_return, int *format_return)
\r
5897 char *selection_tmp;
\r
5899 if (*target == XA_STRING){
\r
5900 FILE* f = fopen(gameCopyFilename, "r");
\r
5903 if (f == NULL) return False;
\r
5907 selection_tmp = XtMalloc(len + 1);
\r
5908 count = fread(selection_tmp, 1, len, f);
\r
5909 if (len != count) {
\r
5910 XtFree(selection_tmp);
\r
5913 selection_tmp[len] = NULLCHAR;
\r
5914 *value_return = selection_tmp;
\r
5915 *length_return = len;
\r
5916 *type_return = XA_STRING;
\r
5917 *format_return = 8; /* bits per byte */
\r
5924 /* note: when called from menu all parameters are NULL, so no clue what the
\r
5925 * Widget which was clicked on was, or what the click event was
\r
5927 void CopyGameProc(w, event, prms, nprms)
\r
5935 ret = SaveGameToFile(gameCopyFilename, FALSE);
\r
5938 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
\r
5940 SendGameSelection,
\r
5941 NULL/* lose_ownership_proc */ ,
\r
5942 NULL/* transfer_done_proc */);
\r
5945 /* function called when the data to Paste is ready */
\r
5947 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
\r
5948 Atom *type, XtPointer value, unsigned long *len, int *format)
\r
5951 if (value == NULL || *len == 0) {
\r
5952 return; /* nothing had been selected to copy */
\r
5954 f = fopen(gamePasteFilename, "w");
\r
5956 DisplayError("Can't open temp file", errno);
\r
5959 fwrite(value, 1, *len, f);
\r
5962 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
\r
5965 /* called when Paste Game button is pressed,
\r
5966 * all parameters will be NULL */
\r
5967 void PasteGameProc(w, event, prms, nprms)
\r
5973 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
\r
5974 /* (XtSelectionCallbackProc) */ PasteGameCB,
\r
5975 NULL, /* client_data passed to PasteGameCB */
\r
5977 /* better to use the time field from the event that triggered the
\r
5978 * call to this function, but that isn't trivial to get
\r
5986 void AutoSaveGame()
\r
5988 SaveGameProc(NULL, NULL, NULL, NULL);
\r
5992 void QuitProc(w, event, prms, nprms)
\r
6001 void PauseProc(w, event, prms, nprms)
\r
6011 void MachineBlackProc(w, event, prms, nprms)
\r
6017 MachineBlackEvent();
\r
6020 void MachineWhiteProc(w, event, prms, nprms)
\r
6026 MachineWhiteEvent();
\r
6029 void AnalyzeModeProc(w, event, prms, nprms)
\r
6035 if (!first.analysisSupport) {
\r
6036 char buf[MSG_SIZ];
\r
6037 sprintf(buf, "%s does not support analysis", first.tidy);
\r
6038 DisplayError(buf, 0);
\r
6041 if (!appData.showThinking)
\r
6042 ShowThinkingProc(w,event,prms,nprms);
\r
6044 AnalyzeModeEvent();
\r
6047 void AnalyzeFileProc(w, event, prms, nprms)
\r
6053 if (!first.analysisSupport) {
\r
6054 char buf[MSG_SIZ];
\r
6055 sprintf(buf, "%s does not support analysis", first.tidy);
\r
6056 DisplayError(buf, 0);
\r
6059 Reset(FALSE, TRUE);
\r
6061 if (!appData.showThinking)
\r
6062 ShowThinkingProc(w,event,prms,nprms);
\r
6064 AnalyzeFileEvent();
\r
6065 FileNamePopUp("File to analyze", "", LoadGamePopUp, "rb");
\r
6066 AnalysisPeriodicEvent(1);
\r
6069 void TwoMachinesProc(w, event, prms, nprms)
\r
6075 TwoMachinesEvent();
\r
6078 void IcsClientProc(w, event, prms, nprms)
\r
6087 void EditGameProc(w, event, prms, nprms)
\r
6096 void EditPositionProc(w, event, prms, nprms)
\r
6102 EditPositionEvent();
\r
6105 void TrainingProc(w, event, prms, nprms)
\r
6114 void EditCommentProc(w, event, prms, nprms)
\r
6121 EditCommentPopDown();
\r
6123 EditCommentEvent();
\r
6127 void IcsInputBoxProc(w, event, prms, nprms)
\r
6133 if (ICSInputBoxUp) {
\r
6134 ICSInputBoxPopDown();
\r
6136 ICSInputBoxPopUp();
\r
6140 void AcceptProc(w, event, prms, nprms)
\r
6149 void DeclineProc(w, event, prms, nprms)
\r
6158 void RematchProc(w, event, prms, nprms)
\r
6167 void CallFlagProc(w, event, prms, nprms)
\r
6176 void DrawProc(w, event, prms, nprms)
\r
6185 void AbortProc(w, event, prms, nprms)
\r
6194 void AdjournProc(w, event, prms, nprms)
\r
6203 void ResignProc(w, event, prms, nprms)
\r
6212 void EnterKeyProc(w, event, prms, nprms)
\r
6218 if (ICSInputBoxUp == True)
\r
6219 ICSInputSendText();
\r
6222 void StopObservingProc(w, event, prms, nprms)
\r
6228 StopObservingEvent();
\r
6231 void StopExaminingProc(w, event, prms, nprms)
\r
6237 StopExaminingEvent();
\r
6241 void ForwardProc(w, event, prms, nprms)
\r
6251 void BackwardProc(w, event, prms, nprms)
\r
6260 void ToStartProc(w, event, prms, nprms)
\r
6269 void ToEndProc(w, event, prms, nprms)
\r
6278 void RevertProc(w, event, prms, nprms)
\r
6287 void TruncateGameProc(w, event, prms, nprms)
\r
6293 TruncateGameEvent();
\r
6295 void RetractMoveProc(w, event, prms, nprms)
\r
6301 RetractMoveEvent();
\r
6304 void MoveNowProc(w, event, prms, nprms)
\r
6314 void AlwaysQueenProc(w, event, prms, nprms)
\r
6322 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
\r
6324 if (appData.alwaysPromoteToQueen) {
\r
6325 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6327 XtSetArg(args[0], XtNleftBitmap, None);
\r
6329 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
\r
6333 void AnimateDraggingProc(w, event, prms, nprms)
\r
6341 appData.animateDragging = !appData.animateDragging;
\r
6343 if (appData.animateDragging) {
\r
6344 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6347 XtSetArg(args[0], XtNleftBitmap, None);
\r
6349 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
\r
6353 void AnimateMovingProc(w, event, prms, nprms)
\r
6361 appData.animate = !appData.animate;
\r
6363 if (appData.animate) {
\r
6364 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6367 XtSetArg(args[0], XtNleftBitmap, None);
\r
6369 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
\r
6373 void AutocommProc(w, event, prms, nprms)
\r
6381 appData.autoComment = !appData.autoComment;
\r
6383 if (appData.autoComment) {
\r
6384 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6386 XtSetArg(args[0], XtNleftBitmap, None);
\r
6388 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
\r
6393 void AutoflagProc(w, event, prms, nprms)
\r
6401 appData.autoCallFlag = !appData.autoCallFlag;
\r
6403 if (appData.autoCallFlag) {
\r
6404 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6406 XtSetArg(args[0], XtNleftBitmap, None);
\r
6408 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
\r
6412 void AutoflipProc(w, event, prms, nprms)
\r
6420 appData.autoFlipView = !appData.autoFlipView;
\r
6422 if (appData.autoFlipView) {
\r
6423 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6425 XtSetArg(args[0], XtNleftBitmap, None);
\r
6427 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
\r
6431 void AutobsProc(w, event, prms, nprms)
\r
6439 appData.autoObserve = !appData.autoObserve;
\r
6441 if (appData.autoObserve) {
\r
6442 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6444 XtSetArg(args[0], XtNleftBitmap, None);
\r
6446 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
\r
6450 void AutoraiseProc(w, event, prms, nprms)
\r
6458 appData.autoRaiseBoard = !appData.autoRaiseBoard;
\r
6460 if (appData.autoRaiseBoard) {
\r
6461 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6463 XtSetArg(args[0], XtNleftBitmap, None);
\r
6465 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
\r
6469 void AutosaveProc(w, event, prms, nprms)
\r
6477 appData.autoSaveGames = !appData.autoSaveGames;
\r
6479 if (appData.autoSaveGames) {
\r
6480 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6482 XtSetArg(args[0], XtNleftBitmap, None);
\r
6484 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
6488 void BlindfoldProc(w, event, prms, nprms)
\r
6496 appData.blindfold = !appData.blindfold;
\r
6498 if (appData.blindfold) {
\r
6499 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6501 XtSetArg(args[0], XtNleftBitmap, None);
\r
6503 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
\r
6506 DrawPosition(True, NULL);
\r
6509 void TestLegalityProc(w, event, prms, nprms)
\r
6517 appData.testLegality = !appData.testLegality;
\r
6519 if (appData.testLegality) {
\r
6520 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6522 XtSetArg(args[0], XtNleftBitmap, None);
\r
6524 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
\r
6529 void FlashMovesProc(w, event, prms, nprms)
\r
6537 if (appData.flashCount == 0) {
\r
6538 appData.flashCount = 3;
\r
6540 appData.flashCount = -appData.flashCount;
\r
6543 if (appData.flashCount > 0) {
\r
6544 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6546 XtSetArg(args[0], XtNleftBitmap, None);
\r
6548 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
\r
6552 void FlipViewProc(w, event, prms, nprms)
\r
6558 flipView = !flipView;
\r
6559 DrawPosition(True, NULL);
\r
6562 void GetMoveListProc(w, event, prms, nprms)
\r
6570 appData.getMoveList = !appData.getMoveList;
\r
6572 if (appData.getMoveList) {
\r
6573 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6574 GetMoveListEvent();
\r
6576 XtSetArg(args[0], XtNleftBitmap, None);
\r
6578 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
\r
6583 void HighlightDraggingProc(w, event, prms, nprms)
\r
6591 appData.highlightDragging = !appData.highlightDragging;
\r
6593 if (appData.highlightDragging) {
\r
6594 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6596 XtSetArg(args[0], XtNleftBitmap, None);
\r
6598 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6599 "menuOptions.Highlight Dragging"), args, 1);
\r
6603 void HighlightLastMoveProc(w, event, prms, nprms)
\r
6611 appData.highlightLastMove = !appData.highlightLastMove;
\r
6613 if (appData.highlightLastMove) {
\r
6614 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6616 XtSetArg(args[0], XtNleftBitmap, None);
\r
6618 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6619 "menuOptions.Highlight Last Move"), args, 1);
\r
6622 void IcsAlarmProc(w, event, prms, nprms)
\r
6630 appData.icsAlarm = !appData.icsAlarm;
\r
6632 if (appData.icsAlarm) {
\r
6633 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6635 XtSetArg(args[0], XtNleftBitmap, None);
\r
6637 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6638 "menuOptions.ICS Alarm"), args, 1);
\r
6641 void MoveSoundProc(w, event, prms, nprms)
\r
6649 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
\r
6651 if (appData.ringBellAfterMoves) {
\r
6652 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6654 XtSetArg(args[0], XtNleftBitmap, None);
\r
6656 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
\r
6661 void OldSaveStyleProc(w, event, prms, nprms)
\r
6669 appData.oldSaveStyle = !appData.oldSaveStyle;
\r
6671 if (appData.oldSaveStyle) {
\r
6672 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6674 XtSetArg(args[0], XtNleftBitmap, None);
\r
6676 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
\r
6680 void PeriodicUpdatesProc(w, event, prms, nprms)
\r
6688 PeriodicUpdatesEvent(!appData.periodicUpdates);
\r
6690 if (appData.periodicUpdates) {
\r
6691 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6693 XtSetArg(args[0], XtNleftBitmap, None);
\r
6695 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
\r
6699 void PonderNextMoveProc(w, event, prms, nprms)
\r
6707 PonderNextMoveEvent(!appData.ponderNextMove);
\r
6709 if (appData.ponderNextMove) {
\r
6710 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6712 XtSetArg(args[0], XtNleftBitmap, None);
\r
6714 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
\r
6718 void PopupExitMessageProc(w, event, prms, nprms)
\r
6726 appData.popupExitMessage = !appData.popupExitMessage;
\r
6728 if (appData.popupExitMessage) {
\r
6729 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6731 XtSetArg(args[0], XtNleftBitmap, None);
\r
6733 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6734 "menuOptions.Popup Exit Message"), args, 1);
\r
6737 void PopupMoveErrorsProc(w, event, prms, nprms)
\r
6745 appData.popupMoveErrors = !appData.popupMoveErrors;
\r
6747 if (appData.popupMoveErrors) {
\r
6748 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6750 XtSetArg(args[0], XtNleftBitmap, None);
\r
6752 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
\r
6756 void PremoveProc(w, event, prms, nprms)
\r
6764 appData.premove = !appData.premove;
\r
6766 if (appData.premove) {
\r
6767 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6769 XtSetArg(args[0], XtNleftBitmap, None);
\r
6771 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6772 "menuOptions.Premove"), args, 1);
\r
6775 void QuietPlayProc(w, event, prms, nprms)
\r
6783 appData.quietPlay = !appData.quietPlay;
\r
6785 if (appData.quietPlay) {
\r
6786 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6788 XtSetArg(args[0], XtNleftBitmap, None);
\r
6790 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
\r
6794 void ShowCoordsProc(w, event, prms, nprms)
\r
6802 appData.showCoords = !appData.showCoords;
\r
6804 if (appData.showCoords) {
\r
6805 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6807 XtSetArg(args[0], XtNleftBitmap, None);
\r
6809 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
\r
6812 DrawPosition(True, NULL);
\r
6815 void ShowThinkingProc(w, event, prms, nprms)
\r
6823 ShowThinkingEvent(!appData.showThinking);
\r
6825 if (appData.showThinking) {
\r
6826 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6828 XtSetArg(args[0], XtNleftBitmap, None);
\r
6830 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
\r
6834 void InfoProc(w, event, prms, nprms)
\r
6840 char buf[MSG_SIZ];
\r
6841 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
\r
6842 INFODIR, INFOFILE);
\r
6846 void ManProc(w, event, prms, nprms)
\r
6852 char buf[MSG_SIZ];
\r
6854 if (nprms && *nprms > 0)
\r
6858 sprintf(buf, "xterm -e man %s &", name);
\r
6862 void HintProc(w, event, prms, nprms)
\r
6871 void BookProc(w, event, prms, nprms)
\r
6880 void AboutProc(w, event, prms, nprms)
\r
6886 char buf[MSG_SIZ];
\r
6888 char *zippy = " (with Zippy code)";
\r
6892 sprintf(buf, "%s%s\n\n%s\n%s\n\n%s%s\n%s",
\r
6893 programVersion, zippy,
\r
6894 "Copyright 1991 Digital Equipment Corporation",
\r
6895 "Enhancements Copyright 1992-2001 Free Software Foundation",
\r
6896 PRODUCT, " is free software and carries NO WARRANTY;",
\r
6897 "see the file COPYING for more information.");
\r
6898 ErrorPopUp("About XBoard", buf, FALSE);
\r
6901 void DebugProc(w, event, prms, nprms)
\r
6907 appData.debugMode = !appData.debugMode;
\r
6910 void AboutGameProc(w, event, prms, nprms)
\r
6919 void NothingProc(w, event, prms, nprms)
\r
6928 void Iconify(w, event, prms, nprms)
\r
6936 fromX = fromY = -1;
\r
6937 XtSetArg(args[0], XtNiconic, True);
\r
6938 XtSetValues(shellWidget, args, 1);
\r
6941 void DisplayMessage(message, extMessage)
\r
6942 char *message, *extMessage;
\r
6944 char buf[MSG_SIZ];
\r
6949 sprintf(buf, "%s %s", message, extMessage);
\r
6952 message = extMessage;
\r
6955 XtSetArg(arg, XtNlabel, message);
\r
6956 XtSetValues(messageWidget, &arg, 1);
\r
6959 void DisplayTitle(text)
\r
6964 char title[MSG_SIZ];
\r
6965 char icon[MSG_SIZ];
\r
6967 if (text == NULL) text = "";
\r
6969 if (appData.titleInWindow) {
\r
6971 XtSetArg(args[i], XtNlabel, text); i++;
\r
6972 XtSetValues(titleWidget, args, i);
\r
6975 if (*text != NULLCHAR) {
\r
6976 strcpy(icon, text);
\r
6977 strcpy(title, text);
\r
6978 } else if (appData.icsActive) {
\r
6979 sprintf(icon, "%s", appData.icsHost);
\r
6980 sprintf(title, "%s: %s", programName, appData.icsHost);
\r
6981 } else if (appData.cmailGameName[0] != NULLCHAR) {
\r
6982 sprintf(icon, "%s", "CMail");
\r
6983 sprintf(title, "%s: %s", programName, "CMail");
\r
6984 } else if (appData.noChessProgram) {
\r
6985 strcpy(icon, programName);
\r
6986 strcpy(title, programName);
\r
6988 strcpy(icon, first.tidy);
\r
6989 sprintf(title, "%s: %s", programName, first.tidy);
\r
6992 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
\r
6993 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
\r
6994 XtSetValues(shellWidget, args, i);
\r
6998 void DisplayError(message, error)
\r
7002 char buf[MSG_SIZ];
\r
7005 if (appData.debugMode || appData.matchMode) {
\r
7006 fprintf(stderr, "%s: %s\n", programName, message);
\r
7009 if (appData.debugMode || appData.matchMode) {
\r
7010 fprintf(stderr, "%s: %s: %s\n",
\r
7011 programName, message, strerror(error));
\r
7013 sprintf(buf, "%s: %s", message, strerror(error));
\r
7016 ErrorPopUp("Error", message, FALSE);
\r
7020 void DisplayMoveError(message)
\r
7023 fromX = fromY = -1;
\r
7024 ClearHighlights();
\r
7025 DrawPosition(FALSE, NULL);
\r
7026 if (appData.debugMode || appData.matchMode) {
\r
7027 fprintf(stderr, "%s: %s\n", programName, message);
\r
7029 if (appData.popupMoveErrors) {
\r
7030 ErrorPopUp("Error", message, FALSE);
\r
7032 DisplayMessage(message, "");
\r
7037 void DisplayFatalError(message, error, status)
\r
7039 int error, status;
\r
7041 char buf[MSG_SIZ];
\r
7043 errorExitStatus = status;
\r
7045 fprintf(stderr, "%s: %s\n", programName, message);
\r
7047 fprintf(stderr, "%s: %s: %s\n",
\r
7048 programName, message, strerror(error));
\r
7049 sprintf(buf, "%s: %s", message, strerror(error));
\r
7052 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
\r
7053 ErrorPopUp(status ? "Fatal Error" : "Exiting", message, TRUE);
\r
7055 ExitEvent(status);
\r
7059 void DisplayInformation(message)
\r
7063 ErrorPopUp("Information", message, TRUE);
\r
7066 void DisplayNote(message)
\r
7070 ErrorPopUp("Note", message, FALSE);
\r
7074 NullXErrorCheck(dpy, error_event)
\r
7076 XErrorEvent *error_event;
\r
7081 void DisplayIcsInteractionTitle(message)
\r
7084 if (oldICSInteractionTitle == NULL) {
\r
7085 /* Magic to find the old window title, adapted from vim */
\r
7086 char *wina = getenv("WINDOWID");
\r
7087 if (wina != NULL) {
\r
7088 Window win = (Window) atoi(wina);
\r
7089 Window root, parent, *children;
\r
7090 unsigned int nchildren;
\r
7091 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
\r
7093 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
\r
7094 if (!XQueryTree(xDisplay, win, &root, &parent,
\r
7095 &children, &nchildren)) break;
\r
7096 if (children) XFree((void *)children);
\r
7097 if (parent == root || parent == 0) break;
\r
7100 XSetErrorHandler(oldHandler);
\r
7102 if (oldICSInteractionTitle == NULL) {
\r
7103 oldICSInteractionTitle = "xterm";
\r
7106 printf("\033]0;%s\007", message);
\r
7110 char pendingReplyPrefix[MSG_SIZ];
\r
7111 ProcRef pendingReplyPR;
\r
7113 void AskQuestionProc(w, event, prms, nprms)
\r
7119 if (*nprms != 4) {
\r
7120 fprintf(stderr, "AskQuestionProc needed 4 parameters, got %d\n",
\r
7124 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
\r
7127 void AskQuestionPopDown()
\r
7129 if (!askQuestionUp) return;
\r
7130 XtPopdown(askQuestionShell);
\r
7131 XtDestroyWidget(askQuestionShell);
\r
7132 askQuestionUp = False;
\r
7135 void AskQuestionReplyAction(w, event, prms, nprms)
\r
7141 char buf[MSG_SIZ];
\r
7145 reply = XawDialogGetValueString(w = XtParent(w));
\r
7146 strcpy(buf, pendingReplyPrefix);
\r
7147 if (*buf) strcat(buf, " ");
\r
7148 strcat(buf, reply);
\r
7149 strcat(buf, "\n");
\r
7150 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
\r
7151 AskQuestionPopDown();
\r
7153 if (err) DisplayFatalError("Error writing to chess program", err, 0);
\r
7156 void AskQuestionCallback(w, client_data, call_data)
\r
7158 XtPointer client_data, call_data;
\r
7163 XtSetArg(args[0], XtNlabel, &name);
\r
7164 XtGetValues(w, args, 1);
\r
7166 if (strcmp(name, "cancel") == 0) {
\r
7167 AskQuestionPopDown();
\r
7169 AskQuestionReplyAction(w, NULL, NULL, NULL);
\r
7173 void AskQuestion(title, question, replyPrefix, pr)
\r
7174 char *title, *question, *replyPrefix;
\r
7178 Widget popup, layout, dialog, edit;
\r
7179 Window root, child;
\r
7182 unsigned int mask;
\r
7184 strcpy(pendingReplyPrefix, replyPrefix);
\r
7185 pendingReplyPR = pr;
\r
7188 XtSetArg(args[i], XtNresizable, True); i++;
\r
7189 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
\r
7190 askQuestionShell = popup =
\r
7191 XtCreatePopupShell(title, transientShellWidgetClass,
\r
7192 shellWidget, args, i);
\r
7195 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
\r
7196 layoutArgs, XtNumber(layoutArgs));
\r
7199 XtSetArg(args[i], XtNlabel, question); i++;
\r
7200 XtSetArg(args[i], XtNvalue, ""); i++;
\r
7201 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
7202 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
\r
7205 XawDialogAddButton(dialog, "enter", AskQuestionCallback,
\r
7206 (XtPointer) dialog);
\r
7207 XawDialogAddButton(dialog, "cancel", AskQuestionCallback,
\r
7208 (XtPointer) dialog);
\r
7210 XtRealizeWidget(popup);
\r
7211 CatchDeleteWindow(popup, "AskQuestionPopDown");
\r
7213 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
\r
7214 &x, &y, &win_x, &win_y, &mask);
\r
7216 XtSetArg(args[0], XtNx, x - 10);
\r
7217 XtSetArg(args[1], XtNy, y - 30);
\r
7218 XtSetValues(popup, args, 2);
\r
7220 XtPopup(popup, XtGrabExclusive);
\r
7221 askQuestionUp = True;
\r
7223 edit = XtNameToWidget(dialog, "*value");
\r
7224 XtSetKeyboardFocus(popup, edit);
\r
7232 if (*name == NULLCHAR) {
\r
7234 } else if (strcmp(name, "$") == 0) {
\r
7235 putc(BELLCHAR, stderr);
\r
7238 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
\r
7246 PlaySound(appData.soundMove);
\r
7252 PlaySound(appData.soundIcsWin);
\r
7256 PlayIcsLossSound()
\r
7258 PlaySound(appData.soundIcsLoss);
\r
7262 PlayIcsDrawSound()
\r
7264 PlaySound(appData.soundIcsDraw);
\r
7268 PlayIcsUnfinishedSound()
\r
7270 PlaySound(appData.soundIcsUnfinished);
\r
7276 PlaySound(appData.soundIcsAlarm);
\r
7282 system("stty echo");
\r
7288 system("stty -echo");
\r
7292 Colorize(cc, continuation)
\r
7296 char buf[MSG_SIZ];
\r
7297 int count, outCount, error;
\r
7299 if (textColors[(int)cc].bg > 0) {
\r
7300 if (textColors[(int)cc].fg > 0) {
\r
7301 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
\r
7302 textColors[(int)cc].fg, textColors[(int)cc].bg);
\r
7304 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
\r
7305 textColors[(int)cc].bg);
\r
7308 if (textColors[(int)cc].fg > 0) {
\r
7309 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
\r
7310 textColors[(int)cc].fg);
\r
7312 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
\r
7315 count = strlen(buf);
\r
7316 outCount = OutputToProcess(NoProc, buf, count, &error);
\r
7317 if (outCount < count) {
\r
7318 DisplayFatalError("Error writing to display", error, 1);
\r
7321 if (continuation) return;
\r
7324 PlaySound(appData.soundShout);
\r
7327 PlaySound(appData.soundSShout);
\r
7329 case ColorChannel1:
\r
7330 PlaySound(appData.soundChannel1);
\r
7332 case ColorChannel:
\r
7333 PlaySound(appData.soundChannel);
\r
7336 PlaySound(appData.soundKibitz);
\r
7339 PlaySound(appData.soundTell);
\r
7341 case ColorChallenge:
\r
7342 PlaySound(appData.soundChallenge);
\r
7344 case ColorRequest:
\r
7345 PlaySound(appData.soundRequest);
\r
7348 PlaySound(appData.soundSeek);
\r
7359 return getpwuid(getuid())->pw_name;
\r
7362 static char *ExpandPathName(path)
\r
7365 static char static_buf[2000];
\r
7366 char *d, *s, buf[2000];
\r
7367 struct passwd *pwd;
\r
7372 while (*s && isspace(*s))
\r
7377 return static_buf;
\r
7381 if (*(s+1) == '/') {
\r
7382 strcpy(d, getpwuid(getuid())->pw_dir);
\r
7387 *strchr(buf, '/') = 0;
\r
7388 pwd = getpwnam(buf);
\r
7391 fprintf(stderr, "ERROR: Unknown user %s (in path %s)\n",
\r
7395 strcpy(d, pwd->pw_dir);
\r
7396 strcat(d, strchr(s+1, '/'));
\r
7402 return static_buf;
\r
7407 static char host_name[MSG_SIZ];
\r
7409 #if HAVE_GETHOSTNAME
\r
7410 gethostname(host_name, MSG_SIZ);
\r
7412 #else /* not HAVE_GETHOSTNAME */
\r
7413 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
\r
7414 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
\r
7416 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
\r
7417 return "localhost";
\r
7418 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
\r
7419 #endif /* not HAVE_GETHOSTNAME */
\r
7422 XtIntervalId delayedEventTimerXID = 0;
\r
7423 DelayedEventCallback delayedEventCallback = 0;
\r
7426 FireDelayedEvent()
\r
7428 delayedEventTimerXID = 0;
\r
7429 delayedEventCallback();
\r
7433 ScheduleDelayedEvent(cb, millisec)
\r
7434 DelayedEventCallback cb; long millisec;
\r
7436 delayedEventCallback = cb;
\r
7437 delayedEventTimerXID =
\r
7438 XtAppAddTimeOut(appContext, millisec,
\r
7439 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
\r
7442 DelayedEventCallback
\r
7445 if (delayedEventTimerXID) {
\r
7446 return delayedEventCallback;
\r
7453 CancelDelayedEvent()
\r
7455 if (delayedEventTimerXID) {
\r
7456 XtRemoveTimeOut(delayedEventTimerXID);
\r
7457 delayedEventTimerXID = 0;
\r
7461 XtIntervalId loadGameTimerXID = 0;
\r
7463 int LoadGameTimerRunning()
\r
7465 return loadGameTimerXID != 0;
\r
7468 int StopLoadGameTimer()
\r
7470 if (loadGameTimerXID != 0) {
\r
7471 XtRemoveTimeOut(loadGameTimerXID);
\r
7472 loadGameTimerXID = 0;
\r
7480 LoadGameTimerCallback(arg, id)
\r
7484 loadGameTimerXID = 0;
\r
7485 AutoPlayGameLoop();
\r
7489 StartLoadGameTimer(millisec)
\r
7492 loadGameTimerXID =
\r
7493 XtAppAddTimeOut(appContext, millisec,
\r
7494 (XtTimerCallbackProc) LoadGameTimerCallback,
\r
7498 XtIntervalId analysisClockXID = 0;
\r
7501 AnalysisClockCallback(arg, id)
\r
7505 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
7506 AnalysisPeriodicEvent(0);
\r
7507 StartAnalysisClock();
\r
7512 StartAnalysisClock()
\r
7514 analysisClockXID =
\r
7515 XtAppAddTimeOut(appContext, 2000,
\r
7516 (XtTimerCallbackProc) AnalysisClockCallback,
\r
7520 XtIntervalId clockTimerXID = 0;
\r
7522 int ClockTimerRunning()
\r
7524 return clockTimerXID != 0;
\r
7527 int StopClockTimer()
\r
7529 if (clockTimerXID != 0) {
\r
7530 XtRemoveTimeOut(clockTimerXID);
\r
7531 clockTimerXID = 0;
\r
7539 ClockTimerCallback(arg, id)
\r
7543 clockTimerXID = 0;
\r
7544 DecrementClocks();
\r
7548 StartClockTimer(millisec)
\r
7552 XtAppAddTimeOut(appContext, millisec,
\r
7553 (XtTimerCallbackProc) ClockTimerCallback,
\r
7558 DisplayTimerLabel(w, color, timer, highlight)
\r
7564 char buf[MSG_SIZ];
\r
7567 if (appData.clockMode) {
\r
7568 sprintf(buf, "%s: %s", color, TimeString(timer));
\r
7569 XtSetArg(args[0], XtNlabel, buf);
\r
7571 sprintf(buf, "%s ", color);
\r
7572 XtSetArg(args[0], XtNlabel, buf);
\r
7576 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
\r
7577 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
\r
7579 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
\r
7580 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
\r
7583 XtSetValues(w, args, 3);
\r
7587 DisplayWhiteClock(timeRemaining, highlight)
\r
7588 long timeRemaining;
\r
7592 DisplayTimerLabel(whiteTimerWidget, "White", timeRemaining, highlight);
\r
7593 if (highlight && iconPixmap == bIconPixmap) {
\r
7594 iconPixmap = wIconPixmap;
\r
7595 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
\r
7596 XtSetValues(shellWidget, args, 1);
\r
7601 DisplayBlackClock(timeRemaining, highlight)
\r
7602 long timeRemaining;
\r
7606 DisplayTimerLabel(blackTimerWidget, "Black", timeRemaining, highlight);
\r
7607 if (highlight && iconPixmap == wIconPixmap) {
\r
7608 iconPixmap = bIconPixmap;
\r
7609 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
\r
7610 XtSetValues(shellWidget, args, 1);
\r
7619 typedef int CPKind;
\r
7624 int fdTo, fdFrom;
\r
7628 int StartChildProcess(cmdLine, dir, pr)
\r
7633 char *argv[64], *p;
\r
7635 int to_prog[2], from_prog[2];
\r
7637 char buf[MSG_SIZ];
\r
7639 if (appData.debugMode) {
\r
7640 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
\r
7643 /* We do NOT feed the cmdLine to the shell; we just
\r
7644 parse it into blank-separated arguments in the
\r
7645 most simple-minded way possible.
\r
7648 strcpy(buf, cmdLine);
\r
7652 p = strchr(p, ' ');
\r
7653 if (p == NULL) break;
\r
7658 SetUpChildIO(to_prog, from_prog);
\r
7660 if ((pid = fork()) == 0) {
\r
7661 /* Child process */
\r
7662 dup2(to_prog[0], 0);
\r
7663 dup2(from_prog[1], 1);
\r
7664 close(to_prog[0]);
\r
7665 close(to_prog[1]);
\r
7666 close(from_prog[0]);
\r
7667 close(from_prog[1]);
\r
7668 dup2(1, fileno(stderr)); /* force stderr to the pipe */
\r
7670 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
\r
7675 execvp(argv[0], argv);
\r
7677 /* If we get here, exec failed */
\r
7682 /* Parent process */
\r
7683 close(to_prog[0]);
\r
7684 close(from_prog[1]);
\r
7686 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
7687 cp->kind = CPReal;
\r
7689 cp->fdFrom = from_prog[0];
\r
7690 cp->fdTo = to_prog[1];
\r
7691 *pr = (ProcRef) cp;
\r
7696 DestroyChildProcess(pr, signal)
\r
7700 ChildProc *cp = (ChildProc *) pr;
\r
7702 if (cp->kind != CPReal) return;
\r
7703 cp->kind = CPNone;
\r
7705 kill(cp->pid, SIGTERM);
\r
7707 /* Process is exiting either because of the kill or because of
\r
7708 a quit command sent by the backend; either way, wait for it to die.
\r
7711 close(cp->fdFrom);
\r
7716 InterruptChildProcess(pr)
\r
7719 ChildProc *cp = (ChildProc *) pr;
\r
7721 if (cp->kind != CPReal) return;
\r
7722 (void) kill(cp->pid, SIGINT); /* stop it thinking */
\r
7725 int OpenTelnet(host, port, pr)
\r
7730 char cmdLine[MSG_SIZ];
\r
7732 if (port[0] == NULLCHAR) {
\r
7733 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
\r
7735 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
\r
7737 return StartChildProcess(cmdLine, "", pr);
\r
7740 int OpenTCP(host, port, pr)
\r
7746 DisplayFatalError("Socket support is not configured in", 0, 2);
\r
7747 #else /* !OMIT_SOCKETS */
\r
7749 struct sockaddr_in sa;
\r
7750 struct hostent *hp;
\r
7751 unsigned short uport;
\r
7754 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
\r
7758 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
\r
7759 sa.sin_family = AF_INET;
\r
7760 sa.sin_addr.s_addr = INADDR_ANY;
\r
7761 uport = (unsigned short) 0;
\r
7762 sa.sin_port = htons(uport);
\r
7763 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
\r
7767 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
\r
7768 if (!(hp = gethostbyname(host))) {
\r
7769 int b0, b1, b2, b3;
\r
7770 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
\r
7771 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
\r
7772 hp->h_addrtype = AF_INET;
\r
7774 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
\r
7775 hp->h_addr_list[0] = (char *) malloc(4);
\r
7776 hp->h_addr_list[0][0] = b0;
\r
7777 hp->h_addr_list[0][1] = b1;
\r
7778 hp->h_addr_list[0][2] = b2;
\r
7779 hp->h_addr_list[0][3] = b3;
\r
7784 sa.sin_family = hp->h_addrtype;
\r
7785 uport = (unsigned short) atoi(port);
\r
7786 sa.sin_port = htons(uport);
\r
7787 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
\r
7789 if (connect(s, (struct sockaddr *) &sa,
\r
7790 sizeof(struct sockaddr_in)) < 0) {
\r
7794 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
7795 cp->kind = CPSock;
\r
7799 *pr = (ProcRef) cp;
\r
7801 #endif /* !OMIT_SOCKETS */
\r
7806 int OpenCommPort(name, pr)
\r
7813 fd = open(name, 2, 0);
\r
7814 if (fd < 0) return errno;
\r
7816 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
7817 cp->kind = CPComm;
\r
7821 *pr = (ProcRef) cp;
\r
7826 int OpenLoopback(pr)
\r
7830 int to[2], from[2];
\r
7832 SetUpChildIO(to, from);
\r
7834 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
7835 cp->kind = CPLoop;
\r
7837 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
\r
7839 *pr = (ProcRef) cp;
\r
7844 int OpenRcmd(host, user, cmd, pr)
\r
7845 char *host, *user, *cmd;
\r
7848 DisplayFatalError("internal rcmd not implemented for Unix", 0, 1);
\r
7852 #define INPUT_SOURCE_BUF_SIZE 8192
\r
7859 InputCallback func;
\r
7861 char buf[INPUT_SOURCE_BUF_SIZE];
\r
7866 DoInputCallback(closure, source, xid)
\r
7871 InputSource *is = (InputSource *) closure;
\r
7876 if (is->lineByLine) {
\r
7877 count = read(is->fd, is->unused,
\r
7878 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
\r
7880 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
\r
7883 is->unused += count;
\r
7885 while (p < is->unused) {
\r
7886 q = memchr(p, '\n', is->unused - p);
\r
7887 if (q == NULL) break;
\r
7889 (is->func)(is, is->closure, p, q - p, 0);
\r
7893 while (p < is->unused) {
\r
7898 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
\r
7903 (is->func)(is, is->closure, is->buf, count, error);
\r
7907 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
\r
7910 InputCallback func;
\r
7914 ChildProc *cp = (ChildProc *) pr;
\r
7916 is = (InputSource *) calloc(1, sizeof(InputSource));
\r
7917 is->lineByLine = lineByLine;
\r
7919 if (pr == NoProc) {
\r
7920 is->kind = CPReal;
\r
7921 is->fd = fileno(stdin);
\r
7923 is->kind = cp->kind;
\r
7924 is->fd = cp->fdFrom;
\r
7927 is->unused = is->buf;
\r
7930 is->xid = XtAppAddInput(appContext, is->fd,
\r
7931 (XtPointer) (XtInputReadMask),
\r
7932 (XtInputCallbackProc) DoInputCallback,
\r
7934 is->closure = closure;
\r
7935 return (InputSourceRef) is;
\r
7939 RemoveInputSource(isr)
\r
7940 InputSourceRef isr;
\r
7942 InputSource *is = (InputSource *) isr;
\r
7944 if (is->xid == 0) return;
\r
7945 XtRemoveInput(is->xid);
\r
7949 int OutputToProcess(pr, message, count, outError)
\r
7955 ChildProc *cp = (ChildProc *) pr;
\r
7959 outCount = fwrite(message, 1, count, stdout);
\r
7961 outCount = write(cp->fdTo, message, count);
\r
7963 if (outCount == -1)
\r
7964 *outError = errno;
\r
7971 /* Output message to process, with "ms" milliseconds of delay
\r
7972 between each character. This is needed when sending the logon
\r
7973 script to ICC, which for some reason doesn't like the
\r
7974 instantaneous send. */
\r
7975 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
\r
7982 ChildProc *cp = (ChildProc *) pr;
\r
7987 r = write(cp->fdTo, message++, 1);
\r
7989 *outError = errno;
\r
7994 TimeDelay(msdelay);
\r
8000 /**** Animation code by Hugh Fisher, DCS, ANU.
\r
8002 Known problem: if a window overlapping the board is
\r
8003 moved away while a piece is being animated underneath,
\r
8004 the newly exposed area won't be updated properly.
\r
8005 I can live with this.
\r
8007 Known problem: if you look carefully at the animation
\r
8008 of pieces in mono mode, they are being drawn as solid
\r
8009 shapes without interior detail while moving. Fixing
\r
8010 this would be a major complication for minimal return.
\r
8013 /* Masks for XPM pieces. Black and white pieces can have
\r
8014 different shapes, but in the interest of retaining my
\r
8015 sanity pieces must have the same outline on both light
\r
8016 and dark squares, and all pieces must use the same
\r
8017 background square colors/images. */
\r
8020 CreateAnimMasks (pieceDepth)
\r
8023 ChessSquare piece;
\r
8027 unsigned long plane;
\r
8030 /* Need a bitmap just to get a GC with right depth */
\r
8031 buf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8033 values.foreground = 1;
\r
8034 values.background = 0;
\r
8035 /* Don't use XtGetGC, not read only */
\r
8036 maskGC = XCreateGC(xDisplay, buf,
\r
8037 GCForeground | GCBackground, &values);
\r
8038 XFreePixmap(xDisplay, buf);
\r
8040 buf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8041 squareSize, squareSize, pieceDepth);
\r
8042 values.foreground = XBlackPixel(xDisplay, xScreen);
\r
8043 values.background = XWhitePixel(xDisplay, xScreen);
\r
8044 bufGC = XCreateGC(xDisplay, buf,
\r
8045 GCForeground | GCBackground, &values);
\r
8047 for (piece = WhitePawn; piece <= BlackKing; piece++) {
\r
8048 /* Begin with empty mask */
\r
8049 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
\r
8050 squareSize, squareSize, 1);
\r
8051 XSetFunction(xDisplay, maskGC, GXclear);
\r
8052 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
\r
8053 0, 0, squareSize, squareSize);
\r
8055 /* Take a copy of the piece */
\r
8060 XSetFunction(xDisplay, bufGC, GXcopy);
\r
8061 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
\r
8063 0, 0, squareSize, squareSize, 0, 0);
\r
8065 /* XOR the background (light) over the piece */
\r
8066 XSetFunction(xDisplay, bufGC, GXxor);
\r
8068 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
\r
8069 0, 0, squareSize, squareSize, 0, 0);
\r
8071 XSetForeground(xDisplay, bufGC, lightSquareColor);
\r
8072 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
\r
8075 /* We now have an inverted piece image with the background
\r
8076 erased. Construct mask by just selecting all the non-zero
\r
8077 pixels - no need to reconstruct the original image. */
\r
8078 XSetFunction(xDisplay, maskGC, GXor);
\r
8080 /* Might be quicker to download an XImage and create bitmap
\r
8081 data from it rather than this N copies per piece, but it
\r
8082 only takes a fraction of a second and there is a much
\r
8083 longer delay for loading the pieces. */
\r
8084 for (n = 0; n < pieceDepth; n ++) {
\r
8085 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
\r
8086 0, 0, squareSize, squareSize,
\r
8088 plane = plane << 1;
\r
8092 XFreePixmap(xDisplay, buf);
\r
8093 XFreeGC(xDisplay, bufGC);
\r
8094 XFreeGC(xDisplay, maskGC);
\r
8098 InitAnimState (anim, info)
\r
8100 XWindowAttributes * info;
\r
8105 /* Each buffer is square size, same depth as window */
\r
8106 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8107 squareSize, squareSize, info->depth);
\r
8108 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8109 squareSize, squareSize, info->depth);
\r
8111 /* Create a plain GC for blitting */
\r
8112 mask = GCForeground | GCBackground | GCFunction |
\r
8113 GCPlaneMask | GCGraphicsExposures;
\r
8114 values.foreground = XBlackPixel(xDisplay, xScreen);
\r
8115 values.background = XWhitePixel(xDisplay, xScreen);
\r
8116 values.function = GXcopy;
\r
8117 values.plane_mask = AllPlanes;
\r
8118 values.graphics_exposures = False;
\r
8119 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
\r
8121 /* Piece will be copied from an existing context at
\r
8122 the start of each new animation/drag. */
\r
8123 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
\r
8125 /* Outline will be a read-only copy of an existing */
\r
8126 anim->outlineGC = None;
\r
8132 static int done = 0;
\r
8133 XWindowAttributes info;
\r
8137 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
\r
8139 InitAnimState(&game, &info);
\r
8140 InitAnimState(&player, &info);
\r
8142 /* For XPM pieces, we need bitmaps to use as masks. */
\r
8144 CreateAnimMasks(info.depth);
\r
8147 #ifndef HAVE_USLEEP
\r
8149 static Boolean frameWaiting;
\r
8151 static RETSIGTYPE FrameAlarm (sig)
\r
8154 frameWaiting = False;
\r
8155 /* In case System-V style signals. Needed?? */
\r
8156 signal(SIGALRM, FrameAlarm);
\r
8163 struct itimerval delay;
\r
8165 XSync(xDisplay, False);
\r
8168 frameWaiting = True;
\r
8169 signal(SIGALRM, FrameAlarm);
\r
8170 delay.it_interval.tv_sec =
\r
8171 delay.it_value.tv_sec = time / 1000;
\r
8172 delay.it_interval.tv_usec =
\r
8173 delay.it_value.tv_usec = (time % 1000) * 1000;
\r
8174 setitimer(ITIMER_REAL, &delay, NULL);
\r
8176 /* Ugh -- busy-wait! --tpm */
\r
8177 while (frameWaiting);
\r
8179 while (frameWaiting) pause();
\r
8181 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
\r
8182 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
\r
8183 setitimer(ITIMER_REAL, &delay, NULL);
\r
8193 XSync(xDisplay, False);
\r
8195 usleep(time * 1000);
\r
8200 /* Convert board position to corner of screen rect and color */
\r
8203 ScreenSquare(column, row, pt, color)
\r
8204 int column; int row; XPoint * pt; int * color;
\r
8207 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
8208 pt->y = lineGap + row * (squareSize + lineGap);
\r
8210 pt->x = lineGap + column * (squareSize + lineGap);
\r
8211 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
8213 *color = SquareColor(row, column);
\r
8216 /* Convert window coords to square */
\r
8219 BoardSquare(x, y, column, row)
\r
8220 int x; int y; int * column; int * row;
\r
8222 *column = EventToSquare(x, BOARD_WIDTH);
\r
8223 if (flipView && *column >= 0)
\r
8224 *column = BOARD_WIDTH - 1 - *column;
\r
8225 *row = EventToSquare(y, BOARD_HEIGHT);
\r
8226 if (!flipView && *row >= 0)
\r
8227 *row = BOARD_HEIGHT - 1 - *row;
\r
8232 #undef Max /* just in case */
\r
8234 #define Max(a, b) ((a) > (b) ? (a) : (b))
\r
8235 #define Min(a, b) ((a) < (b) ? (a) : (b))
\r
8238 SetRect(rect, x, y, width, height)
\r
8239 XRectangle * rect; int x; int y; int width; int height;
\r
8243 rect->width = width;
\r
8244 rect->height = height;
\r
8247 /* Test if two frames overlap. If they do, return
\r
8248 intersection rect within old and location of
\r
8249 that rect within new. */
\r
8252 Intersect(old, new, size, area, pt)
\r
8253 XPoint * old; XPoint * new;
\r
8254 int size; XRectangle * area; XPoint * pt;
\r
8256 if (old->x > new->x + size || new->x > old->x + size ||
\r
8257 old->y > new->y + size || new->y > old->y + size) {
\r
8260 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
\r
8261 size - abs(old->x - new->x), size - abs(old->y - new->y));
\r
8262 pt->x = Max(old->x - new->x, 0);
\r
8263 pt->y = Max(old->y - new->y, 0);
\r
8268 /* For two overlapping frames, return the rect(s)
\r
8269 in the old that do not intersect with the new. */
\r
8272 CalcUpdateRects(old, new, size, update, nUpdates)
\r
8273 XPoint * old; XPoint * new; int size;
\r
8274 XRectangle update[]; int * nUpdates;
\r
8278 /* If old = new (shouldn't happen) then nothing to draw */
\r
8279 if (old->x == new->x && old->y == new->y) {
\r
8283 /* Work out what bits overlap. Since we know the rects
\r
8284 are the same size we don't need a full intersect calc. */
\r
8286 /* Top or bottom edge? */
\r
8287 if (new->y > old->y) {
\r
8288 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
\r
8290 } else if (old->y > new->y) {
\r
8291 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
\r
8292 size, old->y - new->y);
\r
8295 /* Left or right edge - don't overlap any update calculated above. */
\r
8296 if (new->x > old->x) {
\r
8297 SetRect(&(update[count]), old->x, Max(new->y, old->y),
\r
8298 new->x - old->x, size - abs(new->y - old->y));
\r
8300 } else if (old->x > new->x) {
\r
8301 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
\r
8302 old->x - new->x, size - abs(new->y - old->y));
\r
8306 *nUpdates = count;
\r
8309 /* Generate a series of frame coords from start->mid->finish.
\r
8310 The movement rate doubles until the half way point is
\r
8311 reached, then halves back down to the final destination,
\r
8312 which gives a nice slow in/out effect. The algorithmn
\r
8313 may seem to generate too many intermediates for short
\r
8314 moves, but remember that the purpose is to attract the
\r
8315 viewers attention to the piece about to be moved and
\r
8316 then to where it ends up. Too few frames would be less
\r
8320 Tween(start, mid, finish, factor, frames, nFrames)
\r
8321 XPoint * start; XPoint * mid;
\r
8322 XPoint * finish; int factor;
\r
8323 XPoint frames[]; int * nFrames;
\r
8325 int fraction, n, count;
\r
8329 /* Slow in, stepping 1/16th, then 1/8th, ... */
\r
8331 for (n = 0; n < factor; n++)
\r
8333 for (n = 0; n < factor; n++) {
\r
8334 frames[count].x = start->x + (mid->x - start->x) / fraction;
\r
8335 frames[count].y = start->y + (mid->y - start->y) / fraction;
\r
8337 fraction = fraction / 2;
\r
8341 frames[count] = *mid;
\r
8344 /* Slow out, stepping 1/2, then 1/4, ... */
\r
8346 for (n = 0; n < factor; n++) {
\r
8347 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
\r
8348 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
\r
8350 fraction = fraction * 2;
\r
8355 /* Draw a piece on the screen without disturbing what's there */
\r
8358 SelectGCMask(piece, clip, outline, mask)
\r
8359 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
\r
8363 /* Bitmap for piece being moved. */
\r
8364 if (appData.monoMode) {
\r
8365 *mask = *pieceToSolid(piece);
\r
8366 } else if (useImages) {
\r
8368 *mask = xpmMask[piece];
\r
8370 *mask = ximMaskPm[piece%(int)BlackPawn];
\r
8373 *mask = *pieceToSolid(piece);
\r
8376 /* GC for piece being moved. Square color doesn't matter, but
\r
8377 since it gets modified we make a copy of the original. */
\r
8378 if (White(piece)) {
\r
8379 if (appData.monoMode)
\r
8380 source = bwPieceGC;
\r
8382 source = wlPieceGC;
\r
8384 if (appData.monoMode)
\r
8385 source = wbPieceGC;
\r
8387 source = blPieceGC;
\r
8389 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
\r
8391 /* Outline only used in mono mode and is not modified */
\r
8393 *outline = bwPieceGC;
\r
8395 *outline = wbPieceGC;
\r
8399 OverlayPiece(piece, clip, outline, dest)
\r
8400 ChessSquare piece; GC clip; GC outline; Drawable dest;
\r
8405 /* Draw solid rectangle which will be clipped to shape of piece */
\r
8406 XFillRectangle(xDisplay, dest, clip,
\r
8407 0, 0, squareSize, squareSize);
\r
8408 if (appData.monoMode)
\r
8409 /* Also draw outline in contrasting color for black
\r
8410 on black / white on white cases */
\r
8411 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
\r
8412 0, 0, squareSize, squareSize, 0, 0, 1);
\r
8414 /* Copy the piece */
\r
8419 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
\r
8421 0, 0, squareSize, squareSize,
\r
8426 /* Animate the movement of a single piece */
\r
8429 BeginAnimation(anim, piece, startColor, start)
\r
8431 ChessSquare piece;
\r
8437 /* The old buffer is initialised with the start square (empty) */
\r
8438 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
\r
8439 anim->prevFrame = *start;
\r
8441 /* The piece will be drawn using its own bitmap as a matte */
\r
8442 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
\r
8443 XSetClipMask(xDisplay, anim->pieceGC, mask);
\r
8447 AnimationFrame(anim, frame, piece)
\r
8450 ChessSquare piece;
\r
8452 XRectangle updates[4];
\r
8453 XRectangle overlap;
\r
8457 /* Save what we are about to draw into the new buffer */
\r
8458 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
\r
8459 frame->x, frame->y, squareSize, squareSize,
\r
8462 /* Erase bits of the previous frame */
\r
8463 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
\r
8464 /* Where the new frame overlapped the previous,
\r
8465 the contents in newBuf are wrong. */
\r
8466 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
\r
8467 overlap.x, overlap.y,
\r
8468 overlap.width, overlap.height,
\r
8470 /* Repaint the areas in the old that don't overlap new */
\r
8471 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
\r
8472 for (i = 0; i < count; i++)
\r
8473 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8474 updates[i].x - anim->prevFrame.x,
\r
8475 updates[i].y - anim->prevFrame.y,
\r
8476 updates[i].width, updates[i].height,
\r
8477 updates[i].x, updates[i].y);
\r
8479 /* Easy when no overlap */
\r
8480 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8481 0, 0, squareSize, squareSize,
\r
8482 anim->prevFrame.x, anim->prevFrame.y);
\r
8485 /* Save this frame for next time round */
\r
8486 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
\r
8487 0, 0, squareSize, squareSize,
\r
8489 anim->prevFrame = *frame;
\r
8491 /* Draw piece over original screen contents, not current,
\r
8492 and copy entire rect. Wipes out overlapping piece images. */
\r
8493 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
\r
8494 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
\r
8495 0, 0, squareSize, squareSize,
\r
8496 frame->x, frame->y);
\r
8500 EndAnimation (anim, finish)
\r
8504 XRectangle updates[4];
\r
8505 XRectangle overlap;
\r
8509 /* The main code will redraw the final square, so we
\r
8510 only need to erase the bits that don't overlap. */
\r
8511 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
\r
8512 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
\r
8513 for (i = 0; i < count; i++)
\r
8514 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8515 updates[i].x - anim->prevFrame.x,
\r
8516 updates[i].y - anim->prevFrame.y,
\r
8517 updates[i].width, updates[i].height,
\r
8518 updates[i].x, updates[i].y);
\r
8520 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8521 0, 0, squareSize, squareSize,
\r
8522 anim->prevFrame.x, anim->prevFrame.y);
\r
8527 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
\r
8529 ChessSquare piece; int startColor;
\r
8530 XPoint * start; XPoint * finish;
\r
8531 XPoint frames[]; int nFrames;
\r
8535 BeginAnimation(anim, piece, startColor, start);
\r
8536 for (n = 0; n < nFrames; n++) {
\r
8537 AnimationFrame(anim, &(frames[n]), piece);
\r
8538 FrameDelay(appData.animSpeed);
\r
8540 EndAnimation(anim, finish);
\r
8543 /* Main control logic for deciding what to animate and how */
\r
8546 AnimateMove(board, fromX, fromY, toX, toY)
\r
8553 ChessSquare piece;
\r
8555 XPoint start, finish, mid;
\r
8556 XPoint frames[kFactor * 2 + 1];
\r
8557 int nFrames, startColor, endColor;
\r
8559 /* Are we animating? */
\r
8560 if (!appData.animate || appData.blindfold)
\r
8563 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
\r
8564 piece = board[fromY][fromX];
\r
8565 if (piece >= EmptySquare) return;
\r
8570 hop = (piece == WhiteKnight || piece == BlackKnight);
\r
8573 if (appData.debugMode) {
\r
8574 printf("AnimateMove: piece %d %s from %d,%d to %d,%d \n",
\r
8575 piece, hop ? "hops" : "slides", fromX, fromY, toX, toY);
\r
8578 ScreenSquare(fromX, fromY, &start, &startColor);
\r
8579 ScreenSquare(toX, toY, &finish, &endColor);
\r
8582 /* Knight: make diagonal movement then straight */
\r
8583 if (abs(toY - fromY) < abs(toX - fromX)) {
\r
8584 mid.x = start.x + (finish.x - start.x) / 2;
\r
8588 mid.y = start.y + (finish.y - start.y) / 2;
\r
8591 mid.x = start.x + (finish.x - start.x) / 2;
\r
8592 mid.y = start.y + (finish.y - start.y) / 2;
\r
8595 /* Don't use as many frames for very short moves */
\r
8596 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
\r
8597 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
\r
8599 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
\r
8600 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
\r
8602 /* Be sure end square is redrawn */
\r
8603 damage[toY][toX] = True;
\r
8607 DragPieceBegin(x, y)
\r
8610 int boardX, boardY, color;
\r
8613 /* Are we animating? */
\r
8614 if (!appData.animateDragging || appData.blindfold)
\r
8617 /* Figure out which square we start in and the
\r
8618 mouse position relative to top left corner. */
\r
8619 BoardSquare(x, y, &boardX, &boardY);
\r
8620 player.startBoardX = boardX;
\r
8621 player.startBoardY = boardY;
\r
8622 ScreenSquare(boardX, boardY, &corner, &color);
\r
8623 player.startSquare = corner;
\r
8624 player.startColor = color;
\r
8626 /* Start from exactly where the piece is. This can be confusing
\r
8627 if you start dragging far from the center of the square; most
\r
8628 or all of the piece can be over a different square from the one
\r
8629 the mouse pointer is in. */
\r
8630 player.mouseDelta.x = x - corner.x;
\r
8631 player.mouseDelta.y = y - corner.y;
\r
8633 /* As soon as we start dragging, the piece will jump slightly to
\r
8634 be centered over the mouse pointer. */
\r
8635 player.mouseDelta.x = squareSize/2;
\r
8636 player.mouseDelta.y = squareSize/2;
\r
8638 /* Initialise animation */
\r
8639 player.dragPiece = PieceForSquare(boardX, boardY);
\r
8640 /* Sanity check */
\r
8641 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
\r
8642 player.dragActive = True;
\r
8643 BeginAnimation(&player, player.dragPiece, color, &corner);
\r
8644 /* Mark this square as needing to be redrawn. Note that
\r
8645 we don't remove the piece though, since logically (ie
\r
8646 as seen by opponent) the move hasn't been made yet. */
\r
8647 damage[boardY][boardX] = True;
\r
8649 player.dragActive = False;
\r
8654 DragPieceMove(x, y)
\r
8659 /* Are we animating? */
\r
8660 if (!appData.animateDragging || appData.blindfold)
\r
8663 /* Sanity check */
\r
8664 if (! player.dragActive)
\r
8666 /* Move piece, maintaining same relative position
\r
8667 of mouse within square */
\r
8668 corner.x = x - player.mouseDelta.x;
\r
8669 corner.y = y - player.mouseDelta.y;
\r
8670 AnimationFrame(&player, &corner, player.dragPiece);
\r
8672 if (appData.highlightDragging) {
\r
8673 int boardX, boardY;
\r
8674 BoardSquare(x, y, &boardX, &boardY);
\r
8675 SetHighlights(fromX, fromY, boardX, boardY);
\r
8681 DragPieceEnd(x, y)
\r
8684 int boardX, boardY, color;
\r
8687 /* Are we animating? */
\r
8688 if (!appData.animateDragging || appData.blindfold)
\r
8691 /* Sanity check */
\r
8692 if (! player.dragActive)
\r
8694 /* Last frame in sequence is square piece is
\r
8695 placed on, which may not match mouse exactly. */
\r
8696 BoardSquare(x, y, &boardX, &boardY);
\r
8697 ScreenSquare(boardX, boardY, &corner, &color);
\r
8698 EndAnimation(&player, &corner);
\r
8700 /* Be sure end square is redrawn */
\r
8701 damage[boardY][boardX] = True;
\r
8703 /* This prevents weird things happening with fast successive
\r
8704 clicks which on my Sun at least can cause motion events
\r
8705 without corresponding press/release. */
\r
8706 player.dragActive = False;
\r
8709 /* Handle expose event while piece being dragged */
\r
8714 if (!player.dragActive || appData.blindfold)
\r
8717 /* What we're doing: logically, the move hasn't been made yet,
\r
8718 so the piece is still in it's original square. But visually
\r
8719 it's being dragged around the board. So we erase the square
\r
8720 that the piece is on and draw it at the last known drag point. */
\r
8721 BlankSquare(player.startSquare.x, player.startSquare.y,
\r
8722 player.startColor, EmptySquare, xBoardWindow);
\r
8723 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
\r
8724 damage[player.startBoardY][player.startBoardX] = TRUE;
\r
8728 SetProgramStats( FrontEndProgramStats * stats )
\r