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"
197 // must be moved to xengineoutput.h
198 void EngineOutputProc P((Widget w, XEvent *event,
199 String *prms, Cardinal *nprms));
200 void EngineOutputPopDown();
\r
204 #ifndef HAVE_USLEEP
\r
205 #define HAVE_USLEEP
\r
207 #define usleep(t) _sleep2(((t)+500)/1000)
\r
220 int main P((int argc, char **argv));
\r
221 RETSIGTYPE CmailSigHandler P((int sig));
\r
222 RETSIGTYPE IntSigHandler P((int sig));
\r
223 void CreateGCs P((void));
\r
224 void CreateXIMPieces P((void));
\r
225 void CreateXPMPieces P((void));
\r
226 void CreatePieces P((void));
\r
227 void CreatePieceMenus P((void));
\r
228 Widget CreateMenuBar P((Menu *mb));
\r
229 Widget CreateButtonBar P ((MenuItem *mi));
\r
230 char *FindFont P((char *pattern, int targetPxlSize));
\r
231 void PieceMenuPopup P((Widget w, XEvent *event,
\r
232 String *params, Cardinal *num_params));
\r
233 static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
\r
234 static void DropMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
\r
235 void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
\r
236 u_int wreq, u_int hreq));
\r
237 void CreateGrid P((void));
\r
238 int EventToSquare P((int x, int limit));
\r
239 void DrawSquare P((int row, int column, ChessSquare piece, int do_flash));
\r
240 void EventProc P((Widget widget, caddr_t unused, XEvent *event));
\r
241 void HandleUserMove P((Widget w, XEvent *event,
\r
242 String *prms, Cardinal *nprms));
\r
243 void AnimateUserMove P((Widget w, XEvent * event,
\r
244 String * params, Cardinal * nParams));
\r
245 void WhiteClock P((Widget w, XEvent *event,
\r
246 String *prms, Cardinal *nprms));
\r
247 void BlackClock P((Widget w, XEvent *event,
\r
248 String *prms, Cardinal *nprms));
\r
249 void DrawPositionProc P((Widget w, XEvent *event,
\r
250 String *prms, Cardinal *nprms));
\r
251 void XDrawPosition P((Widget w, /*Boolean*/int repaint,
\r
253 void CommentPopUp P((char *title, char *label));
\r
254 void CommentPopDown P((void));
\r
255 void CommentCallback P((Widget w, XtPointer client_data,
\r
256 XtPointer call_data));
\r
257 void ICSInputBoxPopUp P((void));
\r
258 void ICSInputBoxPopDown P((void));
\r
259 void FileNamePopUp P((char *label, char *def,
\r
260 FileProc proc, char *openMode));
\r
261 void FileNamePopDown P((void));
\r
262 void FileNameCallback P((Widget w, XtPointer client_data,
\r
263 XtPointer call_data));
\r
264 void FileNameAction P((Widget w, XEvent *event,
\r
265 String *prms, Cardinal *nprms));
\r
266 void AskQuestionReplyAction P((Widget w, XEvent *event,
\r
267 String *prms, Cardinal *nprms));
\r
268 void AskQuestionProc P((Widget w, XEvent *event,
\r
269 String *prms, Cardinal *nprms));
\r
270 void AskQuestionPopDown P((void));
\r
271 void PromotionPopUp P((void));
\r
272 void PromotionPopDown P((void));
\r
273 void PromotionCallback P((Widget w, XtPointer client_data,
\r
274 XtPointer call_data));
\r
275 void EditCommentPopDown P((void));
\r
276 void EditCommentCallback P((Widget w, XtPointer client_data,
\r
277 XtPointer call_data));
\r
278 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
\r
279 void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
280 void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
281 void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
\r
283 void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
\r
285 void ReloadGameProc P((Widget w, XEvent *event, String *prms,
\r
287 void LoadPositionProc P((Widget w, XEvent *event,
\r
288 String *prms, Cardinal *nprms));
\r
289 void LoadNextPositionProc P((Widget w, XEvent *event, String *prms,
\r
291 void LoadPrevPositionProc P((Widget w, XEvent *event, String *prms,
\r
293 void ReloadPositionProc P((Widget w, XEvent *event, String *prms,
\r
295 void CopyPositionProc P((Widget w, XEvent *event, String *prms,
\r
297 void PastePositionProc P((Widget w, XEvent *event, String *prms,
\r
299 void CopyGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
300 void PasteGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
301 void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
302 void SavePositionProc P((Widget w, XEvent *event,
\r
303 String *prms, Cardinal *nprms));
\r
304 void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
305 void ReloadCmailMsgProc P((Widget w, XEvent *event, String *prms,
\r
307 void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
308 void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
309 void MachineBlackProc P((Widget w, XEvent *event, String *prms,
\r
311 void MachineWhiteProc P((Widget w, XEvent *event,
\r
312 String *prms, Cardinal *nprms));
\r
313 void AnalyzeModeProc P((Widget w, XEvent *event,
\r
314 String *prms, Cardinal *nprms));
\r
315 void AnalyzeFileProc P((Widget w, XEvent *event,
\r
316 String *prms, Cardinal *nprms));
\r
317 void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
\r
319 void IcsClientProc P((Widget w, XEvent *event, String *prms,
\r
321 void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
322 void EditPositionProc P((Widget w, XEvent *event,
\r
323 String *prms, Cardinal *nprms));
\r
324 void TrainingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
325 void EditCommentProc P((Widget w, XEvent *event,
\r
326 String *prms, Cardinal *nprms));
\r
327 void IcsInputBoxProc P((Widget w, XEvent *event,
\r
328 String *prms, Cardinal *nprms));
\r
329 void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
330 void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
331 void RematchProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
332 void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
333 void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
334 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
335 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
336 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
337 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
338 void StopObservingProc P((Widget w, XEvent *event, String *prms,
\r
340 void StopExaminingProc P((Widget w, XEvent *event, String *prms,
\r
342 void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
343 void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
344 void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
345 void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
346 void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
347 void TruncateGameProc P((Widget w, XEvent *event, String *prms,
\r
349 void RetractMoveProc P((Widget w, XEvent *event, String *prms,
\r
351 void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
352 void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
\r
354 void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
\r
356 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
\r
358 void AutocommProc P((Widget w, XEvent *event, String *prms,
\r
360 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
361 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
362 void AutobsProc P((Widget w, XEvent *event, String *prms,
\r
364 void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
365 void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
366 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
367 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
\r
369 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
370 void GetMoveListProc P((Widget w, XEvent *event, String *prms,
\r
372 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
\r
374 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
\r
376 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
377 void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
378 void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
\r
380 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
\r
382 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
\r
384 void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
\r
386 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
\r
388 void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
389 void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
390 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
\r
392 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
\r
394 void HideThinkingProc P((Widget w, XEvent *event, String *prms,
\r
396 void TestLegalityProc P((Widget w, XEvent *event, String *prms,
\r
398 void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
399 void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
400 void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
401 void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
402 void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
403 void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
404 void DebugProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
405 void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
406 void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
407 void DisplayMove P((int moveNumber));
\r
408 void DisplayTitle P((char *title));
\r
409 void ICSInitScript P((void));
\r
410 int LoadGamePopUp P((FILE *f, int gameNumber, char *title));
\r
411 void ErrorPopUp P((char *title, char *text, int modal));
\r
412 void ErrorPopDown P((void));
\r
413 static char *ExpandPathName P((char *path));
\r
414 static void CreateAnimVars P((void));
\r
415 static void DragPieceBegin P((int x, int y));
\r
416 static void DragPieceMove P((int x, int y));
\r
417 static void DragPieceEnd P((int x, int y));
\r
418 static void DrawDragPiece P((void));
\r
419 char *ModeToWidgetName P((GameMode mode));
\r
420 void EngineOutputUpdate( FrontEndProgramStats * stats );
\r
421 void ShuffleMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
422 void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
423 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
424 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
425 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
426 void ShufflePopDown P(());
\r
427 void EnginePopDown P(());
\r
428 void UciPopDown P(());
\r
429 void TimeControlPopDown P(());
\r
430 void NewVariantPopDown P(());
\r
432 * XBoard depends on Xt R4 or higher
\r
434 int xtVersion = XtSpecificationRelease;
\r
438 Window xBoardWindow;
\r
439 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
\r
440 jailSquareColor, highlightSquareColor, premoveHighlightColor;
\r
441 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
\r
442 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
\r
443 wjPieceGC, bjPieceGC, prelineGC, countGC;
\r
444 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
\r
445 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
\r
446 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
\r
447 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
\r
448 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
\r
449 ICSInputShell, fileNameShell, askQuestionShell;
\r
450 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
\r
451 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
\r
452 Font clockFontID, coordFontID, countFontID;
\r
453 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
\r
454 XtAppContext appContext;
\r
456 char *oldICSInteractionTitle;
\r
460 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
\r
462 Position commentX = -1, commentY = -1;
\r
463 Dimension commentW, commentH;
\r
465 int squareSize, smallLayout = 0, tinyLayout = 0,
466 marginW, marginH, // [HGM] for run-time resizing
\r
467 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
\r
468 ICSInputBoxUp = False, askQuestionUp = False,
\r
469 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
\r
470 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
\r
471 Pixel timerForegroundPixel, timerBackgroundPixel;
\r
472 Pixel buttonForegroundPixel, buttonBackgroundPixel;
\r
473 char *chessDir, *programName, *programVersion,
\r
474 *gameCopyFilename, *gamePasteFilename;
\r
478 Pixmap pieceBitmap[2][(int)BlackPawn];
\r
479 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
\r
480 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
\r
481 int useImages, useImageSqs;
\r
482 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
\r
483 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
\r
484 XImage *ximLightSquare, *ximDarkSquare;
\r
487 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
\r
488 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
\r
490 #define White(piece) ((int)(piece) < (int)BlackPawn)
\r
492 /* Variables for doing smooth animation. This whole thing
\r
493 would be much easier if the board was double-buffered,
\r
494 but that would require a fairly major rewrite. */
\r
499 GC blitGC, pieceGC, outlineGC;
\r
500 XPoint startSquare, prevFrame, mouseDelta;
\r
503 Boolean dragActive;
\r
504 int startBoardX, startBoardY;
\r
507 /* There can be two pieces being animated at once: a player
\r
508 can begin dragging a piece before the remote opponent has moved. */
\r
510 static AnimState game, player;
\r
512 /* Bitmaps for use as masks when drawing XPM pieces.
\r
513 Need one for each black and white piece. */
\r
514 static Pixmap xpmMask[BlackKing + 1];
\r
516 /* This magic number is the number of intermediate frames used
\r
517 in each half of the animation. For short moves it's reduced
\r
518 by 1. The total number of frames will be factor * 2 + 1. */
\r
521 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
\r
523 MenuItem fileMenu[] = {
\r
524 {"New Game", ResetProc},
\r
525 {"New Shuffle Game ...", ShuffleMenuProc},
\r
526 {"New Variant ...", NewVariantProc}, // [HGM] variant: not functional yet
\r
527 {"----", NothingProc},
\r
528 {"Load Game", LoadGameProc},
\r
529 {"Load Next Game", LoadNextGameProc},
\r
530 {"Load Previous Game", LoadPrevGameProc},
\r
531 {"Reload Same Game", ReloadGameProc},
\r
532 {"Save Game", SaveGameProc},
\r
533 {"----", NothingProc},
\r
534 {"Copy Game", CopyGameProc},
\r
535 {"Paste Game", PasteGameProc},
\r
536 {"----", NothingProc},
\r
537 {"Load Position", LoadPositionProc},
\r
538 {"Load Next Position", LoadNextPositionProc},
\r
539 {"Load Previous Position", LoadPrevPositionProc},
\r
540 {"Reload Same Position", ReloadPositionProc},
\r
541 {"Save Position", SavePositionProc},
\r
542 {"----", NothingProc},
\r
543 {"Copy Position", CopyPositionProc},
\r
544 {"Paste Position", PastePositionProc},
\r
545 {"----", NothingProc},
\r
546 {"Mail Move", MailMoveProc},
\r
547 {"Reload CMail Message", ReloadCmailMsgProc},
\r
548 {"----", NothingProc},
\r
549 {"Exit", QuitProc},
\r
553 MenuItem modeMenu[] = {
\r
554 {"Machine White", MachineWhiteProc},
\r
555 {"Machine Black", MachineBlackProc},
\r
556 {"Two Machines", TwoMachinesProc},
\r
557 {"Analysis Mode", AnalyzeModeProc},
\r
558 {"Analyze File", AnalyzeFileProc },
\r
559 {"ICS Client", IcsClientProc},
\r
560 {"Edit Game", EditGameProc},
\r
561 {"Edit Position", EditPositionProc},
\r
562 {"Training", TrainingProc},
\r
563 {"----", NothingProc},
\r
564 {"Show Engine Output", EngineOutputProc},
\r
565 {"Show Evaluation Graph", NothingProc}, // [HGM] evalgr: not functional yet
\r
566 {"Show Game List", ShowGameListProc},
\r
567 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
\r
568 {"----", NothingProc},
\r
569 {"Edit Tags", EditTagsProc},
\r
570 {"Edit Comment", EditCommentProc},
\r
571 {"ICS Input Box", IcsInputBoxProc},
\r
572 {"Pause", PauseProc},
\r
576 MenuItem actionMenu[] = {
\r
577 {"Accept", AcceptProc},
\r
578 {"Decline", DeclineProc},
\r
579 {"Rematch", RematchProc},
\r
580 {"----", NothingProc},
\r
581 {"Call Flag", CallFlagProc},
\r
582 {"Draw", DrawProc},
\r
583 {"Adjourn", AdjournProc},
\r
584 {"Abort", AbortProc},
\r
585 {"Resign", ResignProc},
\r
586 {"----", NothingProc},
\r
587 {"Stop Observing", StopObservingProc},
\r
588 {"Stop Examining", StopExaminingProc},
\r
592 MenuItem stepMenu[] = {
\r
593 {"Backward", BackwardProc},
\r
594 {"Forward", ForwardProc},
\r
595 {"Back to Start", ToStartProc},
\r
596 {"Forward to End", ToEndProc},
\r
597 {"Revert", RevertProc},
\r
598 {"Truncate Game", TruncateGameProc},
\r
599 {"----", NothingProc},
\r
600 {"Move Now", MoveNowProc},
\r
601 {"Retract Move", RetractMoveProc},
\r
605 MenuItem optionsMenu[] = {
606 {"Flip View", FlipViewProc},
\r
607 {"----", NothingProc},
\r
608 {"Adjudications ...", EngineMenuProc},
\r
609 {"Engine Settings ...", UciMenuProc},
\r
610 {"Time Control ...", TimeControlProc},
\r
611 {"----", NothingProc},
\r
612 {"Always Queen", AlwaysQueenProc},
\r
613 {"Animate Dragging", AnimateDraggingProc},
\r
614 {"Animate Moving", AnimateMovingProc},
\r
615 {"Auto Comment", AutocommProc},
\r
616 {"Auto Flag", AutoflagProc},
\r
617 {"Auto Flip View", AutoflipProc},
\r
618 {"Auto Observe", AutobsProc},
\r
619 {"Auto Raise Board", AutoraiseProc},
\r
620 {"Auto Save", AutosaveProc},
\r
621 {"Blindfold", BlindfoldProc},
\r
622 {"Flash Moves", FlashMovesProc},
\r
623 {"Get Move List", GetMoveListProc},
\r
625 {"Highlight Dragging", HighlightDraggingProc},
\r
627 {"Highlight Last Move", HighlightLastMoveProc},
\r
628 {"Move Sound", MoveSoundProc},
\r
629 {"ICS Alarm", IcsAlarmProc},
\r
630 {"Old Save Style", OldSaveStyleProc},
\r
631 {"Periodic Updates", PeriodicUpdatesProc},
\r
632 {"Ponder Next Move", PonderNextMoveProc},
\r
633 {"Popup Exit Message", PopupExitMessageProc},
\r
634 {"Popup Move Errors", PopupMoveErrorsProc},
\r
635 {"Premove", PremoveProc},
\r
636 {"Quiet Play", QuietPlayProc},
\r
637 {"Show Coords", ShowCoordsProc},
\r
638 {"Hide Thinking", HideThinkingProc},
\r
639 {"Test Legality", TestLegalityProc},
\r
643 MenuItem helpMenu[] = {
\r
644 {"Info XBoard", InfoProc},
\r
645 {"Man XBoard", ManProc},
\r
646 {"----", NothingProc},
\r
647 {"Hint", HintProc},
\r
648 {"Book", BookProc},
\r
649 {"----", NothingProc},
\r
650 {"About XBoard", AboutProc},
\r
655 {"File", fileMenu},
\r
656 {"Mode", modeMenu},
\r
657 {"Action", actionMenu},
\r
658 {"Step", stepMenu},
\r
659 {"Options", optionsMenu},
\r
660 {"Help", helpMenu},
\r
664 #define PAUSE_BUTTON "P"
\r
665 MenuItem buttonBar[] = {
\r
666 {"<<", ToStartProc},
\r
667 {"<", BackwardProc},
\r
668 {PAUSE_BUTTON, PauseProc},
\r
669 {">", ForwardProc},
\r
674 #define PIECE_MENU_SIZE 11
\r
675 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
\r
676 { "White", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
\r
677 "----", "Empty square", "Clear board" },
\r
678 { "Black", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
\r
679 "----", "Empty square", "Clear board" },
\r
681 /* must be in same order as PieceMenuStrings! */
\r
682 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
\r
683 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
\r
684 WhiteRook, WhiteQueen, WhiteKing,
\r
685 (ChessSquare) 0, EmptySquare, ClearBoard },
\r
686 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
\r
687 BlackRook, BlackQueen, BlackKing,
\r
688 (ChessSquare) 0, EmptySquare, ClearBoard },
\r
691 #define DROP_MENU_SIZE 6
\r
692 String dropMenuStrings[DROP_MENU_SIZE] = {
\r
693 "----", "Pawn", "Knight", "Bishop", "Rook", "Queen"
\r
695 /* must be in same order as PieceMenuStrings! */
\r
696 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
\r
697 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
\r
698 WhiteRook, WhiteQueen
\r
706 DropMenuEnables dmEnables[] = {
\r
714 Arg shellArgs[] = {
\r
717 { XtNminWidth, 0 },
\r
718 { XtNminHeight, 0 },
\r
719 { XtNmaxWidth, 0 },
\r
720 { XtNmaxHeight, 0 }
\r
723 Arg layoutArgs[] = {
\r
724 { XtNborderWidth, 0 },
\r
725 { XtNdefaultDistance, 0 },
\r
729 { XtNborderWidth, 0 },
\r
730 { XtNresizable, (XtArgVal) True },
\r
733 Arg boardArgs[] = {
\r
734 { XtNborderWidth, 0 },
\r
739 Arg titleArgs[] = {
\r
740 { XtNjustify, (XtArgVal) XtJustifyRight },
\r
741 { XtNlabel, (XtArgVal) "..." },
\r
742 { XtNresizable, (XtArgVal) True },
\r
743 { XtNresize, (XtArgVal) False }
\r
746 Arg messageArgs[] = {
\r
747 { XtNjustify, (XtArgVal) XtJustifyLeft },
\r
748 { XtNlabel, (XtArgVal) "..." },
\r
749 { XtNresizable, (XtArgVal) True },
\r
750 { XtNresize, (XtArgVal) False }
\r
753 Arg timerArgs[] = {
\r
754 { XtNborderWidth, 0 },
\r
755 { XtNjustify, (XtArgVal) XtJustifyLeft }
\r
758 XtResource clientResources[] = {
\r
759 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
\r
760 XtOffset(AppDataPtr, whitePieceColor), XtRString,
\r
761 WHITE_PIECE_COLOR },
\r
762 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
\r
763 XtOffset(AppDataPtr, blackPieceColor), XtRString,
\r
764 BLACK_PIECE_COLOR },
\r
765 { "lightSquareColor", "lightSquareColor", XtRString,
\r
766 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
\r
767 XtRString, LIGHT_SQUARE_COLOR },
\r
768 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
\r
769 XtOffset(AppDataPtr, darkSquareColor), XtRString,
\r
770 DARK_SQUARE_COLOR },
\r
771 { "highlightSquareColor", "highlightSquareColor", XtRString,
\r
772 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
\r
773 XtRString, HIGHLIGHT_SQUARE_COLOR },
\r
774 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
\r
775 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
\r
776 XtRString, PREMOVE_HIGHLIGHT_COLOR },
\r
777 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
\r
778 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
\r
779 (XtPointer) MOVES_PER_SESSION },
\r
780 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
\r
781 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
\r
782 (XtPointer) TIME_INCREMENT },
\r
783 { "initString", "initString", XtRString, sizeof(String),
\r
784 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
\r
785 { "secondInitString", "secondInitString", XtRString, sizeof(String),
\r
786 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
\r
787 { "firstComputerString", "firstComputerString", XtRString,
\r
788 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
\r
790 { "secondComputerString", "secondComputerString", XtRString,
\r
791 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
\r
793 { "firstChessProgram", "firstChessProgram", XtRString,
\r
794 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
\r
795 XtRString, FIRST_CHESS_PROGRAM },
\r
796 { "secondChessProgram", "secondChessProgram", XtRString,
\r
797 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
\r
798 XtRString, SECOND_CHESS_PROGRAM },
\r
799 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
\r
800 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
\r
801 XtRImmediate, (XtPointer) False },
\r
802 { "noChessProgram", "noChessProgram", XtRBoolean,
\r
803 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
\r
804 XtRImmediate, (XtPointer) False },
\r
805 { "firstHost", "firstHost", XtRString, sizeof(String),
\r
806 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
\r
807 { "secondHost", "secondHost", XtRString, sizeof(String),
\r
808 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
\r
809 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
\r
810 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
\r
811 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
\r
812 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
\r
813 { "bitmapDirectory", "bitmapDirectory", XtRString,
\r
814 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
\r
816 { "remoteShell", "remoteShell", XtRString, sizeof(String),
\r
817 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
\r
818 { "remoteUser", "remoteUser", XtRString, sizeof(String),
\r
819 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
\r
820 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
\r
821 XtOffset(AppDataPtr, timeDelay), XtRString,
\r
822 (XtPointer) TIME_DELAY_QUOTE },
\r
823 { "timeControl", "timeControl", XtRString, sizeof(String),
\r
824 XtOffset(AppDataPtr, timeControl), XtRString,
\r
825 (XtPointer) TIME_CONTROL },
\r
826 { "internetChessServerMode", "internetChessServerMode",
\r
827 XtRBoolean, sizeof(Boolean),
\r
828 XtOffset(AppDataPtr, icsActive), XtRImmediate,
\r
829 (XtPointer) False },
\r
830 { "internetChessServerHost", "internetChessServerHost",
\r
831 XtRString, sizeof(String),
\r
832 XtOffset(AppDataPtr, icsHost),
\r
833 XtRString, (XtPointer) ICS_HOST },
\r
834 { "internetChessServerPort", "internetChessServerPort",
\r
835 XtRString, sizeof(String),
\r
836 XtOffset(AppDataPtr, icsPort), XtRString,
\r
837 (XtPointer) ICS_PORT },
\r
838 { "internetChessServerCommPort", "internetChessServerCommPort",
\r
839 XtRString, sizeof(String),
\r
840 XtOffset(AppDataPtr, icsCommPort), XtRString,
\r
842 { "internetChessServerLogonScript", "internetChessServerLogonScript",
\r
843 XtRString, sizeof(String),
\r
844 XtOffset(AppDataPtr, icsLogon), XtRString,
\r
846 { "internetChessServerHelper", "internetChessServerHelper",
\r
847 XtRString, sizeof(String),
\r
848 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
\r
849 { "internetChessServerInputBox", "internetChessServerInputBox",
\r
850 XtRBoolean, sizeof(Boolean),
\r
851 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
\r
852 (XtPointer) False },
\r
853 { "icsAlarm", "icsAlarm",
\r
854 XtRBoolean, sizeof(Boolean),
\r
855 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
\r
856 (XtPointer) True },
\r
857 { "icsAlarmTime", "icsAlarmTime",
\r
858 XtRInt, sizeof(int),
\r
859 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
\r
860 (XtPointer) 5000 },
\r
861 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
\r
862 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
\r
863 (XtPointer) False },
\r
864 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
\r
865 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
\r
866 { "gateway", "gateway", XtRString, sizeof(String),
\r
867 XtOffset(AppDataPtr, gateway), XtRString, "" },
\r
868 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
\r
869 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
\r
870 { "loadGameIndex", "loadGameIndex",
\r
871 XtRInt, sizeof(int),
\r
872 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
\r
874 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
\r
875 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
\r
876 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
\r
877 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
\r
878 XtRImmediate, (XtPointer) True },
\r
879 { "autoSaveGames", "autoSaveGames", XtRBoolean,
\r
880 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
\r
881 XtRImmediate, (XtPointer) False },
\r
882 { "blindfold", "blindfold", XtRBoolean,
\r
883 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
\r
884 XtRImmediate, (XtPointer) False },
\r
885 { "loadPositionFile", "loadPositionFile", XtRString,
\r
886 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
\r
888 { "loadPositionIndex", "loadPositionIndex",
\r
889 XtRInt, sizeof(int),
\r
890 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
\r
892 { "savePositionFile", "savePositionFile", XtRString,
\r
893 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
\r
895 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
\r
896 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
\r
897 { "matchGames", "matchGames", XtRInt, sizeof(int),
\r
898 XtOffset(AppDataPtr, matchGames), XtRImmediate,
\r
900 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
\r
901 XtOffset(AppDataPtr, monoMode), XtRImmediate,
\r
902 (XtPointer) False },
\r
903 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
\r
904 XtOffset(AppDataPtr, debugMode), XtRImmediate,
\r
905 (XtPointer) False },
\r
906 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
\r
907 XtOffset(AppDataPtr, clockMode), XtRImmediate,
\r
908 (XtPointer) True },
\r
909 { "boardSize", "boardSize", XtRString, sizeof(String),
\r
910 XtOffset(AppDataPtr, boardSize), XtRString, "" },
\r
911 { "searchTime", "searchTime", XtRString, sizeof(String),
\r
912 XtOffset(AppDataPtr, searchTime), XtRString,
\r
914 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
\r
915 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
\r
917 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
\r
918 XtOffset(AppDataPtr, showCoords), XtRImmediate,
\r
919 (XtPointer) False },
\r
920 { "showJail", "showJail", XtRInt, sizeof(int),
\r
921 XtOffset(AppDataPtr, showJail), XtRImmediate,
\r
923 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
\r
924 XtOffset(AppDataPtr, showThinking), XtRImmediate,
\r
925 (XtPointer) True },
\r
926 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
\r
927 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
\r
928 (XtPointer) True },
\r
929 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
\r
930 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
\r
931 (XtPointer) True },
\r
932 { "clockFont", "clockFont", XtRString, sizeof(String),
\r
933 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
\r
934 { "coordFont", "coordFont", XtRString, sizeof(String),
\r
935 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
\r
936 { "font", "font", XtRString, sizeof(String),
\r
937 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
\r
938 { "ringBellAfterMoves", "ringBellAfterMoves",
\r
939 XtRBoolean, sizeof(Boolean),
\r
940 XtOffset(AppDataPtr, ringBellAfterMoves),
\r
941 XtRImmediate, (XtPointer) False },
\r
942 { "autoCallFlag", "autoCallFlag", XtRBoolean,
\r
943 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
\r
944 XtRImmediate, (XtPointer) False },
\r
945 { "autoFlipView", "autoFlipView", XtRBoolean,
\r
946 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
\r
947 XtRImmediate, (XtPointer) True },
\r
948 { "autoObserve", "autoObserve", XtRBoolean,
\r
949 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
\r
950 XtRImmediate, (XtPointer) False },
\r
951 { "autoComment", "autoComment", XtRBoolean,
\r
952 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
\r
953 XtRImmediate, (XtPointer) False },
\r
954 { "getMoveList", "getMoveList", XtRBoolean,
\r
955 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
\r
956 XtRImmediate, (XtPointer) True },
\r
958 { "highlightDragging", "highlightDragging", XtRBoolean,
\r
959 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
\r
960 XtRImmediate, (XtPointer) False },
\r
962 { "highlightLastMove", "highlightLastMove", XtRBoolean,
\r
963 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
\r
964 XtRImmediate, (XtPointer) False },
\r
965 { "premove", "premove", XtRBoolean,
\r
966 sizeof(Boolean), XtOffset(AppDataPtr, premove),
\r
967 XtRImmediate, (XtPointer) True },
\r
968 { "testLegality", "testLegality", XtRBoolean,
\r
969 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
\r
970 XtRImmediate, (XtPointer) True },
\r
971 { "flipView", "flipView", XtRBoolean,
\r
972 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
\r
973 XtRImmediate, (XtPointer) False },
\r
974 { "cmail", "cmailGameName", XtRString, sizeof(String),
\r
975 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
\r
976 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
\r
977 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
\r
978 XtRImmediate, (XtPointer) False },
\r
979 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
\r
980 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
\r
981 XtRImmediate, (XtPointer) False },
\r
982 { "quietPlay", "quietPlay", XtRBoolean,
\r
983 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
\r
984 XtRImmediate, (XtPointer) False },
\r
985 { "titleInWindow", "titleInWindow", XtRBoolean,
\r
986 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
\r
987 XtRImmediate, (XtPointer) False },
\r
988 { "localLineEditing", "localLineEditing", XtRBoolean,
\r
989 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
\r
990 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
\r
992 { "zippyTalk", "zippyTalk", XtRBoolean,
\r
993 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
\r
994 XtRImmediate, (XtPointer) ZIPPY_TALK },
\r
995 { "zippyPlay", "zippyPlay", XtRBoolean,
\r
996 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
\r
997 XtRImmediate, (XtPointer) ZIPPY_PLAY },
\r
998 { "zippyLines", "zippyLines", XtRString, sizeof(String),
\r
999 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
\r
1000 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
\r
1001 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
\r
1002 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
\r
1003 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
\r
1004 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
\r
1005 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
\r
1006 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
\r
1007 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
\r
1008 ZIPPY_WRONG_PASSWORD },
\r
1009 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
\r
1010 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
\r
1011 { "zippyUseI", "zippyUseI", XtRBoolean,
\r
1012 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
\r
1013 XtRImmediate, (XtPointer) ZIPPY_USE_I },
\r
1014 { "zippyBughouse", "zippyBughouse", XtRInt,
\r
1015 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
\r
1016 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
\r
1017 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
\r
1018 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
\r
1019 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
\r
1020 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
\r
1021 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
\r
1022 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
\r
1023 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
\r
1024 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
\r
1025 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
\r
1026 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
\r
1027 { "zippyAbort", "zippyAbort", XtRBoolean,
\r
1028 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
\r
1029 XtRImmediate, (XtPointer) ZIPPY_ABORT },
\r
1030 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
\r
1031 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
\r
1032 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
\r
1033 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
\r
1034 (XtPointer) ZIPPY_MAX_GAMES },
\r
1035 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
\r
1036 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
\r
1037 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
\r
1039 { "flashCount", "flashCount", XtRInt, sizeof(int),
\r
1040 XtOffset(AppDataPtr, flashCount), XtRImmediate,
\r
1041 (XtPointer) FLASH_COUNT },
\r
1042 { "flashRate", "flashRate", XtRInt, sizeof(int),
\r
1043 XtOffset(AppDataPtr, flashRate), XtRImmediate,
\r
1044 (XtPointer) FLASH_RATE },
\r
1045 { "pixmapDirectory", "pixmapDirectory", XtRString,
\r
1046 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
\r
1048 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
\r
1049 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
\r
1050 (XtPointer) MS_LOGIN_DELAY },
\r
1051 { "colorizeMessages", "colorizeMessages", XtRBoolean,
\r
1052 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
\r
1053 XtRImmediate, (XtPointer) False },
\r
1054 { "colorShout", "colorShout", XtRString,
\r
1055 sizeof(String), XtOffset(AppDataPtr, colorShout),
\r
1056 XtRString, COLOR_SHOUT },
\r
1057 { "colorSShout", "colorSShout", XtRString,
\r
1058 sizeof(String), XtOffset(AppDataPtr, colorSShout),
\r
1059 XtRString, COLOR_SSHOUT },
\r
1060 { "colorChannel1", "colorChannel1", XtRString,
\r
1061 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
\r
1062 XtRString, COLOR_CHANNEL1 },
\r
1063 { "colorChannel", "colorChannel", XtRString,
\r
1064 sizeof(String), XtOffset(AppDataPtr, colorChannel),
\r
1065 XtRString, COLOR_CHANNEL },
\r
1066 { "colorKibitz", "colorKibitz", XtRString,
\r
1067 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
\r
1068 XtRString, COLOR_KIBITZ },
\r
1069 { "colorTell", "colorTell", XtRString,
\r
1070 sizeof(String), XtOffset(AppDataPtr, colorTell),
\r
1071 XtRString, COLOR_TELL },
\r
1072 { "colorChallenge", "colorChallenge", XtRString,
\r
1073 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
\r
1074 XtRString, COLOR_CHALLENGE },
\r
1075 { "colorRequest", "colorRequest", XtRString,
\r
1076 sizeof(String), XtOffset(AppDataPtr, colorRequest),
\r
1077 XtRString, COLOR_REQUEST },
\r
1078 { "colorSeek", "colorSeek", XtRString,
\r
1079 sizeof(String), XtOffset(AppDataPtr, colorSeek),
\r
1080 XtRString, COLOR_SEEK },
\r
1081 { "colorNormal", "colorNormal", XtRString,
\r
1082 sizeof(String), XtOffset(AppDataPtr, colorNormal),
\r
1083 XtRString, COLOR_NORMAL },
\r
1084 { "soundProgram", "soundProgram", XtRString,
\r
1085 sizeof(String), XtOffset(AppDataPtr, soundProgram),
\r
1086 XtRString, "play" },
\r
1087 { "soundShout", "soundShout", XtRString,
\r
1088 sizeof(String), XtOffset(AppDataPtr, soundShout),
\r
1090 { "soundSShout", "soundSShout", XtRString,
\r
1091 sizeof(String), XtOffset(AppDataPtr, soundSShout),
\r
1093 { "soundChannel1", "soundChannel1", XtRString,
\r
1094 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
\r
1096 { "soundChannel", "soundChannel", XtRString,
\r
1097 sizeof(String), XtOffset(AppDataPtr, soundChannel),
\r
1099 { "soundKibitz", "soundKibitz", XtRString,
\r
1100 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
\r
1102 { "soundTell", "soundTell", XtRString,
\r
1103 sizeof(String), XtOffset(AppDataPtr, soundTell),
\r
1105 { "soundChallenge", "soundChallenge", XtRString,
\r
1106 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
\r
1108 { "soundRequest", "soundRequest", XtRString,
\r
1109 sizeof(String), XtOffset(AppDataPtr, soundRequest),
\r
1111 { "soundSeek", "soundSeek", XtRString,
\r
1112 sizeof(String), XtOffset(AppDataPtr, soundSeek),
\r
1114 { "soundMove", "soundMove", XtRString,
\r
1115 sizeof(String), XtOffset(AppDataPtr, soundMove),
\r
1117 { "soundIcsWin", "soundIcsWin", XtRString,
\r
1118 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
\r
1120 { "soundIcsLoss", "soundIcsLoss", XtRString,
\r
1121 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
\r
1123 { "soundIcsDraw", "soundIcsDraw", XtRString,
\r
1124 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
\r
1126 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
\r
1127 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
\r
1129 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
\r
1130 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
\r
1132 { "reuseFirst", "reuseFirst", XtRBoolean,
\r
1133 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
\r
1134 XtRImmediate, (XtPointer) True },
\r
1135 { "reuseSecond", "reuseSecond", XtRBoolean,
\r
1136 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
\r
1137 XtRImmediate, (XtPointer) True },
\r
1138 { "animateDragging", "animateDragging", XtRBoolean,
\r
1139 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
\r
1140 XtRImmediate, (XtPointer) True },
\r
1141 { "animateMoving", "animateMoving", XtRBoolean,
\r
1142 sizeof(Boolean), XtOffset(AppDataPtr, animate),
\r
1143 XtRImmediate, (XtPointer) True },
\r
1144 { "animateSpeed", "animateSpeed", XtRInt,
\r
1145 sizeof(int), XtOffset(AppDataPtr, animSpeed),
\r
1146 XtRImmediate, (XtPointer)10 },
\r
1147 { "popupExitMessage", "popupExitMessage", XtRBoolean,
\r
1148 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
\r
1149 XtRImmediate, (XtPointer) True },
\r
1150 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
\r
1151 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
\r
1152 XtRImmediate, (XtPointer) False },
\r
1153 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
\r
1154 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
\r
1155 XtRImmediate, (XtPointer)4 },
\r
1156 { "initialMode", "initialMode", XtRString,
\r
1157 sizeof(String), XtOffset(AppDataPtr, initialMode),
\r
1158 XtRImmediate, (XtPointer) "" },
\r
1159 { "variant", "variant", XtRString,
\r
1160 sizeof(String), XtOffset(AppDataPtr, variant),
\r
1161 XtRImmediate, (XtPointer) "normal" },
\r
1162 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
\r
1163 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
\r
1164 XtRImmediate, (XtPointer)PROTOVER },
\r
1165 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
\r
1166 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
\r
1167 XtRImmediate, (XtPointer)PROTOVER },
\r
1168 { "showButtonBar", "showButtonBar", XtRBoolean,
\r
1169 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
\r
1170 XtRImmediate, (XtPointer) True },
\r
1171 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
\r
1172 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
\r
1173 XtRImmediate, (XtPointer) False },
\r
1174 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
\r
1175 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
\r
1176 XtRImmediate, (XtPointer) False },
\r
1177 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
\r
1178 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
\r
1179 XtRImmediate, (XtPointer) False },
\r
1180 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
\r
1181 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
\r
1182 XtRImmediate, (XtPointer) True },
\r
1183 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
\r
1184 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
\r
1185 XtRImmediate, (XtPointer) 0},
\r
1186 { "pgnEventHeader", "pgnEventHeader", XtRString,
\r
1187 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
\r
1188 XtRImmediate, (XtPointer) "Computer Chess Game" },
\r
1189 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
\r
1190 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
\r
1191 XtRImmediate, (XtPointer) -1},
\r
1193 // [HGM] 4.3.xx options
\r
1194 { "boardWidth", "boardWidth", XtRInt,
\r
1195 sizeof(int), XtOffset(AppDataPtr, NrFiles),
\r
1196 XtRImmediate, (XtPointer) -1},
\r
1197 { "boardHeight", "boardHeight", XtRInt,
\r
1198 sizeof(int), XtOffset(AppDataPtr, NrRanks),
\r
1199 XtRImmediate, (XtPointer) -1},
\r
1200 { "matchPause", "matchPause", XtRInt,
\r
1201 sizeof(int), XtOffset(AppDataPtr, matchPause),
\r
1202 XtRImmediate, (XtPointer) 10000},
\r
1203 { "holdingsSize", "holdingsSize", XtRInt,
\r
1204 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
\r
1205 XtRImmediate, (XtPointer) -1},
\r
1206 { "flipBlack", "flipBlack", XtRBoolean,
\r
1207 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
\r
1208 XtRImmediate, (XtPointer) False},
\r
1209 { "allWhite", "allWhite", XtRBoolean,
\r
1210 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
\r
1211 XtRImmediate, (XtPointer) False},
\r
1212 { "pieceToCharTable", "pieceToCharTable", XtRString,
\r
1213 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
\r
1214 XtRImmediate, (XtPointer) 0},
\r
1215 { "alphaRank", "alphaRank", XtRBoolean,
\r
1216 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
\r
1217 XtRImmediate, (XtPointer) False},
\r
1218 { "testClaims", "testClaims", XtRBoolean,
\r
1219 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
\r
1220 XtRImmediate, (XtPointer) True},
\r
1221 { "checkMates", "checkMates", XtRBoolean,
\r
1222 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
\r
1223 XtRImmediate, (XtPointer) True},
\r
1224 { "materialDraws", "materialDraws", XtRBoolean,
\r
1225 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
\r
1226 XtRImmediate, (XtPointer) True},
\r
1227 { "trivialDraws", "trivialDraws", XtRBoolean,
\r
1228 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
\r
1229 XtRImmediate, (XtPointer) False},
\r
1230 { "ruleMoves", "ruleMoves", XtRInt,
\r
1231 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
\r
1232 XtRImmediate, (XtPointer) 51},
\r
1233 { "repeatsToDraw", "repeatsToDraw", XtRInt,
\r
1234 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
\r
1235 XtRImmediate, (XtPointer) 6},
\r
1236 { "engineDebugOutput", "engineDebugOutput", XtRInt,
\r
1237 sizeof(int), XtOffset(AppDataPtr, engineComments),
\r
1238 XtRImmediate, (XtPointer) 1},
\r
1239 { "userName", "userName", XtRString,
\r
1240 sizeof(int), XtOffset(AppDataPtr, userName),
\r
1241 XtRImmediate, (XtPointer) 0},
\r
1242 { "autoKibitz", "autoKibitz", XtRBoolean,
\r
1243 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
\r
1244 XtRImmediate, (XtPointer) False},
\r
1245 { "firstTimeOdds", "firstTimeOdds", XtRInt,
\r
1246 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
\r
1247 XtRImmediate, (XtPointer) 1},
\r
1248 { "secondTimeOdds", "secondTimeOdds", XtRInt,
\r
1249 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
\r
1250 XtRImmediate, (XtPointer) 1},
\r
1251 { "timeOddsMode", "timeOddsMode", XtRInt,
\r
1252 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
\r
1253 XtRImmediate, (XtPointer) 0},
\r
1254 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
\r
1255 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
\r
1256 XtRImmediate, (XtPointer) 1},
\r
1257 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
\r
1258 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
\r
1259 XtRImmediate, (XtPointer) 1},
\r
1260 { "firstNPS", "firstNPS", XtRInt,
\r
1261 sizeof(int), XtOffset(AppDataPtr, firstNPS),
\r
1262 XtRImmediate, (XtPointer) -1},
\r
1263 { "secondNPS", "secondNPS", XtRInt,
\r
1264 sizeof(int), XtOffset(AppDataPtr, secondNPS),
\r
1265 XtRImmediate, (XtPointer) -1},
\r
1266 { "serverMoves", "serverMoves", XtRString,
\r
1267 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
\r
1268 XtRImmediate, (XtPointer) 0},
\r
1269 { "serverPause", "serverPause", XtRInt,
\r
1270 sizeof(int), XtOffset(AppDataPtr, serverPause),
\r
1271 XtRImmediate, (XtPointer) 0},
\r
1272 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
\r
1273 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
\r
1274 XtRImmediate, (XtPointer) False},
1275 { "userName", "userName", XtRString,
\r
1276 sizeof(String), XtOffset(AppDataPtr, userName),
\r
1277 XtRImmediate, (XtPointer) 0},
\r
1278 { "egtFormats", "egtFormats", XtRString,
\r
1279 sizeof(String), XtOffset(AppDataPtr, egtFormats),
\r
1280 XtRImmediate, (XtPointer) 0},
\r
1281 { "rewindIndex", "rewindIndex", XtRInt,
\r
1282 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
\r
1283 XtRImmediate, (XtPointer) 0},
\r
1284 { "sameColorGames", "sameColorGames", XtRInt,
\r
1285 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
\r
1286 XtRImmediate, (XtPointer) 0},
\r
1287 { "smpCores", "smpCores", XtRInt,
\r
1288 sizeof(int), XtOffset(AppDataPtr, smpCores),
\r
1289 XtRImmediate, (XtPointer) 1},
\r
1291 // [HGM] Winboard_x UCI options
\r
1292 { "firstIsUCI", "firstIsUCI", XtRBoolean,
\r
1293 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
\r
1294 XtRImmediate, (XtPointer) False},
\r
1295 { "secondIsUCI", "secondIsUCI", XtRBoolean,
\r
1296 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
\r
1297 XtRImmediate, (XtPointer) False},
\r
1298 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
\r
1299 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
\r
1300 XtRImmediate, (XtPointer) True},
\r
1301 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
\r
1302 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
\r
1303 XtRImmediate, (XtPointer) True},
\r
1304 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
\r
1305 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
\r
1306 XtRImmediate, (XtPointer) False},
\r
1307 { "defaultHashSize", "defaultHashSize", XtRInt,
\r
1308 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
\r
1309 XtRImmediate, (XtPointer) 64},
\r
1310 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
\r
1311 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
\r
1312 XtRImmediate, (XtPointer) 4},
\r
1313 { "polyglotDir", "polyglotDir", XtRString,
\r
1314 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
\r
1315 XtRImmediate, (XtPointer) "." },
\r
1316 { "polyglotBook", "polyglotBook", XtRString,
\r
1317 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
\r
1318 XtRImmediate, (XtPointer) "" },
\r
1319 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
\r
1320 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
\r
1321 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
\r
1324 XrmOptionDescRec shellOptions[] = {
\r
1325 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
\r
1326 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
\r
1327 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
\r
1328 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
\r
1329 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
\r
1330 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
\r
1331 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
\r
1332 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
\r
1333 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
\r
1334 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
\r
1335 { "-initString", "initString", XrmoptionSepArg, NULL },
\r
1336 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
\r
1337 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
\r
1338 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
\r
1339 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
\r
1340 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
\r
1341 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
\r
1342 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
\r
1343 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
\r
1344 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
\r
1345 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
\r
1346 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
\r
1347 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
\r
1348 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
\r
1349 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
\r
1350 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
\r
1351 { "-fh", "firstHost", XrmoptionSepArg, NULL },
\r
1352 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
\r
1353 { "-sh", "secondHost", XrmoptionSepArg, NULL },
\r
1354 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
\r
1355 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
\r
1356 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
\r
1357 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
\r
1358 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
\r
1359 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
\r
1360 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
\r
1361 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
\r
1362 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
\r
1363 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
\r
1364 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
\r
1365 { "-td", "timeDelay", XrmoptionSepArg, NULL },
\r
1366 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
\r
1367 { "-tc", "timeControl", XrmoptionSepArg, NULL },
\r
1368 { "-internetChessServerMode", "internetChessServerMode",
\r
1369 XrmoptionSepArg, NULL },
\r
1370 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
\r
1371 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
\r
1372 { "-internetChessServerHost", "internetChessServerHost",
\r
1373 XrmoptionSepArg, NULL },
\r
1374 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
\r
1375 { "-internetChessServerPort", "internetChessServerPort",
\r
1376 XrmoptionSepArg, NULL },
\r
1377 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
\r
1378 { "-internetChessServerCommPort", "internetChessServerCommPort",
\r
1379 XrmoptionSepArg, NULL },
\r
1380 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
\r
1381 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
\r
1382 XrmoptionSepArg, NULL },
\r
1383 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
\r
1384 { "-internetChessServerHelper", "internetChessServerHelper",
\r
1385 XrmoptionSepArg, NULL },
\r
1386 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
\r
1387 { "-internetChessServerInputBox", "internetChessServerInputBox",
\r
1388 XrmoptionSepArg, NULL },
\r
1389 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
\r
1390 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
\r
1391 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
\r
1392 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
\r
1393 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
\r
1394 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
\r
1395 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
\r
1396 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
\r
1397 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
\r
1398 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
\r
1399 { "-gateway", "gateway", XrmoptionSepArg, NULL },
\r
1400 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
\r
1401 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
\r
1402 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
\r
1403 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
\r
1404 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
\r
1405 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
\r
1406 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
\r
1407 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
\r
1408 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
\r
1409 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
\r
1410 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
\r
1411 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
\r
1412 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
\r
1413 { "-blind", "blindfold", XrmoptionNoArg, "True" },
\r
1414 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
\r
1415 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
\r
1416 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
\r
1417 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
\r
1418 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
\r
1419 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
\r
1420 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
\r
1421 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
\r
1422 { "-mm", "matchMode", XrmoptionNoArg, "True" },
\r
1423 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
\r
1424 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
\r
1425 { "-mg", "matchGames", XrmoptionSepArg, NULL },
\r
1426 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
\r
1427 { "-mono", "monoMode", XrmoptionNoArg, "True" },
\r
1428 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
\r
1429 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
\r
1430 { "-debug", "debugMode", XrmoptionNoArg, "True" },
\r
1431 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
\r
1432 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
\r
1433 { "-clock", "clockMode", XrmoptionNoArg, "True" },
\r
1434 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
\r
1435 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
\r
1436 { "-size", "boardSize", XrmoptionSepArg, NULL },
\r
1437 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
\r
1438 { "-st", "searchTime", XrmoptionSepArg, NULL },
\r
1439 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
\r
1440 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
\r
1441 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
\r
1442 { "-coords", "showCoords", XrmoptionNoArg, "True" },
\r
1443 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
\r
1445 { "-showJail", "showJail", XrmoptionSepArg, NULL },
\r
1446 { "-jail", "showJail", XrmoptionNoArg, "1" },
\r
1447 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
\r
1448 { "-xjail", "showJail", XrmoptionNoArg, "0" },
\r
1450 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
\r
1451 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
\r
1452 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
\r
1453 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
\r
1454 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
\r
1455 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
\r
1456 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
\r
1457 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
\r
1458 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
\r
1459 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
\r
1460 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
\r
1461 { "-font", "font", XrmoptionSepArg, NULL },
\r
1462 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
\r
1463 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
\r
1464 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
\r
1465 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
\r
1466 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
\r
1467 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
\r
1468 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
\r
1469 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
\r
1470 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
\r
1471 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
\r
1472 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
\r
1473 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
\r
1474 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
\r
1475 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
\r
1476 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
\r
1477 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
\r
1478 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
\r
1479 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
\r
1480 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
\r
1481 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
\r
1483 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
\r
1484 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
\r
1485 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
\r
1487 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
\r
1488 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
\r
1489 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
\r
1490 { "-premove", "premove", XrmoptionSepArg, NULL },
\r
1491 { "-pre", "premove", XrmoptionNoArg, "True" },
\r
1492 { "-xpre", "premove", XrmoptionNoArg, "False" },
\r
1493 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
\r
1494 { "-legal", "testLegality", XrmoptionNoArg, "True" },
\r
1495 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
\r
1496 { "-flipView", "flipView", XrmoptionSepArg, NULL },
\r
1497 { "-flip", "flipView", XrmoptionNoArg, "True" },
\r
1498 { "-xflip", "flipView", XrmoptionNoArg, "False" },
\r
1499 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
\r
1500 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
\r
1501 XrmoptionSepArg, NULL },
\r
1502 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
\r
1503 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
\r
1504 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
\r
1505 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
\r
1506 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
\r
1507 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
\r
1508 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
\r
1509 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
\r
1510 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
\r
1511 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
\r
1512 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
\r
1514 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
\r
1515 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
\r
1516 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
\r
1517 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
\r
1518 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
\r
1519 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
\r
1520 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
\r
1521 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
\r
1522 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
\r
1523 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
\r
1524 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
\r
1525 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
\r
1526 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
\r
1527 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
\r
1528 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
\r
1529 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
\r
1530 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
\r
1531 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
\r
1532 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
\r
1533 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
\r
1534 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
\r
1535 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
\r
1536 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
\r
1537 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
\r
1538 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
\r
1539 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
\r
1540 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
\r
1541 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
\r
1542 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
\r
1543 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
\r
1545 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
\r
1546 { "-flash", "flashCount", XrmoptionNoArg, "3" },
\r
1547 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
\r
1548 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
\r
1549 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
\r
1550 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
\r
1551 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
\r
1552 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
\r
1553 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
\r
1554 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
\r
1555 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
\r
1556 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
\r
1557 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
\r
1558 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
\r
1559 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
\r
1560 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
\r
1561 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
\r
1562 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
\r
1563 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
\r
1564 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
\r
1565 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
\r
1566 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
\r
1567 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
\r
1568 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
\r
1569 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
\r
1570 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
\r
1571 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
\r
1572 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
\r
1573 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
\r
1574 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
\r
1575 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
\r
1576 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
\r
1577 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
\r
1578 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
\r
1579 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
\r
1580 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
\r
1581 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
\r
1582 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
\r
1583 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
\r
1584 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
\r
1585 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
\r
1586 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
\r
1587 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
\r
1588 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
\r
1589 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
\r
1590 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
\r
1591 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
\r
1592 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
\r
1593 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
\r
1594 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
\r
1595 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
\r
1596 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
\r
1597 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
\r
1598 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
\r
1599 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
\r
1600 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
\r
1601 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
\r
1602 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
\r
1603 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
\r
1604 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
\r
1605 { "-mode", "initialMode", XrmoptionSepArg, NULL },
\r
1606 { "-variant", "variant", XrmoptionSepArg, NULL },
\r
1607 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
\r
1608 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
\r
1609 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
\r
1610 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
\r
1611 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
\r
1612 /* [AS,HR] New features */
\r
1613 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
\r
1614 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
\r
1615 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
\r
1616 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
\r
1617 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
\r
1618 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
\r
1619 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
\r
1620 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
\r
1621 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
\r
1622 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
\r
1623 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
\r
1624 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
\r
1625 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
\r
1626 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
\r
1627 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
\r
1628 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
\r
1629 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
\r
1630 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
\r
1631 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
\r
1632 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
\r
1633 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
\r
1634 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
\r
1636 /* [HGM,HR] User-selectable board size */
\r
1637 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
\r
1638 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
\r
1639 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
\r
1641 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
\r
1642 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
\r
1643 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
\r
1644 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
\r
1645 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
\r
1646 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
\r
1647 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
\r
1648 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
\r
1649 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
\r
1650 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
\r
1651 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
\r
1652 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
\r
1653 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
\r
1654 { "-userName", "userName", XrmoptionSepArg, NULL },
\r
1655 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
\r
1656 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
\r
1657 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
\r
1658 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
\r
1659 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
\r
1660 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
\r
1661 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
\r
1662 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
\r
1663 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
\r
1664 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
\r
1665 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
\r
1666 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
\r
1667 { "-userName", "userName", XrmoptionSepArg, NULL },
\r
1668 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
\r
1669 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
\r
1670 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
\r
1674 XtActionsRec boardActions[] = {
\r
1675 { "DrawPosition", DrawPositionProc },
\r
1676 { "HandleUserMove", HandleUserMove },
\r
1677 { "AnimateUserMove", AnimateUserMove },
\r
1678 { "FileNameAction", FileNameAction },
\r
1679 { "AskQuestionProc", AskQuestionProc },
\r
1680 { "AskQuestionReplyAction", AskQuestionReplyAction },
\r
1681 { "PieceMenuPopup", PieceMenuPopup },
\r
1682 { "WhiteClock", WhiteClock },
\r
1683 { "BlackClock", BlackClock },
\r
1684 { "Iconify", Iconify },
\r
1685 { "ResetProc", ResetProc },
\r
1686 { "LoadGameProc", LoadGameProc },
\r
1687 { "LoadNextGameProc", LoadNextGameProc },
\r
1688 { "LoadPrevGameProc", LoadPrevGameProc },
\r
1689 { "LoadSelectedProc", LoadSelectedProc },
\r
1690 { "ReloadGameProc", ReloadGameProc },
\r
1691 { "LoadPositionProc", LoadPositionProc },
\r
1692 { "LoadNextPositionProc", LoadNextPositionProc },
\r
1693 { "LoadPrevPositionProc", LoadPrevPositionProc },
\r
1694 { "ReloadPositionProc", ReloadPositionProc },
\r
1695 { "CopyPositionProc", CopyPositionProc },
\r
1696 { "PastePositionProc", PastePositionProc },
\r
1697 { "CopyGameProc", CopyGameProc },
\r
1698 { "PasteGameProc", PasteGameProc },
\r
1699 { "SaveGameProc", SaveGameProc },
\r
1700 { "SavePositionProc", SavePositionProc },
\r
1701 { "MailMoveProc", MailMoveProc },
\r
1702 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
\r
1703 { "QuitProc", QuitProc },
\r
1704 { "MachineWhiteProc", MachineWhiteProc },
\r
1705 { "MachineBlackProc", MachineBlackProc },
\r
1706 { "AnalysisModeProc", AnalyzeModeProc },
\r
1707 { "AnalyzeFileProc", AnalyzeFileProc },
\r
1708 { "TwoMachinesProc", TwoMachinesProc },
\r
1709 { "IcsClientProc", IcsClientProc },
\r
1710 { "EditGameProc", EditGameProc },
\r
1711 { "EditPositionProc", EditPositionProc },
\r
1712 { "TrainingProc", EditPositionProc },
\r
1713 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
\r
1714 { "ShowGameListProc", ShowGameListProc },
\r
1715 { "ShowMoveListProc", HistoryShowProc},
\r
1716 { "EditTagsProc", EditCommentProc },
\r
1717 { "EditCommentProc", EditCommentProc },
\r
1718 { "IcsAlarmProc", IcsAlarmProc },
\r
1719 { "IcsInputBoxProc", IcsInputBoxProc },
\r
1720 { "PauseProc", PauseProc },
\r
1721 { "AcceptProc", AcceptProc },
\r
1722 { "DeclineProc", DeclineProc },
\r
1723 { "RematchProc", RematchProc },
\r
1724 { "CallFlagProc", CallFlagProc },
\r
1725 { "DrawProc", DrawProc },
\r
1726 { "AdjournProc", AdjournProc },
\r
1727 { "AbortProc", AbortProc },
\r
1728 { "ResignProc", ResignProc },
\r
1729 { "EnterKeyProc", EnterKeyProc },
\r
1730 { "StopObservingProc", StopObservingProc },
\r
1731 { "StopExaminingProc", StopExaminingProc },
\r
1732 { "BackwardProc", BackwardProc },
\r
1733 { "ForwardProc", ForwardProc },
\r
1734 { "ToStartProc", ToStartProc },
\r
1735 { "ToEndProc", ToEndProc },
\r
1736 { "RevertProc", RevertProc },
\r
1737 { "TruncateGameProc", TruncateGameProc },
\r
1738 { "MoveNowProc", MoveNowProc },
\r
1739 { "RetractMoveProc", RetractMoveProc },
\r
1740 { "AlwaysQueenProc", AlwaysQueenProc },
\r
1741 { "AnimateDraggingProc", AnimateDraggingProc },
\r
1742 { "AnimateMovingProc", AnimateMovingProc },
\r
1743 { "AutoflagProc", AutoflagProc },
\r
1744 { "AutoflipProc", AutoflipProc },
\r
1745 { "AutobsProc", AutobsProc },
\r
1746 { "AutoraiseProc", AutoraiseProc },
\r
1747 { "AutosaveProc", AutosaveProc },
\r
1748 { "BlindfoldProc", BlindfoldProc },
\r
1749 { "FlashMovesProc", FlashMovesProc },
\r
1750 { "FlipViewProc", FlipViewProc },
\r
1751 { "GetMoveListProc", GetMoveListProc },
\r
1753 { "HighlightDraggingProc", HighlightDraggingProc },
\r
1755 { "HighlightLastMoveProc", HighlightLastMoveProc },
\r
1756 { "IcsAlarmProc", IcsAlarmProc },
\r
1757 { "MoveSoundProc", MoveSoundProc },
\r
1758 { "OldSaveStyleProc", OldSaveStyleProc },
\r
1759 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
\r
1760 { "PonderNextMoveProc", PonderNextMoveProc },
\r
1761 { "PopupExitMessageProc", PopupExitMessageProc },
\r
1762 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
\r
1763 { "PremoveProc", PremoveProc },
\r
1764 { "QuietPlayProc", QuietPlayProc },
\r
1765 { "ShowCoordsProc", ShowCoordsProc },
\r
1766 { "ShowThinkingProc", ShowThinkingProc },
\r
1767 { "HideThinkingProc", HideThinkingProc },
\r
1768 { "TestLegalityProc", TestLegalityProc },
\r
1769 { "InfoProc", InfoProc },
\r
1770 { "ManProc", ManProc },
\r
1771 { "HintProc", HintProc },
\r
1772 { "BookProc", BookProc },
\r
1773 { "AboutGameProc", AboutGameProc },
\r
1774 { "AboutProc", AboutProc },
\r
1775 { "DebugProc", DebugProc },
\r
1776 { "NothingProc", NothingProc },
\r
1777 { "CommentPopDown", (XtActionProc) CommentPopDown },
\r
1778 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
\r
1779 { "TagsPopDown", (XtActionProc) TagsPopDown },
\r
1780 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
\r
1781 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
\r
1782 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
\r
1783 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
\r
1784 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
\r
1785 { "GameListPopDown", (XtActionProc) GameListPopDown },
\r
1786 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
\r
1787 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
\r
1788 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
\r
1789 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
\r
1790 { "EnginePopDown", (XtActionProc) EnginePopDown },
\r
1791 { "UciPopDown", (XtActionProc) UciPopDown },
\r
1792 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
\r
1793 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
\r
1796 char globalTranslations[] =
\r
1797 ":<Key>R: ResignProc() \n \
\r
1798 :<Key>r: ResetProc() \n \
\r
1799 :<Key>g: LoadGameProc() \n \
\r
1800 :<Key>N: LoadNextGameProc() \n \
\r
1801 :<Key>P: LoadPrevGameProc() \n \
\r
1802 :<Key>Q: QuitProc() \n \
\r
1803 :<Key>F: ToEndProc() \n \
\r
1804 :<Key>f: ForwardProc() \n \
\r
1805 :<Key>B: ToStartProc() \n \
\r
1806 :<Key>b: BackwardProc() \n \
\r
1807 :<Key>p: PauseProc() \n \
\r
1808 :<Key>d: DrawProc() \n \
\r
1809 :<Key>t: CallFlagProc() \n \
\r
1810 :<Key>i: Iconify() \n \
\r
1811 :<Key>c: Iconify() \n \
\r
1812 :<Key>v: FlipViewProc() \n \
\r
1813 <KeyDown>Control_L: BackwardProc() \n \
\r
1814 <KeyUp>Control_L: ForwardProc() \n \
\r
1815 <KeyDown>Control_R: BackwardProc() \n \
\r
1816 <KeyUp>Control_R: ForwardProc() \n \
\r
1817 Shift<Key>1: AskQuestionProc(\"Direct command\",\
\r
1818 \"Send to chess program:\",,1) \n \
\r
1819 Shift<Key>2: AskQuestionProc(\"Direct command\",\
\r
1820 \"Send to second chess program:\",,2) \n";
\r
1822 char boardTranslations[] =
\r
1823 "<Btn1Down>: HandleUserMove() \n \
\r
1824 <Btn1Up>: HandleUserMove() \n \
\r
1825 <Btn1Motion>: AnimateUserMove() \n \
\r
1826 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
\r
1827 PieceMenuPopup(menuB) \n \
\r
1828 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
\r
1829 PieceMenuPopup(menuW) \n \
\r
1830 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
\r
1831 PieceMenuPopup(menuW) \n \
\r
1832 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
\r
1833 PieceMenuPopup(menuB) \n";
\r
1835 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
\r
1836 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
\r
1838 char ICSInputTranslations[] =
\r
1839 "<Key>Return: EnterKeyProc() \n";
\r
1841 String xboardResources[] = {
\r
1842 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
\r
1843 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
\r
1844 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
\r
1849 /* Max possible square size */
\r
1850 #define MAXSQSIZE 256
\r
1852 static int xpm_avail[MAXSQSIZE];
\r
1854 #ifdef HAVE_DIR_STRUCT
\r
1856 /* Extract piece size from filename */
\r
1858 xpm_getsize(name, len, ext)
\r
1869 if ((p=strchr(name, '.')) == NULL ||
\r
1870 StrCaseCmp(p+1, ext) != 0)
\r
1876 while (*p && isdigit(*p))
\r
1883 /* Setup xpm_avail */
\r
1885 xpm_getavail(dirname, ext)
\r
1890 struct dirent *ent;
\r
1893 for (i=0; i<MAXSQSIZE; ++i)
\r
1896 if (appData.debugMode)
\r
1897 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
\r
1899 dir = opendir(dirname);
\r
1902 fprintf(stderr, "%s: Can't access XPM directory %s\n",
\r
1903 programName, dirname);
\r
1907 while ((ent=readdir(dir)) != NULL) {
\r
1908 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
\r
1909 if (i > 0 && i < MAXSQSIZE)
\r
1919 xpm_print_avail(fp, ext)
\r
1925 fprintf(fp, "Available `%s' sizes:\n", ext);
\r
1926 for (i=1; i<MAXSQSIZE; ++i) {
\r
1928 printf("%d\n", i);
\r
1932 /* Return XPM piecesize closest to size */
\r
1934 xpm_closest_to(dirname, size, ext)
\r
1940 int sm_diff = MAXSQSIZE;
\r
1944 xpm_getavail(dirname, ext);
\r
1946 if (appData.debugMode)
\r
1947 xpm_print_avail(stderr, ext);
\r
1949 for (i=1; i<MAXSQSIZE; ++i) {
\r
1950 if (xpm_avail[i]) {
\r
1952 diff = (diff<0) ? -diff : diff;
\r
1953 if (diff < sm_diff) {
\r
1961 fprintf(stderr, "Error: No `%s' files!\n", ext);
\r
1967 #else /* !HAVE_DIR_STRUCT */
\r
1968 /* If we are on a system without a DIR struct, we can't
\r
1969 read the directory, so we can't collect a list of
\r
1970 filenames, etc., so we can't do any size-fitting. */
\r
1972 xpm_closest_to(dirname, size, ext)
\r
1977 fprintf(stderr, "Warning: No DIR structure found on this system --\n");
\r
1978 fprintf(stderr, " Unable to autosize for XPM/XIM pieces.\n");
\r
1979 fprintf(stderr, " Please report this error to frankm@hiwaay.net.\n");
\r
1980 fprintf(stderr, " Include system type & operating system in message.\n");
\r
1983 #endif /* HAVE_DIR_STRUCT */
\r
1985 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
\r
1986 "magenta", "cyan", "white" };
\r
1990 TextColors textColors[(int)NColorClasses];
\r
1992 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
\r
1994 parse_color(str, which)
\r
1998 char *p, buf[100], *d;
\r
2001 if (strlen(str) > 99) /* watch bounds on buf */
\r
2006 for (i=0; i<which; ++i) {
\r
2007 p = strchr(p, ',');
\r
2013 /* Could be looking at something like:
\r
2015 .. in which case we want to stop on a comma also */
\r
2016 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
\r
2020 return -1; /* Use default for empty field */
\r
2023 if (which == 2 || isdigit(*p))
\r
2026 while (*p && isalpha(*p))
\r
2031 for (i=0; i<8; ++i) {
\r
2032 if (!StrCaseCmp(buf, cnames[i]))
\r
2033 return which? (i+40) : (i+30);
\r
2035 if (!StrCaseCmp(buf, "default")) return -1;
\r
2037 fprintf(stderr, "%s: unrecognized color %s\n", programName, buf);
\r
2042 parse_cpair(cc, str)
\r
2046 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
\r
2047 fprintf(stderr, "%s: can't parse foreground color in `%s'\n",
\r
2048 programName, str);
\r
2052 /* bg and attr are optional */
\r
2053 textColors[(int)cc].bg = parse_color(str, 1);
\r
2054 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
\r
2055 textColors[(int)cc].attr = 0;
\r
2061 /* Arrange to catch delete-window events */
\r
2062 Atom wm_delete_window;
\r
2064 CatchDeleteWindow(Widget w, String procname)
\r
2066 char buf[MSG_SIZ];
\r
2067 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
\r
2068 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
\r
2069 XtAugmentTranslations(w, XtParseTranslationTable(buf));
\r
2076 XtSetArg(args[0], XtNiconic, False);
\r
2077 XtSetValues(shellWidget, args, 1);
\r
2079 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
\r
2083 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
\r
2085 #define BoardSize int
\r
2086 void InitDrawingSizes(BoardSize boardSize, int flags)
\r
2087 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
\r
2088 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2090 XtGeometryResult gres;
\r
2093 if(!formWidget) return;
\r
2096 * Enable shell resizing.
\r
2098 shellArgs[0].value = (XtArgVal) &w;
\r
2099 shellArgs[1].value = (XtArgVal) &h;
\r
2100 XtGetValues(shellWidget, shellArgs, 2);
\r
2102 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
\r
2103 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
\r
2104 XtSetValues(shellWidget, &shellArgs[2], 4);
2106 XtSetArg(args[0], XtNdefaultDistance, &sep);
\r XtGetValues(formWidget, args, 1);
2108 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
2109 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2112 XtSetArg(args[0], XtNwidth, boardWidth);
\r
2113 XtSetArg(args[1], XtNheight, boardHeight);
\r
2114 XtSetValues(boardWidget, args, 2);
\r
2116 timerWidth = (boardWidth - sep) / 2;
\r
2117 XtSetArg(args[0], XtNwidth, timerWidth);
\r
2118 XtSetValues(whiteTimerWidget, args, 1);
\r
2119 XtSetValues(blackTimerWidget, args, 1);
\r
2121 XawFormDoLayout(formWidget, False);
\r
2123 if (appData.titleInWindow) {
\r
2125 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2126 XtSetArg(args[i], XtNheight, &h); i++;
\r
2127 XtGetValues(titleWidget, args, i);
\r
2128 if (smallLayout) {
\r
2129 w = boardWidth - 2*bor;
\r
2131 XtSetArg(args[0], XtNwidth, &w);
\r
2132 XtGetValues(menuBarWidget, args, 1);
\r
2133 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
\r
2136 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
\r
2137 if (gres != XtGeometryYes && appData.debugMode) {
\r
2139 "%s: titleWidget geometry error %d %d %d %d %d\n",
\r
2140 programName, gres, w, h, wr, hr);
\r
2144 XawFormDoLayout(formWidget, True);
\r
2147 * Inhibit shell resizing.
\r
2149 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
\r
2150 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
\r
2151 shellArgs[4].value = shellArgs[2].value = w;
\r
2152 shellArgs[5].value = shellArgs[3].value = h;
\r
2153 XtSetValues(shellWidget, &shellArgs[0], 6);
\r
2162 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
\r
2163 XSetWindowAttributes window_attributes;
\r
2165 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
\r
2166 XrmValue vFrom, vTo;
\r
2167 XtGeometryResult gres;
\r
2170 int forceMono = False;
2171 #define INDIRECTION
\r
2173 // [HGM] before anything else, expand any indirection files amongst options
2174 char *argvCopy[1000]; // 1000 seems enough
2175 char newArgs[10000]; // holds actual characters
2178 srandom(time(0)); // [HGM] book: make random truly random
2181 for(i=0; i<argc; i++) {
2182 if(j >= 1000-2) { printf("too many arguments\n"); exit(-1); }
2183 //fprintf(stderr, "arg %s\n", argv[i]);
2184 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2186 FILE *f = fopen(argv[i]+1, "rb");
2187 if(f == NULL) { fprintf(stderr, "ignore %s\n", argv[i]); continue; } // do not expand non-existing
2188 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2189 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2191 if(j >= 1000-2) { printf("too many arguments\n"); exit(-1); }
2192 newArgs[k++] = 0; // terminate current arg
2193 if(k >= 10000-1) { printf("too long arguments\n"); exit(-1); }
2194 argvCopy[j++] = newArgs + k; // get ready for next
2196 if(k >= 10000-1) { printf("too long arguments\n"); exit(-1); }
2209 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2210 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2216 setbuf(stdout, NULL);
\r
2217 setbuf(stderr, NULL);
\r
2220 programName = strrchr(argv[0], '/');
\r
2221 if (programName == NULL)
\r
2222 programName = argv[0];
\r
2227 XtAppInitialize(&appContext, "XBoard", shellOptions,
\r
2228 XtNumber(shellOptions),
\r
2229 &argc, argv, xboardResources, NULL, 0);
\r
2231 fprintf(stderr, "%s: unrecognized argument %s\n",
\r
2232 programName, argv[1]);
\r
2236 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
\r
2239 if (chdir(chessDir) != 0) {
\r
2240 fprintf(stderr, "%s: can't cd to CHESSDIR: ", programName);
\r
2246 p = getenv("HOME");
\r
2247 if (p == NULL) p = "/tmp";
\r
2248 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
\r
2249 gameCopyFilename = (char*) malloc(i);
\r
2250 gamePasteFilename = (char*) malloc(i);
\r
2251 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
\r
2252 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
\r
2254 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
\r
2255 clientResources, XtNumber(clientResources),
\r
2258 /* [HGM,HR] make sure board size is acceptable */
\r
2259 if(appData.NrFiles > BOARD_SIZE ||
\r
2260 appData.NrRanks > BOARD_SIZE )
\r
2261 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2264 /* This feature does not work; animation needs a rewrite */
\r
2265 appData.highlightDragging = FALSE;
\r
2269 xDisplay = XtDisplay(shellWidget);
\r
2270 xScreen = DefaultScreen(xDisplay);
\r
2271 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
\r
2273 gameInfo.variant = StringToVariant(appData.variant);
\r
2274 InitPosition(FALSE);
\r
2277 * Determine boardSize
\r
2279 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
\r
2282 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
\r
2283 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
\r
2284 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
\r
2285 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
\r
2290 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
\r
2292 if (isdigit(appData.boardSize[0])) {
\r
2293 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
\r
2294 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
\r
2295 &fontPxlSize, &smallLayout, &tinyLayout);
\r
2297 fprintf(stderr, "%s: bad boardSize syntax %s\n",
\r
2298 programName, appData.boardSize);
\r
2302 /* Find some defaults; use the nearest known size */
\r
2303 SizeDefaults *szd, *nearest;
\r
2304 int distance = 99999;
\r
2305 nearest = szd = sizeDefaults;
\r
2306 while (szd->name != NULL) {
\r
2307 if (abs(szd->squareSize - squareSize) < distance) {
\r
2309 distance = abs(szd->squareSize - squareSize);
\r
2310 if (distance == 0) break;
\r
2314 if (i < 2) lineGap = nearest->lineGap;
\r
2315 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
\r
2316 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
\r
2317 if (i < 5) fontPxlSize = nearest->fontPxlSize;
\r
2318 if (i < 6) smallLayout = nearest->smallLayout;
\r
2319 if (i < 7) tinyLayout = nearest->tinyLayout;
\r
2322 SizeDefaults *szd = sizeDefaults;
\r
2323 if (*appData.boardSize == NULLCHAR) {
\r
2324 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
\r
2325 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
\r
2328 if (szd->name == NULL) szd--;
\r
2330 while (szd->name != NULL &&
\r
2331 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
\r
2332 if (szd->name == NULL) {
\r
2333 fprintf(stderr, "%s: unrecognized boardSize name %s\n",
\r
2334 programName, appData.boardSize);
\r
2338 squareSize = szd->squareSize;
\r
2339 lineGap = szd->lineGap;
\r
2340 clockFontPxlSize = szd->clockFontPxlSize;
\r
2341 coordFontPxlSize = szd->coordFontPxlSize;
\r
2342 fontPxlSize = szd->fontPxlSize;
\r
2343 smallLayout = szd->smallLayout;
\r
2344 tinyLayout = szd->tinyLayout;
\r
2347 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
\r
2348 if (strlen(appData.pixmapDirectory) > 0) {
\r
2349 p = ExpandPathName(appData.pixmapDirectory);
\r
2351 fprintf(stderr, "Error expanding path name \"%s\"\n",
\r
2352 appData.pixmapDirectory);
\r
2355 if (appData.debugMode) {
\r
2356 fprintf(stderr, "XBoard square size (hint): %d\n", squareSize);
\r
2357 fprintf(stderr, "%s fulldir:%s:\n", IMAGE_EXT, p);
\r
2359 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
\r
2360 if (appData.debugMode) {
\r
2361 fprintf(stderr, "Closest %s size: %d\n", IMAGE_EXT, squareSize);
\r
2365 /* [HR] height treated separately (hacked) */
\r
2366 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
2367 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
\r
2368 if (appData.showJail == 1) {
\r
2369 /* Jail on top and bottom */
\r
2370 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
\r
2371 XtSetArg(boardArgs[2], XtNheight,
\r
2372 boardHeight + 2*(lineGap + squareSize));
\r
2373 } else if (appData.showJail == 2) {
\r
2374 /* Jail on sides */
\r
2375 XtSetArg(boardArgs[1], XtNwidth,
\r
2376 boardWidth + 2*(lineGap + squareSize));
\r
2377 XtSetArg(boardArgs[2], XtNheight, boardHeight);
\r
2380 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
\r
2381 XtSetArg(boardArgs[2], XtNheight, boardHeight);
\r
2385 * Determine what fonts to use.
\r
2387 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
\r
2388 clockFontID = XLoadFont(xDisplay, appData.clockFont);
\r
2389 clockFontStruct = XQueryFont(xDisplay, clockFontID);
\r
2390 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
\r
2391 coordFontID = XLoadFont(xDisplay, appData.coordFont);
\r
2392 coordFontStruct = XQueryFont(xDisplay, coordFontID);
\r
2393 appData.font = FindFont(appData.font, fontPxlSize);
\r
2394 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
\r
2395 countFontStruct = XQueryFont(xDisplay, countFontID);
\r
2396 // appData.font = FindFont(appData.font, fontPxlSize);
\r
2398 xdb = XtDatabase(xDisplay);
\r
2399 XrmPutStringResource(&xdb, "*font", appData.font);
\r
2402 * Detect if there are not enough colors available and adapt.
\r
2404 if (DefaultDepth(xDisplay, xScreen) <= 2) {
\r
2405 appData.monoMode = True;
\r
2408 if (!appData.monoMode) {
\r
2409 vFrom.addr = (caddr_t) appData.lightSquareColor;
\r
2410 vFrom.size = strlen(appData.lightSquareColor);
\r
2411 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2412 if (vTo.addr == NULL) {
\r
2413 appData.monoMode = True;
\r
2416 lightSquareColor = *(Pixel *) vTo.addr;
\r
2419 if (!appData.monoMode) {
\r
2420 vFrom.addr = (caddr_t) appData.darkSquareColor;
\r
2421 vFrom.size = strlen(appData.darkSquareColor);
\r
2422 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2423 if (vTo.addr == NULL) {
\r
2424 appData.monoMode = True;
\r
2427 darkSquareColor = *(Pixel *) vTo.addr;
\r
2430 if (!appData.monoMode) {
\r
2431 vFrom.addr = (caddr_t) appData.whitePieceColor;
\r
2432 vFrom.size = strlen(appData.whitePieceColor);
\r
2433 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2434 if (vTo.addr == NULL) {
\r
2435 appData.monoMode = True;
\r
2438 whitePieceColor = *(Pixel *) vTo.addr;
\r
2441 if (!appData.monoMode) {
\r
2442 vFrom.addr = (caddr_t) appData.blackPieceColor;
\r
2443 vFrom.size = strlen(appData.blackPieceColor);
\r
2444 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2445 if (vTo.addr == NULL) {
\r
2446 appData.monoMode = True;
\r
2449 blackPieceColor = *(Pixel *) vTo.addr;
\r
2453 if (!appData.monoMode) {
\r
2454 vFrom.addr = (caddr_t) appData.highlightSquareColor;
\r
2455 vFrom.size = strlen(appData.highlightSquareColor);
\r
2456 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2457 if (vTo.addr == NULL) {
\r
2458 appData.monoMode = True;
\r
2461 highlightSquareColor = *(Pixel *) vTo.addr;
\r
2465 if (!appData.monoMode) {
\r
2466 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
\r
2467 vFrom.size = strlen(appData.premoveHighlightColor);
\r
2468 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2469 if (vTo.addr == NULL) {
\r
2470 appData.monoMode = True;
\r
2473 premoveHighlightColor = *(Pixel *) vTo.addr;
\r
2478 fprintf(stderr, "%s: too few colors available; trying monochrome mode\n",
\r
2482 if (appData.monoMode && appData.debugMode) {
\r
2483 fprintf(stderr, "white pixel = 0x%lx, black pixel = 0x%lx\n",
\r
2484 (unsigned long) XWhitePixel(xDisplay, xScreen),
\r
2485 (unsigned long) XBlackPixel(xDisplay, xScreen));
\r
2488 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
\r
2489 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
\r
2490 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
\r
2491 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
\r
2492 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
\r
2493 parse_cpair(ColorTell, appData.colorTell) < 0 ||
\r
2494 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
\r
2495 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
\r
2496 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
\r
2497 parse_cpair(ColorNormal, appData.colorNormal) < 0)
\r
2499 if (appData.colorize) {
\r
2501 "%s: can't parse color names; disabling colorization\n",
\r
2504 appData.colorize = FALSE;
\r
2506 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
\r
2507 textColors[ColorNone].attr = 0;
\r
2509 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
\r
2512 * widget hierarchy
\r
2515 layoutName = "tinyLayout";
\r
2516 } else if (smallLayout) {
\r
2517 layoutName = "smallLayout";
\r
2519 layoutName = "normalLayout";
\r
2521 /* Outer layoutWidget is there only to provide a name for use in
\r
2522 resources that depend on the layout style */
\r
2524 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
\r
2525 layoutArgs, XtNumber(layoutArgs));
\r
2527 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
\r
2528 formArgs, XtNumber(formArgs));
\r
2529 XtSetArg(args[0], XtNdefaultDistance, &sep);
\r
2530 XtGetValues(formWidget, args, 1);
\r
2533 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
\r
2534 XtSetArg(args[0], XtNtop, XtChainTop);
\r
2535 XtSetArg(args[1], XtNbottom, XtChainTop);
2536 XtSetValues(menuBarWidget, args, 2);
\r
2538 widgetList[j++] = whiteTimerWidget =
\r
2539 XtCreateWidget("whiteTime", labelWidgetClass,
\r
2540 formWidget, timerArgs, XtNumber(timerArgs));
\r
2541 XtSetArg(args[0], XtNfont, clockFontStruct);
\r
2542 XtSetArg(args[1], XtNtop, XtChainTop);
\r
2543 XtSetArg(args[2], XtNbottom, XtChainTop);
2544 XtSetValues(whiteTimerWidget, args, 3);
\r
2546 widgetList[j++] = blackTimerWidget =
\r
2547 XtCreateWidget("blackTime", labelWidgetClass,
\r
2548 formWidget, timerArgs, XtNumber(timerArgs));
\r
2549 XtSetArg(args[0], XtNfont, clockFontStruct);
\r
2550 XtSetArg(args[1], XtNtop, XtChainTop);
\r
2551 XtSetArg(args[2], XtNbottom, XtChainTop);
2552 XtSetValues(blackTimerWidget, args, 3);
\r
2554 if (appData.titleInWindow) {
\r
2555 widgetList[j++] = titleWidget =
\r
2556 XtCreateWidget("title", labelWidgetClass, formWidget,
\r
2557 titleArgs, XtNumber(titleArgs));
\r
2558 XtSetArg(args[0], XtNtop, XtChainTop);
\r
2559 XtSetArg(args[1], XtNbottom, XtChainTop);
2560 XtSetValues(titleWidget, args, 2);
\r
2563 if (appData.showButtonBar) {
\r
2564 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
\r
2565 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
\r
2566 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2567 XtSetArg(args[2], XtNtop, XtChainTop);
\r
2568 XtSetArg(args[3], XtNbottom, XtChainTop);
2569 XtSetValues(buttonBarWidget, args, 4);
\r
2572 widgetList[j++] = messageWidget =
\r
2573 XtCreateWidget("message", labelWidgetClass, formWidget,
\r
2574 messageArgs, XtNumber(messageArgs));
2575 XtSetArg(args[0], XtNtop, XtChainTop);
\r
2576 XtSetArg(args[1], XtNbottom, XtChainTop);
2577 XtSetValues(messageWidget, args, 2);
\r
2579 widgetList[j++] = boardWidget =
\r
2580 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
\r
2581 XtNumber(boardArgs));
\r
2583 XtManageChildren(widgetList, j);
\r
2585 timerWidth = (boardWidth - sep) / 2;
\r
2586 XtSetArg(args[0], XtNwidth, timerWidth);
\r
2587 XtSetValues(whiteTimerWidget, args, 1);
\r
2588 XtSetValues(blackTimerWidget, args, 1);
\r
2590 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
\r
2591 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
\r
2592 XtGetValues(whiteTimerWidget, args, 2);
\r
2594 if (appData.showButtonBar) {
\r
2595 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
\r
2596 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
\r
2597 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
\r
2601 * formWidget uses these constraints but they are stored
\r
2602 * in the children.
\r
2605 XtSetArg(args[i], XtNfromHoriz, 0); i++;
\r
2606 XtSetValues(menuBarWidget, args, i);
\r
2607 if (appData.titleInWindow) {
\r
2608 if (smallLayout) {
\r
2610 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2611 XtSetValues(whiteTimerWidget, args, i);
\r
2613 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2614 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2615 XtSetValues(blackTimerWidget, args, i);
\r
2617 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2618 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
\r
2619 XtSetValues(titleWidget, args, i);
\r
2621 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2622 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2623 XtSetValues(messageWidget, args, i);
\r
2624 if (appData.showButtonBar) {
\r
2626 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2627 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2628 XtSetValues(buttonBarWidget, args, i);
\r
2632 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2633 XtSetValues(whiteTimerWidget, args, i);
\r
2635 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2636 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2637 XtSetValues(blackTimerWidget, args, i);
\r
2639 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
\r
2640 XtSetValues(titleWidget, args, i);
\r
2642 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2643 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2644 XtSetValues(messageWidget, args, i);
\r
2645 if (appData.showButtonBar) {
\r
2647 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2648 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2649 XtSetValues(buttonBarWidget, args, i);
\r
2654 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2655 XtSetValues(whiteTimerWidget, args, i);
\r
2657 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2658 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2659 XtSetValues(blackTimerWidget, args, i);
\r
2661 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2662 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2663 XtSetValues(messageWidget, args, i);
\r
2664 if (appData.showButtonBar) {
\r
2666 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2667 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2668 XtSetValues(buttonBarWidget, args, i);
\r
2672 XtSetArg(args[0], XtNfromVert, messageWidget);
\r
2673 XtSetArg(args[1], XtNtop, XtChainTop);
\r
2674 XtSetArg(args[2], XtNbottom, XtChainBottom);
2675 XtSetArg(args[3], XtNleft, XtChainLeft);
\r
2676 XtSetArg(args[4], XtNright, XtChainRight);
2677 XtSetValues(boardWidget, args, 5);
\r
2679 XtRealizeWidget(shellWidget);
\r
2682 * Correct the width of the message and title widgets.
\r
2683 * It is not known why some systems need the extra fudge term.
\r
2684 * The value "2" is probably larger than needed.
\r
2686 XawFormDoLayout(formWidget, False);
\r
2688 #define WIDTH_FUDGE 2
\r
2690 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2691 XtSetArg(args[i], XtNheight, &h); i++;
\r
2692 XtGetValues(messageWidget, args, i);
\r
2693 if (appData.showButtonBar) {
\r
2695 XtSetArg(args[i], XtNwidth, &w); i++;
\r
2696 XtGetValues(buttonBarWidget, args, i);
\r
2697 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
\r
2699 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
\r
2702 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
\r
2703 if (gres != XtGeometryYes && appData.debugMode) {
\r
2704 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
\r
2705 programName, gres, w, h, wr, hr);
\r
2708 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
\r
2709 /* The size used for the child widget in layout lags one resize behind
\r
2710 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
\r
2712 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
\r
2713 if (gres != XtGeometryYes && appData.debugMode) {
\r
2714 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
\r
2715 programName, gres, w, h, wr, hr);
\r
2718 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
\r
2719 XtSetArg(args[1], XtNright, XtChainRight);
2720 XtSetValues(messageWidget, args, 2);
\r
2722 if (appData.titleInWindow) {
\r
2724 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2725 XtSetArg(args[i], XtNheight, &h); i++;
\r
2726 XtGetValues(titleWidget, args, i);
\r
2727 if (smallLayout) {
\r
2728 w = boardWidth - 2*bor;
\r
2730 XtSetArg(args[0], XtNwidth, &w);
\r
2731 XtGetValues(menuBarWidget, args, 1);
\r
2732 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
\r
2735 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
\r
2736 if (gres != XtGeometryYes && appData.debugMode) {
\r
2738 "%s: titleWidget geometry error %d %d %d %d %d\n",
\r
2739 programName, gres, w, h, wr, hr);
\r
2742 XawFormDoLayout(formWidget, True);
\r
2744 xBoardWindow = XtWindow(boardWidget);
\r
2746 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
\r
2747 // not need to go into InitDrawingSizes().
\r
2751 * Create X checkmark bitmap and initialize option menu checks.
\r
2753 ReadBitmap(&xMarkPixmap, "checkmark.bm",
\r
2754 checkmark_bits, checkmark_width, checkmark_height);
\r
2755 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
2756 if (appData.alwaysPromoteToQueen) {
\r
2757 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
\r
2760 if (appData.animateDragging) {
\r
2761 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2762 "menuOptions.Animate Dragging"),
\r
2765 if (appData.animate) {
\r
2766 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
\r
2769 if (appData.autoComment) {
\r
2770 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
\r
2773 if (appData.autoCallFlag) {
\r
2774 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
\r
2777 if (appData.autoFlipView) {
\r
2778 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
\r
2781 if (appData.autoObserve) {
\r
2782 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
\r
2785 if (appData.autoRaiseBoard) {
\r
2786 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2787 "menuOptions.Auto Raise Board"), args, 1);
\r
2789 if (appData.autoSaveGames) {
\r
2790 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2793 if (appData.saveGameFile[0] != NULLCHAR) {
\r
2794 /* Can't turn this off from menu */
\r
2795 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2797 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2801 if (appData.blindfold) {
\r
2802 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2803 "menuOptions.Blindfold"), args, 1);
\r
2805 if (appData.flashCount > 0) {
\r
2806 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2807 "menuOptions.Flash Moves"),
\r
2810 if (appData.getMoveList) {
\r
2811 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
\r
2815 if (appData.highlightDragging) {
\r
2816 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2817 "menuOptions.Highlight Dragging"),
\r
2821 if (appData.highlightLastMove) {
\r
2822 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2823 "menuOptions.Highlight Last Move"),
\r
2826 if (appData.icsAlarm) {
\r
2827 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
\r
2830 if (appData.ringBellAfterMoves) {
\r
2831 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
\r
2834 if (appData.oldSaveStyle) {
\r
2835 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2836 "menuOptions.Old Save Style"), args, 1);
\r
2838 if (appData.periodicUpdates) {
\r
2839 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2840 "menuOptions.Periodic Updates"), args, 1);
\r
2842 if (appData.ponderNextMove) {
\r
2843 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2844 "menuOptions.Ponder Next Move"), args, 1);
\r
2846 if (appData.popupExitMessage) {
\r
2847 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2848 "menuOptions.Popup Exit Message"), args, 1);
\r
2850 if (appData.popupMoveErrors) {
\r
2851 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2852 "menuOptions.Popup Move Errors"), args, 1);
\r
2854 if (appData.premove) {
\r
2855 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2856 "menuOptions.Premove"), args, 1);
\r
2858 if (appData.quietPlay) {
\r
2859 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2860 "menuOptions.Quiet Play"), args, 1);
\r
2862 if (appData.showCoords) {
\r
2863 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
\r
2866 if (appData.hideThinkingFromHuman) {
\r
2867 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
\r
2870 if (appData.testLegality) {
\r
2871 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
\r
2878 ReadBitmap(&wIconPixmap, "icon_white.bm",
\r
2879 icon_white_bits, icon_white_width, icon_white_height);
\r
2880 ReadBitmap(&bIconPixmap, "icon_black.bm",
\r
2881 icon_black_bits, icon_black_width, icon_black_height);
\r
2882 iconPixmap = wIconPixmap;
\r
2884 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
\r
2885 XtSetValues(shellWidget, args, i);
\r
2888 * Create a cursor for the board widget.
\r
2890 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
\r
2891 XChangeWindowAttributes(xDisplay, xBoardWindow,
\r
2892 CWCursor, &window_attributes);
\r
2895 * Inhibit shell resizing.
\r
2897 shellArgs[0].value = (XtArgVal) &w;
\r
2898 shellArgs[1].value = (XtArgVal) &h;
\r
2899 XtGetValues(shellWidget, shellArgs, 2);
\r
2900 shellArgs[4].value = shellArgs[2].value = w;
\r
2901 shellArgs[5].value = shellArgs[3].value = h;
\r
2902 XtSetValues(shellWidget, &shellArgs[2], 4);
2903 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
\r
2904 marginH = h - boardHeight;
\r
2906 CatchDeleteWindow(shellWidget, "QuitProc");
\r
2911 if (appData.bitmapDirectory[0] != NULLCHAR) {
\r
2914 CreateXPMPieces();
\r
2917 CreateXIMPieces();
\r
2918 /* Create regular pieces */
\r
2919 if (!useImages) CreatePieces();
\r
2922 CreatePieceMenus();
\r
2924 if (appData.animate || appData.animateDragging)
\r
2927 XtAugmentTranslations(formWidget,
\r
2928 XtParseTranslationTable(globalTranslations));
\r
2929 XtAugmentTranslations(boardWidget,
\r
2930 XtParseTranslationTable(boardTranslations));
\r
2931 XtAugmentTranslations(whiteTimerWidget,
\r
2932 XtParseTranslationTable(whiteTranslations));
\r
2933 XtAugmentTranslations(blackTimerWidget,
\r
2934 XtParseTranslationTable(blackTranslations));
\r
2936 /* Why is the following needed on some versions of X instead
\r
2937 * of a translation? */
\r
2938 XtAddEventHandler(boardWidget, ExposureMask, False,
\r
2939 (XtEventHandler) EventProc, NULL);
\r
2944 if (errorExitStatus == -1) {
\r
2945 if (appData.icsActive) {
\r
2946 /* We now wait until we see "login:" from the ICS before
\r
2947 sending the logon script (problems with timestamp otherwise) */
\r
2948 /*ICSInitScript();*/
\r
2949 if (appData.icsInputBox) ICSInputBoxPopUp();
\r
2952 signal(SIGINT, IntSigHandler);
\r
2953 signal(SIGTERM, IntSigHandler);
\r
2954 if (*appData.cmailGameName != NULLCHAR) {
\r
2955 signal(SIGUSR1, CmailSigHandler);
\r
2958 InitPosition(TRUE);
\r
2960 XtAppMainLoop(appContext);
\r
2965 ShutDownFrontEnd()
\r
2967 if (appData.icsActive && oldICSInteractionTitle != NULL) {
\r
2968 DisplayIcsInteractionTitle(oldICSInteractionTitle);
\r
2970 unlink(gameCopyFilename);
\r
2971 unlink(gamePasteFilename);
\r
2975 IntSigHandler(sig)
\r
2982 CmailSigHandler(sig)
\r
2988 signal(SIGUSR1, SIG_IGN); /* suspend handler */
\r
2990 /* Activate call-back function CmailSigHandlerCallBack() */
\r
2991 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
\r
2993 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
\r
2997 CmailSigHandlerCallBack(isr, closure, message, count, error)
\r
2998 InputSourceRef isr;
\r
3005 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
\r
3007 /**** end signal code ****/
\r
3014 char buf[MSG_SIZ];
\r
3017 f = fopen(appData.icsLogon, "r");
\r
3019 p = getenv("HOME");
\r
3023 strcat(buf, appData.icsLogon);
\r
3024 f = fopen(buf, "r");
\r
3028 ProcessICSInitScript(f);
\r
3035 EditCommentPopDown();
\r
3046 SetMenuEnables(enab)
\r
3050 if (!menuBarWidget) return;
\r
3051 while (enab->name != NULL) {
\r
3052 w = XtNameToWidget(menuBarWidget, enab->name);
\r
3054 DisplayError(enab->name, 0);
\r
3056 XtSetSensitive(w, enab->value);
\r
3062 Enables icsEnables[] = {
\r
3063 { "menuFile.Mail Move", False },
\r
3064 { "menuFile.Reload CMail Message", False },
\r
3065 { "menuMode.Machine Black", False },
\r
3066 { "menuMode.Machine White", False },
\r
3067 { "menuMode.Analysis Mode", False },
\r
3068 { "menuMode.Analyze File", False },
\r
3069 { "menuMode.Two Machines", False },
\r
3071 { "menuHelp.Hint", False },
\r
3072 { "menuHelp.Book", False },
\r
3073 { "menuStep.Move Now", False },
\r
3074 { "menuOptions.Periodic Updates", False },
\r
3075 { "menuOptions.Hide Thinking", False },
\r
3076 { "menuOptions.Ponder Next Move", False },
\r
3081 Enables ncpEnables[] = {
\r
3082 { "menuFile.Mail Move", False },
\r
3083 { "menuFile.Reload CMail Message", False },
\r
3084 { "menuMode.Machine White", False },
\r
3085 { "menuMode.Machine Black", False },
\r
3086 { "menuMode.Analysis Mode", False },
\r
3087 { "menuMode.Analyze File", False },
\r
3088 { "menuMode.Two Machines", False },
\r
3089 { "menuMode.ICS Client", False },
\r
3090 { "menuMode.ICS Input Box", False },
\r
3091 { "Action", False },
\r
3092 { "menuStep.Revert", False },
\r
3093 { "menuStep.Move Now", False },
\r
3094 { "menuStep.Retract Move", False },
\r
3095 { "menuOptions.Auto Comment", False },
\r
3096 { "menuOptions.Auto Flag", False },
\r
3097 { "menuOptions.Auto Flip View", False },
\r
3098 { "menuOptions.Auto Observe", False },
\r
3099 { "menuOptions.Auto Raise Board", False },
\r
3100 { "menuOptions.Get Move List", False },
\r
3101 { "menuOptions.ICS Alarm", False },
\r
3102 { "menuOptions.Move Sound", False },
\r
3103 { "menuOptions.Quiet Play", False },
\r
3104 { "menuOptions.Hide Thinking", False },
\r
3105 { "menuOptions.Periodic Updates", False },
\r
3106 { "menuOptions.Ponder Next Move", False },
\r
3107 { "menuHelp.Hint", False },
\r
3108 { "menuHelp.Book", False },
\r
3112 Enables gnuEnables[] = {
\r
3113 { "menuMode.ICS Client", False },
\r
3114 { "menuMode.ICS Input Box", False },
\r
3115 { "menuAction.Accept", False },
\r
3116 { "menuAction.Decline", False },
\r
3117 { "menuAction.Rematch", False },
\r
3118 { "menuAction.Adjourn", False },
\r
3119 { "menuAction.Stop Examining", False },
\r
3120 { "menuAction.Stop Observing", False },
\r
3121 { "menuStep.Revert", False },
\r
3122 { "menuOptions.Auto Comment", False },
\r
3123 { "menuOptions.Auto Observe", False },
\r
3124 { "menuOptions.Auto Raise Board", False },
\r
3125 { "menuOptions.Get Move List", False },
\r
3126 { "menuOptions.Premove", False },
\r
3127 { "menuOptions.Quiet Play", False },
\r
3129 /* The next two options rely on SetCmailMode being called *after* */
\r
3130 /* SetGNUMode so that when GNU is being used to give hints these */
\r
3131 /* menu options are still available */
\r
3133 { "menuFile.Mail Move", False },
\r
3134 { "menuFile.Reload CMail Message", False },
\r
3138 Enables cmailEnables[] = {
\r
3139 { "Action", True },
\r
3140 { "menuAction.Call Flag", False },
\r
3141 { "menuAction.Draw", True },
\r
3142 { "menuAction.Adjourn", False },
\r
3143 { "menuAction.Abort", False },
\r
3144 { "menuAction.Stop Observing", False },
\r
3145 { "menuAction.Stop Examining", False },
\r
3146 { "menuFile.Mail Move", True },
\r
3147 { "menuFile.Reload CMail Message", True },
\r
3151 Enables trainingOnEnables[] = {
\r
3152 { "menuMode.Edit Comment", False },
\r
3153 { "menuMode.Pause", False },
\r
3154 { "menuStep.Forward", False },
\r
3155 { "menuStep.Backward", False },
\r
3156 { "menuStep.Forward to End", False },
\r
3157 { "menuStep.Back to Start", False },
\r
3158 { "menuStep.Move Now", False },
\r
3159 { "menuStep.Truncate Game", False },
\r
3163 Enables trainingOffEnables[] = {
\r
3164 { "menuMode.Edit Comment", True },
\r
3165 { "menuMode.Pause", True },
\r
3166 { "menuStep.Forward", True },
\r
3167 { "menuStep.Backward", True },
\r
3168 { "menuStep.Forward to End", True },
\r
3169 { "menuStep.Back to Start", True },
\r
3170 { "menuStep.Move Now", True },
\r
3171 { "menuStep.Truncate Game", True },
\r
3175 Enables machineThinkingEnables[] = {
\r
3176 { "menuFile.Load Game", False },
\r
3177 { "menuFile.Load Next Game", False },
\r
3178 { "menuFile.Load Previous Game", False },
\r
3179 { "menuFile.Reload Same Game", False },
\r
3180 { "menuFile.Paste Game", False },
\r
3181 { "menuFile.Load Position", False },
\r
3182 { "menuFile.Load Next Position", False },
\r
3183 { "menuFile.Load Previous Position", False },
\r
3184 { "menuFile.Reload Same Position", False },
\r
3185 { "menuFile.Paste Position", False },
\r
3186 { "menuMode.Machine White", False },
\r
3187 { "menuMode.Machine Black", False },
\r
3188 { "menuMode.Two Machines", False },
\r
3189 { "menuStep.Retract Move", False },
\r
3193 Enables userThinkingEnables[] = {
\r
3194 { "menuFile.Load Game", True },
\r
3195 { "menuFile.Load Next Game", True },
\r
3196 { "menuFile.Load Previous Game", True },
\r
3197 { "menuFile.Reload Same Game", True },
\r
3198 { "menuFile.Paste Game", True },
\r
3199 { "menuFile.Load Position", True },
\r
3200 { "menuFile.Load Next Position", True },
\r
3201 { "menuFile.Load Previous Position", True },
\r
3202 { "menuFile.Reload Same Position", True },
\r
3203 { "menuFile.Paste Position", True },
\r
3204 { "menuMode.Machine White", True },
\r
3205 { "menuMode.Machine Black", True },
\r
3206 { "menuMode.Two Machines", True },
\r
3207 { "menuStep.Retract Move", True },
\r
3213 SetMenuEnables(icsEnables);
\r
3219 SetMenuEnables(ncpEnables);
\r
3225 SetMenuEnables(gnuEnables);
\r
3231 SetMenuEnables(cmailEnables);
\r
3235 SetTrainingModeOn()
\r
3237 SetMenuEnables(trainingOnEnables);
\r
3238 if (appData.showButtonBar) {
\r
3239 XtSetSensitive(buttonBarWidget, False);
\r
3245 SetTrainingModeOff()
\r
3247 SetMenuEnables(trainingOffEnables);
\r
3248 if (appData.showButtonBar) {
\r
3249 XtSetSensitive(buttonBarWidget, True);
\r
3254 SetUserThinkingEnables()
\r
3256 if (appData.noChessProgram) return;
\r
3257 SetMenuEnables(userThinkingEnables);
\r
3261 SetMachineThinkingEnables()
\r
3263 if (appData.noChessProgram) return;
\r
3264 SetMenuEnables(machineThinkingEnables);
\r
3265 switch (gameMode) {
\r
3266 case MachinePlaysBlack:
\r
3267 case MachinePlaysWhite:
\r
3268 case TwoMachinesPlay:
\r
3269 XtSetSensitive(XtNameToWidget(menuBarWidget,
\r
3270 ModeToWidgetName(gameMode)), True);
\r
3277 #define Abs(n) ((n)<0 ? -(n) : (n))
\r
3280 * Find a font that matches "pattern" that is as close as
\r
3281 * possible to the targetPxlSize. Prefer fonts that are k
\r
3282 * pixels smaller to fonts that are k pixels larger. The
\r
3283 * pattern must be in the X Consortium standard format,
\r
3284 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
\r
3285 * The return value should be freed with XtFree when no
\r
3288 char *FindFont(pattern, targetPxlSize)
\r
3290 int targetPxlSize;
\r
3292 char **fonts, *p, *best, *scalable, *scalableTail;
\r
3293 int i, j, nfonts, minerr, err, pxlSize;
\r
3295 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
\r
3297 fprintf(stderr, "%s: no fonts match pattern %s\n",
\r
3298 programName, pattern);
\r
3304 for (i=0; i<nfonts; i++) {
\r
3307 if (*p != '-') continue;
\r
3309 if (*p == NULLCHAR) break;
\r
3310 if (*p++ == '-') j++;
\r
3312 if (j < 7) continue;
\r
3313 pxlSize = atoi(p);
\r
3314 if (pxlSize == 0) {
\r
3315 scalable = fonts[i];
\r
3318 err = pxlSize - targetPxlSize;
\r
3319 if (Abs(err) < Abs(minerr) ||
\r
3320 (minerr > 0 && err < 0 && -err == minerr)) {
\r
3326 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
\r
3327 /* If the error is too big and there is a scalable font,
\r
3328 use the scalable font. */
\r
3329 int headlen = scalableTail - scalable;
\r
3330 p = (char *) XtMalloc(strlen(scalable) + 10);
\r
3331 while (isdigit(*scalableTail)) scalableTail++;
\r
3332 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
\r
3334 p = (char *) XtMalloc(strlen(best) + 1);
\r
3337 if (appData.debugMode) {
\r
3338 fprintf(debugFP, "resolved %s at pixel size %d\n to %s\n",
\r
3339 pattern, targetPxlSize, p);
\r
3341 XFreeFontNames(fonts);
\r
3347 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
\r
3348 | GCBackground | GCFunction | GCPlaneMask;
\r
3349 XGCValues gc_values;
\r
3350 GC copyInvertedGC;
\r
3352 gc_values.plane_mask = AllPlanes;
\r
3353 gc_values.line_width = lineGap;
\r
3354 gc_values.line_style = LineSolid;
\r
3355 gc_values.function = GXcopy;
\r
3357 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3358 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3359 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3361 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3362 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3363 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3364 XSetFont(xDisplay, coordGC, coordFontID);
\r
3366 // [HGM] make font for holdings counts (white on black0
3367 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3368 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3369 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3370 XSetFont(xDisplay, countGC, countFontID);
\r
3372 if (appData.monoMode) {
\r
3373 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3374 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3375 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3377 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3378 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3379 lightSquareGC = wbPieceGC
\r
3380 = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3382 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3383 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3384 darkSquareGC = bwPieceGC
\r
3385 = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3387 if (DefaultDepth(xDisplay, xScreen) == 1) {
\r
3388 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
\r
3389 gc_values.function = GXcopyInverted;
\r
3390 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3391 gc_values.function = GXcopy;
\r
3392 if (XBlackPixel(xDisplay, xScreen) == 1) {
\r
3393 bwPieceGC = darkSquareGC;
\r
3394 wbPieceGC = copyInvertedGC;
\r
3396 bwPieceGC = copyInvertedGC;
\r
3397 wbPieceGC = lightSquareGC;
\r
3401 gc_values.foreground = highlightSquareColor;
\r
3402 gc_values.background = highlightSquareColor;
\r
3403 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3405 gc_values.foreground = premoveHighlightColor;
\r
3406 gc_values.background = premoveHighlightColor;
\r
3407 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3409 gc_values.foreground = lightSquareColor;
\r
3410 gc_values.background = darkSquareColor;
\r
3411 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3413 gc_values.foreground = darkSquareColor;
\r
3414 gc_values.background = lightSquareColor;
\r
3415 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3417 gc_values.foreground = jailSquareColor;
\r
3418 gc_values.background = jailSquareColor;
\r
3419 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3421 gc_values.foreground = whitePieceColor;
\r
3422 gc_values.background = darkSquareColor;
\r
3423 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3425 gc_values.foreground = whitePieceColor;
\r
3426 gc_values.background = lightSquareColor;
\r
3427 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3429 gc_values.foreground = whitePieceColor;
\r
3430 gc_values.background = jailSquareColor;
\r
3431 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3433 gc_values.foreground = blackPieceColor;
\r
3434 gc_values.background = darkSquareColor;
\r
3435 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3437 gc_values.foreground = blackPieceColor;
\r
3438 gc_values.background = lightSquareColor;
\r
3439 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3441 gc_values.foreground = blackPieceColor;
\r
3442 gc_values.background = jailSquareColor;
\r
3443 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3447 void loadXIM(xim, xmask, filename, dest, mask)
\r
3454 int x, y, w, h, p;
\r
3460 fp = fopen(filename, "rb");
\r
3462 fprintf(stderr, "%s: error loading XIM!\n", programName);
\r
3469 for (y=0; y<h; ++y) {
\r
3470 for (x=0; x<h; ++x) {
\r
3475 XPutPixel(xim, x, y, blackPieceColor);
\r
3477 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
\r
3480 XPutPixel(xim, x, y, darkSquareColor);
\r
3482 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
\r
3485 XPutPixel(xim, x, y, whitePieceColor);
\r
3487 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
\r
3490 XPutPixel(xim, x, y, lightSquareColor);
\r
3492 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
\r
3498 /* create Pixmap of piece */
\r
3499 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3500 w, h, xim->depth);
\r
3501 XPutImage(xDisplay, *dest, lightSquareGC, xim,
\r
3502 0, 0, 0, 0, w, h);
\r
3504 /* create Pixmap of clipmask
\r
3505 Note: We assume the white/black pieces have the same
\r
3506 outline, so we make only 6 masks. This is okay
\r
3507 since the XPM clipmask routines do the same. */
\r
3509 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3510 w, h, xim->depth);
\r
3511 XPutImage(xDisplay, temp, lightSquareGC, xmask,
\r
3512 0, 0, 0, 0, w, h);
\r
3514 /* now create the 1-bit version */
\r
3515 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3518 values.foreground = 1;
\r
3519 values.background = 0;
\r
3521 /* Don't use XtGetGC, not read only */
\r
3522 maskGC = XCreateGC(xDisplay, *mask,
\r
3523 GCForeground | GCBackground, &values);
\r
3524 XCopyPlane(xDisplay, temp, *mask, maskGC,
\r
3525 0, 0, squareSize, squareSize, 0, 0, 1);
\r
3526 XFreePixmap(xDisplay, temp);
\r
3530 void CreateXIMPieces()
\r
3533 char buf[MSG_SIZ];
\r
3535 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
\r
3540 /* The XSynchronize calls were copied from CreatePieces.
\r
3541 Not sure if needed, but can't hurt */
\r
3542 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3545 /* temp needed by loadXIM() */
\r
3546 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3547 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3549 if (strlen(appData.pixmapDirectory) == 0) {
\r
3553 if (appData.monoMode) {
\r
3554 DisplayFatalError("XIM pieces cannot be used in monochrome mode",
\r
3558 fprintf(stderr, "\nLoading XIMs...\n");
\r
3560 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3561 fprintf(stderr, "%d", piece+1);
\r
3562 for (kind=0; kind<4; kind++) {
\r
3563 fprintf(stderr, ".");
\r
3564 sprintf(buf, "%s/%c%s%u.xim",
\r
3565 ExpandPathName(appData.pixmapDirectory),
\r
3566 ToLower(PieceToChar((ChessSquare)piece)),
\r
3567 ximkind[kind], ss);
\r
3568 ximPieceBitmap[kind][piece] =
\r
3569 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3570 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3571 if (appData.debugMode)
\r
3572 fprintf(stderr, "(File:%s:) ", buf);
\r
3573 loadXIM(ximPieceBitmap[kind][piece],
\r
3575 &(xpmPieceBitmap[kind][piece]),
\r
3576 &(ximMaskPm[piece%(int)BlackPawn]));
\r
3578 fprintf(stderr," ");
\r
3580 /* Load light and dark squares */
\r
3581 /* If the LSQ and DSQ pieces don't exist, we will
\r
3582 draw them with solid squares. */
\r
3583 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
\r
3584 if (access(buf, 0) != 0) {
\r
3588 fprintf(stderr, "light square ");
\r
3590 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3591 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3592 if (appData.debugMode)
\r
3593 fprintf(stderr, "(File:%s:) ", buf);
\r
3595 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
\r
3596 fprintf(stderr, "dark square ");
\r
3597 sprintf(buf, "%s/dsq%u.xim",
\r
3598 ExpandPathName(appData.pixmapDirectory), ss);
\r
3599 if (appData.debugMode)
\r
3600 fprintf(stderr, "(File:%s:) ", buf);
\r
3602 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3603 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3604 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
\r
3605 xpmJailSquare = xpmLightSquare;
\r
3607 fprintf(stderr, "Done.\n");
\r
3609 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
\r
3613 void CreateXPMPieces()
\r
3615 int piece, kind, r;
\r
3616 char buf[MSG_SIZ];
\r
3617 u_int ss = squareSize;
\r
3618 XpmAttributes attr;
\r
3619 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
\r
3620 XpmColorSymbol symbols[4];
\r
3623 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
\r
3624 if (appData.debugMode) {
\r
3625 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
\r
3626 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
\r
3630 /* The XSynchronize calls were copied from CreatePieces.
\r
3631 Not sure if needed, but can't hurt */
\r
3632 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
\r
3634 /* Setup translations so piece colors match square colors */
\r
3635 symbols[0].name = "light_piece";
\r
3636 symbols[0].value = appData.whitePieceColor;
\r
3637 symbols[1].name = "dark_piece";
\r
3638 symbols[1].value = appData.blackPieceColor;
\r
3639 symbols[2].name = "light_square";
\r
3640 symbols[2].value = appData.lightSquareColor;
\r
3641 symbols[3].name = "dark_square";
\r
3642 symbols[3].value = appData.darkSquareColor;
\r
3644 attr.valuemask = XpmColorSymbols;
\r
3645 attr.colorsymbols = symbols;
\r
3646 attr.numsymbols = 4;
\r
3648 if (appData.monoMode) {
\r
3649 DisplayFatalError("XPM pieces cannot be used in monochrome mode",
\r
3653 if (strlen(appData.pixmapDirectory) == 0) {
\r
3654 XpmPieces* pieces = builtInXpms;
\r
3657 while (pieces->size != squareSize && pieces->size) pieces++;
\r
3658 if (!pieces->size) {
\r
3659 fprintf(stderr, "No builtin XPM pieces of size %d\n", squareSize);
\r
3662 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3663 for (kind=0; kind<4; kind++) {
\r
3665 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
\r
3666 pieces->xpm[piece][kind],
\r
3667 &(xpmPieceBitmap[kind][piece]),
\r
3668 NULL, &attr)) != 0) {
\r
3669 fprintf(stderr, "Error %d loading XPM image \"%s\"\n",
\r
3676 xpmJailSquare = xpmLightSquare;
\r
3680 fprintf(stderr, "\nLoading XPMs...\n");
\r
3683 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3684 fprintf(stderr, "%d ", piece+1);
\r
3685 for (kind=0; kind<4; kind++) {
\r
3686 sprintf(buf, "%s/%c%s%u.xpm",
\r
3687 ExpandPathName(appData.pixmapDirectory),
\r
3688 ToLower(PieceToChar((ChessSquare)piece)),
\r
3689 xpmkind[kind], ss);
\r
3690 if (appData.debugMode) {
\r
3691 fprintf(stderr, "(File:%s:) ", buf);
\r
3693 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3694 &(xpmPieceBitmap[kind][piece]),
\r
3695 NULL, &attr)) != 0) {
\r
3696 fprintf(stderr, "Error %d loading XPM file \"%s\"\n",
\r
3702 /* Load light and dark squares */
\r
3703 /* If the LSQ and DSQ pieces don't exist, we will
\r
3704 draw them with solid squares. */
\r
3705 fprintf(stderr, "light square ");
\r
3706 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
\r
3707 if (access(buf, 0) != 0) {
\r
3711 if (appData.debugMode)
\r
3712 fprintf(stderr, "(File:%s:) ", buf);
\r
3714 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3715 &xpmLightSquare, NULL, &attr)) != 0) {
\r
3716 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
\r
3719 fprintf(stderr, "dark square ");
\r
3720 sprintf(buf, "%s/dsq%u.xpm",
\r
3721 ExpandPathName(appData.pixmapDirectory), ss);
\r
3722 if (appData.debugMode) {
\r
3723 fprintf(stderr, "(File:%s:) ", buf);
\r
3725 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3726 &xpmDarkSquare, NULL, &attr)) != 0) {
\r
3727 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
\r
3731 xpmJailSquare = xpmLightSquare;
\r
3732 fprintf(stderr, "Done.\n");
\r
3734 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3737 #endif /* HAVE_LIBXPM */
\r
3740 /* No built-in bitmaps */
\r
3741 void CreatePieces()
\r
3744 char buf[MSG_SIZ];
\r
3745 u_int ss = squareSize;
\r
3747 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3750 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
\r
3751 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3752 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
\r
3753 ss, kind == SOLID ? 's' : 'o');
\r
3754 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
\r
3758 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3762 /* With built-in bitmaps */
\r
3763 void CreatePieces()
\r
3765 BuiltInBits* bib = builtInBits;
\r
3767 char buf[MSG_SIZ];
\r
3768 u_int ss = squareSize;
\r
3770 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3773 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
\r
3775 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
\r
3776 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3777 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
\r
3778 ss, kind == SOLID ? 's' : 'o');
\r
3779 ReadBitmap(&pieceBitmap[kind][piece], buf,
\r
3780 bib->bits[kind][piece], ss, ss);
\r
3784 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3789 void ReadBitmap(pm, name, bits, wreq, hreq)
\r
3792 unsigned char bits[];
\r
3798 char msg[MSG_SIZ], fullname[MSG_SIZ];
\r
3800 if (*appData.bitmapDirectory != NULLCHAR) {
\r
3801 strcpy(fullname, appData.bitmapDirectory);
\r
3802 strcat(fullname, "/");
\r
3803 strcat(fullname, name);
\r
3804 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
\r
3805 &w, &h, pm, &x_hot, &y_hot);
\r
3806 if (errcode != BitmapSuccess) {
\r
3807 switch (errcode) {
\r
3808 case BitmapOpenFailed:
\r
3809 sprintf(msg, "Can't open bitmap file %s", fullname);
\r
3811 case BitmapFileInvalid:
\r
3812 sprintf(msg, "Invalid bitmap in file %s", fullname);
\r
3814 case BitmapNoMemory:
\r
3815 sprintf(msg, "Ran out of memory reading bitmap file %s",
\r
3819 sprintf(msg, "Unknown XReadBitmapFile error %d on file %s",
\r
3820 errcode, fullname);
\r
3823 fprintf(stderr, "%s: %s...using built-in\n",
\r
3824 programName, msg);
\r
3825 } else if (w != wreq || h != hreq) {
\r
3827 "%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n",
\r
3828 programName, fullname, w, h, wreq, hreq);
\r
3833 if (bits == NULL) {
\r
3835 fprintf(stderr, "%s: No built-in bitmap for %s; giving up\n",
\r
3836 programName, name);
\r
3839 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
\r
3841 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
\r
3850 if (lineGap == 0) return;
\r
3852 /* [HR] Split this into 2 loops for non-square boards. */
\r
3854 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3855 gridSegments[i].x1 = 0;
\r
3856 gridSegments[i].x2 =
\r
3857 lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
3858 gridSegments[i].y1 = gridSegments[i].y2
\r
3859 = lineGap / 2 + (i * (squareSize + lineGap));
\r
3862 for (j = 0; j < BOARD_WIDTH + 1; j++) {
\r
3863 gridSegments[j + i].y1 = 0;
\r
3864 gridSegments[j + i].y2 =
\r
3865 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
\r
3866 gridSegments[j + i].x1 = gridSegments[j + i].x2
\r
3867 = lineGap / 2 + (j * (squareSize + lineGap));
\r
3871 static void MenuBarSelect(w, addr, index)
\r
3876 XtActionProc proc = (XtActionProc) addr;
\r
3878 (proc)(NULL, NULL, NULL, NULL);
\r
3881 void CreateMenuBarPopup(parent, name, mb)
\r
3887 Widget menu, entry;
\r
3891 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
\r
3894 XtSetArg(args[j], XtNleftMargin, 20); j++;
\r
3895 XtSetArg(args[j], XtNrightMargin, 20); j++;
\r
3897 while (mi->string != NULL) {
\r
3898 if (strcmp(mi->string, "----") == 0) {
\r
3899 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
\r
3902 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
\r
3904 XtAddCallback(entry, XtNcallback,
\r
3905 (XtCallbackProc) MenuBarSelect,
\r
3906 (caddr_t) mi->proc);
\r
3912 Widget CreateMenuBar(mb)
\r
3916 Widget anchor, menuBar;
\r
3918 char menuName[MSG_SIZ];
\r
3921 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
\r
3922 XtSetArg(args[j], XtNvSpace, 0); j++;
\r
3923 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3924 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
\r
3925 formWidget, args, j);
\r
3927 while (mb->name != NULL) {
\r
3928 strcpy(menuName, "menu");
\r
3929 strcat(menuName, mb->name);
\r
3931 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
\r
3933 char shortName[2];
\r
3934 shortName[0] = mb->name[0];
\r
3935 shortName[1] = NULLCHAR;
\r
3936 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
\r
3938 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3939 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
\r
3940 menuBar, args, j);
\r
3941 CreateMenuBarPopup(menuBar, menuName, mb);
\r
3947 Widget CreateButtonBar(mi)
\r
3951 Widget button, buttonBar;
\r
3955 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
\r
3957 XtSetArg(args[j], XtNhSpace, 0); j++;
\r
3959 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3960 XtSetArg(args[j], XtNvSpace, 0); j++;
\r
3961 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
\r
3962 formWidget, args, j);
\r
3964 while (mi->string != NULL) {
\r
3967 XtSetArg(args[j], XtNinternalWidth, 2); j++;
\r
3968 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3970 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
\r
3971 buttonBar, args, j);
\r
3972 XtAddCallback(button, XtNcallback,
\r
3973 (XtCallbackProc) MenuBarSelect,
\r
3974 (caddr_t) mi->proc);
\r
3981 CreatePieceMenu(name, color)
\r
3986 Widget entry, menu;
\r
3988 ChessSquare selection;
\r
3990 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
\r
3991 boardWidget, args, 0);
\r
3993 for (i = 0; i < PIECE_MENU_SIZE; i++) {
\r
3994 String item = pieceMenuStrings[color][i];
\r
3996 if (strcmp(item, "----") == 0) {
\r
3997 entry = XtCreateManagedWidget(item, smeLineObjectClass,
\r
4000 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
\r
4002 selection = pieceMenuTranslation[color][i];
\r
4003 XtAddCallback(entry, XtNcallback,
\r
4004 (XtCallbackProc) PieceMenuSelect,
\r
4005 (caddr_t) selection);
\r
4006 if (selection == WhitePawn || selection == BlackPawn) {
\r
4007 XtSetArg(args[0], XtNpopupOnEntry, entry);
\r
4008 XtSetValues(menu, args, 1);
\r
4016 CreatePieceMenus()
\r
4021 ChessSquare selection;
\r
4023 whitePieceMenu = CreatePieceMenu("menuW", 0);
\r
4024 blackPieceMenu = CreatePieceMenu("menuB", 1);
\r
4026 XtRegisterGrabAction(PieceMenuPopup, True,
\r
4027 (unsigned)(ButtonPressMask|ButtonReleaseMask),
\r
4028 GrabModeAsync, GrabModeAsync);
\r
4030 XtSetArg(args[0], XtNlabel, "Drop");
\r
4031 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
\r
4032 boardWidget, args, 1);
\r
4033 for (i = 0; i < DROP_MENU_SIZE; i++) {
\r
4034 String item = dropMenuStrings[i];
\r
4036 if (strcmp(item, "----") == 0) {
\r
4037 entry = XtCreateManagedWidget(item, smeLineObjectClass,
\r
4038 dropMenu, NULL, 0);
\r
4040 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
\r
4041 dropMenu, NULL, 0);
\r
4042 selection = dropMenuTranslation[i];
\r
4043 XtAddCallback(entry, XtNcallback,
\r
4044 (XtCallbackProc) DropMenuSelect,
\r
4045 (caddr_t) selection);
\r
4050 void SetupDropMenu()
\r
4058 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
\r
4059 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
\r
4060 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
\r
4061 dmEnables[i].piece);
\r
4062 XtSetSensitive(entry, p != NULL || !appData.testLegality
\r
4063 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
\r
4064 && !appData.icsActive));
\r
4066 while (p && *p++ == dmEnables[i].piece) count++;
\r
4067 sprintf(label, "%s %d", dmEnables[i].widget, count);
\r
4069 XtSetArg(args[j], XtNlabel, label); j++;
\r
4070 XtSetValues(entry, args, j);
\r
4074 void PieceMenuPopup(w, event, params, num_params)
\r
4078 Cardinal *num_params;
\r
4081 if (event->type != ButtonPress) return;
\r
4082 if (errorUp) ErrorPopDown();
\r
4083 switch (gameMode) {
\r
4084 case EditPosition:
\r
4085 case IcsExamining:
\r
4086 whichMenu = params[0];
\r
4088 case IcsPlayingWhite:
\r
4089 case IcsPlayingBlack:
\r
4091 case MachinePlaysWhite:
\r
4092 case MachinePlaysBlack:
\r
4093 if (appData.testLegality &&
\r
4094 gameInfo.variant != VariantBughouse &&
\r
4095 gameInfo.variant != VariantCrazyhouse) return;
\r
4097 whichMenu = "menuD";
\r
4103 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
\r
4104 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
\r
4105 pmFromX = pmFromY = -1;
\r
4109 pmFromX = BOARD_WIDTH - 1 - pmFromX;
\r
4111 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
\r
4113 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
\r
4116 static void PieceMenuSelect(w, piece, junk)
\r
4118 ChessSquare piece;
\r
4121 if (pmFromX < 0 || pmFromY < 0) return;
\r
4122 EditPositionMenuEvent(piece, pmFromX, pmFromY);
\r
4125 static void DropMenuSelect(w, piece, junk)
\r
4127 ChessSquare piece;
\r
4130 if (pmFromX < 0 || pmFromY < 0) return;
\r
4131 DropMenuEvent(piece, pmFromX, pmFromY);
\r
4134 void WhiteClock(w, event, prms, nprms)
\r
4140 if (gameMode == EditPosition || gameMode == IcsExamining) {
\r
4141 SetWhiteToPlayEvent();
\r
4142 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
\r
4147 void BlackClock(w, event, prms, nprms)
\r
4153 if (gameMode == EditPosition || gameMode == IcsExamining) {
\r
4154 SetBlackToPlayEvent();
\r
4155 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
\r
4162 * If the user selects on a border boundary, return -1; if off the board,
\r
4163 * return -2. Otherwise map the event coordinate to the square.
\r
4165 int EventToSquare(x, limit)
\r
4173 if ((x % (squareSize + lineGap)) >= squareSize)
\r
4175 x /= (squareSize + lineGap);
\r
4181 static void do_flash_delay(msec)
\r
4182 unsigned long msec;
\r
4187 static void drawHighlight(file, rank, gc)
\r
4193 if (lineGap == 0 || appData.blindfold) return;
\r
4196 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
\r
4197 (squareSize + lineGap);
\r
4198 y = lineGap/2 + rank * (squareSize + lineGap);
\r
4200 x = lineGap/2 + file * (squareSize + lineGap);
\r
4201 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
\r
4202 (squareSize + lineGap);
\r
4205 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
\r
4206 squareSize+lineGap, squareSize+lineGap);
\r
4209 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
\r
4210 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
\r
4213 SetHighlights(fromX, fromY, toX, toY)
\r
4214 int fromX, fromY, toX, toY;
\r
4216 if (hi1X != fromX || hi1Y != fromY) {
\r
4217 if (hi1X >= 0 && hi1Y >= 0) {
\r
4218 drawHighlight(hi1X, hi1Y, lineGC);
\r
4220 if (fromX >= 0 && fromY >= 0) {
\r
4221 drawHighlight(fromX, fromY, highlineGC);
\r
4224 if (hi2X != toX || hi2Y != toY) {
\r
4225 if (hi2X >= 0 && hi2Y >= 0) {
\r
4226 drawHighlight(hi2X, hi2Y, lineGC);
\r
4228 if (toX >= 0 && toY >= 0) {
\r
4229 drawHighlight(toX, toY, highlineGC);
\r
4241 SetHighlights(-1, -1, -1, -1);
\r
4246 SetPremoveHighlights(fromX, fromY, toX, toY)
\r
4247 int fromX, fromY, toX, toY;
\r
4249 if (pm1X != fromX || pm1Y != fromY) {
\r
4250 if (pm1X >= 0 && pm1Y >= 0) {
\r
4251 drawHighlight(pm1X, pm1Y, lineGC);
\r
4253 if (fromX >= 0 && fromY >= 0) {
\r
4254 drawHighlight(fromX, fromY, prelineGC);
\r
4257 if (pm2X != toX || pm2Y != toY) {
\r
4258 if (pm2X >= 0 && pm2Y >= 0) {
\r
4259 drawHighlight(pm2X, pm2Y, lineGC);
\r
4261 if (toX >= 0 && toY >= 0) {
\r
4262 drawHighlight(toX, toY, prelineGC);
\r
4272 ClearPremoveHighlights()
\r
4274 SetPremoveHighlights(-1, -1, -1, -1);
\r
4277 static void BlankSquare(x, y, color, piece, dest)
\r
4279 ChessSquare piece;
\r
4282 if (useImages && useImageSqs) {
\r
4285 case 1: /* light */
\r
4286 pm = xpmLightSquare;
\r
4288 case 0: /* dark */
\r
4289 pm = xpmDarkSquare;
\r
4291 case 2: /* neutral */
\r
4293 pm = xpmJailSquare;
\r
4296 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
\r
4297 squareSize, squareSize, x, y);
\r
4301 case 1: /* light */
\r
4302 gc = lightSquareGC;
\r
4304 case 0: /* dark */
\r
4305 gc = darkSquareGC;
\r
4307 case 2: /* neutral */
\r
4309 gc = jailSquareGC;
\r
4312 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
\r
4317 I split out the routines to draw a piece so that I could
\r
4318 make a generic flash routine.
\r
4320 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
\r
4321 ChessSquare piece;
\r
4322 int square_color, x, y;
\r
4325 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
\r
4326 switch (square_color) {
\r
4327 case 1: /* light */
\r
4328 case 2: /* neutral */
\r
4330 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
\r
4331 ? *pieceToOutline(piece)
\r
4332 : *pieceToSolid(piece),
\r
4333 dest, bwPieceGC, 0, 0,
\r
4334 squareSize, squareSize, x, y);
\r
4336 case 0: /* dark */
\r
4337 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
\r
4338 ? *pieceToSolid(piece)
\r
4339 : *pieceToOutline(piece),
\r
4340 dest, wbPieceGC, 0, 0,
\r
4341 squareSize, squareSize, x, y);
\r
4346 static void monoDrawPiece(piece, square_color, x, y, dest)
\r
4347 ChessSquare piece;
\r
4348 int square_color, x, y;
\r
4351 switch (square_color) {
\r
4352 case 1: /* light */
\r
4353 case 2: /* neutral */
\r
4355 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
\r
4356 ? *pieceToOutline(piece)
\r
4357 : *pieceToSolid(piece),
\r
4358 dest, bwPieceGC, 0, 0,
\r
4359 squareSize, squareSize, x, y, 1);
\r
4361 case 0: /* dark */
\r
4362 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
\r
4363 ? *pieceToSolid(piece)
\r
4364 : *pieceToOutline(piece),
\r
4365 dest, wbPieceGC, 0, 0,
\r
4366 squareSize, squareSize, x, y, 1);
\r
4371 static void colorDrawPiece(piece, square_color, x, y, dest)
\r
4372 ChessSquare piece;
\r
4373 int square_color, x, y;
\r
4376 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
\r
4377 switch (square_color) {
\r
4378 case 1: /* light */
\r
4379 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4380 dest, (int) piece < (int) BlackPawn
\r
4381 ? wlPieceGC : blPieceGC, 0, 0,
\r
4382 squareSize, squareSize, x, y, 1);
\r
4384 case 0: /* dark */
\r
4385 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4386 dest, (int) piece < (int) BlackPawn
\r
4387 ? wdPieceGC : bdPieceGC, 0, 0,
\r
4388 squareSize, squareSize, x, y, 1);
\r
4390 case 2: /* neutral */
\r
4392 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4393 dest, (int) piece < (int) BlackPawn
\r
4394 ? wjPieceGC : bjPieceGC, 0, 0,
\r
4395 squareSize, squareSize, x, y, 1);
\r
4400 static void colorDrawPieceImage(piece, square_color, x, y, dest)
\r
4401 ChessSquare piece;
\r
4402 int square_color, x, y;
\r
4407 switch (square_color) {
\r
4408 case 1: /* light */
\r
4409 case 2: /* neutral */
\r
4411 if ((int)piece < (int) BlackPawn) {
\r
4415 piece -= BlackPawn;
\r
4418 case 0: /* dark */
\r
4419 if ((int)piece < (int) BlackPawn) {
\r
4423 piece -= BlackPawn;
\r
4427 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
\r
4428 dest, wlPieceGC, 0, 0,
\r
4429 squareSize, squareSize, x, y);
\r
4432 typedef void (*DrawFunc)();
\r
4434 DrawFunc ChooseDrawFunc()
\r
4436 if (appData.monoMode) {
\r
4437 if (DefaultDepth(xDisplay, xScreen) == 1) {
\r
4438 return monoDrawPiece_1bit;
\r
4440 return monoDrawPiece;
\r
4444 return colorDrawPieceImage;
\r
4446 return colorDrawPiece;
\r
4450 /* [HR] determine square color depending on chess variant. */
\r
4451 static int SquareColor(row, column)
\r
4456 if (gameInfo.variant == VariantXiangqi) {
\r
4457 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
\r
4459 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
\r
4461 } else if (row <= 4) {
\r
4467 square_color = ((column + row) % 2) == 1;
\r
4470 /* [hgm] holdings: next line makes all holdings squares light */
\r
4471 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
\r
4473 return square_color;
\r
4476 void DrawSquare(row, column, piece, do_flash)
\r
4477 int row, column, do_flash;
\r
4478 ChessSquare piece;
\r
4480 int square_color, x, y, direction, font_ascent, font_descent;
\r
4483 XCharStruct overall;
\r
4484 DrawFunc drawfunc;
\r
4487 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4488 if(piece == WhiteQueen) piece = WhiteLance; else
4489 if(piece == BlackQueen) piece = BlackLance;
4492 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4493 if(piece == WhiteMarshall) piece = WhiteSilver; else
4494 if(piece == BlackMarshall) piece = BlackSilver;
4498 /* Calculate delay in milliseconds (2-delays per complete flash) */
\r
4499 flash_delay = 500 / appData.flashRate;
\r
4502 x = lineGap + ((BOARD_WIDTH-1)-column) *
\r
4503 (squareSize + lineGap);
\r
4504 y = lineGap + row * (squareSize + lineGap);
\r
4506 x = lineGap + column * (squareSize + lineGap);
\r
4507 y = lineGap + ((BOARD_HEIGHT-1)-row) *
\r
4508 (squareSize + lineGap);
\r
4511 square_color = SquareColor(row, column);
\r
4513 if ( // [HGM] holdings: blank out area between board and holdings
\r
4514 column == BOARD_LEFT-1 || column == BOARD_RGHT
\r
4515 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
\r
4516 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
\r
4517 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4519 // [HGM] print piece counts next to holdings
4520 string[1] = NULLCHAR;
\r
4521 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
\r
4522 string[0] = '0' + piece;
\r
4523 XTextExtents(countFontStruct, string, 1, &direction,
\r
4524 &font_ascent, &font_descent, &overall);
\r
4525 if (appData.monoMode) {
\r
4526 XDrawImageString(xDisplay, xBoardWindow, countGC,
\r
4527 x + squareSize - overall.width - 2,
\r
4528 y + font_ascent + 1, string, 1);
\r
4530 XDrawString(xDisplay, xBoardWindow, countGC,
\r
4531 x + squareSize - overall.width - 2,
\r
4532 y + font_ascent + 1, string, 1);
\r
4535 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
\r
4536 string[0] = '0' + piece;
\r
4537 XTextExtents(countFontStruct, string, 1, &direction,
\r
4538 &font_ascent, &font_descent, &overall);
\r
4539 if (appData.monoMode) {
\r
4540 XDrawImageString(xDisplay, xBoardWindow, countGC,
\r
4541 x + 2, y + font_ascent + 1, string, 1);
\r
4543 XDrawString(xDisplay, xBoardWindow, countGC,
\r
4544 x + 2, y + font_ascent + 1, string, 1);
\r
4548 if (piece == EmptySquare || appData.blindfold) {
\r
4549 BlankSquare(x, y, square_color, piece, xBoardWindow);
\r
4551 drawfunc = ChooseDrawFunc();
\r
4552 if (do_flash && appData.flashCount > 0) {
\r
4553 for (i=0; i<appData.flashCount; ++i) {
\r
4555 drawfunc(piece, square_color, x, y, xBoardWindow);
\r
4556 XSync(xDisplay, False);
\r
4557 do_flash_delay(flash_delay);
\r
4559 BlankSquare(x, y, square_color, piece, xBoardWindow);
\r
4560 XSync(xDisplay, False);
\r
4561 do_flash_delay(flash_delay);
\r
4564 drawfunc(piece, square_color, x, y, xBoardWindow);
\r
4568 string[1] = NULLCHAR;
\r
4569 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4570 && column >= BOARD_LEFT && column < BOARD_RGHT) {
\r
4571 string[0] = 'a' + column - BOARD_LEFT;
\r
4572 XTextExtents(coordFontStruct, string, 1, &direction,
\r
4573 &font_ascent, &font_descent, &overall);
\r
4574 if (appData.monoMode) {
\r
4575 XDrawImageString(xDisplay, xBoardWindow, coordGC,
\r
4576 x + squareSize - overall.width - 2,
\r
4577 y + squareSize - font_descent - 1, string, 1);
\r
4579 XDrawString(xDisplay, xBoardWindow, coordGC,
\r
4580 x + squareSize - overall.width - 2,
\r
4581 y + squareSize - font_descent - 1, string, 1);
\r
4584 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
\r
4585 string[0] = ONE + row;
\r
4586 XTextExtents(coordFontStruct, string, 1, &direction,
\r
4587 &font_ascent, &font_descent, &overall);
\r
4588 if (appData.monoMode) {
\r
4589 XDrawImageString(xDisplay, xBoardWindow, coordGC,
\r
4590 x + 2, y + font_ascent + 1, string, 1);
\r
4592 XDrawString(xDisplay, xBoardWindow, coordGC,
\r
4593 x + 2, y + font_ascent + 1, string, 1);
\r
4599 /* Why is this needed on some versions of X? */
\r
4600 void EventProc(widget, unused, event)
\r
4605 if (!XtIsRealized(widget))
\r
4608 switch (event->type) {
\r
4610 if (event->xexpose.count > 0) return; /* no clipping is done */
\r
4611 XDrawPosition(widget, True, NULL);
\r
4619 void DrawPosition(fullRedraw, board)
\r
4620 /*Boolean*/int fullRedraw;
\r
4623 XDrawPosition(boardWidget, fullRedraw, board);
\r
4626 /* Returns 1 if there are "too many" differences between b1 and b2
\r
4627 (i.e. more than 1 move was made) */
\r
4628 static int too_many_diffs(b1, b2)
\r
4634 for (i=0; i<BOARD_HEIGHT; ++i) {
\r
4635 for (j=0; j<BOARD_WIDTH; ++j) {
\r
4636 if (b1[i][j] != b2[i][j]) {
\r
4637 if (++c > 4) /* Castling causes 4 diffs */
\r
4646 /* Matrix describing castling maneuvers */
\r
4647 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
\r
4648 static int castling_matrix[4][5] = {
\r
4649 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
\r
4650 { 0, 7, 4, 5, 6 }, /* 0-0, white */
\r
4651 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
\r
4652 { 7, 7, 4, 5, 6 } /* 0-0, black */
\r
4655 /* Checks whether castling occurred. If it did, *rrow and *rcol
\r
4656 are set to the destination (row,col) of the rook that moved.
\r
4658 Returns 1 if castling occurred, 0 if not.
\r
4660 Note: Only handles a max of 1 castling move, so be sure
\r
4661 to call too_many_diffs() first.
\r
4663 static int check_castle_draw(newb, oldb, rrow, rcol)
\r
4670 /* For each type of castling... */
\r
4671 for (i=0; i<4; ++i) {
\r
4672 r = castling_matrix[i];
\r
4674 /* Check the 4 squares involved in the castling move */
\r
4676 for (j=1; j<=4; ++j) {
\r
4677 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
\r
4684 /* All 4 changed, so it must be a castling move */
\r
4693 static int damage[BOARD_SIZE][BOARD_SIZE];
\r
4696 * event handler for redrawing the board
\r
4698 void XDrawPosition(w, repaint, board)
\r
4700 /*Boolean*/int repaint;
\r
4703 int i, j, do_flash;
\r
4704 static int lastFlipView = 0;
\r
4705 static int lastBoardValid = 0;
\r
4706 static Board lastBoard;
\r
4710 if (board == NULL) {
\r
4711 if (!lastBoardValid) return;
\r
4712 board = lastBoard;
\r
4714 if (!lastBoardValid || lastFlipView != flipView) {
\r
4715 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
\r
4716 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
\r
4721 * It would be simpler to clear the window with XClearWindow()
\r
4722 * but this causes a very distracting flicker.
\r
4725 if (!repaint && lastBoardValid && lastFlipView == flipView) {
\r
4727 /* If too much changes (begin observing new game, etc.), don't
\r
4729 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
\r
4731 /* Special check for castling so we don't flash both the king
\r
4732 and the rook (just flash the king). */
\r
4734 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
\r
4735 /* Draw rook with NO flashing. King will be drawn flashing later */
\r
4736 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
\r
4737 lastBoard[rrow][rcol] = board[rrow][rcol];
\r
4741 /* First pass -- Draw (newly) empty squares and repair damage.
\r
4742 This prevents you from having a piece show up twice while it
\r
4743 is flashing on its new square */
\r
4744 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4745 for (j = 0; j < BOARD_WIDTH; j++)
\r
4746 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
\r
4747 || damage[i][j]) {
\r
4748 DrawSquare(i, j, board[i][j], 0);
\r
4749 damage[i][j] = False;
\r
4752 /* Second pass -- Draw piece(s) in new position and flash them */
\r
4753 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4754 for (j = 0; j < BOARD_WIDTH; j++)
\r
4755 if (board[i][j] != lastBoard[i][j]) {
\r
4756 DrawSquare(i, j, board[i][j], do_flash);
\r
4760 XDrawSegments(xDisplay, xBoardWindow, lineGC,
\r
4761 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
\r
4763 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4764 for (j = 0; j < BOARD_WIDTH; j++) {
\r
4765 DrawSquare(i, j, board[i][j], 0);
\r
4766 damage[i][j] = False;
\r
4770 CopyBoard(lastBoard, board);
\r
4771 lastBoardValid = 1;
\r
4772 lastFlipView = flipView;
\r
4774 /* Draw highlights */
\r
4775 if (pm1X >= 0 && pm1Y >= 0) {
\r
4776 drawHighlight(pm1X, pm1Y, prelineGC);
\r
4778 if (pm2X >= 0 && pm2Y >= 0) {
\r
4779 drawHighlight(pm2X, pm2Y, prelineGC);
\r
4781 if (hi1X >= 0 && hi1Y >= 0) {
\r
4782 drawHighlight(hi1X, hi1Y, highlineGC);
\r
4784 if (hi2X >= 0 && hi2Y >= 0) {
\r
4785 drawHighlight(hi2X, hi2Y, highlineGC);
\r
4788 /* If piece being dragged around board, must redraw that too */
\r
4791 XSync(xDisplay, False);
\r
4796 * event handler for redrawing the board
\r
4798 void DrawPositionProc(w, event, prms, nprms)
\r
4804 XDrawPosition(w, True, NULL);
\r
4809 * event handler for parsing user moves
\r
4811 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
\r
4812 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
\r
4813 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
\r
4814 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
\r
4815 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
\r
4816 // and at the end FinishMove() to perform the move after optional promotion popups.
\r
4817 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
\r
4818 void HandleUserMove(w, event, prms, nprms)
\r
4825 Boolean saveAnimate;
\r
4826 static int second = 0;
\r
4828 if (w != boardWidget || errorExitStatus != -1) return;
\r
4830 if (event->type == ButtonPress) ErrorPopDown();
\r
4832 if (promotionUp) {
\r
4833 if (event->type == ButtonPress) {
\r
4834 XtPopdown(promotionShell);
\r
4835 XtDestroyWidget(promotionShell);
\r
4836 promotionUp = False;
\r
4837 ClearHighlights();
\r
4838 fromX = fromY = -1;
\r
4844 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
\r
4845 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
\r
4846 if (!flipView && y >= 0) {
\r
4847 y = BOARD_HEIGHT - 1 - y;
\r
4849 if (flipView && x >= 0) {
\r
4850 x = BOARD_WIDTH - 1 - x;
\r
4853 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
\r
4854 if(event->type == ButtonPress
\r
4855 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
\r
4856 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
\r
4857 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
\r
4860 if (fromX == -1) {
\r
4861 if (event->type == ButtonPress) {
\r
4862 /* First square */
\r
4863 if (OKToStartUserMove(x, y)) {
\r
4867 DragPieceBegin(event->xbutton.x, event->xbutton.y);
\r
4868 if (appData.highlightDragging) {
\r
4869 SetHighlights(x, y, -1, -1);
\r
4877 if (event->type == ButtonPress && gameMode != EditPosition &&
\r
4878 x >= 0 && y >= 0) {
\r
4879 ChessSquare fromP;
\r
4882 /* Check if clicking again on the same color piece */
\r
4883 fromP = boards[currentMove][fromY][fromX];
\r
4884 toP = boards[currentMove][y][x];
\r
4885 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
\r
4886 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
\r
4887 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
\r
4888 BlackPawn <= toP && toP <= BlackKing)) {
\r
4889 /* Clicked again on same color piece -- changed his mind */
\r
4890 second = (x == fromX && y == fromY);
\r
4891 if (appData.highlightDragging) {
\r
4892 SetHighlights(x, y, -1, -1);
\r
4894 ClearHighlights();
\r
4896 if (OKToStartUserMove(x, y)) {
\r
4899 DragPieceBegin(event->xbutton.x, event->xbutton.y);
\r
4905 if (event->type == ButtonRelease && x == fromX && y == fromY) {
\r
4906 DragPieceEnd(event->xbutton.x, event->xbutton.y);
\r
4907 if (appData.animateDragging) {
\r
4908 /* Undo animation damage if any */
\r
4909 DrawPosition(FALSE, NULL);
\r
4912 /* Second up/down in same square; just abort move */
\r
4914 fromX = fromY = -1;
\r
4915 ClearHighlights();
\r
4917 ClearPremoveHighlights();
\r
4919 /* First upclick in same square; start click-click mode */
\r
4920 SetHighlights(x, y, -1, -1);
\r
4925 /* Completed move */
\r
4928 saveAnimate = appData.animate;
\r
4929 if (event->type == ButtonPress) {
\r
4930 /* Finish clickclick move */
\r
4931 if (appData.animate || appData.highlightLastMove) {
\r
4932 SetHighlights(fromX, fromY, toX, toY);
\r
4934 ClearHighlights();
\r
4937 /* Finish drag move */
\r
4938 if (appData.highlightLastMove) {
\r
4939 SetHighlights(fromX, fromY, toX, toY);
\r
4941 ClearHighlights();
\r
4943 DragPieceEnd(event->xbutton.x, event->xbutton.y);
\r
4944 /* Don't animate move and drag both */
\r
4945 appData.animate = FALSE;
\r
4947 if (IsPromotion(fromX, fromY, toX, toY)) {
\r
4948 if (appData.alwaysPromoteToQueen) {
\r
4949 UserMoveEvent(fromX, fromY, toX, toY, 'q');
\r
4950 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
4951 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
4952 fromX = fromY = -1;
\r
4954 SetHighlights(fromX, fromY, toX, toY);
\r
4958 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
\r
4959 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
4960 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
4961 fromX = fromY = -1;
\r
4963 appData.animate = saveAnimate;
\r
4964 if (appData.animate || appData.animateDragging) {
\r
4965 /* Undo animation damage if needed */
\r
4966 DrawPosition(FALSE, NULL);
\r
4970 void AnimateUserMove (Widget w, XEvent * event,
\r
4971 String * params, Cardinal * nParams)
\r
4973 DragPieceMove(event->xmotion.x, event->xmotion.y);
\r
4976 Widget CommentCreate(name, text, mutable, callback, lines)
\r
4977 char *name, *text;
\r
4978 int /*Boolean*/ mutable;
\r
4979 XtCallbackProc callback;
\r
4983 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
\r
4984 Dimension bw_width;
\r
4988 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
4989 XtGetValues(boardWidget, args, j);
\r
4992 XtSetArg(args[j], XtNresizable, True); j++;
\r
4995 XtCreatePopupShell(name, topLevelShellWidgetClass,
\r
4996 shellWidget, args, j);
\r
4999 XtCreatePopupShell(name, transientShellWidgetClass,
\r
5000 shellWidget, args, j);
\r
5003 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
\r
5004 layoutArgs, XtNumber(layoutArgs));
\r
5006 XtCreateManagedWidget("form", formWidgetClass, layout,
\r
5007 formArgs, XtNumber(formArgs));
\r
5011 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
\r
5012 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
\r
5014 XtSetArg(args[j], XtNstring, text); j++;
\r
5015 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
5016 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5017 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5018 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r
5019 XtSetArg(args[j], XtNresizable, True); j++;
\r
5020 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
\r
5022 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
\r
5024 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
\r
5025 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
\r
5027 XtSetArg(args[j], XtNautoFill, True); j++;
\r
5028 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
\r
5030 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
\r
5034 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5035 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5036 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5037 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5038 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5040 XtCreateManagedWidget("ok", commandWidgetClass, form, args, j);
\r
5041 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
\r
5044 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5045 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
\r
5046 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5047 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5048 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5049 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5051 XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);
\r
5052 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
\r
5055 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5056 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
\r
5057 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5058 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5059 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5060 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5062 XtCreateManagedWidget("clear", commandWidgetClass, form, args, j);
\r
5063 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
\r
5066 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5067 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5068 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5069 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5070 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5072 XtCreateManagedWidget("close", commandWidgetClass, form, args, j);
\r
5073 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
\r
5076 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5077 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
\r
5078 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5079 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5080 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5081 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5083 XtCreateManagedWidget("edit", commandWidgetClass, form, args, j);
\r
5084 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
\r
5087 XtRealizeWidget(shell);
\r
5089 if (commentX == -1) {
\r
5092 Dimension pw_height;
\r
5093 Dimension ew_height;
\r
5096 XtSetArg(args[j], XtNheight, &ew_height); j++;
\r
5097 XtGetValues(edit, args, j);
\r
5100 XtSetArg(args[j], XtNheight, &pw_height); j++;
\r
5101 XtGetValues(shell, args, j);
\r
5102 commentH = pw_height + (lines - 1) * ew_height;
\r
5103 commentW = bw_width - 16;
\r
5105 XSync(xDisplay, False);
\r
5107 /* This code seems to tickle an X bug if it is executed too soon
\r
5108 after xboard starts up. The coordinates get transformed as if
\r
5109 the main window was positioned at (0, 0).
\r
5111 XtTranslateCoords(shellWidget,
\r
5112 (bw_width - commentW) / 2, 0 - commentH / 2,
\r
5113 &commentX, &commentY);
\r
5115 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
\r
5116 RootWindowOfScreen(XtScreen(shellWidget)),
\r
5117 (bw_width - commentW) / 2, 0 - commentH / 2,
\r
5121 #endif /*!NOTDEF*/
\r
5122 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
\r
5125 XtSetArg(args[j], XtNheight, commentH); j++;
\r
5126 XtSetArg(args[j], XtNwidth, commentW); j++;
\r
5127 XtSetArg(args[j], XtNx, commentX); j++;
\r
5128 XtSetArg(args[j], XtNy, commentY); j++;
\r
5129 XtSetValues(shell, args, j);
\r
5130 XtSetKeyboardFocus(shell, edit);
\r
5135 /* Used for analysis window and ICS input window */
\r
5136 Widget MiscCreate(name, text, mutable, callback, lines)
\r
5137 char *name, *text;
\r
5138 int /*Boolean*/ mutable;
\r
5139 XtCallbackProc callback;
\r
5143 Widget shell, layout, form, edit;
\r
5145 Dimension bw_width, pw_height, ew_height, w, h;
\r
5151 XtSetArg(args[j], XtNresizable, True); j++;
\r
5154 XtCreatePopupShell(name, topLevelShellWidgetClass,
\r
5155 shellWidget, args, j);
\r
5158 XtCreatePopupShell(name, transientShellWidgetClass,
\r
5159 shellWidget, args, j);
\r
5162 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
\r
5163 layoutArgs, XtNumber(layoutArgs));
\r
5165 XtCreateManagedWidget("form", formWidgetClass, layout,
\r
5166 formArgs, XtNumber(formArgs));
\r
5170 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
\r
5171 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
\r
5173 XtSetArg(args[j], XtNstring, text); j++;
\r
5174 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
5175 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5176 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5177 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r
5178 XtSetArg(args[j], XtNresizable, True); j++;
\r
5180 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
\r
5182 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
\r
5183 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
\r
5185 XtSetArg(args[j], XtNautoFill, True); j++;
\r
5186 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
\r
5188 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
\r
5190 XtRealizeWidget(shell);
\r
5193 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
5194 XtGetValues(boardWidget, args, j);
\r
5197 XtSetArg(args[j], XtNheight, &ew_height); j++;
\r
5198 XtGetValues(edit, args, j);
\r
5201 XtSetArg(args[j], XtNheight, &pw_height); j++;
\r
5202 XtGetValues(shell, args, j);
\r
5203 h = pw_height + (lines - 1) * ew_height;
\r
5204 w = bw_width - 16;
\r
5206 XSync(xDisplay, False);
\r
5208 /* This code seems to tickle an X bug if it is executed too soon
\r
5209 after xboard starts up. The coordinates get transformed as if
\r
5210 the main window was positioned at (0, 0).
\r
5212 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
\r
5214 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
\r
5215 RootWindowOfScreen(XtScreen(shellWidget)),
\r
5216 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
\r
5217 #endif /*!NOTDEF*/
\r
5220 if (y < 0) y = 0; /*avoid positioning top offscreen*/
\r
5223 XtSetArg(args[j], XtNheight, h); j++;
\r
5224 XtSetArg(args[j], XtNwidth, w); j++;
\r
5225 XtSetArg(args[j], XtNx, x); j++;
\r
5226 XtSetArg(args[j], XtNy, y); j++;
\r
5227 XtSetValues(shell, args, j);
\r
5233 static int savedIndex; /* gross that this is global */
\r
5235 void EditCommentPopUp(index, title, text)
\r
5237 char *title, *text;
\r
5243 savedIndex = index;
\r
5244 if (text == NULL) text = "";
\r
5246 if (editShell == NULL) {
\r
5248 CommentCreate(title, text, True, EditCommentCallback, 4);
\r
5249 XtRealizeWidget(editShell);
\r
5250 CatchDeleteWindow(editShell, "EditCommentPopDown");
\r
5252 edit = XtNameToWidget(editShell, "*form.text");
\r
5254 XtSetArg(args[j], XtNstring, text); j++;
\r
5255 XtSetValues(edit, args, j);
\r
5257 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5258 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5259 XtSetValues(editShell, args, j);
\r
5262 XtPopup(editShell, XtGrabNone);
\r
5266 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
\r
5267 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
\r
5271 void EditCommentCallback(w, client_data, call_data)
\r
5273 XtPointer client_data, call_data;
\r
5281 XtSetArg(args[j], XtNlabel, &name); j++;
\r
5282 XtGetValues(w, args, j);
\r
5284 if (strcmp(name, "ok") == 0) {
\r
5285 edit = XtNameToWidget(editShell, "*form.text");
\r
5287 XtSetArg(args[j], XtNstring, &val); j++;
\r
5288 XtGetValues(edit, args, j);
\r
5289 ReplaceComment(savedIndex, val);
\r
5290 EditCommentPopDown();
\r
5291 } else if (strcmp(name, "cancel") == 0) {
\r
5292 EditCommentPopDown();
\r
5293 } else if (strcmp(name, "clear") == 0) {
\r
5294 edit = XtNameToWidget(editShell, "*form.text");
\r
5295 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
\r
5296 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
\r
5300 void EditCommentPopDown()
\r
5305 if (!editUp) return;
\r
5307 XtSetArg(args[j], XtNx, &commentX); j++;
\r
5308 XtSetArg(args[j], XtNy, &commentY); j++;
\r
5309 XtSetArg(args[j], XtNheight, &commentH); j++;
\r
5310 XtSetArg(args[j], XtNwidth, &commentW); j++;
\r
5311 XtGetValues(editShell, args, j);
\r
5312 XtPopdown(editShell);
\r
5315 XtSetArg(args[j], XtNleftBitmap, None); j++;
\r
5316 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
\r
5320 void ICSInputBoxPopUp()
\r
5325 char *title = "ICS Input";
\r
5326 XtTranslations tr;
\r
5328 if (ICSInputShell == NULL) {
\r
5329 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
\r
5330 tr = XtParseTranslationTable(ICSInputTranslations);
\r
5331 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5332 XtOverrideTranslations(edit, tr);
\r
5333 XtRealizeWidget(ICSInputShell);
\r
5334 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
\r
5337 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5339 XtSetArg(args[j], XtNstring, ""); j++;
\r
5340 XtSetValues(edit, args, j);
\r
5342 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5343 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5344 XtSetValues(ICSInputShell, args, j);
\r
5347 XtPopup(ICSInputShell, XtGrabNone);
\r
5348 XtSetKeyboardFocus(ICSInputShell, edit);
\r
5350 ICSInputBoxUp = True;
\r
5352 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
\r
5353 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
\r
5357 void ICSInputSendText()
\r
5364 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5366 XtSetArg(args[j], XtNstring, &val); j++;
\r
5367 XtGetValues(edit, args, j);
\r
5368 SendMultiLineToICS(val);
\r
5369 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
\r
5370 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
\r
5373 void ICSInputBoxPopDown()
\r
5378 if (!ICSInputBoxUp) return;
\r
5380 XtPopdown(ICSInputShell);
\r
5381 ICSInputBoxUp = False;
\r
5383 XtSetArg(args[j], XtNleftBitmap, None); j++;
\r
5384 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
\r
5388 void CommentPopUp(title, text)
\r
5389 char *title, *text;
\r
5395 if (commentShell == NULL) {
\r
5397 CommentCreate(title, text, False, CommentCallback, 4);
\r
5398 XtRealizeWidget(commentShell);
\r
5399 CatchDeleteWindow(commentShell, "CommentPopDown");
\r
5401 edit = XtNameToWidget(commentShell, "*form.text");
\r
5403 XtSetArg(args[j], XtNstring, text); j++;
\r
5404 XtSetValues(edit, args, j);
\r
5406 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5407 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5408 XtSetValues(commentShell, args, j);
\r
5411 XtPopup(commentShell, XtGrabNone);
\r
5412 XSync(xDisplay, False);
\r
5417 void AnalysisPopUp(title, text)
\r
5418 char *title, *text;
\r
5424 if (analysisShell == NULL) {
\r
5425 analysisShell = MiscCreate(title, text, False, NULL, 4);
\r
5426 XtRealizeWidget(analysisShell);
\r
5427 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
\r
5430 edit = XtNameToWidget(analysisShell, "*form.text");
\r
5432 XtSetArg(args[j], XtNstring, text); j++;
\r
5433 XtSetValues(edit, args, j);
\r
5435 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5436 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5437 XtSetValues(analysisShell, args, j);
\r
5440 if (!analysisUp) {
\r
5441 XtPopup(analysisShell, XtGrabNone);
\r
5443 XSync(xDisplay, False);
\r
5445 analysisUp = True;
\r
5448 void CommentCallback(w, client_data, call_data)
\r
5450 XtPointer client_data, call_data;
\r
5457 XtSetArg(args[j], XtNlabel, &name); j++;
\r
5458 XtGetValues(w, args, j);
\r
5460 if (strcmp(name, "close") == 0) {
\r
5462 } else if (strcmp(name, "edit") == 0) {
\r
5464 EditCommentEvent();
\r
5469 void CommentPopDown()
\r
5474 if (!commentUp) return;
\r
5476 XtSetArg(args[j], XtNx, &commentX); j++;
\r
5477 XtSetArg(args[j], XtNy, &commentY); j++;
\r
5478 XtSetArg(args[j], XtNwidth, &commentW); j++;
\r
5479 XtSetArg(args[j], XtNheight, &commentH); j++;
\r
5480 XtGetValues(commentShell, args, j);
\r
5481 XtPopdown(commentShell);
\r
5482 XSync(xDisplay, False);
\r
5483 commentUp = False;
\r
5486 void AnalysisPopDown()
\r
5488 if (!analysisUp) return;
\r
5489 XtPopdown(analysisShell);
\r
5490 XSync(xDisplay, False);
\r
5491 analysisUp = False;
\r
5495 void FileNamePopUp(label, def, proc, openMode)
\r
5502 Widget popup, layout, dialog, edit;
\r
5503 Window root, child;
\r
5506 unsigned int mask;
\r
5508 fileProc = proc; /* I can't see a way not */
\r
5509 fileOpenMode = openMode; /* to use globals here */
\r
5512 XtSetArg(args[i], XtNresizable, True); i++;
\r
5513 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
\r
5514 fileNameShell = popup =
\r
5515 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
\r
5516 shellWidget, args, i);
\r
5519 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
\r
5520 layoutArgs, XtNumber(layoutArgs));
\r
5523 XtSetArg(args[i], XtNlabel, label); i++;
\r
5524 XtSetArg(args[i], XtNvalue, def); i++;
\r
5525 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
5526 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
\r
5529 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
\r
5530 XawDialogAddButton(dialog, "cancel", FileNameCallback,
\r
5531 (XtPointer) dialog);
\r
5533 XtRealizeWidget(popup);
\r
5534 CatchDeleteWindow(popup, "FileNamePopDown");
\r
5536 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
\r
5537 &x, &y, &win_x, &win_y, &mask);
\r
5539 XtSetArg(args[0], XtNx, x - 10);
\r
5540 XtSetArg(args[1], XtNy, y - 30);
\r
5541 XtSetValues(popup, args, 2);
\r
5543 XtPopup(popup, XtGrabExclusive);
\r
5544 filenameUp = True;
\r
5546 edit = XtNameToWidget(dialog, "*value");
\r
5547 XtSetKeyboardFocus(popup, edit);
\r
5550 void FileNamePopDown()
\r
5552 if (!filenameUp) return;
\r
5553 XtPopdown(fileNameShell);
\r
5554 XtDestroyWidget(fileNameShell);
\r
5555 filenameUp = False;
\r
5559 void FileNameCallback(w, client_data, call_data)
\r
5561 XtPointer client_data, call_data;
\r
5566 XtSetArg(args[0], XtNlabel, &name);
\r
5567 XtGetValues(w, args, 1);
\r
5569 if (strcmp(name, "cancel") == 0) {
\r
5570 FileNamePopDown();
\r
5574 FileNameAction(w, NULL, NULL, NULL);
\r
5577 void FileNameAction(w, event, prms, nprms)
\r
5583 char buf[MSG_SIZ];
\r
5586 char *p, *fullname;
\r
5589 name = XawDialogGetValueString(w = XtParent(w));
\r
5591 if ((name != NULL) && (*name != NULLCHAR)) {
\r
5592 strcpy(buf, name);
\r
5593 XtPopdown(w = XtParent(XtParent(w)));
\r
5594 XtDestroyWidget(w);
\r
5595 filenameUp = False;
\r
5597 p = strrchr(buf, ' ');
\r
5604 fullname = ExpandPathName(buf);
\r
5606 ErrorPopUp("Error", "Can't open file", FALSE);
\r
5609 f = fopen(fullname, fileOpenMode);
\r
5611 DisplayError("Failed to open file", errno);
\r
5613 (void) (*fileProc)(f, index, buf);
\r
5620 XtPopdown(w = XtParent(XtParent(w)));
\r
5621 XtDestroyWidget(w);
\r
5622 filenameUp = False;
\r
5626 void PromotionPopUp()
\r
5629 Widget dialog, layout;
\r
5631 Dimension bw_width, pw_width;
\r
5635 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
5636 XtGetValues(boardWidget, args, j);
\r
5639 XtSetArg(args[j], XtNresizable, True); j++;
\r
5641 XtCreatePopupShell("Promotion", transientShellWidgetClass,
\r
5642 shellWidget, args, j);
\r
5644 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
\r
5645 layoutArgs, XtNumber(layoutArgs));
\r
5648 XtSetArg(args[j], XtNlabel, "Promote pawn to what?"); j++;
\r
5649 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
5650 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
\r
5653 XawDialogAddButton(dialog, "Queen", PromotionCallback,
\r
5654 (XtPointer) dialog);
\r
5655 XawDialogAddButton(dialog, "Rook", PromotionCallback,
\r
5656 (XtPointer) dialog);
\r
5657 XawDialogAddButton(dialog, "Bishop", PromotionCallback,
\r
5658 (XtPointer) dialog);
\r
5659 XawDialogAddButton(dialog, "Knight", PromotionCallback,
\r
5660 (XtPointer) dialog);
\r
5661 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
\r
5662 gameInfo.variant == VariantGiveaway) {
\r
5663 XawDialogAddButton(dialog, "King", PromotionCallback,
\r
5664 (XtPointer) dialog);
\r
5666 XawDialogAddButton(dialog, "cancel", PromotionCallback,
\r
5667 (XtPointer) dialog);
\r
5669 XtRealizeWidget(promotionShell);
\r
5670 CatchDeleteWindow(promotionShell, "PromotionPopDown");
\r
5673 XtSetArg(args[j], XtNwidth, &pw_width); j++;
\r
5674 XtGetValues(promotionShell, args, j);
\r
5676 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
\r
5677 lineGap + squareSize/3 +
\r
5678 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
\r
5679 0 : 6*(squareSize + lineGap)), &x, &y);
\r
5682 XtSetArg(args[j], XtNx, x); j++;
\r
5683 XtSetArg(args[j], XtNy, y); j++;
\r
5684 XtSetValues(promotionShell, args, j);
\r
5686 XtPopup(promotionShell, XtGrabNone);
\r
5688 promotionUp = True;
\r
5691 void PromotionPopDown()
\r
5693 if (!promotionUp) return;
\r
5694 XtPopdown(promotionShell);
\r
5695 XtDestroyWidget(promotionShell);
\r
5696 promotionUp = False;
\r
5699 void PromotionCallback(w, client_data, call_data)
\r
5701 XtPointer client_data, call_data;
\r
5707 XtSetArg(args[0], XtNlabel, &name);
\r
5708 XtGetValues(w, args, 1);
\r
5710 PromotionPopDown();
\r
5712 if (fromX == -1) return;
\r
5714 if (strcmp(name, "cancel") == 0) {
\r
5715 fromX = fromY = -1;
\r
5716 ClearHighlights();
\r
5718 } else if (strcmp(name, "Knight") == 0) {
\r
5721 promoChar = ToLower(name[0]);
\r
5724 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
\r
5726 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
5727 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
5728 fromX = fromY = -1;
\r
5732 void ErrorCallback(w, client_data, call_data)
\r
5734 XtPointer client_data, call_data;
\r
5737 XtPopdown(w = XtParent(XtParent(XtParent(w))));
\r
5738 XtDestroyWidget(w);
\r
5739 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
\r
5743 void ErrorPopDown()
\r
5745 if (!errorUp) return;
\r
5747 XtPopdown(errorShell);
\r
5748 XtDestroyWidget(errorShell);
\r
5749 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
\r
5752 void ErrorPopUp(title, label, modal)
\r
5753 char *title, *label;
\r
5757 Widget dialog, layout;
\r
5761 Dimension bw_width, pw_width;
\r
5762 Dimension pw_height;
\r
5766 XtSetArg(args[i], XtNresizable, True); i++;
\r
5767 XtSetArg(args[i], XtNtitle, title); i++;
\r
5769 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
\r
5770 shellWidget, args, i);
\r
5772 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
\r
5773 layoutArgs, XtNumber(layoutArgs));
\r
5776 XtSetArg(args[i], XtNlabel, label); i++;
\r
5777 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
5778 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
\r
5781 XawDialogAddButton(dialog, "ok", ErrorCallback, (XtPointer) dialog);
\r
5783 XtRealizeWidget(errorShell);
\r
5784 CatchDeleteWindow(errorShell, "ErrorPopDown");
\r
5787 XtSetArg(args[i], XtNwidth, &bw_width); i++;
\r
5788 XtGetValues(boardWidget, args, i);
\r
5790 XtSetArg(args[i], XtNwidth, &pw_width); i++;
\r
5791 XtSetArg(args[i], XtNheight, &pw_height); i++;
\r
5792 XtGetValues(errorShell, args, i);
\r
5795 /* This code seems to tickle an X bug if it is executed too soon
\r
5796 after xboard starts up. The coordinates get transformed as if
\r
5797 the main window was positioned at (0, 0).
\r
5799 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
\r
5800 0 - pw_height + squareSize / 3, &x, &y);
\r
5802 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
\r
5803 RootWindowOfScreen(XtScreen(boardWidget)),
\r
5804 (bw_width - pw_width) / 2,
\r
5805 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
\r
5809 if (y < 0) y = 0; /*avoid positioning top offscreen*/
\r
5812 XtSetArg(args[i], XtNx, x); i++;
\r
5813 XtSetArg(args[i], XtNy, y); i++;
\r
5814 XtSetValues(errorShell, args, i);
\r
5817 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
\r
5820 /* Disable all user input other than deleting the window */
\r
5821 static int frozen = 0;
\r
5824 if (frozen) return;
\r
5825 /* Grab by a widget that doesn't accept input */
\r
5826 XtAddGrab(messageWidget, TRUE, FALSE);
\r
5830 /* Undo a FreezeUI */
\r
5833 if (!frozen) return;
\r
5834 XtRemoveGrab(messageWidget);
\r
5838 char *ModeToWidgetName(mode)
\r
5842 case BeginningOfGame:
\r
5843 if (appData.icsActive)
\r
5844 return "menuMode.ICS Client";
\r
5845 else if (appData.noChessProgram ||
\r
5846 *appData.cmailGameName != NULLCHAR)
\r
5847 return "menuMode.Edit Game";
\r
5849 return "menuMode.Machine Black";
\r
5850 case MachinePlaysBlack:
\r
5851 return "menuMode.Machine Black";
\r
5852 case MachinePlaysWhite:
\r
5853 return "menuMode.Machine White";
\r
5855 return "menuMode.Analysis Mode";
\r
5857 return "menuMode.Analyze File";
\r
5858 case TwoMachinesPlay:
\r
5859 return "menuMode.Two Machines";
\r
5861 return "menuMode.Edit Game";
\r
5862 case PlayFromGameFile:
\r
5863 return "menuFile.Load Game";
\r
5864 case EditPosition:
\r
5865 return "menuMode.Edit Position";
\r
5867 return "menuMode.Training";
\r
5868 case IcsPlayingWhite:
\r
5869 case IcsPlayingBlack:
\r
5870 case IcsObserving:
\r
5872 case IcsExamining:
\r
5873 return "menuMode.ICS Client";
\r
5880 void ModeHighlight()
\r
5883 static int oldPausing = FALSE;
\r
5884 static GameMode oldmode = (GameMode) -1;
\r
5887 if (!boardWidget || !XtIsRealized(boardWidget)) return;
\r
5889 if (pausing != oldPausing) {
\r
5890 oldPausing = pausing;
\r
5892 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
5894 XtSetArg(args[0], XtNleftBitmap, None);
\r
5896 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
\r
5899 if (appData.showButtonBar) {
\r
5902 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
\r
5903 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
\r
5905 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
\r
5906 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
\r
5909 /* Always toggle, don't set. Previous code messes up when
\r
5910 invoked while the button is pressed, as releasing it
\r
5911 toggles the state again. */
\r
5913 Pixel oldbg, oldfg;
\r
5914 XtSetArg(args[0], XtNbackground, &oldbg);
\r
5915 XtSetArg(args[1], XtNforeground, &oldfg);
\r
5916 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
\r
5918 XtSetArg(args[0], XtNbackground, oldfg);
\r
5919 XtSetArg(args[1], XtNforeground, oldbg);
\r
5922 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
\r
5926 wname = ModeToWidgetName(oldmode);
\r
5927 if (wname != NULL) {
\r
5928 XtSetArg(args[0], XtNleftBitmap, None);
\r
5929 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
\r
5931 wname = ModeToWidgetName(gameMode);
\r
5932 if (wname != NULL) {
\r
5933 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
5934 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
\r
5936 oldmode = gameMode;
\r
5938 /* Maybe all the enables should be handled here, not just this one */
\r
5939 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
\r
5940 gameMode == Training || gameMode == PlayFromGameFile);
\r
5945 * Button/menu procedures
\r
5947 void ResetProc(w, event, prms, nprms)
\r
5954 AnalysisPopDown();
\r
5957 int LoadGamePopUp(f, gameNumber, title)
\r
5962 cmailMsgLoaded = FALSE;
\r
5963 if (gameNumber == 0) {
\r
5964 int error = GameListBuild(f);
\r
5966 DisplayError("Cannot build game list", error);
\r
5967 } else if (!ListEmpty(&gameList) &&
\r
5968 ((ListGame *) gameList.tailPred)->number > 1) {
\r
5969 GameListPopUp(f, title);
\r
5972 GameListDestroy();
\r
5975 return LoadGame(f, gameNumber, title, FALSE);
\r
5978 void LoadGameProc(w, event, prms, nprms)
\r
5984 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
5985 Reset(FALSE, TRUE);
\r
5987 FileNamePopUp("Load game file name?", "", LoadGamePopUp, "rb");
\r
5990 void LoadNextGameProc(w, event, prms, nprms)
\r
5999 void LoadPrevGameProc(w, event, prms, nprms)
\r
6008 void ReloadGameProc(w, event, prms, nprms)
\r
6017 void LoadNextPositionProc(w, event, prms, nprms)
\r
6023 ReloadPosition(1);
\r
6026 void LoadPrevPositionProc(w, event, prms, nprms)
\r
6032 ReloadPosition(-1);
\r
6035 void ReloadPositionProc(w, event, prms, nprms)
\r
6041 ReloadPosition(0);
\r
6044 void LoadPositionProc(w, event, prms, nprms)
\r
6050 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
6051 Reset(FALSE, TRUE);
\r
6053 FileNamePopUp("Load position file name?", "", LoadPosition, "rb");
\r
6056 void SaveGameProc(w, event, prms, nprms)
\r
6062 FileNamePopUp("Save game file name?",
\r
6063 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
\r
6067 void SavePositionProc(w, event, prms, nprms)
\r
6073 FileNamePopUp("Save position file name?",
\r
6074 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
\r
6075 SavePosition, "a");
\r
6078 void ReloadCmailMsgProc(w, event, prms, nprms)
\r
6084 ReloadCmailMsgEvent(FALSE);
\r
6087 void MailMoveProc(w, event, prms, nprms)
\r
6096 /* this variable is shared between CopyPositionProc and SendPositionSelection */
\r
6097 static char *selected_fen_position=NULL;
\r
6100 SendPositionSelection(Widget w, Atom *selection, Atom *target,
\r
6101 Atom *type_return, XtPointer *value_return,
\r
6102 unsigned long *length_return, int *format_return)
\r
6104 char *selection_tmp;
\r
6106 if (!selected_fen_position) return False; /* should never happen */
\r
6107 if (*target == XA_STRING){
\r
6108 /* note: since no XtSelectionDoneProc was registered, Xt will
\r
6109 * automatically call XtFree on the value returned. So have to
\r
6110 * make a copy of it allocated with XtMalloc */
\r
6111 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
\r
6112 strcpy(selection_tmp, selected_fen_position);
\r
6114 *value_return=selection_tmp;
\r
6115 *length_return=strlen(selection_tmp);
\r
6116 *type_return=XA_STRING;
\r
6117 *format_return = 8; /* bits per byte */
\r
6124 /* note: when called from menu all parameters are NULL, so no clue what the
\r
6125 * Widget which was clicked on was, or what the click event was
\r
6127 void CopyPositionProc(w, event, prms, nprms)
\r
6135 if (selected_fen_position) free(selected_fen_position);
\r
6136 selected_fen_position = (char *)PositionToFEN(currentMove,1);
\r
6137 if (!selected_fen_position) return;
\r
6138 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
\r
6140 SendPositionSelection,
\r
6141 NULL/* lose_ownership_proc */ ,
\r
6142 NULL/* transfer_done_proc */);
\r
6144 free(selected_fen_position);
\r
6145 selected_fen_position=NULL;
\r
6149 /* function called when the data to Paste is ready */
\r
6151 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
\r
6152 Atom *type, XtPointer value, unsigned long *len, int *format)
\r
6154 char *fenstr=value;
\r
6155 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
\r
6156 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
\r
6157 EditPositionPasteFEN(fenstr);
\r
6161 /* called when Paste Position button is pressed,
\r
6162 * all parameters will be NULL */
\r
6163 void PastePositionProc(w, event, prms, nprms)
\r
6169 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
\r
6170 /* (XtSelectionCallbackProc) */ PastePositionCB,
\r
6171 NULL, /* client_data passed to PastePositionCB */
\r
6173 /* better to use the time field from the event that triggered the
\r
6174 * call to this function, but that isn't trivial to get
\r
6182 SendGameSelection(Widget w, Atom *selection, Atom *target,
\r
6183 Atom *type_return, XtPointer *value_return,
\r
6184 unsigned long *length_return, int *format_return)
\r
6186 char *selection_tmp;
\r
6188 if (*target == XA_STRING){
\r
6189 FILE* f = fopen(gameCopyFilename, "r");
\r
6192 if (f == NULL) return False;
\r
6196 selection_tmp = XtMalloc(len + 1);
\r
6197 count = fread(selection_tmp, 1, len, f);
\r
6198 if (len != count) {
\r
6199 XtFree(selection_tmp);
\r
6202 selection_tmp[len] = NULLCHAR;
\r
6203 *value_return = selection_tmp;
\r
6204 *length_return = len;
\r
6205 *type_return = XA_STRING;
\r
6206 *format_return = 8; /* bits per byte */
\r
6213 /* note: when called from menu all parameters are NULL, so no clue what the
\r
6214 * Widget which was clicked on was, or what the click event was
\r
6216 void CopyGameProc(w, event, prms, nprms)
\r
6224 ret = SaveGameToFile(gameCopyFilename, FALSE);
\r
6227 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
\r
6229 SendGameSelection,
\r
6230 NULL/* lose_ownership_proc */ ,
\r
6231 NULL/* transfer_done_proc */);
\r
6234 /* function called when the data to Paste is ready */
\r
6236 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
\r
6237 Atom *type, XtPointer value, unsigned long *len, int *format)
\r
6240 if (value == NULL || *len == 0) {
\r
6241 return; /* nothing had been selected to copy */
\r
6243 f = fopen(gamePasteFilename, "w");
\r
6245 DisplayError("Can't open temp file", errno);
\r
6248 fwrite(value, 1, *len, f);
\r
6251 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
\r
6254 /* called when Paste Game button is pressed,
\r
6255 * all parameters will be NULL */
\r
6256 void PasteGameProc(w, event, prms, nprms)
\r
6262 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
\r
6263 /* (XtSelectionCallbackProc) */ PasteGameCB,
\r
6264 NULL, /* client_data passed to PasteGameCB */
\r
6266 /* better to use the time field from the event that triggered the
\r
6267 * call to this function, but that isn't trivial to get
\r
6275 void AutoSaveGame()
\r
6277 SaveGameProc(NULL, NULL, NULL, NULL);
\r
6281 void QuitProc(w, event, prms, nprms)
\r
6290 void PauseProc(w, event, prms, nprms)
\r
6300 void MachineBlackProc(w, event, prms, nprms)
\r
6306 MachineBlackEvent();
\r
6309 void MachineWhiteProc(w, event, prms, nprms)
\r
6315 MachineWhiteEvent();
\r
6318 void AnalyzeModeProc(w, event, prms, nprms)
\r
6324 if (!first.analysisSupport) {
\r
6325 char buf[MSG_SIZ];
\r
6326 sprintf(buf, "%s does not support analysis", first.tidy);
\r
6327 DisplayError(buf, 0);
\r
6330 if (!appData.showThinking)
\r
6331 ShowThinkingProc(w,event,prms,nprms);
\r
6333 AnalyzeModeEvent();
\r
6336 void AnalyzeFileProc(w, event, prms, nprms)
\r
6342 if (!first.analysisSupport) {
\r
6343 char buf[MSG_SIZ];
\r
6344 sprintf(buf, "%s does not support analysis", first.tidy);
\r
6345 DisplayError(buf, 0);
\r
6348 Reset(FALSE, TRUE);
\r
6350 if (!appData.showThinking)
\r
6351 ShowThinkingProc(w,event,prms,nprms);
\r
6353 AnalyzeFileEvent();
\r
6354 FileNamePopUp("File to analyze", "", LoadGamePopUp, "rb");
\r
6355 AnalysisPeriodicEvent(1);
\r
6358 void TwoMachinesProc(w, event, prms, nprms)
\r
6364 TwoMachinesEvent();
\r
6367 void IcsClientProc(w, event, prms, nprms)
\r
6376 void EditGameProc(w, event, prms, nprms)
\r
6385 void EditPositionProc(w, event, prms, nprms)
\r
6391 EditPositionEvent();
\r
6394 void TrainingProc(w, event, prms, nprms)
\r
6403 void EditCommentProc(w, event, prms, nprms)
\r
6410 EditCommentPopDown();
\r
6412 EditCommentEvent();
\r
6416 void IcsInputBoxProc(w, event, prms, nprms)
\r
6422 if (ICSInputBoxUp) {
\r
6423 ICSInputBoxPopDown();
\r
6425 ICSInputBoxPopUp();
\r
6429 void AcceptProc(w, event, prms, nprms)
\r
6438 void DeclineProc(w, event, prms, nprms)
\r
6447 void RematchProc(w, event, prms, nprms)
\r
6456 void CallFlagProc(w, event, prms, nprms)
\r
6465 void DrawProc(w, event, prms, nprms)
\r
6474 void AbortProc(w, event, prms, nprms)
\r
6483 void AdjournProc(w, event, prms, nprms)
\r
6492 void ResignProc(w, event, prms, nprms)
\r
6501 void EnterKeyProc(w, event, prms, nprms)
\r
6507 if (ICSInputBoxUp == True)
\r
6508 ICSInputSendText();
\r
6511 void StopObservingProc(w, event, prms, nprms)
\r
6517 StopObservingEvent();
\r
6520 void StopExaminingProc(w, event, prms, nprms)
\r
6526 StopExaminingEvent();
\r
6530 void ForwardProc(w, event, prms, nprms)
\r
6540 void BackwardProc(w, event, prms, nprms)
\r
6549 void ToStartProc(w, event, prms, nprms)
\r
6558 void ToEndProc(w, event, prms, nprms)
\r
6567 void RevertProc(w, event, prms, nprms)
\r
6576 void TruncateGameProc(w, event, prms, nprms)
\r
6582 TruncateGameEvent();
\r
6584 void RetractMoveProc(w, event, prms, nprms)
\r
6590 RetractMoveEvent();
\r
6593 void MoveNowProc(w, event, prms, nprms)
\r
6603 void AlwaysQueenProc(w, event, prms, nprms)
\r
6611 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
\r
6613 if (appData.alwaysPromoteToQueen) {
\r
6614 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6616 XtSetArg(args[0], XtNleftBitmap, None);
\r
6618 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
\r
6622 void AnimateDraggingProc(w, event, prms, nprms)
\r
6630 appData.animateDragging = !appData.animateDragging;
\r
6632 if (appData.animateDragging) {
\r
6633 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6636 XtSetArg(args[0], XtNleftBitmap, None);
\r
6638 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
\r
6642 void AnimateMovingProc(w, event, prms, nprms)
\r
6650 appData.animate = !appData.animate;
\r
6652 if (appData.animate) {
\r
6653 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6656 XtSetArg(args[0], XtNleftBitmap, None);
\r
6658 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
\r
6662 void AutocommProc(w, event, prms, nprms)
\r
6670 appData.autoComment = !appData.autoComment;
\r
6672 if (appData.autoComment) {
\r
6673 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6675 XtSetArg(args[0], XtNleftBitmap, None);
\r
6677 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
\r
6682 void AutoflagProc(w, event, prms, nprms)
\r
6690 appData.autoCallFlag = !appData.autoCallFlag;
\r
6692 if (appData.autoCallFlag) {
\r
6693 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6695 XtSetArg(args[0], XtNleftBitmap, None);
\r
6697 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
\r
6701 void AutoflipProc(w, event, prms, nprms)
\r
6709 appData.autoFlipView = !appData.autoFlipView;
\r
6711 if (appData.autoFlipView) {
\r
6712 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6714 XtSetArg(args[0], XtNleftBitmap, None);
\r
6716 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
\r
6720 void AutobsProc(w, event, prms, nprms)
\r
6728 appData.autoObserve = !appData.autoObserve;
\r
6730 if (appData.autoObserve) {
\r
6731 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6733 XtSetArg(args[0], XtNleftBitmap, None);
\r
6735 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
\r
6739 void AutoraiseProc(w, event, prms, nprms)
\r
6747 appData.autoRaiseBoard = !appData.autoRaiseBoard;
\r
6749 if (appData.autoRaiseBoard) {
\r
6750 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6752 XtSetArg(args[0], XtNleftBitmap, None);
\r
6754 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
\r
6758 void AutosaveProc(w, event, prms, nprms)
\r
6766 appData.autoSaveGames = !appData.autoSaveGames;
\r
6768 if (appData.autoSaveGames) {
\r
6769 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6771 XtSetArg(args[0], XtNleftBitmap, None);
\r
6773 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
6777 void BlindfoldProc(w, event, prms, nprms)
\r
6785 appData.blindfold = !appData.blindfold;
\r
6787 if (appData.blindfold) {
\r
6788 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6790 XtSetArg(args[0], XtNleftBitmap, None);
\r
6792 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
\r
6795 DrawPosition(True, NULL);
\r
6798 void TestLegalityProc(w, event, prms, nprms)
\r
6806 appData.testLegality = !appData.testLegality;
\r
6808 if (appData.testLegality) {
\r
6809 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6811 XtSetArg(args[0], XtNleftBitmap, None);
\r
6813 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
\r
6818 void FlashMovesProc(w, event, prms, nprms)
\r
6826 if (appData.flashCount == 0) {
\r
6827 appData.flashCount = 3;
\r
6829 appData.flashCount = -appData.flashCount;
\r
6832 if (appData.flashCount > 0) {
\r
6833 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6835 XtSetArg(args[0], XtNleftBitmap, None);
\r
6837 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
\r
6841 void FlipViewProc(w, event, prms, nprms)
\r
6847 flipView = !flipView;
\r
6848 DrawPosition(True, NULL);
\r
6851 void GetMoveListProc(w, event, prms, nprms)
\r
6859 appData.getMoveList = !appData.getMoveList;
\r
6861 if (appData.getMoveList) {
\r
6862 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6863 GetMoveListEvent();
\r
6865 XtSetArg(args[0], XtNleftBitmap, None);
\r
6867 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
\r
6872 void HighlightDraggingProc(w, event, prms, nprms)
\r
6880 appData.highlightDragging = !appData.highlightDragging;
\r
6882 if (appData.highlightDragging) {
\r
6883 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6885 XtSetArg(args[0], XtNleftBitmap, None);
\r
6887 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6888 "menuOptions.Highlight Dragging"), args, 1);
\r
6892 void HighlightLastMoveProc(w, event, prms, nprms)
\r
6900 appData.highlightLastMove = !appData.highlightLastMove;
\r
6902 if (appData.highlightLastMove) {
\r
6903 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6905 XtSetArg(args[0], XtNleftBitmap, None);
\r
6907 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6908 "menuOptions.Highlight Last Move"), args, 1);
\r
6911 void IcsAlarmProc(w, event, prms, nprms)
\r
6919 appData.icsAlarm = !appData.icsAlarm;
\r
6921 if (appData.icsAlarm) {
\r
6922 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6924 XtSetArg(args[0], XtNleftBitmap, None);
\r
6926 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6927 "menuOptions.ICS Alarm"), args, 1);
\r
6930 void MoveSoundProc(w, event, prms, nprms)
\r
6938 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
\r
6940 if (appData.ringBellAfterMoves) {
\r
6941 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6943 XtSetArg(args[0], XtNleftBitmap, None);
\r
6945 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
\r
6950 void OldSaveStyleProc(w, event, prms, nprms)
\r
6958 appData.oldSaveStyle = !appData.oldSaveStyle;
\r
6960 if (appData.oldSaveStyle) {
\r
6961 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6963 XtSetArg(args[0], XtNleftBitmap, None);
\r
6965 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
\r
6969 void PeriodicUpdatesProc(w, event, prms, nprms)
\r
6977 PeriodicUpdatesEvent(!appData.periodicUpdates);
\r
6979 if (appData.periodicUpdates) {
\r
6980 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6982 XtSetArg(args[0], XtNleftBitmap, None);
\r
6984 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
\r
6988 void PonderNextMoveProc(w, event, prms, nprms)
\r
6996 PonderNextMoveEvent(!appData.ponderNextMove);
\r
6998 if (appData.ponderNextMove) {
\r
6999 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7001 XtSetArg(args[0], XtNleftBitmap, None);
\r
7003 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
\r
7007 void PopupExitMessageProc(w, event, prms, nprms)
\r
7015 appData.popupExitMessage = !appData.popupExitMessage;
\r
7017 if (appData.popupExitMessage) {
\r
7018 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7020 XtSetArg(args[0], XtNleftBitmap, None);
\r
7022 XtSetValues(XtNameToWidget(menuBarWidget,
\r
7023 "menuOptions.Popup Exit Message"), args, 1);
\r
7026 void PopupMoveErrorsProc(w, event, prms, nprms)
\r
7034 appData.popupMoveErrors = !appData.popupMoveErrors;
\r
7036 if (appData.popupMoveErrors) {
\r
7037 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7039 XtSetArg(args[0], XtNleftBitmap, None);
\r
7041 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
\r
7045 void PremoveProc(w, event, prms, nprms)
\r
7053 appData.premove = !appData.premove;
\r
7055 if (appData.premove) {
\r
7056 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7058 XtSetArg(args[0], XtNleftBitmap, None);
\r
7060 XtSetValues(XtNameToWidget(menuBarWidget,
\r
7061 "menuOptions.Premove"), args, 1);
\r
7064 void QuietPlayProc(w, event, prms, nprms)
\r
7072 appData.quietPlay = !appData.quietPlay;
\r
7074 if (appData.quietPlay) {
\r
7075 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7077 XtSetArg(args[0], XtNleftBitmap, None);
\r
7079 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
\r
7083 void ShowCoordsProc(w, event, prms, nprms)
\r
7091 appData.showCoords = !appData.showCoords;
\r
7093 if (appData.showCoords) {
\r
7094 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7096 XtSetArg(args[0], XtNleftBitmap, None);
\r
7098 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
\r
7101 DrawPosition(True, NULL);
\r
7104 void ShowThinkingProc(w, event, prms, nprms)
\r
7112 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7113 ShowThinkingEvent();
\r
7115 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
\r
7116 if (appData.showThinking) {
\r
7117 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7119 XtSetArg(args[0], XtNleftBitmap, None);
\r
7121 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
\r
7126 void HideThinkingProc(w, event, prms, nprms)
\r
7134 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7135 ShowThinkingEvent();
\r
7137 if (appData.hideThinkingFromHuman) {
\r
7138 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7140 XtSetArg(args[0], XtNleftBitmap, None);
\r
7142 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
\r
7146 void InfoProc(w, event, prms, nprms)
\r
7152 char buf[MSG_SIZ];
\r
7153 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
\r
7154 INFODIR, INFOFILE);
\r
7158 void ManProc(w, event, prms, nprms)
\r
7164 char buf[MSG_SIZ];
\r
7166 if (nprms && *nprms > 0)
\r
7170 sprintf(buf, "xterm -e man %s &", name);
\r
7174 void HintProc(w, event, prms, nprms)
\r
7183 void BookProc(w, event, prms, nprms)
\r
7192 void AboutProc(w, event, prms, nprms)
\r
7198 char buf[MSG_SIZ];
\r
7200 char *zippy = " (with Zippy code)";
\r
7204 sprintf(buf, "%s%s\n\n%s\n%s\n%s\n%s\n\n%s%s\n%s",
\r
7205 programVersion, zippy,
\r
7206 "Copyright 1991 Digital Equipment Corporation",
\r
7207 "Enhancements Copyright 1992-2001 Free Software Foundation",
7208 "Enhancements Copyright 2005 Alessandro Scotti",
\r
7209 "Enhancements Copyright 2007-2008 H.G.Muller",
\r
7210 PRODUCT, " is free software and carries NO WARRANTY;",
\r
7211 "see the file COPYING for more information.");
\r
7212 ErrorPopUp("About XBoard", buf, FALSE);
\r
7215 void DebugProc(w, event, prms, nprms)
\r
7221 appData.debugMode = !appData.debugMode;
\r
7224 void AboutGameProc(w, event, prms, nprms)
\r
7233 void NothingProc(w, event, prms, nprms)
\r
7242 void Iconify(w, event, prms, nprms)
\r
7250 fromX = fromY = -1;
\r
7251 XtSetArg(args[0], XtNiconic, True);
\r
7252 XtSetValues(shellWidget, args, 1);
\r
7255 void DisplayMessage(message, extMessage)
\r
7256 char *message, *extMessage;
\r
7258 char buf[MSG_SIZ];
\r
7263 sprintf(buf, "%s %s", message, extMessage);
\r
7266 message = extMessage;
\r
7269 XtSetArg(arg, XtNlabel, message);
\r
7270 XtSetValues(messageWidget, &arg, 1);
\r
7273 void DisplayTitle(text)
\r
7278 char title[MSG_SIZ];
\r
7279 char icon[MSG_SIZ];
\r
7281 if (text == NULL) text = "";
\r
7283 if (appData.titleInWindow) {
\r
7285 XtSetArg(args[i], XtNlabel, text); i++;
\r
7286 XtSetValues(titleWidget, args, i);
\r
7289 if (*text != NULLCHAR) {
\r
7290 strcpy(icon, text);
\r
7291 strcpy(title, text);
\r
7292 } else if (appData.icsActive) {
\r
7293 sprintf(icon, "%s", appData.icsHost);
\r
7294 sprintf(title, "%s: %s", programName, appData.icsHost);
\r
7295 } else if (appData.cmailGameName[0] != NULLCHAR) {
\r
7296 sprintf(icon, "%s", "CMail");
\r
7297 sprintf(title, "%s: %s", programName, "CMail");
\r
7299 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7300 } else if (gameInfo.variant == VariantGothic) {
\r
7301 strcpy(icon, programName);
\r
7302 strcpy(title, GOTHIC);
\r
7305 } else if (gameInfo.variant == VariantFalcon) {
\r
7306 strcpy(icon, programName);
\r
7307 strcpy(title, FALCON);
\r
7309 } else if (appData.noChessProgram) {
\r
7310 strcpy(icon, programName);
\r
7311 strcpy(title, programName);
\r
7313 strcpy(icon, first.tidy);
\r
7314 sprintf(title, "%s: %s", programName, first.tidy);
\r
7317 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
\r
7318 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
\r
7319 XtSetValues(shellWidget, args, i);
\r
7323 void DisplayError(message, error)
\r
7327 char buf[MSG_SIZ];
\r
7330 if (appData.debugMode || appData.matchMode) {
\r
7331 fprintf(stderr, "%s: %s\n", programName, message);
\r
7334 if (appData.debugMode || appData.matchMode) {
\r
7335 fprintf(stderr, "%s: %s: %s\n",
\r
7336 programName, message, strerror(error));
\r
7338 sprintf(buf, "%s: %s", message, strerror(error));
\r
7341 ErrorPopUp("Error", message, FALSE);
\r
7345 void DisplayMoveError(message)
\r
7348 fromX = fromY = -1;
\r
7349 ClearHighlights();
\r
7350 DrawPosition(FALSE, NULL);
\r
7351 if (appData.debugMode || appData.matchMode) {
\r
7352 fprintf(stderr, "%s: %s\n", programName, message);
\r
7354 if (appData.popupMoveErrors) {
\r
7355 ErrorPopUp("Error", message, FALSE);
\r
7357 DisplayMessage(message, "");
\r
7362 void DisplayFatalError(message, error, status)
\r
7364 int error, status;
\r
7366 char buf[MSG_SIZ];
\r
7368 errorExitStatus = status;
\r
7370 fprintf(stderr, "%s: %s\n", programName, message);
\r
7372 fprintf(stderr, "%s: %s: %s\n",
\r
7373 programName, message, strerror(error));
\r
7374 sprintf(buf, "%s: %s", message, strerror(error));
\r
7377 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
\r
7378 ErrorPopUp(status ? "Fatal Error" : "Exiting", message, TRUE);
\r
7380 ExitEvent(status);
\r
7384 void DisplayInformation(message)
\r
7388 ErrorPopUp("Information", message, TRUE);
\r
7391 void DisplayNote(message)
\r
7395 ErrorPopUp("Note", message, FALSE);
\r
7399 NullXErrorCheck(dpy, error_event)
\r
7401 XErrorEvent *error_event;
\r
7406 void DisplayIcsInteractionTitle(message)
\r
7409 if (oldICSInteractionTitle == NULL) {
\r
7410 /* Magic to find the old window title, adapted from vim */
\r
7411 char *wina = getenv("WINDOWID");
\r
7412 if (wina != NULL) {
\r
7413 Window win = (Window) atoi(wina);
\r
7414 Window root, parent, *children;
\r
7415 unsigned int nchildren;
\r
7416 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
\r
7418 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
\r
7419 if (!XQueryTree(xDisplay, win, &root, &parent,
\r
7420 &children, &nchildren)) break;
\r
7421 if (children) XFree((void *)children);
\r
7422 if (parent == root || parent == 0) break;
\r
7425 XSetErrorHandler(oldHandler);
\r
7427 if (oldICSInteractionTitle == NULL) {
\r
7428 oldICSInteractionTitle = "xterm";
\r
7431 printf("\033]0;%s\007", message);
\r
7435 char pendingReplyPrefix[MSG_SIZ];
\r
7436 ProcRef pendingReplyPR;
\r
7438 void AskQuestionProc(w, event, prms, nprms)
\r
7444 if (*nprms != 4) {
\r
7445 fprintf(stderr, "AskQuestionProc needed 4 parameters, got %d\n",
\r
7449 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
\r
7452 void AskQuestionPopDown()
\r
7454 if (!askQuestionUp) return;
\r
7455 XtPopdown(askQuestionShell);
\r
7456 XtDestroyWidget(askQuestionShell);
\r
7457 askQuestionUp = False;
\r
7460 void AskQuestionReplyAction(w, event, prms, nprms)
\r
7466 char buf[MSG_SIZ];
\r
7470 reply = XawDialogGetValueString(w = XtParent(w));
\r
7471 strcpy(buf, pendingReplyPrefix);
\r
7472 if (*buf) strcat(buf, " ");
\r
7473 strcat(buf, reply);
\r
7474 strcat(buf, "\n");
\r
7475 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
\r
7476 AskQuestionPopDown();
\r
7478 if (err) DisplayFatalError("Error writing to chess program", err, 0);
\r
7481 void AskQuestionCallback(w, client_data, call_data)
\r
7483 XtPointer client_data, call_data;
\r
7488 XtSetArg(args[0], XtNlabel, &name);
\r
7489 XtGetValues(w, args, 1);
\r
7491 if (strcmp(name, "cancel") == 0) {
\r
7492 AskQuestionPopDown();
\r
7494 AskQuestionReplyAction(w, NULL, NULL, NULL);
\r
7498 void AskQuestion(title, question, replyPrefix, pr)
\r
7499 char *title, *question, *replyPrefix;
\r
7503 Widget popup, layout, dialog, edit;
\r
7504 Window root, child;
\r
7507 unsigned int mask;
\r
7509 strcpy(pendingReplyPrefix, replyPrefix);
\r
7510 pendingReplyPR = pr;
\r
7513 XtSetArg(args[i], XtNresizable, True); i++;
\r
7514 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
\r
7515 askQuestionShell = popup =
\r
7516 XtCreatePopupShell(title, transientShellWidgetClass,
\r
7517 shellWidget, args, i);
\r
7520 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
\r
7521 layoutArgs, XtNumber(layoutArgs));
\r
7524 XtSetArg(args[i], XtNlabel, question); i++;
\r
7525 XtSetArg(args[i], XtNvalue, ""); i++;
\r
7526 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
7527 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
\r
7530 XawDialogAddButton(dialog, "enter", AskQuestionCallback,
\r
7531 (XtPointer) dialog);
\r
7532 XawDialogAddButton(dialog, "cancel", AskQuestionCallback,
\r
7533 (XtPointer) dialog);
\r
7535 XtRealizeWidget(popup);
\r
7536 CatchDeleteWindow(popup, "AskQuestionPopDown");
\r
7538 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
\r
7539 &x, &y, &win_x, &win_y, &mask);
\r
7541 XtSetArg(args[0], XtNx, x - 10);
\r
7542 XtSetArg(args[1], XtNy, y - 30);
\r
7543 XtSetValues(popup, args, 2);
\r
7545 XtPopup(popup, XtGrabExclusive);
\r
7546 askQuestionUp = True;
\r
7548 edit = XtNameToWidget(dialog, "*value");
\r
7549 XtSetKeyboardFocus(popup, edit);
\r
7557 if (*name == NULLCHAR) {
\r
7559 } else if (strcmp(name, "$") == 0) {
\r
7560 putc(BELLCHAR, stderr);
\r
7563 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
\r
7571 PlaySound(appData.soundMove);
\r
7577 PlaySound(appData.soundIcsWin);
\r
7581 PlayIcsLossSound()
\r
7583 PlaySound(appData.soundIcsLoss);
\r
7587 PlayIcsDrawSound()
\r
7589 PlaySound(appData.soundIcsDraw);
\r
7593 PlayIcsUnfinishedSound()
\r
7595 PlaySound(appData.soundIcsUnfinished);
\r
7601 PlaySound(appData.soundIcsAlarm);
\r
7607 system("stty echo");
\r
7613 system("stty -echo");
\r
7617 Colorize(cc, continuation)
\r
7621 char buf[MSG_SIZ];
\r
7622 int count, outCount, error;
\r
7624 if (textColors[(int)cc].bg > 0) {
\r
7625 if (textColors[(int)cc].fg > 0) {
\r
7626 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
\r
7627 textColors[(int)cc].fg, textColors[(int)cc].bg);
\r
7629 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
\r
7630 textColors[(int)cc].bg);
\r
7633 if (textColors[(int)cc].fg > 0) {
\r
7634 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
\r
7635 textColors[(int)cc].fg);
\r
7637 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
\r
7640 count = strlen(buf);
\r
7641 outCount = OutputToProcess(NoProc, buf, count, &error);
\r
7642 if (outCount < count) {
\r
7643 DisplayFatalError("Error writing to display", error, 1);
\r
7646 if (continuation) return;
\r
7649 PlaySound(appData.soundShout);
\r
7652 PlaySound(appData.soundSShout);
\r
7654 case ColorChannel1:
\r
7655 PlaySound(appData.soundChannel1);
\r
7657 case ColorChannel:
\r
7658 PlaySound(appData.soundChannel);
\r
7661 PlaySound(appData.soundKibitz);
\r
7664 PlaySound(appData.soundTell);
\r
7666 case ColorChallenge:
\r
7667 PlaySound(appData.soundChallenge);
\r
7669 case ColorRequest:
\r
7670 PlaySound(appData.soundRequest);
\r
7673 PlaySound(appData.soundSeek);
\r
7684 return getpwuid(getuid())->pw_name;
\r
7687 static char *ExpandPathName(path)
\r
7690 static char static_buf[2000];
\r
7691 char *d, *s, buf[2000];
\r
7692 struct passwd *pwd;
\r
7697 while (*s && isspace(*s))
\r
7702 return static_buf;
\r
7706 if (*(s+1) == '/') {
\r
7707 strcpy(d, getpwuid(getuid())->pw_dir);
\r
7712 *strchr(buf, '/') = 0;
\r
7713 pwd = getpwnam(buf);
\r
7716 fprintf(stderr, "ERROR: Unknown user %s (in path %s)\n",
\r
7720 strcpy(d, pwd->pw_dir);
\r
7721 strcat(d, strchr(s+1, '/'));
\r
7727 return static_buf;
\r
7732 static char host_name[MSG_SIZ];
\r
7734 #if HAVE_GETHOSTNAME
\r
7735 gethostname(host_name, MSG_SIZ);
\r
7737 #else /* not HAVE_GETHOSTNAME */
\r
7738 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
\r
7739 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
\r
7741 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
\r
7742 return "localhost";
\r
7743 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
\r
7744 #endif /* not HAVE_GETHOSTNAME */
\r
7747 XtIntervalId delayedEventTimerXID = 0;
\r
7748 DelayedEventCallback delayedEventCallback = 0;
\r
7751 FireDelayedEvent()
\r
7753 delayedEventTimerXID = 0;
\r
7754 delayedEventCallback();
\r
7758 ScheduleDelayedEvent(cb, millisec)
\r
7759 DelayedEventCallback cb; long millisec;
\r
7761 delayedEventCallback = cb;
\r
7762 delayedEventTimerXID =
\r
7763 XtAppAddTimeOut(appContext, millisec,
\r
7764 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
\r
7767 DelayedEventCallback
\r
7770 if (delayedEventTimerXID) {
\r
7771 return delayedEventCallback;
\r
7778 CancelDelayedEvent()
\r
7780 if (delayedEventTimerXID) {
\r
7781 XtRemoveTimeOut(delayedEventTimerXID);
\r
7782 delayedEventTimerXID = 0;
\r
7786 XtIntervalId loadGameTimerXID = 0;
\r
7788 int LoadGameTimerRunning()
\r
7790 return loadGameTimerXID != 0;
\r
7793 int StopLoadGameTimer()
\r
7795 if (loadGameTimerXID != 0) {
\r
7796 XtRemoveTimeOut(loadGameTimerXID);
\r
7797 loadGameTimerXID = 0;
\r
7805 LoadGameTimerCallback(arg, id)
\r
7809 loadGameTimerXID = 0;
\r
7810 AutoPlayGameLoop();
\r
7814 StartLoadGameTimer(millisec)
\r
7817 loadGameTimerXID =
\r
7818 XtAppAddTimeOut(appContext, millisec,
\r
7819 (XtTimerCallbackProc) LoadGameTimerCallback,
\r
7823 XtIntervalId analysisClockXID = 0;
\r
7826 AnalysisClockCallback(arg, id)
\r
7830 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
7831 AnalysisPeriodicEvent(0);
\r
7832 StartAnalysisClock();
\r
7837 StartAnalysisClock()
\r
7839 analysisClockXID =
\r
7840 XtAppAddTimeOut(appContext, 2000,
\r
7841 (XtTimerCallbackProc) AnalysisClockCallback,
\r
7845 XtIntervalId clockTimerXID = 0;
\r
7847 int ClockTimerRunning()
\r
7849 return clockTimerXID != 0;
\r
7852 int StopClockTimer()
\r
7854 if (clockTimerXID != 0) {
\r
7855 XtRemoveTimeOut(clockTimerXID);
\r
7856 clockTimerXID = 0;
\r
7864 ClockTimerCallback(arg, id)
\r
7868 clockTimerXID = 0;
\r
7869 DecrementClocks();
\r
7873 StartClockTimer(millisec)
\r
7877 XtAppAddTimeOut(appContext, millisec,
\r
7878 (XtTimerCallbackProc) ClockTimerCallback,
\r
7883 DisplayTimerLabel(w, color, timer, highlight)
\r
7889 char buf[MSG_SIZ];
\r
7892 if (appData.clockMode) {
\r
7893 sprintf(buf, "%s: %s", color, TimeString(timer));
\r
7894 XtSetArg(args[0], XtNlabel, buf);
\r
7896 sprintf(buf, "%s ", color);
\r
7897 XtSetArg(args[0], XtNlabel, buf);
\r
7901 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
\r
7902 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
\r
7904 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
\r
7905 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
\r
7908 XtSetValues(w, args, 3);
\r
7912 DisplayWhiteClock(timeRemaining, highlight)
\r
7913 long timeRemaining;
\r
7917 DisplayTimerLabel(whiteTimerWidget, "White", timeRemaining, highlight);
\r
7918 if (highlight && iconPixmap == bIconPixmap) {
\r
7919 iconPixmap = wIconPixmap;
\r
7920 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
\r
7921 XtSetValues(shellWidget, args, 1);
\r
7926 DisplayBlackClock(timeRemaining, highlight)
\r
7927 long timeRemaining;
\r
7931 DisplayTimerLabel(blackTimerWidget, "Black", timeRemaining, highlight);
\r
7932 if (highlight && iconPixmap == wIconPixmap) {
\r
7933 iconPixmap = bIconPixmap;
\r
7934 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
\r
7935 XtSetValues(shellWidget, args, 1);
\r
7944 typedef int CPKind;
\r
7949 int fdTo, fdFrom;
\r
7953 int StartChildProcess(cmdLine, dir, pr)
\r
7958 char *argv[64], *p;
\r
7960 int to_prog[2], from_prog[2];
\r
7962 char buf[MSG_SIZ];
\r
7964 if (appData.debugMode) {
\r
7965 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
\r
7968 /* We do NOT feed the cmdLine to the shell; we just
\r
7969 parse it into blank-separated arguments in the
\r
7970 most simple-minded way possible.
\r
7973 strcpy(buf, cmdLine);
\r
7977 p = strchr(p, ' ');
\r
7978 if (p == NULL) break;
\r
7983 SetUpChildIO(to_prog, from_prog);
\r
7985 if ((pid = fork()) == 0) {
\r
7987 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
\r
7988 close(to_prog[1]); // first close the unused pipe ends
\r
7989 close(from_prog[0]);
\r
7990 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
\r
7991 dup2(from_prog[1], 1);
\r
7992 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
\r
7993 close(from_prog[1]); // and closing again loses one of the pipes!
\r
7994 if(fileno(stderr) >= 2) // better safe than sorry...
7995 dup2(1, fileno(stderr)); /* force stderr to the pipe */
\r
7997 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
\r
8002 execvp(argv[0], argv);
\r
8004 /* If we get here, exec failed */
\r
8009 /* Parent process */
\r
8010 close(to_prog[0]);
\r
8011 close(from_prog[1]);
\r
8013 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8014 cp->kind = CPReal;
\r
8016 cp->fdFrom = from_prog[0];
\r
8017 cp->fdTo = to_prog[1];
\r
8018 *pr = (ProcRef) cp;
\r
8023 DestroyChildProcess(pr, signal)
\r
8027 ChildProc *cp = (ChildProc *) pr;
\r
8029 if (cp->kind != CPReal) return;
\r
8030 cp->kind = CPNone;
\r
8032 kill(cp->pid, SIGTERM);
\r
8034 /* Process is exiting either because of the kill or because of
\r
8035 a quit command sent by the backend; either way, wait for it to die.
\r
8038 close(cp->fdFrom);
\r
8043 InterruptChildProcess(pr)
\r
8046 ChildProc *cp = (ChildProc *) pr;
\r
8048 if (cp->kind != CPReal) return;
\r
8049 (void) kill(cp->pid, SIGINT); /* stop it thinking */
\r
8052 int OpenTelnet(host, port, pr)
\r
8057 char cmdLine[MSG_SIZ];
\r
8059 if (port[0] == NULLCHAR) {
\r
8060 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
\r
8062 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
\r
8064 return StartChildProcess(cmdLine, "", pr);
\r
8067 int OpenTCP(host, port, pr)
\r
8073 DisplayFatalError("Socket support is not configured in", 0, 2);
\r
8074 #else /* !OMIT_SOCKETS */
\r
8076 struct sockaddr_in sa;
\r
8077 struct hostent *hp;
\r
8078 unsigned short uport;
\r
8081 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
\r
8085 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
\r
8086 sa.sin_family = AF_INET;
\r
8087 sa.sin_addr.s_addr = INADDR_ANY;
\r
8088 uport = (unsigned short) 0;
\r
8089 sa.sin_port = htons(uport);
\r
8090 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
\r
8094 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
\r
8095 if (!(hp = gethostbyname(host))) {
\r
8096 int b0, b1, b2, b3;
\r
8097 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
\r
8098 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
\r
8099 hp->h_addrtype = AF_INET;
\r
8101 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
\r
8102 hp->h_addr_list[0] = (char *) malloc(4);
\r
8103 hp->h_addr_list[0][0] = b0;
\r
8104 hp->h_addr_list[0][1] = b1;
\r
8105 hp->h_addr_list[0][2] = b2;
\r
8106 hp->h_addr_list[0][3] = b3;
\r
8111 sa.sin_family = hp->h_addrtype;
\r
8112 uport = (unsigned short) atoi(port);
\r
8113 sa.sin_port = htons(uport);
\r
8114 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
\r
8116 if (connect(s, (struct sockaddr *) &sa,
\r
8117 sizeof(struct sockaddr_in)) < 0) {
\r
8121 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8122 cp->kind = CPSock;
\r
8126 *pr = (ProcRef) cp;
\r
8128 #endif /* !OMIT_SOCKETS */
\r
8133 int OpenCommPort(name, pr)
\r
8140 fd = open(name, 2, 0);
\r
8141 if (fd < 0) return errno;
\r
8143 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8144 cp->kind = CPComm;
\r
8148 *pr = (ProcRef) cp;
\r
8153 int OpenLoopback(pr)
\r
8157 int to[2], from[2];
\r
8159 SetUpChildIO(to, from);
\r
8161 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8162 cp->kind = CPLoop;
\r
8164 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
\r
8166 *pr = (ProcRef) cp;
\r
8171 int OpenRcmd(host, user, cmd, pr)
\r
8172 char *host, *user, *cmd;
\r
8175 DisplayFatalError("internal rcmd not implemented for Unix", 0, 1);
\r
8179 #define INPUT_SOURCE_BUF_SIZE 8192
\r
8186 InputCallback func;
\r
8188 char buf[INPUT_SOURCE_BUF_SIZE];
\r
8193 DoInputCallback(closure, source, xid)
\r
8198 InputSource *is = (InputSource *) closure;
\r
8203 if (is->lineByLine) {
\r
8204 count = read(is->fd, is->unused,
\r
8205 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
\r
8207 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
\r
8210 is->unused += count;
\r
8212 while (p < is->unused) {
\r
8213 q = memchr(p, '\n', is->unused - p);
\r
8214 if (q == NULL) break;
\r
8216 (is->func)(is, is->closure, p, q - p, 0);
\r
8220 while (p < is->unused) {
\r
8225 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
\r
8230 (is->func)(is, is->closure, is->buf, count, error);
\r
8234 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
\r
8237 InputCallback func;
\r
8241 ChildProc *cp = (ChildProc *) pr;
\r
8243 is = (InputSource *) calloc(1, sizeof(InputSource));
\r
8244 is->lineByLine = lineByLine;
\r
8246 if (pr == NoProc) {
\r
8247 is->kind = CPReal;
\r
8248 is->fd = fileno(stdin);
\r
8250 is->kind = cp->kind;
\r
8251 is->fd = cp->fdFrom;
\r
8254 is->unused = is->buf;
\r
8257 is->xid = XtAppAddInput(appContext, is->fd,
\r
8258 (XtPointer) (XtInputReadMask),
\r
8259 (XtInputCallbackProc) DoInputCallback,
\r
8261 is->closure = closure;
\r
8262 return (InputSourceRef) is;
\r
8266 RemoveInputSource(isr)
\r
8267 InputSourceRef isr;
\r
8269 InputSource *is = (InputSource *) isr;
\r
8271 if (is->xid == 0) return;
\r
8272 XtRemoveInput(is->xid);
\r
8276 int OutputToProcess(pr, message, count, outError)
\r
8282 ChildProc *cp = (ChildProc *) pr;
\r
8286 outCount = fwrite(message, 1, count, stdout);
\r
8288 outCount = write(cp->fdTo, message, count);
\r
8290 if (outCount == -1)
\r
8291 *outError = errno;
\r
8298 /* Output message to process, with "ms" milliseconds of delay
\r
8299 between each character. This is needed when sending the logon
\r
8300 script to ICC, which for some reason doesn't like the
\r
8301 instantaneous send. */
\r
8302 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
\r
8309 ChildProc *cp = (ChildProc *) pr;
\r
8314 r = write(cp->fdTo, message++, 1);
\r
8316 *outError = errno;
\r
8321 TimeDelay(msdelay);
\r
8327 /**** Animation code by Hugh Fisher, DCS, ANU.
\r
8329 Known problem: if a window overlapping the board is
\r
8330 moved away while a piece is being animated underneath,
\r
8331 the newly exposed area won't be updated properly.
\r
8332 I can live with this.
\r
8334 Known problem: if you look carefully at the animation
\r
8335 of pieces in mono mode, they are being drawn as solid
\r
8336 shapes without interior detail while moving. Fixing
\r
8337 this would be a major complication for minimal return.
\r
8340 /* Masks for XPM pieces. Black and white pieces can have
\r
8341 different shapes, but in the interest of retaining my
\r
8342 sanity pieces must have the same outline on both light
\r
8343 and dark squares, and all pieces must use the same
\r
8344 background square colors/images. */
\r
8347 CreateAnimMasks (pieceDepth)
\r
8350 ChessSquare piece;
\r
8354 unsigned long plane;
\r
8357 /* Need a bitmap just to get a GC with right depth */
\r
8358 buf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8360 values.foreground = 1;
\r
8361 values.background = 0;
\r
8362 /* Don't use XtGetGC, not read only */
\r
8363 maskGC = XCreateGC(xDisplay, buf,
\r
8364 GCForeground | GCBackground, &values);
\r
8365 XFreePixmap(xDisplay, buf);
\r
8367 buf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8368 squareSize, squareSize, pieceDepth);
\r
8369 values.foreground = XBlackPixel(xDisplay, xScreen);
\r
8370 values.background = XWhitePixel(xDisplay, xScreen);
\r
8371 bufGC = XCreateGC(xDisplay, buf,
\r
8372 GCForeground | GCBackground, &values);
\r
8374 for (piece = WhitePawn; piece <= BlackKing; piece++) {
\r
8375 /* Begin with empty mask */
\r
8376 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
\r
8377 squareSize, squareSize, 1);
\r
8378 XSetFunction(xDisplay, maskGC, GXclear);
\r
8379 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
\r
8380 0, 0, squareSize, squareSize);
\r
8382 /* Take a copy of the piece */
\r
8387 XSetFunction(xDisplay, bufGC, GXcopy);
\r
8388 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
\r
8390 0, 0, squareSize, squareSize, 0, 0);
\r
8392 /* XOR the background (light) over the piece */
\r
8393 XSetFunction(xDisplay, bufGC, GXxor);
\r
8395 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
\r
8396 0, 0, squareSize, squareSize, 0, 0);
\r
8398 XSetForeground(xDisplay, bufGC, lightSquareColor);
\r
8399 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
\r
8402 /* We now have an inverted piece image with the background
\r
8403 erased. Construct mask by just selecting all the non-zero
\r
8404 pixels - no need to reconstruct the original image. */
\r
8405 XSetFunction(xDisplay, maskGC, GXor);
\r
8407 /* Might be quicker to download an XImage and create bitmap
\r
8408 data from it rather than this N copies per piece, but it
\r
8409 only takes a fraction of a second and there is a much
\r
8410 longer delay for loading the pieces. */
\r
8411 for (n = 0; n < pieceDepth; n ++) {
\r
8412 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
\r
8413 0, 0, squareSize, squareSize,
\r
8415 plane = plane << 1;
\r
8419 XFreePixmap(xDisplay, buf);
\r
8420 XFreeGC(xDisplay, bufGC);
\r
8421 XFreeGC(xDisplay, maskGC);
\r
8425 InitAnimState (anim, info)
\r
8427 XWindowAttributes * info;
\r
8432 /* Each buffer is square size, same depth as window */
\r
8433 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8434 squareSize, squareSize, info->depth);
\r
8435 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8436 squareSize, squareSize, info->depth);
\r
8438 /* Create a plain GC for blitting */
\r
8439 mask = GCForeground | GCBackground | GCFunction |
\r
8440 GCPlaneMask | GCGraphicsExposures;
\r
8441 values.foreground = XBlackPixel(xDisplay, xScreen);
\r
8442 values.background = XWhitePixel(xDisplay, xScreen);
\r
8443 values.function = GXcopy;
\r
8444 values.plane_mask = AllPlanes;
\r
8445 values.graphics_exposures = False;
\r
8446 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
\r
8448 /* Piece will be copied from an existing context at
\r
8449 the start of each new animation/drag. */
\r
8450 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
\r
8452 /* Outline will be a read-only copy of an existing */
\r
8453 anim->outlineGC = None;
\r
8459 static int done = 0;
\r
8460 XWindowAttributes info;
\r
8464 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
\r
8466 InitAnimState(&game, &info);
\r
8467 InitAnimState(&player, &info);
\r
8469 /* For XPM pieces, we need bitmaps to use as masks. */
\r
8471 CreateAnimMasks(info.depth);
\r
8474 #ifndef HAVE_USLEEP
\r
8476 static Boolean frameWaiting;
\r
8478 static RETSIGTYPE FrameAlarm (sig)
\r
8481 frameWaiting = False;
\r
8482 /* In case System-V style signals. Needed?? */
\r
8483 signal(SIGALRM, FrameAlarm);
\r
8490 struct itimerval delay;
\r
8492 XSync(xDisplay, False);
\r
8495 frameWaiting = True;
\r
8496 signal(SIGALRM, FrameAlarm);
\r
8497 delay.it_interval.tv_sec =
\r
8498 delay.it_value.tv_sec = time / 1000;
\r
8499 delay.it_interval.tv_usec =
\r
8500 delay.it_value.tv_usec = (time % 1000) * 1000;
\r
8501 setitimer(ITIMER_REAL, &delay, NULL);
\r
8503 /* Ugh -- busy-wait! --tpm */
\r
8504 while (frameWaiting);
\r
8506 while (frameWaiting) pause();
\r
8508 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
\r
8509 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
\r
8510 setitimer(ITIMER_REAL, &delay, NULL);
\r
8520 XSync(xDisplay, False);
\r
8522 usleep(time * 1000);
\r
8527 /* Convert board position to corner of screen rect and color */
\r
8530 ScreenSquare(column, row, pt, color)
\r
8531 int column; int row; XPoint * pt; int * color;
\r
8534 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
8535 pt->y = lineGap + row * (squareSize + lineGap);
\r
8537 pt->x = lineGap + column * (squareSize + lineGap);
\r
8538 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
8540 *color = SquareColor(row, column);
\r
8543 /* Convert window coords to square */
\r
8546 BoardSquare(x, y, column, row)
\r
8547 int x; int y; int * column; int * row;
\r
8549 *column = EventToSquare(x, BOARD_WIDTH);
\r
8550 if (flipView && *column >= 0)
\r
8551 *column = BOARD_WIDTH - 1 - *column;
\r
8552 *row = EventToSquare(y, BOARD_HEIGHT);
\r
8553 if (!flipView && *row >= 0)
\r
8554 *row = BOARD_HEIGHT - 1 - *row;
\r
8559 #undef Max /* just in case */
\r
8561 #define Max(a, b) ((a) > (b) ? (a) : (b))
\r
8562 #define Min(a, b) ((a) < (b) ? (a) : (b))
\r
8565 SetRect(rect, x, y, width, height)
\r
8566 XRectangle * rect; int x; int y; int width; int height;
\r
8570 rect->width = width;
\r
8571 rect->height = height;
\r
8574 /* Test if two frames overlap. If they do, return
\r
8575 intersection rect within old and location of
\r
8576 that rect within new. */
\r
8579 Intersect(old, new, size, area, pt)
\r
8580 XPoint * old; XPoint * new;
\r
8581 int size; XRectangle * area; XPoint * pt;
\r
8583 if (old->x > new->x + size || new->x > old->x + size ||
\r
8584 old->y > new->y + size || new->y > old->y + size) {
\r
8587 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
\r
8588 size - abs(old->x - new->x), size - abs(old->y - new->y));
\r
8589 pt->x = Max(old->x - new->x, 0);
\r
8590 pt->y = Max(old->y - new->y, 0);
\r
8595 /* For two overlapping frames, return the rect(s)
\r
8596 in the old that do not intersect with the new. */
\r
8599 CalcUpdateRects(old, new, size, update, nUpdates)
\r
8600 XPoint * old; XPoint * new; int size;
\r
8601 XRectangle update[]; int * nUpdates;
\r
8605 /* If old = new (shouldn't happen) then nothing to draw */
\r
8606 if (old->x == new->x && old->y == new->y) {
\r
8610 /* Work out what bits overlap. Since we know the rects
\r
8611 are the same size we don't need a full intersect calc. */
\r
8613 /* Top or bottom edge? */
\r
8614 if (new->y > old->y) {
\r
8615 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
\r
8617 } else if (old->y > new->y) {
\r
8618 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
\r
8619 size, old->y - new->y);
\r
8622 /* Left or right edge - don't overlap any update calculated above. */
\r
8623 if (new->x > old->x) {
\r
8624 SetRect(&(update[count]), old->x, Max(new->y, old->y),
\r
8625 new->x - old->x, size - abs(new->y - old->y));
\r
8627 } else if (old->x > new->x) {
\r
8628 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
\r
8629 old->x - new->x, size - abs(new->y - old->y));
\r
8633 *nUpdates = count;
\r
8636 /* Generate a series of frame coords from start->mid->finish.
\r
8637 The movement rate doubles until the half way point is
\r
8638 reached, then halves back down to the final destination,
\r
8639 which gives a nice slow in/out effect. The algorithmn
\r
8640 may seem to generate too many intermediates for short
\r
8641 moves, but remember that the purpose is to attract the
\r
8642 viewers attention to the piece about to be moved and
\r
8643 then to where it ends up. Too few frames would be less
\r
8647 Tween(start, mid, finish, factor, frames, nFrames)
\r
8648 XPoint * start; XPoint * mid;
\r
8649 XPoint * finish; int factor;
\r
8650 XPoint frames[]; int * nFrames;
\r
8652 int fraction, n, count;
\r
8656 /* Slow in, stepping 1/16th, then 1/8th, ... */
\r
8658 for (n = 0; n < factor; n++)
\r
8660 for (n = 0; n < factor; n++) {
\r
8661 frames[count].x = start->x + (mid->x - start->x) / fraction;
\r
8662 frames[count].y = start->y + (mid->y - start->y) / fraction;
\r
8664 fraction = fraction / 2;
\r
8668 frames[count] = *mid;
\r
8671 /* Slow out, stepping 1/2, then 1/4, ... */
\r
8673 for (n = 0; n < factor; n++) {
\r
8674 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
\r
8675 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
\r
8677 fraction = fraction * 2;
\r
8682 /* Draw a piece on the screen without disturbing what's there */
\r
8685 SelectGCMask(piece, clip, outline, mask)
\r
8686 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
\r
8690 /* Bitmap for piece being moved. */
\r
8691 if (appData.monoMode) {
\r
8692 *mask = *pieceToSolid(piece);
\r
8693 } else if (useImages) {
\r
8695 *mask = xpmMask[piece];
\r
8697 *mask = ximMaskPm[piece%(int)BlackPawn];
\r
8700 *mask = *pieceToSolid(piece);
\r
8703 /* GC for piece being moved. Square color doesn't matter, but
\r
8704 since it gets modified we make a copy of the original. */
\r
8705 if (White(piece)) {
\r
8706 if (appData.monoMode)
\r
8707 source = bwPieceGC;
\r
8709 source = wlPieceGC;
\r
8711 if (appData.monoMode)
\r
8712 source = wbPieceGC;
\r
8714 source = blPieceGC;
\r
8716 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
\r
8718 /* Outline only used in mono mode and is not modified */
\r
8720 *outline = bwPieceGC;
\r
8722 *outline = wbPieceGC;
\r
8726 OverlayPiece(piece, clip, outline, dest)
\r
8727 ChessSquare piece; GC clip; GC outline; Drawable dest;
\r
8732 /* Draw solid rectangle which will be clipped to shape of piece */
\r
8733 XFillRectangle(xDisplay, dest, clip,
\r
8734 0, 0, squareSize, squareSize);
\r
8735 if (appData.monoMode)
\r
8736 /* Also draw outline in contrasting color for black
\r
8737 on black / white on white cases */
\r
8738 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
\r
8739 0, 0, squareSize, squareSize, 0, 0, 1);
\r
8741 /* Copy the piece */
\r
8746 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
\r
8748 0, 0, squareSize, squareSize,
\r
8753 /* Animate the movement of a single piece */
\r
8756 BeginAnimation(anim, piece, startColor, start)
\r
8758 ChessSquare piece;
\r
8764 /* The old buffer is initialised with the start square (empty) */
\r
8765 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
\r
8766 anim->prevFrame = *start;
\r
8768 /* The piece will be drawn using its own bitmap as a matte */
\r
8769 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
\r
8770 XSetClipMask(xDisplay, anim->pieceGC, mask);
\r
8774 AnimationFrame(anim, frame, piece)
\r
8777 ChessSquare piece;
\r
8779 XRectangle updates[4];
\r
8780 XRectangle overlap;
\r
8784 /* Save what we are about to draw into the new buffer */
\r
8785 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
\r
8786 frame->x, frame->y, squareSize, squareSize,
\r
8789 /* Erase bits of the previous frame */
\r
8790 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
\r
8791 /* Where the new frame overlapped the previous,
\r
8792 the contents in newBuf are wrong. */
\r
8793 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
\r
8794 overlap.x, overlap.y,
\r
8795 overlap.width, overlap.height,
\r
8797 /* Repaint the areas in the old that don't overlap new */
\r
8798 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
\r
8799 for (i = 0; i < count; i++)
\r
8800 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8801 updates[i].x - anim->prevFrame.x,
\r
8802 updates[i].y - anim->prevFrame.y,
\r
8803 updates[i].width, updates[i].height,
\r
8804 updates[i].x, updates[i].y);
\r
8806 /* Easy when no overlap */
\r
8807 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8808 0, 0, squareSize, squareSize,
\r
8809 anim->prevFrame.x, anim->prevFrame.y);
\r
8812 /* Save this frame for next time round */
\r
8813 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
\r
8814 0, 0, squareSize, squareSize,
\r
8816 anim->prevFrame = *frame;
\r
8818 /* Draw piece over original screen contents, not current,
\r
8819 and copy entire rect. Wipes out overlapping piece images. */
\r
8820 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
\r
8821 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
\r
8822 0, 0, squareSize, squareSize,
\r
8823 frame->x, frame->y);
\r
8827 EndAnimation (anim, finish)
\r
8831 XRectangle updates[4];
\r
8832 XRectangle overlap;
\r
8836 /* The main code will redraw the final square, so we
\r
8837 only need to erase the bits that don't overlap. */
\r
8838 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
\r
8839 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
\r
8840 for (i = 0; i < count; i++)
\r
8841 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8842 updates[i].x - anim->prevFrame.x,
\r
8843 updates[i].y - anim->prevFrame.y,
\r
8844 updates[i].width, updates[i].height,
\r
8845 updates[i].x, updates[i].y);
\r
8847 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8848 0, 0, squareSize, squareSize,
\r
8849 anim->prevFrame.x, anim->prevFrame.y);
\r
8854 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
\r
8856 ChessSquare piece; int startColor;
\r
8857 XPoint * start; XPoint * finish;
\r
8858 XPoint frames[]; int nFrames;
\r
8862 BeginAnimation(anim, piece, startColor, start);
\r
8863 for (n = 0; n < nFrames; n++) {
\r
8864 AnimationFrame(anim, &(frames[n]), piece);
\r
8865 FrameDelay(appData.animSpeed);
\r
8867 EndAnimation(anim, finish);
\r
8870 /* Main control logic for deciding what to animate and how */
\r
8873 AnimateMove(board, fromX, fromY, toX, toY)
\r
8880 ChessSquare piece;
\r
8882 XPoint start, finish, mid;
\r
8883 XPoint frames[kFactor * 2 + 1];
\r
8884 int nFrames, startColor, endColor;
\r
8886 /* Are we animating? */
\r
8887 if (!appData.animate || appData.blindfold)
\r
8890 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
\r
8891 piece = board[fromY][fromX];
\r
8892 if (piece >= EmptySquare) return;
\r
8897 hop = (piece == WhiteKnight || piece == BlackKnight);
\r
8900 if (appData.debugMode) {
\r
8901 printf("AnimateMove: piece %d %s from %d,%d to %d,%d \n",
\r
8902 piece, hop ? "hops" : "slides", fromX, fromY, toX, toY);
\r
8905 ScreenSquare(fromX, fromY, &start, &startColor);
\r
8906 ScreenSquare(toX, toY, &finish, &endColor);
\r
8909 /* Knight: make diagonal movement then straight */
\r
8910 if (abs(toY - fromY) < abs(toX - fromX)) {
\r
8911 mid.x = start.x + (finish.x - start.x) / 2;
\r
8915 mid.y = start.y + (finish.y - start.y) / 2;
\r
8918 mid.x = start.x + (finish.x - start.x) / 2;
\r
8919 mid.y = start.y + (finish.y - start.y) / 2;
\r
8922 /* Don't use as many frames for very short moves */
\r
8923 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
\r
8924 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
\r
8926 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
\r
8927 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
\r
8929 /* Be sure end square is redrawn */
\r
8930 damage[toY][toX] = True;
\r
8934 DragPieceBegin(x, y)
\r
8937 int boardX, boardY, color;
\r
8940 /* Are we animating? */
\r
8941 if (!appData.animateDragging || appData.blindfold)
\r
8944 /* Figure out which square we start in and the
\r
8945 mouse position relative to top left corner. */
\r
8946 BoardSquare(x, y, &boardX, &boardY);
\r
8947 player.startBoardX = boardX;
\r
8948 player.startBoardY = boardY;
\r
8949 ScreenSquare(boardX, boardY, &corner, &color);
\r
8950 player.startSquare = corner;
\r
8951 player.startColor = color;
\r
8953 /* Start from exactly where the piece is. This can be confusing
\r
8954 if you start dragging far from the center of the square; most
\r
8955 or all of the piece can be over a different square from the one
\r
8956 the mouse pointer is in. */
\r
8957 player.mouseDelta.x = x - corner.x;
\r
8958 player.mouseDelta.y = y - corner.y;
\r
8960 /* As soon as we start dragging, the piece will jump slightly to
\r
8961 be centered over the mouse pointer. */
\r
8962 player.mouseDelta.x = squareSize/2;
\r
8963 player.mouseDelta.y = squareSize/2;
\r
8965 /* Initialise animation */
\r
8966 player.dragPiece = PieceForSquare(boardX, boardY);
\r
8967 /* Sanity check */
\r
8968 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
\r
8969 player.dragActive = True;
\r
8970 BeginAnimation(&player, player.dragPiece, color, &corner);
\r
8971 /* Mark this square as needing to be redrawn. Note that
\r
8972 we don't remove the piece though, since logically (ie
\r
8973 as seen by opponent) the move hasn't been made yet. */
\r
8974 damage[boardY][boardX] = True;
\r
8976 player.dragActive = False;
\r
8981 DragPieceMove(x, y)
\r
8986 /* Are we animating? */
\r
8987 if (!appData.animateDragging || appData.blindfold)
\r
8990 /* Sanity check */
\r
8991 if (! player.dragActive)
\r
8993 /* Move piece, maintaining same relative position
\r
8994 of mouse within square */
\r
8995 corner.x = x - player.mouseDelta.x;
\r
8996 corner.y = y - player.mouseDelta.y;
\r
8997 AnimationFrame(&player, &corner, player.dragPiece);
\r
8999 if (appData.highlightDragging) {
\r
9000 int boardX, boardY;
\r
9001 BoardSquare(x, y, &boardX, &boardY);
\r
9002 SetHighlights(fromX, fromY, boardX, boardY);
\r
9008 DragPieceEnd(x, y)
\r
9011 int boardX, boardY, color;
\r
9014 /* Are we animating? */
\r
9015 if (!appData.animateDragging || appData.blindfold)
\r
9018 /* Sanity check */
\r
9019 if (! player.dragActive)
\r
9021 /* Last frame in sequence is square piece is
\r
9022 placed on, which may not match mouse exactly. */
\r
9023 BoardSquare(x, y, &boardX, &boardY);
\r
9024 ScreenSquare(boardX, boardY, &corner, &color);
\r
9025 EndAnimation(&player, &corner);
\r
9027 /* Be sure end square is redrawn */
\r
9028 damage[boardY][boardX] = True;
\r
9030 /* This prevents weird things happening with fast successive
\r
9031 clicks which on my Sun at least can cause motion events
\r
9032 without corresponding press/release. */
\r
9033 player.dragActive = False;
\r
9036 /* Handle expose event while piece being dragged */
\r
9041 if (!player.dragActive || appData.blindfold)
\r
9044 /* What we're doing: logically, the move hasn't been made yet,
\r
9045 so the piece is still in it's original square. But visually
\r
9046 it's being dragged around the board. So we erase the square
\r
9047 that the piece is on and draw it at the last known drag point. */
\r
9048 BlankSquare(player.startSquare.x, player.startSquare.y,
\r
9049 player.startColor, EmptySquare, xBoardWindow);
\r
9050 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
\r
9051 damage[player.startBoardY][player.startBoardX] = TRUE;
\r
9055 SetProgramStats( FrontEndProgramStats * stats )
\r
9058 // [HGM] done, but perhaps backend should call this directly?
\r
9059 EngineOutputUpdate( stats );
\r