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 FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
427 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
\r
428 void ShufflePopDown P(());
\r
429 void EnginePopDown P(());
\r
430 void UciPopDown P(());
\r
431 void TimeControlPopDown P(());
\r
432 void NewVariantPopDown P(());
\r
433 void SettingsPopDown P(());
\r
435 * XBoard depends on Xt R4 or higher
\r
437 int xtVersion = XtSpecificationRelease;
\r
441 Window xBoardWindow;
\r
442 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
\r
443 jailSquareColor, highlightSquareColor, premoveHighlightColor;
\r
444 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
\r
445 bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
\r
446 wjPieceGC, bjPieceGC, prelineGC, countGC;
\r
447 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
\r
448 Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
\r
449 whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16],
\r
450 commentShell, promotionShell, whitePieceMenu, blackPieceMenu, dropMenu,
\r
451 menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
\r
452 ICSInputShell, fileNameShell, askQuestionShell;
\r
453 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
\r
454 XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
\r
455 Font clockFontID, coordFontID, countFontID;
\r
456 XFontStruct *clockFontStruct, *coordFontStruct, *countFontStruct;
\r
457 XtAppContext appContext;
\r
459 char *oldICSInteractionTitle;
\r
463 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
\r
465 Position commentX = -1, commentY = -1;
\r
466 Dimension commentW, commentH;
\r
468 int squareSize, smallLayout = 0, tinyLayout = 0,
469 marginW, marginH, // [HGM] for run-time resizing
\r
470 fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False,
\r
471 ICSInputBoxUp = False, askQuestionUp = False,
\r
472 filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1,
\r
473 editUp = False, errorUp = False, errorExitStatus = -1, lineGap;
\r
474 Pixel timerForegroundPixel, timerBackgroundPixel;
\r
475 Pixel buttonForegroundPixel, buttonBackgroundPixel;
\r
476 char *chessDir, *programName, *programVersion,
\r
477 *gameCopyFilename, *gamePasteFilename;
\r
481 Pixmap pieceBitmap[2][(int)BlackPawn];
\r
482 Pixmap xpmPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
\r
483 Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
\r
484 int useImages, useImageSqs;
\r
485 XImage *ximPieceBitmap[4][(int)BlackPawn]; /* LL, LD, DL, DD */
\r
486 Pixmap ximMaskPm[(int)BlackPawn]; /* clipmasks, used for XIM pieces */
\r
487 XImage *ximLightSquare, *ximDarkSquare;
\r
490 #define pieceToSolid(piece) &pieceBitmap[SOLID][((int)(piece)) % (int)BlackPawn]
\r
491 #define pieceToOutline(piece) &pieceBitmap[OUTLINE][((int)(piece)) % (int)BlackPawn]
\r
493 #define White(piece) ((int)(piece) < (int)BlackPawn)
\r
495 /* Variables for doing smooth animation. This whole thing
\r
496 would be much easier if the board was double-buffered,
\r
497 but that would require a fairly major rewrite. */
\r
502 GC blitGC, pieceGC, outlineGC;
\r
503 XPoint startSquare, prevFrame, mouseDelta;
\r
506 Boolean dragActive;
\r
507 int startBoardX, startBoardY;
\r
510 /* There can be two pieces being animated at once: a player
\r
511 can begin dragging a piece before the remote opponent has moved. */
\r
513 static AnimState game, player;
\r
515 /* Bitmaps for use as masks when drawing XPM pieces.
\r
516 Need one for each black and white piece. */
\r
517 static Pixmap xpmMask[BlackKing + 1];
\r
519 /* This magic number is the number of intermediate frames used
\r
520 in each half of the animation. For short moves it's reduced
\r
521 by 1. The total number of frames will be factor * 2 + 1. */
\r
524 SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
\r
526 MenuItem fileMenu[] = {
\r
527 {"New Game", ResetProc},
\r
528 {"New Shuffle Game ...", ShuffleMenuProc},
\r
529 {"New Variant ...", NewVariantProc}, // [HGM] variant: not functional yet
\r
530 {"----", NothingProc},
\r
531 {"Load Game", LoadGameProc},
\r
532 {"Load Next Game", LoadNextGameProc},
\r
533 {"Load Previous Game", LoadPrevGameProc},
\r
534 {"Reload Same Game", ReloadGameProc},
\r
535 {"Save Game", SaveGameProc},
\r
536 {"----", NothingProc},
\r
537 {"Copy Game", CopyGameProc},
\r
538 {"Paste Game", PasteGameProc},
\r
539 {"----", NothingProc},
\r
540 {"Load Position", LoadPositionProc},
\r
541 {"Load Next Position", LoadNextPositionProc},
\r
542 {"Load Previous Position", LoadPrevPositionProc},
\r
543 {"Reload Same Position", ReloadPositionProc},
\r
544 {"Save Position", SavePositionProc},
\r
545 {"----", NothingProc},
\r
546 {"Copy Position", CopyPositionProc},
\r
547 {"Paste Position", PastePositionProc},
\r
548 {"----", NothingProc},
\r
549 {"Mail Move", MailMoveProc},
\r
550 {"Reload CMail Message", ReloadCmailMsgProc},
\r
551 {"----", NothingProc},
\r
552 {"Exit", QuitProc},
\r
556 MenuItem modeMenu[] = {
\r
557 {"Machine White", MachineWhiteProc},
\r
558 {"Machine Black", MachineBlackProc},
\r
559 {"Two Machines", TwoMachinesProc},
\r
560 {"Analysis Mode", AnalyzeModeProc},
\r
561 {"Analyze File", AnalyzeFileProc },
\r
562 {"ICS Client", IcsClientProc},
\r
563 {"Edit Game", EditGameProc},
\r
564 {"Edit Position", EditPositionProc},
\r
565 {"Training", TrainingProc},
\r
566 {"----", NothingProc},
\r
567 {"Show Engine Output", EngineOutputProc},
\r
568 {"Show Evaluation Graph", NothingProc}, // [HGM] evalgr: not functional yet
\r
569 {"Show Game List", ShowGameListProc},
\r
570 {"Show Move History", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
\r
571 {"----", NothingProc},
\r
572 {"Edit Tags", EditTagsProc},
\r
573 {"Edit Comment", EditCommentProc},
\r
574 {"ICS Input Box", IcsInputBoxProc},
\r
575 {"Pause", PauseProc},
\r
579 MenuItem actionMenu[] = {
\r
580 {"Accept", AcceptProc},
\r
581 {"Decline", DeclineProc},
\r
582 {"Rematch", RematchProc},
\r
583 {"----", NothingProc},
\r
584 {"Call Flag", CallFlagProc},
\r
585 {"Draw", DrawProc},
\r
586 {"Adjourn", AdjournProc},
\r
587 {"Abort", AbortProc},
\r
588 {"Resign", ResignProc},
\r
589 {"----", NothingProc},
\r
590 {"Stop Observing", StopObservingProc},
\r
591 {"Stop Examining", StopExaminingProc},
\r
595 MenuItem stepMenu[] = {
\r
596 {"Backward", BackwardProc},
\r
597 {"Forward", ForwardProc},
\r
598 {"Back to Start", ToStartProc},
\r
599 {"Forward to End", ToEndProc},
\r
600 {"Revert", RevertProc},
\r
601 {"Truncate Game", TruncateGameProc},
\r
602 {"----", NothingProc},
\r
603 {"Move Now", MoveNowProc},
\r
604 {"Retract Move", RetractMoveProc},
\r
608 MenuItem optionsMenu[] = {
609 {"Flip View", FlipViewProc},
\r
610 {"----", NothingProc},
\r
611 {"Adjudications ...", EngineMenuProc},
\r
612 {"General Settings ...", UciMenuProc},
\r
613 {"Engine #1 Settings ...", FirstSettingsProc},
\r
614 {"Engine #2 Settings ...", SecondSettingsProc},
\r
615 {"Time Control ...", TimeControlProc},
\r
616 {"----", NothingProc},
\r
617 {"Always Queen", AlwaysQueenProc},
\r
618 {"Animate Dragging", AnimateDraggingProc},
\r
619 {"Animate Moving", AnimateMovingProc},
\r
620 {"Auto Comment", AutocommProc},
\r
621 {"Auto Flag", AutoflagProc},
\r
622 {"Auto Flip View", AutoflipProc},
\r
623 {"Auto Observe", AutobsProc},
\r
624 {"Auto Raise Board", AutoraiseProc},
\r
625 {"Auto Save", AutosaveProc},
\r
626 {"Blindfold", BlindfoldProc},
\r
627 {"Flash Moves", FlashMovesProc},
\r
628 {"Get Move List", GetMoveListProc},
\r
630 {"Highlight Dragging", HighlightDraggingProc},
\r
632 {"Highlight Last Move", HighlightLastMoveProc},
\r
633 {"Move Sound", MoveSoundProc},
\r
634 {"ICS Alarm", IcsAlarmProc},
\r
635 {"Old Save Style", OldSaveStyleProc},
\r
636 {"Periodic Updates", PeriodicUpdatesProc},
\r
637 {"Ponder Next Move", PonderNextMoveProc},
\r
638 {"Popup Exit Message", PopupExitMessageProc},
\r
639 {"Popup Move Errors", PopupMoveErrorsProc},
\r
640 {"Premove", PremoveProc},
\r
641 {"Quiet Play", QuietPlayProc},
\r
642 {"Show Coords", ShowCoordsProc},
\r
643 {"Hide Thinking", HideThinkingProc},
\r
644 {"Test Legality", TestLegalityProc},
\r
648 MenuItem helpMenu[] = {
\r
649 {"Info XBoard", InfoProc},
\r
650 {"Man XBoard", ManProc},
\r
651 {"----", NothingProc},
\r
652 {"Hint", HintProc},
\r
653 {"Book", BookProc},
\r
654 {"----", NothingProc},
\r
655 {"About XBoard", AboutProc},
\r
660 {"File", fileMenu},
\r
661 {"Mode", modeMenu},
\r
662 {"Action", actionMenu},
\r
663 {"Step", stepMenu},
\r
664 {"Options", optionsMenu},
\r
665 {"Help", helpMenu},
\r
669 #define PAUSE_BUTTON "P"
\r
670 MenuItem buttonBar[] = {
\r
671 {"<<", ToStartProc},
\r
672 {"<", BackwardProc},
\r
673 {PAUSE_BUTTON, PauseProc},
\r
674 {">", ForwardProc},
\r
679 #define PIECE_MENU_SIZE 11
\r
680 String pieceMenuStrings[2][PIECE_MENU_SIZE] = {
\r
681 { "White", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
\r
682 "----", "Empty square", "Clear board" },
\r
683 { "Black", "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
\r
684 "----", "Empty square", "Clear board" },
\r
686 /* must be in same order as PieceMenuStrings! */
\r
687 ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
\r
688 { WhitePlay, (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
\r
689 WhiteRook, WhiteQueen, WhiteKing,
\r
690 (ChessSquare) 0, EmptySquare, ClearBoard },
\r
691 { BlackPlay, (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
\r
692 BlackRook, BlackQueen, BlackKing,
\r
693 (ChessSquare) 0, EmptySquare, ClearBoard },
\r
696 #define DROP_MENU_SIZE 6
\r
697 String dropMenuStrings[DROP_MENU_SIZE] = {
\r
698 "----", "Pawn", "Knight", "Bishop", "Rook", "Queen"
\r
700 /* must be in same order as PieceMenuStrings! */
\r
701 ChessSquare dropMenuTranslation[DROP_MENU_SIZE] = {
\r
702 (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
\r
703 WhiteRook, WhiteQueen
\r
711 DropMenuEnables dmEnables[] = {
\r
719 Arg shellArgs[] = {
\r
722 { XtNminWidth, 0 },
\r
723 { XtNminHeight, 0 },
\r
724 { XtNmaxWidth, 0 },
\r
725 { XtNmaxHeight, 0 }
\r
728 Arg layoutArgs[] = {
\r
729 { XtNborderWidth, 0 },
\r
730 { XtNdefaultDistance, 0 },
\r
734 { XtNborderWidth, 0 },
\r
735 { XtNresizable, (XtArgVal) True },
\r
738 Arg boardArgs[] = {
\r
739 { XtNborderWidth, 0 },
\r
744 Arg titleArgs[] = {
\r
745 { XtNjustify, (XtArgVal) XtJustifyRight },
\r
746 { XtNlabel, (XtArgVal) "..." },
\r
747 { XtNresizable, (XtArgVal) True },
\r
748 { XtNresize, (XtArgVal) False }
\r
751 Arg messageArgs[] = {
\r
752 { XtNjustify, (XtArgVal) XtJustifyLeft },
\r
753 { XtNlabel, (XtArgVal) "..." },
\r
754 { XtNresizable, (XtArgVal) True },
\r
755 { XtNresize, (XtArgVal) False }
\r
758 Arg timerArgs[] = {
\r
759 { XtNborderWidth, 0 },
\r
760 { XtNjustify, (XtArgVal) XtJustifyLeft }
\r
763 XtResource clientResources[] = {
\r
764 { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
\r
765 XtOffset(AppDataPtr, whitePieceColor), XtRString,
\r
766 WHITE_PIECE_COLOR },
\r
767 { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
\r
768 XtOffset(AppDataPtr, blackPieceColor), XtRString,
\r
769 BLACK_PIECE_COLOR },
\r
770 { "lightSquareColor", "lightSquareColor", XtRString,
\r
771 sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
\r
772 XtRString, LIGHT_SQUARE_COLOR },
\r
773 { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
\r
774 XtOffset(AppDataPtr, darkSquareColor), XtRString,
\r
775 DARK_SQUARE_COLOR },
\r
776 { "highlightSquareColor", "highlightSquareColor", XtRString,
\r
777 sizeof(String), XtOffset(AppDataPtr, highlightSquareColor),
\r
778 XtRString, HIGHLIGHT_SQUARE_COLOR },
\r
779 { "premoveHighlightColor", "premoveHighlightColor", XtRString,
\r
780 sizeof(String), XtOffset(AppDataPtr, premoveHighlightColor),
\r
781 XtRString, PREMOVE_HIGHLIGHT_COLOR },
\r
782 { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
\r
783 XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
\r
784 (XtPointer) MOVES_PER_SESSION },
\r
785 { "timeIncrement", "timeIncrement", XtRInt, sizeof(int),
\r
786 XtOffset(AppDataPtr, timeIncrement), XtRImmediate,
\r
787 (XtPointer) TIME_INCREMENT },
\r
788 { "initString", "initString", XtRString, sizeof(String),
\r
789 XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
\r
790 { "secondInitString", "secondInitString", XtRString, sizeof(String),
\r
791 XtOffset(AppDataPtr, secondInitString), XtRString, INIT_STRING },
\r
792 { "firstComputerString", "firstComputerString", XtRString,
\r
793 sizeof(String), XtOffset(AppDataPtr, firstComputerString), XtRString,
\r
795 { "secondComputerString", "secondComputerString", XtRString,
\r
796 sizeof(String), XtOffset(AppDataPtr, secondComputerString), XtRString,
\r
798 { "firstChessProgram", "firstChessProgram", XtRString,
\r
799 sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
\r
800 XtRString, FIRST_CHESS_PROGRAM },
\r
801 { "secondChessProgram", "secondChessProgram", XtRString,
\r
802 sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
\r
803 XtRString, SECOND_CHESS_PROGRAM },
\r
804 { "firstPlaysBlack", "firstPlaysBlack", XtRBoolean,
\r
805 sizeof(Boolean), XtOffset(AppDataPtr, firstPlaysBlack),
\r
806 XtRImmediate, (XtPointer) False },
\r
807 { "noChessProgram", "noChessProgram", XtRBoolean,
\r
808 sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
\r
809 XtRImmediate, (XtPointer) False },
\r
810 { "firstHost", "firstHost", XtRString, sizeof(String),
\r
811 XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
\r
812 { "secondHost", "secondHost", XtRString, sizeof(String),
\r
813 XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
\r
814 { "firstDirectory", "firstDirectory", XtRString, sizeof(String),
\r
815 XtOffset(AppDataPtr, firstDirectory), XtRString, "." },
\r
816 { "secondDirectory", "secondDirectory", XtRString, sizeof(String),
\r
817 XtOffset(AppDataPtr, secondDirectory), XtRString, "." },
\r
818 { "bitmapDirectory", "bitmapDirectory", XtRString,
\r
819 sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
\r
821 { "remoteShell", "remoteShell", XtRString, sizeof(String),
\r
822 XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
\r
823 { "remoteUser", "remoteUser", XtRString, sizeof(String),
\r
824 XtOffset(AppDataPtr, remoteUser), XtRString, "" },
\r
825 { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
\r
826 XtOffset(AppDataPtr, timeDelay), XtRString,
\r
827 (XtPointer) TIME_DELAY_QUOTE },
\r
828 { "timeControl", "timeControl", XtRString, sizeof(String),
\r
829 XtOffset(AppDataPtr, timeControl), XtRString,
\r
830 (XtPointer) TIME_CONTROL },
\r
831 { "internetChessServerMode", "internetChessServerMode",
\r
832 XtRBoolean, sizeof(Boolean),
\r
833 XtOffset(AppDataPtr, icsActive), XtRImmediate,
\r
834 (XtPointer) False },
\r
835 { "internetChessServerHost", "internetChessServerHost",
\r
836 XtRString, sizeof(String),
\r
837 XtOffset(AppDataPtr, icsHost),
\r
838 XtRString, (XtPointer) ICS_HOST },
\r
839 { "internetChessServerPort", "internetChessServerPort",
\r
840 XtRString, sizeof(String),
\r
841 XtOffset(AppDataPtr, icsPort), XtRString,
\r
842 (XtPointer) ICS_PORT },
\r
843 { "internetChessServerCommPort", "internetChessServerCommPort",
\r
844 XtRString, sizeof(String),
\r
845 XtOffset(AppDataPtr, icsCommPort), XtRString,
\r
847 { "internetChessServerLogonScript", "internetChessServerLogonScript",
\r
848 XtRString, sizeof(String),
\r
849 XtOffset(AppDataPtr, icsLogon), XtRString,
\r
851 { "internetChessServerHelper", "internetChessServerHelper",
\r
852 XtRString, sizeof(String),
\r
853 XtOffset(AppDataPtr, icsHelper), XtRString, "" },
\r
854 { "internetChessServerInputBox", "internetChessServerInputBox",
\r
855 XtRBoolean, sizeof(Boolean),
\r
856 XtOffset(AppDataPtr, icsInputBox), XtRImmediate,
\r
857 (XtPointer) False },
\r
858 { "icsAlarm", "icsAlarm",
\r
859 XtRBoolean, sizeof(Boolean),
\r
860 XtOffset(AppDataPtr, icsAlarm), XtRImmediate,
\r
861 (XtPointer) True },
\r
862 { "icsAlarmTime", "icsAlarmTime",
\r
863 XtRInt, sizeof(int),
\r
864 XtOffset(AppDataPtr, icsAlarmTime), XtRImmediate,
\r
865 (XtPointer) 5000 },
\r
866 { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
\r
867 XtOffset(AppDataPtr, useTelnet), XtRImmediate,
\r
868 (XtPointer) False },
\r
869 { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
\r
870 XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
\r
871 { "gateway", "gateway", XtRString, sizeof(String),
\r
872 XtOffset(AppDataPtr, gateway), XtRString, "" },
\r
873 { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
\r
874 XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
\r
875 { "loadGameIndex", "loadGameIndex",
\r
876 XtRInt, sizeof(int),
\r
877 XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
\r
879 { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
\r
880 XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
\r
881 { "autoRaiseBoard", "autoRaiseBoard", XtRBoolean,
\r
882 sizeof(Boolean), XtOffset(AppDataPtr, autoRaiseBoard),
\r
883 XtRImmediate, (XtPointer) True },
\r
884 { "autoSaveGames", "autoSaveGames", XtRBoolean,
\r
885 sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
\r
886 XtRImmediate, (XtPointer) False },
\r
887 { "blindfold", "blindfold", XtRBoolean,
\r
888 sizeof(Boolean), XtOffset(AppDataPtr, blindfold),
\r
889 XtRImmediate, (XtPointer) False },
\r
890 { "loadPositionFile", "loadPositionFile", XtRString,
\r
891 sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
\r
893 { "loadPositionIndex", "loadPositionIndex",
\r
894 XtRInt, sizeof(int),
\r
895 XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
\r
897 { "savePositionFile", "savePositionFile", XtRString,
\r
898 sizeof(String), XtOffset(AppDataPtr, savePositionFile),
\r
900 { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
\r
901 XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
\r
902 { "matchGames", "matchGames", XtRInt, sizeof(int),
\r
903 XtOffset(AppDataPtr, matchGames), XtRImmediate,
\r
905 { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
\r
906 XtOffset(AppDataPtr, monoMode), XtRImmediate,
\r
907 (XtPointer) False },
\r
908 { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
\r
909 XtOffset(AppDataPtr, debugMode), XtRImmediate,
\r
910 (XtPointer) False },
\r
911 { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
\r
912 XtOffset(AppDataPtr, clockMode), XtRImmediate,
\r
913 (XtPointer) True },
\r
914 { "boardSize", "boardSize", XtRString, sizeof(String),
\r
915 XtOffset(AppDataPtr, boardSize), XtRString, "" },
\r
916 { "searchTime", "searchTime", XtRString, sizeof(String),
\r
917 XtOffset(AppDataPtr, searchTime), XtRString,
\r
919 { "searchDepth", "searchDepth", XtRInt, sizeof(int),
\r
920 XtOffset(AppDataPtr, searchDepth), XtRImmediate,
\r
922 { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
\r
923 XtOffset(AppDataPtr, showCoords), XtRImmediate,
\r
924 (XtPointer) False },
\r
925 { "showJail", "showJail", XtRInt, sizeof(int),
\r
926 XtOffset(AppDataPtr, showJail), XtRImmediate,
\r
928 { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
\r
929 XtOffset(AppDataPtr, showThinking), XtRImmediate,
\r
930 (XtPointer) True },
\r
931 { "ponderNextMove", "ponderNextMove", XtRBoolean, sizeof(Boolean),
\r
932 XtOffset(AppDataPtr, ponderNextMove), XtRImmediate,
\r
933 (XtPointer) True },
\r
934 { "periodicUpdates", "periodicUpdates", XtRBoolean, sizeof(Boolean),
\r
935 XtOffset(AppDataPtr, periodicUpdates), XtRImmediate,
\r
936 (XtPointer) True },
\r
937 { "clockFont", "clockFont", XtRString, sizeof(String),
\r
938 XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
\r
939 { "coordFont", "coordFont", XtRString, sizeof(String),
\r
940 XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
\r
941 { "font", "font", XtRString, sizeof(String),
\r
942 XtOffset(AppDataPtr, font), XtRString, DEFAULT_FONT },
\r
943 { "ringBellAfterMoves", "ringBellAfterMoves",
\r
944 XtRBoolean, sizeof(Boolean),
\r
945 XtOffset(AppDataPtr, ringBellAfterMoves),
\r
946 XtRImmediate, (XtPointer) False },
\r
947 { "autoCallFlag", "autoCallFlag", XtRBoolean,
\r
948 sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
\r
949 XtRImmediate, (XtPointer) False },
\r
950 { "autoFlipView", "autoFlipView", XtRBoolean,
\r
951 sizeof(Boolean), XtOffset(AppDataPtr, autoFlipView),
\r
952 XtRImmediate, (XtPointer) True },
\r
953 { "autoObserve", "autoObserve", XtRBoolean,
\r
954 sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
\r
955 XtRImmediate, (XtPointer) False },
\r
956 { "autoComment", "autoComment", XtRBoolean,
\r
957 sizeof(Boolean), XtOffset(AppDataPtr, autoComment),
\r
958 XtRImmediate, (XtPointer) False },
\r
959 { "getMoveList", "getMoveList", XtRBoolean,
\r
960 sizeof(Boolean), XtOffset(AppDataPtr, getMoveList),
\r
961 XtRImmediate, (XtPointer) True },
\r
963 { "highlightDragging", "highlightDragging", XtRBoolean,
\r
964 sizeof(Boolean), XtOffset(AppDataPtr, highlightDragging),
\r
965 XtRImmediate, (XtPointer) False },
\r
967 { "highlightLastMove", "highlightLastMove", XtRBoolean,
\r
968 sizeof(Boolean), XtOffset(AppDataPtr, highlightLastMove),
\r
969 XtRImmediate, (XtPointer) False },
\r
970 { "premove", "premove", XtRBoolean,
\r
971 sizeof(Boolean), XtOffset(AppDataPtr, premove),
\r
972 XtRImmediate, (XtPointer) True },
\r
973 { "testLegality", "testLegality", XtRBoolean,
\r
974 sizeof(Boolean), XtOffset(AppDataPtr, testLegality),
\r
975 XtRImmediate, (XtPointer) True },
\r
976 { "flipView", "flipView", XtRBoolean,
\r
977 sizeof(Boolean), XtOffset(AppDataPtr, flipView),
\r
978 XtRImmediate, (XtPointer) False },
\r
979 { "cmail", "cmailGameName", XtRString, sizeof(String),
\r
980 XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
\r
981 { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
\r
982 sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
\r
983 XtRImmediate, (XtPointer) False },
\r
984 { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
\r
985 sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
\r
986 XtRImmediate, (XtPointer) False },
\r
987 { "quietPlay", "quietPlay", XtRBoolean,
\r
988 sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
\r
989 XtRImmediate, (XtPointer) False },
\r
990 { "titleInWindow", "titleInWindow", XtRBoolean,
\r
991 sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
\r
992 XtRImmediate, (XtPointer) False },
\r
993 { "localLineEditing", "localLineEditing", XtRBoolean,
\r
994 sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing),
\r
995 XtRImmediate, (XtPointer) True }, /* not implemented, must be True */
\r
997 { "zippyTalk", "zippyTalk", XtRBoolean,
\r
998 sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
\r
999 XtRImmediate, (XtPointer) ZIPPY_TALK },
\r
1000 { "zippyPlay", "zippyPlay", XtRBoolean,
\r
1001 sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
\r
1002 XtRImmediate, (XtPointer) ZIPPY_PLAY },
\r
1003 { "zippyLines", "zippyLines", XtRString, sizeof(String),
\r
1004 XtOffset(AppDataPtr, zippyLines), XtRString, ZIPPY_LINES },
\r
1005 { "zippyPinhead", "zippyPinhead", XtRString, sizeof(String),
\r
1006 XtOffset(AppDataPtr, zippyPinhead), XtRString, ZIPPY_PINHEAD },
\r
1007 { "zippyPassword", "zippyPassword", XtRString, sizeof(String),
\r
1008 XtOffset(AppDataPtr, zippyPassword), XtRString, ZIPPY_PASSWORD },
\r
1009 { "zippyPassword2", "zippyPassword2", XtRString, sizeof(String),
\r
1010 XtOffset(AppDataPtr, zippyPassword2), XtRString, ZIPPY_PASSWORD2 },
\r
1011 { "zippyWrongPassword", "zippyWrongPassword", XtRString, sizeof(String),
\r
1012 XtOffset(AppDataPtr, zippyWrongPassword), XtRString,
\r
1013 ZIPPY_WRONG_PASSWORD },
\r
1014 { "zippyAcceptOnly", "zippyAcceptOnly", XtRString, sizeof(String),
\r
1015 XtOffset(AppDataPtr, zippyAcceptOnly), XtRString, ZIPPY_ACCEPT_ONLY },
\r
1016 { "zippyUseI", "zippyUseI", XtRBoolean,
\r
1017 sizeof(Boolean), XtOffset(AppDataPtr, zippyUseI),
\r
1018 XtRImmediate, (XtPointer) ZIPPY_USE_I },
\r
1019 { "zippyBughouse", "zippyBughouse", XtRInt,
\r
1020 sizeof(int), XtOffset(AppDataPtr, zippyBughouse),
\r
1021 XtRImmediate, (XtPointer) ZIPPY_BUGHOUSE },
\r
1022 { "zippyNoplayCrafty", "zippyNoplayCrafty", XtRBoolean,
\r
1023 sizeof(Boolean), XtOffset(AppDataPtr, zippyNoplayCrafty),
\r
1024 XtRImmediate, (XtPointer) ZIPPY_NOPLAY_CRAFTY },
\r
1025 { "zippyGameEnd", "zippyGameEnd", XtRString, sizeof(String),
\r
1026 XtOffset(AppDataPtr, zippyGameEnd), XtRString, ZIPPY_GAME_END },
\r
1027 { "zippyGameStart", "zippyGameStart", XtRString, sizeof(String),
\r
1028 XtOffset(AppDataPtr, zippyGameStart), XtRString, ZIPPY_GAME_START },
\r
1029 { "zippyAdjourn", "zippyAdjourn", XtRBoolean,
\r
1030 sizeof(Boolean), XtOffset(AppDataPtr, zippyAdjourn),
\r
1031 XtRImmediate, (XtPointer) ZIPPY_ADJOURN },
\r
1032 { "zippyAbort", "zippyAbort", XtRBoolean,
\r
1033 sizeof(Boolean), XtOffset(AppDataPtr, zippyAbort),
\r
1034 XtRImmediate, (XtPointer) ZIPPY_ABORT },
\r
1035 { "zippyVariants", "zippyVariants", XtRString, sizeof(String),
\r
1036 XtOffset(AppDataPtr, zippyVariants), XtRString, ZIPPY_VARIANTS },
\r
1037 { "zippyMaxGames", "zippyMaxGames", XtRInt, sizeof(int),
\r
1038 XtOffset(AppDataPtr, zippyMaxGames), XtRImmediate,
\r
1039 (XtPointer) ZIPPY_MAX_GAMES },
\r
1040 { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
\r
1041 XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
\r
1042 (XtPointer) ZIPPY_REPLAY_TIMEOUT },
\r
1044 { "flashCount", "flashCount", XtRInt, sizeof(int),
\r
1045 XtOffset(AppDataPtr, flashCount), XtRImmediate,
\r
1046 (XtPointer) FLASH_COUNT },
\r
1047 { "flashRate", "flashRate", XtRInt, sizeof(int),
\r
1048 XtOffset(AppDataPtr, flashRate), XtRImmediate,
\r
1049 (XtPointer) FLASH_RATE },
\r
1050 { "pixmapDirectory", "pixmapDirectory", XtRString,
\r
1051 sizeof(String), XtOffset(AppDataPtr, pixmapDirectory),
\r
1053 { "msLoginDelay", "msLoginDelay", XtRInt, sizeof(int),
\r
1054 XtOffset(AppDataPtr, msLoginDelay), XtRImmediate,
\r
1055 (XtPointer) MS_LOGIN_DELAY },
\r
1056 { "colorizeMessages", "colorizeMessages", XtRBoolean,
\r
1057 sizeof(Boolean), XtOffset(AppDataPtr, colorize),
\r
1058 XtRImmediate, (XtPointer) False },
\r
1059 { "colorShout", "colorShout", XtRString,
\r
1060 sizeof(String), XtOffset(AppDataPtr, colorShout),
\r
1061 XtRString, COLOR_SHOUT },
\r
1062 { "colorSShout", "colorSShout", XtRString,
\r
1063 sizeof(String), XtOffset(AppDataPtr, colorSShout),
\r
1064 XtRString, COLOR_SSHOUT },
\r
1065 { "colorChannel1", "colorChannel1", XtRString,
\r
1066 sizeof(String), XtOffset(AppDataPtr, colorChannel1),
\r
1067 XtRString, COLOR_CHANNEL1 },
\r
1068 { "colorChannel", "colorChannel", XtRString,
\r
1069 sizeof(String), XtOffset(AppDataPtr, colorChannel),
\r
1070 XtRString, COLOR_CHANNEL },
\r
1071 { "colorKibitz", "colorKibitz", XtRString,
\r
1072 sizeof(String), XtOffset(AppDataPtr, colorKibitz),
\r
1073 XtRString, COLOR_KIBITZ },
\r
1074 { "colorTell", "colorTell", XtRString,
\r
1075 sizeof(String), XtOffset(AppDataPtr, colorTell),
\r
1076 XtRString, COLOR_TELL },
\r
1077 { "colorChallenge", "colorChallenge", XtRString,
\r
1078 sizeof(String), XtOffset(AppDataPtr, colorChallenge),
\r
1079 XtRString, COLOR_CHALLENGE },
\r
1080 { "colorRequest", "colorRequest", XtRString,
\r
1081 sizeof(String), XtOffset(AppDataPtr, colorRequest),
\r
1082 XtRString, COLOR_REQUEST },
\r
1083 { "colorSeek", "colorSeek", XtRString,
\r
1084 sizeof(String), XtOffset(AppDataPtr, colorSeek),
\r
1085 XtRString, COLOR_SEEK },
\r
1086 { "colorNormal", "colorNormal", XtRString,
\r
1087 sizeof(String), XtOffset(AppDataPtr, colorNormal),
\r
1088 XtRString, COLOR_NORMAL },
\r
1089 { "soundProgram", "soundProgram", XtRString,
\r
1090 sizeof(String), XtOffset(AppDataPtr, soundProgram),
\r
1091 XtRString, "play" },
\r
1092 { "soundShout", "soundShout", XtRString,
\r
1093 sizeof(String), XtOffset(AppDataPtr, soundShout),
\r
1095 { "soundSShout", "soundSShout", XtRString,
\r
1096 sizeof(String), XtOffset(AppDataPtr, soundSShout),
\r
1098 { "soundChannel1", "soundChannel1", XtRString,
\r
1099 sizeof(String), XtOffset(AppDataPtr, soundChannel1),
\r
1101 { "soundChannel", "soundChannel", XtRString,
\r
1102 sizeof(String), XtOffset(AppDataPtr, soundChannel),
\r
1104 { "soundKibitz", "soundKibitz", XtRString,
\r
1105 sizeof(String), XtOffset(AppDataPtr, soundKibitz),
\r
1107 { "soundTell", "soundTell", XtRString,
\r
1108 sizeof(String), XtOffset(AppDataPtr, soundTell),
\r
1110 { "soundChallenge", "soundChallenge", XtRString,
\r
1111 sizeof(String), XtOffset(AppDataPtr, soundChallenge),
\r
1113 { "soundRequest", "soundRequest", XtRString,
\r
1114 sizeof(String), XtOffset(AppDataPtr, soundRequest),
\r
1116 { "soundSeek", "soundSeek", XtRString,
\r
1117 sizeof(String), XtOffset(AppDataPtr, soundSeek),
\r
1119 { "soundMove", "soundMove", XtRString,
\r
1120 sizeof(String), XtOffset(AppDataPtr, soundMove),
\r
1122 { "soundIcsWin", "soundIcsWin", XtRString,
\r
1123 sizeof(String), XtOffset(AppDataPtr, soundIcsWin),
\r
1125 { "soundIcsLoss", "soundIcsLoss", XtRString,
\r
1126 sizeof(String), XtOffset(AppDataPtr, soundIcsLoss),
\r
1128 { "soundIcsDraw", "soundIcsDraw", XtRString,
\r
1129 sizeof(String), XtOffset(AppDataPtr, soundIcsDraw),
\r
1131 { "soundIcsUnfinished", "soundIcsUnfinished", XtRString,
\r
1132 sizeof(String), XtOffset(AppDataPtr, soundIcsUnfinished),
\r
1134 { "soundIcsAlarm", "soundIcsAlarm", XtRString,
\r
1135 sizeof(String), XtOffset(AppDataPtr, soundIcsAlarm),
\r
1137 { "reuseFirst", "reuseFirst", XtRBoolean,
\r
1138 sizeof(Boolean), XtOffset(AppDataPtr, reuseFirst),
\r
1139 XtRImmediate, (XtPointer) True },
\r
1140 { "reuseSecond", "reuseSecond", XtRBoolean,
\r
1141 sizeof(Boolean), XtOffset(AppDataPtr, reuseSecond),
\r
1142 XtRImmediate, (XtPointer) True },
\r
1143 { "animateDragging", "animateDragging", XtRBoolean,
\r
1144 sizeof(Boolean), XtOffset(AppDataPtr, animateDragging),
\r
1145 XtRImmediate, (XtPointer) True },
\r
1146 { "animateMoving", "animateMoving", XtRBoolean,
\r
1147 sizeof(Boolean), XtOffset(AppDataPtr, animate),
\r
1148 XtRImmediate, (XtPointer) True },
\r
1149 { "animateSpeed", "animateSpeed", XtRInt,
\r
1150 sizeof(int), XtOffset(AppDataPtr, animSpeed),
\r
1151 XtRImmediate, (XtPointer)10 },
\r
1152 { "popupExitMessage", "popupExitMessage", XtRBoolean,
\r
1153 sizeof(Boolean), XtOffset(AppDataPtr, popupExitMessage),
\r
1154 XtRImmediate, (XtPointer) True },
\r
1155 { "popupMoveErrors", "popupMoveErrors", XtRBoolean,
\r
1156 sizeof(Boolean), XtOffset(AppDataPtr, popupMoveErrors),
\r
1157 XtRImmediate, (XtPointer) False },
\r
1158 { "fontSizeTolerance", "fontSizeTolerance", XtRInt,
\r
1159 sizeof(int), XtOffset(AppDataPtr, fontSizeTolerance),
\r
1160 XtRImmediate, (XtPointer)4 },
\r
1161 { "initialMode", "initialMode", XtRString,
\r
1162 sizeof(String), XtOffset(AppDataPtr, initialMode),
\r
1163 XtRImmediate, (XtPointer) "" },
\r
1164 { "variant", "variant", XtRString,
\r
1165 sizeof(String), XtOffset(AppDataPtr, variant),
\r
1166 XtRImmediate, (XtPointer) "normal" },
\r
1167 { "firstProtocolVersion", "firstProtocolVersion", XtRInt,
\r
1168 sizeof(int), XtOffset(AppDataPtr, firstProtocolVersion),
\r
1169 XtRImmediate, (XtPointer)PROTOVER },
\r
1170 { "secondProtocolVersion", "secondProtocolVersion", XtRInt,
\r
1171 sizeof(int), XtOffset(AppDataPtr, secondProtocolVersion),
\r
1172 XtRImmediate, (XtPointer)PROTOVER },
\r
1173 { "showButtonBar", "showButtonBar", XtRBoolean,
\r
1174 sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
\r
1175 XtRImmediate, (XtPointer) True },
\r
1176 { "firstScoreAbs", "firstScoreAbs", XtRBoolean,
\r
1177 sizeof(Boolean), XtOffset(AppDataPtr, firstScoreIsAbsolute),
\r
1178 XtRImmediate, (XtPointer) False },
\r
1179 { "secondScoreAbs", "secondScoreAbs", XtRBoolean,
\r
1180 sizeof(Boolean), XtOffset(AppDataPtr, secondScoreIsAbsolute),
\r
1181 XtRImmediate, (XtPointer) False },
\r
1182 { "pgnExtendedInfo", "pgnExtendedInfo", XtRBoolean,
\r
1183 sizeof(Boolean), XtOffset(AppDataPtr, saveExtendedInfoInPGN),
\r
1184 XtRImmediate, (XtPointer) False },
\r
1185 { "hideThinkingFromHuman", "hideThinkingFromHuman", XtRBoolean,
\r
1186 sizeof(Boolean), XtOffset(AppDataPtr, hideThinkingFromHuman),
\r
1187 XtRImmediate, (XtPointer) True },
\r
1188 { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt,
\r
1189 sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold),
\r
1190 XtRImmediate, (XtPointer) 0},
\r
1191 { "pgnEventHeader", "pgnEventHeader", XtRString,
\r
1192 sizeof(String), XtOffset(AppDataPtr, pgnEventHeader),
\r
1193 XtRImmediate, (XtPointer) "Computer Chess Game" },
\r
1194 { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
\r
1195 sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
\r
1196 XtRImmediate, (XtPointer) -1},
\r
1198 // [HGM] 4.3.xx options
\r
1199 { "boardWidth", "boardWidth", XtRInt,
\r
1200 sizeof(int), XtOffset(AppDataPtr, NrFiles),
\r
1201 XtRImmediate, (XtPointer) -1},
\r
1202 { "boardHeight", "boardHeight", XtRInt,
\r
1203 sizeof(int), XtOffset(AppDataPtr, NrRanks),
\r
1204 XtRImmediate, (XtPointer) -1},
\r
1205 { "matchPause", "matchPause", XtRInt,
\r
1206 sizeof(int), XtOffset(AppDataPtr, matchPause),
\r
1207 XtRImmediate, (XtPointer) 10000},
\r
1208 { "holdingsSize", "holdingsSize", XtRInt,
\r
1209 sizeof(int), XtOffset(AppDataPtr, holdingsSize),
\r
1210 XtRImmediate, (XtPointer) -1},
\r
1211 { "flipBlack", "flipBlack", XtRBoolean,
\r
1212 sizeof(Boolean), XtOffset(AppDataPtr, upsideDown),
\r
1213 XtRImmediate, (XtPointer) False},
\r
1214 { "allWhite", "allWhite", XtRBoolean,
\r
1215 sizeof(Boolean), XtOffset(AppDataPtr, allWhite),
\r
1216 XtRImmediate, (XtPointer) False},
\r
1217 { "pieceToCharTable", "pieceToCharTable", XtRString,
\r
1218 sizeof(String), XtOffset(AppDataPtr, pieceToCharTable),
\r
1219 XtRImmediate, (XtPointer) 0},
\r
1220 { "alphaRank", "alphaRank", XtRBoolean,
\r
1221 sizeof(Boolean), XtOffset(AppDataPtr, alphaRank),
\r
1222 XtRImmediate, (XtPointer) False},
\r
1223 { "testClaims", "testClaims", XtRBoolean,
\r
1224 sizeof(Boolean), XtOffset(AppDataPtr, testClaims),
\r
1225 XtRImmediate, (XtPointer) True},
\r
1226 { "checkMates", "checkMates", XtRBoolean,
\r
1227 sizeof(Boolean), XtOffset(AppDataPtr, checkMates),
\r
1228 XtRImmediate, (XtPointer) True},
\r
1229 { "materialDraws", "materialDraws", XtRBoolean,
\r
1230 sizeof(Boolean), XtOffset(AppDataPtr, materialDraws),
\r
1231 XtRImmediate, (XtPointer) True},
\r
1232 { "trivialDraws", "trivialDraws", XtRBoolean,
\r
1233 sizeof(Boolean), XtOffset(AppDataPtr, trivialDraws),
\r
1234 XtRImmediate, (XtPointer) False},
\r
1235 { "ruleMoves", "ruleMoves", XtRInt,
\r
1236 sizeof(int), XtOffset(AppDataPtr, ruleMoves),
\r
1237 XtRImmediate, (XtPointer) 51},
\r
1238 { "repeatsToDraw", "repeatsToDraw", XtRInt,
\r
1239 sizeof(int), XtOffset(AppDataPtr, drawRepeats),
\r
1240 XtRImmediate, (XtPointer) 6},
\r
1241 { "engineDebugOutput", "engineDebugOutput", XtRInt,
\r
1242 sizeof(int), XtOffset(AppDataPtr, engineComments),
\r
1243 XtRImmediate, (XtPointer) 1},
\r
1244 { "userName", "userName", XtRString,
\r
1245 sizeof(int), XtOffset(AppDataPtr, userName),
\r
1246 XtRImmediate, (XtPointer) 0},
\r
1247 { "autoKibitz", "autoKibitz", XtRBoolean,
\r
1248 sizeof(Boolean), XtOffset(AppDataPtr, autoKibitz),
\r
1249 XtRImmediate, (XtPointer) False},
\r
1250 { "firstTimeOdds", "firstTimeOdds", XtRInt,
\r
1251 sizeof(int), XtOffset(AppDataPtr, firstTimeOdds),
\r
1252 XtRImmediate, (XtPointer) 1},
\r
1253 { "secondTimeOdds", "secondTimeOdds", XtRInt,
\r
1254 sizeof(int), XtOffset(AppDataPtr, secondTimeOdds),
\r
1255 XtRImmediate, (XtPointer) 1},
\r
1256 { "timeOddsMode", "timeOddsMode", XtRInt,
\r
1257 sizeof(int), XtOffset(AppDataPtr, timeOddsMode),
\r
1258 XtRImmediate, (XtPointer) 0},
\r
1259 { "firstAccumulateTC", "firstAccumulateTC", XtRInt,
\r
1260 sizeof(int), XtOffset(AppDataPtr, firstAccumulateTC),
\r
1261 XtRImmediate, (XtPointer) 1},
\r
1262 { "secondAccumulateTC", "secondAccumulateTC", XtRInt,
\r
1263 sizeof(int), XtOffset(AppDataPtr, secondAccumulateTC),
\r
1264 XtRImmediate, (XtPointer) 1},
\r
1265 { "firstNPS", "firstNPS", XtRInt,
\r
1266 sizeof(int), XtOffset(AppDataPtr, firstNPS),
\r
1267 XtRImmediate, (XtPointer) -1},
\r
1268 { "secondNPS", "secondNPS", XtRInt,
\r
1269 sizeof(int), XtOffset(AppDataPtr, secondNPS),
\r
1270 XtRImmediate, (XtPointer) -1},
\r
1271 { "serverMoves", "serverMoves", XtRString,
\r
1272 sizeof(String), XtOffset(AppDataPtr, serverMovesName),
\r
1273 XtRImmediate, (XtPointer) 0},
\r
1274 { "serverPause", "serverPause", XtRInt,
\r
1275 sizeof(int), XtOffset(AppDataPtr, serverPause),
\r
1276 XtRImmediate, (XtPointer) 0},
\r
1277 { "suppressLoadMoves", "suppressLoadMoves", XtRBoolean,
\r
1278 sizeof(Boolean), XtOffset(AppDataPtr, suppressLoadMoves),
\r
1279 XtRImmediate, (XtPointer) False},
1280 { "userName", "userName", XtRString,
\r
1281 sizeof(String), XtOffset(AppDataPtr, userName),
\r
1282 XtRImmediate, (XtPointer) 0},
\r
1283 { "egtFormats", "egtFormats", XtRString,
\r
1284 sizeof(String), XtOffset(AppDataPtr, egtFormats),
\r
1285 XtRImmediate, (XtPointer) 0},
\r
1286 { "rewindIndex", "rewindIndex", XtRInt,
\r
1287 sizeof(int), XtOffset(AppDataPtr, rewindIndex),
\r
1288 XtRImmediate, (XtPointer) 0},
\r
1289 { "sameColorGames", "sameColorGames", XtRInt,
\r
1290 sizeof(int), XtOffset(AppDataPtr, sameColorGames),
\r
1291 XtRImmediate, (XtPointer) 0},
\r
1292 { "smpCores", "smpCores", XtRInt,
\r
1293 sizeof(int), XtOffset(AppDataPtr, smpCores),
\r
1294 XtRImmediate, (XtPointer) 1},
\r
1295 { "niceEngines", "niceEngines", XtRInt,
\r
1296 sizeof(int), XtOffset(AppDataPtr, niceEngines),
\r
1297 XtRImmediate, (XtPointer) 0},
\r
1299 // [HGM] Winboard_x UCI options
\r
1300 { "firstIsUCI", "firstIsUCI", XtRBoolean,
\r
1301 sizeof(Boolean), XtOffset(AppDataPtr, firstIsUCI),
\r
1302 XtRImmediate, (XtPointer) False},
\r
1303 { "secondIsUCI", "secondIsUCI", XtRBoolean,
\r
1304 sizeof(Boolean), XtOffset(AppDataPtr, secondIsUCI),
\r
1305 XtRImmediate, (XtPointer) False},
\r
1306 { "firstHasOwnBookUCI", "firstHasOwnBookUCI", XtRBoolean,
\r
1307 sizeof(Boolean), XtOffset(AppDataPtr, firstHasOwnBookUCI),
\r
1308 XtRImmediate, (XtPointer) True},
\r
1309 { "secondHasOwnBookUCI", "secondHasOwnBookUCI", XtRBoolean,
\r
1310 sizeof(Boolean), XtOffset(AppDataPtr, secondHasOwnBookUCI),
\r
1311 XtRImmediate, (XtPointer) True},
\r
1312 { "usePolyglotBook", "usePolyglotBook", XtRBoolean,
\r
1313 sizeof(Boolean), XtOffset(AppDataPtr, usePolyglotBook),
\r
1314 XtRImmediate, (XtPointer) False},
\r
1315 { "defaultHashSize", "defaultHashSize", XtRInt,
\r
1316 sizeof(int), XtOffset(AppDataPtr, defaultHashSize),
\r
1317 XtRImmediate, (XtPointer) 64},
\r
1318 { "defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XtRInt,
\r
1319 sizeof(int), XtOffset(AppDataPtr, defaultCacheSizeEGTB),
\r
1320 XtRImmediate, (XtPointer) 4},
\r
1321 { "polyglotDir", "polyglotDir", XtRString,
\r
1322 sizeof(String), XtOffset(AppDataPtr, polyglotDir),
\r
1323 XtRImmediate, (XtPointer) "." },
\r
1324 { "polyglotBook", "polyglotBook", XtRString,
\r
1325 sizeof(String), XtOffset(AppDataPtr, polyglotBook),
\r
1326 XtRImmediate, (XtPointer) "" },
\r
1327 { "defaultPathEGTB", "defaultPathEGTB", XtRString,
\r
1328 sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),
\r
1329 XtRImmediate, (XtPointer) "/usr/local/share/egtb"},
\r
1330 { "delayBeforeQuit", "delayBeforeQuit", XtRInt,
\r
1331 sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),
\r
1332 XtRImmediate, (XtPointer) 0},
\r
1333 { "delayAfterQuit", "delayAfterQuit", XtRInt,
\r
1334 sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),
\r
1335 XtRImmediate, (XtPointer) 0},
\r
1338 XrmOptionDescRec shellOptions[] = {
\r
1339 { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
\r
1340 { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
\r
1341 { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
\r
1342 { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
\r
1343 { "-highlightSquareColor", "highlightSquareColor", XrmoptionSepArg, NULL },
\r
1344 { "-premoveHighlightColor", "premoveHighlightColor", XrmoptionSepArg,NULL},
\r
1345 { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
\r
1346 { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
\r
1347 { "-timeIncrement", "timeIncrement", XrmoptionSepArg, NULL },
\r
1348 { "-inc", "timeIncrement", XrmoptionSepArg, NULL },
\r
1349 { "-initString", "initString", XrmoptionSepArg, NULL },
\r
1350 { "-firstInitString", "initString", XrmoptionSepArg, NULL },
\r
1351 { "-secondInitString", "secondInitString", XrmoptionSepArg, NULL },
\r
1352 { "-firstComputerString", "firstComputerString", XrmoptionSepArg, NULL },
\r
1353 { "-secondComputerString", "secondComputerString", XrmoptionSepArg, NULL },
\r
1354 { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
\r
1355 { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
\r
1356 { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
\r
1357 { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
\r
1358 { "-firstPlaysBlack", "firstPlaysBlack", XrmoptionSepArg, NULL },
\r
1359 { "-fb", "firstPlaysBlack", XrmoptionNoArg, "True" },
\r
1360 { "-xfb", "firstPlaysBlack", XrmoptionNoArg, "False" },
\r
1361 { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
\r
1362 { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
\r
1363 { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
\r
1364 { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
\r
1365 { "-fh", "firstHost", XrmoptionSepArg, NULL },
\r
1366 { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
\r
1367 { "-sh", "secondHost", XrmoptionSepArg, NULL },
\r
1368 { "-firstDirectory", "firstDirectory", XrmoptionSepArg, NULL },
\r
1369 { "-fd", "firstDirectory", XrmoptionSepArg, NULL },
\r
1370 { "-secondDirectory", "secondDirectory", XrmoptionSepArg, NULL },
\r
1371 { "-sd", "secondDirectory", XrmoptionSepArg, NULL },
\r
1372 { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
\r
1373 { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
\r
1374 { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
\r
1375 { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
\r
1376 { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
\r
1377 { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
\r
1378 { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
\r
1379 { "-td", "timeDelay", XrmoptionSepArg, NULL },
\r
1380 { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
\r
1381 { "-tc", "timeControl", XrmoptionSepArg, NULL },
\r
1382 { "-internetChessServerMode", "internetChessServerMode",
\r
1383 XrmoptionSepArg, NULL },
\r
1384 { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
\r
1385 { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
\r
1386 { "-internetChessServerHost", "internetChessServerHost",
\r
1387 XrmoptionSepArg, NULL },
\r
1388 { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
\r
1389 { "-internetChessServerPort", "internetChessServerPort",
\r
1390 XrmoptionSepArg, NULL },
\r
1391 { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
\r
1392 { "-internetChessServerCommPort", "internetChessServerCommPort",
\r
1393 XrmoptionSepArg, NULL },
\r
1394 { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
\r
1395 { "-internetChessServerLogonScript", "internetChessServerLogonScript",
\r
1396 XrmoptionSepArg, NULL },
\r
1397 { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
\r
1398 { "-internetChessServerHelper", "internetChessServerHelper",
\r
1399 XrmoptionSepArg, NULL },
\r
1400 { "-icshelper", "internetChessServerHelper", XrmoptionSepArg, NULL },
\r
1401 { "-internetChessServerInputBox", "internetChessServerInputBox",
\r
1402 XrmoptionSepArg, NULL },
\r
1403 { "-icsinput", "internetChessServerInputBox", XrmoptionNoArg, "True" },
\r
1404 { "-xicsinput", "internetChessServerInputBox", XrmoptionNoArg, "False" },
\r
1405 { "-icsAlarm", "icsAlarm", XrmoptionSepArg, NULL },
\r
1406 { "-alarm", "icsAlarm", XrmoptionNoArg, "True" },
\r
1407 { "-xalarm", "icsAlarm", XrmoptionNoArg, "False" },
\r
1408 { "-icsAlarmTime", "icsAlarmTime", XrmoptionSepArg, NULL },
\r
1409 { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
\r
1410 { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
\r
1411 { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
\r
1412 { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
\r
1413 { "-gateway", "gateway", XrmoptionSepArg, NULL },
\r
1414 { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
\r
1415 { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
\r
1416 { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
\r
1417 { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
\r
1418 { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
\r
1419 { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
\r
1420 { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
\r
1421 { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
\r
1422 { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
\r
1423 { "-autoRaiseBoard", "autoRaiseBoard", XrmoptionSepArg, NULL },
\r
1424 { "-autoraise", "autoRaiseBoard", XrmoptionNoArg, "True" },
\r
1425 { "-xautoraise", "autoRaiseBoard", XrmoptionNoArg, "False" },
\r
1426 { "-blindfold", "blindfold", XrmoptionSepArg, NULL },
\r
1427 { "-blind", "blindfold", XrmoptionNoArg, "True" },
\r
1428 { "-xblind", "blindfold", XrmoptionNoArg, "False" },
\r
1429 { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
\r
1430 { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
\r
1431 { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
\r
1432 { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
\r
1433 { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
\r
1434 { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
\r
1435 { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
\r
1436 { "-mm", "matchMode", XrmoptionNoArg, "True" },
\r
1437 { "-xmm", "matchMode", XrmoptionNoArg, "False" },
\r
1438 { "-matchGames", "matchGames", XrmoptionSepArg, NULL },
\r
1439 { "-mg", "matchGames", XrmoptionSepArg, NULL },
\r
1440 { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
\r
1441 { "-mono", "monoMode", XrmoptionNoArg, "True" },
\r
1442 { "-xmono", "monoMode", XrmoptionNoArg, "False" },
\r
1443 { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
\r
1444 { "-debug", "debugMode", XrmoptionNoArg, "True" },
\r
1445 { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
\r
1446 { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
\r
1447 { "-clock", "clockMode", XrmoptionNoArg, "True" },
\r
1448 { "-xclock", "clockMode", XrmoptionNoArg, "False" },
\r
1449 { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
\r
1450 { "-size", "boardSize", XrmoptionSepArg, NULL },
\r
1451 { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
\r
1452 { "-st", "searchTime", XrmoptionSepArg, NULL },
\r
1453 { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
\r
1454 { "-depth", "searchDepth", XrmoptionSepArg, NULL },
\r
1455 { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
\r
1456 { "-coords", "showCoords", XrmoptionNoArg, "True" },
\r
1457 { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
\r
1459 { "-showJail", "showJail", XrmoptionSepArg, NULL },
\r
1460 { "-jail", "showJail", XrmoptionNoArg, "1" },
\r
1461 { "-sidejail", "showJail", XrmoptionNoArg, "2" },
\r
1462 { "-xjail", "showJail", XrmoptionNoArg, "0" },
\r
1464 { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
\r
1465 { "-thinking", "showThinking", XrmoptionNoArg, "True" },
\r
1466 { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
\r
1467 { "-ponderNextMove", "ponderNextMove", XrmoptionSepArg, NULL },
\r
1468 { "-ponder", "ponderNextMove", XrmoptionNoArg, "True" },
\r
1469 { "-xponder", "ponderNextMove", XrmoptionNoArg, "False" },
\r
1470 { "-periodicUpdates", "periodicUpdates", XrmoptionSepArg, NULL },
\r
1471 { "-periodic", "periodicUpdates", XrmoptionNoArg, "True" },
\r
1472 { "-xperiodic", "periodicUpdates", XrmoptionNoArg, "False" },
\r
1473 { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
\r
1474 { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
\r
1475 { "-font", "font", XrmoptionSepArg, NULL },
\r
1476 { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
\r
1477 { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
\r
1478 { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
\r
1479 { "-movesound", "ringBellAfterMoves", XrmoptionNoArg, "True" },
\r
1480 { "-xmovesound", "ringBellAfterMoves", XrmoptionNoArg, "False" },
\r
1481 { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
\r
1482 { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
\r
1483 { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
\r
1484 { "-autoFlipView", "autoFlipView", XrmoptionSepArg, NULL },
\r
1485 { "-autoflip", "autoFlipView", XrmoptionNoArg, "True" },
\r
1486 { "-xautoflip", "autoFlipView", XrmoptionNoArg, "False" },
\r
1487 { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
\r
1488 { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
\r
1489 { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
\r
1490 { "-autoComment", "autoComment", XrmoptionSepArg, NULL },
\r
1491 { "-autocomm", "autoComment", XrmoptionNoArg, "True" },
\r
1492 { "-xautocomm", "autoComment", XrmoptionNoArg, "False" },
\r
1493 { "-getMoveList", "getMoveList", XrmoptionSepArg, NULL },
\r
1494 { "-moves", "getMoveList", XrmoptionNoArg, "True" },
\r
1495 { "-xmoves", "getMoveList", XrmoptionNoArg, "False" },
\r
1497 { "-highlightDragging", "highlightDragging", XrmoptionSepArg, NULL },
\r
1498 { "-highdrag", "highlightDragging", XrmoptionNoArg, "True" },
\r
1499 { "-xhighdrag", "highlightDragging", XrmoptionNoArg, "False" },
\r
1501 { "-highlightLastMove", "highlightLastMove", XrmoptionSepArg, NULL },
\r
1502 { "-highlight", "highlightLastMove", XrmoptionNoArg, "True" },
\r
1503 { "-xhighlight", "highlightLastMove", XrmoptionNoArg, "False" },
\r
1504 { "-premove", "premove", XrmoptionSepArg, NULL },
\r
1505 { "-pre", "premove", XrmoptionNoArg, "True" },
\r
1506 { "-xpre", "premove", XrmoptionNoArg, "False" },
\r
1507 { "-testLegality", "testLegality", XrmoptionSepArg, NULL },
\r
1508 { "-legal", "testLegality", XrmoptionNoArg, "True" },
\r
1509 { "-xlegal", "testLegality", XrmoptionNoArg, "False" },
\r
1510 { "-flipView", "flipView", XrmoptionSepArg, NULL },
\r
1511 { "-flip", "flipView", XrmoptionNoArg, "True" },
\r
1512 { "-xflip", "flipView", XrmoptionNoArg, "False" },
\r
1513 { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
\r
1514 { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
\r
1515 XrmoptionSepArg, NULL },
\r
1516 { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
\r
1517 { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
\r
1518 { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
\r
1519 { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
\r
1520 { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
\r
1521 { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
\r
1522 { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
\r
1523 { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
\r
1524 { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
\r
1525 { "-title", "titleInWindow", XrmoptionNoArg, "True" },
\r
1526 { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
\r
1528 { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
\r
1529 { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
\r
1530 { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
\r
1531 { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
\r
1532 { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
\r
1533 { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
\r
1534 { "-zippyLines", "zippyLines", XrmoptionSepArg, NULL },
\r
1535 { "-zippyPinhead", "zippyPinhead", XrmoptionSepArg, NULL },
\r
1536 { "-zippyPassword", "zippyPassword", XrmoptionSepArg, NULL },
\r
1537 { "-zippyPassword2", "zippyPassword2", XrmoptionSepArg, NULL },
\r
1538 { "-zippyWrongPassword", "zippyWrongPassword", XrmoptionSepArg, NULL },
\r
1539 { "-zippyAcceptOnly", "zippyAcceptOnly", XrmoptionSepArg, NULL },
\r
1540 { "-zippyUseI", "zippyUseI", XrmoptionSepArg, NULL },
\r
1541 { "-zui", "zippyUseI", XrmoptionNoArg, "True" },
\r
1542 { "-xzui", "zippyUseI", XrmoptionNoArg, "False" },
\r
1543 { "-zippyBughouse", "zippyBughouse", XrmoptionSepArg, NULL },
\r
1544 { "-zippyNoplayCrafty", "zippyNoplayCrafty", XrmoptionSepArg, NULL },
\r
1545 { "-znc", "zippyNoplayCrafty", XrmoptionNoArg, "True" },
\r
1546 { "-xznc", "zippyNoplayCrafty", XrmoptionNoArg, "False" },
\r
1547 { "-zippyGameEnd", "zippyGameEnd", XrmoptionSepArg, NULL },
\r
1548 { "-zippyGameStart", "zippyGameStart", XrmoptionSepArg, NULL },
\r
1549 { "-zippyAdjourn", "zippyAdjourn", XrmoptionSepArg, NULL },
\r
1550 { "-zadj", "zippyAdjourn", XrmoptionNoArg, "True" },
\r
1551 { "-xzadj", "zippyAdjourn", XrmoptionNoArg, "False" },
\r
1552 { "-zippyAbort", "zippyAbort", XrmoptionSepArg, NULL },
\r
1553 { "-zab", "zippyAbort", XrmoptionNoArg, "True" },
\r
1554 { "-xzab", "zippyAbort", XrmoptionNoArg, "False" },
\r
1555 { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
\r
1556 { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
\r
1557 { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
\r
1559 { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
\r
1560 { "-flash", "flashCount", XrmoptionNoArg, "3" },
\r
1561 { "-xflash", "flashCount", XrmoptionNoArg, "0" },
\r
1562 { "-flashRate", "flashRate", XrmoptionSepArg, NULL },
\r
1563 { "-pixmapDirectory", "pixmapDirectory", XrmoptionSepArg, NULL },
\r
1564 { "-msLoginDelay", "msLoginDelay", XrmoptionSepArg, NULL },
\r
1565 { "-pixmap", "pixmapDirectory", XrmoptionSepArg, NULL },
\r
1566 { "-colorizeMessages", "colorizeMessages", XrmoptionSepArg, NULL },
\r
1567 { "-colorize", "colorizeMessages", XrmoptionNoArg, "True" },
\r
1568 { "-xcolorize", "colorizeMessages", XrmoptionNoArg, "False" },
\r
1569 { "-colorShout", "colorShout", XrmoptionSepArg, NULL },
\r
1570 { "-colorSShout", "colorSShout", XrmoptionSepArg, NULL },
\r
1571 { "-colorCShout", "colorSShout", XrmoptionSepArg, NULL }, /*FICS name*/
\r
1572 { "-colorChannel1", "colorChannel1", XrmoptionSepArg, NULL },
\r
1573 { "-colorChannel", "colorChannel", XrmoptionSepArg, NULL },
\r
1574 { "-colorKibitz", "colorKibitz", XrmoptionSepArg, NULL },
\r
1575 { "-colorTell", "colorTell", XrmoptionSepArg, NULL },
\r
1576 { "-colorChallenge", "colorChallenge", XrmoptionSepArg, NULL },
\r
1577 { "-colorRequest", "colorRequest", XrmoptionSepArg, NULL },
\r
1578 { "-colorSeek", "colorSeek", XrmoptionSepArg, NULL },
\r
1579 { "-colorNormal", "colorNormal", XrmoptionSepArg, NULL },
\r
1580 { "-soundProgram", "soundProgram", XrmoptionSepArg, NULL },
\r
1581 { "-soundShout", "soundShout", XrmoptionSepArg, NULL },
\r
1582 { "-soundSShout", "soundSShout", XrmoptionSepArg, NULL },
\r
1583 { "-soundCShout", "soundSShout", XrmoptionSepArg, NULL }, /*FICS name*/
\r
1584 { "-soundChannel1", "soundChannel1", XrmoptionSepArg, NULL },
\r
1585 { "-soundChannel", "soundChannel", XrmoptionSepArg, NULL },
\r
1586 { "-soundKibitz", "soundKibitz", XrmoptionSepArg, NULL },
\r
1587 { "-soundTell", "soundTell", XrmoptionSepArg, NULL },
\r
1588 { "-soundChallenge", "soundChallenge", XrmoptionSepArg, NULL },
\r
1589 { "-soundRequest", "soundRequest", XrmoptionSepArg, NULL },
\r
1590 { "-soundSeek", "soundSeek", XrmoptionSepArg, NULL },
\r
1591 { "-soundMove", "soundMove", XrmoptionSepArg, NULL },
\r
1592 { "-soundIcsWin", "soundIcsWin", XrmoptionSepArg, NULL },
\r
1593 { "-soundIcsLoss", "soundIcsLoss", XrmoptionSepArg, NULL },
\r
1594 { "-soundIcsDraw", "soundIcsDraw", XrmoptionSepArg, NULL },
\r
1595 { "-soundIcsUnfinished", "soundIcsUnfinished", XrmoptionSepArg, NULL },
\r
1596 { "-soundIcsAlarm", "soundIcsAlarm", XrmoptionSepArg, NULL },
\r
1597 { "-reuseFirst", "reuseFirst", XrmoptionSepArg, NULL },
\r
1598 { "-reuseChessPrograms", "reuseFirst", XrmoptionSepArg, NULL }, /*compat*/
\r
1599 { "-reuse", "reuseFirst", XrmoptionNoArg, "True" },
\r
1600 { "-xreuse", "reuseFirst", XrmoptionNoArg, "False" },
\r
1601 { "-reuseSecond", "reuseSecond", XrmoptionSepArg, NULL },
\r
1602 { "-reuse2", "reuseSecond", XrmoptionNoArg, "True" },
\r
1603 { "-xreuse2", "reuseSecond", XrmoptionNoArg, "False" },
\r
1604 { "-animateMoving", "animateMoving", XrmoptionSepArg, NULL },
\r
1605 { "-animate", "animateMoving", XrmoptionNoArg, "True" },
\r
1606 { "-xanimate", "animateMoving", XrmoptionNoArg, "False" },
\r
1607 { "-animateDragging", "animateDragging", XrmoptionSepArg, NULL },
\r
1608 { "-drag", "animateDragging", XrmoptionNoArg, "True" },
\r
1609 { "-xdrag", "animateDragging", XrmoptionNoArg, "False" },
\r
1610 { "-animateSpeed", "animateSpeed", XrmoptionSepArg, NULL },
\r
1611 { "-popupExitMessage", "popupExitMessage", XrmoptionSepArg, NULL },
\r
1612 { "-exit", "popupExitMessage", XrmoptionNoArg, "True" },
\r
1613 { "-xexit", "popupExitMessage", XrmoptionNoArg, "False" },
\r
1614 { "-popupMoveErrors", "popupMoveErrors", XrmoptionSepArg, NULL },
\r
1615 { "-popup", "popupMoveErrors", XrmoptionNoArg, "True" },
\r
1616 { "-xpopup", "popupMoveErrors", XrmoptionNoArg, "False" },
\r
1617 { "-fontSizeTolerance", "fontSizeTolerance", XrmoptionSepArg, NULL },
\r
1618 { "-initialMode", "initialMode", XrmoptionSepArg, NULL },
\r
1619 { "-mode", "initialMode", XrmoptionSepArg, NULL },
\r
1620 { "-variant", "variant", XrmoptionSepArg, NULL },
\r
1621 { "-firstProtocolVersion", "firstProtocolVersion", XrmoptionSepArg, NULL },
\r
1622 { "-secondProtocolVersion","secondProtocolVersion",XrmoptionSepArg, NULL },
\r
1623 { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
\r
1624 { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
\r
1625 { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
\r
1626 /* [AS,HR] New features */
\r
1627 { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
\r
1628 { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
\r
1629 { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL },
\r
1630 { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL },
\r
1631 { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL },
\r
1632 { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL },
\r
1633 { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL },
\r
1634 { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL },
\r
1635 { "-fUCI", "firstIsUCI", XrmoptionNoArg, "True" },
\r
1636 { "-sUCI", "secondIsUCI", XrmoptionNoArg, "True" },
\r
1637 { "-firstHasOwnBookUCI", "firstHasOwnBookUCI", XrmoptionSepArg, NULL },
\r
1638 { "-secondHasOwnBookUCI", "secondHasOwnBookUCI", XrmoptionSepArg, NULL },
\r
1639 { "-fNoOwnBookUCI", "firstHasOwnBookUCI", XrmoptionNoArg, "False" },
\r
1640 { "-sNoOwnBookUCI", "secondHasOwnBookUCI", XrmoptionNoArg, "False" },
\r
1641 { "-polyglotDir", "polyglotDir", XrmoptionSepArg, NULL },
\r
1642 { "-usePolyglotBook", "usePolyglotBook", XrmoptionSepArg, NULL },
\r
1643 { "-polyglotBook", "polyglotBook", XrmoptionSepArg, NULL },
\r
1644 { "-defaultHashSize", "defaultHashSize", XrmoptionSepArg, NULL },
\r
1645 { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
\r
1646 { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
\r
1647 { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
\r
1648 // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
\r
1650 /* [HGM,HR] User-selectable board size */
\r
1651 { "-boardWidth", "boardWidth", XrmoptionSepArg, NULL },
\r
1652 { "-boardHeight", "boardHeight", XrmoptionSepArg, NULL },
\r
1653 { "-matchPause", "matchPause", XrmoptionSepArg, NULL },
\r
1655 /* [HGM] new arguments of 4.3.xx. All except first three are back-end options, which should work immediately */
\r
1656 { "-holdingsSize", "holdingsSize", XrmoptionSepArg, NULL }, // requires extensive front-end changes to work
\r
1657 { "-flipBlack", "flipBlack", XrmoptionSepArg, NULL }, // requires front-end changes to work
\r
1658 { "-allWhite", "allWhite", XrmoptionSepArg, NULL }, // requires front-end changes to work
\r
1659 { "-pieceToCharTable", "pieceToCharTable", XrmoptionSepArg, NULL },
\r
1660 { "-alphaRank", "alphaRank", XrmoptionSepArg, NULL },
\r
1661 { "-testClaims", "testClaims", XrmoptionSepArg, NULL },
\r
1662 { "-checkMates", "checkMates", XrmoptionSepArg, NULL },
\r
1663 { "-materialDraws", "materialDraws", XrmoptionSepArg, NULL },
\r
1664 { "-trivialDraws", "trivialDraws", XrmoptionSepArg, NULL },
\r
1665 { "-ruleMoves", "ruleMoves", XrmoptionSepArg, NULL },
\r
1666 { "-repeatsToDraw", "repeatsToDraw", XrmoptionSepArg, NULL },
\r
1667 { "-engineDebugOutput", "engineDebugOutput", XrmoptionSepArg, NULL },
\r
1668 { "-userName", "userName", XrmoptionSepArg, NULL },
\r
1669 { "-autoKibitz", "autoKibitz", XrmoptionNoArg, "True" },
\r
1670 { "-firstTimeOdds", "firstTimeOdds", XrmoptionSepArg, NULL },
\r
1671 { "-secondTimeOdds", "secondTimeOdds", XrmoptionSepArg, NULL },
\r
1672 { "-timeOddsMode", "timeOddsMode", XrmoptionSepArg, NULL },
\r
1673 { "-firstAccumulateTC", "firstAccumulateTC", XrmoptionSepArg, NULL },
\r
1674 { "-secondAccumulateTC", "secondAccumulateTC", XrmoptionSepArg, NULL },
\r
1675 { "-firstNPS", "firstNPS", XrmoptionSepArg, NULL },
\r
1676 { "-secondNPS", "secondNPS", XrmoptionSepArg, NULL },
\r
1677 { "-serverMoves", "serverMoves", XrmoptionSepArg, NULL },
\r
1678 { "-serverPause", "serverPause", XrmoptionSepArg, NULL },
\r
1679 { "-suppressLoadMoves", "suppressLoadMoves", XrmoptionSepArg, NULL },
\r
1680 { "-egtFormats", "egtFormats", XrmoptionSepArg, NULL },
\r
1681 { "-userName", "userName", XrmoptionSepArg, NULL },
\r
1682 { "-smpCores", "smpCores", XrmoptionSepArg, NULL },
\r
1683 { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL },
\r
1684 { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL },
\r
1685 { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL },
\r
1686 { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL },
\r
1687 { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL },
\r
1691 XtActionsRec boardActions[] = {
\r
1692 { "DrawPosition", DrawPositionProc },
\r
1693 { "HandleUserMove", HandleUserMove },
\r
1694 { "AnimateUserMove", AnimateUserMove },
\r
1695 { "FileNameAction", FileNameAction },
\r
1696 { "AskQuestionProc", AskQuestionProc },
\r
1697 { "AskQuestionReplyAction", AskQuestionReplyAction },
\r
1698 { "PieceMenuPopup", PieceMenuPopup },
\r
1699 { "WhiteClock", WhiteClock },
\r
1700 { "BlackClock", BlackClock },
\r
1701 { "Iconify", Iconify },
\r
1702 { "ResetProc", ResetProc },
\r
1703 { "LoadGameProc", LoadGameProc },
\r
1704 { "LoadNextGameProc", LoadNextGameProc },
\r
1705 { "LoadPrevGameProc", LoadPrevGameProc },
\r
1706 { "LoadSelectedProc", LoadSelectedProc },
\r
1707 { "ReloadGameProc", ReloadGameProc },
\r
1708 { "LoadPositionProc", LoadPositionProc },
\r
1709 { "LoadNextPositionProc", LoadNextPositionProc },
\r
1710 { "LoadPrevPositionProc", LoadPrevPositionProc },
\r
1711 { "ReloadPositionProc", ReloadPositionProc },
\r
1712 { "CopyPositionProc", CopyPositionProc },
\r
1713 { "PastePositionProc", PastePositionProc },
\r
1714 { "CopyGameProc", CopyGameProc },
\r
1715 { "PasteGameProc", PasteGameProc },
\r
1716 { "SaveGameProc", SaveGameProc },
\r
1717 { "SavePositionProc", SavePositionProc },
\r
1718 { "MailMoveProc", MailMoveProc },
\r
1719 { "ReloadCmailMsgProc", ReloadCmailMsgProc },
\r
1720 { "QuitProc", QuitProc },
\r
1721 { "MachineWhiteProc", MachineWhiteProc },
\r
1722 { "MachineBlackProc", MachineBlackProc },
\r
1723 { "AnalysisModeProc", AnalyzeModeProc },
\r
1724 { "AnalyzeFileProc", AnalyzeFileProc },
\r
1725 { "TwoMachinesProc", TwoMachinesProc },
\r
1726 { "IcsClientProc", IcsClientProc },
\r
1727 { "EditGameProc", EditGameProc },
\r
1728 { "EditPositionProc", EditPositionProc },
\r
1729 { "TrainingProc", EditPositionProc },
\r
1730 { "EngineOutputProc", EngineOutputProc}, // [HGM] Winboard_x engine-output window
\r
1731 { "ShowGameListProc", ShowGameListProc },
\r
1732 { "ShowMoveListProc", HistoryShowProc},
\r
1733 { "EditTagsProc", EditCommentProc },
\r
1734 { "EditCommentProc", EditCommentProc },
\r
1735 { "IcsAlarmProc", IcsAlarmProc },
\r
1736 { "IcsInputBoxProc", IcsInputBoxProc },
\r
1737 { "PauseProc", PauseProc },
\r
1738 { "AcceptProc", AcceptProc },
\r
1739 { "DeclineProc", DeclineProc },
\r
1740 { "RematchProc", RematchProc },
\r
1741 { "CallFlagProc", CallFlagProc },
\r
1742 { "DrawProc", DrawProc },
\r
1743 { "AdjournProc", AdjournProc },
\r
1744 { "AbortProc", AbortProc },
\r
1745 { "ResignProc", ResignProc },
\r
1746 { "EnterKeyProc", EnterKeyProc },
\r
1747 { "StopObservingProc", StopObservingProc },
\r
1748 { "StopExaminingProc", StopExaminingProc },
\r
1749 { "BackwardProc", BackwardProc },
\r
1750 { "ForwardProc", ForwardProc },
\r
1751 { "ToStartProc", ToStartProc },
\r
1752 { "ToEndProc", ToEndProc },
\r
1753 { "RevertProc", RevertProc },
\r
1754 { "TruncateGameProc", TruncateGameProc },
\r
1755 { "MoveNowProc", MoveNowProc },
\r
1756 { "RetractMoveProc", RetractMoveProc },
\r
1757 { "AlwaysQueenProc", AlwaysQueenProc },
\r
1758 { "AnimateDraggingProc", AnimateDraggingProc },
\r
1759 { "AnimateMovingProc", AnimateMovingProc },
\r
1760 { "AutoflagProc", AutoflagProc },
\r
1761 { "AutoflipProc", AutoflipProc },
\r
1762 { "AutobsProc", AutobsProc },
\r
1763 { "AutoraiseProc", AutoraiseProc },
\r
1764 { "AutosaveProc", AutosaveProc },
\r
1765 { "BlindfoldProc", BlindfoldProc },
\r
1766 { "FlashMovesProc", FlashMovesProc },
\r
1767 { "FlipViewProc", FlipViewProc },
\r
1768 { "GetMoveListProc", GetMoveListProc },
\r
1770 { "HighlightDraggingProc", HighlightDraggingProc },
\r
1772 { "HighlightLastMoveProc", HighlightLastMoveProc },
\r
1773 { "IcsAlarmProc", IcsAlarmProc },
\r
1774 { "MoveSoundProc", MoveSoundProc },
\r
1775 { "OldSaveStyleProc", OldSaveStyleProc },
\r
1776 { "PeriodicUpdatesProc", PeriodicUpdatesProc },
\r
1777 { "PonderNextMoveProc", PonderNextMoveProc },
\r
1778 { "PopupExitMessageProc", PopupExitMessageProc },
\r
1779 { "PopupMoveErrorsProc", PopupMoveErrorsProc },
\r
1780 { "PremoveProc", PremoveProc },
\r
1781 { "QuietPlayProc", QuietPlayProc },
\r
1782 { "ShowCoordsProc", ShowCoordsProc },
\r
1783 { "ShowThinkingProc", ShowThinkingProc },
\r
1784 { "HideThinkingProc", HideThinkingProc },
\r
1785 { "TestLegalityProc", TestLegalityProc },
\r
1786 { "InfoProc", InfoProc },
\r
1787 { "ManProc", ManProc },
\r
1788 { "HintProc", HintProc },
\r
1789 { "BookProc", BookProc },
\r
1790 { "AboutGameProc", AboutGameProc },
\r
1791 { "AboutProc", AboutProc },
\r
1792 { "DebugProc", DebugProc },
\r
1793 { "NothingProc", NothingProc },
\r
1794 { "CommentPopDown", (XtActionProc) CommentPopDown },
\r
1795 { "EditCommentPopDown", (XtActionProc) EditCommentPopDown },
\r
1796 { "TagsPopDown", (XtActionProc) TagsPopDown },
\r
1797 { "ErrorPopDown", (XtActionProc) ErrorPopDown },
\r
1798 { "ICSInputBoxPopDown", (XtActionProc) ICSInputBoxPopDown },
\r
1799 { "AnalysisPopDown", (XtActionProc) AnalysisPopDown },
\r
1800 { "FileNamePopDown", (XtActionProc) FileNamePopDown },
\r
1801 { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
\r
1802 { "GameListPopDown", (XtActionProc) GameListPopDown },
\r
1803 { "PromotionPopDown", (XtActionProc) PromotionPopDown },
\r
1804 { "HistoryPopDown", (XtActionProc) HistoryPopDown },
\r
1805 { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
\r
1806 { "ShufflePopDown", (XtActionProc) ShufflePopDown },
\r
1807 { "EnginePopDown", (XtActionProc) EnginePopDown },
\r
1808 { "UciPopDown", (XtActionProc) UciPopDown },
\r
1809 { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },
\r
1810 { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },
\r
1811 { "SettingsPopDown", (XtActionProc) SettingsPopDown },
\r
1814 char globalTranslations[] =
\r
1815 ":<Key>R: ResignProc() \n \
\r
1816 :<Key>r: ResetProc() \n \
\r
1817 :<Key>g: LoadGameProc() \n \
\r
1818 :<Key>N: LoadNextGameProc() \n \
\r
1819 :<Key>P: LoadPrevGameProc() \n \
\r
1820 :<Key>Q: QuitProc() \n \
\r
1821 :<Key>F: ToEndProc() \n \
\r
1822 :<Key>f: ForwardProc() \n \
\r
1823 :<Key>B: ToStartProc() \n \
\r
1824 :<Key>b: BackwardProc() \n \
\r
1825 :<Key>p: PauseProc() \n \
\r
1826 :<Key>d: DrawProc() \n \
\r
1827 :<Key>t: CallFlagProc() \n \
\r
1828 :<Key>i: Iconify() \n \
\r
1829 :<Key>c: Iconify() \n \
\r
1830 :<Key>v: FlipViewProc() \n \
\r
1831 <KeyDown>Control_L: BackwardProc() \n \
\r
1832 <KeyUp>Control_L: ForwardProc() \n \
\r
1833 <KeyDown>Control_R: BackwardProc() \n \
\r
1834 <KeyUp>Control_R: ForwardProc() \n \
\r
1835 Shift<Key>1: AskQuestionProc(\"Direct command\",\
\r
1836 \"Send to chess program:\",,1) \n \
\r
1837 Shift<Key>2: AskQuestionProc(\"Direct command\",\
\r
1838 \"Send to second chess program:\",,2) \n";
\r
1840 char boardTranslations[] =
\r
1841 "<Btn1Down>: HandleUserMove() \n \
\r
1842 <Btn1Up>: HandleUserMove() \n \
\r
1843 <Btn1Motion>: AnimateUserMove() \n \
\r
1844 Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
\r
1845 PieceMenuPopup(menuB) \n \
\r
1846 Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
\r
1847 PieceMenuPopup(menuW) \n \
\r
1848 Shift<Btn3Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD)\
\r
1849 PieceMenuPopup(menuW) \n \
\r
1850 Any<Btn3Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD) \
\r
1851 PieceMenuPopup(menuB) \n";
\r
1853 char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
\r
1854 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
\r
1856 char ICSInputTranslations[] =
\r
1857 "<Key>Return: EnterKeyProc() \n";
\r
1859 String xboardResources[] = {
\r
1860 "*fileName*value.translations: #override\\n <Key>Return: FileNameAction()",
\r
1861 "*question*value.translations: #override\\n <Key>Return: AskQuestionReplyAction()",
\r
1862 "*errorpopup*translations: #override\\n <Key>Return: ErrorPopDown()",
\r
1867 /* Max possible square size */
\r
1868 #define MAXSQSIZE 256
\r
1870 static int xpm_avail[MAXSQSIZE];
\r
1872 #ifdef HAVE_DIR_STRUCT
\r
1874 /* Extract piece size from filename */
\r
1876 xpm_getsize(name, len, ext)
\r
1887 if ((p=strchr(name, '.')) == NULL ||
\r
1888 StrCaseCmp(p+1, ext) != 0)
\r
1894 while (*p && isdigit(*p))
\r
1901 /* Setup xpm_avail */
\r
1903 xpm_getavail(dirname, ext)
\r
1908 struct dirent *ent;
\r
1911 for (i=0; i<MAXSQSIZE; ++i)
\r
1914 if (appData.debugMode)
\r
1915 fprintf(stderr, "XPM dir:%s:ext:%s:\n", dirname, ext);
\r
1917 dir = opendir(dirname);
\r
1920 fprintf(stderr, "%s: Can't access XPM directory %s\n",
\r
1921 programName, dirname);
\r
1925 while ((ent=readdir(dir)) != NULL) {
\r
1926 i = xpm_getsize(ent->d_name, NAMLEN(ent), ext);
\r
1927 if (i > 0 && i < MAXSQSIZE)
\r
1937 xpm_print_avail(fp, ext)
\r
1943 fprintf(fp, "Available `%s' sizes:\n", ext);
\r
1944 for (i=1; i<MAXSQSIZE; ++i) {
\r
1946 printf("%d\n", i);
\r
1950 /* Return XPM piecesize closest to size */
\r
1952 xpm_closest_to(dirname, size, ext)
\r
1958 int sm_diff = MAXSQSIZE;
\r
1962 xpm_getavail(dirname, ext);
\r
1964 if (appData.debugMode)
\r
1965 xpm_print_avail(stderr, ext);
\r
1967 for (i=1; i<MAXSQSIZE; ++i) {
\r
1968 if (xpm_avail[i]) {
\r
1970 diff = (diff<0) ? -diff : diff;
\r
1971 if (diff < sm_diff) {
\r
1979 fprintf(stderr, "Error: No `%s' files!\n", ext);
\r
1985 #else /* !HAVE_DIR_STRUCT */
\r
1986 /* If we are on a system without a DIR struct, we can't
\r
1987 read the directory, so we can't collect a list of
\r
1988 filenames, etc., so we can't do any size-fitting. */
\r
1990 xpm_closest_to(dirname, size, ext)
\r
1995 fprintf(stderr, "Warning: No DIR structure found on this system --\n");
\r
1996 fprintf(stderr, " Unable to autosize for XPM/XIM pieces.\n");
\r
1997 fprintf(stderr, " Please report this error to frankm@hiwaay.net.\n");
\r
1998 fprintf(stderr, " Include system type & operating system in message.\n");
\r
2001 #endif /* HAVE_DIR_STRUCT */
\r
2003 static char *cnames[9] = { "black", "red", "green", "yellow", "blue",
\r
2004 "magenta", "cyan", "white" };
\r
2008 TextColors textColors[(int)NColorClasses];
\r
2010 /* String is: "fg, bg, attr". Which is 0, 1, 2 */
\r
2012 parse_color(str, which)
\r
2016 char *p, buf[100], *d;
\r
2019 if (strlen(str) > 99) /* watch bounds on buf */
\r
2024 for (i=0; i<which; ++i) {
\r
2025 p = strchr(p, ',');
\r
2031 /* Could be looking at something like:
\r
2033 .. in which case we want to stop on a comma also */
\r
2034 while (*p && *p != ',' && !isalpha(*p) && !isdigit(*p))
\r
2038 return -1; /* Use default for empty field */
\r
2041 if (which == 2 || isdigit(*p))
\r
2044 while (*p && isalpha(*p))
\r
2049 for (i=0; i<8; ++i) {
\r
2050 if (!StrCaseCmp(buf, cnames[i]))
\r
2051 return which? (i+40) : (i+30);
\r
2053 if (!StrCaseCmp(buf, "default")) return -1;
\r
2055 fprintf(stderr, "%s: unrecognized color %s\n", programName, buf);
\r
2060 parse_cpair(cc, str)
\r
2064 if ((textColors[(int)cc].fg=parse_color(str, 0)) == -2) {
\r
2065 fprintf(stderr, "%s: can't parse foreground color in `%s'\n",
\r
2066 programName, str);
\r
2070 /* bg and attr are optional */
\r
2071 textColors[(int)cc].bg = parse_color(str, 1);
\r
2072 if ((textColors[(int)cc].attr = parse_color(str, 2)) < 0) {
\r
2073 textColors[(int)cc].attr = 0;
\r
2079 /* Arrange to catch delete-window events */
\r
2080 Atom wm_delete_window;
\r
2082 CatchDeleteWindow(Widget w, String procname)
\r
2084 char buf[MSG_SIZ];
\r
2085 XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
\r
2086 sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
\r
2087 XtAugmentTranslations(w, XtParseTranslationTable(buf));
\r
2094 XtSetArg(args[0], XtNiconic, False);
\r
2095 XtSetValues(shellWidget, args, 1);
\r
2097 XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */
\r
2101 // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined
\r
2103 #define BoardSize int
\r
2104 void InitDrawingSizes(BoardSize boardSize, int flags)
\r
2105 { // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
\r
2106 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
2108 XtGeometryResult gres;
\r
2111 if(!formWidget) return;
\r
2114 * Enable shell resizing.
\r
2116 shellArgs[0].value = (XtArgVal) &w;
\r
2117 shellArgs[1].value = (XtArgVal) &h;
\r
2118 XtGetValues(shellWidget, shellArgs, 2);
\r
2120 shellArgs[4].value = 2*w; shellArgs[2].value = 10;
\r
2121 shellArgs[5].value = 2*h; shellArgs[3].value = 10;
\r
2122 XtSetValues(shellWidget, &shellArgs[2], 4);
2124 XtSetArg(args[0], XtNdefaultDistance, &sep);
\r XtGetValues(formWidget, args, 1);
2126 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
2127 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
2130 XtSetArg(args[0], XtNwidth, boardWidth);
\r
2131 XtSetArg(args[1], XtNheight, boardHeight);
\r
2132 XtSetValues(boardWidget, args, 2);
\r
2134 timerWidth = (boardWidth - sep) / 2;
\r
2135 XtSetArg(args[0], XtNwidth, timerWidth);
\r
2136 XtSetValues(whiteTimerWidget, args, 1);
\r
2137 XtSetValues(blackTimerWidget, args, 1);
\r
2139 XawFormDoLayout(formWidget, False);
\r
2141 if (appData.titleInWindow) {
\r
2143 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2144 XtSetArg(args[i], XtNheight, &h); i++;
\r
2145 XtGetValues(titleWidget, args, i);
\r
2146 if (smallLayout) {
\r
2147 w = boardWidth - 2*bor;
\r
2149 XtSetArg(args[0], XtNwidth, &w);
\r
2150 XtGetValues(menuBarWidget, args, 1);
\r
2151 w = boardWidth - w - sep - 2*bor - 2; // WIDTH_FUDGE
\r
2154 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
\r
2155 if (gres != XtGeometryYes && appData.debugMode) {
\r
2157 "%s: titleWidget geometry error %d %d %d %d %d\n",
\r
2158 programName, gres, w, h, wr, hr);
\r
2162 XawFormDoLayout(formWidget, True);
\r
2165 * Inhibit shell resizing.
\r
2167 shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
\r
2168 shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
\r
2169 shellArgs[4].value = shellArgs[2].value = w;
\r
2170 shellArgs[5].value = shellArgs[3].value = h;
\r
2171 XtSetValues(shellWidget, &shellArgs[0], 6);
\r
2180 int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
\r
2181 XSetWindowAttributes window_attributes;
\r
2183 Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
\r
2184 XrmValue vFrom, vTo;
\r
2185 XtGeometryResult gres;
\r
2188 int forceMono = False;
2189 #define INDIRECTION
\r
2191 // [HGM] before anything else, expand any indirection files amongst options
2192 char *argvCopy[1000]; // 1000 seems enough
2193 char newArgs[10000]; // holds actual characters
2196 srandom(time(0)); // [HGM] book: make random truly random
2199 for(i=0; i<argc; i++) {
2200 if(j >= 1000-2) { printf("too many arguments\n"); exit(-1); }
2201 //fprintf(stderr, "arg %s\n", argv[i]);
2202 if(argv[i][0] != '@') argvCopy[j++] = argv[i]; else {
2204 FILE *f = fopen(argv[i]+1, "rb");
2205 if(f == NULL) { fprintf(stderr, "ignore %s\n", argv[i]); continue; } // do not expand non-existing
2206 argvCopy[j++] = newArgs + k; // get ready for first argument from file
2207 while((c = fgetc(f)) != EOF) { // each line of file inserts 1 argument in the list
2209 if(j >= 1000-2) { printf("too many arguments\n"); exit(-1); }
2210 newArgs[k++] = 0; // terminate current arg
2211 if(k >= 10000-1) { printf("too long arguments\n"); exit(-1); }
2212 argvCopy[j++] = newArgs + k; // get ready for next
2214 if(k >= 10000-1) { printf("too long arguments\n"); exit(-1); }
2227 if(appData.debugMode,1) { // OK, appData is not initialized here yet...
2228 for(i=0; i<argc; i++) fprintf(stderr, "argv[%2d] = '%s'\n", i, argv[i]);
2234 setbuf(stdout, NULL);
\r
2235 setbuf(stderr, NULL);
\r
2238 programName = strrchr(argv[0], '/');
\r
2239 if (programName == NULL)
\r
2240 programName = argv[0];
\r
2245 XtAppInitialize(&appContext, "XBoard", shellOptions,
\r
2246 XtNumber(shellOptions),
\r
2247 &argc, argv, xboardResources, NULL, 0);
\r
2249 fprintf(stderr, "%s: unrecognized argument %s\n",
\r
2250 programName, argv[1]);
\r
2254 if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
\r
2257 if (chdir(chessDir) != 0) {
\r
2258 fprintf(stderr, "%s: can't cd to CHESSDIR: ", programName);
\r
2264 p = getenv("HOME");
\r
2265 if (p == NULL) p = "/tmp";
\r
2266 i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
\r
2267 gameCopyFilename = (char*) malloc(i);
\r
2268 gamePasteFilename = (char*) malloc(i);
\r
2269 sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
\r
2270 sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
\r
2272 XtGetApplicationResources(shellWidget, (XtPointer) &appData,
\r
2273 clientResources, XtNumber(clientResources),
\r
2276 /* [HGM,HR] make sure board size is acceptable */
\r
2277 if(appData.NrFiles > BOARD_SIZE ||
\r
2278 appData.NrRanks > BOARD_SIZE )
\r
2279 DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);
\r
2282 /* This feature does not work; animation needs a rewrite */
\r
2283 appData.highlightDragging = FALSE;
\r
2287 xDisplay = XtDisplay(shellWidget);
\r
2288 xScreen = DefaultScreen(xDisplay);
\r
2289 wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
\r
2291 gameInfo.variant = StringToVariant(appData.variant);
\r
2292 InitPosition(FALSE);
\r
2295 * Determine boardSize
\r
2297 gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8
\r
2300 // [HGM] as long as we have not created the possibility to change size while running, start with requested size
\r
2301 gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8;
\r
2302 gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8;
\r
2303 gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0;
\r
2308 InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine
\r
2310 if (isdigit(appData.boardSize[0])) {
\r
2311 i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
\r
2312 &lineGap, &clockFontPxlSize, &coordFontPxlSize,
\r
2313 &fontPxlSize, &smallLayout, &tinyLayout);
\r
2315 fprintf(stderr, "%s: bad boardSize syntax %s\n",
\r
2316 programName, appData.boardSize);
\r
2320 /* Find some defaults; use the nearest known size */
\r
2321 SizeDefaults *szd, *nearest;
\r
2322 int distance = 99999;
\r
2323 nearest = szd = sizeDefaults;
\r
2324 while (szd->name != NULL) {
\r
2325 if (abs(szd->squareSize - squareSize) < distance) {
\r
2327 distance = abs(szd->squareSize - squareSize);
\r
2328 if (distance == 0) break;
\r
2332 if (i < 2) lineGap = nearest->lineGap;
\r
2333 if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
\r
2334 if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
\r
2335 if (i < 5) fontPxlSize = nearest->fontPxlSize;
\r
2336 if (i < 6) smallLayout = nearest->smallLayout;
\r
2337 if (i < 7) tinyLayout = nearest->tinyLayout;
\r
2340 SizeDefaults *szd = sizeDefaults;
\r
2341 if (*appData.boardSize == NULLCHAR) {
\r
2342 while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
\r
2343 DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
\r
2346 if (szd->name == NULL) szd--;
\r
2348 while (szd->name != NULL &&
\r
2349 StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
\r
2350 if (szd->name == NULL) {
\r
2351 fprintf(stderr, "%s: unrecognized boardSize name %s\n",
\r
2352 programName, appData.boardSize);
\r
2356 squareSize = szd->squareSize;
\r
2357 lineGap = szd->lineGap;
\r
2358 clockFontPxlSize = szd->clockFontPxlSize;
\r
2359 coordFontPxlSize = szd->coordFontPxlSize;
\r
2360 fontPxlSize = szd->fontPxlSize;
\r
2361 smallLayout = szd->smallLayout;
\r
2362 tinyLayout = szd->tinyLayout;
\r
2365 /* Now, using squareSize as a hint, find a good XPM/XIM set size */
\r
2366 if (strlen(appData.pixmapDirectory) > 0) {
\r
2367 p = ExpandPathName(appData.pixmapDirectory);
\r
2369 fprintf(stderr, "Error expanding path name \"%s\"\n",
\r
2370 appData.pixmapDirectory);
\r
2373 if (appData.debugMode) {
\r
2374 fprintf(stderr, "XBoard square size (hint): %d\n", squareSize);
\r
2375 fprintf(stderr, "%s fulldir:%s:\n", IMAGE_EXT, p);
\r
2377 squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
\r
2378 if (appData.debugMode) {
\r
2379 fprintf(stderr, "Closest %s size: %d\n", IMAGE_EXT, squareSize);
\r
2383 /* [HR] height treated separately (hacked) */
\r
2384 boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
2385 boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
\r
2386 if (appData.showJail == 1) {
\r
2387 /* Jail on top and bottom */
\r
2388 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
\r
2389 XtSetArg(boardArgs[2], XtNheight,
\r
2390 boardHeight + 2*(lineGap + squareSize));
\r
2391 } else if (appData.showJail == 2) {
\r
2392 /* Jail on sides */
\r
2393 XtSetArg(boardArgs[1], XtNwidth,
\r
2394 boardWidth + 2*(lineGap + squareSize));
\r
2395 XtSetArg(boardArgs[2], XtNheight, boardHeight);
\r
2398 XtSetArg(boardArgs[1], XtNwidth, boardWidth);
\r
2399 XtSetArg(boardArgs[2], XtNheight, boardHeight);
\r
2403 * Determine what fonts to use.
\r
2405 appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
\r
2406 clockFontID = XLoadFont(xDisplay, appData.clockFont);
\r
2407 clockFontStruct = XQueryFont(xDisplay, clockFontID);
\r
2408 appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
\r
2409 coordFontID = XLoadFont(xDisplay, appData.coordFont);
\r
2410 coordFontStruct = XQueryFont(xDisplay, coordFontID);
\r
2411 appData.font = FindFont(appData.font, fontPxlSize);
\r
2412 countFontID = XLoadFont(xDisplay, appData.coordFont); // [HGM] holdings
\r
2413 countFontStruct = XQueryFont(xDisplay, countFontID);
\r
2414 // appData.font = FindFont(appData.font, fontPxlSize);
\r
2416 xdb = XtDatabase(xDisplay);
\r
2417 XrmPutStringResource(&xdb, "*font", appData.font);
\r
2420 * Detect if there are not enough colors available and adapt.
\r
2422 if (DefaultDepth(xDisplay, xScreen) <= 2) {
\r
2423 appData.monoMode = True;
\r
2426 if (!appData.monoMode) {
\r
2427 vFrom.addr = (caddr_t) appData.lightSquareColor;
\r
2428 vFrom.size = strlen(appData.lightSquareColor);
\r
2429 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2430 if (vTo.addr == NULL) {
\r
2431 appData.monoMode = True;
\r
2434 lightSquareColor = *(Pixel *) vTo.addr;
\r
2437 if (!appData.monoMode) {
\r
2438 vFrom.addr = (caddr_t) appData.darkSquareColor;
\r
2439 vFrom.size = strlen(appData.darkSquareColor);
\r
2440 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2441 if (vTo.addr == NULL) {
\r
2442 appData.monoMode = True;
\r
2445 darkSquareColor = *(Pixel *) vTo.addr;
\r
2448 if (!appData.monoMode) {
\r
2449 vFrom.addr = (caddr_t) appData.whitePieceColor;
\r
2450 vFrom.size = strlen(appData.whitePieceColor);
\r
2451 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2452 if (vTo.addr == NULL) {
\r
2453 appData.monoMode = True;
\r
2456 whitePieceColor = *(Pixel *) vTo.addr;
\r
2459 if (!appData.monoMode) {
\r
2460 vFrom.addr = (caddr_t) appData.blackPieceColor;
\r
2461 vFrom.size = strlen(appData.blackPieceColor);
\r
2462 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2463 if (vTo.addr == NULL) {
\r
2464 appData.monoMode = True;
\r
2467 blackPieceColor = *(Pixel *) vTo.addr;
\r
2471 if (!appData.monoMode) {
\r
2472 vFrom.addr = (caddr_t) appData.highlightSquareColor;
\r
2473 vFrom.size = strlen(appData.highlightSquareColor);
\r
2474 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2475 if (vTo.addr == NULL) {
\r
2476 appData.monoMode = True;
\r
2479 highlightSquareColor = *(Pixel *) vTo.addr;
\r
2483 if (!appData.monoMode) {
\r
2484 vFrom.addr = (caddr_t) appData.premoveHighlightColor;
\r
2485 vFrom.size = strlen(appData.premoveHighlightColor);
\r
2486 XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
\r
2487 if (vTo.addr == NULL) {
\r
2488 appData.monoMode = True;
\r
2491 premoveHighlightColor = *(Pixel *) vTo.addr;
\r
2496 fprintf(stderr, "%s: too few colors available; trying monochrome mode\n",
\r
2500 if (appData.monoMode && appData.debugMode) {
\r
2501 fprintf(stderr, "white pixel = 0x%lx, black pixel = 0x%lx\n",
\r
2502 (unsigned long) XWhitePixel(xDisplay, xScreen),
\r
2503 (unsigned long) XBlackPixel(xDisplay, xScreen));
\r
2506 if (parse_cpair(ColorShout, appData.colorShout) < 0 ||
\r
2507 parse_cpair(ColorSShout, appData.colorSShout) < 0 ||
\r
2508 parse_cpair(ColorChannel1, appData.colorChannel1) < 0 ||
\r
2509 parse_cpair(ColorChannel, appData.colorChannel) < 0 ||
\r
2510 parse_cpair(ColorKibitz, appData.colorKibitz) < 0 ||
\r
2511 parse_cpair(ColorTell, appData.colorTell) < 0 ||
\r
2512 parse_cpair(ColorChallenge, appData.colorChallenge) < 0 ||
\r
2513 parse_cpair(ColorRequest, appData.colorRequest) < 0 ||
\r
2514 parse_cpair(ColorSeek, appData.colorSeek) < 0 ||
\r
2515 parse_cpair(ColorNormal, appData.colorNormal) < 0)
\r
2517 if (appData.colorize) {
\r
2519 "%s: can't parse color names; disabling colorization\n",
\r
2522 appData.colorize = FALSE;
\r
2524 textColors[ColorNone].fg = textColors[ColorNone].bg = -1;
\r
2525 textColors[ColorNone].attr = 0;
\r
2527 XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
\r
2530 * widget hierarchy
\r
2533 layoutName = "tinyLayout";
\r
2534 } else if (smallLayout) {
\r
2535 layoutName = "smallLayout";
\r
2537 layoutName = "normalLayout";
\r
2539 /* Outer layoutWidget is there only to provide a name for use in
\r
2540 resources that depend on the layout style */
\r
2542 XtCreateManagedWidget(layoutName, formWidgetClass, shellWidget,
\r
2543 layoutArgs, XtNumber(layoutArgs));
\r
2545 XtCreateManagedWidget("form", formWidgetClass, layoutWidget,
\r
2546 formArgs, XtNumber(formArgs));
\r
2547 XtSetArg(args[0], XtNdefaultDistance, &sep);
\r
2548 XtGetValues(formWidget, args, 1);
\r
2551 widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
\r
2552 XtSetArg(args[0], XtNtop, XtChainTop);
\r
2553 XtSetArg(args[1], XtNbottom, XtChainTop);
2554 XtSetValues(menuBarWidget, args, 2);
\r
2556 widgetList[j++] = whiteTimerWidget =
\r
2557 XtCreateWidget("whiteTime", labelWidgetClass,
\r
2558 formWidget, timerArgs, XtNumber(timerArgs));
\r
2559 XtSetArg(args[0], XtNfont, clockFontStruct);
\r
2560 XtSetArg(args[1], XtNtop, XtChainTop);
\r
2561 XtSetArg(args[2], XtNbottom, XtChainTop);
2562 XtSetValues(whiteTimerWidget, args, 3);
\r
2564 widgetList[j++] = blackTimerWidget =
\r
2565 XtCreateWidget("blackTime", labelWidgetClass,
\r
2566 formWidget, timerArgs, XtNumber(timerArgs));
\r
2567 XtSetArg(args[0], XtNfont, clockFontStruct);
\r
2568 XtSetArg(args[1], XtNtop, XtChainTop);
\r
2569 XtSetArg(args[2], XtNbottom, XtChainTop);
2570 XtSetValues(blackTimerWidget, args, 3);
\r
2572 if (appData.titleInWindow) {
\r
2573 widgetList[j++] = titleWidget =
\r
2574 XtCreateWidget("title", labelWidgetClass, formWidget,
\r
2575 titleArgs, XtNumber(titleArgs));
\r
2576 XtSetArg(args[0], XtNtop, XtChainTop);
\r
2577 XtSetArg(args[1], XtNbottom, XtChainTop);
2578 XtSetValues(titleWidget, args, 2);
\r
2581 if (appData.showButtonBar) {
\r
2582 widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
\r
2583 XtSetArg(args[0], XtNleft, XtChainRight); // [HGM] glue to right window edge
\r
2584 XtSetArg(args[1], XtNright, XtChainRight); // for good run-time sizing
2585 XtSetArg(args[2], XtNtop, XtChainTop);
\r
2586 XtSetArg(args[3], XtNbottom, XtChainTop);
2587 XtSetValues(buttonBarWidget, args, 4);
\r
2590 widgetList[j++] = messageWidget =
\r
2591 XtCreateWidget("message", labelWidgetClass, formWidget,
\r
2592 messageArgs, XtNumber(messageArgs));
2593 XtSetArg(args[0], XtNtop, XtChainTop);
\r
2594 XtSetArg(args[1], XtNbottom, XtChainTop);
2595 XtSetValues(messageWidget, args, 2);
\r
2597 widgetList[j++] = boardWidget =
\r
2598 XtCreateWidget("board", widgetClass, formWidget, boardArgs,
\r
2599 XtNumber(boardArgs));
\r
2601 XtManageChildren(widgetList, j);
\r
2603 timerWidth = (boardWidth - sep) / 2;
\r
2604 XtSetArg(args[0], XtNwidth, timerWidth);
\r
2605 XtSetValues(whiteTimerWidget, args, 1);
\r
2606 XtSetValues(blackTimerWidget, args, 1);
\r
2608 XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
\r
2609 XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
\r
2610 XtGetValues(whiteTimerWidget, args, 2);
\r
2612 if (appData.showButtonBar) {
\r
2613 XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
\r
2614 XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
\r
2615 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
\r
2619 * formWidget uses these constraints but they are stored
\r
2620 * in the children.
\r
2623 XtSetArg(args[i], XtNfromHoriz, 0); i++;
\r
2624 XtSetValues(menuBarWidget, args, i);
\r
2625 if (appData.titleInWindow) {
\r
2626 if (smallLayout) {
\r
2628 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2629 XtSetValues(whiteTimerWidget, args, i);
\r
2631 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2632 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2633 XtSetValues(blackTimerWidget, args, i);
\r
2635 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2636 XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
\r
2637 XtSetValues(titleWidget, args, i);
\r
2639 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2640 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2641 XtSetValues(messageWidget, args, i);
\r
2642 if (appData.showButtonBar) {
\r
2644 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2645 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2646 XtSetValues(buttonBarWidget, args, i);
\r
2650 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2651 XtSetValues(whiteTimerWidget, args, i);
\r
2653 XtSetArg(args[i], XtNfromVert, titleWidget); i++;
\r
2654 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2655 XtSetValues(blackTimerWidget, args, i);
\r
2657 XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
\r
2658 XtSetValues(titleWidget, args, i);
\r
2660 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2661 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2662 XtSetValues(messageWidget, args, i);
\r
2663 if (appData.showButtonBar) {
\r
2665 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2666 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2667 XtSetValues(buttonBarWidget, args, i);
\r
2672 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2673 XtSetValues(whiteTimerWidget, args, i);
\r
2675 XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
\r
2676 XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
\r
2677 XtSetValues(blackTimerWidget, args, i);
\r
2679 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2680 XtSetArg(args[i], XtNresizable, (XtArgVal) True); i++;
\r
2681 XtSetValues(messageWidget, args, i);
\r
2682 if (appData.showButtonBar) {
\r
2684 XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
\r
2685 XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
\r
2686 XtSetValues(buttonBarWidget, args, i);
\r
2690 XtSetArg(args[0], XtNfromVert, messageWidget);
\r
2691 XtSetArg(args[1], XtNtop, XtChainTop);
\r
2692 XtSetArg(args[2], XtNbottom, XtChainBottom);
2693 XtSetArg(args[3], XtNleft, XtChainLeft);
\r
2694 XtSetArg(args[4], XtNright, XtChainRight);
2695 XtSetValues(boardWidget, args, 5);
\r
2697 XtRealizeWidget(shellWidget);
\r
2700 * Correct the width of the message and title widgets.
\r
2701 * It is not known why some systems need the extra fudge term.
\r
2702 * The value "2" is probably larger than needed.
\r
2704 XawFormDoLayout(formWidget, False);
\r
2706 #define WIDTH_FUDGE 2
\r
2708 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2709 XtSetArg(args[i], XtNheight, &h); i++;
\r
2710 XtGetValues(messageWidget, args, i);
\r
2711 if (appData.showButtonBar) {
\r
2713 XtSetArg(args[i], XtNwidth, &w); i++;
\r
2714 XtGetValues(buttonBarWidget, args, i);
\r
2715 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
\r
2717 w = boardWidth - 2*bor + 1; /*!! +1 compensates for kludge below */
\r
2720 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
\r
2721 if (gres != XtGeometryYes && appData.debugMode) {
\r
2722 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
\r
2723 programName, gres, w, h, wr, hr);
\r
2726 /* !! Horrible hack to work around bug in XFree86 4.0.1 (X11R6.4.3) */
\r
2727 /* The size used for the child widget in layout lags one resize behind
\r
2728 its true size, so we resize a second time, 1 pixel smaller. Yeech! */
\r
2730 gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
\r
2731 if (gres != XtGeometryYes && appData.debugMode) {
\r
2732 fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
\r
2733 programName, gres, w, h, wr, hr);
\r
2736 XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing
\r
2737 XtSetArg(args[1], XtNright, XtChainRight);
2738 XtSetValues(messageWidget, args, 2);
\r
2740 if (appData.titleInWindow) {
\r
2742 XtSetArg(args[i], XtNborderWidth, &bor); i++;
\r
2743 XtSetArg(args[i], XtNheight, &h); i++;
\r
2744 XtGetValues(titleWidget, args, i);
\r
2745 if (smallLayout) {
\r
2746 w = boardWidth - 2*bor;
\r
2748 XtSetArg(args[0], XtNwidth, &w);
\r
2749 XtGetValues(menuBarWidget, args, 1);
\r
2750 w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
\r
2753 gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
\r
2754 if (gres != XtGeometryYes && appData.debugMode) {
\r
2756 "%s: titleWidget geometry error %d %d %d %d %d\n",
\r
2757 programName, gres, w, h, wr, hr);
\r
2760 XawFormDoLayout(formWidget, True);
\r
2762 xBoardWindow = XtWindow(boardWidget);
\r
2764 // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would
\r
2765 // not need to go into InitDrawingSizes().
\r
2769 * Create X checkmark bitmap and initialize option menu checks.
\r
2771 ReadBitmap(&xMarkPixmap, "checkmark.bm",
\r
2772 checkmark_bits, checkmark_width, checkmark_height);
\r
2773 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
2774 if (appData.alwaysPromoteToQueen) {
\r
2775 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
\r
2778 if (appData.animateDragging) {
\r
2779 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2780 "menuOptions.Animate Dragging"),
\r
2783 if (appData.animate) {
\r
2784 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
\r
2787 if (appData.autoComment) {
\r
2788 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
\r
2791 if (appData.autoCallFlag) {
\r
2792 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
\r
2795 if (appData.autoFlipView) {
\r
2796 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
\r
2799 if (appData.autoObserve) {
\r
2800 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
\r
2803 if (appData.autoRaiseBoard) {
\r
2804 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2805 "menuOptions.Auto Raise Board"), args, 1);
\r
2807 if (appData.autoSaveGames) {
\r
2808 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2811 if (appData.saveGameFile[0] != NULLCHAR) {
\r
2812 /* Can't turn this off from menu */
\r
2813 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2815 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
2819 if (appData.blindfold) {
\r
2820 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2821 "menuOptions.Blindfold"), args, 1);
\r
2823 if (appData.flashCount > 0) {
\r
2824 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2825 "menuOptions.Flash Moves"),
\r
2828 if (appData.getMoveList) {
\r
2829 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
\r
2833 if (appData.highlightDragging) {
\r
2834 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2835 "menuOptions.Highlight Dragging"),
\r
2839 if (appData.highlightLastMove) {
\r
2840 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2841 "menuOptions.Highlight Last Move"),
\r
2844 if (appData.icsAlarm) {
\r
2845 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
\r
2848 if (appData.ringBellAfterMoves) {
\r
2849 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
\r
2852 if (appData.oldSaveStyle) {
\r
2853 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2854 "menuOptions.Old Save Style"), args, 1);
\r
2856 if (appData.periodicUpdates) {
\r
2857 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2858 "menuOptions.Periodic Updates"), args, 1);
\r
2860 if (appData.ponderNextMove) {
\r
2861 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2862 "menuOptions.Ponder Next Move"), args, 1);
\r
2864 if (appData.popupExitMessage) {
\r
2865 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2866 "menuOptions.Popup Exit Message"), args, 1);
\r
2868 if (appData.popupMoveErrors) {
\r
2869 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2870 "menuOptions.Popup Move Errors"), args, 1);
\r
2872 if (appData.premove) {
\r
2873 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2874 "menuOptions.Premove"), args, 1);
\r
2876 if (appData.quietPlay) {
\r
2877 XtSetValues(XtNameToWidget(menuBarWidget,
\r
2878 "menuOptions.Quiet Play"), args, 1);
\r
2880 if (appData.showCoords) {
\r
2881 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
\r
2884 if (appData.hideThinkingFromHuman) {
\r
2885 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
\r
2888 if (appData.testLegality) {
\r
2889 XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"),
\r
2896 ReadBitmap(&wIconPixmap, "icon_white.bm",
\r
2897 icon_white_bits, icon_white_width, icon_white_height);
\r
2898 ReadBitmap(&bIconPixmap, "icon_black.bm",
\r
2899 icon_black_bits, icon_black_width, icon_black_height);
\r
2900 iconPixmap = wIconPixmap;
\r
2902 XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++;
\r
2903 XtSetValues(shellWidget, args, i);
\r
2906 * Create a cursor for the board widget.
\r
2908 window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
\r
2909 XChangeWindowAttributes(xDisplay, xBoardWindow,
\r
2910 CWCursor, &window_attributes);
\r
2913 * Inhibit shell resizing.
\r
2915 shellArgs[0].value = (XtArgVal) &w;
\r
2916 shellArgs[1].value = (XtArgVal) &h;
\r
2917 XtGetValues(shellWidget, shellArgs, 2);
\r
2918 shellArgs[4].value = shellArgs[2].value = w;
\r
2919 shellArgs[5].value = shellArgs[3].value = h;
\r
2920 XtSetValues(shellWidget, &shellArgs[2], 4);
2921 marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
\r
2922 marginH = h - boardHeight;
\r
2924 CatchDeleteWindow(shellWidget, "QuitProc");
\r
2929 if (appData.bitmapDirectory[0] != NULLCHAR) {
\r
2932 CreateXPMPieces();
\r
2935 CreateXIMPieces();
\r
2936 /* Create regular pieces */
\r
2937 if (!useImages) CreatePieces();
\r
2940 CreatePieceMenus();
\r
2942 if (appData.animate || appData.animateDragging)
\r
2945 XtAugmentTranslations(formWidget,
\r
2946 XtParseTranslationTable(globalTranslations));
\r
2947 XtAugmentTranslations(boardWidget,
\r
2948 XtParseTranslationTable(boardTranslations));
\r
2949 XtAugmentTranslations(whiteTimerWidget,
\r
2950 XtParseTranslationTable(whiteTranslations));
\r
2951 XtAugmentTranslations(blackTimerWidget,
\r
2952 XtParseTranslationTable(blackTranslations));
\r
2954 /* Why is the following needed on some versions of X instead
\r
2955 * of a translation? */
\r
2956 XtAddEventHandler(boardWidget, ExposureMask, False,
\r
2957 (XtEventHandler) EventProc, NULL);
\r
2962 if (errorExitStatus == -1) {
\r
2963 if (appData.icsActive) {
\r
2964 /* We now wait until we see "login:" from the ICS before
\r
2965 sending the logon script (problems with timestamp otherwise) */
\r
2966 /*ICSInitScript();*/
\r
2967 if (appData.icsInputBox) ICSInputBoxPopUp();
\r
2970 signal(SIGINT, IntSigHandler);
\r
2971 signal(SIGTERM, IntSigHandler);
\r
2972 if (*appData.cmailGameName != NULLCHAR) {
\r
2973 signal(SIGUSR1, CmailSigHandler);
\r
2976 InitPosition(TRUE);
\r
2978 XtAppMainLoop(appContext);
\r
2983 ShutDownFrontEnd()
\r
2985 if (appData.icsActive && oldICSInteractionTitle != NULL) {
\r
2986 DisplayIcsInteractionTitle(oldICSInteractionTitle);
\r
2988 unlink(gameCopyFilename);
\r
2989 unlink(gamePasteFilename);
\r
2993 IntSigHandler(sig)
\r
3000 CmailSigHandler(sig)
\r
3006 signal(SIGUSR1, SIG_IGN); /* suspend handler */
\r
3008 /* Activate call-back function CmailSigHandlerCallBack() */
\r
3009 OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
\r
3011 signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
\r
3015 CmailSigHandlerCallBack(isr, closure, message, count, error)
\r
3016 InputSourceRef isr;
\r
3023 ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */
\r
3025 /**** end signal code ****/
\r
3032 char buf[MSG_SIZ];
\r
3035 f = fopen(appData.icsLogon, "r");
\r
3037 p = getenv("HOME");
\r
3041 strcat(buf, appData.icsLogon);
\r
3042 f = fopen(buf, "r");
\r
3046 ProcessICSInitScript(f);
\r
3053 EditCommentPopDown();
\r
3064 SetMenuEnables(enab)
\r
3068 if (!menuBarWidget) return;
\r
3069 while (enab->name != NULL) {
\r
3070 w = XtNameToWidget(menuBarWidget, enab->name);
\r
3072 DisplayError(enab->name, 0);
\r
3074 XtSetSensitive(w, enab->value);
\r
3080 Enables icsEnables[] = {
\r
3081 { "menuFile.Mail Move", False },
\r
3082 { "menuFile.Reload CMail Message", False },
\r
3083 { "menuMode.Machine Black", False },
\r
3084 { "menuMode.Machine White", False },
\r
3085 { "menuMode.Analysis Mode", False },
\r
3086 { "menuMode.Analyze File", False },
\r
3087 { "menuMode.Two Machines", False },
\r
3089 { "menuHelp.Hint", False },
\r
3090 { "menuHelp.Book", False },
\r
3091 { "menuStep.Move Now", False },
\r
3092 { "menuOptions.Periodic Updates", False },
\r
3093 { "menuOptions.Hide Thinking", False },
\r
3094 { "menuOptions.Ponder Next Move", False },
\r
3099 Enables ncpEnables[] = {
\r
3100 { "menuFile.Mail Move", False },
\r
3101 { "menuFile.Reload CMail Message", False },
\r
3102 { "menuMode.Machine White", False },
\r
3103 { "menuMode.Machine Black", False },
\r
3104 { "menuMode.Analysis Mode", False },
\r
3105 { "menuMode.Analyze File", False },
\r
3106 { "menuMode.Two Machines", False },
\r
3107 { "menuMode.ICS Client", False },
\r
3108 { "menuMode.ICS Input Box", False },
\r
3109 { "Action", False },
\r
3110 { "menuStep.Revert", False },
\r
3111 { "menuStep.Move Now", False },
\r
3112 { "menuStep.Retract Move", False },
\r
3113 { "menuOptions.Auto Comment", False },
\r
3114 { "menuOptions.Auto Flag", False },
\r
3115 { "menuOptions.Auto Flip View", False },
\r
3116 { "menuOptions.Auto Observe", False },
\r
3117 { "menuOptions.Auto Raise Board", False },
\r
3118 { "menuOptions.Get Move List", False },
\r
3119 { "menuOptions.ICS Alarm", False },
\r
3120 { "menuOptions.Move Sound", False },
\r
3121 { "menuOptions.Quiet Play", False },
\r
3122 { "menuOptions.Hide Thinking", False },
\r
3123 { "menuOptions.Periodic Updates", False },
\r
3124 { "menuOptions.Ponder Next Move", False },
\r
3125 { "menuHelp.Hint", False },
\r
3126 { "menuHelp.Book", False },
\r
3130 Enables gnuEnables[] = {
\r
3131 { "menuMode.ICS Client", False },
\r
3132 { "menuMode.ICS Input Box", False },
\r
3133 { "menuAction.Accept", False },
\r
3134 { "menuAction.Decline", False },
\r
3135 { "menuAction.Rematch", False },
\r
3136 { "menuAction.Adjourn", False },
\r
3137 { "menuAction.Stop Examining", False },
\r
3138 { "menuAction.Stop Observing", False },
\r
3139 { "menuStep.Revert", False },
\r
3140 { "menuOptions.Auto Comment", False },
\r
3141 { "menuOptions.Auto Observe", False },
\r
3142 { "menuOptions.Auto Raise Board", False },
\r
3143 { "menuOptions.Get Move List", False },
\r
3144 { "menuOptions.Premove", False },
\r
3145 { "menuOptions.Quiet Play", False },
\r
3147 /* The next two options rely on SetCmailMode being called *after* */
\r
3148 /* SetGNUMode so that when GNU is being used to give hints these */
\r
3149 /* menu options are still available */
\r
3151 { "menuFile.Mail Move", False },
\r
3152 { "menuFile.Reload CMail Message", False },
\r
3156 Enables cmailEnables[] = {
\r
3157 { "Action", True },
\r
3158 { "menuAction.Call Flag", False },
\r
3159 { "menuAction.Draw", True },
\r
3160 { "menuAction.Adjourn", False },
\r
3161 { "menuAction.Abort", False },
\r
3162 { "menuAction.Stop Observing", False },
\r
3163 { "menuAction.Stop Examining", False },
\r
3164 { "menuFile.Mail Move", True },
\r
3165 { "menuFile.Reload CMail Message", True },
\r
3169 Enables trainingOnEnables[] = {
\r
3170 { "menuMode.Edit Comment", False },
\r
3171 { "menuMode.Pause", False },
\r
3172 { "menuStep.Forward", False },
\r
3173 { "menuStep.Backward", False },
\r
3174 { "menuStep.Forward to End", False },
\r
3175 { "menuStep.Back to Start", False },
\r
3176 { "menuStep.Move Now", False },
\r
3177 { "menuStep.Truncate Game", False },
\r
3181 Enables trainingOffEnables[] = {
\r
3182 { "menuMode.Edit Comment", True },
\r
3183 { "menuMode.Pause", True },
\r
3184 { "menuStep.Forward", True },
\r
3185 { "menuStep.Backward", True },
\r
3186 { "menuStep.Forward to End", True },
\r
3187 { "menuStep.Back to Start", True },
\r
3188 { "menuStep.Move Now", True },
\r
3189 { "menuStep.Truncate Game", True },
\r
3193 Enables machineThinkingEnables[] = {
\r
3194 { "menuFile.Load Game", False },
\r
3195 { "menuFile.Load Next Game", False },
\r
3196 { "menuFile.Load Previous Game", False },
\r
3197 { "menuFile.Reload Same Game", False },
\r
3198 { "menuFile.Paste Game", False },
\r
3199 { "menuFile.Load Position", False },
\r
3200 { "menuFile.Load Next Position", False },
\r
3201 { "menuFile.Load Previous Position", False },
\r
3202 { "menuFile.Reload Same Position", False },
\r
3203 { "menuFile.Paste Position", False },
\r
3204 { "menuMode.Machine White", False },
\r
3205 { "menuMode.Machine Black", False },
\r
3206 { "menuMode.Two Machines", False },
\r
3207 { "menuStep.Retract Move", False },
\r
3211 Enables userThinkingEnables[] = {
\r
3212 { "menuFile.Load Game", True },
\r
3213 { "menuFile.Load Next Game", True },
\r
3214 { "menuFile.Load Previous Game", True },
\r
3215 { "menuFile.Reload Same Game", True },
\r
3216 { "menuFile.Paste Game", True },
\r
3217 { "menuFile.Load Position", True },
\r
3218 { "menuFile.Load Next Position", True },
\r
3219 { "menuFile.Load Previous Position", True },
\r
3220 { "menuFile.Reload Same Position", True },
\r
3221 { "menuFile.Paste Position", True },
\r
3222 { "menuMode.Machine White", True },
\r
3223 { "menuMode.Machine Black", True },
\r
3224 { "menuMode.Two Machines", True },
\r
3225 { "menuStep.Retract Move", True },
\r
3231 SetMenuEnables(icsEnables);
\r
3237 SetMenuEnables(ncpEnables);
\r
3243 SetMenuEnables(gnuEnables);
\r
3249 SetMenuEnables(cmailEnables);
\r
3253 SetTrainingModeOn()
\r
3255 SetMenuEnables(trainingOnEnables);
\r
3256 if (appData.showButtonBar) {
\r
3257 XtSetSensitive(buttonBarWidget, False);
\r
3263 SetTrainingModeOff()
\r
3265 SetMenuEnables(trainingOffEnables);
\r
3266 if (appData.showButtonBar) {
\r
3267 XtSetSensitive(buttonBarWidget, True);
\r
3272 SetUserThinkingEnables()
\r
3274 if (appData.noChessProgram) return;
\r
3275 SetMenuEnables(userThinkingEnables);
\r
3279 SetMachineThinkingEnables()
\r
3281 if (appData.noChessProgram) return;
\r
3282 SetMenuEnables(machineThinkingEnables);
\r
3283 switch (gameMode) {
\r
3284 case MachinePlaysBlack:
\r
3285 case MachinePlaysWhite:
\r
3286 case TwoMachinesPlay:
\r
3287 XtSetSensitive(XtNameToWidget(menuBarWidget,
\r
3288 ModeToWidgetName(gameMode)), True);
\r
3295 #define Abs(n) ((n)<0 ? -(n) : (n))
\r
3298 * Find a font that matches "pattern" that is as close as
\r
3299 * possible to the targetPxlSize. Prefer fonts that are k
\r
3300 * pixels smaller to fonts that are k pixels larger. The
\r
3301 * pattern must be in the X Consortium standard format,
\r
3302 * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
\r
3303 * The return value should be freed with XtFree when no
\r
3306 char *FindFont(pattern, targetPxlSize)
\r
3308 int targetPxlSize;
\r
3310 char **fonts, *p, *best, *scalable, *scalableTail;
\r
3311 int i, j, nfonts, minerr, err, pxlSize;
\r
3313 fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
\r
3315 fprintf(stderr, "%s: no fonts match pattern %s\n",
\r
3316 programName, pattern);
\r
3322 for (i=0; i<nfonts; i++) {
\r
3325 if (*p != '-') continue;
\r
3327 if (*p == NULLCHAR) break;
\r
3328 if (*p++ == '-') j++;
\r
3330 if (j < 7) continue;
\r
3331 pxlSize = atoi(p);
\r
3332 if (pxlSize == 0) {
\r
3333 scalable = fonts[i];
\r
3336 err = pxlSize - targetPxlSize;
\r
3337 if (Abs(err) < Abs(minerr) ||
\r
3338 (minerr > 0 && err < 0 && -err == minerr)) {
\r
3344 if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
\r
3345 /* If the error is too big and there is a scalable font,
\r
3346 use the scalable font. */
\r
3347 int headlen = scalableTail - scalable;
\r
3348 p = (char *) XtMalloc(strlen(scalable) + 10);
\r
3349 while (isdigit(*scalableTail)) scalableTail++;
\r
3350 sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
\r
3352 p = (char *) XtMalloc(strlen(best) + 1);
\r
3355 if (appData.debugMode) {
\r
3356 fprintf(debugFP, "resolved %s at pixel size %d\n to %s\n",
\r
3357 pattern, targetPxlSize, p);
\r
3359 XFreeFontNames(fonts);
\r
3365 XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
\r
3366 | GCBackground | GCFunction | GCPlaneMask;
\r
3367 XGCValues gc_values;
\r
3368 GC copyInvertedGC;
\r
3370 gc_values.plane_mask = AllPlanes;
\r
3371 gc_values.line_width = lineGap;
\r
3372 gc_values.line_style = LineSolid;
\r
3373 gc_values.function = GXcopy;
\r
3375 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3376 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3377 lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3379 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3380 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3381 coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3382 XSetFont(xDisplay, coordGC, coordFontID);
\r
3384 // [HGM] make font for holdings counts (white on black0
3385 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3386 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3387 countGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3388 XSetFont(xDisplay, countGC, countFontID);
\r
3390 if (appData.monoMode) {
\r
3391 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3392 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3393 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3395 gc_values.foreground = XWhitePixel(xDisplay, xScreen);
\r
3396 gc_values.background = XBlackPixel(xDisplay, xScreen);
\r
3397 lightSquareGC = wbPieceGC
\r
3398 = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3400 gc_values.foreground = XBlackPixel(xDisplay, xScreen);
\r
3401 gc_values.background = XWhitePixel(xDisplay, xScreen);
\r
3402 darkSquareGC = bwPieceGC
\r
3403 = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3405 if (DefaultDepth(xDisplay, xScreen) == 1) {
\r
3406 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
\r
3407 gc_values.function = GXcopyInverted;
\r
3408 copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3409 gc_values.function = GXcopy;
\r
3410 if (XBlackPixel(xDisplay, xScreen) == 1) {
\r
3411 bwPieceGC = darkSquareGC;
\r
3412 wbPieceGC = copyInvertedGC;
\r
3414 bwPieceGC = copyInvertedGC;
\r
3415 wbPieceGC = lightSquareGC;
\r
3419 gc_values.foreground = highlightSquareColor;
\r
3420 gc_values.background = highlightSquareColor;
\r
3421 highlineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3423 gc_values.foreground = premoveHighlightColor;
\r
3424 gc_values.background = premoveHighlightColor;
\r
3425 prelineGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3427 gc_values.foreground = lightSquareColor;
\r
3428 gc_values.background = darkSquareColor;
\r
3429 lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3431 gc_values.foreground = darkSquareColor;
\r
3432 gc_values.background = lightSquareColor;
\r
3433 darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3435 gc_values.foreground = jailSquareColor;
\r
3436 gc_values.background = jailSquareColor;
\r
3437 jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3439 gc_values.foreground = whitePieceColor;
\r
3440 gc_values.background = darkSquareColor;
\r
3441 wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3443 gc_values.foreground = whitePieceColor;
\r
3444 gc_values.background = lightSquareColor;
\r
3445 wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3447 gc_values.foreground = whitePieceColor;
\r
3448 gc_values.background = jailSquareColor;
\r
3449 wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3451 gc_values.foreground = blackPieceColor;
\r
3452 gc_values.background = darkSquareColor;
\r
3453 bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3455 gc_values.foreground = blackPieceColor;
\r
3456 gc_values.background = lightSquareColor;
\r
3457 blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3459 gc_values.foreground = blackPieceColor;
\r
3460 gc_values.background = jailSquareColor;
\r
3461 bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
\r
3465 void loadXIM(xim, xmask, filename, dest, mask)
\r
3472 int x, y, w, h, p;
\r
3478 fp = fopen(filename, "rb");
\r
3480 fprintf(stderr, "%s: error loading XIM!\n", programName);
\r
3487 for (y=0; y<h; ++y) {
\r
3488 for (x=0; x<h; ++x) {
\r
3493 XPutPixel(xim, x, y, blackPieceColor);
\r
3495 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
\r
3498 XPutPixel(xim, x, y, darkSquareColor);
\r
3500 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
\r
3503 XPutPixel(xim, x, y, whitePieceColor);
\r
3505 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
\r
3508 XPutPixel(xim, x, y, lightSquareColor);
\r
3510 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
\r
3516 /* create Pixmap of piece */
\r
3517 *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3518 w, h, xim->depth);
\r
3519 XPutImage(xDisplay, *dest, lightSquareGC, xim,
\r
3520 0, 0, 0, 0, w, h);
\r
3522 /* create Pixmap of clipmask
\r
3523 Note: We assume the white/black pieces have the same
\r
3524 outline, so we make only 6 masks. This is okay
\r
3525 since the XPM clipmask routines do the same. */
\r
3527 temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3528 w, h, xim->depth);
\r
3529 XPutImage(xDisplay, temp, lightSquareGC, xmask,
\r
3530 0, 0, 0, 0, w, h);
\r
3532 /* now create the 1-bit version */
\r
3533 *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
\r
3536 values.foreground = 1;
\r
3537 values.background = 0;
\r
3539 /* Don't use XtGetGC, not read only */
\r
3540 maskGC = XCreateGC(xDisplay, *mask,
\r
3541 GCForeground | GCBackground, &values);
\r
3542 XCopyPlane(xDisplay, temp, *mask, maskGC,
\r
3543 0, 0, squareSize, squareSize, 0, 0, 1);
\r
3544 XFreePixmap(xDisplay, temp);
\r
3548 void CreateXIMPieces()
\r
3551 char buf[MSG_SIZ];
\r
3553 static char *ximkind[] = { "ll", "ld", "dl", "dd" };
\r
3558 /* The XSynchronize calls were copied from CreatePieces.
\r
3559 Not sure if needed, but can't hurt */
\r
3560 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3563 /* temp needed by loadXIM() */
\r
3564 ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3565 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3567 if (strlen(appData.pixmapDirectory) == 0) {
\r
3571 if (appData.monoMode) {
\r
3572 DisplayFatalError("XIM pieces cannot be used in monochrome mode",
\r
3576 fprintf(stderr, "\nLoading XIMs...\n");
\r
3578 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3579 fprintf(stderr, "%d", piece+1);
\r
3580 for (kind=0; kind<4; kind++) {
\r
3581 fprintf(stderr, ".");
\r
3582 sprintf(buf, "%s/%c%s%u.xim",
\r
3583 ExpandPathName(appData.pixmapDirectory),
\r
3584 ToLower(PieceToChar((ChessSquare)piece)),
\r
3585 ximkind[kind], ss);
\r
3586 ximPieceBitmap[kind][piece] =
\r
3587 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3588 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3589 if (appData.debugMode)
\r
3590 fprintf(stderr, "(File:%s:) ", buf);
\r
3591 loadXIM(ximPieceBitmap[kind][piece],
\r
3593 &(xpmPieceBitmap[kind][piece]),
\r
3594 &(ximMaskPm[piece%(int)BlackPawn]));
\r
3596 fprintf(stderr," ");
\r
3598 /* Load light and dark squares */
\r
3599 /* If the LSQ and DSQ pieces don't exist, we will
\r
3600 draw them with solid squares. */
\r
3601 sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
\r
3602 if (access(buf, 0) != 0) {
\r
3606 fprintf(stderr, "light square ");
\r
3608 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3609 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3610 if (appData.debugMode)
\r
3611 fprintf(stderr, "(File:%s:) ", buf);
\r
3613 loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
\r
3614 fprintf(stderr, "dark square ");
\r
3615 sprintf(buf, "%s/dsq%u.xim",
\r
3616 ExpandPathName(appData.pixmapDirectory), ss);
\r
3617 if (appData.debugMode)
\r
3618 fprintf(stderr, "(File:%s:) ", buf);
\r
3620 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
\r
3621 0, 0, ss, ss, AllPlanes, XYPixmap);
\r
3622 loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
\r
3623 xpmJailSquare = xpmLightSquare;
\r
3625 fprintf(stderr, "Done.\n");
\r
3627 XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
\r
3631 void CreateXPMPieces()
\r
3633 int piece, kind, r;
\r
3634 char buf[MSG_SIZ];
\r
3635 u_int ss = squareSize;
\r
3636 XpmAttributes attr;
\r
3637 static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
\r
3638 XpmColorSymbol symbols[4];
\r
3641 /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */
\r
3642 if (appData.debugMode) {
\r
3643 fprintf(stderr, "XPM Library Version: %d.%d%c\n",
\r
3644 XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1));
\r
3648 /* The XSynchronize calls were copied from CreatePieces.
\r
3649 Not sure if needed, but can't hurt */
\r
3650 XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
\r
3652 /* Setup translations so piece colors match square colors */
\r
3653 symbols[0].name = "light_piece";
\r
3654 symbols[0].value = appData.whitePieceColor;
\r
3655 symbols[1].name = "dark_piece";
\r
3656 symbols[1].value = appData.blackPieceColor;
\r
3657 symbols[2].name = "light_square";
\r
3658 symbols[2].value = appData.lightSquareColor;
\r
3659 symbols[3].name = "dark_square";
\r
3660 symbols[3].value = appData.darkSquareColor;
\r
3662 attr.valuemask = XpmColorSymbols;
\r
3663 attr.colorsymbols = symbols;
\r
3664 attr.numsymbols = 4;
\r
3666 if (appData.monoMode) {
\r
3667 DisplayFatalError("XPM pieces cannot be used in monochrome mode",
\r
3671 if (strlen(appData.pixmapDirectory) == 0) {
\r
3672 XpmPieces* pieces = builtInXpms;
\r
3675 while (pieces->size != squareSize && pieces->size) pieces++;
\r
3676 if (!pieces->size) {
\r
3677 fprintf(stderr, "No builtin XPM pieces of size %d\n", squareSize);
\r
3680 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3681 for (kind=0; kind<4; kind++) {
\r
3683 if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
\r
3684 pieces->xpm[piece][kind],
\r
3685 &(xpmPieceBitmap[kind][piece]),
\r
3686 NULL, &attr)) != 0) {
\r
3687 fprintf(stderr, "Error %d loading XPM image \"%s\"\n",
\r
3694 xpmJailSquare = xpmLightSquare;
\r
3698 fprintf(stderr, "\nLoading XPMs...\n");
\r
3701 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3702 fprintf(stderr, "%d ", piece+1);
\r
3703 for (kind=0; kind<4; kind++) {
\r
3704 sprintf(buf, "%s/%c%s%u.xpm",
\r
3705 ExpandPathName(appData.pixmapDirectory),
\r
3706 ToLower(PieceToChar((ChessSquare)piece)),
\r
3707 xpmkind[kind], ss);
\r
3708 if (appData.debugMode) {
\r
3709 fprintf(stderr, "(File:%s:) ", buf);
\r
3711 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3712 &(xpmPieceBitmap[kind][piece]),
\r
3713 NULL, &attr)) != 0) {
\r
3714 fprintf(stderr, "Error %d loading XPM file \"%s\"\n",
\r
3720 /* Load light and dark squares */
\r
3721 /* If the LSQ and DSQ pieces don't exist, we will
\r
3722 draw them with solid squares. */
\r
3723 fprintf(stderr, "light square ");
\r
3724 sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
\r
3725 if (access(buf, 0) != 0) {
\r
3729 if (appData.debugMode)
\r
3730 fprintf(stderr, "(File:%s:) ", buf);
\r
3732 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3733 &xpmLightSquare, NULL, &attr)) != 0) {
\r
3734 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
\r
3737 fprintf(stderr, "dark square ");
\r
3738 sprintf(buf, "%s/dsq%u.xpm",
\r
3739 ExpandPathName(appData.pixmapDirectory), ss);
\r
3740 if (appData.debugMode) {
\r
3741 fprintf(stderr, "(File:%s:) ", buf);
\r
3743 if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
\r
3744 &xpmDarkSquare, NULL, &attr)) != 0) {
\r
3745 fprintf(stderr, "Error %d loading XPM file \"%s\"\n", r, buf);
\r
3749 xpmJailSquare = xpmLightSquare;
\r
3750 fprintf(stderr, "Done.\n");
\r
3752 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3755 #endif /* HAVE_LIBXPM */
\r
3758 /* No built-in bitmaps */
\r
3759 void CreatePieces()
\r
3762 char buf[MSG_SIZ];
\r
3763 u_int ss = squareSize;
\r
3765 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3768 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
\r
3769 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3770 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
\r
3771 ss, kind == SOLID ? 's' : 'o');
\r
3772 ReadBitmap(&pieceBitmap[kind][piece], buf, NULL, ss, ss);
\r
3776 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3780 /* With built-in bitmaps */
\r
3781 void CreatePieces()
\r
3783 BuiltInBits* bib = builtInBits;
\r
3785 char buf[MSG_SIZ];
\r
3786 u_int ss = squareSize;
\r
3788 XSynchronize(xDisplay, True); /* Work-around for xlib/xt
\r
3791 while (bib->squareSize != ss && bib->squareSize != 0) bib++;
\r
3793 for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
\r
3794 for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
\r
3795 sprintf(buf, "%c%u%c.bm", ToLower(PieceToChar((ChessSquare)piece)),
\r
3796 ss, kind == SOLID ? 's' : 'o');
\r
3797 ReadBitmap(&pieceBitmap[kind][piece], buf,
\r
3798 bib->bits[kind][piece], ss, ss);
\r
3802 XSynchronize(xDisplay, False); /* Work-around for xlib/xt
\r
3807 void ReadBitmap(pm, name, bits, wreq, hreq)
\r
3810 unsigned char bits[];
\r
3816 char msg[MSG_SIZ], fullname[MSG_SIZ];
\r
3818 if (*appData.bitmapDirectory != NULLCHAR) {
\r
3819 strcpy(fullname, appData.bitmapDirectory);
\r
3820 strcat(fullname, "/");
\r
3821 strcat(fullname, name);
\r
3822 errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
\r
3823 &w, &h, pm, &x_hot, &y_hot);
\r
3824 if (errcode != BitmapSuccess) {
\r
3825 switch (errcode) {
\r
3826 case BitmapOpenFailed:
\r
3827 sprintf(msg, "Can't open bitmap file %s", fullname);
\r
3829 case BitmapFileInvalid:
\r
3830 sprintf(msg, "Invalid bitmap in file %s", fullname);
\r
3832 case BitmapNoMemory:
\r
3833 sprintf(msg, "Ran out of memory reading bitmap file %s",
\r
3837 sprintf(msg, "Unknown XReadBitmapFile error %d on file %s",
\r
3838 errcode, fullname);
\r
3841 fprintf(stderr, "%s: %s...using built-in\n",
\r
3842 programName, msg);
\r
3843 } else if (w != wreq || h != hreq) {
\r
3845 "%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n",
\r
3846 programName, fullname, w, h, wreq, hreq);
\r
3851 if (bits == NULL) {
\r
3853 fprintf(stderr, "%s: No built-in bitmap for %s; giving up\n",
\r
3854 programName, name);
\r
3857 ; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
\r
3859 *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
\r
3868 if (lineGap == 0) return;
\r
3870 /* [HR] Split this into 2 loops for non-square boards. */
\r
3872 for (i = 0; i < BOARD_HEIGHT + 1; i++) {
\r
3873 gridSegments[i].x1 = 0;
\r
3874 gridSegments[i].x2 =
\r
3875 lineGap + BOARD_WIDTH * (squareSize + lineGap);
\r
3876 gridSegments[i].y1 = gridSegments[i].y2
\r
3877 = lineGap / 2 + (i * (squareSize + lineGap));
\r
3880 for (j = 0; j < BOARD_WIDTH + 1; j++) {
\r
3881 gridSegments[j + i].y1 = 0;
\r
3882 gridSegments[j + i].y2 =
\r
3883 lineGap + BOARD_HEIGHT * (squareSize + lineGap);
\r
3884 gridSegments[j + i].x1 = gridSegments[j + i].x2
\r
3885 = lineGap / 2 + (j * (squareSize + lineGap));
\r
3889 static void MenuBarSelect(w, addr, index)
\r
3894 XtActionProc proc = (XtActionProc) addr;
\r
3896 (proc)(NULL, NULL, NULL, NULL);
\r
3899 void CreateMenuBarPopup(parent, name, mb)
\r
3905 Widget menu, entry;
\r
3909 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
\r
3912 XtSetArg(args[j], XtNleftMargin, 20); j++;
\r
3913 XtSetArg(args[j], XtNrightMargin, 20); j++;
\r
3915 while (mi->string != NULL) {
\r
3916 if (strcmp(mi->string, "----") == 0) {
\r
3917 entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
\r
3920 entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
\r
3922 XtAddCallback(entry, XtNcallback,
\r
3923 (XtCallbackProc) MenuBarSelect,
\r
3924 (caddr_t) mi->proc);
\r
3930 Widget CreateMenuBar(mb)
\r
3934 Widget anchor, menuBar;
\r
3936 char menuName[MSG_SIZ];
\r
3939 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
\r
3940 XtSetArg(args[j], XtNvSpace, 0); j++;
\r
3941 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3942 menuBar = XtCreateWidget("menuBar", boxWidgetClass,
\r
3943 formWidget, args, j);
\r
3945 while (mb->name != NULL) {
\r
3946 strcpy(menuName, "menu");
\r
3947 strcat(menuName, mb->name);
\r
3949 XtSetArg(args[j], XtNmenuName, XtNewString(menuName)); j++;
\r
3951 char shortName[2];
\r
3952 shortName[0] = mb->name[0];
\r
3953 shortName[1] = NULLCHAR;
\r
3954 XtSetArg(args[j], XtNlabel, XtNewString(shortName)); j++;
\r
3956 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3957 anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
\r
3958 menuBar, args, j);
\r
3959 CreateMenuBarPopup(menuBar, menuName, mb);
\r
3965 Widget CreateButtonBar(mi)
\r
3969 Widget button, buttonBar;
\r
3973 XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++;
\r
3975 XtSetArg(args[j], XtNhSpace, 0); j++;
\r
3977 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3978 XtSetArg(args[j], XtNvSpace, 0); j++;
\r
3979 buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
\r
3980 formWidget, args, j);
\r
3982 while (mi->string != NULL) {
\r
3985 XtSetArg(args[j], XtNinternalWidth, 2); j++;
\r
3986 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
3988 button = XtCreateManagedWidget(mi->string, commandWidgetClass,
\r
3989 buttonBar, args, j);
\r
3990 XtAddCallback(button, XtNcallback,
\r
3991 (XtCallbackProc) MenuBarSelect,
\r
3992 (caddr_t) mi->proc);
\r
3999 CreatePieceMenu(name, color)
\r
4004 Widget entry, menu;
\r
4006 ChessSquare selection;
\r
4008 menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
\r
4009 boardWidget, args, 0);
\r
4011 for (i = 0; i < PIECE_MENU_SIZE; i++) {
\r
4012 String item = pieceMenuStrings[color][i];
\r
4014 if (strcmp(item, "----") == 0) {
\r
4015 entry = XtCreateManagedWidget(item, smeLineObjectClass,
\r
4018 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
\r
4020 selection = pieceMenuTranslation[color][i];
\r
4021 XtAddCallback(entry, XtNcallback,
\r
4022 (XtCallbackProc) PieceMenuSelect,
\r
4023 (caddr_t) selection);
\r
4024 if (selection == WhitePawn || selection == BlackPawn) {
\r
4025 XtSetArg(args[0], XtNpopupOnEntry, entry);
\r
4026 XtSetValues(menu, args, 1);
\r
4034 CreatePieceMenus()
\r
4039 ChessSquare selection;
\r
4041 whitePieceMenu = CreatePieceMenu("menuW", 0);
\r
4042 blackPieceMenu = CreatePieceMenu("menuB", 1);
\r
4044 XtRegisterGrabAction(PieceMenuPopup, True,
\r
4045 (unsigned)(ButtonPressMask|ButtonReleaseMask),
\r
4046 GrabModeAsync, GrabModeAsync);
\r
4048 XtSetArg(args[0], XtNlabel, "Drop");
\r
4049 dropMenu = XtCreatePopupShell("menuD", simpleMenuWidgetClass,
\r
4050 boardWidget, args, 1);
\r
4051 for (i = 0; i < DROP_MENU_SIZE; i++) {
\r
4052 String item = dropMenuStrings[i];
\r
4054 if (strcmp(item, "----") == 0) {
\r
4055 entry = XtCreateManagedWidget(item, smeLineObjectClass,
\r
4056 dropMenu, NULL, 0);
\r
4058 entry = XtCreateManagedWidget(item, smeBSBObjectClass,
\r
4059 dropMenu, NULL, 0);
\r
4060 selection = dropMenuTranslation[i];
\r
4061 XtAddCallback(entry, XtNcallback,
\r
4062 (XtCallbackProc) DropMenuSelect,
\r
4063 (caddr_t) selection);
\r
4068 void SetupDropMenu()
\r
4076 for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
\r
4077 entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
\r
4078 p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
\r
4079 dmEnables[i].piece);
\r
4080 XtSetSensitive(entry, p != NULL || !appData.testLegality
\r
4081 /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
\r
4082 && !appData.icsActive));
\r
4084 while (p && *p++ == dmEnables[i].piece) count++;
\r
4085 sprintf(label, "%s %d", dmEnables[i].widget, count);
\r
4087 XtSetArg(args[j], XtNlabel, label); j++;
\r
4088 XtSetValues(entry, args, j);
\r
4092 void PieceMenuPopup(w, event, params, num_params)
\r
4096 Cardinal *num_params;
\r
4099 if (event->type != ButtonPress) return;
\r
4100 if (errorUp) ErrorPopDown();
\r
4101 switch (gameMode) {
\r
4102 case EditPosition:
\r
4103 case IcsExamining:
\r
4104 whichMenu = params[0];
\r
4106 case IcsPlayingWhite:
\r
4107 case IcsPlayingBlack:
\r
4109 case MachinePlaysWhite:
\r
4110 case MachinePlaysBlack:
\r
4111 if (appData.testLegality &&
\r
4112 gameInfo.variant != VariantBughouse &&
\r
4113 gameInfo.variant != VariantCrazyhouse) return;
\r
4115 whichMenu = "menuD";
\r
4121 if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
\r
4122 ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
\r
4123 pmFromX = pmFromY = -1;
\r
4127 pmFromX = BOARD_WIDTH - 1 - pmFromX;
\r
4129 pmFromY = BOARD_HEIGHT - 1 - pmFromY;
\r
4131 XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
\r
4134 static void PieceMenuSelect(w, piece, junk)
\r
4136 ChessSquare piece;
\r
4139 if (pmFromX < 0 || pmFromY < 0) return;
\r
4140 EditPositionMenuEvent(piece, pmFromX, pmFromY);
\r
4143 static void DropMenuSelect(w, piece, junk)
\r
4145 ChessSquare piece;
\r
4148 if (pmFromX < 0 || pmFromY < 0) return;
\r
4149 DropMenuEvent(piece, pmFromX, pmFromY);
\r
4152 void WhiteClock(w, event, prms, nprms)
\r
4158 if (gameMode == EditPosition || gameMode == IcsExamining) {
\r
4159 SetWhiteToPlayEvent();
\r
4160 } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
\r
4165 void BlackClock(w, event, prms, nprms)
\r
4171 if (gameMode == EditPosition || gameMode == IcsExamining) {
\r
4172 SetBlackToPlayEvent();
\r
4173 } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
\r
4180 * If the user selects on a border boundary, return -1; if off the board,
\r
4181 * return -2. Otherwise map the event coordinate to the square.
\r
4183 int EventToSquare(x, limit)
\r
4191 if ((x % (squareSize + lineGap)) >= squareSize)
\r
4193 x /= (squareSize + lineGap);
\r
4199 static void do_flash_delay(msec)
\r
4200 unsigned long msec;
\r
4205 static void drawHighlight(file, rank, gc)
\r
4211 if (lineGap == 0 || appData.blindfold) return;
\r
4214 x = lineGap/2 + ((BOARD_WIDTH-1)-file) *
\r
4215 (squareSize + lineGap);
\r
4216 y = lineGap/2 + rank * (squareSize + lineGap);
\r
4218 x = lineGap/2 + file * (squareSize + lineGap);
\r
4219 y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) *
\r
4220 (squareSize + lineGap);
\r
4223 XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
\r
4224 squareSize+lineGap, squareSize+lineGap);
\r
4227 int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1;
\r
4228 int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1;
\r
4231 SetHighlights(fromX, fromY, toX, toY)
\r
4232 int fromX, fromY, toX, toY;
\r
4234 if (hi1X != fromX || hi1Y != fromY) {
\r
4235 if (hi1X >= 0 && hi1Y >= 0) {
\r
4236 drawHighlight(hi1X, hi1Y, lineGC);
\r
4238 if (fromX >= 0 && fromY >= 0) {
\r
4239 drawHighlight(fromX, fromY, highlineGC);
\r
4242 if (hi2X != toX || hi2Y != toY) {
\r
4243 if (hi2X >= 0 && hi2Y >= 0) {
\r
4244 drawHighlight(hi2X, hi2Y, lineGC);
\r
4246 if (toX >= 0 && toY >= 0) {
\r
4247 drawHighlight(toX, toY, highlineGC);
\r
4259 SetHighlights(-1, -1, -1, -1);
\r
4264 SetPremoveHighlights(fromX, fromY, toX, toY)
\r
4265 int fromX, fromY, toX, toY;
\r
4267 if (pm1X != fromX || pm1Y != fromY) {
\r
4268 if (pm1X >= 0 && pm1Y >= 0) {
\r
4269 drawHighlight(pm1X, pm1Y, lineGC);
\r
4271 if (fromX >= 0 && fromY >= 0) {
\r
4272 drawHighlight(fromX, fromY, prelineGC);
\r
4275 if (pm2X != toX || pm2Y != toY) {
\r
4276 if (pm2X >= 0 && pm2Y >= 0) {
\r
4277 drawHighlight(pm2X, pm2Y, lineGC);
\r
4279 if (toX >= 0 && toY >= 0) {
\r
4280 drawHighlight(toX, toY, prelineGC);
\r
4290 ClearPremoveHighlights()
\r
4292 SetPremoveHighlights(-1, -1, -1, -1);
\r
4295 static void BlankSquare(x, y, color, piece, dest)
\r
4297 ChessSquare piece;
\r
4300 if (useImages && useImageSqs) {
\r
4303 case 1: /* light */
\r
4304 pm = xpmLightSquare;
\r
4306 case 0: /* dark */
\r
4307 pm = xpmDarkSquare;
\r
4309 case 2: /* neutral */
\r
4311 pm = xpmJailSquare;
\r
4314 XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
\r
4315 squareSize, squareSize, x, y);
\r
4319 case 1: /* light */
\r
4320 gc = lightSquareGC;
\r
4322 case 0: /* dark */
\r
4323 gc = darkSquareGC;
\r
4325 case 2: /* neutral */
\r
4327 gc = jailSquareGC;
\r
4330 XFillRectangle(xDisplay, dest, gc, x, y, squareSize, squareSize);
\r
4335 I split out the routines to draw a piece so that I could
\r
4336 make a generic flash routine.
\r
4338 static void monoDrawPiece_1bit(piece, square_color, x, y, dest)
\r
4339 ChessSquare piece;
\r
4340 int square_color, x, y;
\r
4343 /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
\r
4344 switch (square_color) {
\r
4345 case 1: /* light */
\r
4346 case 2: /* neutral */
\r
4348 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
\r
4349 ? *pieceToOutline(piece)
\r
4350 : *pieceToSolid(piece),
\r
4351 dest, bwPieceGC, 0, 0,
\r
4352 squareSize, squareSize, x, y);
\r
4354 case 0: /* dark */
\r
4355 XCopyArea(xDisplay, (int) piece < (int) BlackPawn
\r
4356 ? *pieceToSolid(piece)
\r
4357 : *pieceToOutline(piece),
\r
4358 dest, wbPieceGC, 0, 0,
\r
4359 squareSize, squareSize, x, y);
\r
4364 static void monoDrawPiece(piece, square_color, x, y, dest)
\r
4365 ChessSquare piece;
\r
4366 int square_color, x, y;
\r
4369 switch (square_color) {
\r
4370 case 1: /* light */
\r
4371 case 2: /* neutral */
\r
4373 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
\r
4374 ? *pieceToOutline(piece)
\r
4375 : *pieceToSolid(piece),
\r
4376 dest, bwPieceGC, 0, 0,
\r
4377 squareSize, squareSize, x, y, 1);
\r
4379 case 0: /* dark */
\r
4380 XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
\r
4381 ? *pieceToSolid(piece)
\r
4382 : *pieceToOutline(piece),
\r
4383 dest, wbPieceGC, 0, 0,
\r
4384 squareSize, squareSize, x, y, 1);
\r
4389 static void colorDrawPiece(piece, square_color, x, y, dest)
\r
4390 ChessSquare piece;
\r
4391 int square_color, x, y;
\r
4394 if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
\r
4395 switch (square_color) {
\r
4396 case 1: /* light */
\r
4397 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4398 dest, (int) piece < (int) BlackPawn
\r
4399 ? wlPieceGC : blPieceGC, 0, 0,
\r
4400 squareSize, squareSize, x, y, 1);
\r
4402 case 0: /* dark */
\r
4403 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4404 dest, (int) piece < (int) BlackPawn
\r
4405 ? wdPieceGC : bdPieceGC, 0, 0,
\r
4406 squareSize, squareSize, x, y, 1);
\r
4408 case 2: /* neutral */
\r
4410 XCopyPlane(xDisplay, *pieceToSolid(piece),
\r
4411 dest, (int) piece < (int) BlackPawn
\r
4412 ? wjPieceGC : bjPieceGC, 0, 0,
\r
4413 squareSize, squareSize, x, y, 1);
\r
4418 static void colorDrawPieceImage(piece, square_color, x, y, dest)
\r
4419 ChessSquare piece;
\r
4420 int square_color, x, y;
\r
4425 switch (square_color) {
\r
4426 case 1: /* light */
\r
4427 case 2: /* neutral */
\r
4429 if ((int)piece < (int) BlackPawn) {
\r
4433 piece -= BlackPawn;
\r
4436 case 0: /* dark */
\r
4437 if ((int)piece < (int) BlackPawn) {
\r
4441 piece -= BlackPawn;
\r
4445 XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
\r
4446 dest, wlPieceGC, 0, 0,
\r
4447 squareSize, squareSize, x, y);
\r
4450 typedef void (*DrawFunc)();
\r
4452 DrawFunc ChooseDrawFunc()
\r
4454 if (appData.monoMode) {
\r
4455 if (DefaultDepth(xDisplay, xScreen) == 1) {
\r
4456 return monoDrawPiece_1bit;
\r
4458 return monoDrawPiece;
\r
4462 return colorDrawPieceImage;
\r
4464 return colorDrawPiece;
\r
4468 /* [HR] determine square color depending on chess variant. */
\r
4469 static int SquareColor(row, column)
\r
4474 if (gameInfo.variant == VariantXiangqi) {
\r
4475 if (column >= 3 && column <= 5 && row >= 0 && row <= 2) {
\r
4477 } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) {
\r
4479 } else if (row <= 4) {
\r
4485 square_color = ((column + row) % 2) == 1;
\r
4488 /* [hgm] holdings: next line makes all holdings squares light */
\r
4489 if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1;
\r
4491 return square_color;
\r
4494 void DrawSquare(row, column, piece, do_flash)
\r
4495 int row, column, do_flash;
\r
4496 ChessSquare piece;
\r
4498 int square_color, x, y, direction, font_ascent, font_descent;
\r
4501 XCharStruct overall;
\r
4502 DrawFunc drawfunc;
\r
4505 if(gameInfo.variant == VariantShogi) { // [HGM] shogi: in shogi Q is used for Lance
4506 if(piece == WhiteQueen) piece = WhiteLance; else
4507 if(piece == BlackQueen) piece = BlackLance;
4510 else if(gameInfo.variant == VariantGothic) { // [HGM] shogi: in Gothic Chancelor has alternative look
4511 if(piece == WhiteMarshall) piece = WhiteSilver; else
4512 if(piece == BlackMarshall) piece = BlackSilver;
4516 /* Calculate delay in milliseconds (2-delays per complete flash) */
\r
4517 flash_delay = 500 / appData.flashRate;
\r
4520 x = lineGap + ((BOARD_WIDTH-1)-column) *
\r
4521 (squareSize + lineGap);
\r
4522 y = lineGap + row * (squareSize + lineGap);
\r
4524 x = lineGap + column * (squareSize + lineGap);
\r
4525 y = lineGap + ((BOARD_HEIGHT-1)-row) *
\r
4526 (squareSize + lineGap);
\r
4529 square_color = SquareColor(row, column);
\r
4531 if ( // [HGM] holdings: blank out area between board and holdings
\r
4532 column == BOARD_LEFT-1 || column == BOARD_RGHT
\r
4533 || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize)
\r
4534 || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) {
\r
4535 BlankSquare(x, y, 2, EmptySquare, xBoardWindow);
4537 // [HGM] print piece counts next to holdings
4538 string[1] = NULLCHAR;
\r
4539 if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) {
\r
4540 string[0] = '0' + piece;
\r
4541 XTextExtents(countFontStruct, string, 1, &direction,
\r
4542 &font_ascent, &font_descent, &overall);
\r
4543 if (appData.monoMode) {
\r
4544 XDrawImageString(xDisplay, xBoardWindow, countGC,
\r
4545 x + squareSize - overall.width - 2,
\r
4546 y + font_ascent + 1, string, 1);
\r
4548 XDrawString(xDisplay, xBoardWindow, countGC,
\r
4549 x + squareSize - overall.width - 2,
\r
4550 y + font_ascent + 1, string, 1);
\r
4553 if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) {
\r
4554 string[0] = '0' + piece;
\r
4555 XTextExtents(countFontStruct, string, 1, &direction,
\r
4556 &font_ascent, &font_descent, &overall);
\r
4557 if (appData.monoMode) {
\r
4558 XDrawImageString(xDisplay, xBoardWindow, countGC,
\r
4559 x + 2, y + font_ascent + 1, string, 1);
\r
4561 XDrawString(xDisplay, xBoardWindow, countGC,
\r
4562 x + 2, y + font_ascent + 1, string, 1);
\r
4566 if (piece == EmptySquare || appData.blindfold) {
\r
4567 BlankSquare(x, y, square_color, piece, xBoardWindow);
\r
4569 drawfunc = ChooseDrawFunc();
\r
4570 if (do_flash && appData.flashCount > 0) {
\r
4571 for (i=0; i<appData.flashCount; ++i) {
\r
4573 drawfunc(piece, square_color, x, y, xBoardWindow);
\r
4574 XSync(xDisplay, False);
\r
4575 do_flash_delay(flash_delay);
\r
4577 BlankSquare(x, y, square_color, piece, xBoardWindow);
\r
4578 XSync(xDisplay, False);
\r
4579 do_flash_delay(flash_delay);
\r
4582 drawfunc(piece, square_color, x, y, xBoardWindow);
\r
4586 string[1] = NULLCHAR;
\r
4587 if (appData.showCoords && row == (flipView ? BOARD_HEIGHT-1 : 0)
4588 && column >= BOARD_LEFT && column < BOARD_RGHT) {
\r
4589 string[0] = 'a' + column - BOARD_LEFT;
\r
4590 XTextExtents(coordFontStruct, string, 1, &direction,
\r
4591 &font_ascent, &font_descent, &overall);
\r
4592 if (appData.monoMode) {
\r
4593 XDrawImageString(xDisplay, xBoardWindow, coordGC,
\r
4594 x + squareSize - overall.width - 2,
\r
4595 y + squareSize - font_descent - 1, string, 1);
\r
4597 XDrawString(xDisplay, xBoardWindow, coordGC,
\r
4598 x + squareSize - overall.width - 2,
\r
4599 y + squareSize - font_descent - 1, string, 1);
\r
4602 if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) {
\r
4603 string[0] = ONE + row;
\r
4604 XTextExtents(coordFontStruct, string, 1, &direction,
\r
4605 &font_ascent, &font_descent, &overall);
\r
4606 if (appData.monoMode) {
\r
4607 XDrawImageString(xDisplay, xBoardWindow, coordGC,
\r
4608 x + 2, y + font_ascent + 1, string, 1);
\r
4610 XDrawString(xDisplay, xBoardWindow, coordGC,
\r
4611 x + 2, y + font_ascent + 1, string, 1);
\r
4617 /* Why is this needed on some versions of X? */
\r
4618 void EventProc(widget, unused, event)
\r
4623 if (!XtIsRealized(widget))
\r
4626 switch (event->type) {
\r
4628 if (event->xexpose.count > 0) return; /* no clipping is done */
\r
4629 XDrawPosition(widget, True, NULL);
\r
4637 void DrawPosition(fullRedraw, board)
\r
4638 /*Boolean*/int fullRedraw;
\r
4641 XDrawPosition(boardWidget, fullRedraw, board);
\r
4644 /* Returns 1 if there are "too many" differences between b1 and b2
\r
4645 (i.e. more than 1 move was made) */
\r
4646 static int too_many_diffs(b1, b2)
\r
4652 for (i=0; i<BOARD_HEIGHT; ++i) {
\r
4653 for (j=0; j<BOARD_WIDTH; ++j) {
\r
4654 if (b1[i][j] != b2[i][j]) {
\r
4655 if (++c > 4) /* Castling causes 4 diffs */
\r
4664 /* Matrix describing castling maneuvers */
\r
4665 /* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */
\r
4666 static int castling_matrix[4][5] = {
\r
4667 { 0, 0, 4, 3, 2 }, /* 0-0-0, white */
\r
4668 { 0, 7, 4, 5, 6 }, /* 0-0, white */
\r
4669 { 7, 0, 4, 3, 2 }, /* 0-0-0, black */
\r
4670 { 7, 7, 4, 5, 6 } /* 0-0, black */
\r
4673 /* Checks whether castling occurred. If it did, *rrow and *rcol
\r
4674 are set to the destination (row,col) of the rook that moved.
\r
4676 Returns 1 if castling occurred, 0 if not.
\r
4678 Note: Only handles a max of 1 castling move, so be sure
\r
4679 to call too_many_diffs() first.
\r
4681 static int check_castle_draw(newb, oldb, rrow, rcol)
\r
4688 /* For each type of castling... */
\r
4689 for (i=0; i<4; ++i) {
\r
4690 r = castling_matrix[i];
\r
4692 /* Check the 4 squares involved in the castling move */
\r
4694 for (j=1; j<=4; ++j) {
\r
4695 if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) {
\r
4702 /* All 4 changed, so it must be a castling move */
\r
4711 static int damage[BOARD_SIZE][BOARD_SIZE];
\r
4714 * event handler for redrawing the board
\r
4716 void XDrawPosition(w, repaint, board)
\r
4718 /*Boolean*/int repaint;
\r
4721 int i, j, do_flash;
\r
4722 static int lastFlipView = 0;
\r
4723 static int lastBoardValid = 0;
\r
4724 static Board lastBoard;
\r
4728 if (board == NULL) {
\r
4729 if (!lastBoardValid) return;
\r
4730 board = lastBoard;
\r
4732 if (!lastBoardValid || lastFlipView != flipView) {
\r
4733 XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
\r
4734 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
\r
4739 * It would be simpler to clear the window with XClearWindow()
\r
4740 * but this causes a very distracting flicker.
\r
4743 if (!repaint && lastBoardValid && lastFlipView == flipView) {
\r
4745 /* If too much changes (begin observing new game, etc.), don't
\r
4747 do_flash = too_many_diffs(board, lastBoard) ? 0 : 1;
\r
4749 /* Special check for castling so we don't flash both the king
\r
4750 and the rook (just flash the king). */
\r
4752 if (check_castle_draw(board, lastBoard, &rrow, &rcol)) {
\r
4753 /* Draw rook with NO flashing. King will be drawn flashing later */
\r
4754 DrawSquare(rrow, rcol, board[rrow][rcol], 0);
\r
4755 lastBoard[rrow][rcol] = board[rrow][rcol];
\r
4759 /* First pass -- Draw (newly) empty squares and repair damage.
\r
4760 This prevents you from having a piece show up twice while it
\r
4761 is flashing on its new square */
\r
4762 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4763 for (j = 0; j < BOARD_WIDTH; j++)
\r
4764 if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
\r
4765 || damage[i][j]) {
\r
4766 DrawSquare(i, j, board[i][j], 0);
\r
4767 damage[i][j] = False;
\r
4770 /* Second pass -- Draw piece(s) in new position and flash them */
\r
4771 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4772 for (j = 0; j < BOARD_WIDTH; j++)
\r
4773 if (board[i][j] != lastBoard[i][j]) {
\r
4774 DrawSquare(i, j, board[i][j], do_flash);
\r
4778 XDrawSegments(xDisplay, xBoardWindow, lineGC,
\r
4779 gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
\r
4781 for (i = 0; i < BOARD_HEIGHT; i++)
\r
4782 for (j = 0; j < BOARD_WIDTH; j++) {
\r
4783 DrawSquare(i, j, board[i][j], 0);
\r
4784 damage[i][j] = False;
\r
4788 CopyBoard(lastBoard, board);
\r
4789 lastBoardValid = 1;
\r
4790 lastFlipView = flipView;
\r
4792 /* Draw highlights */
\r
4793 if (pm1X >= 0 && pm1Y >= 0) {
\r
4794 drawHighlight(pm1X, pm1Y, prelineGC);
\r
4796 if (pm2X >= 0 && pm2Y >= 0) {
\r
4797 drawHighlight(pm2X, pm2Y, prelineGC);
\r
4799 if (hi1X >= 0 && hi1Y >= 0) {
\r
4800 drawHighlight(hi1X, hi1Y, highlineGC);
\r
4802 if (hi2X >= 0 && hi2Y >= 0) {
\r
4803 drawHighlight(hi2X, hi2Y, highlineGC);
\r
4806 /* If piece being dragged around board, must redraw that too */
\r
4809 XSync(xDisplay, False);
\r
4814 * event handler for redrawing the board
\r
4816 void DrawPositionProc(w, event, prms, nprms)
\r
4822 XDrawPosition(w, True, NULL);
\r
4827 * event handler for parsing user moves
\r
4829 // [HGM] This routine will need quite some reworking. Although the backend still supports the old
\r
4830 // way of doing things, by calling UserMoveEvent() to test the legality of the move and then perform
\r
4831 // it at the end, and doing all kind of preliminary tests here (e.g. to weed out self-captures), it
\r
4832 // should be made to use the new way, of calling UserMoveTest early to determine the legality of the
\r
4833 // move, (which will weed out the illegal selfcaptures and moves into the holdings, and flag promotions),
\r
4834 // and at the end FinishMove() to perform the move after optional promotion popups.
\r
4835 // For now I patched it to allow self-capture with King, and suppress clicks between board and holdings.
\r
4836 void HandleUserMove(w, event, prms, nprms)
\r
4843 Boolean saveAnimate;
\r
4844 static int second = 0;
\r
4846 if (w != boardWidget || errorExitStatus != -1) return;
\r
4848 if (event->type == ButtonPress) ErrorPopDown();
\r
4850 if (promotionUp) {
\r
4851 if (event->type == ButtonPress) {
\r
4852 XtPopdown(promotionShell);
\r
4853 XtDestroyWidget(promotionShell);
\r
4854 promotionUp = False;
\r
4855 ClearHighlights();
\r
4856 fromX = fromY = -1;
\r
4862 x = EventToSquare(event->xbutton.x, BOARD_WIDTH);
\r
4863 y = EventToSquare(event->xbutton.y, BOARD_HEIGHT);
\r
4864 if (!flipView && y >= 0) {
\r
4865 y = BOARD_HEIGHT - 1 - y;
\r
4867 if (flipView && x >= 0) {
\r
4868 x = BOARD_WIDTH - 1 - x;
\r
4871 /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
\r
4872 if(event->type == ButtonPress
\r
4873 && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
\r
4874 || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
\r
4875 || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
\r
4878 if (fromX == -1) {
\r
4879 if (event->type == ButtonPress) {
\r
4880 /* First square */
\r
4881 if (OKToStartUserMove(x, y)) {
\r
4885 DragPieceBegin(event->xbutton.x, event->xbutton.y);
\r
4886 if (appData.highlightDragging) {
\r
4887 SetHighlights(x, y, -1, -1);
\r
4895 if (event->type == ButtonPress && gameMode != EditPosition &&
\r
4896 x >= 0 && y >= 0) {
\r
4897 ChessSquare fromP;
\r
4900 /* Check if clicking again on the same color piece */
\r
4901 fromP = boards[currentMove][fromY][fromX];
\r
4902 toP = boards[currentMove][y][x];
\r
4903 if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it.
\r
4904 WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King
\r
4905 (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings.
\r
4906 BlackPawn <= toP && toP <= BlackKing)) {
\r
4907 /* Clicked again on same color piece -- changed his mind */
\r
4908 second = (x == fromX && y == fromY);
\r
4909 if (appData.highlightDragging) {
\r
4910 SetHighlights(x, y, -1, -1);
\r
4912 ClearHighlights();
\r
4914 if (OKToStartUserMove(x, y)) {
\r
4917 DragPieceBegin(event->xbutton.x, event->xbutton.y);
\r
4923 if (event->type == ButtonRelease && x == fromX && y == fromY) {
\r
4924 DragPieceEnd(event->xbutton.x, event->xbutton.y);
\r
4925 if (appData.animateDragging) {
\r
4926 /* Undo animation damage if any */
\r
4927 DrawPosition(FALSE, NULL);
\r
4930 /* Second up/down in same square; just abort move */
\r
4932 fromX = fromY = -1;
\r
4933 ClearHighlights();
\r
4935 ClearPremoveHighlights();
\r
4937 /* First upclick in same square; start click-click mode */
\r
4938 SetHighlights(x, y, -1, -1);
\r
4943 /* Completed move */
\r
4946 saveAnimate = appData.animate;
\r
4947 if (event->type == ButtonPress) {
\r
4948 /* Finish clickclick move */
\r
4949 if (appData.animate || appData.highlightLastMove) {
\r
4950 SetHighlights(fromX, fromY, toX, toY);
\r
4952 ClearHighlights();
\r
4955 /* Finish drag move */
\r
4956 if (appData.highlightLastMove) {
\r
4957 SetHighlights(fromX, fromY, toX, toY);
\r
4959 ClearHighlights();
\r
4961 DragPieceEnd(event->xbutton.x, event->xbutton.y);
\r
4962 /* Don't animate move and drag both */
\r
4963 appData.animate = FALSE;
\r
4965 if (IsPromotion(fromX, fromY, toX, toY)) {
\r
4966 if (appData.alwaysPromoteToQueen) {
\r
4967 UserMoveEvent(fromX, fromY, toX, toY, 'q');
\r
4968 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
4969 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
4970 fromX = fromY = -1;
\r
4972 SetHighlights(fromX, fromY, toX, toY);
\r
4976 UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
\r
4977 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
4978 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
4979 fromX = fromY = -1;
\r
4981 appData.animate = saveAnimate;
\r
4982 if (appData.animate || appData.animateDragging) {
\r
4983 /* Undo animation damage if needed */
\r
4984 DrawPosition(FALSE, NULL);
\r
4988 void AnimateUserMove (Widget w, XEvent * event,
\r
4989 String * params, Cardinal * nParams)
\r
4991 DragPieceMove(event->xmotion.x, event->xmotion.y);
\r
4994 Widget CommentCreate(name, text, mutable, callback, lines)
\r
4995 char *name, *text;
\r
4996 int /*Boolean*/ mutable;
\r
4997 XtCallbackProc callback;
\r
5001 Widget shell, layout, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
\r
5002 Dimension bw_width;
\r
5006 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
5007 XtGetValues(boardWidget, args, j);
\r
5010 XtSetArg(args[j], XtNresizable, True); j++;
\r
5013 XtCreatePopupShell(name, topLevelShellWidgetClass,
\r
5014 shellWidget, args, j);
\r
5017 XtCreatePopupShell(name, transientShellWidgetClass,
\r
5018 shellWidget, args, j);
\r
5021 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
\r
5022 layoutArgs, XtNumber(layoutArgs));
\r
5024 XtCreateManagedWidget("form", formWidgetClass, layout,
\r
5025 formArgs, XtNumber(formArgs));
\r
5029 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
\r
5030 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
\r
5032 XtSetArg(args[j], XtNstring, text); j++;
\r
5033 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
5034 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5035 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5036 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r
5037 XtSetArg(args[j], XtNresizable, True); j++;
\r
5038 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
\r
5040 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
\r
5042 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
\r
5043 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
\r
5045 XtSetArg(args[j], XtNautoFill, True); j++;
\r
5046 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
\r
5048 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
\r
5052 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5053 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5054 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5055 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5056 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5058 XtCreateManagedWidget("ok", commandWidgetClass, form, args, j);
\r
5059 XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
\r
5062 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5063 XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
\r
5064 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5065 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5066 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5067 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5069 XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);
\r
5070 XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
\r
5073 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5074 XtSetArg(args[j], XtNfromHoriz, b_cancel); j++;
\r
5075 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5076 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5077 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5078 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5080 XtCreateManagedWidget("clear", commandWidgetClass, form, args, j);
\r
5081 XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
\r
5084 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5085 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5086 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5087 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5088 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5090 XtCreateManagedWidget("close", commandWidgetClass, form, args, j);
\r
5091 XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
\r
5094 XtSetArg(args[j], XtNfromVert, edit); j++;
\r
5095 XtSetArg(args[j], XtNfromHoriz, b_close); j++;
\r
5096 XtSetArg(args[j], XtNtop, XtChainBottom); j++;
\r
5097 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5098 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5099 XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r
5101 XtCreateManagedWidget("edit", commandWidgetClass, form, args, j);
\r
5102 XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
\r
5105 XtRealizeWidget(shell);
\r
5107 if (commentX == -1) {
\r
5110 Dimension pw_height;
\r
5111 Dimension ew_height;
\r
5114 XtSetArg(args[j], XtNheight, &ew_height); j++;
\r
5115 XtGetValues(edit, args, j);
\r
5118 XtSetArg(args[j], XtNheight, &pw_height); j++;
\r
5119 XtGetValues(shell, args, j);
\r
5120 commentH = pw_height + (lines - 1) * ew_height;
\r
5121 commentW = bw_width - 16;
\r
5123 XSync(xDisplay, False);
\r
5125 /* This code seems to tickle an X bug if it is executed too soon
\r
5126 after xboard starts up. The coordinates get transformed as if
\r
5127 the main window was positioned at (0, 0).
\r
5129 XtTranslateCoords(shellWidget,
\r
5130 (bw_width - commentW) / 2, 0 - commentH / 2,
\r
5131 &commentX, &commentY);
\r
5133 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
\r
5134 RootWindowOfScreen(XtScreen(shellWidget)),
\r
5135 (bw_width - commentW) / 2, 0 - commentH / 2,
\r
5139 #endif /*!NOTDEF*/
\r
5140 if (commentY < 0) commentY = 0; /*avoid positioning top offscreen*/
\r
5143 XtSetArg(args[j], XtNheight, commentH); j++;
\r
5144 XtSetArg(args[j], XtNwidth, commentW); j++;
\r
5145 XtSetArg(args[j], XtNx, commentX); j++;
\r
5146 XtSetArg(args[j], XtNy, commentY); j++;
\r
5147 XtSetValues(shell, args, j);
\r
5148 XtSetKeyboardFocus(shell, edit);
\r
5153 /* Used for analysis window and ICS input window */
\r
5154 Widget MiscCreate(name, text, mutable, callback, lines)
\r
5155 char *name, *text;
\r
5156 int /*Boolean*/ mutable;
\r
5157 XtCallbackProc callback;
\r
5161 Widget shell, layout, form, edit;
\r
5163 Dimension bw_width, pw_height, ew_height, w, h;
\r
5169 XtSetArg(args[j], XtNresizable, True); j++;
\r
5172 XtCreatePopupShell(name, topLevelShellWidgetClass,
\r
5173 shellWidget, args, j);
\r
5176 XtCreatePopupShell(name, transientShellWidgetClass,
\r
5177 shellWidget, args, j);
\r
5180 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
\r
5181 layoutArgs, XtNumber(layoutArgs));
\r
5183 XtCreateManagedWidget("form", formWidgetClass, layout,
\r
5184 formArgs, XtNumber(formArgs));
\r
5188 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
\r
5189 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
\r
5191 XtSetArg(args[j], XtNstring, text); j++;
\r
5192 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
5193 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
5194 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
5195 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r
5196 XtSetArg(args[j], XtNresizable, True); j++;
\r
5198 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
\r
5200 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
\r
5201 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
\r
5203 XtSetArg(args[j], XtNautoFill, True); j++;
\r
5204 XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
\r
5206 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
\r
5208 XtRealizeWidget(shell);
\r
5211 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
5212 XtGetValues(boardWidget, args, j);
\r
5215 XtSetArg(args[j], XtNheight, &ew_height); j++;
\r
5216 XtGetValues(edit, args, j);
\r
5219 XtSetArg(args[j], XtNheight, &pw_height); j++;
\r
5220 XtGetValues(shell, args, j);
\r
5221 h = pw_height + (lines - 1) * ew_height;
\r
5222 w = bw_width - 16;
\r
5224 XSync(xDisplay, False);
\r
5226 /* This code seems to tickle an X bug if it is executed too soon
\r
5227 after xboard starts up. The coordinates get transformed as if
\r
5228 the main window was positioned at (0, 0).
\r
5230 XtTranslateCoords(shellWidget, (bw_width - w) / 2, 0 - h / 2, &x, &y);
\r
5232 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
\r
5233 RootWindowOfScreen(XtScreen(shellWidget)),
\r
5234 (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
\r
5235 #endif /*!NOTDEF*/
\r
5238 if (y < 0) y = 0; /*avoid positioning top offscreen*/
\r
5241 XtSetArg(args[j], XtNheight, h); j++;
\r
5242 XtSetArg(args[j], XtNwidth, w); j++;
\r
5243 XtSetArg(args[j], XtNx, x); j++;
\r
5244 XtSetArg(args[j], XtNy, y); j++;
\r
5245 XtSetValues(shell, args, j);
\r
5251 static int savedIndex; /* gross that this is global */
\r
5253 void EditCommentPopUp(index, title, text)
\r
5255 char *title, *text;
\r
5261 savedIndex = index;
\r
5262 if (text == NULL) text = "";
\r
5264 if (editShell == NULL) {
\r
5266 CommentCreate(title, text, True, EditCommentCallback, 4);
\r
5267 XtRealizeWidget(editShell);
\r
5268 CatchDeleteWindow(editShell, "EditCommentPopDown");
\r
5270 edit = XtNameToWidget(editShell, "*form.text");
\r
5272 XtSetArg(args[j], XtNstring, text); j++;
\r
5273 XtSetValues(edit, args, j);
\r
5275 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5276 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5277 XtSetValues(editShell, args, j);
\r
5280 XtPopup(editShell, XtGrabNone);
\r
5284 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
\r
5285 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
\r
5289 void EditCommentCallback(w, client_data, call_data)
\r
5291 XtPointer client_data, call_data;
\r
5299 XtSetArg(args[j], XtNlabel, &name); j++;
\r
5300 XtGetValues(w, args, j);
\r
5302 if (strcmp(name, "ok") == 0) {
\r
5303 edit = XtNameToWidget(editShell, "*form.text");
\r
5305 XtSetArg(args[j], XtNstring, &val); j++;
\r
5306 XtGetValues(edit, args, j);
\r
5307 ReplaceComment(savedIndex, val);
\r
5308 EditCommentPopDown();
\r
5309 } else if (strcmp(name, "cancel") == 0) {
\r
5310 EditCommentPopDown();
\r
5311 } else if (strcmp(name, "clear") == 0) {
\r
5312 edit = XtNameToWidget(editShell, "*form.text");
\r
5313 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
\r
5314 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
\r
5318 void EditCommentPopDown()
\r
5323 if (!editUp) return;
\r
5325 XtSetArg(args[j], XtNx, &commentX); j++;
\r
5326 XtSetArg(args[j], XtNy, &commentY); j++;
\r
5327 XtSetArg(args[j], XtNheight, &commentH); j++;
\r
5328 XtSetArg(args[j], XtNwidth, &commentW); j++;
\r
5329 XtGetValues(editShell, args, j);
\r
5330 XtPopdown(editShell);
\r
5333 XtSetArg(args[j], XtNleftBitmap, None); j++;
\r
5334 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Edit Comment"),
\r
5338 void ICSInputBoxPopUp()
\r
5343 char *title = "ICS Input";
\r
5344 XtTranslations tr;
\r
5346 if (ICSInputShell == NULL) {
\r
5347 ICSInputShell = MiscCreate(title, "", True, NULL, 1);
\r
5348 tr = XtParseTranslationTable(ICSInputTranslations);
\r
5349 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5350 XtOverrideTranslations(edit, tr);
\r
5351 XtRealizeWidget(ICSInputShell);
\r
5352 CatchDeleteWindow(ICSInputShell, "ICSInputBoxPopDown");
\r
5355 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5357 XtSetArg(args[j], XtNstring, ""); j++;
\r
5358 XtSetValues(edit, args, j);
\r
5360 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5361 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5362 XtSetValues(ICSInputShell, args, j);
\r
5365 XtPopup(ICSInputShell, XtGrabNone);
\r
5366 XtSetKeyboardFocus(ICSInputShell, edit);
\r
5368 ICSInputBoxUp = True;
\r
5370 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
\r
5371 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
\r
5375 void ICSInputSendText()
\r
5382 edit = XtNameToWidget(ICSInputShell, "*form.text");
\r
5384 XtSetArg(args[j], XtNstring, &val); j++;
\r
5385 XtGetValues(edit, args, j);
\r
5386 SendMultiLineToICS(val);
\r
5387 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
\r
5388 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
\r
5391 void ICSInputBoxPopDown()
\r
5396 if (!ICSInputBoxUp) return;
\r
5398 XtPopdown(ICSInputShell);
\r
5399 ICSInputBoxUp = False;
\r
5401 XtSetArg(args[j], XtNleftBitmap, None); j++;
\r
5402 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.ICS Input Box"),
\r
5406 void CommentPopUp(title, text)
\r
5407 char *title, *text;
\r
5413 if (commentShell == NULL) {
\r
5415 CommentCreate(title, text, False, CommentCallback, 4);
\r
5416 XtRealizeWidget(commentShell);
\r
5417 CatchDeleteWindow(commentShell, "CommentPopDown");
\r
5419 edit = XtNameToWidget(commentShell, "*form.text");
\r
5421 XtSetArg(args[j], XtNstring, text); j++;
\r
5422 XtSetValues(edit, args, j);
\r
5424 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5425 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5426 XtSetValues(commentShell, args, j);
\r
5429 XtPopup(commentShell, XtGrabNone);
\r
5430 XSync(xDisplay, False);
\r
5435 void AnalysisPopUp(title, text)
\r
5436 char *title, *text;
\r
5442 if (analysisShell == NULL) {
\r
5443 analysisShell = MiscCreate(title, text, False, NULL, 4);
\r
5444 XtRealizeWidget(analysisShell);
\r
5445 CatchDeleteWindow(analysisShell, "AnalysisPopDown");
\r
5448 edit = XtNameToWidget(analysisShell, "*form.text");
\r
5450 XtSetArg(args[j], XtNstring, text); j++;
\r
5451 XtSetValues(edit, args, j);
\r
5453 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
5454 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
5455 XtSetValues(analysisShell, args, j);
\r
5458 if (!analysisUp) {
\r
5459 XtPopup(analysisShell, XtGrabNone);
\r
5461 XSync(xDisplay, False);
\r
5463 analysisUp = True;
\r
5466 void CommentCallback(w, client_data, call_data)
\r
5468 XtPointer client_data, call_data;
\r
5475 XtSetArg(args[j], XtNlabel, &name); j++;
\r
5476 XtGetValues(w, args, j);
\r
5478 if (strcmp(name, "close") == 0) {
\r
5480 } else if (strcmp(name, "edit") == 0) {
\r
5482 EditCommentEvent();
\r
5487 void CommentPopDown()
\r
5492 if (!commentUp) return;
\r
5494 XtSetArg(args[j], XtNx, &commentX); j++;
\r
5495 XtSetArg(args[j], XtNy, &commentY); j++;
\r
5496 XtSetArg(args[j], XtNwidth, &commentW); j++;
\r
5497 XtSetArg(args[j], XtNheight, &commentH); j++;
\r
5498 XtGetValues(commentShell, args, j);
\r
5499 XtPopdown(commentShell);
\r
5500 XSync(xDisplay, False);
\r
5501 commentUp = False;
\r
5504 void AnalysisPopDown()
\r
5506 if (!analysisUp) return;
\r
5507 XtPopdown(analysisShell);
\r
5508 XSync(xDisplay, False);
\r
5509 analysisUp = False;
\r
5513 void FileNamePopUp(label, def, proc, openMode)
\r
5520 Widget popup, layout, dialog, edit;
\r
5521 Window root, child;
\r
5524 unsigned int mask;
\r
5526 fileProc = proc; /* I can't see a way not */
\r
5527 fileOpenMode = openMode; /* to use globals here */
\r
5530 XtSetArg(args[i], XtNresizable, True); i++;
\r
5531 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
\r
5532 fileNameShell = popup =
\r
5533 XtCreatePopupShell("File name prompt", transientShellWidgetClass,
\r
5534 shellWidget, args, i);
\r
5537 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
\r
5538 layoutArgs, XtNumber(layoutArgs));
\r
5541 XtSetArg(args[i], XtNlabel, label); i++;
\r
5542 XtSetArg(args[i], XtNvalue, def); i++;
\r
5543 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
5544 dialog = XtCreateManagedWidget("fileName", dialogWidgetClass,
\r
5547 XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
\r
5548 XawDialogAddButton(dialog, "cancel", FileNameCallback,
\r
5549 (XtPointer) dialog);
\r
5551 XtRealizeWidget(popup);
\r
5552 CatchDeleteWindow(popup, "FileNamePopDown");
\r
5554 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
\r
5555 &x, &y, &win_x, &win_y, &mask);
\r
5557 XtSetArg(args[0], XtNx, x - 10);
\r
5558 XtSetArg(args[1], XtNy, y - 30);
\r
5559 XtSetValues(popup, args, 2);
\r
5561 XtPopup(popup, XtGrabExclusive);
\r
5562 filenameUp = True;
\r
5564 edit = XtNameToWidget(dialog, "*value");
\r
5565 XtSetKeyboardFocus(popup, edit);
\r
5568 void FileNamePopDown()
\r
5570 if (!filenameUp) return;
\r
5571 XtPopdown(fileNameShell);
\r
5572 XtDestroyWidget(fileNameShell);
\r
5573 filenameUp = False;
\r
5577 void FileNameCallback(w, client_data, call_data)
\r
5579 XtPointer client_data, call_data;
\r
5584 XtSetArg(args[0], XtNlabel, &name);
\r
5585 XtGetValues(w, args, 1);
\r
5587 if (strcmp(name, "cancel") == 0) {
\r
5588 FileNamePopDown();
\r
5592 FileNameAction(w, NULL, NULL, NULL);
\r
5595 void FileNameAction(w, event, prms, nprms)
\r
5601 char buf[MSG_SIZ];
\r
5604 char *p, *fullname;
\r
5607 name = XawDialogGetValueString(w = XtParent(w));
\r
5609 if ((name != NULL) && (*name != NULLCHAR)) {
\r
5610 strcpy(buf, name);
\r
5611 XtPopdown(w = XtParent(XtParent(w)));
\r
5612 XtDestroyWidget(w);
\r
5613 filenameUp = False;
\r
5615 p = strrchr(buf, ' ');
\r
5622 fullname = ExpandPathName(buf);
\r
5624 ErrorPopUp("Error", "Can't open file", FALSE);
\r
5627 f = fopen(fullname, fileOpenMode);
\r
5629 DisplayError("Failed to open file", errno);
\r
5631 (void) (*fileProc)(f, index, buf);
\r
5638 XtPopdown(w = XtParent(XtParent(w)));
\r
5639 XtDestroyWidget(w);
\r
5640 filenameUp = False;
\r
5644 void PromotionPopUp()
\r
5647 Widget dialog, layout;
\r
5649 Dimension bw_width, pw_width;
\r
5653 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r
5654 XtGetValues(boardWidget, args, j);
\r
5657 XtSetArg(args[j], XtNresizable, True); j++;
\r
5659 XtCreatePopupShell("Promotion", transientShellWidgetClass,
\r
5660 shellWidget, args, j);
\r
5662 XtCreateManagedWidget(layoutName, formWidgetClass, promotionShell,
\r
5663 layoutArgs, XtNumber(layoutArgs));
\r
5666 XtSetArg(args[j], XtNlabel, "Promote pawn to what?"); j++;
\r
5667 XtSetArg(args[j], XtNborderWidth, 0); j++;
\r
5668 dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
\r
5671 XawDialogAddButton(dialog, "Queen", PromotionCallback,
\r
5672 (XtPointer) dialog);
\r
5673 XawDialogAddButton(dialog, "Rook", PromotionCallback,
\r
5674 (XtPointer) dialog);
\r
5675 XawDialogAddButton(dialog, "Bishop", PromotionCallback,
\r
5676 (XtPointer) dialog);
\r
5677 XawDialogAddButton(dialog, "Knight", PromotionCallback,
\r
5678 (XtPointer) dialog);
\r
5679 if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
\r
5680 gameInfo.variant == VariantGiveaway) {
\r
5681 XawDialogAddButton(dialog, "King", PromotionCallback,
\r
5682 (XtPointer) dialog);
\r
5684 XawDialogAddButton(dialog, "cancel", PromotionCallback,
\r
5685 (XtPointer) dialog);
\r
5687 XtRealizeWidget(promotionShell);
\r
5688 CatchDeleteWindow(promotionShell, "PromotionPopDown");
\r
5691 XtSetArg(args[j], XtNwidth, &pw_width); j++;
\r
5692 XtGetValues(promotionShell, args, j);
\r
5694 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
\r
5695 lineGap + squareSize/3 +
\r
5696 ((toY == BOARD_HEIGHT-1) ^ (flipView) ?
\r
5697 0 : 6*(squareSize + lineGap)), &x, &y);
\r
5700 XtSetArg(args[j], XtNx, x); j++;
\r
5701 XtSetArg(args[j], XtNy, y); j++;
\r
5702 XtSetValues(promotionShell, args, j);
\r
5704 XtPopup(promotionShell, XtGrabNone);
\r
5706 promotionUp = True;
\r
5709 void PromotionPopDown()
\r
5711 if (!promotionUp) return;
\r
5712 XtPopdown(promotionShell);
\r
5713 XtDestroyWidget(promotionShell);
\r
5714 promotionUp = False;
\r
5717 void PromotionCallback(w, client_data, call_data)
\r
5719 XtPointer client_data, call_data;
\r
5725 XtSetArg(args[0], XtNlabel, &name);
\r
5726 XtGetValues(w, args, 1);
\r
5728 PromotionPopDown();
\r
5730 if (fromX == -1) return;
\r
5732 if (strcmp(name, "cancel") == 0) {
\r
5733 fromX = fromY = -1;
\r
5734 ClearHighlights();
\r
5736 } else if (strcmp(name, "Knight") == 0) {
\r
5739 promoChar = ToLower(name[0]);
\r
5742 UserMoveEvent(fromX, fromY, toX, toY, promoChar);
\r
5744 if (!appData.highlightLastMove || gotPremove) ClearHighlights();
\r
5745 if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
\r
5746 fromX = fromY = -1;
\r
5750 void ErrorCallback(w, client_data, call_data)
\r
5752 XtPointer client_data, call_data;
\r
5755 XtPopdown(w = XtParent(XtParent(XtParent(w))));
\r
5756 XtDestroyWidget(w);
\r
5757 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
\r
5761 void ErrorPopDown()
\r
5763 if (!errorUp) return;
\r
5765 XtPopdown(errorShell);
\r
5766 XtDestroyWidget(errorShell);
\r
5767 if (errorExitStatus != -1) ExitEvent(errorExitStatus);
\r
5770 void ErrorPopUp(title, label, modal)
\r
5771 char *title, *label;
\r
5775 Widget dialog, layout;
\r
5779 Dimension bw_width, pw_width;
\r
5780 Dimension pw_height;
\r
5784 XtSetArg(args[i], XtNresizable, True); i++;
\r
5785 XtSetArg(args[i], XtNtitle, title); i++;
\r
5787 XtCreatePopupShell("errorpopup", transientShellWidgetClass,
\r
5788 shellWidget, args, i);
\r
5790 XtCreateManagedWidget(layoutName, formWidgetClass, errorShell,
\r
5791 layoutArgs, XtNumber(layoutArgs));
\r
5794 XtSetArg(args[i], XtNlabel, label); i++;
\r
5795 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
5796 dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
\r
5799 XawDialogAddButton(dialog, "ok", ErrorCallback, (XtPointer) dialog);
\r
5801 XtRealizeWidget(errorShell);
\r
5802 CatchDeleteWindow(errorShell, "ErrorPopDown");
\r
5805 XtSetArg(args[i], XtNwidth, &bw_width); i++;
\r
5806 XtGetValues(boardWidget, args, i);
\r
5808 XtSetArg(args[i], XtNwidth, &pw_width); i++;
\r
5809 XtSetArg(args[i], XtNheight, &pw_height); i++;
\r
5810 XtGetValues(errorShell, args, i);
\r
5813 /* This code seems to tickle an X bug if it is executed too soon
\r
5814 after xboard starts up. The coordinates get transformed as if
\r
5815 the main window was positioned at (0, 0).
\r
5817 XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
\r
5818 0 - pw_height + squareSize / 3, &x, &y);
\r
5820 XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
\r
5821 RootWindowOfScreen(XtScreen(boardWidget)),
\r
5822 (bw_width - pw_width) / 2,
\r
5823 0 - pw_height + squareSize / 3, &xx, &yy, &junk);
\r
5827 if (y < 0) y = 0; /*avoid positioning top offscreen*/
\r
5830 XtSetArg(args[i], XtNx, x); i++;
\r
5831 XtSetArg(args[i], XtNy, y); i++;
\r
5832 XtSetValues(errorShell, args, i);
\r
5835 XtPopup(errorShell, modal ? XtGrabExclusive : XtGrabNone);
\r
5838 /* Disable all user input other than deleting the window */
\r
5839 static int frozen = 0;
\r
5842 if (frozen) return;
\r
5843 /* Grab by a widget that doesn't accept input */
\r
5844 XtAddGrab(messageWidget, TRUE, FALSE);
\r
5848 /* Undo a FreezeUI */
\r
5851 if (!frozen) return;
\r
5852 XtRemoveGrab(messageWidget);
\r
5856 char *ModeToWidgetName(mode)
\r
5860 case BeginningOfGame:
\r
5861 if (appData.icsActive)
\r
5862 return "menuMode.ICS Client";
\r
5863 else if (appData.noChessProgram ||
\r
5864 *appData.cmailGameName != NULLCHAR)
\r
5865 return "menuMode.Edit Game";
\r
5867 return "menuMode.Machine Black";
\r
5868 case MachinePlaysBlack:
\r
5869 return "menuMode.Machine Black";
\r
5870 case MachinePlaysWhite:
\r
5871 return "menuMode.Machine White";
\r
5873 return "menuMode.Analysis Mode";
\r
5875 return "menuMode.Analyze File";
\r
5876 case TwoMachinesPlay:
\r
5877 return "menuMode.Two Machines";
\r
5879 return "menuMode.Edit Game";
\r
5880 case PlayFromGameFile:
\r
5881 return "menuFile.Load Game";
\r
5882 case EditPosition:
\r
5883 return "menuMode.Edit Position";
\r
5885 return "menuMode.Training";
\r
5886 case IcsPlayingWhite:
\r
5887 case IcsPlayingBlack:
\r
5888 case IcsObserving:
\r
5890 case IcsExamining:
\r
5891 return "menuMode.ICS Client";
\r
5898 void ModeHighlight()
\r
5901 static int oldPausing = FALSE;
\r
5902 static GameMode oldmode = (GameMode) -1;
\r
5905 if (!boardWidget || !XtIsRealized(boardWidget)) return;
\r
5907 if (pausing != oldPausing) {
\r
5908 oldPausing = pausing;
\r
5910 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
5912 XtSetArg(args[0], XtNleftBitmap, None);
\r
5914 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
\r
5917 if (appData.showButtonBar) {
\r
5920 XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
\r
5921 XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
\r
5923 XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
\r
5924 XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
\r
5927 /* Always toggle, don't set. Previous code messes up when
\r
5928 invoked while the button is pressed, as releasing it
\r
5929 toggles the state again. */
\r
5931 Pixel oldbg, oldfg;
\r
5932 XtSetArg(args[0], XtNbackground, &oldbg);
\r
5933 XtSetArg(args[1], XtNforeground, &oldfg);
\r
5934 XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON),
\r
5936 XtSetArg(args[0], XtNbackground, oldfg);
\r
5937 XtSetArg(args[1], XtNforeground, oldbg);
\r
5940 XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
\r
5944 wname = ModeToWidgetName(oldmode);
\r
5945 if (wname != NULL) {
\r
5946 XtSetArg(args[0], XtNleftBitmap, None);
\r
5947 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
\r
5949 wname = ModeToWidgetName(gameMode);
\r
5950 if (wname != NULL) {
\r
5951 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
5952 XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
\r
5954 oldmode = gameMode;
\r
5956 /* Maybe all the enables should be handled here, not just this one */
\r
5957 XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"),
\r
5958 gameMode == Training || gameMode == PlayFromGameFile);
\r
5963 * Button/menu procedures
\r
5965 void ResetProc(w, event, prms, nprms)
\r
5972 AnalysisPopDown();
\r
5975 int LoadGamePopUp(f, gameNumber, title)
\r
5980 cmailMsgLoaded = FALSE;
\r
5981 if (gameNumber == 0) {
\r
5982 int error = GameListBuild(f);
\r
5984 DisplayError("Cannot build game list", error);
\r
5985 } else if (!ListEmpty(&gameList) &&
\r
5986 ((ListGame *) gameList.tailPred)->number > 1) {
\r
5987 GameListPopUp(f, title);
\r
5990 GameListDestroy();
\r
5993 return LoadGame(f, gameNumber, title, FALSE);
\r
5996 void LoadGameProc(w, event, prms, nprms)
\r
6002 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
6003 Reset(FALSE, TRUE);
\r
6005 FileNamePopUp("Load game file name?", "", LoadGamePopUp, "rb");
\r
6008 void LoadNextGameProc(w, event, prms, nprms)
\r
6017 void LoadPrevGameProc(w, event, prms, nprms)
\r
6026 void ReloadGameProc(w, event, prms, nprms)
\r
6035 void LoadNextPositionProc(w, event, prms, nprms)
\r
6041 ReloadPosition(1);
\r
6044 void LoadPrevPositionProc(w, event, prms, nprms)
\r
6050 ReloadPosition(-1);
\r
6053 void ReloadPositionProc(w, event, prms, nprms)
\r
6059 ReloadPosition(0);
\r
6062 void LoadPositionProc(w, event, prms, nprms)
\r
6068 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
6069 Reset(FALSE, TRUE);
\r
6071 FileNamePopUp("Load position file name?", "", LoadPosition, "rb");
\r
6074 void SaveGameProc(w, event, prms, nprms)
\r
6080 FileNamePopUp("Save game file name?",
\r
6081 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
\r
6085 void SavePositionProc(w, event, prms, nprms)
\r
6091 FileNamePopUp("Save position file name?",
\r
6092 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
\r
6093 SavePosition, "a");
\r
6096 void ReloadCmailMsgProc(w, event, prms, nprms)
\r
6102 ReloadCmailMsgEvent(FALSE);
\r
6105 void MailMoveProc(w, event, prms, nprms)
\r
6114 /* this variable is shared between CopyPositionProc and SendPositionSelection */
\r
6115 static char *selected_fen_position=NULL;
\r
6118 SendPositionSelection(Widget w, Atom *selection, Atom *target,
\r
6119 Atom *type_return, XtPointer *value_return,
\r
6120 unsigned long *length_return, int *format_return)
\r
6122 char *selection_tmp;
\r
6124 if (!selected_fen_position) return False; /* should never happen */
\r
6125 if (*target == XA_STRING){
\r
6126 /* note: since no XtSelectionDoneProc was registered, Xt will
\r
6127 * automatically call XtFree on the value returned. So have to
\r
6128 * make a copy of it allocated with XtMalloc */
\r
6129 selection_tmp= XtMalloc(strlen(selected_fen_position)+16);
\r
6130 strcpy(selection_tmp, selected_fen_position);
\r
6132 *value_return=selection_tmp;
\r
6133 *length_return=strlen(selection_tmp);
\r
6134 *type_return=XA_STRING;
\r
6135 *format_return = 8; /* bits per byte */
\r
6142 /* note: when called from menu all parameters are NULL, so no clue what the
\r
6143 * Widget which was clicked on was, or what the click event was
\r
6145 void CopyPositionProc(w, event, prms, nprms)
\r
6153 if (selected_fen_position) free(selected_fen_position);
\r
6154 selected_fen_position = (char *)PositionToFEN(currentMove,1);
\r
6155 if (!selected_fen_position) return;
\r
6156 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
\r
6158 SendPositionSelection,
\r
6159 NULL/* lose_ownership_proc */ ,
\r
6160 NULL/* transfer_done_proc */);
\r
6162 free(selected_fen_position);
\r
6163 selected_fen_position=NULL;
\r
6167 /* function called when the data to Paste is ready */
\r
6169 PastePositionCB(Widget w, XtPointer client_data, Atom *selection,
\r
6170 Atom *type, XtPointer value, unsigned long *len, int *format)
\r
6172 char *fenstr=value;
\r
6173 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
\r
6174 fenstr[*len]='\0'; /* normally this string is terminated, but be safe */
\r
6175 EditPositionPasteFEN(fenstr);
\r
6179 /* called when Paste Position button is pressed,
\r
6180 * all parameters will be NULL */
\r
6181 void PastePositionProc(w, event, prms, nprms)
\r
6187 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
\r
6188 /* (XtSelectionCallbackProc) */ PastePositionCB,
\r
6189 NULL, /* client_data passed to PastePositionCB */
\r
6191 /* better to use the time field from the event that triggered the
\r
6192 * call to this function, but that isn't trivial to get
\r
6200 SendGameSelection(Widget w, Atom *selection, Atom *target,
\r
6201 Atom *type_return, XtPointer *value_return,
\r
6202 unsigned long *length_return, int *format_return)
\r
6204 char *selection_tmp;
\r
6206 if (*target == XA_STRING){
\r
6207 FILE* f = fopen(gameCopyFilename, "r");
\r
6210 if (f == NULL) return False;
\r
6214 selection_tmp = XtMalloc(len + 1);
\r
6215 count = fread(selection_tmp, 1, len, f);
\r
6216 if (len != count) {
\r
6217 XtFree(selection_tmp);
\r
6220 selection_tmp[len] = NULLCHAR;
\r
6221 *value_return = selection_tmp;
\r
6222 *length_return = len;
\r
6223 *type_return = XA_STRING;
\r
6224 *format_return = 8; /* bits per byte */
\r
6231 /* note: when called from menu all parameters are NULL, so no clue what the
\r
6232 * Widget which was clicked on was, or what the click event was
\r
6234 void CopyGameProc(w, event, prms, nprms)
\r
6242 ret = SaveGameToFile(gameCopyFilename, FALSE);
\r
6245 ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
\r
6247 SendGameSelection,
\r
6248 NULL/* lose_ownership_proc */ ,
\r
6249 NULL/* transfer_done_proc */);
\r
6252 /* function called when the data to Paste is ready */
\r
6254 PasteGameCB(Widget w, XtPointer client_data, Atom *selection,
\r
6255 Atom *type, XtPointer value, unsigned long *len, int *format)
\r
6258 if (value == NULL || *len == 0) {
\r
6259 return; /* nothing had been selected to copy */
\r
6261 f = fopen(gamePasteFilename, "w");
\r
6263 DisplayError("Can't open temp file", errno);
\r
6266 fwrite(value, 1, *len, f);
\r
6269 LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
\r
6272 /* called when Paste Game button is pressed,
\r
6273 * all parameters will be NULL */
\r
6274 void PasteGameProc(w, event, prms, nprms)
\r
6280 XtGetSelectionValue(menuBarWidget, XA_PRIMARY, XA_STRING,
\r
6281 /* (XtSelectionCallbackProc) */ PasteGameCB,
\r
6282 NULL, /* client_data passed to PasteGameCB */
\r
6284 /* better to use the time field from the event that triggered the
\r
6285 * call to this function, but that isn't trivial to get
\r
6293 void AutoSaveGame()
\r
6295 SaveGameProc(NULL, NULL, NULL, NULL);
\r
6299 void QuitProc(w, event, prms, nprms)
\r
6308 void PauseProc(w, event, prms, nprms)
\r
6318 void MachineBlackProc(w, event, prms, nprms)
\r
6324 MachineBlackEvent();
\r
6327 void MachineWhiteProc(w, event, prms, nprms)
\r
6333 MachineWhiteEvent();
\r
6336 void AnalyzeModeProc(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 if (!appData.showThinking)
\r
6349 ShowThinkingProc(w,event,prms,nprms);
\r
6351 AnalyzeModeEvent();
\r
6354 void AnalyzeFileProc(w, event, prms, nprms)
\r
6360 if (!first.analysisSupport) {
\r
6361 char buf[MSG_SIZ];
\r
6362 sprintf(buf, "%s does not support analysis", first.tidy);
\r
6363 DisplayError(buf, 0);
\r
6366 Reset(FALSE, TRUE);
\r
6368 if (!appData.showThinking)
\r
6369 ShowThinkingProc(w,event,prms,nprms);
\r
6371 AnalyzeFileEvent();
\r
6372 FileNamePopUp("File to analyze", "", LoadGamePopUp, "rb");
\r
6373 AnalysisPeriodicEvent(1);
\r
6376 void TwoMachinesProc(w, event, prms, nprms)
\r
6382 TwoMachinesEvent();
\r
6385 void IcsClientProc(w, event, prms, nprms)
\r
6394 void EditGameProc(w, event, prms, nprms)
\r
6403 void EditPositionProc(w, event, prms, nprms)
\r
6409 EditPositionEvent();
\r
6412 void TrainingProc(w, event, prms, nprms)
\r
6421 void EditCommentProc(w, event, prms, nprms)
\r
6428 EditCommentPopDown();
\r
6430 EditCommentEvent();
\r
6434 void IcsInputBoxProc(w, event, prms, nprms)
\r
6440 if (ICSInputBoxUp) {
\r
6441 ICSInputBoxPopDown();
\r
6443 ICSInputBoxPopUp();
\r
6447 void AcceptProc(w, event, prms, nprms)
\r
6456 void DeclineProc(w, event, prms, nprms)
\r
6465 void RematchProc(w, event, prms, nprms)
\r
6474 void CallFlagProc(w, event, prms, nprms)
\r
6483 void DrawProc(w, event, prms, nprms)
\r
6492 void AbortProc(w, event, prms, nprms)
\r
6501 void AdjournProc(w, event, prms, nprms)
\r
6510 void ResignProc(w, event, prms, nprms)
\r
6519 void EnterKeyProc(w, event, prms, nprms)
\r
6525 if (ICSInputBoxUp == True)
\r
6526 ICSInputSendText();
\r
6529 void StopObservingProc(w, event, prms, nprms)
\r
6535 StopObservingEvent();
\r
6538 void StopExaminingProc(w, event, prms, nprms)
\r
6544 StopExaminingEvent();
\r
6548 void ForwardProc(w, event, prms, nprms)
\r
6558 void BackwardProc(w, event, prms, nprms)
\r
6567 void ToStartProc(w, event, prms, nprms)
\r
6576 void ToEndProc(w, event, prms, nprms)
\r
6585 void RevertProc(w, event, prms, nprms)
\r
6594 void TruncateGameProc(w, event, prms, nprms)
\r
6600 TruncateGameEvent();
\r
6602 void RetractMoveProc(w, event, prms, nprms)
\r
6608 RetractMoveEvent();
\r
6611 void MoveNowProc(w, event, prms, nprms)
\r
6621 void AlwaysQueenProc(w, event, prms, nprms)
\r
6629 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
\r
6631 if (appData.alwaysPromoteToQueen) {
\r
6632 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6634 XtSetArg(args[0], XtNleftBitmap, None);
\r
6636 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
\r
6640 void AnimateDraggingProc(w, event, prms, nprms)
\r
6648 appData.animateDragging = !appData.animateDragging;
\r
6650 if (appData.animateDragging) {
\r
6651 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6654 XtSetArg(args[0], XtNleftBitmap, None);
\r
6656 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"),
\r
6660 void AnimateMovingProc(w, event, prms, nprms)
\r
6668 appData.animate = !appData.animate;
\r
6670 if (appData.animate) {
\r
6671 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6674 XtSetArg(args[0], XtNleftBitmap, None);
\r
6676 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
\r
6680 void AutocommProc(w, event, prms, nprms)
\r
6688 appData.autoComment = !appData.autoComment;
\r
6690 if (appData.autoComment) {
\r
6691 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6693 XtSetArg(args[0], XtNleftBitmap, None);
\r
6695 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
\r
6700 void AutoflagProc(w, event, prms, nprms)
\r
6708 appData.autoCallFlag = !appData.autoCallFlag;
\r
6710 if (appData.autoCallFlag) {
\r
6711 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6713 XtSetArg(args[0], XtNleftBitmap, None);
\r
6715 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
\r
6719 void AutoflipProc(w, event, prms, nprms)
\r
6727 appData.autoFlipView = !appData.autoFlipView;
\r
6729 if (appData.autoFlipView) {
\r
6730 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6732 XtSetArg(args[0], XtNleftBitmap, None);
\r
6734 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"),
\r
6738 void AutobsProc(w, event, prms, nprms)
\r
6746 appData.autoObserve = !appData.autoObserve;
\r
6748 if (appData.autoObserve) {
\r
6749 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6751 XtSetArg(args[0], XtNleftBitmap, None);
\r
6753 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
\r
6757 void AutoraiseProc(w, event, prms, nprms)
\r
6765 appData.autoRaiseBoard = !appData.autoRaiseBoard;
\r
6767 if (appData.autoRaiseBoard) {
\r
6768 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6770 XtSetArg(args[0], XtNleftBitmap, None);
\r
6772 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
\r
6776 void AutosaveProc(w, event, prms, nprms)
\r
6784 appData.autoSaveGames = !appData.autoSaveGames;
\r
6786 if (appData.autoSaveGames) {
\r
6787 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6789 XtSetArg(args[0], XtNleftBitmap, None);
\r
6791 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
\r
6795 void BlindfoldProc(w, event, prms, nprms)
\r
6803 appData.blindfold = !appData.blindfold;
\r
6805 if (appData.blindfold) {
\r
6806 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6808 XtSetArg(args[0], XtNleftBitmap, None);
\r
6810 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"),
\r
6813 DrawPosition(True, NULL);
\r
6816 void TestLegalityProc(w, event, prms, nprms)
\r
6824 appData.testLegality = !appData.testLegality;
\r
6826 if (appData.testLegality) {
\r
6827 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6829 XtSetArg(args[0], XtNleftBitmap, None);
\r
6831 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"),
\r
6836 void FlashMovesProc(w, event, prms, nprms)
\r
6844 if (appData.flashCount == 0) {
\r
6845 appData.flashCount = 3;
\r
6847 appData.flashCount = -appData.flashCount;
\r
6850 if (appData.flashCount > 0) {
\r
6851 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6853 XtSetArg(args[0], XtNleftBitmap, None);
\r
6855 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"),
\r
6859 void FlipViewProc(w, event, prms, nprms)
\r
6865 flipView = !flipView;
\r
6866 DrawPosition(True, NULL);
\r
6869 void GetMoveListProc(w, event, prms, nprms)
\r
6877 appData.getMoveList = !appData.getMoveList;
\r
6879 if (appData.getMoveList) {
\r
6880 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6881 GetMoveListEvent();
\r
6883 XtSetArg(args[0], XtNleftBitmap, None);
\r
6885 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
\r
6890 void HighlightDraggingProc(w, event, prms, nprms)
\r
6898 appData.highlightDragging = !appData.highlightDragging;
\r
6900 if (appData.highlightDragging) {
\r
6901 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6903 XtSetArg(args[0], XtNleftBitmap, None);
\r
6905 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6906 "menuOptions.Highlight Dragging"), args, 1);
\r
6910 void HighlightLastMoveProc(w, event, prms, nprms)
\r
6918 appData.highlightLastMove = !appData.highlightLastMove;
\r
6920 if (appData.highlightLastMove) {
\r
6921 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6923 XtSetArg(args[0], XtNleftBitmap, None);
\r
6925 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6926 "menuOptions.Highlight Last Move"), args, 1);
\r
6929 void IcsAlarmProc(w, event, prms, nprms)
\r
6937 appData.icsAlarm = !appData.icsAlarm;
\r
6939 if (appData.icsAlarm) {
\r
6940 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6942 XtSetArg(args[0], XtNleftBitmap, None);
\r
6944 XtSetValues(XtNameToWidget(menuBarWidget,
\r
6945 "menuOptions.ICS Alarm"), args, 1);
\r
6948 void MoveSoundProc(w, event, prms, nprms)
\r
6956 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
\r
6958 if (appData.ringBellAfterMoves) {
\r
6959 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6961 XtSetArg(args[0], XtNleftBitmap, None);
\r
6963 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
\r
6968 void OldSaveStyleProc(w, event, prms, nprms)
\r
6976 appData.oldSaveStyle = !appData.oldSaveStyle;
\r
6978 if (appData.oldSaveStyle) {
\r
6979 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
6981 XtSetArg(args[0], XtNleftBitmap, None);
\r
6983 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
\r
6987 void PeriodicUpdatesProc(w, event, prms, nprms)
\r
6995 PeriodicUpdatesEvent(!appData.periodicUpdates);
\r
6997 if (appData.periodicUpdates) {
\r
6998 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7000 XtSetArg(args[0], XtNleftBitmap, None);
\r
7002 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"),
\r
7006 void PonderNextMoveProc(w, event, prms, nprms)
\r
7014 PonderNextMoveEvent(!appData.ponderNextMove);
\r
7016 if (appData.ponderNextMove) {
\r
7017 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7019 XtSetArg(args[0], XtNleftBitmap, None);
\r
7021 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"),
\r
7025 void PopupExitMessageProc(w, event, prms, nprms)
\r
7033 appData.popupExitMessage = !appData.popupExitMessage;
\r
7035 if (appData.popupExitMessage) {
\r
7036 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7038 XtSetArg(args[0], XtNleftBitmap, None);
\r
7040 XtSetValues(XtNameToWidget(menuBarWidget,
\r
7041 "menuOptions.Popup Exit Message"), args, 1);
\r
7044 void PopupMoveErrorsProc(w, event, prms, nprms)
\r
7052 appData.popupMoveErrors = !appData.popupMoveErrors;
\r
7054 if (appData.popupMoveErrors) {
\r
7055 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7057 XtSetArg(args[0], XtNleftBitmap, None);
\r
7059 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"),
\r
7063 void PremoveProc(w, event, prms, nprms)
\r
7071 appData.premove = !appData.premove;
\r
7073 if (appData.premove) {
\r
7074 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7076 XtSetArg(args[0], XtNleftBitmap, None);
\r
7078 XtSetValues(XtNameToWidget(menuBarWidget,
\r
7079 "menuOptions.Premove"), args, 1);
\r
7082 void QuietPlayProc(w, event, prms, nprms)
\r
7090 appData.quietPlay = !appData.quietPlay;
\r
7092 if (appData.quietPlay) {
\r
7093 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7095 XtSetArg(args[0], XtNleftBitmap, None);
\r
7097 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
\r
7101 void ShowCoordsProc(w, event, prms, nprms)
\r
7109 appData.showCoords = !appData.showCoords;
\r
7111 if (appData.showCoords) {
\r
7112 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7114 XtSetArg(args[0], XtNleftBitmap, None);
\r
7116 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
\r
7119 DrawPosition(True, NULL);
\r
7122 void ShowThinkingProc(w, event, prms, nprms)
\r
7130 appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent
7131 ShowThinkingEvent();
\r
7133 // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human)
\r
7134 if (appData.showThinking) {
\r
7135 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7137 XtSetArg(args[0], XtNleftBitmap, None);
\r
7139 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
\r
7144 void HideThinkingProc(w, event, prms, nprms)
\r
7152 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent
7153 ShowThinkingEvent();
\r
7155 if (appData.hideThinkingFromHuman) {
\r
7156 XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
\r
7158 XtSetArg(args[0], XtNleftBitmap, None);
\r
7160 XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"),
\r
7164 void InfoProc(w, event, prms, nprms)
\r
7170 char buf[MSG_SIZ];
\r
7171 sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
\r
7172 INFODIR, INFOFILE);
\r
7176 void ManProc(w, event, prms, nprms)
\r
7182 char buf[MSG_SIZ];
\r
7184 if (nprms && *nprms > 0)
\r
7188 sprintf(buf, "xterm -e man %s &", name);
\r
7192 void HintProc(w, event, prms, nprms)
\r
7201 void BookProc(w, event, prms, nprms)
\r
7210 void AboutProc(w, event, prms, nprms)
\r
7216 char buf[MSG_SIZ];
\r
7218 char *zippy = " (with Zippy code)";
\r
7222 sprintf(buf, "%s%s\n\n%s\n%s\n%s\n%s\n\n%s%s\n%s",
\r
7223 programVersion, zippy,
\r
7224 "Copyright 1991 Digital Equipment Corporation",
\r
7225 "Enhancements Copyright 1992-2001 Free Software Foundation",
7226 "Enhancements Copyright 2005 Alessandro Scotti",
\r
7227 "Enhancements Copyright 2007-2008 H.G.Muller",
\r
7228 PRODUCT, " is free software and carries NO WARRANTY;",
\r
7229 "see the file COPYING for more information.");
\r
7230 ErrorPopUp("About XBoard", buf, FALSE);
\r
7233 void DebugProc(w, event, prms, nprms)
\r
7239 appData.debugMode = !appData.debugMode;
\r
7242 void AboutGameProc(w, event, prms, nprms)
\r
7251 void NothingProc(w, event, prms, nprms)
\r
7260 void Iconify(w, event, prms, nprms)
\r
7268 fromX = fromY = -1;
\r
7269 XtSetArg(args[0], XtNiconic, True);
\r
7270 XtSetValues(shellWidget, args, 1);
\r
7273 void DisplayMessage(message, extMessage)
\r
7274 char *message, *extMessage;
\r
7276 char buf[MSG_SIZ];
\r
7281 sprintf(buf, "%s %s", message, extMessage);
\r
7284 message = extMessage;
\r
7287 XtSetArg(arg, XtNlabel, message);
\r
7288 XtSetValues(messageWidget, &arg, 1);
\r
7291 void DisplayTitle(text)
\r
7296 char title[MSG_SIZ];
\r
7297 char icon[MSG_SIZ];
\r
7299 if (text == NULL) text = "";
\r
7301 if (appData.titleInWindow) {
\r
7303 XtSetArg(args[i], XtNlabel, text); i++;
\r
7304 XtSetValues(titleWidget, args, i);
\r
7307 if (*text != NULLCHAR) {
\r
7308 strcpy(icon, text);
\r
7309 strcpy(title, text);
\r
7310 } else if (appData.icsActive) {
\r
7311 sprintf(icon, "%s", appData.icsHost);
\r
7312 sprintf(title, "%s: %s", programName, appData.icsHost);
\r
7313 } else if (appData.cmailGameName[0] != NULLCHAR) {
\r
7314 sprintf(icon, "%s", "CMail");
\r
7315 sprintf(title, "%s: %s", programName, "CMail");
\r
7317 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
7318 } else if (gameInfo.variant == VariantGothic) {
\r
7319 strcpy(icon, programName);
\r
7320 strcpy(title, GOTHIC);
\r
7323 } else if (gameInfo.variant == VariantFalcon) {
\r
7324 strcpy(icon, programName);
\r
7325 strcpy(title, FALCON);
\r
7327 } else if (appData.noChessProgram) {
\r
7328 strcpy(icon, programName);
\r
7329 strcpy(title, programName);
\r
7331 strcpy(icon, first.tidy);
\r
7332 sprintf(title, "%s: %s", programName, first.tidy);
\r
7335 XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++;
\r
7336 XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++;
\r
7337 XtSetValues(shellWidget, args, i);
\r
7341 void DisplayError(message, error)
\r
7345 char buf[MSG_SIZ];
\r
7348 if (appData.debugMode || appData.matchMode) {
\r
7349 fprintf(stderr, "%s: %s\n", programName, message);
\r
7352 if (appData.debugMode || appData.matchMode) {
\r
7353 fprintf(stderr, "%s: %s: %s\n",
\r
7354 programName, message, strerror(error));
\r
7356 sprintf(buf, "%s: %s", message, strerror(error));
\r
7359 ErrorPopUp("Error", message, FALSE);
\r
7363 void DisplayMoveError(message)
\r
7366 fromX = fromY = -1;
\r
7367 ClearHighlights();
\r
7368 DrawPosition(FALSE, NULL);
\r
7369 if (appData.debugMode || appData.matchMode) {
\r
7370 fprintf(stderr, "%s: %s\n", programName, message);
\r
7372 if (appData.popupMoveErrors) {
\r
7373 ErrorPopUp("Error", message, FALSE);
\r
7375 DisplayMessage(message, "");
\r
7380 void DisplayFatalError(message, error, status)
\r
7382 int error, status;
\r
7384 char buf[MSG_SIZ];
\r
7386 errorExitStatus = status;
\r
7388 fprintf(stderr, "%s: %s\n", programName, message);
\r
7390 fprintf(stderr, "%s: %s: %s\n",
\r
7391 programName, message, strerror(error));
\r
7392 sprintf(buf, "%s: %s", message, strerror(error));
\r
7395 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
\r
7396 ErrorPopUp(status ? "Fatal Error" : "Exiting", message, TRUE);
\r
7398 ExitEvent(status);
\r
7402 void DisplayInformation(message)
\r
7406 ErrorPopUp("Information", message, TRUE);
\r
7409 void DisplayNote(message)
\r
7413 ErrorPopUp("Note", message, FALSE);
\r
7417 NullXErrorCheck(dpy, error_event)
\r
7419 XErrorEvent *error_event;
\r
7424 void DisplayIcsInteractionTitle(message)
\r
7427 if (oldICSInteractionTitle == NULL) {
\r
7428 /* Magic to find the old window title, adapted from vim */
\r
7429 char *wina = getenv("WINDOWID");
\r
7430 if (wina != NULL) {
\r
7431 Window win = (Window) atoi(wina);
\r
7432 Window root, parent, *children;
\r
7433 unsigned int nchildren;
\r
7434 int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
\r
7436 if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
\r
7437 if (!XQueryTree(xDisplay, win, &root, &parent,
\r
7438 &children, &nchildren)) break;
\r
7439 if (children) XFree((void *)children);
\r
7440 if (parent == root || parent == 0) break;
\r
7443 XSetErrorHandler(oldHandler);
\r
7445 if (oldICSInteractionTitle == NULL) {
\r
7446 oldICSInteractionTitle = "xterm";
\r
7449 printf("\033]0;%s\007", message);
\r
7453 char pendingReplyPrefix[MSG_SIZ];
\r
7454 ProcRef pendingReplyPR;
\r
7456 void AskQuestionProc(w, event, prms, nprms)
\r
7462 if (*nprms != 4) {
\r
7463 fprintf(stderr, "AskQuestionProc needed 4 parameters, got %d\n",
\r
7467 AskQuestionEvent(prms[0], prms[1], prms[2], prms[3]);
\r
7470 void AskQuestionPopDown()
\r
7472 if (!askQuestionUp) return;
\r
7473 XtPopdown(askQuestionShell);
\r
7474 XtDestroyWidget(askQuestionShell);
\r
7475 askQuestionUp = False;
\r
7478 void AskQuestionReplyAction(w, event, prms, nprms)
\r
7484 char buf[MSG_SIZ];
\r
7488 reply = XawDialogGetValueString(w = XtParent(w));
\r
7489 strcpy(buf, pendingReplyPrefix);
\r
7490 if (*buf) strcat(buf, " ");
\r
7491 strcat(buf, reply);
\r
7492 strcat(buf, "\n");
\r
7493 OutputToProcess(pendingReplyPR, buf, strlen(buf), &err);
\r
7494 AskQuestionPopDown();
\r
7496 if (err) DisplayFatalError("Error writing to chess program", err, 0);
\r
7499 void AskQuestionCallback(w, client_data, call_data)
\r
7501 XtPointer client_data, call_data;
\r
7506 XtSetArg(args[0], XtNlabel, &name);
\r
7507 XtGetValues(w, args, 1);
\r
7509 if (strcmp(name, "cancel") == 0) {
\r
7510 AskQuestionPopDown();
\r
7512 AskQuestionReplyAction(w, NULL, NULL, NULL);
\r
7516 void AskQuestion(title, question, replyPrefix, pr)
\r
7517 char *title, *question, *replyPrefix;
\r
7521 Widget popup, layout, dialog, edit;
\r
7522 Window root, child;
\r
7525 unsigned int mask;
\r
7527 strcpy(pendingReplyPrefix, replyPrefix);
\r
7528 pendingReplyPR = pr;
\r
7531 XtSetArg(args[i], XtNresizable, True); i++;
\r
7532 XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
\r
7533 askQuestionShell = popup =
\r
7534 XtCreatePopupShell(title, transientShellWidgetClass,
\r
7535 shellWidget, args, i);
\r
7538 XtCreateManagedWidget(layoutName, formWidgetClass, popup,
\r
7539 layoutArgs, XtNumber(layoutArgs));
\r
7542 XtSetArg(args[i], XtNlabel, question); i++;
\r
7543 XtSetArg(args[i], XtNvalue, ""); i++;
\r
7544 XtSetArg(args[i], XtNborderWidth, 0); i++;
\r
7545 dialog = XtCreateManagedWidget("question", dialogWidgetClass,
\r
7548 XawDialogAddButton(dialog, "enter", AskQuestionCallback,
\r
7549 (XtPointer) dialog);
\r
7550 XawDialogAddButton(dialog, "cancel", AskQuestionCallback,
\r
7551 (XtPointer) dialog);
\r
7553 XtRealizeWidget(popup);
\r
7554 CatchDeleteWindow(popup, "AskQuestionPopDown");
\r
7556 XQueryPointer(xDisplay, xBoardWindow, &root, &child,
\r
7557 &x, &y, &win_x, &win_y, &mask);
\r
7559 XtSetArg(args[0], XtNx, x - 10);
\r
7560 XtSetArg(args[1], XtNy, y - 30);
\r
7561 XtSetValues(popup, args, 2);
\r
7563 XtPopup(popup, XtGrabExclusive);
\r
7564 askQuestionUp = True;
\r
7566 edit = XtNameToWidget(dialog, "*value");
\r
7567 XtSetKeyboardFocus(popup, edit);
\r
7575 if (*name == NULLCHAR) {
\r
7577 } else if (strcmp(name, "$") == 0) {
\r
7578 putc(BELLCHAR, stderr);
\r
7581 sprintf(buf, "%s '%s' &", appData.soundProgram, name);
\r
7589 PlaySound(appData.soundMove);
\r
7595 PlaySound(appData.soundIcsWin);
\r
7599 PlayIcsLossSound()
\r
7601 PlaySound(appData.soundIcsLoss);
\r
7605 PlayIcsDrawSound()
\r
7607 PlaySound(appData.soundIcsDraw);
\r
7611 PlayIcsUnfinishedSound()
\r
7613 PlaySound(appData.soundIcsUnfinished);
\r
7619 PlaySound(appData.soundIcsAlarm);
\r
7625 system("stty echo");
\r
7631 system("stty -echo");
\r
7635 Colorize(cc, continuation)
\r
7639 char buf[MSG_SIZ];
\r
7640 int count, outCount, error;
\r
7642 if (textColors[(int)cc].bg > 0) {
\r
7643 if (textColors[(int)cc].fg > 0) {
\r
7644 sprintf(buf, "\033[0;%d;%d;%dm", textColors[(int)cc].attr,
\r
7645 textColors[(int)cc].fg, textColors[(int)cc].bg);
\r
7647 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
\r
7648 textColors[(int)cc].bg);
\r
7651 if (textColors[(int)cc].fg > 0) {
\r
7652 sprintf(buf, "\033[0;%d;%dm", textColors[(int)cc].attr,
\r
7653 textColors[(int)cc].fg);
\r
7655 sprintf(buf, "\033[0;%dm", textColors[(int)cc].attr);
\r
7658 count = strlen(buf);
\r
7659 outCount = OutputToProcess(NoProc, buf, count, &error);
\r
7660 if (outCount < count) {
\r
7661 DisplayFatalError("Error writing to display", error, 1);
\r
7664 if (continuation) return;
\r
7667 PlaySound(appData.soundShout);
\r
7670 PlaySound(appData.soundSShout);
\r
7672 case ColorChannel1:
\r
7673 PlaySound(appData.soundChannel1);
\r
7675 case ColorChannel:
\r
7676 PlaySound(appData.soundChannel);
\r
7679 PlaySound(appData.soundKibitz);
\r
7682 PlaySound(appData.soundTell);
\r
7684 case ColorChallenge:
\r
7685 PlaySound(appData.soundChallenge);
\r
7687 case ColorRequest:
\r
7688 PlaySound(appData.soundRequest);
\r
7691 PlaySound(appData.soundSeek);
\r
7702 return getpwuid(getuid())->pw_name;
\r
7705 static char *ExpandPathName(path)
\r
7708 static char static_buf[2000];
\r
7709 char *d, *s, buf[2000];
\r
7710 struct passwd *pwd;
\r
7715 while (*s && isspace(*s))
\r
7720 return static_buf;
\r
7724 if (*(s+1) == '/') {
\r
7725 strcpy(d, getpwuid(getuid())->pw_dir);
\r
7730 *strchr(buf, '/') = 0;
\r
7731 pwd = getpwnam(buf);
\r
7734 fprintf(stderr, "ERROR: Unknown user %s (in path %s)\n",
\r
7738 strcpy(d, pwd->pw_dir);
\r
7739 strcat(d, strchr(s+1, '/'));
\r
7745 return static_buf;
\r
7750 static char host_name[MSG_SIZ];
\r
7752 #if HAVE_GETHOSTNAME
\r
7753 gethostname(host_name, MSG_SIZ);
\r
7755 #else /* not HAVE_GETHOSTNAME */
\r
7756 # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
\r
7757 sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
\r
7759 # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
\r
7760 return "localhost";
\r
7761 # endif/* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
\r
7762 #endif /* not HAVE_GETHOSTNAME */
\r
7765 XtIntervalId delayedEventTimerXID = 0;
\r
7766 DelayedEventCallback delayedEventCallback = 0;
\r
7769 FireDelayedEvent()
\r
7771 delayedEventTimerXID = 0;
\r
7772 delayedEventCallback();
\r
7776 ScheduleDelayedEvent(cb, millisec)
\r
7777 DelayedEventCallback cb; long millisec;
\r
7779 delayedEventCallback = cb;
\r
7780 delayedEventTimerXID =
\r
7781 XtAppAddTimeOut(appContext, millisec,
\r
7782 (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
\r
7785 DelayedEventCallback
\r
7788 if (delayedEventTimerXID) {
\r
7789 return delayedEventCallback;
\r
7796 CancelDelayedEvent()
\r
7798 if (delayedEventTimerXID) {
\r
7799 XtRemoveTimeOut(delayedEventTimerXID);
\r
7800 delayedEventTimerXID = 0;
\r
7804 XtIntervalId loadGameTimerXID = 0;
\r
7806 int LoadGameTimerRunning()
\r
7808 return loadGameTimerXID != 0;
\r
7811 int StopLoadGameTimer()
\r
7813 if (loadGameTimerXID != 0) {
\r
7814 XtRemoveTimeOut(loadGameTimerXID);
\r
7815 loadGameTimerXID = 0;
\r
7823 LoadGameTimerCallback(arg, id)
\r
7827 loadGameTimerXID = 0;
\r
7828 AutoPlayGameLoop();
\r
7832 StartLoadGameTimer(millisec)
\r
7835 loadGameTimerXID =
\r
7836 XtAppAddTimeOut(appContext, millisec,
\r
7837 (XtTimerCallbackProc) LoadGameTimerCallback,
\r
7841 XtIntervalId analysisClockXID = 0;
\r
7844 AnalysisClockCallback(arg, id)
\r
7848 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
\r
7849 AnalysisPeriodicEvent(0);
\r
7850 StartAnalysisClock();
\r
7855 StartAnalysisClock()
\r
7857 analysisClockXID =
\r
7858 XtAppAddTimeOut(appContext, 2000,
\r
7859 (XtTimerCallbackProc) AnalysisClockCallback,
\r
7863 XtIntervalId clockTimerXID = 0;
\r
7865 int ClockTimerRunning()
\r
7867 return clockTimerXID != 0;
\r
7870 int StopClockTimer()
\r
7872 if (clockTimerXID != 0) {
\r
7873 XtRemoveTimeOut(clockTimerXID);
\r
7874 clockTimerXID = 0;
\r
7882 ClockTimerCallback(arg, id)
\r
7886 clockTimerXID = 0;
\r
7887 DecrementClocks();
\r
7891 StartClockTimer(millisec)
\r
7895 XtAppAddTimeOut(appContext, millisec,
\r
7896 (XtTimerCallbackProc) ClockTimerCallback,
\r
7901 DisplayTimerLabel(w, color, timer, highlight)
\r
7907 char buf[MSG_SIZ];
\r
7910 if (appData.clockMode) {
\r
7911 sprintf(buf, "%s: %s", color, TimeString(timer));
\r
7912 XtSetArg(args[0], XtNlabel, buf);
\r
7914 sprintf(buf, "%s ", color);
\r
7915 XtSetArg(args[0], XtNlabel, buf);
\r
7919 XtSetArg(args[1], XtNbackground, timerForegroundPixel);
\r
7920 XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
\r
7922 XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
\r
7923 XtSetArg(args[2], XtNforeground, timerForegroundPixel);
\r
7926 XtSetValues(w, args, 3);
\r
7930 DisplayWhiteClock(timeRemaining, highlight)
\r
7931 long timeRemaining;
\r
7935 DisplayTimerLabel(whiteTimerWidget, "White", timeRemaining, highlight);
\r
7936 if (highlight && iconPixmap == bIconPixmap) {
\r
7937 iconPixmap = wIconPixmap;
\r
7938 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
\r
7939 XtSetValues(shellWidget, args, 1);
\r
7944 DisplayBlackClock(timeRemaining, highlight)
\r
7945 long timeRemaining;
\r
7949 DisplayTimerLabel(blackTimerWidget, "Black", timeRemaining, highlight);
\r
7950 if (highlight && iconPixmap == wIconPixmap) {
\r
7951 iconPixmap = bIconPixmap;
\r
7952 XtSetArg(args[0], XtNiconPixmap, iconPixmap);
\r
7953 XtSetValues(shellWidget, args, 1);
\r
7962 typedef int CPKind;
\r
7967 int fdTo, fdFrom;
\r
7971 int StartChildProcess(cmdLine, dir, pr)
\r
7976 char *argv[64], *p;
\r
7978 int to_prog[2], from_prog[2];
\r
7980 char buf[MSG_SIZ];
\r
7982 if (appData.debugMode) {
\r
7983 fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine);
\r
7986 /* We do NOT feed the cmdLine to the shell; we just
\r
7987 parse it into blank-separated arguments in the
\r
7988 most simple-minded way possible.
\r
7991 strcpy(buf, cmdLine);
\r
7995 p = strchr(p, ' ');
\r
7996 if (p == NULL) break;
\r
8001 SetUpChildIO(to_prog, from_prog);
\r
8003 if ((pid = fork()) == 0) {
\r
8005 // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1
\r
8006 close(to_prog[1]); // first close the unused pipe ends
\r
8007 close(from_prog[0]);
\r
8008 dup2(to_prog[0], 0); // to_prog was created first, nd is the only one to use 0 or 1
\r
8009 dup2(from_prog[1], 1);
\r
8010 if(to_prog[0] >= 2) close(to_prog[0]); // if 0 or 1, the dup2 already cosed the original
\r
8011 close(from_prog[1]); // and closing again loses one of the pipes!
\r
8012 if(fileno(stderr) >= 2) // better safe than sorry...
8013 dup2(1, fileno(stderr)); /* force stderr to the pipe */
\r
8015 if (dir[0] != NULLCHAR && chdir(dir) != 0) {
\r
8020 nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc
\r
8022 execvp(argv[0], argv);
\r
8024 /* If we get here, exec failed */
\r
8029 /* Parent process */
\r
8030 close(to_prog[0]);
\r
8031 close(from_prog[1]);
\r
8033 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8034 cp->kind = CPReal;
\r
8036 cp->fdFrom = from_prog[0];
\r
8037 cp->fdTo = to_prog[1];
\r
8038 *pr = (ProcRef) cp;
\r
8042 // [HGM] kill: implement the 'hard killing' of AS's Winboard_x
\r
8043 static RETSIGTYPE AlarmCallBack(int n)
\r
8049 DestroyChildProcess(pr, signalType)
\r
8053 ChildProc *cp = (ChildProc *) pr;
\r
8055 if (cp->kind != CPReal) return;
\r
8056 cp->kind = CPNone;
\r
8057 if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill
\r
8058 signal(SIGALRM, AlarmCallBack);
\r
8060 if(wait((int *) 0) == -1) { // process does not terminate on its own accord
\r
8061 kill(cp->pid, SIGKILL); // kill it forcefully
\r
8062 wait((int *) 0); // and wait again
\r
8066 kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested
\r
8068 /* Process is exiting either because of the kill or because of
\r
8069 a quit command sent by the backend; either way, wait for it to die.
\r
8073 close(cp->fdFrom);
\r
8078 InterruptChildProcess(pr)
\r
8081 ChildProc *cp = (ChildProc *) pr;
\r
8083 if (cp->kind != CPReal) return;
\r
8084 (void) kill(cp->pid, SIGINT); /* stop it thinking */
\r
8087 int OpenTelnet(host, port, pr)
\r
8092 char cmdLine[MSG_SIZ];
\r
8094 if (port[0] == NULLCHAR) {
\r
8095 sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
\r
8097 sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
\r
8099 return StartChildProcess(cmdLine, "", pr);
\r
8102 int OpenTCP(host, port, pr)
\r
8108 DisplayFatalError("Socket support is not configured in", 0, 2);
\r
8109 #else /* !OMIT_SOCKETS */
\r
8111 struct sockaddr_in sa;
\r
8112 struct hostent *hp;
\r
8113 unsigned short uport;
\r
8116 if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
\r
8120 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
\r
8121 sa.sin_family = AF_INET;
\r
8122 sa.sin_addr.s_addr = INADDR_ANY;
\r
8123 uport = (unsigned short) 0;
\r
8124 sa.sin_port = htons(uport);
\r
8125 if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
\r
8129 memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
\r
8130 if (!(hp = gethostbyname(host))) {
\r
8131 int b0, b1, b2, b3;
\r
8132 if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
\r
8133 hp = (struct hostent *) calloc(1, sizeof(struct hostent));
\r
8134 hp->h_addrtype = AF_INET;
\r
8136 hp->h_addr_list = (char **) calloc(2, sizeof(char *));
\r
8137 hp->h_addr_list[0] = (char *) malloc(4);
\r
8138 hp->h_addr_list[0][0] = b0;
\r
8139 hp->h_addr_list[0][1] = b1;
\r
8140 hp->h_addr_list[0][2] = b2;
\r
8141 hp->h_addr_list[0][3] = b3;
\r
8146 sa.sin_family = hp->h_addrtype;
\r
8147 uport = (unsigned short) atoi(port);
\r
8148 sa.sin_port = htons(uport);
\r
8149 memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
\r
8151 if (connect(s, (struct sockaddr *) &sa,
\r
8152 sizeof(struct sockaddr_in)) < 0) {
\r
8156 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8157 cp->kind = CPSock;
\r
8161 *pr = (ProcRef) cp;
\r
8163 #endif /* !OMIT_SOCKETS */
\r
8168 int OpenCommPort(name, pr)
\r
8175 fd = open(name, 2, 0);
\r
8176 if (fd < 0) return errno;
\r
8178 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8179 cp->kind = CPComm;
\r
8183 *pr = (ProcRef) cp;
\r
8188 int OpenLoopback(pr)
\r
8192 int to[2], from[2];
\r
8194 SetUpChildIO(to, from);
\r
8196 cp = (ChildProc *) calloc(1, sizeof(ChildProc));
\r
8197 cp->kind = CPLoop;
\r
8199 cp->fdFrom = to[0]; /* note not from[0]; we are doing a loopback */
\r
8201 *pr = (ProcRef) cp;
\r
8206 int OpenRcmd(host, user, cmd, pr)
\r
8207 char *host, *user, *cmd;
\r
8210 DisplayFatalError("internal rcmd not implemented for Unix", 0, 1);
\r
8214 #define INPUT_SOURCE_BUF_SIZE 8192
\r
8221 InputCallback func;
\r
8223 char buf[INPUT_SOURCE_BUF_SIZE];
\r
8228 DoInputCallback(closure, source, xid)
\r
8233 InputSource *is = (InputSource *) closure;
\r
8238 if (is->lineByLine) {
\r
8239 count = read(is->fd, is->unused,
\r
8240 INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
\r
8242 (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
\r
8245 is->unused += count;
\r
8247 while (p < is->unused) {
\r
8248 q = memchr(p, '\n', is->unused - p);
\r
8249 if (q == NULL) break;
\r
8251 (is->func)(is, is->closure, p, q - p, 0);
\r
8255 while (p < is->unused) {
\r
8260 count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
\r
8265 (is->func)(is, is->closure, is->buf, count, error);
\r
8269 InputSourceRef AddInputSource(pr, lineByLine, func, closure)
\r
8272 InputCallback func;
\r
8276 ChildProc *cp = (ChildProc *) pr;
\r
8278 is = (InputSource *) calloc(1, sizeof(InputSource));
\r
8279 is->lineByLine = lineByLine;
\r
8281 if (pr == NoProc) {
\r
8282 is->kind = CPReal;
\r
8283 is->fd = fileno(stdin);
\r
8285 is->kind = cp->kind;
\r
8286 is->fd = cp->fdFrom;
\r
8289 is->unused = is->buf;
\r
8292 is->xid = XtAppAddInput(appContext, is->fd,
\r
8293 (XtPointer) (XtInputReadMask),
\r
8294 (XtInputCallbackProc) DoInputCallback,
\r
8296 is->closure = closure;
\r
8297 return (InputSourceRef) is;
\r
8301 RemoveInputSource(isr)
\r
8302 InputSourceRef isr;
\r
8304 InputSource *is = (InputSource *) isr;
\r
8306 if (is->xid == 0) return;
\r
8307 XtRemoveInput(is->xid);
\r
8311 int OutputToProcess(pr, message, count, outError)
\r
8317 ChildProc *cp = (ChildProc *) pr;
\r
8321 outCount = fwrite(message, 1, count, stdout);
\r
8323 outCount = write(cp->fdTo, message, count);
\r
8325 if (outCount == -1)
\r
8326 *outError = errno;
\r
8333 /* Output message to process, with "ms" milliseconds of delay
\r
8334 between each character. This is needed when sending the logon
\r
8335 script to ICC, which for some reason doesn't like the
\r
8336 instantaneous send. */
\r
8337 int OutputToProcessDelayed(pr, message, count, outError, msdelay)
\r
8344 ChildProc *cp = (ChildProc *) pr;
\r
8349 r = write(cp->fdTo, message++, 1);
\r
8351 *outError = errno;
\r
8356 TimeDelay(msdelay);
\r
8362 /**** Animation code by Hugh Fisher, DCS, ANU.
\r
8364 Known problem: if a window overlapping the board is
\r
8365 moved away while a piece is being animated underneath,
\r
8366 the newly exposed area won't be updated properly.
\r
8367 I can live with this.
\r
8369 Known problem: if you look carefully at the animation
\r
8370 of pieces in mono mode, they are being drawn as solid
\r
8371 shapes without interior detail while moving. Fixing
\r
8372 this would be a major complication for minimal return.
\r
8375 /* Masks for XPM pieces. Black and white pieces can have
\r
8376 different shapes, but in the interest of retaining my
\r
8377 sanity pieces must have the same outline on both light
\r
8378 and dark squares, and all pieces must use the same
\r
8379 background square colors/images. */
\r
8382 CreateAnimMasks (pieceDepth)
\r
8385 ChessSquare piece;
\r
8389 unsigned long plane;
\r
8392 /* Need a bitmap just to get a GC with right depth */
\r
8393 buf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8395 values.foreground = 1;
\r
8396 values.background = 0;
\r
8397 /* Don't use XtGetGC, not read only */
\r
8398 maskGC = XCreateGC(xDisplay, buf,
\r
8399 GCForeground | GCBackground, &values);
\r
8400 XFreePixmap(xDisplay, buf);
\r
8402 buf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8403 squareSize, squareSize, pieceDepth);
\r
8404 values.foreground = XBlackPixel(xDisplay, xScreen);
\r
8405 values.background = XWhitePixel(xDisplay, xScreen);
\r
8406 bufGC = XCreateGC(xDisplay, buf,
\r
8407 GCForeground | GCBackground, &values);
\r
8409 for (piece = WhitePawn; piece <= BlackKing; piece++) {
\r
8410 /* Begin with empty mask */
\r
8411 xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
\r
8412 squareSize, squareSize, 1);
\r
8413 XSetFunction(xDisplay, maskGC, GXclear);
\r
8414 XFillRectangle(xDisplay, xpmMask[piece], maskGC,
\r
8415 0, 0, squareSize, squareSize);
\r
8417 /* Take a copy of the piece */
\r
8422 XSetFunction(xDisplay, bufGC, GXcopy);
\r
8423 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
\r
8425 0, 0, squareSize, squareSize, 0, 0);
\r
8427 /* XOR the background (light) over the piece */
\r
8428 XSetFunction(xDisplay, bufGC, GXxor);
\r
8430 XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
\r
8431 0, 0, squareSize, squareSize, 0, 0);
\r
8433 XSetForeground(xDisplay, bufGC, lightSquareColor);
\r
8434 XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
\r
8437 /* We now have an inverted piece image with the background
\r
8438 erased. Construct mask by just selecting all the non-zero
\r
8439 pixels - no need to reconstruct the original image. */
\r
8440 XSetFunction(xDisplay, maskGC, GXor);
\r
8442 /* Might be quicker to download an XImage and create bitmap
\r
8443 data from it rather than this N copies per piece, but it
\r
8444 only takes a fraction of a second and there is a much
\r
8445 longer delay for loading the pieces. */
\r
8446 for (n = 0; n < pieceDepth; n ++) {
\r
8447 XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
\r
8448 0, 0, squareSize, squareSize,
\r
8450 plane = plane << 1;
\r
8454 XFreePixmap(xDisplay, buf);
\r
8455 XFreeGC(xDisplay, bufGC);
\r
8456 XFreeGC(xDisplay, maskGC);
\r
8460 InitAnimState (anim, info)
\r
8462 XWindowAttributes * info;
\r
8467 /* Each buffer is square size, same depth as window */
\r
8468 anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8469 squareSize, squareSize, info->depth);
\r
8470 anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow,
\r
8471 squareSize, squareSize, info->depth);
\r
8473 /* Create a plain GC for blitting */
\r
8474 mask = GCForeground | GCBackground | GCFunction |
\r
8475 GCPlaneMask | GCGraphicsExposures;
\r
8476 values.foreground = XBlackPixel(xDisplay, xScreen);
\r
8477 values.background = XWhitePixel(xDisplay, xScreen);
\r
8478 values.function = GXcopy;
\r
8479 values.plane_mask = AllPlanes;
\r
8480 values.graphics_exposures = False;
\r
8481 anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values);
\r
8483 /* Piece will be copied from an existing context at
\r
8484 the start of each new animation/drag. */
\r
8485 anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values);
\r
8487 /* Outline will be a read-only copy of an existing */
\r
8488 anim->outlineGC = None;
\r
8494 static int done = 0;
\r
8495 XWindowAttributes info;
\r
8499 XGetWindowAttributes(xDisplay, xBoardWindow, &info);
\r
8501 InitAnimState(&game, &info);
\r
8502 InitAnimState(&player, &info);
\r
8504 /* For XPM pieces, we need bitmaps to use as masks. */
\r
8506 CreateAnimMasks(info.depth);
\r
8509 #ifndef HAVE_USLEEP
\r
8511 static Boolean frameWaiting;
\r
8513 static RETSIGTYPE FrameAlarm (sig)
\r
8516 frameWaiting = False;
\r
8517 /* In case System-V style signals. Needed?? */
\r
8518 signal(SIGALRM, FrameAlarm);
\r
8525 struct itimerval delay;
\r
8527 XSync(xDisplay, False);
\r
8530 frameWaiting = True;
\r
8531 signal(SIGALRM, FrameAlarm);
\r
8532 delay.it_interval.tv_sec =
\r
8533 delay.it_value.tv_sec = time / 1000;
\r
8534 delay.it_interval.tv_usec =
\r
8535 delay.it_value.tv_usec = (time % 1000) * 1000;
\r
8536 setitimer(ITIMER_REAL, &delay, NULL);
\r
8538 /* Ugh -- busy-wait! --tpm */
\r
8539 while (frameWaiting);
\r
8541 while (frameWaiting) pause();
\r
8543 delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
\r
8544 delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
\r
8545 setitimer(ITIMER_REAL, &delay, NULL);
\r
8555 XSync(xDisplay, False);
\r
8557 usleep(time * 1000);
\r
8562 /* Convert board position to corner of screen rect and color */
\r
8565 ScreenSquare(column, row, pt, color)
\r
8566 int column; int row; XPoint * pt; int * color;
\r
8569 pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap);
\r
8570 pt->y = lineGap + row * (squareSize + lineGap);
\r
8572 pt->x = lineGap + column * (squareSize + lineGap);
\r
8573 pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap);
\r
8575 *color = SquareColor(row, column);
\r
8578 /* Convert window coords to square */
\r
8581 BoardSquare(x, y, column, row)
\r
8582 int x; int y; int * column; int * row;
\r
8584 *column = EventToSquare(x, BOARD_WIDTH);
\r
8585 if (flipView && *column >= 0)
\r
8586 *column = BOARD_WIDTH - 1 - *column;
\r
8587 *row = EventToSquare(y, BOARD_HEIGHT);
\r
8588 if (!flipView && *row >= 0)
\r
8589 *row = BOARD_HEIGHT - 1 - *row;
\r
8594 #undef Max /* just in case */
\r
8596 #define Max(a, b) ((a) > (b) ? (a) : (b))
\r
8597 #define Min(a, b) ((a) < (b) ? (a) : (b))
\r
8600 SetRect(rect, x, y, width, height)
\r
8601 XRectangle * rect; int x; int y; int width; int height;
\r
8605 rect->width = width;
\r
8606 rect->height = height;
\r
8609 /* Test if two frames overlap. If they do, return
\r
8610 intersection rect within old and location of
\r
8611 that rect within new. */
\r
8614 Intersect(old, new, size, area, pt)
\r
8615 XPoint * old; XPoint * new;
\r
8616 int size; XRectangle * area; XPoint * pt;
\r
8618 if (old->x > new->x + size || new->x > old->x + size ||
\r
8619 old->y > new->y + size || new->y > old->y + size) {
\r
8622 SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0),
\r
8623 size - abs(old->x - new->x), size - abs(old->y - new->y));
\r
8624 pt->x = Max(old->x - new->x, 0);
\r
8625 pt->y = Max(old->y - new->y, 0);
\r
8630 /* For two overlapping frames, return the rect(s)
\r
8631 in the old that do not intersect with the new. */
\r
8634 CalcUpdateRects(old, new, size, update, nUpdates)
\r
8635 XPoint * old; XPoint * new; int size;
\r
8636 XRectangle update[]; int * nUpdates;
\r
8640 /* If old = new (shouldn't happen) then nothing to draw */
\r
8641 if (old->x == new->x && old->y == new->y) {
\r
8645 /* Work out what bits overlap. Since we know the rects
\r
8646 are the same size we don't need a full intersect calc. */
\r
8648 /* Top or bottom edge? */
\r
8649 if (new->y > old->y) {
\r
8650 SetRect(&(update[count]), old->x, old->y, size, new->y - old->y);
\r
8652 } else if (old->y > new->y) {
\r
8653 SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y),
\r
8654 size, old->y - new->y);
\r
8657 /* Left or right edge - don't overlap any update calculated above. */
\r
8658 if (new->x > old->x) {
\r
8659 SetRect(&(update[count]), old->x, Max(new->y, old->y),
\r
8660 new->x - old->x, size - abs(new->y - old->y));
\r
8662 } else if (old->x > new->x) {
\r
8663 SetRect(&(update[count]), new->x + size, Max(new->y, old->y),
\r
8664 old->x - new->x, size - abs(new->y - old->y));
\r
8668 *nUpdates = count;
\r
8671 /* Generate a series of frame coords from start->mid->finish.
\r
8672 The movement rate doubles until the half way point is
\r
8673 reached, then halves back down to the final destination,
\r
8674 which gives a nice slow in/out effect. The algorithmn
\r
8675 may seem to generate too many intermediates for short
\r
8676 moves, but remember that the purpose is to attract the
\r
8677 viewers attention to the piece about to be moved and
\r
8678 then to where it ends up. Too few frames would be less
\r
8682 Tween(start, mid, finish, factor, frames, nFrames)
\r
8683 XPoint * start; XPoint * mid;
\r
8684 XPoint * finish; int factor;
\r
8685 XPoint frames[]; int * nFrames;
\r
8687 int fraction, n, count;
\r
8691 /* Slow in, stepping 1/16th, then 1/8th, ... */
\r
8693 for (n = 0; n < factor; n++)
\r
8695 for (n = 0; n < factor; n++) {
\r
8696 frames[count].x = start->x + (mid->x - start->x) / fraction;
\r
8697 frames[count].y = start->y + (mid->y - start->y) / fraction;
\r
8699 fraction = fraction / 2;
\r
8703 frames[count] = *mid;
\r
8706 /* Slow out, stepping 1/2, then 1/4, ... */
\r
8708 for (n = 0; n < factor; n++) {
\r
8709 frames[count].x = finish->x - (finish->x - mid->x) / fraction;
\r
8710 frames[count].y = finish->y - (finish->y - mid->y) / fraction;
\r
8712 fraction = fraction * 2;
\r
8717 /* Draw a piece on the screen without disturbing what's there */
\r
8720 SelectGCMask(piece, clip, outline, mask)
\r
8721 ChessSquare piece; GC * clip; GC * outline; Pixmap * mask;
\r
8725 /* Bitmap for piece being moved. */
\r
8726 if (appData.monoMode) {
\r
8727 *mask = *pieceToSolid(piece);
\r
8728 } else if (useImages) {
\r
8730 *mask = xpmMask[piece];
\r
8732 *mask = ximMaskPm[piece%(int)BlackPawn];
\r
8735 *mask = *pieceToSolid(piece);
\r
8738 /* GC for piece being moved. Square color doesn't matter, but
\r
8739 since it gets modified we make a copy of the original. */
\r
8740 if (White(piece)) {
\r
8741 if (appData.monoMode)
\r
8742 source = bwPieceGC;
\r
8744 source = wlPieceGC;
\r
8746 if (appData.monoMode)
\r
8747 source = wbPieceGC;
\r
8749 source = blPieceGC;
\r
8751 XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
\r
8753 /* Outline only used in mono mode and is not modified */
\r
8755 *outline = bwPieceGC;
\r
8757 *outline = wbPieceGC;
\r
8761 OverlayPiece(piece, clip, outline, dest)
\r
8762 ChessSquare piece; GC clip; GC outline; Drawable dest;
\r
8767 /* Draw solid rectangle which will be clipped to shape of piece */
\r
8768 XFillRectangle(xDisplay, dest, clip,
\r
8769 0, 0, squareSize, squareSize);
\r
8770 if (appData.monoMode)
\r
8771 /* Also draw outline in contrasting color for black
\r
8772 on black / white on white cases */
\r
8773 XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
\r
8774 0, 0, squareSize, squareSize, 0, 0, 1);
\r
8776 /* Copy the piece */
\r
8781 XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
\r
8783 0, 0, squareSize, squareSize,
\r
8788 /* Animate the movement of a single piece */
\r
8791 BeginAnimation(anim, piece, startColor, start)
\r
8793 ChessSquare piece;
\r
8799 /* The old buffer is initialised with the start square (empty) */
\r
8800 BlankSquare(0, 0, startColor, EmptySquare, anim->saveBuf);
\r
8801 anim->prevFrame = *start;
\r
8803 /* The piece will be drawn using its own bitmap as a matte */
\r
8804 SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask);
\r
8805 XSetClipMask(xDisplay, anim->pieceGC, mask);
\r
8809 AnimationFrame(anim, frame, piece)
\r
8812 ChessSquare piece;
\r
8814 XRectangle updates[4];
\r
8815 XRectangle overlap;
\r
8819 /* Save what we are about to draw into the new buffer */
\r
8820 XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC,
\r
8821 frame->x, frame->y, squareSize, squareSize,
\r
8824 /* Erase bits of the previous frame */
\r
8825 if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) {
\r
8826 /* Where the new frame overlapped the previous,
\r
8827 the contents in newBuf are wrong. */
\r
8828 XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC,
\r
8829 overlap.x, overlap.y,
\r
8830 overlap.width, overlap.height,
\r
8832 /* Repaint the areas in the old that don't overlap new */
\r
8833 CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count);
\r
8834 for (i = 0; i < count; i++)
\r
8835 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8836 updates[i].x - anim->prevFrame.x,
\r
8837 updates[i].y - anim->prevFrame.y,
\r
8838 updates[i].width, updates[i].height,
\r
8839 updates[i].x, updates[i].y);
\r
8841 /* Easy when no overlap */
\r
8842 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8843 0, 0, squareSize, squareSize,
\r
8844 anim->prevFrame.x, anim->prevFrame.y);
\r
8847 /* Save this frame for next time round */
\r
8848 XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC,
\r
8849 0, 0, squareSize, squareSize,
\r
8851 anim->prevFrame = *frame;
\r
8853 /* Draw piece over original screen contents, not current,
\r
8854 and copy entire rect. Wipes out overlapping piece images. */
\r
8855 OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf);
\r
8856 XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC,
\r
8857 0, 0, squareSize, squareSize,
\r
8858 frame->x, frame->y);
\r
8862 EndAnimation (anim, finish)
\r
8866 XRectangle updates[4];
\r
8867 XRectangle overlap;
\r
8871 /* The main code will redraw the final square, so we
\r
8872 only need to erase the bits that don't overlap. */
\r
8873 if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) {
\r
8874 CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count);
\r
8875 for (i = 0; i < count; i++)
\r
8876 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8877 updates[i].x - anim->prevFrame.x,
\r
8878 updates[i].y - anim->prevFrame.y,
\r
8879 updates[i].width, updates[i].height,
\r
8880 updates[i].x, updates[i].y);
\r
8882 XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC,
\r
8883 0, 0, squareSize, squareSize,
\r
8884 anim->prevFrame.x, anim->prevFrame.y);
\r
8889 FrameSequence(anim, piece, startColor, start, finish, frames, nFrames)
\r
8891 ChessSquare piece; int startColor;
\r
8892 XPoint * start; XPoint * finish;
\r
8893 XPoint frames[]; int nFrames;
\r
8897 BeginAnimation(anim, piece, startColor, start);
\r
8898 for (n = 0; n < nFrames; n++) {
\r
8899 AnimationFrame(anim, &(frames[n]), piece);
\r
8900 FrameDelay(appData.animSpeed);
\r
8902 EndAnimation(anim, finish);
\r
8905 /* Main control logic for deciding what to animate and how */
\r
8908 AnimateMove(board, fromX, fromY, toX, toY)
\r
8915 ChessSquare piece;
\r
8917 XPoint start, finish, mid;
\r
8918 XPoint frames[kFactor * 2 + 1];
\r
8919 int nFrames, startColor, endColor;
\r
8921 /* Are we animating? */
\r
8922 if (!appData.animate || appData.blindfold)
\r
8925 if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return;
\r
8926 piece = board[fromY][fromX];
\r
8927 if (piece >= EmptySquare) return;
\r
8932 hop = (piece == WhiteKnight || piece == BlackKnight);
\r
8935 if (appData.debugMode) {
\r
8936 printf("AnimateMove: piece %d %s from %d,%d to %d,%d \n",
\r
8937 piece, hop ? "hops" : "slides", fromX, fromY, toX, toY);
\r
8940 ScreenSquare(fromX, fromY, &start, &startColor);
\r
8941 ScreenSquare(toX, toY, &finish, &endColor);
\r
8944 /* Knight: make diagonal movement then straight */
\r
8945 if (abs(toY - fromY) < abs(toX - fromX)) {
\r
8946 mid.x = start.x + (finish.x - start.x) / 2;
\r
8950 mid.y = start.y + (finish.y - start.y) / 2;
\r
8953 mid.x = start.x + (finish.x - start.x) / 2;
\r
8954 mid.y = start.y + (finish.y - start.y) / 2;
\r
8957 /* Don't use as many frames for very short moves */
\r
8958 if (abs(toY - fromY) + abs(toX - fromX) <= 2)
\r
8959 Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);
\r
8961 Tween(&start, &mid, &finish, kFactor, frames, &nFrames);
\r
8962 FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames);
\r
8964 /* Be sure end square is redrawn */
\r
8965 damage[toY][toX] = True;
\r
8969 DragPieceBegin(x, y)
\r
8972 int boardX, boardY, color;
\r
8975 /* Are we animating? */
\r
8976 if (!appData.animateDragging || appData.blindfold)
\r
8979 /* Figure out which square we start in and the
\r
8980 mouse position relative to top left corner. */
\r
8981 BoardSquare(x, y, &boardX, &boardY);
\r
8982 player.startBoardX = boardX;
\r
8983 player.startBoardY = boardY;
\r
8984 ScreenSquare(boardX, boardY, &corner, &color);
\r
8985 player.startSquare = corner;
\r
8986 player.startColor = color;
\r
8988 /* Start from exactly where the piece is. This can be confusing
\r
8989 if you start dragging far from the center of the square; most
\r
8990 or all of the piece can be over a different square from the one
\r
8991 the mouse pointer is in. */
\r
8992 player.mouseDelta.x = x - corner.x;
\r
8993 player.mouseDelta.y = y - corner.y;
\r
8995 /* As soon as we start dragging, the piece will jump slightly to
\r
8996 be centered over the mouse pointer. */
\r
8997 player.mouseDelta.x = squareSize/2;
\r
8998 player.mouseDelta.y = squareSize/2;
\r
9000 /* Initialise animation */
\r
9001 player.dragPiece = PieceForSquare(boardX, boardY);
\r
9002 /* Sanity check */
\r
9003 if (player.dragPiece >= 0 && player.dragPiece < EmptySquare) {
\r
9004 player.dragActive = True;
\r
9005 BeginAnimation(&player, player.dragPiece, color, &corner);
\r
9006 /* Mark this square as needing to be redrawn. Note that
\r
9007 we don't remove the piece though, since logically (ie
\r
9008 as seen by opponent) the move hasn't been made yet. */
\r
9009 damage[boardY][boardX] = True;
\r
9011 player.dragActive = False;
\r
9016 DragPieceMove(x, y)
\r
9021 /* Are we animating? */
\r
9022 if (!appData.animateDragging || appData.blindfold)
\r
9025 /* Sanity check */
\r
9026 if (! player.dragActive)
\r
9028 /* Move piece, maintaining same relative position
\r
9029 of mouse within square */
\r
9030 corner.x = x - player.mouseDelta.x;
\r
9031 corner.y = y - player.mouseDelta.y;
\r
9032 AnimationFrame(&player, &corner, player.dragPiece);
\r
9034 if (appData.highlightDragging) {
\r
9035 int boardX, boardY;
\r
9036 BoardSquare(x, y, &boardX, &boardY);
\r
9037 SetHighlights(fromX, fromY, boardX, boardY);
\r
9043 DragPieceEnd(x, y)
\r
9046 int boardX, boardY, color;
\r
9049 /* Are we animating? */
\r
9050 if (!appData.animateDragging || appData.blindfold)
\r
9053 /* Sanity check */
\r
9054 if (! player.dragActive)
\r
9056 /* Last frame in sequence is square piece is
\r
9057 placed on, which may not match mouse exactly. */
\r
9058 BoardSquare(x, y, &boardX, &boardY);
\r
9059 ScreenSquare(boardX, boardY, &corner, &color);
\r
9060 EndAnimation(&player, &corner);
\r
9062 /* Be sure end square is redrawn */
\r
9063 damage[boardY][boardX] = True;
\r
9065 /* This prevents weird things happening with fast successive
\r
9066 clicks which on my Sun at least can cause motion events
\r
9067 without corresponding press/release. */
\r
9068 player.dragActive = False;
\r
9071 /* Handle expose event while piece being dragged */
\r
9076 if (!player.dragActive || appData.blindfold)
\r
9079 /* What we're doing: logically, the move hasn't been made yet,
\r
9080 so the piece is still in it's original square. But visually
\r
9081 it's being dragged around the board. So we erase the square
\r
9082 that the piece is on and draw it at the last known drag point. */
\r
9083 BlankSquare(player.startSquare.x, player.startSquare.y,
\r
9084 player.startColor, EmptySquare, xBoardWindow);
\r
9085 AnimationFrame(&player, &player.prevFrame, player.dragPiece);
\r
9086 damage[player.startBoardY][player.startBoardX] = TRUE;
\r
9090 SetProgramStats( FrontEndProgramStats * stats )
\r
9093 // [HGM] done, but perhaps backend should call this directly?
\r
9094 EngineOutputUpdate( stats );
\r