home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / szachy / gnu / amyboard-3.2.pl2 / xboard.c < prev    next >
C/C++ Source or Header  |  1995-03-08  |  116KB  |  4,084 lines

  1. /*
  2.  * xboard.c -- X front end for XBoard
  3.  * $Id: xboard.c,v 1.42 1995/03/09 00:43:28 mann Exp $
  4.  *
  5.  * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
  6.  * Enhancements Copyright 1992-95 Free Software Foundation, Inc.
  7.  *
  8.  * The following terms apply to Digital Equipment Corporation's copyright
  9.  * interest in XBoard:
  10.  * ------------------------------------------------------------------------
  11.  * All Rights Reserved
  12.  *
  13.  * Permission to use, copy, modify, and distribute this software and its
  14.  * documentation for any purpose and without fee is hereby granted,
  15.  * provided that the above copyright notice appear in all copies and that
  16.  * both that copyright notice and this permission notice appear in
  17.  * supporting documentation, and that the name of Digital not be
  18.  * used in advertising or publicity pertaining to distribution of the
  19.  * software without specific, written prior permission.
  20.  *
  21.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  22.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  23.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  24.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  25.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  26.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  27.  * SOFTWARE.
  28.  * ------------------------------------------------------------------------
  29.  *
  30.  * The following terms apply to the enhanced version of XBoard distributed
  31.  * by the Free Software Foundation:
  32.  * ------------------------------------------------------------------------
  33.  * This program is free software; you can redistribute it and/or modify
  34.  * it under the terms of the GNU General Public License as published by
  35.  * the Free Software Foundation; either version 2 of the License, or
  36.  * (at your option) any later version.
  37.  *
  38.  * This program is distributed in the hope that it will be useful,
  39.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  40.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  41.  * GNU General Public License for more details.
  42.  *
  43.  * You should have received a copy of the GNU General Public License
  44.  * along with this program; if not, write to the Free Software
  45.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  46.  * ------------------------------------------------------------------------
  47.  *
  48.  * See the file ChangeLog for a revision history.
  49.  */
  50.  
  51. #include <stdio.h>
  52. #include <ctype.h>
  53. #include <signal.h>
  54. #include <errno.h>
  55. #include <sys/types.h>
  56. #include <sys/stat.h>
  57. #include <pwd.h>
  58.  
  59. #if !OMIT_SOCKETS
  60. # if HAVE_SYS_SOCKET_H
  61. #  include <sys/socket.h>
  62. #  include <netinet/in.h>
  63. #  include <netdb.h>
  64. # else /* not HAVE_SYS_SOCKET_H */
  65. #  if HAVE_LAN_SOCKET_H
  66. #   include <lan/socket.h>
  67. #   include <lan/in.h>
  68. #   include <lan/netdb.h>
  69. #  else /* not HAVE_LAN_SOCKET_H */
  70. #   define OMIT_SOCKETS 1
  71. #  endif /* not HAVE_LAN_SOCKET_H */
  72. # endif /* not HAVE_SYS_SOCKET_H */
  73. #endif /* !OMIT_SOCKETS */
  74.  
  75. #if STDC_HEADERS
  76. # include <stdlib.h>
  77. # include <string.h>
  78. #else /* not STDC_HEADERS */
  79. extern char *getenv();
  80. # if HAVE_STRING_H
  81. #  include <string.h>
  82. # else /* not HAVE_STRING_H */
  83. #  include <strings.h>
  84. # endif /* not HAVE_STRING_H */
  85. #endif /* not STDC_HEADERS */
  86.  
  87. #if HAVE_SYS_FCNTL_H
  88. # include <sys/fcntl.h>
  89. #else /* not HAVE_SYS_FCNTL_H */
  90. # if HAVE_FCNTL_H
  91. #  include <fcntl.h>
  92. # endif /* HAVE_FCNTL_H */
  93. #endif /* not HAVE_SYS_FCNTL_H */
  94.  
  95. #if HAVE_SYS_SYSTEMINFO_H
  96. # include <sys/systeminfo.h>
  97. #endif /* HAVE_SYS_SYSTEMINFO_H */
  98.  
  99. #if HAVE_UNISTD_H
  100. # include <unistd.h>
  101. #endif
  102.  
  103. #if HAVE_SYS_WAIT_H
  104. # include <sys/wait.h>
  105. #endif
  106.  
  107. #include <X11/Intrinsic.h>
  108. #include <X11/StringDefs.h>
  109. #include <X11/Shell.h>
  110. #include <X11/Xaw/Dialog.h>
  111. #include <X11/Xaw/Form.h>
  112. #include <X11/Xaw/List.h>
  113. #include <X11/Xaw/Label.h>
  114. #include <X11/Xaw/SimpleMenu.h>
  115. #include <X11/Xaw/SmeBSB.h>
  116. #include <X11/Xaw/SmeLine.h>
  117. #include <X11/Xaw/Box.h>
  118. #include <X11/Xaw/MenuButton.h>
  119. #include <X11/cursorfont.h>
  120. #include <X11/Xaw/Text.h>
  121. #include <X11/Xaw/AsciiText.h>
  122.  
  123. #include "common.h"
  124. #include "frontend.h"
  125. #include "backend.h"
  126. #include "moves.h"
  127. #include "xboard.h"
  128. #include "childio.h"
  129. #include "bitmaps.h"
  130.  
  131. typedef struct {
  132.     String string;
  133.     XtActionProc proc;
  134. } MenuItem;
  135.  
  136. typedef struct {
  137.     String name;
  138.     MenuItem *mi;
  139. } Menu;
  140.  
  141. typedef int (*FileProc) P((FILE *f, int n, char *title));
  142.  
  143. void main P((int argc, char **argv));
  144. void CmailSigHandler P((int sig));
  145. void IntSigHandler P((int sig));
  146. void CreateGCs P((void));
  147. void CreatePieces P((void));
  148. void CreatePieceMenus P((void));
  149. Widget CreateMenuBar P((Menu *mb));
  150. Widget CreateButtonBar P ((MenuItem *mi));
  151. char *FindFont P((char *pattern, int targetPxlSize));
  152. void PieceMenuPopup P((Widget w, XEvent *event,
  153.                String *params, Cardinal *num_params));
  154. static void PieceMenuSelect P((Widget w, ChessSquare piece, caddr_t junk));
  155. void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[],
  156.            u_int wreq, u_int hreq));
  157. void CreateGrid P((void));
  158. int EventToSquare P((int x));
  159. void DrawSquare P((int row, int column, ChessSquare piece));
  160. void EventProc P((Widget widget, caddr_t unused, XEvent *event));
  161. void HandleUserMove P((Widget w, XEvent *event,
  162.              String *prms, Cardinal *nprms));
  163. void WhiteClock P((Widget w, XEvent *event,
  164.            String *prms, Cardinal *nprms));
  165. void BlackClock P((Widget w, XEvent *event,
  166.            String *prms, Cardinal *nprms));
  167. void DrawPositionProc P((Widget w, XEvent *event,
  168.              String *prms, Cardinal *nprms));
  169. void XDrawPosition P((Widget w, /*Boolean*/int repaint, 
  170.              Board board));
  171. void CommentPopUp P((char *title, char *label));
  172. void CommentPopDown P((void));
  173. void CommentCallback P((Widget w, XtPointer client_data,
  174.             XtPointer call_data));
  175. void FileNamePopUp P((char *label, char *def,
  176.               FileProc proc, char *openMode));
  177. void FileNameCallback P((Widget w, XtPointer client_data,
  178.              XtPointer call_data));
  179. void FileNameAction P((Widget w, XEvent *event,
  180.                String *prms, Cardinal *nprms));
  181. void PromotionPopUp P((void));
  182. void PromotionCallback P((Widget w, XtPointer client_data,
  183.               XtPointer call_data));
  184. void EditCommentPopDown P((void));
  185. void EditCommentCallback P((Widget w, XtPointer client_data,
  186.                 XtPointer call_data));
  187. void ErrorPopDown P((void));
  188. void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
  189. void ResetProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  190. void LoadGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  191. void LoadNextGameProc P((Widget w, XEvent *event, String *prms,
  192.              Cardinal *nprms));
  193. void LoadPrevGameProc P((Widget w, XEvent *event, String *prms,
  194.              Cardinal *nprms));
  195. void ReloadGameProc P((Widget w, XEvent *event, String *prms,
  196.                Cardinal *nprms));
  197. void LoadPositionProc P((Widget w, XEvent *event,
  198.              String *prms, Cardinal *nprms));
  199. void SaveGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  200. void SavePositionProc P((Widget w, XEvent *event,
  201.              String *prms, Cardinal *nprms));
  202. void MailMoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  203. void ReloadCmailGameProc P((Widget w, XEvent *event, String *prms,
  204.                 Cardinal *nprms));
  205. void QuitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  206. void PauseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  207. void MachineBlackProc P((Widget w, XEvent *event, String *prms,
  208.              Cardinal *nprms));
  209. void MachineWhiteProc P((Widget w, XEvent *event,
  210.              String *prms, Cardinal *nprms));
  211. void TwoMachinesProc P((Widget w, XEvent *event, String *prms,
  212.             Cardinal *nprms));
  213. void IcsClientProc P((Widget w, XEvent *event, String *prms,
  214.               Cardinal *nprms));
  215. void EditGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  216. void EditPositionProc P((Widget w, XEvent *event,
  217.              String *prms, Cardinal *nprms));
  218. void EditCommentProc P((Widget w, XEvent *event,
  219.             String *prms, Cardinal *nprms));
  220. void AcceptProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  221. void DeclineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  222. void CallFlagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  223. void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  224. void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  225. void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  226. void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  227. void StopObservingProc P((Widget w, XEvent *event, String *prms,
  228.               Cardinal *nprms));
  229. void StopExaminingProc P((Widget w, XEvent *event, String *prms,
  230.               Cardinal *nprms));
  231. void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  232. void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  233. void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  234. void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  235. void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  236. void TruncateGameProc P((Widget w, XEvent *event, String *prms,
  237.              Cardinal *nprms));
  238. void RetractMoveProc P((Widget w, XEvent *event, String *prms,
  239.             Cardinal *nprms));
  240. void MoveNowProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  241. void AlwaysQueenProc P((Widget w, XEvent *event, String *prms,
  242.             Cardinal *nprms));
  243. void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  244. void AutobsProc P((Widget w, XEvent *event, String *prms,
  245.             Cardinal *nprms));
  246. void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  247. void BellProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  248. void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  249. void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
  250.              Cardinal *nprms));
  251. void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  252. void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
  253.                Cardinal *nprms));
  254. void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
  255.              Cardinal *nprms));
  256. void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  257. void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  258. void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  259. void AboutProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  260. void NothingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  261. void Iconify P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
  262. void DisplayMove P((int moveNumber));
  263. void DisplayTitle P((char *title));
  264. void Usage P((void));
  265. void ICSInitScript P((void));
  266.  
  267. /*
  268. * XBoard depends on Xt R4 or higher
  269. */
  270. int xtVersion = XtSpecificationRelease;
  271.  
  272. int xScreen;
  273. Display *xDisplay;
  274. Window xBoardWindow;
  275. Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor;
  276. GC lightSquareGC, darkSquareGC, lineGC, wdPieceGC, wlPieceGC,
  277.   bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC;
  278. Pixmap solidPawnBitmap, solidRookBitmap, solidKnightBitmap,
  279.   solidBishopBitmap, solidQueenBitmap, solidKingBitmap,
  280.   outlinePawnBitmap, outlineRookBitmap, outlineKnightBitmap,
  281.   outlineBishopBitmap, outlineQueenBitmap, outlineKingBitmap,
  282.   iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
  283. Widget shellWidget, formWidget, boardWidget, messageWidget, titleWidget,
  284.   whiteTimerWidget, blackTimerWidget, titleWidget, widgetList[16], 
  285.   commentShell, promotionShell, whitePieceMenu, blackPieceMenu,
  286.   menuBarWidget, buttonBarWidget, editShell, errorShell;
  287. XSegment gridSegments[(BOARD_SIZE + 1) * 2];
  288. Font clockFontID, coordFontID;
  289. XFontStruct *clockFontStruct, *coordFontStruct;
  290. XtAppContext appContext;
  291.  
  292. FileProc fileProc;
  293. char *fileOpenMode;
  294.  
  295. Position commentX = -1, commentY = -1;
  296. Dimension commentW, commentH;
  297. static BoardSize boardSize = Large;
  298.  
  299. int squareSize = LARGE_SQUARE_SIZE, fromX = -1,
  300.   fromY = -1, toX, toY, commentUp = False, filenameUp = False,
  301.   promotionUp = False, pmFromX = -1, pmFromY = -1, editUp = False,
  302.   errorUp = False, errorExitStatus = -1, lineGap;
  303. Pixel timerForegroundPixel, timerBackgroundPixel;
  304. Pixel buttonForegroundPixel, buttonBackgroundPixel;
  305. char *chessDir, *programName;
  306.  
  307. MenuItem fileMenu[] = {
  308.     {"Reset Game", ResetProc},
  309.     {"----", NothingProc},
  310.     {"Load Game", LoadGameProc},
  311.     {"Load Next Game", LoadNextGameProc},
  312.     {"Load Previous Game", LoadPrevGameProc},
  313.     {"Reload Same Game", ReloadGameProc},
  314.     {"Load Position", LoadPositionProc},
  315.     {"----", NothingProc},
  316.     {"Save Game", SaveGameProc},
  317.     {"Save Position", SavePositionProc},
  318.     {"----", NothingProc},
  319.     {"Mail Move", MailMoveProc},
  320.     {"Reload CMail Message", ReloadCmailGameProc},
  321.     {"----", NothingProc},
  322.     {"Exit", QuitProc},
  323.     {NULL, NULL}
  324. };
  325.  
  326. MenuItem modeMenu[] = {
  327.     {"Pause", PauseProc},
  328.     {"Edit Comment", EditCommentProc},
  329.     {"----", NothingProc},
  330.     {"Machine White", MachineWhiteProc},
  331.     {"Machine Black", MachineBlackProc},
  332.     {"Two Machines", TwoMachinesProc},
  333.     {"ICS Client", IcsClientProc},
  334.     {"Edit Game", EditGameProc},
  335.     {"Edit Position", EditPositionProc},
  336.     {NULL, NULL}
  337. };
  338.  
  339. MenuItem actionMenu[] = {
  340.     {"Accept", AcceptProc},
  341.     {"Decline", DeclineProc},
  342.     {"----", NothingProc},    
  343.     {"Call Flag", CallFlagProc},
  344.     {"Draw", DrawProc},
  345.     {"Adjourn", AdjournProc},
  346.     {"Abort", AbortProc},
  347.     {"Resign", ResignProc},
  348.     {"----", NothingProc},    
  349.     {"Stop Observing", StopObservingProc},
  350.     {"Stop Examining", StopExaminingProc},
  351.     {NULL, NULL}
  352. };
  353.  
  354. MenuItem stepMenu[] = {
  355.     {"Backward", BackwardProc},
  356.     {"Forward", ForwardProc},
  357.     {"Back to Start", ToStartProc},
  358.     {"Forward to End", ToEndProc},
  359.     {"Revert", RevertProc},
  360.     {"----", NothingProc},    
  361.     {"Truncate Game", TruncateGameProc},
  362.     {"----", NothingProc},    
  363.     {"Move Now", MoveNowProc},
  364.     {"Retract Move", RetractMoveProc},
  365.     {NULL, NULL}
  366. };    
  367.  
  368. MenuItem optionsMenu[] = {
  369.     {"Always Queen", AlwaysQueenProc},
  370.     {"Auto Flag", AutoflagProc},
  371.     {"Auto Observe", AutobsProc},
  372.     {"Auto Save", AutosaveProc},
  373.     {"Bell", BellProc},
  374.     {"Flip View", FlipViewProc},
  375.     {"Old Save Style", OldSaveStyleProc},
  376.     {"Quiet Play", QuietPlayProc},
  377.     {"Show Coords", ShowCoordsProc},
  378.     {"Show Thinking", ShowThinkingProc},
  379.     {NULL, NULL}
  380. };
  381.  
  382. MenuItem helpMenu[] = {
  383.     {"Hint", HintProc},
  384.     {"Book", BookProc},
  385.     {"About Game", AboutGameProc},
  386.     {"----", NothingProc},
  387.     {"About XBoard", AboutProc},
  388.     {NULL, NULL}
  389. };
  390.  
  391. Menu menuBar[] = {
  392.     {"File", fileMenu},
  393.     {"Mode", modeMenu},
  394.     {"Action", actionMenu},
  395.     {"Step", stepMenu},
  396.     {"Options", optionsMenu},
  397.     {"Help", helpMenu},
  398.     {NULL, NULL}
  399. };
  400.  
  401. #define PAUSE_BUTTON "P"
  402. MenuItem buttonBar[] = {
  403.     {"<<", ToStartProc},
  404.     {"<", BackwardProc},
  405.     {PAUSE_BUTTON, PauseProc},
  406.     {">", ForwardProc},
  407.     {">>", ToEndProc},
  408.     {NULL, NULL}
  409. };
  410.  
  411. #define PIECE_MENU_SIZE 10
  412. String pieceMenuStrings[PIECE_MENU_SIZE] = {
  413.     "----", "Pawn", "Knight", "Bishop", "Rook", "Queen", "King",
  414.     "----", "Empty square", "Clear board"
  415.   };
  416. /* must be in same order as PieceMenuStrings! */
  417. ChessSquare pieceMenuTranslation[2][PIECE_MENU_SIZE] = {
  418.     { (ChessSquare) 0, WhitePawn, WhiteKnight, WhiteBishop,
  419.     WhiteRook, WhiteQueen, WhiteKing,
  420.     (ChessSquare) 0, EmptySquare, ClearBoard },
  421.     { (ChessSquare) 0, BlackPawn, BlackKnight, BlackBishop,
  422.     BlackRook, BlackQueen, BlackKing,
  423.     (ChessSquare) 0, EmptySquare, ClearBoard },
  424. };
  425.  
  426. Arg shellArgs[] = {
  427.     { XtNwidth, 0 },
  428.     { XtNheight, 0 },
  429.     { XtNminWidth, 0 },
  430.     { XtNminHeight, 0 },
  431.     { XtNmaxWidth, 0 },
  432.     { XtNmaxHeight, 0 }
  433. };
  434.  
  435. Arg boardArgs[] = {
  436.     { XtNborderWidth, 0 },
  437.     { XtNwidth, 0 },
  438.     { XtNheight, 0 }
  439. };
  440.  
  441. Arg titleArgs[] = {
  442.     { XtNjustify, (XtArgVal) XtJustifyRight },
  443.     { XtNlabel, (XtArgVal) "starting..." },
  444.     { XtNresizable, (XtArgVal) True },
  445.     { XtNresize, (XtArgVal) False }
  446. };
  447.  
  448. Arg messageArgs[] = {
  449.     { XtNjustify, (XtArgVal) XtJustifyLeft },
  450.     { XtNlabel, (XtArgVal) "starting..." },
  451.     { XtNresizable, (XtArgVal) True },
  452.     { XtNresize, (XtArgVal) False }
  453. };
  454.  
  455. Arg timerArgs[] = {
  456.     { XtNborderWidth, 0 },
  457.     { XtNjustify, (XtArgVal) XtJustifyLeft }
  458. };
  459.  
  460. XtResource clientResources[] = {
  461.     { "whitePieceColor", "whitePieceColor", XtRString, sizeof(String),
  462.     XtOffset(AppDataPtr, whitePieceColor), XtRString,
  463.     WHITE_PIECE_COLOR },
  464.     { "blackPieceColor", "blackPieceColor", XtRString, sizeof(String),
  465.     XtOffset(AppDataPtr, blackPieceColor), XtRString,
  466.     BLACK_PIECE_COLOR },
  467.     { "lightSquareColor", "lightSquareColor", XtRString,
  468.     sizeof(String), XtOffset(AppDataPtr, lightSquareColor),
  469.     XtRString, LIGHT_SQUARE_COLOR }, 
  470.     { "darkSquareColor", "darkSquareColor", XtRString, sizeof(String),
  471.     XtOffset(AppDataPtr, darkSquareColor), XtRString,
  472.     DARK_SQUARE_COLOR },
  473.     { "movesPerSession", "movesPerSession", XtRInt, sizeof(int),
  474.     XtOffset(AppDataPtr, movesPerSession), XtRImmediate,
  475.     (XtPointer) MOVES_PER_SESSION },
  476.     { "initString", "initString", XtRString, sizeof(String),
  477.     XtOffset(AppDataPtr, initString), XtRString, INIT_STRING },
  478.     { "whiteString", "whiteString", XtRString, sizeof(String),
  479.     XtOffset(AppDataPtr, whiteString), XtRString, WHITE_STRING },
  480.     { "blackString", "blackString", XtRString, sizeof(String),
  481.     XtOffset(AppDataPtr, blackString), XtRString, BLACK_STRING },
  482.     { "firstChessProgram", "firstChessProgram", XtRString,
  483.     sizeof(String), XtOffset(AppDataPtr, firstChessProgram),
  484.     XtRString, FIRST_CHESS_PROGRAM },
  485.     { "secondChessProgram", "secondChessProgram", XtRString,
  486.     sizeof(String), XtOffset(AppDataPtr, secondChessProgram),
  487.     XtRString, SECOND_CHESS_PROGRAM },
  488.     { "noChessProgram", "noChessProgram", XtRBoolean,
  489.     sizeof(Boolean), XtOffset(AppDataPtr, noChessProgram),
  490.     XtRImmediate, (XtPointer) False },
  491.     { "firstHost", "firstHost", XtRString, sizeof(String),
  492.     XtOffset(AppDataPtr, firstHost), XtRString, FIRST_HOST },
  493.     { "secondHost", "secondHost", XtRString, sizeof(String),
  494.     XtOffset(AppDataPtr, secondHost), XtRString, SECOND_HOST },
  495.     { "bitmapDirectory", "bitmapDirectory", XtRString,
  496.     sizeof(String), XtOffset(AppDataPtr, bitmapDirectory),
  497.     XtRString, "" },
  498.     { "remoteShell", "remoteShell", XtRString, sizeof(String),
  499.     XtOffset(AppDataPtr, remoteShell), XtRString, REMOTE_SHELL },
  500.     { "remoteUser", "remoteUser", XtRString, sizeof(String),
  501.     XtOffset(AppDataPtr, remoteUser), XtRString, "" },
  502.     { "timeDelay", "timeDelay", XtRFloat, sizeof(float),
  503.     XtOffset(AppDataPtr, timeDelay), XtRString,
  504.     (XtPointer) TIME_DELAY_QUOTE },
  505.     { "timeControl", "timeControl", XtRString, sizeof(String),
  506.     XtOffset(AppDataPtr, timeControl), XtRString,
  507.     (XtPointer) TIME_CONTROL },
  508.     { "internetChessServerMode", "internetChessServerMode",
  509.     XtRBoolean, sizeof(Boolean),
  510.     XtOffset(AppDataPtr, icsActive), XtRImmediate,
  511.     (XtPointer) False },
  512.     { "internetChessServerHost", "internetChessServerHost",
  513.     XtRString, sizeof(String),
  514.     XtOffset(AppDataPtr, icsHost),
  515.     XtRString, (XtPointer) ICS_HOST },
  516.     { "internetChessServerPort", "internetChessServerPort",
  517.     XtRInt, sizeof(int),
  518.     XtOffset(AppDataPtr, icsPort), XtRImmediate,
  519.     (XtPointer) ICS_PORT },
  520.     { "internetChessServerCommPort", "internetChessServerCommPort",
  521.     XtRString, sizeof(String),
  522.     XtOffset(AppDataPtr, icsCommPort), XtRString,
  523.     ICS_COMM_PORT },
  524.     { "internetChessServerLogonScript", "internetChessServerLogonScript",
  525.     XtRString, sizeof(String),
  526.     XtOffset(AppDataPtr, icsLogon), XtRString,
  527.     ICS_LOGON },
  528.     { "useTelnet", "useTelnet", XtRBoolean, sizeof(Boolean),
  529.     XtOffset(AppDataPtr, useTelnet), XtRImmediate,
  530.     (XtPointer) False },
  531.     { "telnetProgram", "telnetProgram", XtRString, sizeof(String),
  532.     XtOffset(AppDataPtr, telnetProgram), XtRString, TELNET_PROGRAM },
  533.     { "gateway", "gateway", XtRString, sizeof(String),
  534.     XtOffset(AppDataPtr, gateway), XtRString, "" },
  535.     { "loadGameFile", "loadGameFile", XtRString, sizeof(String),
  536.     XtOffset(AppDataPtr, loadGameFile), XtRString, "" },
  537.     { "loadGameIndex", "loadGameIndex",
  538.     XtRInt, sizeof(int),
  539.     XtOffset(AppDataPtr, loadGameIndex), XtRImmediate,
  540.     (XtPointer) 1 },
  541.     { "saveGameFile", "saveGameFile", XtRString, sizeof(String),
  542.     XtOffset(AppDataPtr, saveGameFile), XtRString, "" },
  543.     { "autoSaveGames", "autoSaveGames", XtRBoolean,
  544.     sizeof(Boolean), XtOffset(AppDataPtr, autoSaveGames),
  545.     XtRImmediate, (XtPointer) False },
  546.     { "loadPositionFile", "loadPositionFile", XtRString,
  547.     sizeof(String), XtOffset(AppDataPtr, loadPositionFile),
  548.     XtRString, "" },
  549.     { "loadPositionIndex", "loadPositionIndex",
  550.     XtRInt, sizeof(int),
  551.     XtOffset(AppDataPtr, loadPositionIndex), XtRImmediate,
  552.     (XtPointer) 1 },
  553.     { "savePositionFile", "savePositionFile", XtRString,
  554.     sizeof(String), XtOffset(AppDataPtr, savePositionFile),
  555.     XtRString, "" },
  556.     { "matchMode", "matchMode", XtRBoolean, sizeof(Boolean),
  557.     XtOffset(AppDataPtr, matchMode), XtRImmediate, (XtPointer) False },
  558.     { "monoMode", "monoMode", XtRBoolean, sizeof(Boolean),
  559.     XtOffset(AppDataPtr, monoMode), XtRImmediate,
  560.     (XtPointer) False },
  561.     { "debugMode", "debugMode", XtRBoolean, sizeof(Boolean),
  562.     XtOffset(AppDataPtr, debugMode), XtRImmediate,
  563.     (XtPointer) False },
  564.     { "clockMode", "clockMode", XtRBoolean, sizeof(Boolean),
  565.     XtOffset(AppDataPtr, clockMode), XtRImmediate,
  566.     (XtPointer) True },
  567.     { "boardSize", "boardSize", XtRString, sizeof(String),
  568.     XtOffset(AppDataPtr, boardSize), XtRString, "" },
  569.     { "searchTime", "searchTime", XtRString, sizeof(String),
  570.     XtOffset(AppDataPtr, searchTime), XtRString,
  571.     (XtPointer) "" },
  572.     { "searchDepth", "searchDepth", XtRInt, sizeof(int),
  573.     XtOffset(AppDataPtr, searchDepth), XtRImmediate, 
  574.     (XtPointer) 0 },
  575.     { "showCoords", "showCoords", XtRBoolean, sizeof(Boolean),
  576.     XtOffset(AppDataPtr, showCoords), XtRImmediate,
  577.     (XtPointer) False },
  578.     { "showThinking", "showThinking", XtRBoolean, sizeof(Boolean),
  579.     XtOffset(AppDataPtr, showThinking), XtRImmediate,
  580.     (XtPointer) False },
  581.     { "clockFont", "clockFont", XtRString, sizeof(String),
  582.     XtOffset(AppDataPtr, clockFont), XtRString, CLOCK_FONT },
  583.     { "coordFont", "coordFont", XtRString, sizeof(String),
  584.     XtOffset(AppDataPtr, coordFont), XtRString, COORD_FONT },
  585.     { "ringBellAfterMoves", "ringBellAfterMoves",
  586.     XtRBoolean, sizeof(Boolean),
  587.     XtOffset(AppDataPtr, ringBellAfterMoves),
  588.     XtRImmediate, (XtPointer) False    },
  589.     { "autoCallFlag", "autoCallFlag", XtRBoolean,
  590.     sizeof(Boolean), XtOffset(AppDataPtr, autoCallFlag),
  591.     XtRImmediate, (XtPointer) False },
  592.     { "autoObserve", "autoObserve", XtRBoolean,
  593.     sizeof(Boolean), XtOffset(AppDataPtr, autoObserve),
  594.     XtRImmediate, (XtPointer) False },
  595.     { "flipView", "flipView", XtRBoolean,
  596.     sizeof(Boolean), XtOffset(AppDataPtr, flipView),
  597.     XtRImmediate, (XtPointer) False },
  598.     { "cmail", "cmailGameName", XtRString, sizeof(String),
  599.     XtOffset(AppDataPtr, cmailGameName), XtRString, "" },
  600.     { "alwaysPromoteToQueen", "alwaysPromoteToQueen", XtRBoolean,
  601.     sizeof(Boolean), XtOffset(AppDataPtr, alwaysPromoteToQueen),
  602.     XtRImmediate, (XtPointer) False },
  603.     { "oldSaveStyle", "oldSaveStyle", XtRBoolean,
  604.     sizeof(Boolean), XtOffset(AppDataPtr, oldSaveStyle),
  605.     XtRImmediate, (XtPointer) False },
  606.     { "quietPlay", "quietPlay", XtRBoolean,
  607.     sizeof(Boolean), XtOffset(AppDataPtr, quietPlay),
  608.     XtRImmediate, (XtPointer) False },
  609.     { "borderXoffset", "borderXoffset", XtRInt, sizeof(int),
  610.     XtOffset(AppDataPtr, borderXoffset), XtRImmediate,
  611.     (XtPointer) BORDER_X_OFFSET },
  612.     { "borderYoffset", "borderYOffset", XtRInt, sizeof(int),
  613.     XtOffset(AppDataPtr, borderYoffset), XtRImmediate,
  614.     (XtPointer) BORDER_Y_OFFSET },
  615.     { "titleInWindow", "titleInWindow", XtRBoolean,
  616.     sizeof(Boolean), XtOffset(AppDataPtr, titleInWindow),
  617.     XtRImmediate, (XtPointer) False },
  618. #ifdef ZIPPY
  619.     { "zippyTalk", "zippyTalk", XtRBoolean,
  620.     sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk),
  621.     XtRImmediate, (XtPointer) False },
  622.     { "zippyPlay", "zippyPlay", XtRBoolean,
  623.     sizeof(Boolean), XtOffset(AppDataPtr, zippyPlay),
  624.     XtRImmediate, (XtPointer) False },
  625. #endif
  626. };
  627.  
  628. Pixmap *pieceToSolid[] = {
  629.     &solidPawnBitmap, &solidRookBitmap, &solidKnightBitmap,
  630.     &solidBishopBitmap, &solidQueenBitmap, &solidKingBitmap,
  631.     &solidPawnBitmap, &solidRookBitmap, &solidKnightBitmap,
  632.     &solidBishopBitmap, &solidQueenBitmap, &solidKingBitmap
  633.   };
  634.  
  635. Pixmap *pieceToOutline[] = {
  636.     &outlinePawnBitmap, &outlineRookBitmap, &outlineKnightBitmap,
  637.     &outlineBishopBitmap, &outlineQueenBitmap, &outlineKingBitmap,
  638.     &outlinePawnBitmap, &outlineRookBitmap, &outlineKnightBitmap,
  639.     &outlineBishopBitmap, &outlineQueenBitmap, &outlineKingBitmap
  640.   };
  641.  
  642. XrmOptionDescRec shellOptions[] = {
  643.     { "-whitePieceColor", "whitePieceColor", XrmoptionSepArg, NULL },
  644.     { "-blackPieceColor", "blackPieceColor", XrmoptionSepArg, NULL },
  645.     { "-lightSquareColor", "lightSquareColor", XrmoptionSepArg, NULL },
  646.     { "-darkSquareColor", "darkSquareColor", XrmoptionSepArg, NULL },
  647.     { "-movesPerSession", "movesPerSession", XrmoptionSepArg, NULL },
  648.     { "-mps", "movesPerSession", XrmoptionSepArg, NULL },
  649.     { "-initString", "initString", XrmoptionSepArg, NULL },
  650.     { "-whiteString", "whiteString", XrmoptionSepArg, NULL },
  651.     { "-blackString", "blackString", XrmoptionSepArg, NULL },
  652.     { "-firstChessProgram", "firstChessProgram", XrmoptionSepArg, NULL },
  653.     { "-fcp", "firstChessProgram", XrmoptionSepArg, NULL },
  654.     { "-secondChessProgram", "secondChessProgram", XrmoptionSepArg, NULL },
  655.     { "-scp", "secondChessProgram", XrmoptionSepArg, NULL },
  656.     { "-noChessProgram", "noChessProgram", XrmoptionSepArg, NULL },
  657.     { "-ncp", "noChessProgram", XrmoptionNoArg, "True" },
  658.     { "-xncp", "noChessProgram", XrmoptionNoArg, "False" },
  659.     { "-firstHost", "firstHost", XrmoptionSepArg, NULL },
  660.     { "-fh", "firstHost", XrmoptionSepArg, NULL },
  661.     { "-secondHost", "secondHost", XrmoptionSepArg, NULL },
  662.     { "-sh", "secondHost", XrmoptionSepArg, NULL },
  663.     { "-bitmapDirectory", "bitmapDirectory", XrmoptionSepArg, NULL },
  664.     { "-bm", "bitmapDirectory", XrmoptionSepArg, NULL },
  665.     { "-remoteShell", "remoteShell", XrmoptionSepArg, NULL },
  666.     { "-rsh", "remoteShell", XrmoptionSepArg, NULL },
  667.     { "-remoteUser", "remoteUser", XrmoptionSepArg, NULL },
  668.     { "-ruser", "remoteUser", XrmoptionSepArg, NULL },
  669.     { "-timeDelay", "timeDelay", XrmoptionSepArg, NULL },
  670.     { "-td", "timeDelay", XrmoptionSepArg, NULL },
  671.     { "-timeControl", "timeControl", XrmoptionSepArg, NULL },
  672.     { "-tc", "timeControl", XrmoptionSepArg, NULL },
  673.     { "-internetChessServerMode", "internetChessServerMode",
  674.     XrmoptionSepArg, NULL },
  675.     { "-ics", "internetChessServerMode", XrmoptionNoArg, "True" },
  676.     { "-xics", "internetChessServerMode", XrmoptionNoArg, "False" },
  677.     { "-internetChessServerHost", "internetChessServerHost",
  678.     XrmoptionSepArg, NULL },
  679.     { "-icshost", "internetChessServerHost", XrmoptionSepArg, NULL },
  680.     { "-internetChessServerPort", "internetChessServerPort",
  681.     XrmoptionSepArg, NULL },
  682.     { "-icsport", "internetChessServerPort", XrmoptionSepArg, NULL },
  683.     { "-internetChessServerCommPort", "internetChessServerCommPort",
  684.     XrmoptionSepArg, NULL },
  685.     { "-icscomm", "internetChessServerCommPort", XrmoptionSepArg, NULL },
  686.     { "-internetChessServerLogonScript", "internetChessServerLogonScript",
  687.     XrmoptionSepArg, NULL },
  688.     { "-icslogon", "internetChessServerLogonScript", XrmoptionSepArg, NULL },
  689.     { "-useTelnet", "useTelnet", XrmoptionSepArg, NULL },
  690.     { "-telnet", "useTelnet", XrmoptionNoArg, "True" },
  691.     { "-xtelnet", "useTelnet", XrmoptionNoArg, "False" },
  692.     { "-telnetProgram", "telnetProgram", XrmoptionSepArg, NULL },
  693.     { "-gateway", "gateway", XrmoptionSepArg, NULL },
  694.     { "-loadGameFile", "loadGameFile", XrmoptionSepArg, NULL },
  695.     { "-lgf", "loadGameFile", XrmoptionSepArg, NULL },
  696.     { "-loadGameIndex", "loadGameIndex", XrmoptionSepArg, NULL },
  697.     { "-lgi", "loadGameIndex", XrmoptionSepArg, NULL },
  698.     { "-saveGameFile", "saveGameFile", XrmoptionSepArg, NULL },
  699.     { "-sgf", "saveGameFile", XrmoptionSepArg, NULL },
  700.     { "-autoSaveGames", "autoSaveGames", XrmoptionSepArg, NULL },
  701.     { "-autosave", "autoSaveGames", XrmoptionNoArg, "True" },
  702.     { "-xautosave", "autoSaveGames", XrmoptionNoArg, "False" },
  703.     { "-loadPositionFile", "loadPositionFile", XrmoptionSepArg, NULL },
  704.     { "-lpf", "loadPositionFile", XrmoptionSepArg, NULL },
  705.     { "-loadPositionIndex", "loadPositionIndex", XrmoptionSepArg, NULL },
  706.     { "-lpi", "loadPositionIndex", XrmoptionSepArg, NULL },
  707.     { "-savePositionFile", "savePositionFile", XrmoptionSepArg, NULL },
  708.     { "-spf", "savePositionFile", XrmoptionSepArg, NULL },
  709.     { "-matchMode", "matchMode", XrmoptionSepArg, NULL },
  710.     { "-mm", "matchMode", XrmoptionNoArg, "True" },
  711.     { "-xmm", "matchMode", XrmoptionNoArg, "False" },
  712.     { "-monoMode", "monoMode", XrmoptionSepArg, NULL },
  713.     { "-mono", "monoMode", XrmoptionNoArg, "True" },
  714.     { "-xmono", "monoMode", XrmoptionNoArg, "False" },
  715.     { "-debugMode", "debugMode", XrmoptionSepArg, NULL },
  716.     { "-debug", "debugMode", XrmoptionNoArg, "True" },
  717.     { "-xdebug", "debugMode", XrmoptionNoArg, "False" },
  718.     { "-clockMode", "clockMode", XrmoptionSepArg, NULL },
  719.     { "-clock", "clockMode", XrmoptionNoArg, "True" },
  720.     { "-xclock", "clockMode", XrmoptionNoArg, "False" },
  721.     { "-boardSize", "boardSize", XrmoptionSepArg, NULL },
  722.     { "-size", "boardSize", XrmoptionSepArg, NULL },
  723.     { "-searchTime", "searchTime", XrmoptionSepArg, NULL },
  724.     { "-st", "searchTime", XrmoptionSepArg, NULL },
  725.     { "-searchDepth", "searchDepth", XrmoptionSepArg, NULL },
  726.     { "-sd", "searchDepth", XrmoptionSepArg, NULL },
  727.     { "-showCoords", "showCoords", XrmoptionSepArg, NULL },
  728.     { "-coords", "showCoords", XrmoptionNoArg, "True" },
  729.     { "-xcoords", "showCoords", XrmoptionNoArg, "False" },
  730.     { "-showThinking", "showThinking", XrmoptionSepArg, NULL },
  731.     { "-thinking", "showThinking", XrmoptionNoArg, "True" },
  732.     { "-xthinking", "showThinking", XrmoptionNoArg, "False" },
  733.     { "-clockFont", "clockFont", XrmoptionSepArg, NULL },
  734.     { "-coordFont", "coordFont", XrmoptionSepArg, NULL },
  735.     { "-ringBellAfterMoves", "ringBellAfterMoves", XrmoptionSepArg, NULL },
  736.     { "-bell", "ringBellAfterMoves", XrmoptionNoArg, "True" },
  737.     { "-xbell", "ringBellAfterMoves", XrmoptionNoArg, "False" },
  738.     { "-autoCallFlag", "autoCallFlag", XrmoptionSepArg, NULL },
  739.     { "-autoflag", "autoCallFlag", XrmoptionNoArg, "True" },
  740.     { "-xautoflag", "autoCallFlag", XrmoptionNoArg, "False" },
  741.     { "-autoObserve", "autoObserve", XrmoptionSepArg, NULL },
  742.     { "-autobs", "autoObserve", XrmoptionNoArg, "True" },
  743.     { "-xautobs", "autoObserve", XrmoptionNoArg, "False" },
  744.     { "-flipView", "flipView", XrmoptionSepArg, NULL },
  745.     { "-flip", "flipView", XrmoptionNoArg, "True" },
  746.     { "-xflip", "flipView", XrmoptionNoArg, "False" },
  747.     { "-cmail", "cmailGameName", XrmoptionSepArg, NULL },
  748.     { "-alwaysPromoteToQueen", "alwaysPromoteToQueen",
  749.     XrmoptionSepArg, NULL },
  750.     { "-queen", "alwaysPromoteToQueen", XrmoptionNoArg, "True" },
  751.     { "-xqueen", "alwaysPromoteToQueen", XrmoptionNoArg, "False" },
  752.     { "-oldSaveStyle", "oldSaveStyle", XrmoptionSepArg, NULL },
  753.     { "-oldsave", "oldSaveStyle", XrmoptionNoArg, "True" },
  754.     { "-xoldsave", "oldSaveStyle", XrmoptionNoArg, "False" },
  755.     { "-quietPlay", "quietPlay", XrmoptionSepArg, NULL },
  756.     { "-quiet", "quietPlay", XrmoptionNoArg, "True" },
  757.     { "-xquiet", "quietPlay", XrmoptionNoArg, "False" },
  758.     { "-borderXoffset", "borderXoffset", XrmoptionSepArg, NULL },
  759.     { "-borderYoffset", "borderYoffset", XrmoptionSepArg, NULL },
  760.     { "-titleInWindow", "titleInWindow", XrmoptionSepArg, NULL },
  761.     { "-title", "titleInWindow", XrmoptionNoArg, "True" },
  762.     { "-xtitle", "titleInWindow", XrmoptionNoArg, "False" },
  763. #ifdef ZIPPY
  764.     { "-zippyTalk", "zippyTalk", XrmoptionSepArg, NULL },
  765.     { "-zt", "zippyTalk", XrmoptionNoArg, "True" },
  766.     { "-xzt", "zippyTalk", XrmoptionNoArg, "False" },
  767.     { "-zippyPlay", "zippyPlay", XrmoptionSepArg, NULL },
  768.     { "-zp", "zippyPlay", XrmoptionNoArg, "True" },
  769.     { "-xzp", "zippyPlay", XrmoptionNoArg, "False" },
  770. #endif
  771. };
  772.  
  773.  
  774. XtActionsRec boardActions[] = {
  775.     { "DrawPosition", DrawPositionProc },
  776.     { "HandleUserMove", HandleUserMove },
  777.     { "FileNameAction", FileNameAction },
  778.     { "PieceMenuPopup", PieceMenuPopup },
  779.     { "WhiteClock", WhiteClock },
  780.     { "BlackClock", BlackClock },
  781.     { "Iconify", Iconify },
  782.     { "ResetProc", ResetProc },
  783.     { "LoadGameProc", LoadGameProc },
  784.     { "LoadNextGameProc", LoadNextGameProc },
  785.     { "LoadPrevGameProc", LoadPrevGameProc },
  786.     { "ReloadGameProc", ReloadGameProc },
  787.     { "LoadPositionProc", LoadPositionProc },
  788.     { "SaveGameProc", SaveGameProc },
  789.     { "SavePositionProc", SavePositionProc },
  790.     { "ReloadCmailGameProc", ReloadCmailGameProc },
  791.     { "MailMoveProc", MailMoveProc },
  792.     { "QuitProc", QuitProc },
  793.     { "PauseProc", PauseProc },
  794.     { "MachineBlackProc", MachineBlackProc },
  795.     { "MachineWhiteProc", MachineWhiteProc },
  796.     { "TwoMachinesProc", TwoMachinesProc },
  797.     { "IcsClientProc", IcsClientProc },
  798.     { "EditGameProc", EditGameProc },
  799.     { "EditPositionProc", EditPositionProc },
  800.     { "AcceptProc", AcceptProc },
  801.     { "DeclineProc", DeclineProc },
  802.     { "CallFlagProc", CallFlagProc },
  803.     { "DrawProc", DrawProc },
  804.     { "AdjournProc", AdjournProc },
  805.     { "AbortProc", AbortProc },
  806.     { "ResignProc", ResignProc },
  807.     { "StopObservingProc", StopObservingProc },
  808.     { "StopExaminingProc", StopExaminingProc },
  809.     { "BackwardProc", BackwardProc },
  810.     { "ForwardProc", ForwardProc },
  811.     { "ToStartProc", ToStartProc },
  812.     { "ToEndProc", ToEndProc },
  813.     { "RevertProc", RevertProc },
  814.     { "TruncateGameProc", TruncateGameProc },
  815.     { "MoveNowProc", MoveNowProc },
  816.     { "RetractMoveProc", RetractMoveProc },
  817.     { "AlwaysQueenProc", AlwaysQueenProc },
  818.     { "AutoflagProc", AutoflagProc },
  819.     { "AutobsProc", AutobsProc },
  820.     { "AutosaveProc", AutosaveProc },
  821.     { "BellProc", BellProc },
  822.     { "FlipViewProc", FlipViewProc },
  823.     { "OldSaveStyleProc", OldSaveStyleProc },
  824.     { "QuietPlayProc", QuietPlayProc },
  825.     { "ShowCoordsProc", ShowCoordsProc },
  826.     { "ShowThinkingProc", ShowThinkingProc },
  827.     { "HintProc", HintProc },
  828.     { "BookProc", BookProc },
  829.     { "AboutGameProc", AboutGameProc },
  830.     { "AboutProc", AboutProc },
  831.     { "NothingProc", NothingProc },
  832. };
  833.      
  834. char globalTranslations[] =
  835.   "Shift<Key>r: ResignProc() \n \
  836.    <Key>r: ResetProc() \n \
  837.    <Key>g: LoadGameProc() \n \
  838.    Shift<Key>n: LoadNextGameProc() \n \
  839.    Shift<Key>p: LoadPrevGameProc() \n \
  840.    <Key>q: QuitProc() \n \
  841.    Shift<Key>f: ToEndProc() \n \
  842.    <Key>f: ForwardProc() \n \
  843.    Shift<Key>b: ToStartProc() \n \
  844.    <Key>b: BackwardProc() \n \
  845.    <Key>p: PauseProc() \n \
  846.    <Key>d: DrawProc() \n \
  847.    <Key>t: CallFlagProc() \n \
  848.    <Key>i: Iconify() \n \
  849.    <Key>c: Iconify() \n";
  850.  
  851. char boardTranslations[] =
  852.   "<Expose>: DrawPosition() \n \
  853.    <Btn1Down>: HandleUserMove() \n \
  854.    <Btn1Up>: HandleUserMove() \n \
  855.    <Btn2Down>: XawPositionSimpleMenu(menuW) PieceMenuPopup(menuW) \n \
  856.    <Btn3Down>: XawPositionSimpleMenu(menuB) PieceMenuPopup(menuB) \n \
  857.    <Message>WM_PROTOCOLS: QuitProc() \n";
  858.      
  859. char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
  860. char blackTranslations[] = "<BtnDown>: BlackClock()\n";
  861.      
  862. String xboardResources[] = {
  863.     DEFAULT_FONT,
  864.     "*Dialog*value.translations: #override \\n <Key>Return: FileNameAction()",
  865.     NULL
  866.   };
  867.      
  868. void main(argc, argv)
  869.      int argc;
  870.      char **argv;
  871. {
  872.     int i, j, clockFontPxlSize, coordFontPxlSize;
  873.     XSetWindowAttributes window_attributes;
  874.     Arg args[16];
  875.     Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
  876.     XrmValue vFrom, vTo;
  877.     XtTranslations tr;
  878.     XtGeometryResult gres;
  879.  
  880.     setbuf(stdout, NULL);
  881.     setbuf(stderr, NULL);
  882.     fromUserFP = stdin;
  883.     toUserFP = stdout;
  884.     debugFP = stderr;
  885.     
  886.     programName = strrchr(argv[0], '/');
  887.     if (programName == NULL)
  888.       programName = argv[0];
  889.     else
  890.       programName++;
  891.     
  892.     shellWidget =
  893.       XtAppInitialize(&appContext, "XBoard", shellOptions,
  894.               XtNumber(shellOptions),
  895.               &argc, argv, xboardResources, NULL, 0);
  896.     if (argc > 1)
  897.       Usage();
  898.     
  899.     if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
  900.     chessDir = ".";
  901.     } else {
  902.     if (chdir(chessDir) != 0) {
  903.         fprintf(stderr, "%s: can't cd to CHESSDIR: ", programName);
  904.         perror(chessDir);
  905.         exit(1);
  906.     }
  907.     }
  908.     
  909.     XtGetApplicationResources(shellWidget, (XtPointer) &appData,
  910.                   clientResources, XtNumber(clientResources),
  911.                   NULL, 0);
  912.  
  913.     InitBackEnd1();
  914.  
  915.     xDisplay = XtDisplay(shellWidget);
  916.     xScreen = DefaultScreen(xDisplay);
  917.  
  918.     /*
  919.      * Determine boardSize
  920.      */
  921.     if (*appData.boardSize == NULLCHAR) {
  922.     if (((DisplayWidth(xDisplay, xScreen) < 800) ||
  923.          (DisplayHeight(xDisplay, xScreen) < 800)))
  924.       boardSize = Medium;
  925.     else
  926.       boardSize = Large;
  927.     } else if (StrCaseCmp(appData.boardSize, "Large") == 0) {
  928.     boardSize = Large;
  929.     } else if (StrCaseCmp(appData.boardSize, "Medium") == 0) {
  930.     boardSize = Medium;
  931.     } else if (StrCaseCmp(appData.boardSize, "Small") == 0) {
  932.     boardSize = Small;
  933.     } else {
  934.     fprintf(stderr, "%s: bad boardSize option %s\n",
  935.         programName, appData.boardSize);
  936.     Usage();
  937.     }
  938.     switch (boardSize) {
  939.       case Small:
  940.     squareSize = SMALL_SQUARE_SIZE;
  941.     lineGap = SMALL_LINE_GAP;
  942.     clockFontPxlSize = 20;
  943.     coordFontPxlSize = 10;
  944.     break;
  945.       case Medium:
  946.     squareSize = MEDIUM_SQUARE_SIZE;
  947.     lineGap = MEDIUM_LINE_GAP;
  948.     clockFontPxlSize = 34;
  949.     coordFontPxlSize = 12;
  950.     break;
  951.       case Large:
  952.       default:
  953.     squareSize = LARGE_SQUARE_SIZE;
  954.     lineGap = LARGE_LINE_GAP;
  955.     clockFontPxlSize = 34;
  956.     coordFontPxlSize = 14;
  957.     break;
  958.     }
  959.     boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
  960.     XtSetArg(boardArgs[1], XtNwidth, boardWidth);
  961.     XtSetArg(boardArgs[2], XtNheight,
  962.          lineGap + BOARD_SIZE * (squareSize + lineGap));
  963.  
  964.     /*
  965.      * Determine what fonts to use.
  966.      */
  967.     appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
  968.     clockFontID = XLoadFont(xDisplay, appData.clockFont);
  969.     clockFontStruct = XQueryFont(xDisplay, clockFontID);
  970.     appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
  971.     coordFontID = XLoadFont(xDisplay, appData.coordFont);
  972.     coordFontStruct = XQueryFont(xDisplay, coordFontID);
  973.  
  974.     /*
  975.      * Detect if there are not enough colors are available and adapt.
  976.      */
  977.     if (DefaultDepth(xDisplay, xScreen) <= 2)
  978.       appData.monoMode = True;
  979.  
  980.     if (!appData.monoMode) {
  981.     vFrom.addr = (caddr_t) appData.lightSquareColor;
  982.     vFrom.size = strlen(appData.lightSquareColor);
  983.     XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
  984.     if (vTo.addr == NULL)
  985.       appData.monoMode = True;
  986.     else
  987.       lightSquareColor = *(Pixel *) vTo.addr;
  988.     }
  989.     if (!appData.monoMode) {
  990.     vFrom.addr = (caddr_t) appData.darkSquareColor;
  991.     vFrom.size = strlen(appData.darkSquareColor);
  992.     XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
  993.     if (vTo.addr == NULL)
  994.       appData.monoMode = True;
  995.     else
  996.       darkSquareColor = *(Pixel *) vTo.addr;
  997.     }
  998.     if (!appData.monoMode) {
  999.     vFrom.addr = (caddr_t) appData.whitePieceColor;
  1000.     vFrom.size = strlen(appData.whitePieceColor);
  1001.     XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
  1002.     if (vTo.addr == NULL)
  1003.       appData.monoMode = True;
  1004.     else
  1005.       whitePieceColor = *(Pixel *) vTo.addr;
  1006.     }
  1007.     if (!appData.monoMode) {
  1008.     vFrom.addr = (caddr_t) appData.blackPieceColor;
  1009.     vFrom.size = strlen(appData.blackPieceColor);
  1010.     XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
  1011.     if (vTo.addr == NULL)
  1012.       appData.monoMode = True;
  1013.     else
  1014.       blackPieceColor = *(Pixel *) vTo.addr;
  1015.     }
  1016.  
  1017.     if (appData.monoMode && appData.debugMode) {
  1018.     fprintf(stderr, "white pixel = 0x%lx, black pixel = 0x%lx\n",
  1019.         (unsigned long) XWhitePixel(xDisplay, xScreen),
  1020.         (unsigned long) XBlackPixel(xDisplay, xScreen));
  1021.     }
  1022.     
  1023.     XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
  1024.     
  1025.     /*
  1026.      * widget hierarchy
  1027.      */
  1028.     formWidget =
  1029.       XtCreateManagedWidget("form", formWidgetClass, shellWidget, NULL, 0);
  1030.     XtSetArg(args[0], XtNdefaultDistance, &sep);
  1031.     XtGetValues(formWidget, args, 1);
  1032.     
  1033.     j = 0;
  1034.     widgetList[j++] = menuBarWidget = CreateMenuBar(menuBar);
  1035.  
  1036.     widgetList[j++] = whiteTimerWidget =
  1037.       XtCreateWidget("whiteTime", labelWidgetClass,
  1038.              formWidget, timerArgs, XtNumber(timerArgs));
  1039.     XtSetArg(args[0], XtNfont, clockFontStruct);
  1040.     XtSetValues(whiteTimerWidget, args, 1);
  1041.     
  1042.     widgetList[j++] = blackTimerWidget =
  1043.       XtCreateWidget("blackTime", labelWidgetClass,
  1044.              formWidget, timerArgs, XtNumber(timerArgs));
  1045.     XtSetArg(args[0], XtNfont, clockFontStruct);
  1046.     XtSetValues(blackTimerWidget, args, 1);
  1047.     
  1048.     if (appData.titleInWindow) {
  1049.     widgetList[j++] = titleWidget = 
  1050.       XtCreateWidget("title", labelWidgetClass, formWidget,
  1051.              titleArgs, XtNumber(titleArgs));
  1052.     }
  1053.  
  1054.     widgetList[j++] = buttonBarWidget = CreateButtonBar(buttonBar);
  1055.  
  1056.     widgetList[j++] = messageWidget =
  1057.       XtCreateWidget("message", labelWidgetClass, formWidget,
  1058.              messageArgs, XtNumber(messageArgs));
  1059.     
  1060.     widgetList[j++] = boardWidget =
  1061.       XtCreateWidget("board", widgetClass, formWidget, boardArgs,
  1062.              XtNumber(boardArgs));
  1063.     
  1064.     XtManageChildren(widgetList, j);
  1065.     
  1066.     timerWidth = (boardWidth - sep) / 2;
  1067.     XtSetArg(args[0], XtNwidth, timerWidth);
  1068.     XtSetValues(whiteTimerWidget, args, 1);
  1069.     XtSetValues(blackTimerWidget, args, 1);
  1070.     
  1071.     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
  1072.     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
  1073.     XtGetValues(whiteTimerWidget, args, 2);
  1074.     
  1075.     XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
  1076.     XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
  1077.     XtGetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
  1078.  
  1079.     /*
  1080.      * formWidget uses these constraints but they are stored
  1081.      * in the children.
  1082.      */
  1083.     i = 0;
  1084.     XtSetArg(args[i], XtNfromHoriz, 0); i++;
  1085.     XtSetValues(menuBarWidget, args, i);
  1086.     if (appData.titleInWindow) {
  1087.     if (boardSize == Small) {
  1088.         i = 0;
  1089.         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
  1090.         XtSetValues(whiteTimerWidget, args, i);
  1091.         i = 0;
  1092.         XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
  1093.         XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
  1094.         XtSetValues(blackTimerWidget, args, i);
  1095.         i = 0;
  1096.         XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
  1097.             XtSetArg(args[i], XtNjustify, XtJustifyLeft); i++;
  1098.         XtSetValues(titleWidget, args, i);
  1099.         i = 0;
  1100.         XtSetArg(args[i], XtNfromVert, titleWidget); i++;
  1101.         XtSetValues(messageWidget, args, i);
  1102.         i = 0;
  1103.         XtSetArg(args[i], XtNfromVert, titleWidget); i++;
  1104.         XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
  1105.         XtSetValues(buttonBarWidget, args, i);
  1106.     } else {
  1107.         i = 0;
  1108.         XtSetArg(args[i], XtNfromVert, titleWidget); i++;
  1109.         XtSetValues(whiteTimerWidget, args, i);
  1110.         i = 0;
  1111.         XtSetArg(args[i], XtNfromVert, titleWidget); i++;
  1112.         XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
  1113.         XtSetValues(blackTimerWidget, args, i);
  1114.         i = 0;
  1115.         XtSetArg(args[i], XtNfromHoriz, menuBarWidget); i++;
  1116.         XtSetValues(titleWidget, args, i);
  1117.         i = 0;
  1118.         XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
  1119.         XtSetValues(messageWidget, args, i);
  1120.         i = 0;
  1121.         XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
  1122.         XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
  1123.         XtSetValues(buttonBarWidget, args, i);
  1124.     }
  1125.     } else {
  1126.     i = 0;
  1127.     XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
  1128.     XtSetValues(whiteTimerWidget, args, i);
  1129.     i = 0;
  1130.     XtSetArg(args[i], XtNfromVert, menuBarWidget); i++;
  1131.     XtSetArg(args[i], XtNfromHoriz, whiteTimerWidget); i++;
  1132.     XtSetValues(blackTimerWidget, args, i);
  1133.     i = 0;
  1134.     XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
  1135.     XtSetValues(messageWidget, args, i);
  1136.     i = 0;
  1137.     XtSetArg(args[i], XtNfromVert, whiteTimerWidget); i++;
  1138.     XtSetArg(args[i], XtNfromHoriz, messageWidget); i++;
  1139.     XtSetValues(buttonBarWidget, args, i);
  1140.     }
  1141.     i = 0;
  1142.     XtSetArg(args[0], XtNfromVert, messageWidget);
  1143.     XtSetValues(boardWidget, args, 1);
  1144.     
  1145.     XtRealizeWidget(shellWidget);
  1146.  
  1147.     /*
  1148.      * Correct the width of the message and title widgets.
  1149.      * It is not known why some systems need the extra fudge term.
  1150.      * The value "2" is probably larger than needed.
  1151.      */
  1152. #define WIDTH_FUDGE 2
  1153.     i = 0;
  1154.     XtSetArg(args[i], XtNwidth, &w);  i++;
  1155.     XtGetValues(buttonBarWidget, args, i);
  1156.     i = 0;
  1157.     XtSetArg(args[i], XtNborderWidth, &bor);  i++;
  1158.     XtSetArg(args[i], XtNheight, &h);  i++;
  1159.     XtGetValues(messageWidget, args, i);
  1160.  
  1161.     w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
  1162.     gres = XtMakeResizeRequest(messageWidget, w, h, &wr, &hr);
  1163.     if (gres != XtGeometryYes) {
  1164.     fprintf(stderr, "%s: messageWidget geometry error %d %d %d %d %d\n",
  1165.         programName, gres, w, h, wr, hr);
  1166.     }
  1167.  
  1168.     if (appData.titleInWindow) {
  1169.     i = 0;
  1170.     XtSetArg(args[i], XtNborderWidth, &bor); i++;
  1171.     XtSetArg(args[i], XtNheight, &h);  i++;
  1172.     XtGetValues(titleWidget, args, i);
  1173.     if (boardSize == Small) {
  1174.         w = boardWidth - 2*bor;
  1175.     } else {
  1176.         XtSetArg(args[0], XtNwidth, &w);
  1177.         XtGetValues(menuBarWidget, args, 1);
  1178.         w = boardWidth - w - sep - 2*bor - WIDTH_FUDGE;
  1179.     }
  1180.  
  1181.     gres = XtMakeResizeRequest(titleWidget, w, h, &wr, &hr);
  1182.     if (gres != XtGeometryYes) {
  1183.         fprintf(stderr,
  1184.             "%s: titleWidget geometry error %d %d %d %d %d\n",
  1185.             programName, gres, w, h, wr, hr);
  1186.     }
  1187.     }
  1188.     xBoardWindow = XtWindow(boardWidget);
  1189.     
  1190.     /* 
  1191.      * Create X checkmark bitmap and initialize option menu checks.
  1192.      */
  1193.     ReadBitmap(&xMarkPixmap, "checkmark.bm",
  1194.            checkmark_bits, checkmark_width, checkmark_height);
  1195.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  1196.     if (appData.alwaysPromoteToQueen) {
  1197.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
  1198.             args, 1);
  1199.     }
  1200.     if (appData.autoCallFlag) {
  1201.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
  1202.             args, 1);
  1203.     }
  1204.     if (appData.autoObserve) {
  1205.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
  1206.             args, 1);
  1207.     }
  1208.     if (appData.autoSaveGames) {
  1209.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
  1210.             args, 1);
  1211.     }
  1212.     if (appData.saveGameFile[0] != NULLCHAR) {
  1213.     /* Can't turn this off from menu */
  1214.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
  1215.             args, 1);
  1216.     XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
  1217.                False);
  1218.  
  1219.     }
  1220.     if (appData.ringBellAfterMoves) {
  1221.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Bell"),
  1222.             args, 1);
  1223.     }
  1224.     if (appData.showCoords) {
  1225.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
  1226.             args, 1);
  1227.     }
  1228.     if (appData.showThinking) {
  1229.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
  1230.             args, 1);
  1231.     }
  1232.     if (appData.oldSaveStyle) {
  1233.     XtSetValues(XtNameToWidget(menuBarWidget,
  1234.                    "menuOptions.Old Save Style"), args, 1);
  1235.     }
  1236.     if (appData.quietPlay) {
  1237.     XtSetValues(XtNameToWidget(menuBarWidget,
  1238.                    "menuOptions.Quiet Play"), args, 1);
  1239.     }
  1240.  
  1241.     /*
  1242.      * Create an icon.
  1243.      */
  1244.     ReadBitmap(&wIconPixmap, "icon_white.bm",
  1245.            icon_white_bits, icon_white_width, icon_white_height);
  1246.     ReadBitmap(&bIconPixmap, "icon_black.bm",
  1247.            icon_black_bits, icon_black_width, icon_black_height);
  1248.     iconPixmap = wIconPixmap;
  1249.     i = 0;
  1250.     XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
  1251.     XtSetValues(shellWidget, args, i);
  1252.     
  1253.     /*
  1254.      * Create a cursor for the board widget.
  1255.      */
  1256.     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
  1257.     XChangeWindowAttributes(xDisplay, xBoardWindow,
  1258.                 CWCursor, &window_attributes);
  1259.     
  1260.     /*
  1261.      * Inhibit shell resizing.
  1262.      */
  1263.     shellArgs[0].value = (XtArgVal) &w;
  1264.     shellArgs[1].value = (XtArgVal) &h;
  1265.     XtGetValues(shellWidget, shellArgs, 2);
  1266.     shellArgs[4].value = shellArgs[2].value = w;
  1267.     shellArgs[5].value = shellArgs[3].value = h;
  1268.     XtSetValues(shellWidget, &shellArgs[2], 4);
  1269.     
  1270.     CreateGCs();
  1271.     CreateGrid();
  1272.     CreatePieces();
  1273.     CreatePieceMenus();
  1274.     
  1275.     tr = XtParseTranslationTable(globalTranslations);
  1276.     XtAugmentTranslations(formWidget, tr);
  1277.     XtSetArg(args[0], XtNtranslations, &tr);
  1278.     XtGetValues(formWidget, args, 1);
  1279.     XtSetArg(args[0], XtNtranslations, tr);
  1280.     XtSetValues(boardWidget, args, 1);
  1281.     XtAugmentTranslations(boardWidget,
  1282.               XtParseTranslationTable(boardTranslations));
  1283.     XtAugmentTranslations(whiteTimerWidget,
  1284.               XtParseTranslationTable(whiteTranslations));
  1285.     XtAugmentTranslations(blackTimerWidget,
  1286.               XtParseTranslationTable(blackTranslations));
  1287.     
  1288.     XtAddEventHandler(boardWidget, ExposureMask | ButtonPressMask
  1289.               | ButtonReleaseMask | Button1MotionMask | KeyPressMask,
  1290.               False, (XtEventHandler) EventProc, NULL);
  1291.     
  1292.     InitBackEnd2();
  1293.     
  1294.     if (errorExitStatus == -1) {
  1295.     if (appData.icsActive) {
  1296.         ICSInitScript();
  1297.     }
  1298.  
  1299.     signal(SIGINT, IntSigHandler);
  1300.     signal(SIGTERM, IntSigHandler);
  1301.     if (*appData.cmailGameName != NULLCHAR) {
  1302.         signal(SIGUSR1, CmailSigHandler);
  1303.     }
  1304.     }
  1305.  
  1306.     XtAppMainLoop(appContext);
  1307. }
  1308.  
  1309. RETSIGTYPE
  1310. IntSigHandler(sig)
  1311.      int sig;
  1312. {
  1313.     ExitEvent(sig);
  1314. }
  1315.  
  1316. RETSIGTYPE
  1317. CmailSigHandler(sig)
  1318.      int sig;
  1319. {
  1320.     int dummy = 0;
  1321.     int error;
  1322.  
  1323.     signal(SIGUSR1, SIG_IGN);              /* suspend handler     */
  1324.  
  1325.     /* Activate call-back function CmailSigHandlerCallBack()             */
  1326.     OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
  1327.  
  1328.     signal(SIGUSR1, CmailSigHandler);          /* re-activate handler */
  1329. }
  1330.  
  1331. void CmailSigHandlerCallBack(isr, message, count, error)
  1332.      InputSourceRef isr;
  1333.      char *message;
  1334.      int count;
  1335.      int error;
  1336. {
  1337.     XtMapWidget(shellWidget);                       /* Open if iconified */
  1338.     XtPopup(shellWidget, XtGrabNone);               /* Raise if lowered  */
  1339.  
  1340.     ReloadCmailGameEvent(TRUE);                /* Reload cmail msg  */
  1341.  
  1342. }
  1343. /**** end signal code ****/
  1344.  
  1345. void Usage()
  1346. {
  1347.     fprintf(stderr, "Usage: %s\n", programName);
  1348.     fprintf(stderr, "\t-timeControl (or -tc) minutes[:seconds]\n");
  1349.     fprintf(stderr, "\t-movesPerSession (or -mps) number\n");
  1350.     fprintf(stderr, "\t-clockMode (True | False), or -[x]clock\n");
  1351.     fprintf(stderr, "\t-searchTime (or -st) minutes[:seconds]\n");
  1352.     fprintf(stderr, "\t-searchDepth (or -sd) number\n");
  1353.     fprintf(stderr, "\t-matchMode (True | False), or -[x]mm\n");
  1354.     fprintf(stderr, "\t-internetChessServerMode (True | False), or -[x]ics\n");
  1355.     fprintf(stderr, "\t-internetChessServerHost (or -icshost) host_name\n");
  1356.     fprintf(stderr, "\t-loadGameFile (or -lgf) file_name\n");
  1357.     fprintf(stderr, "\t-loadGameIndex (or -lgi) number\n");
  1358.     fprintf(stderr, "\t-boardSize (or -size) (Large | Medium | Small)\n");
  1359.     fprintf(stderr, "\t-noChessProgram (True | False), or -[x]ncp\n");
  1360.     fprintf(stderr, "\t-debugMode (True | False), or -[x]debug\n");
  1361.     fprintf(stderr, "See the man page for more options and information\n");
  1362.     exit(2);
  1363. }
  1364.  
  1365. void ICSInitScript()
  1366. {
  1367.     FILE *f;
  1368.     char buf[MSG_SIZ];
  1369.     char *p;
  1370.  
  1371.     f = fopen(appData.icsLogon, "r");
  1372.     if (f == NULL) {
  1373.     p = getenv("HOME");
  1374.     if (p != NULL) {
  1375.         strcpy(buf, p);
  1376.         strcat(buf, "/");
  1377.         strcat(buf, appData.icsLogon);
  1378.         f = fopen(buf, "r");
  1379.     }
  1380.     }
  1381.     if (f != NULL)
  1382.       ProcessICSInitScript(f);
  1383. }
  1384.  
  1385. void ResetFrontEnd()
  1386. {
  1387.     CommentPopDown();
  1388.     EditCommentPopDown();
  1389.     return;
  1390. }
  1391.  
  1392. typedef struct {
  1393.     char *name;
  1394.     Boolean value;
  1395. } Sensitivity;
  1396.  
  1397. void SetMenuSensitivity(sens)
  1398.      Sensitivity *sens;
  1399. {
  1400.     while (sens->name != NULL) {
  1401.     XtSetSensitive(XtNameToWidget(menuBarWidget, sens->name), sens->value);
  1402.     sens++;
  1403.     }
  1404. }
  1405.  
  1406. Sensitivity icsSensitivity[] = {
  1407.     { "menuFile.Mail Move", False },
  1408.     { "menuFile.Reload CMail Message", False },
  1409.     { "menuMode.Machine Black", False },
  1410.     { "menuMode.Machine White", False },
  1411.     { "menuMode.Two Machines", False },
  1412. #ifndef ZIPPY
  1413.     { "menuHelp.Hint", False },
  1414.     { "menuHelp.Book", False },
  1415.     { "menuStep.Move Now", False },
  1416.     { "menuOptions.Show Thinking", False },
  1417. #endif
  1418.     { NULL, False }
  1419. };
  1420.  
  1421. void SetICSMode()
  1422. {
  1423.     SetMenuSensitivity(icsSensitivity);
  1424. }
  1425.  
  1426. Sensitivity ncpSensitivity[] = {    
  1427.     { "menuFile.Mail Move", False },
  1428.     { "menuFile.Reload CMail Message", False },
  1429.     { "menuMode.Machine White", False },
  1430.     { "menuMode.Machine Black", False },
  1431.     { "menuMode.Two Machines", False },
  1432.     { "menuMode.ICS Client", False },
  1433.     { "Action", False },
  1434.     { "menuStep.Revert", False },
  1435.     { "menuStep.Move Now", False },
  1436.     { "menuStep.Retract Move", False },
  1437.     { "menuOptions.Auto Flag", False },
  1438.     { "menuOptions.Auto Observe", False },
  1439.     { "menuOptions.Bell", False },
  1440.     { "menuOptions.Quiet Play", False },
  1441.     { "menuOptions.Show Thinking", False },
  1442.     { "menuHelp.Hint", False },
  1443.     { "menuHelp.Book", False },
  1444.     { NULL, False }
  1445. };
  1446.  
  1447. void SetNCPMode()
  1448. {
  1449.     SetMenuSensitivity(ncpSensitivity);
  1450. }
  1451.  
  1452. Sensitivity gnuSensitivity[] = {    
  1453.     { "menuMode.ICS Client", False },
  1454.     { "menuAction.Accept", False },
  1455.     { "menuAction.Decline", False },
  1456.     { "menuAction.Draw", False },
  1457.     { "menuAction.Adjourn", False },
  1458.     { "menuAction.Stop Examining", False },
  1459.     { "menuAction.Stop Observing", False },
  1460.     { "menuStep.Revert", False },
  1461.     { "menuOptions.Auto Flag", False },
  1462.     { "menuOptions.Auto Observe", False },
  1463.     { "menuOptions.Quiet Play", False },
  1464.  
  1465.     /* The next two options rely on SetCmailMode being called *after*    */
  1466.     /* SetGNUMode so that when GNU is being used to give hints these     */
  1467.     /* menu options are still available                                  */
  1468.  
  1469.     { "menuFile.Mail Move", False },
  1470.     { "menuFile.Reload CMail Message", False },
  1471.     { NULL, False }
  1472. };
  1473.  
  1474. void SetGNUMode()
  1475. {
  1476.     SetMenuSensitivity(gnuSensitivity);
  1477. }
  1478.  
  1479. Sensitivity cmailSensitivity[] = {    
  1480.     { "Action", True },
  1481.     { "menuAction.Call Flag", False },
  1482.     { "menuAction.Draw", True },
  1483.     { "menuAction.Adjourn", False },
  1484.     { "menuAction.Abort", False },
  1485.     { "menuAction.Stop Observing", False },
  1486.     { "menuAction.Stop Examining", False },
  1487.     { "menuFile.Mail Move", True },
  1488.     { "menuFile.Reload CMail Message", True },
  1489.     { NULL, False }
  1490. };
  1491.  
  1492. void SetCmailMode()
  1493. {
  1494.     SetMenuSensitivity(cmailSensitivity);
  1495. }
  1496.  
  1497. #define Abs(n) ((n)<0 ? -(n) : (n))
  1498.  
  1499. /*
  1500.  * Find a font that matches "pattern" that is as close as
  1501.  * possible to the targetPxlSize.  Prefer fonts that are k
  1502.  * pixels smaller to fonts that are k pixels larger.  The
  1503.  * pattern must be in the X Consortium standard format, 
  1504.  * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
  1505.  * The return value should be freed with XtFree when no
  1506.  * longer needed.
  1507.  */
  1508. char *FindFont(pattern, targetPxlSize)
  1509.      char *pattern;
  1510.      int targetPxlSize;
  1511. {
  1512.     char **fonts, *p, *best;
  1513.     int i, j, nfonts, minerr, err, pxlSize;
  1514.     char errbuf[MSG_SIZ];
  1515.  
  1516.     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
  1517.     if (nfonts < 1) {
  1518.     sprintf(errbuf, "No fonts match pattern %s\n", pattern);
  1519.     DisplayFatalError(errbuf, 0, 2);
  1520.     }
  1521.     best = "";
  1522.     minerr = 999999;
  1523.     for (i=0; i<nfonts; i++) {
  1524.     j = 0;
  1525.     p = fonts[i];
  1526.     if (*p != '-') continue;
  1527.     while (j < 7) {
  1528.         if (*p == NULLCHAR) break;
  1529.         if (*p++ == '-') j++;
  1530.     }
  1531.     if (j < 7) continue;
  1532.     pxlSize = atoi(p);
  1533.     if (pxlSize == targetPxlSize) {
  1534.         best = fonts[i];
  1535.         break;
  1536.     }
  1537.     err = pxlSize - targetPxlSize;
  1538.     if (Abs(err) < Abs(minerr) ||
  1539.         (minerr > 0 && err < 0 && -err == minerr)) {
  1540.         best = fonts[i];
  1541.         minerr = err;
  1542.     }
  1543.     }
  1544.     p = (char *) XtMalloc(strlen(best) + 1);
  1545.     strcpy(p, best);
  1546.     XFreeFontNames(fonts);
  1547.     return p;
  1548. }
  1549.  
  1550. void CreateGCs()
  1551. {
  1552.     XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
  1553.       | GCBackground | GCFunction | GCPlaneMask;
  1554.     XGCValues gc_values;
  1555.     GC copyInvertedGC;
  1556.     
  1557.     gc_values.plane_mask = AllPlanes;
  1558.     gc_values.line_width = lineGap;
  1559.     gc_values.line_style = LineSolid;
  1560.     gc_values.function = GXcopy;
  1561.     
  1562.     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
  1563.     gc_values.background = XBlackPixel(xDisplay, xScreen);
  1564.     lineGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1565.     
  1566.     gc_values.background = XWhitePixel(xDisplay, xScreen);
  1567.     coordGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1568.     XSetFont(xDisplay, coordGC, coordFontID);
  1569.     
  1570.     if (appData.monoMode) {
  1571.     gc_values.foreground = XWhitePixel(xDisplay, xScreen);
  1572.     gc_values.background = XBlackPixel(xDisplay, xScreen);
  1573.     lightSquareGC = wbPieceGC 
  1574.       = XtGetGC(shellWidget, value_mask, &gc_values);
  1575.  
  1576.     gc_values.foreground = XBlackPixel(xDisplay, xScreen);
  1577.     gc_values.background = XWhitePixel(xDisplay, xScreen);
  1578.     darkSquareGC = bwPieceGC
  1579.       = XtGetGC(shellWidget, value_mask, &gc_values);
  1580.  
  1581.     if (DefaultDepth(xDisplay, xScreen) == 1) {
  1582.         /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
  1583.         gc_values.function = GXcopyInverted;
  1584.         copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1585.         gc_values.function = GXcopy;
  1586.         if (XBlackPixel(xDisplay, xScreen) == 1) {
  1587.         bwPieceGC = darkSquareGC;
  1588.         wbPieceGC = copyInvertedGC;
  1589.         } else {
  1590.         bwPieceGC = copyInvertedGC;
  1591.         wbPieceGC = lightSquareGC;
  1592.         }
  1593.     }
  1594.     } else {
  1595.     gc_values.foreground = lightSquareColor;
  1596.     gc_values.background = darkSquareColor;
  1597.     lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1598.     
  1599.     gc_values.foreground = darkSquareColor;
  1600.     gc_values.background = lightSquareColor;
  1601.     darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1602.     
  1603.     gc_values.foreground = whitePieceColor;
  1604.     gc_values.background = darkSquareColor;
  1605.     wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1606.     
  1607.     gc_values.foreground = whitePieceColor;
  1608.     gc_values.background = lightSquareColor;
  1609.     wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1610.     
  1611.     gc_values.foreground = blackPieceColor;
  1612.     gc_values.background = darkSquareColor;
  1613.     bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1614.     
  1615.     gc_values.foreground = blackPieceColor;
  1616.     gc_values.background = lightSquareColor;
  1617.     blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values);
  1618.     }
  1619. }
  1620.  
  1621. void CreatePieces()
  1622. {
  1623.     u_int ss = squareSize;
  1624.     XSynchronize(xDisplay, True); /* Work-around for xlib/xt
  1625.                      buffering bug */
  1626.     
  1627.     switch (boardSize) {
  1628.       case Small:
  1629.     ReadBitmap(&solidPawnBitmap,   "p40s.bm", p40s_bits, ss, ss);
  1630.     ReadBitmap(&solidKnightBitmap, "n40s.bm", n40s_bits, ss, ss);
  1631.     ReadBitmap(&solidBishopBitmap, "b40s.bm", b40s_bits, ss, ss);
  1632.     ReadBitmap(&solidRookBitmap,   "r40s.bm", r40s_bits, ss, ss);
  1633.     ReadBitmap(&solidQueenBitmap,  "q40s.bm", q40s_bits, ss, ss);
  1634.     ReadBitmap(&solidKingBitmap,   "k40s.bm", k40s_bits, ss, ss);
  1635.         break;
  1636.       case Medium:
  1637.     ReadBitmap(&solidPawnBitmap,   "p64s.bm", p64s_bits, ss, ss);
  1638.     ReadBitmap(&solidKnightBitmap, "n64s.bm", n64s_bits, ss, ss);
  1639.     ReadBitmap(&solidBishopBitmap, "b64s.bm", b64s_bits, ss, ss);
  1640.     ReadBitmap(&solidRookBitmap,   "r64s.bm", r64s_bits, ss, ss);
  1641.     ReadBitmap(&solidQueenBitmap,  "q64s.bm", q64s_bits, ss, ss);
  1642.     ReadBitmap(&solidKingBitmap,   "k64s.bm", k64s_bits, ss, ss);
  1643.         break;
  1644.       case Large:
  1645.     ReadBitmap(&solidPawnBitmap,   "p80s.bm", p80s_bits, ss, ss);
  1646.     ReadBitmap(&solidKnightBitmap, "n80s.bm", n80s_bits, ss, ss);
  1647.     ReadBitmap(&solidBishopBitmap, "b80s.bm", b80s_bits, ss, ss);
  1648.     ReadBitmap(&solidRookBitmap,   "r80s.bm", r80s_bits, ss, ss);
  1649.     ReadBitmap(&solidQueenBitmap,  "q80s.bm", q80s_bits, ss, ss);
  1650.     ReadBitmap(&solidKingBitmap,   "k80s.bm", k80s_bits, ss, ss);
  1651.         break;
  1652.     }
  1653.     
  1654.     if (appData.monoMode) {
  1655.     switch (boardSize) {
  1656.       case Small:
  1657.         ReadBitmap(&outlinePawnBitmap,   "p40o.bm", p40o_bits, ss, ss);
  1658.         ReadBitmap(&outlineKnightBitmap, "n40o.bm", n40o_bits, ss, ss);
  1659.         ReadBitmap(&outlineBishopBitmap, "b40o.bm", b40o_bits, ss, ss);
  1660.         ReadBitmap(&outlineRookBitmap,   "r40o.bm", r40o_bits, ss, ss);
  1661.         ReadBitmap(&outlineQueenBitmap,  "q40o.bm", q40o_bits, ss, ss);
  1662.         ReadBitmap(&outlineKingBitmap,   "k40o.bm", k40o_bits, ss, ss);
  1663.         break;
  1664.       case Medium:
  1665.         ReadBitmap(&outlinePawnBitmap,   "p64o.bm", p64o_bits, ss, ss);
  1666.         ReadBitmap(&outlineKnightBitmap, "n64o.bm", n64o_bits, ss, ss);
  1667.         ReadBitmap(&outlineBishopBitmap, "b64o.bm", b64o_bits, ss, ss);
  1668.         ReadBitmap(&outlineRookBitmap,   "r64o.bm", r64o_bits, ss, ss);
  1669.         ReadBitmap(&outlineQueenBitmap,  "q64o.bm", q64o_bits, ss, ss);
  1670.         ReadBitmap(&outlineKingBitmap,   "k64o.bm", k64o_bits, ss, ss);
  1671.         break;
  1672.       case Large:
  1673.         ReadBitmap(&outlinePawnBitmap,   "p80o.bm", p80o_bits, ss, ss);
  1674.         ReadBitmap(&outlineKnightBitmap, "n80o.bm", n80o_bits, ss, ss);
  1675.         ReadBitmap(&outlineBishopBitmap, "b80o.bm", b80o_bits, ss, ss);
  1676.         ReadBitmap(&outlineRookBitmap,   "r80o.bm", r80o_bits, ss, ss);
  1677.         ReadBitmap(&outlineQueenBitmap,  "q80o.bm", q80o_bits, ss, ss);
  1678.         ReadBitmap(&outlineKingBitmap,   "k80o.bm", k80o_bits, ss, ss);
  1679.         break;
  1680.     }
  1681.     }
  1682.     
  1683.     XSynchronize(xDisplay, False); /* Work-around for xlib/xt
  1684.                       buffering bug */
  1685. }
  1686.  
  1687. void ReadBitmap(pm, name, bits, wreq, hreq)
  1688.      Pixmap *pm;
  1689.      String name;
  1690.      unsigned char bits[];
  1691.      u_int wreq, hreq;
  1692. {
  1693.     int x_hot, y_hot;
  1694.     u_int w, h;
  1695.     int errcode;
  1696.     char msg[MSG_SIZ], fullname[MSG_SIZ];
  1697.     
  1698.     if (*appData.bitmapDirectory == NULLCHAR) {
  1699.     *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
  1700.                     wreq, hreq);
  1701.     } else {
  1702.         strcpy(fullname, appData.bitmapDirectory);
  1703.     strcat(fullname, "/");
  1704.     strcat(fullname, name);
  1705.     errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
  1706.                   &w, &h, pm, &x_hot, &y_hot);
  1707.     if (errcode != BitmapSuccess) {
  1708.         switch (errcode) {
  1709.           case BitmapOpenFailed:
  1710.         sprintf(msg, "Can't open bitmap file %s", fullname);
  1711.         break;
  1712.           case BitmapFileInvalid:
  1713.         sprintf(msg, "Invalid bitmap in file %s", fullname);
  1714.         break;
  1715.           case BitmapNoMemory:
  1716.         sprintf(msg, "Ran out of memory reading bitmap file %s",
  1717.             fullname);
  1718.         break;
  1719.           default:
  1720.         sprintf(msg, "Unknown XReadBitmapFile error %d on file %s",
  1721.             errcode, fullname);
  1722.         break;
  1723.         }
  1724.         DisplayFatalError(msg, 0, 1);
  1725.     }
  1726.     if (w != wreq || h != hreq) {
  1727.         sprintf(msg, "Bitmap is %dx%d, should be %dx%d; file %s",
  1728.             w, h, wreq, hreq, fullname);
  1729.         DisplayFatalError(msg, 0, 1);
  1730.     }
  1731.     }
  1732. }
  1733.  
  1734. void CreateGrid()
  1735. {
  1736.     int i;
  1737.     
  1738.     for (i = 0; i < BOARD_SIZE + 1; i++) {
  1739.     gridSegments[i].x1 = gridSegments[i + BOARD_SIZE + 1].y1 = 0;
  1740.     gridSegments[i].y1 = gridSegments[i].y2
  1741.       = lineGap / 2 + (i * (squareSize + lineGap));
  1742.     gridSegments[i].x2 = lineGap + BOARD_SIZE *
  1743.       (squareSize + lineGap);
  1744.     gridSegments[i + BOARD_SIZE + 1].x1 =
  1745.       gridSegments[i + BOARD_SIZE + 1].x2 = lineGap / 2
  1746.         + (i * (squareSize + lineGap));
  1747.     gridSegments[i + BOARD_SIZE + 1].y2 =
  1748.       BOARD_SIZE * (squareSize + lineGap);
  1749.     }
  1750. }
  1751.  
  1752. static void MenuBarSelect(w, addr, index)
  1753.      Widget w;
  1754.      caddr_t addr;
  1755.      caddr_t index;
  1756. {
  1757.     XtActionProc proc = (XtActionProc) addr;
  1758.  
  1759.     (proc)(NULL, NULL, NULL, NULL);
  1760. }
  1761.  
  1762. void CreateMenuBarPopup(parent, name, mb)
  1763.      Widget parent;
  1764.      String name;
  1765.      Menu *mb;
  1766. {
  1767.     int j;
  1768.     Widget menu, entry;
  1769.     MenuItem *mi;
  1770.     Arg args[16];
  1771.  
  1772.     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
  1773.                   parent, NULL, 0);
  1774.     j = 0;
  1775.     XtSetArg(args[j], XtNleftMargin, 20);   j++;
  1776.     XtSetArg(args[j], XtNrightMargin, 20);  j++;
  1777.     mi = mb->mi;
  1778.     while (mi->string != NULL) {
  1779.     if (strcmp(mi->string, "----") == 0) {
  1780.         entry = XtCreateManagedWidget(mi->string, smeLineObjectClass,
  1781.                       menu, args, j);
  1782.     } else {
  1783.         entry = XtCreateManagedWidget(mi->string, smeBSBObjectClass,
  1784.                       menu, args, j);
  1785.         XtAddCallback(entry, XtNcallback,
  1786.               (XtCallbackProc) MenuBarSelect,
  1787.               (caddr_t) mi->proc);
  1788.     }
  1789.     mi++;
  1790.     }
  1791. }    
  1792.  
  1793. Widget CreateMenuBar(mb)
  1794.      Menu *mb;
  1795. {
  1796.     int j;
  1797.     Widget anchor, menuBar;
  1798.     Arg args[16];
  1799.     char menuName[MSG_SIZ];
  1800.  
  1801.     j = 0;
  1802.     XtSetArg(args[j], XtNorientation, XtorientHorizontal);  j++;
  1803.     XtSetArg(args[j], XtNvSpace, 0);                        j++;
  1804.     XtSetArg(args[j], XtNborderWidth, 0);                   j++;
  1805.     menuBar = XtCreateWidget("menuBar", boxWidgetClass,
  1806.                  formWidget, args, j);
  1807.  
  1808.     while (mb->name != NULL) {
  1809.     strcpy(menuName, "menu");
  1810.     strcat(menuName, mb->name);
  1811.     j = 0;
  1812.     XtSetArg(args[j], XtNmenuName, XtNewString(menuName));  j++;
  1813.     XtSetArg(args[j], XtNborderWidth, 0);                   j++;
  1814.     anchor = XtCreateManagedWidget(mb->name, menuButtonWidgetClass,
  1815.                        menuBar, args, j);
  1816.     CreateMenuBarPopup(menuBar, menuName, mb);
  1817.     mb++;
  1818.     }
  1819.     return menuBar;
  1820. }
  1821.  
  1822. Widget CreateButtonBar(mi)
  1823.      MenuItem *mi;
  1824. {
  1825.     int j;
  1826.     Widget button, buttonBar;
  1827.     Arg args[16];
  1828.  
  1829.     j = 0;
  1830.     XtSetArg(args[j], XtNorientation, XtorientHorizontal);  j++;
  1831.     XtSetArg(args[j], XtNvSpace, 0);                        j++;
  1832.     XtSetArg(args[j], XtNborderWidth, 0);                   j++;
  1833.     buttonBar = XtCreateWidget("buttonBar", boxWidgetClass,
  1834.                    formWidget, args, j);
  1835.  
  1836.     while (mi->string != NULL) {
  1837.     j = 0;
  1838.     button = XtCreateManagedWidget(mi->string, commandWidgetClass,
  1839.                        buttonBar, args, j);
  1840.     XtAddCallback(button, XtNcallback,
  1841.               (XtCallbackProc) MenuBarSelect,
  1842.               (caddr_t) mi->proc);
  1843.     mi++;
  1844.     }
  1845.     return buttonBar;
  1846. }     
  1847.  
  1848. void CreatePieceMenus()
  1849. {
  1850.     int i;
  1851.     Widget entry;
  1852.     Arg args[16];
  1853.     ChessSquare selection;
  1854.     
  1855.     XtSetArg(args[0], XtNlabel, "White");
  1856.     whitePieceMenu = XtCreatePopupShell("menuW", simpleMenuWidgetClass,
  1857.                     boardWidget, args, 1);
  1858.     for (i = 0; i < PIECE_MENU_SIZE; i++) {
  1859.     String item = pieceMenuStrings[i];
  1860.     
  1861.     if (strcmp(item, "----") == 0) {
  1862.         entry = XtCreateManagedWidget(item, smeLineObjectClass,
  1863.                       whitePieceMenu, NULL, 0);
  1864.     } else {
  1865.         entry = XtCreateManagedWidget(item, smeBSBObjectClass,
  1866.                       whitePieceMenu, NULL, 0);
  1867.         selection = pieceMenuTranslation[0][i];
  1868.         XtAddCallback(entry, XtNcallback,
  1869.               (XtCallbackProc) PieceMenuSelect,
  1870.               (caddr_t) selection);
  1871.         if (selection == WhitePawn) {
  1872.         XtSetArg(args[0], XtNpopupOnEntry, entry);
  1873.         XtSetValues(whitePieceMenu, args, 1);
  1874.         }
  1875.     }
  1876.     }
  1877.     
  1878.     XtSetArg(args[0], XtNlabel, "Black");
  1879.     blackPieceMenu = XtCreatePopupShell("menuB", simpleMenuWidgetClass,
  1880.                     boardWidget, args, 1);
  1881.     for (i = 0; i < PIECE_MENU_SIZE; i++) {
  1882.     String item = pieceMenuStrings[i];
  1883.     
  1884.     if (strcmp(item, "----") == 0) {
  1885.         entry = XtCreateManagedWidget(item, smeLineObjectClass,
  1886.                       blackPieceMenu, NULL, 0);
  1887.     } else {
  1888.         entry = XtCreateManagedWidget(item, smeBSBObjectClass,
  1889.                       blackPieceMenu, NULL, 0);
  1890.         selection = pieceMenuTranslation[1][i];
  1891.         XtAddCallback(entry, XtNcallback,
  1892.               (XtCallbackProc) PieceMenuSelect,
  1893.               (caddr_t) selection);
  1894.         if (selection == BlackPawn) {
  1895.         XtSetArg(args[0], XtNpopupOnEntry, entry);
  1896.         XtSetValues(blackPieceMenu, args, 1);
  1897.         }
  1898.     }
  1899.     }
  1900.     
  1901.     XtRegisterGrabAction(PieceMenuPopup, True,
  1902.              (unsigned)(ButtonPressMask|ButtonReleaseMask),
  1903.              GrabModeAsync, GrabModeAsync);
  1904. }    
  1905.  
  1906. void PieceMenuPopup(w, event, params, num_params)
  1907.      Widget w;
  1908.      XEvent *event;
  1909.      String *params;
  1910.      Cardinal *num_params;
  1911. {
  1912.     if (event->type != ButtonPress) return;
  1913.     if (gameMode != EditPosition && gameMode != IcsExamining) return;
  1914.     
  1915.     if (((pmFromX = EventToSquare(event->xbutton.x)) < 0) ||
  1916.     ((pmFromY = EventToSquare(event->xbutton.y)) < 0)) {
  1917.     pmFromX = pmFromY = -1;
  1918.     return;
  1919.     }
  1920.     if (flipView)
  1921.       pmFromX = BOARD_SIZE - 1 - pmFromX;
  1922.     else
  1923.       pmFromY = BOARD_SIZE - 1 - pmFromY;
  1924.     
  1925.     XtPopupSpringLoaded(XtNameToWidget(boardWidget, params[0]));
  1926. }
  1927.  
  1928. static void PieceMenuSelect(w, piece, junk)
  1929.      Widget w;
  1930.      ChessSquare piece;
  1931.      caddr_t junk;
  1932. {
  1933.     if (pmFromX < 0 || pmFromY < 0) return;
  1934.     EditPositionMenuEvent(piece, pmFromX, pmFromY);
  1935. }
  1936.  
  1937. void WhiteClock(w, event, prms, nprms)
  1938.      Widget w;
  1939.      XEvent *event;
  1940.      String *prms;
  1941.      Cardinal *nprms;
  1942. {
  1943.     if (gameMode == EditPosition) {
  1944.     SetWhiteToPlayEvent();
  1945.     } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
  1946.     CallFlagEvent();
  1947.     }
  1948. }
  1949.  
  1950. void BlackClock(w, event, prms, nprms)
  1951.      Widget w;
  1952.      XEvent *event;
  1953.      String *prms;
  1954.      Cardinal *nprms;
  1955. {
  1956.     if (gameMode == EditPosition) {
  1957.     SetBlackToPlayEvent();
  1958.     } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
  1959.     CallFlagEvent();
  1960.     }
  1961. }
  1962.  
  1963.  
  1964. /*
  1965.  * If the user selects on a border boundary, return -1; if off the board,
  1966.  *   return -2.  Otherwise map the event coordinate to the square.
  1967.  */
  1968. int EventToSquare(x)
  1969.      int x;
  1970. {
  1971.     if (x <= 0) 
  1972.       return -2;
  1973.     if (x < lineGap)
  1974.       return -1;
  1975.     x -= lineGap;
  1976.     if ((x % (squareSize + lineGap)) >= squareSize)
  1977.       return -1;
  1978.     x /= (squareSize + lineGap);
  1979.     if (x >= BOARD_SIZE)
  1980.       return -2;
  1981.     return x;
  1982. }
  1983.  
  1984. void DrawSquare(row, column, piece)
  1985.      int row, column;
  1986.      ChessSquare piece;
  1987. {
  1988.     int square_color, x, y, direction, font_ascent, font_descent;
  1989.     char string[2];
  1990.     XCharStruct overall;
  1991.     
  1992.     if (flipView) {
  1993.     x = lineGap + ((BOARD_SIZE-1)-column) * 
  1994.       (squareSize + lineGap);
  1995.     y = lineGap + row * (squareSize + lineGap);
  1996.     } else {
  1997.     x = lineGap + column * (squareSize + lineGap);
  1998.     y = lineGap + ((BOARD_SIZE-1)-row) * 
  1999.       (squareSize + lineGap);
  2000.     }
  2001.     
  2002.     square_color = ((column + row) % 2) == 1;
  2003.     
  2004.     if (piece == EmptySquare) {
  2005.     XFillRectangle(xDisplay, xBoardWindow,
  2006.                square_color ? lightSquareGC : darkSquareGC,
  2007.                x, y, squareSize, squareSize);
  2008.     } else if (appData.monoMode) {
  2009.     if (DefaultDepth(xDisplay, xScreen) == 1) {
  2010.         /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
  2011.         if (square_color)
  2012.           XCopyArea(xDisplay, (int) piece < (int) BlackPawn
  2013.              ? *pieceToOutline[(int) piece]
  2014.              : *pieceToSolid[(int) piece],
  2015.              xBoardWindow, bwPieceGC, 0, 0,
  2016.              squareSize, squareSize, x, y);
  2017.         else
  2018.           XCopyArea(xDisplay, (int) piece < (int) BlackPawn
  2019.              ? *pieceToSolid[(int) piece]
  2020.              : *pieceToOutline[(int) piece],
  2021.              xBoardWindow, wbPieceGC, 0, 0,
  2022.              squareSize, squareSize, x, y);
  2023.     } else {
  2024.         if (square_color)
  2025.           XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
  2026.              ? *pieceToOutline[(int) piece]
  2027.              : *pieceToSolid[(int) piece],
  2028.              xBoardWindow, bwPieceGC, 0, 0,
  2029.              squareSize, squareSize, x, y, 1);
  2030.         else
  2031.           XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
  2032.              ? *pieceToSolid[(int) piece]
  2033.              : *pieceToOutline[(int) piece],
  2034.              xBoardWindow, wbPieceGC, 0, 0,
  2035.              squareSize, squareSize, x, y, 1);
  2036.     }
  2037.     } else {
  2038.     if (square_color)
  2039.       XCopyPlane(xDisplay, *pieceToSolid[(int) piece],
  2040.              xBoardWindow, (int) piece < (int) BlackPawn
  2041.              ? wlPieceGC : blPieceGC, 0, 0,
  2042.              squareSize, squareSize, x, y, 1);
  2043.     else
  2044.       XCopyPlane(xDisplay, *pieceToSolid[(int) piece],
  2045.              xBoardWindow, (int) piece < (int) BlackPawn
  2046.              ? wdPieceGC : bdPieceGC, 0, 0,
  2047.              squareSize, squareSize, x, y, 1);
  2048.     }
  2049.     string[1] = NULLCHAR;
  2050.     if (appData.showCoords && row == (flipView ? 7 : 0)) {
  2051.     string[0] = 'a' + column;
  2052.     XTextExtents(coordFontStruct, string, 1, &direction, 
  2053.              &font_ascent, &font_descent, &overall);
  2054.     if (appData.monoMode) {
  2055.         XDrawImageString(xDisplay, xBoardWindow, coordGC,
  2056.                  x + squareSize - overall.width - 2, 
  2057.                  y + squareSize - font_descent - 1, string, 1);
  2058.     } else {
  2059.         XDrawString(xDisplay, xBoardWindow, coordGC,
  2060.             x + squareSize - overall.width - 2, 
  2061.             y + squareSize - font_descent - 1, string, 1);
  2062.     }
  2063.     }
  2064.     if (appData.showCoords && column == (flipView ? 7 : 0)) {
  2065.     string[0] = '1' + row;
  2066.     XTextExtents(coordFontStruct, string, 1, &direction, 
  2067.              &font_ascent, &font_descent, &overall);
  2068.     if (appData.monoMode) {
  2069.         XDrawImageString(xDisplay, xBoardWindow, coordGC,
  2070.                  x + 2, y + font_ascent + 1, string, 1);
  2071.     } else {
  2072.         XDrawString(xDisplay, xBoardWindow, coordGC,
  2073.             x + 2, y + font_ascent + 1, string, 1);
  2074.     }        
  2075.     }   
  2076. }
  2077.  
  2078. void EventProc(widget, unused, event)
  2079.      Widget widget;
  2080.      caddr_t unused;
  2081.      XEvent *event;
  2082. {
  2083.     if (event->type == MappingNotify) {
  2084.     XRefreshKeyboardMapping((XMappingEvent *) event);
  2085.     return;
  2086.     }
  2087.     
  2088.     if (!XtIsRealized(widget))
  2089.       return;
  2090.     
  2091.     if ((event->type == ButtonPress) || (event->type == ButtonRelease))
  2092.       if (event->xbutton.button != Button1)
  2093.     return;
  2094.     
  2095.     switch (event->type) {
  2096.       case Expose:
  2097.     DrawPositionProc(widget, event, NULL, NULL);
  2098.     break;
  2099.       default:
  2100.     return;
  2101.     }
  2102. }
  2103.  
  2104.  
  2105. void DrawPosition(fullRedraw, board)
  2106.      /*Boolean*/int fullRedraw;
  2107.      Board board;
  2108. {
  2109.     XDrawPosition(boardWidget, fullRedraw, board);
  2110. }
  2111.  
  2112. /*
  2113.  * event handler for redrawing the board
  2114.  */
  2115. void XDrawPosition(w, repaint, board)
  2116.      Widget w;
  2117.      /*Boolean*/int repaint;
  2118.      Board board;
  2119. {
  2120.     int i, j;
  2121.     static int lastFlipView = 0;
  2122.     static int lastBoardValid = 0;
  2123.     static Board lastBoard;
  2124.     Arg args[16];
  2125.     
  2126.     if (board == NULL) {
  2127.     if (!lastBoardValid) return;
  2128.     board = lastBoard;
  2129.     }
  2130.  
  2131.     /*
  2132.      * It would be simpler to clear the window with XClearWindow()
  2133.      * but this causes a very distracting flicker.
  2134.      */
  2135.     
  2136.     if (!repaint && lastBoardValid && lastFlipView == flipView) {
  2137.     for (i = 0; i < BOARD_SIZE; i++)
  2138.       for (j = 0; j < BOARD_SIZE; j++)
  2139.         if (board[i][j] != lastBoard[i][j])
  2140.           DrawSquare(i, j, board[i][j]);
  2141.     } else {
  2142.     XDrawSegments(xDisplay, xBoardWindow, lineGC,
  2143.               gridSegments, (BOARD_SIZE + 1) * 2);
  2144.     
  2145.     for (i = 0; i < BOARD_SIZE; i++)
  2146.       for (j = 0; j < BOARD_SIZE; j++)
  2147.         DrawSquare(i, j, board[i][j]);
  2148.     }
  2149.     
  2150.     if (!lastBoardValid || lastFlipView != flipView) {
  2151.     XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None));
  2152.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"),
  2153.             args, 1);
  2154.     }
  2155.  
  2156.     CopyBoard(lastBoard, board);
  2157.     lastBoardValid = 1;
  2158.     lastFlipView = flipView;
  2159.     
  2160.     XSync(xDisplay, False);
  2161. }
  2162.  
  2163. /*
  2164.  * event handler for redrawing the board
  2165.  */
  2166. void DrawPositionProc(w, event, prms, nprms)
  2167.      Widget w;
  2168.      XEvent *event;
  2169.      String *prms;
  2170.      Cardinal *nprms;
  2171. {
  2172.     XDrawPosition(w, True, NULL);
  2173. }
  2174.  
  2175.  
  2176. /*
  2177.  * event handler for parsing user moves
  2178.  */
  2179. void HandleUserMove(w, event, prms, nprms)
  2180.      Widget w;
  2181.      XEvent *event;
  2182.      String *prms;
  2183.      Cardinal *nprms;
  2184. {
  2185.     int x, y;
  2186.     
  2187.     if (w != boardWidget)
  2188.       return;
  2189.     
  2190.     if (promotionUp) {
  2191.     XtPopdown(promotionShell);
  2192.     XtDestroyWidget(promotionShell);
  2193.     promotionUp = False;
  2194.     fromX = fromY = -1;
  2195.     }
  2196.     
  2197.     x = EventToSquare(event->xbutton.x);
  2198.     y = EventToSquare(event->xbutton.y);
  2199.     if (!flipView && y >= 0) {
  2200.     y = BOARD_SIZE - 1 - y;
  2201.     }
  2202.     if (flipView && x >= 0) {
  2203.     x = BOARD_SIZE - 1 - x;
  2204.     }
  2205.  
  2206.     switch (event->type) {
  2207.       case ButtonPress:
  2208.     if (errorExitStatus != -1) return;
  2209.     if (errorUp) ErrorPopDown();
  2210.     if (OKToStartUserMove(x, y)) {
  2211.         fromX = x;
  2212.         fromY = y;
  2213.     } else {
  2214.         fromX = fromY = -1;
  2215.     }
  2216.     break;
  2217.  
  2218.       case ButtonRelease:
  2219.     toX = x;
  2220.     toY = y;
  2221.     if (IsPromotion(fromX, fromY, toX, toY)) {
  2222.         if (appData.alwaysPromoteToQueen) {
  2223.         UserMoveEvent(fromX, fromY, toX, toY, 'q');
  2224.         fromX = fromY = -1;
  2225.         } else {
  2226.         PromotionPopUp();
  2227.         }
  2228.     } else {
  2229.         UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
  2230.         fromX = fromY = -1;
  2231.     }
  2232.     break;
  2233.     }
  2234.  
  2235. }
  2236.  
  2237. Widget CommentCreate(name, text, mutable, callback)
  2238.      char *name, *text;
  2239.      int /*Boolean*/ mutable;
  2240.      XtCallbackProc callback;
  2241. {
  2242.     Arg args[16];
  2243.     Widget shell, form, edit, b_ok, b_cancel, b_clear, b_close, b_edit;
  2244.     Dimension fw_width;
  2245.     int j;
  2246.  
  2247.     j = 0;
  2248.     XtSetArg(args[j], XtNwidth, &fw_width);  j++;
  2249.     XtGetValues(formWidget, args, j);
  2250.  
  2251.     j = 0;
  2252.     XtSetArg(args[j], XtNresizable, True);  j++;
  2253.     shell =
  2254.       XtCreatePopupShell(name, transientShellWidgetClass,
  2255.              shellWidget, args, j);
  2256.     j = 0;
  2257.     form =
  2258.       XtCreateManagedWidget("form", formWidgetClass, shell, args, j);
  2259.  
  2260.     j = 0;
  2261.     if (mutable) {
  2262.     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
  2263.     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
  2264.     }
  2265.     XtSetArg(args[j], XtNstring, text);  j++;
  2266.     XtSetArg(args[j], XtNtop, XtChainTop);  j++;
  2267.     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
  2268.     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
  2269.     XtSetArg(args[j], XtNright, XtChainRight);  j++;
  2270.     XtSetArg(args[j], XtNresizable, True);  j++;
  2271.     XtSetArg(args[j], XtNwidth, fw_width);  j++;  /*force wider than buttons*/
  2272.     XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded);  j++;
  2273.     XtSetArg(args[j], XtNautoFill, True);  j++;
  2274.     edit =
  2275.       XtCreateManagedWidget("edit", asciiTextWidgetClass, form, args, j);
  2276.  
  2277.     if (mutable) {
  2278.     j = 0;
  2279.     XtSetArg(args[j], XtNfromVert, edit);  j++;
  2280.     XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  2281.     XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  2282.     XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  2283.     XtSetArg(args[j], XtNright, XtChainLeft); j++;
  2284.     b_ok =
  2285.       XtCreateManagedWidget("ok", commandWidgetClass, form, args, j);
  2286.     XtAddCallback(b_ok, XtNcallback, callback, (XtPointer) 0);
  2287.  
  2288.     j = 0;
  2289.     XtSetArg(args[j], XtNfromVert, edit);  j++;
  2290.     XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;
  2291.     XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  2292.     XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  2293.     XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  2294.     XtSetArg(args[j], XtNright, XtChainLeft); j++;
  2295.     b_cancel =
  2296.       XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);
  2297.     XtAddCallback(b_cancel, XtNcallback, callback, (XtPointer) 0);
  2298.  
  2299.     j = 0;
  2300.     XtSetArg(args[j], XtNfromVert, edit);  j++;
  2301.     XtSetArg(args[j], XtNfromHoriz, b_cancel);  j++;
  2302.     XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  2303.     XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  2304.     XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  2305.     XtSetArg(args[j], XtNright, XtChainLeft); j++;
  2306.     b_clear =
  2307.       XtCreateManagedWidget("clear", commandWidgetClass, form, args, j);
  2308.     XtAddCallback(b_clear, XtNcallback, callback, (XtPointer) 0);
  2309.     } else {
  2310.     j = 0;
  2311.     XtSetArg(args[j], XtNfromVert, edit);  j++;
  2312.     XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  2313.     XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  2314.     XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  2315.     XtSetArg(args[j], XtNright, XtChainLeft); j++;
  2316.     b_close =
  2317.       XtCreateManagedWidget("close", commandWidgetClass, form, args, j);
  2318.     XtAddCallback(b_close, XtNcallback, callback, (XtPointer) 0);
  2319.  
  2320.     j = 0;
  2321.     XtSetArg(args[j], XtNfromVert, edit);  j++;
  2322.     XtSetArg(args[j], XtNfromHoriz, b_close);  j++;
  2323.     XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  2324.     XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  2325.     XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  2326.     XtSetArg(args[j], XtNright, XtChainLeft); j++;
  2327.     b_edit =
  2328.       XtCreateManagedWidget("edit", commandWidgetClass, form, args, j);
  2329.     XtAddCallback(b_edit, XtNcallback, callback, (XtPointer) 0);
  2330.     }
  2331.  
  2332.     if (commentX == -1) {
  2333.     Position y1, y2;
  2334.     int xx, yy;
  2335.     Window junk;
  2336.  
  2337.     j = 0;
  2338.     XtSetArg(args[j], XtNy, &y1); j++;
  2339.     XtGetValues(menuBarWidget, args, j);
  2340.     y1 -= appData.borderYoffset; /* offset by banner height */
  2341.     j = 0;
  2342.     XtSetArg(args[j], XtNy, &y2); j++;
  2343.     XtGetValues(messageWidget, args, j);
  2344.     commentW = fw_width - 16;
  2345.     commentH = y2 - y1;
  2346.  
  2347.     XSync(xDisplay, False);
  2348. #ifdef NOTDEF
  2349.     /* This code seems to tickle an X bug if it is executed too soon
  2350.        after xboard starts up.  The coordinates get transformed as if
  2351.        the main window was positioned at (0, 0).
  2352.     */
  2353.     XtTranslateCoords(shellWidget, (fw_width - commentW) / 2, y1,
  2354.               &commentX, &commentY);
  2355. #else /*!NOTDEF*/
  2356.         XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
  2357.                   RootWindowOfScreen(XtScreen(shellWidget)),
  2358.                   (fw_width - commentW) / 2, y1,
  2359.                   &xx, &yy, &junk);
  2360.     commentX = xx;
  2361.     commentY = yy;
  2362. #endif /*!NOTDEF*/
  2363.     }
  2364.     j = 0;
  2365.     XtSetArg(args[j], XtNheight, commentH);  j++;
  2366.     XtSetArg(args[j], XtNwidth, commentW);  j++;
  2367.     XtSetArg(args[j], XtNx, commentX - appData.borderXoffset);  j++;
  2368.     XtSetArg(args[j], XtNy, commentY - appData.borderYoffset);  j++;
  2369.     XtSetValues(shell, args, j);
  2370.  
  2371.     XtRealizeWidget(shell);
  2372.  
  2373.     return shell;
  2374. }
  2375.  
  2376. static int savedIndex;  /* gross that this is global */
  2377.  
  2378. void EditCommentPopUp(index, title, text)
  2379.      int index;
  2380.      char *title, *text;
  2381. {
  2382.     Widget edit;
  2383.     Arg args[16];
  2384.     int j;
  2385.  
  2386.     savedIndex = index;
  2387.     if (text == NULL) text = "";
  2388.  
  2389.     if (editShell == NULL) {
  2390.     editShell =
  2391.       CommentCreate(title, text, True, EditCommentCallback); 
  2392.     } else {
  2393.     edit = XtNameToWidget(editShell, "form.edit");
  2394.     j = 0;
  2395.     XtSetArg(args[j], XtNstring, text); j++;
  2396.     XtSetValues(edit, args, j);
  2397.     j = 0;
  2398.     XtSetArg(args[j], XtNiconName, (XtArgVal) title);   j++;
  2399.     XtSetArg(args[j], XtNtitle, (XtArgVal) title);      j++;
  2400.     XtSetValues(editShell, args, j);
  2401.     }
  2402.  
  2403.     XtPopup(editShell, XtGrabExclusive);
  2404.     XtSetKeyboardFocus(shellWidget, editShell);
  2405.  
  2406.     editUp = True;
  2407. }
  2408.  
  2409. void EditCommentCallback(w, client_data, call_data)
  2410.      Widget w;
  2411.      XtPointer client_data, call_data;
  2412. {
  2413.     String name, val;
  2414.     Arg args[16];
  2415.     int j;
  2416.     Widget edit;
  2417.  
  2418.     j = 0;
  2419.     XtSetArg(args[j], XtNlabel, &name);  j++;
  2420.     XtGetValues(w, args, j);
  2421.  
  2422.     if (strcmp(name, "ok") == 0) {
  2423.     edit = XtNameToWidget(editShell, "form.edit");
  2424.     j = 0;
  2425.     XtSetArg(args[j], XtNstring, &val); j++;
  2426.     XtGetValues(edit, args, j);
  2427.     ReplaceComment(savedIndex, val);
  2428.     EditCommentPopDown();
  2429.     } else if (strcmp(name, "cancel") == 0) {
  2430.     EditCommentPopDown();
  2431.     } else if (strcmp(name, "clear") == 0) {
  2432.     edit = XtNameToWidget(editShell, "form.edit");
  2433.     XtCallActionProc(edit, "select-all", NULL, NULL, 0);
  2434.     XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
  2435.     }
  2436. }
  2437.  
  2438. void EditCommentPopDown()
  2439. {
  2440.     Arg args[16];
  2441.     int j;
  2442.  
  2443.     if (!editUp) return;
  2444.     j = 0;
  2445.     XtSetArg(args[j], XtNx, &commentX); j++;
  2446.     XtSetArg(args[j], XtNy, &commentY); j++;
  2447.     XtSetArg(args[j], XtNheight, &commentH); j++;
  2448.     XtSetArg(args[j], XtNwidth, &commentW); j++;
  2449.     XtGetValues(editShell, args, j);
  2450.     XtPopdown(editShell);
  2451.     XtSetKeyboardFocus(shellWidget, formWidget);
  2452.     editUp = False;
  2453. }
  2454.  
  2455. void CommentPopUp(title, text)
  2456.      char *title, *text;
  2457. {
  2458.     Arg args[16];
  2459.     int j;
  2460.     Widget edit;
  2461.  
  2462.     if (commentShell == NULL) {
  2463.     commentShell =
  2464.       CommentCreate(title, text, False, CommentCallback);
  2465.     } else {
  2466.     edit = XtNameToWidget(commentShell, "form.edit");
  2467.     j = 0;
  2468.     XtSetArg(args[j], XtNstring, text); j++;
  2469.     XtSetValues(edit, args, j);
  2470.     j = 0;
  2471.     XtSetArg(args[j], XtNiconName, (XtArgVal) title);   j++;
  2472.     XtSetArg(args[j], XtNtitle, (XtArgVal) title);      j++;
  2473.     XtSetValues(commentShell, args, j);
  2474.     }
  2475.  
  2476.     XtPopup(commentShell, XtGrabNone);
  2477.     XSync(xDisplay, False);
  2478.  
  2479.     commentUp = True;
  2480. }
  2481.  
  2482. void CommentCallback(w, client_data, call_data)
  2483.      Widget w;
  2484.      XtPointer client_data, call_data;
  2485. {
  2486.     String name;
  2487.     Arg args[16];
  2488.     int j;
  2489.  
  2490.     j = 0;
  2491.     XtSetArg(args[j], XtNlabel, &name);  j++;
  2492.     XtGetValues(w, args, j);
  2493.  
  2494.     if (strcmp(name, "close") == 0) {
  2495.     CommentPopDown();
  2496.     } else if (strcmp(name, "edit") == 0) {
  2497.     CommentPopDown();
  2498.     EditCommentEvent();
  2499.     }
  2500. }
  2501.  
  2502.  
  2503. void CommentPopDown()
  2504. {
  2505.     Arg args[16];
  2506.     int j;
  2507.  
  2508.     if (!commentUp) return;
  2509.     j = 0;
  2510.     XtSetArg(args[j], XtNx, &commentX); j++;
  2511.     XtSetArg(args[j], XtNy, &commentY); j++;
  2512.     XtSetArg(args[j], XtNwidth, &commentW); j++;
  2513.     XtSetArg(args[j], XtNheight, &commentH); j++;
  2514.     XtGetValues(commentShell, args, j);
  2515.     XtPopdown(commentShell);
  2516.     XSync(xDisplay, False);
  2517.     commentUp = False;
  2518. }
  2519.  
  2520.  
  2521. void FileNamePopUp(label, def, proc, openMode)
  2522.      char *label;
  2523.      char *def;
  2524.      FileProc proc;
  2525.      char *openMode;
  2526. {
  2527.     Arg args[16];
  2528.     Widget popup, dialog;
  2529.     Window root, child;
  2530.     int x, y;
  2531.     int win_x, win_y;
  2532.     unsigned int mask;
  2533.     
  2534.     fileProc = proc;          /* I can't see a way not */
  2535.     fileOpenMode = openMode;  /*   to use globals here */
  2536.     
  2537.     XtSetArg(args[0], XtNresizable, True);
  2538.     XtSetArg(args[1], XtNwidth, DIALOG_SIZE);
  2539.     
  2540.     popup =
  2541.       XtCreatePopupShell("File Name Prompt", transientShellWidgetClass,
  2542.              shellWidget, args, 2);
  2543.     
  2544.     XtSetArg(args[0], XtNlabel, label);
  2545.     XtSetArg(args[1], XtNvalue, def);
  2546.     
  2547.     dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
  2548.                    popup, args, 2);
  2549.     
  2550.     XawDialogAddButton(dialog, "ok", FileNameCallback, (XtPointer) dialog);
  2551.     XawDialogAddButton(dialog, "cancel", FileNameCallback,
  2552.                (XtPointer) dialog);
  2553.     
  2554.     XtRealizeWidget(popup);
  2555.     
  2556.     XQueryPointer(xDisplay, xBoardWindow, &root, &child,
  2557.           &x, &y, &win_x, &win_y, &mask);
  2558.     
  2559.     XtSetArg(args[0], XtNx, x - 10);
  2560.     XtSetArg(args[1], XtNy, y - 10);
  2561.     XtSetValues(popup, args, 2);
  2562.     
  2563.     XtPopup(popup, XtGrabExclusive);
  2564.     filenameUp = True;
  2565.     
  2566.     XtSetKeyboardFocus(shellWidget, popup);
  2567. }
  2568.  
  2569. void FileNameCallback(w, client_data, call_data)
  2570.      Widget w;
  2571.      XtPointer client_data, call_data;
  2572. {
  2573.     String name;
  2574.     Arg args[16];
  2575.     
  2576.     XtSetArg(args[0], XtNlabel, &name);
  2577.     XtGetValues(w, args, 1);
  2578.     
  2579.     if (strcmp(name, "cancel") == 0) {
  2580.     XtPopdown(w = XtParent(XtParent(w)));
  2581.     XtDestroyWidget(w);
  2582.     filenameUp = False;
  2583.     ModeHighlight();
  2584.     return;
  2585.     }
  2586.     
  2587.     FileNameAction(w, NULL, NULL, NULL);
  2588. }
  2589.  
  2590. void FileNameAction(w, event, prms, nprms)
  2591.      Widget w;
  2592.      XEvent *event;
  2593.      String *prms;
  2594.      Cardinal *nprms;
  2595. {
  2596.     char buf[MSG_SIZ];
  2597.     String name;
  2598.     FILE *f;
  2599.     char *p;
  2600.     int index;
  2601.  
  2602.     name = XawDialogGetValueString(w = XtParent(w));
  2603.     
  2604.     if ((name != NULL) && (*name != NULLCHAR)) {
  2605.     strcpy(buf, name);
  2606.     XtPopdown(w = XtParent(w));
  2607.     XtDestroyWidget(w);
  2608.     filenameUp = False;
  2609.  
  2610.     p = strrchr(buf, ' ');
  2611.     if (p == NULL) {
  2612.         index = 1;
  2613.     } else {
  2614.         *p++ = NULLCHAR;
  2615.         index = atoi(p);
  2616.     }
  2617.     f = fopen(buf, fileOpenMode);
  2618.     if (f == NULL) {
  2619.         DisplayError("Failed to open file", errno);
  2620.     } else {
  2621.         (void) (*fileProc)(f, index, buf);
  2622.     }
  2623.     ModeHighlight();
  2624.     XtSetKeyboardFocus(shellWidget, formWidget);
  2625.     return;
  2626.     }
  2627.     
  2628.     XtPopdown(w = XtParent(w));
  2629.     XtDestroyWidget(w);
  2630.     filenameUp = False;
  2631.     ModeHighlight();
  2632.     XtSetKeyboardFocus(shellWidget, formWidget);
  2633. }
  2634.  
  2635. void PromotionPopUp()
  2636. {
  2637.     Arg args[16];
  2638.     Widget dialog;
  2639.     Position x, y;
  2640.     Dimension bw_width, pw_width;
  2641.     int j;
  2642.  
  2643.     j = 0;
  2644.     XtSetArg(args[j], XtNwidth, &bw_width); j++;
  2645.     XtGetValues(boardWidget, args, j);
  2646.     
  2647.     j = 0;
  2648.     XtSetArg(args[j], XtNresizable, True); j++;
  2649.     promotionShell =
  2650.       XtCreatePopupShell("Promotion", transientShellWidgetClass,
  2651.              shellWidget, args, j);
  2652.     
  2653.     j = 0;
  2654.     XtSetArg(args[j], XtNlabel, "Promote pawn to what?"); j++;
  2655.     dialog = XtCreateManagedWidget("promotion", dialogWidgetClass,
  2656.                    promotionShell, args, j);
  2657.     
  2658.     XawDialogAddButton(dialog, "Queen", PromotionCallback, 
  2659.                (XtPointer) dialog);
  2660.     XawDialogAddButton(dialog, "Rook", PromotionCallback, 
  2661.                (XtPointer) dialog);
  2662.     XawDialogAddButton(dialog, "Bishop", PromotionCallback, 
  2663.                (XtPointer) dialog);
  2664.     XawDialogAddButton(dialog, "Knight", PromotionCallback, 
  2665.                (XtPointer) dialog);
  2666.     XawDialogAddButton(dialog, "cancel", PromotionCallback, 
  2667.                (XtPointer) dialog);
  2668.     
  2669.     XtRealizeWidget(promotionShell);
  2670.     
  2671.     j = 0;
  2672.     XtSetArg(args[j], XtNwidth, &pw_width); j++;
  2673.     XtGetValues(promotionShell, args, j);
  2674.     
  2675.     XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
  2676.               lineGap + squareSize/3 +
  2677.               ((toY == 7) ^ (flipView) ?
  2678.                0 : 6*(squareSize + lineGap)), &x, &y);
  2679.     
  2680.     j = 0;
  2681.     XtSetArg(args[j], XtNx, x); j++;
  2682.     XtSetArg(args[j], XtNy, y); j++;
  2683.     XtSetValues(promotionShell, args, j);
  2684.     
  2685.     XtPopup(promotionShell, XtGrabNone);
  2686.     
  2687.     promotionUp = True;
  2688. }
  2689.  
  2690. void PromotionCallback(w, client_data, call_data)
  2691.      Widget w;
  2692.      XtPointer client_data, call_data;
  2693. {
  2694.     String name;
  2695.     Arg args[16];
  2696.     int promoChar;
  2697.     
  2698.     XtSetArg(args[0], XtNlabel, &name);
  2699.     XtGetValues(w, args, 1);
  2700.     
  2701.     XtPopdown(w = XtParent(XtParent(w)));
  2702.     XtDestroyWidget(w);
  2703.     promotionUp = False;
  2704.     
  2705.     if (fromX == -1) return;
  2706.     
  2707.     if (strcmp(name, "cancel") == 0) {
  2708.     fromX = fromY = -1;
  2709.     return;
  2710.     } else if (strcmp(name, "Knight") == 0) {
  2711.     promoChar = 'n';
  2712.     } else {
  2713.     promoChar = ToLower(name[0]);
  2714.     }
  2715.  
  2716.     UserMoveEvent(fromX, fromY, toX, toY, promoChar);
  2717. }
  2718.  
  2719.  
  2720. void ErrorCallback(w, client_data, call_data)
  2721.      Widget w;
  2722.      XtPointer client_data, call_data;
  2723. {
  2724.     errorUp = False;
  2725.     XtPopdown(w = XtParent(XtParent(w)));
  2726.     XtDestroyWidget(w);
  2727.     if (errorExitStatus != -1) ExitEvent(errorExitStatus);
  2728. }
  2729.  
  2730.  
  2731. void ErrorPopDown()
  2732. {
  2733.     if (!errorUp) return;
  2734.     errorUp = False;
  2735.     XtPopdown(errorShell);
  2736.     XtDestroyWidget(errorShell);
  2737. }
  2738.  
  2739. void ErrorPopUp(title, label)
  2740.      char *title, *label;
  2741. {
  2742.     Arg args[16];
  2743.     Widget dialog;
  2744.     Position x, y;
  2745.     int xx, yy;
  2746.     Window junk;
  2747.     Dimension bw_width, pw_width;
  2748.     Dimension pw_height;
  2749.     int i;
  2750.     
  2751.     i = 0;
  2752.     XtSetArg(args[i], XtNresizable, True);  i++;
  2753.     errorShell = 
  2754.       XtCreatePopupShell(title, transientShellWidgetClass,
  2755.              shellWidget, args, i);
  2756.     
  2757.     i = 0;
  2758.     XtSetArg(args[i], XtNlabel, label);  i++;
  2759.     dialog = XtCreateManagedWidget("dialog", dialogWidgetClass,
  2760.                    errorShell, args, i);
  2761.     
  2762.     XawDialogAddButton(dialog, "ok", ErrorCallback, (XtPointer) dialog);
  2763.     
  2764.     XtRealizeWidget(errorShell);
  2765.     
  2766.     i = 0;
  2767.     XtSetArg(args[i], XtNwidth, &bw_width);  i++;
  2768.     XtGetValues(boardWidget, args, i);
  2769.     i = 0;
  2770.     XtSetArg(args[i], XtNwidth, &pw_width);  i++;
  2771.     XtSetArg(args[i], XtNheight, &pw_height);  i++;
  2772.     XtGetValues(errorShell, args, i);
  2773.  
  2774. #ifdef NOTDEF
  2775.     /* This code seems to tickle an X bug if it is executed too soon
  2776.        after xboard starts up.  The coordinates get transformed as if
  2777.        the main window was positioned at (0, 0).
  2778.     */
  2779.     XtTranslateCoords(boardWidget, (bw_width - pw_width) / 2,
  2780.               0 - pw_height - appData.borderYoffset
  2781.               + squareSize / 3, &x, &y);
  2782. #else
  2783.     XTranslateCoordinates(xDisplay, XtWindow(boardWidget),
  2784.               RootWindowOfScreen(XtScreen(boardWidget)),
  2785.               (bw_width - pw_width) / 2,
  2786.               0 - pw_height - appData.borderYoffset
  2787.               + squareSize / 3, &xx, &yy, &junk);
  2788.     x = xx;
  2789.     y = yy;
  2790. #endif
  2791.  
  2792.     i = 0;
  2793.     XtSetArg(args[i], XtNx, x);  i++;
  2794.     XtSetArg(args[i], XtNy, y);  i++;
  2795.     XtSetValues(errorShell, args, i);
  2796.  
  2797.     errorUp = True;
  2798.     XtPopup(errorShell, XtGrabNone);
  2799. }
  2800.  
  2801.  
  2802. char *ModeToWidgetName(mode)
  2803.      GameMode mode;
  2804. {
  2805.     switch (mode) {
  2806.       case BeginningOfGame:
  2807.     if (appData.icsActive)
  2808.       return "menuMode.ICS Client";
  2809.     else if (appData.noChessProgram ||
  2810.          *appData.cmailGameName != NULLCHAR)
  2811.       return "menuMode.Edit Game";
  2812.     else
  2813.       return "menuMode.Machine Black";
  2814.       case MachinePlaysBlack:
  2815.     return "menuMode.Machine Black";
  2816.       case MachinePlaysWhite:
  2817.     return "menuMode.Machine White";
  2818.       case TwoMachinesPlay:
  2819.     return "menuMode.Two Machines";
  2820.       case EditGame:
  2821.     return "menuMode.Edit Game";
  2822.       case PlayFromGameFile:
  2823.     return "menuFile.Load Game";
  2824.       case EditPosition:
  2825.     return "menuMode.Edit Position";
  2826.       case IcsPlayingWhite:
  2827.       case IcsPlayingBlack:
  2828.       case IcsObserving:
  2829.       case IcsIdle:
  2830.       case IcsExamining:
  2831.     return "menuMode.ICS Client";
  2832.       default:
  2833.       case EndOfGame:
  2834.     return NULL;
  2835.     }
  2836. }     
  2837.  
  2838. void ModeHighlight()
  2839. {
  2840.     Arg args[16];
  2841.     static int oldPausing = FALSE;
  2842.     static GameMode oldmode = (GameMode) -1;
  2843.     char *wname;
  2844.     
  2845.     if (pausing != oldPausing) {
  2846.     oldPausing = pausing;
  2847.     if (pausing) {
  2848.         XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  2849.     } else {
  2850.         XtSetArg(args[0], XtNleftBitmap, None);
  2851.     }
  2852.     XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"),
  2853.             args, 1);
  2854.  
  2855.     if (pausing) {
  2856.         XtSetArg(args[0], XtNbackground, buttonForegroundPixel);
  2857.         XtSetArg(args[1], XtNforeground, buttonBackgroundPixel);
  2858.     } else {
  2859.         XtSetArg(args[0], XtNbackground, buttonBackgroundPixel);
  2860.         XtSetArg(args[1], XtNforeground, buttonForegroundPixel);
  2861.     }
  2862.     XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2);
  2863.     }
  2864.  
  2865.     wname = ModeToWidgetName(oldmode);
  2866.     if (wname != NULL) {
  2867.     XtSetArg(args[0], XtNleftBitmap, None);
  2868.     XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
  2869.     }
  2870.     wname = ModeToWidgetName(gameMode);
  2871.     if (wname != NULL) {
  2872.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  2873.     XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1);
  2874.     }
  2875.     oldmode = gameMode;
  2876. }
  2877.  
  2878.  
  2879. /*
  2880.  * Button/menu procedures
  2881.  */
  2882. void ResetProc(w, event, prms, nprms)
  2883.      Widget w;
  2884.      XEvent *event;
  2885.      String *prms;
  2886.      Cardinal *nprms;
  2887. {
  2888.     ResetGameEvent();
  2889. }
  2890.  
  2891. /* Lets LoadGame know it was called from a pop-up */
  2892. int LoadGamePopUp(f, gameNumber, title)
  2893.      FILE *f;
  2894.      int gameNumber;
  2895.      char *title;
  2896. {
  2897.     cmailMsgLoaded = FALSE;
  2898.     return LoadGame(f, gameNumber, title);
  2899. }
  2900.  
  2901. void LoadGameProc(w, event, prms, nprms)
  2902.      Widget w;
  2903.      XEvent *event;
  2904.      String *prms;
  2905.      Cardinal *nprms;
  2906. {
  2907.     FileNamePopUp("Load game file name?", "", LoadGamePopUp, "r");
  2908. }
  2909.  
  2910. void LoadNextGameProc(w, event, prms, nprms)
  2911.      Widget w;
  2912.      XEvent *event;
  2913.      String *prms;
  2914.      Cardinal *nprms;
  2915. {
  2916.     ReloadGame(1);
  2917. }
  2918.  
  2919. void LoadPrevGameProc(w, event, prms, nprms)
  2920.      Widget w;
  2921.      XEvent *event;
  2922.      String *prms;
  2923.      Cardinal *nprms;
  2924. {
  2925.     ReloadGame(-1);
  2926. }
  2927.  
  2928. void ReloadGameProc(w, event, prms, nprms)
  2929.      Widget w;
  2930.      XEvent *event;
  2931.      String *prms;
  2932.      Cardinal *nprms;
  2933. {
  2934.     ReloadGame(0);
  2935. }
  2936.  
  2937. void LoadPositionProc(w, event, prms, nprms)
  2938.      Widget w;
  2939.      XEvent *event;
  2940.      String *prms;
  2941.      Cardinal *nprms;
  2942. {
  2943.     FileNamePopUp("Load position file name?", "", LoadPosition, "r");
  2944. }
  2945.  
  2946. void SaveGameProc(w, event, prms, nprms)
  2947.      Widget w;
  2948.      XEvent *event;
  2949.      String *prms;
  2950.      Cardinal *nprms;
  2951. {
  2952.     FileNamePopUp("Save game file name?",
  2953.           DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
  2954.           SaveGame, "a");
  2955. }
  2956.  
  2957. void SavePositionProc(w, event, prms, nprms)
  2958.      Widget w;
  2959.      XEvent *event;
  2960.      String *prms;
  2961.      Cardinal *nprms;
  2962. {
  2963.     FileNamePopUp("Save position file name?",
  2964.           DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
  2965.           SavePosition, "a");
  2966. }
  2967.  
  2968. void ReloadCmailGameProc(w, event, prms, nprms)
  2969.      Widget w;
  2970.      XEvent *event;
  2971.      String *prms;
  2972.      Cardinal *nprms;
  2973. {
  2974.     ReloadCmailGameEvent(FALSE);
  2975. }
  2976.  
  2977. void MailMoveProc(w, event, prms, nprms)
  2978.      Widget w;
  2979.      XEvent *event;
  2980.      String *prms;
  2981.      Cardinal *nprms;
  2982. {
  2983.     MailMoveEvent();
  2984. }
  2985.  
  2986. void AutoSaveGame()
  2987. {
  2988.     SaveGameProc(NULL, NULL, NULL, NULL);
  2989. }
  2990.  
  2991.  
  2992. void QuitProc(w, event, prms, nprms)
  2993.      Widget w;
  2994.      XEvent *event;
  2995.      String *prms;
  2996.      Cardinal *nprms;
  2997. {
  2998.     ExitEvent(0);
  2999. }
  3000.  
  3001. void PauseProc(w, event, prms, nprms)
  3002.      Widget w;
  3003.      XEvent *event;
  3004.      String *prms;
  3005.      Cardinal *nprms;
  3006. {
  3007.     PauseEvent();
  3008. }
  3009.  
  3010.  
  3011. void MachineBlackProc(w, event, prms, nprms)
  3012.      Widget w;
  3013.      XEvent *event;
  3014.      String *prms;
  3015.      Cardinal *nprms;
  3016. {
  3017.     MachineBlackEvent();
  3018. }
  3019.  
  3020. void MachineWhiteProc(w, event, prms, nprms)
  3021.      Widget w;
  3022.      XEvent *event;
  3023.      String *prms;
  3024.      Cardinal *nprms;
  3025. {
  3026.     MachineWhiteEvent();
  3027. }
  3028.  
  3029.  
  3030. void TwoMachinesProc(w, event, prms, nprms)
  3031.      Widget w;
  3032.      XEvent *event;
  3033.      String *prms;
  3034.      Cardinal *nprms;
  3035. {
  3036.     TwoMachinesEvent();
  3037. }
  3038.  
  3039. void IcsClientProc(w, event, prms, nprms)
  3040.      Widget w;
  3041.      XEvent *event;
  3042.      String *prms;
  3043.      Cardinal *nprms;
  3044. {
  3045.     IcsClientEvent();
  3046. }
  3047.  
  3048. void EditGameProc(w, event, prms, nprms)
  3049.      Widget w;
  3050.      XEvent *event;
  3051.      String *prms;
  3052.      Cardinal *nprms;
  3053. {
  3054.     EditGameEvent();
  3055. }
  3056.  
  3057. void EditPositionProc(w, event, prms, nprms)
  3058.      Widget w;
  3059.      XEvent *event;
  3060.      String *prms;
  3061.      Cardinal *nprms;
  3062. {
  3063.     EditPositionEvent();
  3064. }
  3065.  
  3066. void EditCommentProc(w, event, prms, nprms)
  3067.      Widget w;
  3068.      XEvent *event;
  3069.      String *prms;
  3070.      Cardinal *nprms;
  3071. {
  3072.     EditCommentEvent();
  3073. }
  3074.  
  3075. void AcceptProc(w, event, prms, nprms)
  3076.      Widget w;
  3077.      XEvent *event;
  3078.      String *prms;
  3079.      Cardinal *nprms;
  3080. {
  3081.     AcceptEvent();
  3082. }
  3083.  
  3084. void DeclineProc(w, event, prms, nprms)
  3085.      Widget w;
  3086.      XEvent *event;
  3087.      String *prms;
  3088.      Cardinal *nprms;
  3089. {
  3090.     DeclineEvent();
  3091. }
  3092.  
  3093. void CallFlagProc(w, event, prms, nprms)
  3094.      Widget w;
  3095.      XEvent *event;
  3096.      String *prms;
  3097.      Cardinal *nprms;
  3098. {
  3099.     CallFlagEvent();
  3100. }
  3101.  
  3102. void DrawProc(w, event, prms, nprms)
  3103.      Widget w;
  3104.      XEvent *event;
  3105.      String *prms;
  3106.      Cardinal *nprms;
  3107. {
  3108.     DrawEvent();
  3109. }
  3110.  
  3111. void AbortProc(w, event, prms, nprms)
  3112.      Widget w;
  3113.      XEvent *event;
  3114.      String *prms;
  3115.      Cardinal *nprms;
  3116. {
  3117.     AbortEvent();
  3118. }
  3119.  
  3120. void AdjournProc(w, event, prms, nprms)
  3121.      Widget w;
  3122.      XEvent *event;
  3123.      String *prms;
  3124.      Cardinal *nprms;
  3125. {
  3126.     AdjournEvent();
  3127. }
  3128.  
  3129. void ResignProc(w, event, prms, nprms)
  3130.      Widget w;
  3131.      XEvent *event;
  3132.      String *prms;
  3133.      Cardinal *nprms;
  3134. {
  3135.     ResignEvent();
  3136. }
  3137.  
  3138. void StopObservingProc(w, event, prms, nprms)
  3139.      Widget w;
  3140.      XEvent *event;
  3141.      String *prms;
  3142.      Cardinal *nprms;
  3143. {
  3144.     StopObservingEvent();
  3145. }
  3146.  
  3147. void StopExaminingProc(w, event, prms, nprms)
  3148.      Widget w;
  3149.      XEvent *event;
  3150.      String *prms;
  3151.      Cardinal *nprms;
  3152. {
  3153.     StopExaminingEvent();
  3154. }
  3155.  
  3156.  
  3157. void ForwardProc(w, event, prms, nprms)
  3158.      Widget w;
  3159.      XEvent *event;
  3160.      String *prms;
  3161.      Cardinal *nprms;
  3162. {
  3163.     ForwardEvent();
  3164. }
  3165.  
  3166.  
  3167. void BackwardProc(w, event, prms, nprms)
  3168.      Widget w;
  3169.      XEvent *event;
  3170.      String *prms;
  3171.      Cardinal *nprms;
  3172. {
  3173.     BackwardEvent();
  3174. }
  3175.  
  3176. void ToStartProc(w, event, prms, nprms)
  3177.      Widget w;
  3178.      XEvent *event;
  3179.      String *prms;
  3180.      Cardinal *nprms;
  3181. {
  3182.     ToStartEvent();
  3183. }
  3184.  
  3185. void ToEndProc(w, event, prms, nprms)
  3186.      Widget w;
  3187.      XEvent *event;
  3188.      String *prms;
  3189.      Cardinal *nprms;
  3190. {
  3191.     ToEndEvent();
  3192. }
  3193.  
  3194. void RevertProc(w, event, prms, nprms)
  3195.      Widget w;
  3196.      XEvent *event;
  3197.      String *prms;
  3198.      Cardinal *nprms;
  3199. {
  3200.     RevertEvent();
  3201. }
  3202.  
  3203. void TruncateGameProc(w, event, prms, nprms)
  3204.      Widget w;
  3205.      XEvent *event;
  3206.      String *prms;
  3207.      Cardinal *nprms;
  3208. {
  3209.     TruncateGameEvent();
  3210. }
  3211. void RetractMoveProc(w, event, prms, nprms)
  3212.      Widget w;
  3213.      XEvent *event;
  3214.      String *prms;
  3215.      Cardinal *nprms;
  3216. {
  3217.     RetractMoveEvent();
  3218. }
  3219.  
  3220. void MoveNowProc(w, event, prms, nprms)
  3221.      Widget w;
  3222.      XEvent *event;
  3223.      String *prms;
  3224.      Cardinal *nprms;
  3225. {
  3226.     MoveNowEvent();
  3227. }
  3228.  
  3229.  
  3230. void AlwaysQueenProc(w, event, prms, nprms)
  3231.      Widget w;
  3232.      XEvent *event;
  3233.      String *prms;
  3234.      Cardinal *nprms;
  3235. {
  3236.     Arg args[16];
  3237.  
  3238.     appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
  3239.  
  3240.     if (appData.alwaysPromoteToQueen) {
  3241.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3242.     } else {
  3243.     XtSetArg(args[0], XtNleftBitmap, None);
  3244.     }
  3245.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"),
  3246.         args, 1);
  3247. }
  3248.  
  3249.  
  3250. void AutoflagProc(w, event, prms, nprms)
  3251.      Widget w;
  3252.      XEvent *event;
  3253.      String *prms;
  3254.      Cardinal *nprms;
  3255. {
  3256.     Arg args[16];
  3257.  
  3258.     appData.autoCallFlag = !appData.autoCallFlag;
  3259.  
  3260.     if (appData.autoCallFlag) {
  3261.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3262.     } else {
  3263.     XtSetArg(args[0], XtNleftBitmap, None);
  3264.     }
  3265.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
  3266.         args, 1);
  3267. }
  3268.  
  3269. void AutobsProc(w, event, prms, nprms)
  3270.      Widget w;
  3271.      XEvent *event;
  3272.      String *prms;
  3273.      Cardinal *nprms;
  3274. {
  3275.     Arg args[16];
  3276.  
  3277.     appData.autoObserve = !appData.autoObserve;
  3278.  
  3279.     if (appData.autoObserve) {
  3280.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3281.     } else {
  3282.     XtSetArg(args[0], XtNleftBitmap, None);
  3283.     }
  3284.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
  3285.         args, 1);
  3286. }
  3287.  
  3288. void AutosaveProc(w, event, prms, nprms)
  3289.      Widget w;
  3290.      XEvent *event;
  3291.      String *prms;
  3292.      Cardinal *nprms;
  3293. {
  3294.     Arg args[16];
  3295.  
  3296.     appData.autoSaveGames = !appData.autoSaveGames;
  3297.  
  3298.     if (appData.autoSaveGames) {
  3299.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3300.     } else {
  3301.     XtSetArg(args[0], XtNleftBitmap, None);
  3302.     }
  3303.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
  3304.         args, 1);
  3305. }
  3306.  
  3307. void BellProc(w, event, prms, nprms)
  3308.      Widget w;
  3309.      XEvent *event;
  3310.      String *prms;
  3311.      Cardinal *nprms;
  3312. {
  3313.     Arg args[16];
  3314.  
  3315.     appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
  3316.  
  3317.     if (appData.ringBellAfterMoves) {
  3318.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3319.     } else {
  3320.     XtSetArg(args[0], XtNleftBitmap, None);
  3321.     }
  3322.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Bell"),
  3323.         args, 1);
  3324. }
  3325.  
  3326.  
  3327. void FlipViewProc(w, event, prms, nprms)
  3328.      Widget w;
  3329.      XEvent *event;
  3330.      String *prms;
  3331.      Cardinal *nprms;
  3332. {
  3333.     flipView = !flipView;
  3334.     DrawPosition(True, NULL);
  3335. }
  3336.  
  3337. void OldSaveStyleProc(w, event, prms, nprms)
  3338.      Widget w;
  3339.      XEvent *event;
  3340.      String *prms;
  3341.      Cardinal *nprms;
  3342. {
  3343.     Arg args[16];
  3344.  
  3345.     appData.oldSaveStyle = !appData.oldSaveStyle;
  3346.  
  3347.     if (appData.oldSaveStyle) {
  3348.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3349.     } else {
  3350.     XtSetArg(args[0], XtNleftBitmap, None);
  3351.     }
  3352.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
  3353.         args, 1);
  3354. }
  3355.  
  3356. void QuietPlayProc(w, event, prms, nprms)
  3357.      Widget w;
  3358.      XEvent *event;
  3359.      String *prms;
  3360.      Cardinal *nprms;
  3361. {
  3362.     Arg args[16];
  3363.  
  3364.     appData.quietPlay = !appData.quietPlay;
  3365.  
  3366.     if (appData.quietPlay) {
  3367.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3368.     } else {
  3369.     XtSetArg(args[0], XtNleftBitmap, None);
  3370.     }
  3371.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
  3372.         args, 1);
  3373. }
  3374.  
  3375. void ShowCoordsProc(w, event, prms, nprms)
  3376.      Widget w;
  3377.      XEvent *event;
  3378.      String *prms;
  3379.      Cardinal *nprms;
  3380. {
  3381.     Arg args[16];
  3382.  
  3383.     appData.showCoords = !appData.showCoords;
  3384.  
  3385.     if (appData.showCoords) {
  3386.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3387.     } else {
  3388.     XtSetArg(args[0], XtNleftBitmap, None);
  3389.     }
  3390.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
  3391.         args, 1);
  3392.  
  3393.     DrawPosition(True, NULL);
  3394. }
  3395.  
  3396. void ShowThinkingProc(w, event, prms, nprms)
  3397.      Widget w;
  3398.      XEvent *event;
  3399.      String *prms;
  3400.      Cardinal *nprms;
  3401. {
  3402.     Arg args[16];
  3403.  
  3404.     ShowThinkingEvent(!appData.showThinking);
  3405.  
  3406.     if (appData.showThinking) {
  3407.     XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  3408.     } else {
  3409.     XtSetArg(args[0], XtNleftBitmap, None);
  3410.     }
  3411.     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"),
  3412.         args, 1);
  3413. }
  3414.  
  3415.  
  3416. void AboutProc(w, event, prms, nprms)
  3417.      Widget w;
  3418.      XEvent *event;
  3419.      String *prms;
  3420.      Cardinal *nprms;
  3421. {
  3422.     char buf[MSG_SIZ];
  3423.  
  3424.     sprintf(buf, "%s version %s, patchlevel %s\n\n%s\n%s\n\n%s\n%s",
  3425.         PRODUCT, VERSION, PATCHLEVEL,
  3426.         "Copyright 1991 Digital Equipment Corporation",
  3427.         "Enhancements Copyright 1992-95 Free Software Foundation",
  3428.         "This program is free software and carries NO WARRANTY;",
  3429.         "see the file COPYING for more information.");
  3430.     ErrorPopUp("About XBoard", buf);
  3431. }
  3432.  
  3433. void HintProc(w, event, prms, nprms)
  3434.      Widget w;
  3435.      XEvent *event;
  3436.      String *prms;
  3437.      Cardinal *nprms;
  3438. {
  3439.     HintEvent();
  3440. }
  3441.  
  3442. void BookProc(w, event, prms, nprms)
  3443.      Widget w;
  3444.      XEvent *event;
  3445.      String *prms;
  3446.      Cardinal *nprms;
  3447. {
  3448.     BookEvent();
  3449. }
  3450.  
  3451. void AboutGameProc(w, event, prms, nprms)
  3452.      Widget w;
  3453.      XEvent *event;
  3454.      String *prms;
  3455.      Cardinal *nprms;
  3456. {
  3457.     AboutGameEvent();
  3458. }
  3459.  
  3460. void NothingProc(w, event, prms, nprms)
  3461.      Widget w;
  3462.      XEvent *event;
  3463.      String *prms;
  3464.      Cardinal *nprms;
  3465. {
  3466.     return;
  3467. }
  3468.  
  3469. void Iconify(w, event, prms, nprms)
  3470.      Widget w;
  3471.      XEvent *event;
  3472.      String *prms;
  3473.      Cardinal *nprms;
  3474. {
  3475.     Arg args[16];
  3476.     
  3477.     fromX = fromY = -1;
  3478.     
  3479.     XtSetArg(args[0], XtNiconic, False);
  3480.     XtSetValues(shellWidget, args, 1);
  3481.     XtSetArg(args[0], XtNiconic, True);
  3482.     XtSetValues(shellWidget, args, 1);
  3483. }
  3484.  
  3485. void DisplayMessage(message, extMessage)
  3486.      char *message, *extMessage;
  3487. {
  3488.     char buf[MSG_SIZ];
  3489.     Arg arg;
  3490.     
  3491.     if (extMessage) {
  3492.     if (message) {
  3493.         sprintf(buf, "%s  %s", message, extMessage);
  3494.         message = buf;
  3495.     } else {
  3496.         message = extMessage;
  3497.     }
  3498.     }
  3499.     XtSetArg(arg, XtNlabel, message);
  3500.     XtSetValues(messageWidget, &arg, 1);
  3501. }
  3502.  
  3503. void DisplayTitle(text)
  3504.      char *text;
  3505. {
  3506.     Arg args[16];
  3507.     int i;
  3508.     char title[MSG_SIZ];
  3509.     char *icon;
  3510.  
  3511.     if (text == NULL) text = "";
  3512.  
  3513.     if (appData.titleInWindow) {
  3514.     i = 0;
  3515.     XtSetArg(args[i], XtNlabel, text);   i++;
  3516.     XtSetValues(titleWidget, args, i);
  3517.     }
  3518.  
  3519.     if (*text != NULLCHAR) {
  3520.     icon = text;
  3521.     sprintf(title, "%s: %s", programName, icon);
  3522.     } else if (appData.icsActive) {
  3523.     icon = appData.icsHost;
  3524.     sprintf(title, "%s: %s", programName, icon);
  3525.     } else if (appData.cmailGameName[0] != NULLCHAR) {
  3526.     icon = "CMail";
  3527.     sprintf(title, "%s: %s", programName, icon);
  3528.     } else if (appData.noChessProgram) {
  3529.     icon = programName;
  3530.     sprintf(title, "%s", programName);
  3531.     } else {
  3532.     if (StrStr(appData.firstChessProgram, "gnuchess")) {
  3533.         icon = "GNU Chess";
  3534.         sprintf(title, "%s: %s", programName, icon);
  3535.     } else {
  3536.         icon = strrchr(appData.firstChessProgram, '/');
  3537.         if (icon == NULL)
  3538.           icon = appData.firstChessProgram;
  3539.         else
  3540.           icon++;
  3541.         sprintf(title, "%s: %s", programName, icon);
  3542.     }
  3543.     }
  3544.     i = 0;
  3545.     XtSetArg(args[i], XtNiconName, (XtArgVal) icon);    i++;
  3546.     XtSetArg(args[i], XtNtitle, (XtArgVal) title);      i++;
  3547.     XtSetValues(shellWidget, args, i);
  3548. }
  3549.  
  3550.  
  3551. void DisplayError(message, error)
  3552.      String message;
  3553.      int error;
  3554. {
  3555.     extern char *sys_errlist[];
  3556.     char buf[MSG_SIZ];
  3557.  
  3558.     if (error == 0) {
  3559.     if (appData.debugMode || appData.matchMode) {
  3560.         fprintf(stderr, "%s: %s\n", programName, message);
  3561.     }
  3562.     ErrorPopUp("Error", message);
  3563.     } else {
  3564.     if (appData.debugMode || appData.matchMode) {
  3565.         fprintf(stderr, "%s: %s: %s\n",
  3566.             programName, message, sys_errlist[error]);
  3567.     }
  3568.     sprintf(buf, "%s: %s", message, sys_errlist[error]);
  3569.     ErrorPopUp("Error", buf);
  3570.     }    
  3571. }
  3572.  
  3573.  
  3574. void DisplayFatalError(message, error, status)
  3575.      String message;
  3576.      int error, status;
  3577. {
  3578.     extern char *sys_errlist[];
  3579.     char buf[MSG_SIZ];
  3580.  
  3581.     errorExitStatus = status;
  3582.     if (errorExitStatus != -1) {
  3583.     XtSetSensitive(menuBarWidget, False);
  3584.     XtSetSensitive(buttonBarWidget, False);
  3585.     XtUninstallTranslations(formWidget);
  3586.     XtUninstallTranslations(boardWidget);
  3587.     XtUninstallTranslations(whiteTimerWidget);
  3588.     XtUninstallTranslations(blackTimerWidget);
  3589.     }
  3590.     if (error == 0) {
  3591.     fprintf(stderr, "%s: %s\n", programName, message);
  3592.     ErrorPopUp("Fatal Error", message);
  3593.     } else {
  3594.     fprintf(stderr, "%s: %s: %s\n",
  3595.         programName, message, sys_errlist[error]);
  3596.     sprintf(buf, "%s: %s", message, sys_errlist[error]);
  3597.     ErrorPopUp("Fatal Error", buf);
  3598.     }
  3599. }
  3600.  
  3601.  
  3602. void DisplayInformation(message)
  3603.      String message;
  3604. {
  3605.     ErrorPopDown();
  3606.     ErrorPopUp("Information", message);
  3607. }
  3608.  
  3609. void RingBell()
  3610. {
  3611.     putc(BELLCHAR, stderr);
  3612. }
  3613.  
  3614. void EchoOn()
  3615. {
  3616.     system("stty echo\n");
  3617. }
  3618.  
  3619. void EchoOff()
  3620. {
  3621.     system("stty -echo\n");
  3622. }
  3623.  
  3624. char *UserName()
  3625. {
  3626.     return getpwuid(getuid())->pw_name;
  3627. }
  3628.  
  3629. char *HostName()
  3630. {
  3631.     static char host_name[MSG_SIZ];
  3632.     
  3633. #if HAVE_GETHOSTNAME
  3634.     gethostname(host_name, MSG_SIZ);
  3635.     return host_name;
  3636. #else /* not HAVE_GETHOSTNAME */
  3637. # if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
  3638.     sysinfo(SI_HOSTNAME, host_name, MSG_SIZ);
  3639.     return host_name;
  3640. # else /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
  3641.     return "localhost";
  3642. # endif /* not (HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H) */
  3643. #endif /* not HAVE_GETHOSTNAME */
  3644. }
  3645.  
  3646. XtIntervalId loadGameTimerXID = 0;
  3647.  
  3648. int LoadGameTimerRunning()
  3649. {
  3650.     return loadGameTimerXID != 0;
  3651. }
  3652.  
  3653. int StopLoadGameTimer()
  3654. {
  3655.     if (loadGameTimerXID != 0) {
  3656.     XtRemoveTimeOut(loadGameTimerXID);
  3657.     loadGameTimerXID = 0;
  3658.     return TRUE;
  3659.     } else {
  3660.     return FALSE;
  3661.     }
  3662. }
  3663.  
  3664. void LoadGameTimerCallback(arg, id)
  3665.      XtPointer arg;
  3666.      XtIntervalId *id;
  3667. {
  3668.     loadGameTimerXID = 0;
  3669.     LoadGameLoop();
  3670. }
  3671.  
  3672. void StartLoadGameTimer(millisec)
  3673.      long millisec;
  3674. {
  3675.     loadGameTimerXID =
  3676.       XtAppAddTimeOut(appContext, millisec,
  3677.               (XtTimerCallbackProc) LoadGameTimerCallback,
  3678.               (XtPointer) 0);
  3679. }
  3680.  
  3681. XtIntervalId clockTimerXID = 0;
  3682.  
  3683. int ClockTimerRunning()
  3684. {
  3685.     return clockTimerXID != 0;
  3686. }
  3687.  
  3688. int StopClockTimer()
  3689. {
  3690.     if (clockTimerXID != 0) {
  3691.     XtRemoveTimeOut(clockTimerXID);
  3692.     clockTimerXID = 0;
  3693.     return TRUE;
  3694.     } else {
  3695.     return FALSE;
  3696.     }
  3697. }
  3698.  
  3699. void ClockTimerCallback(arg, id)
  3700.      XtPointer arg;
  3701.      XtIntervalId *id;
  3702. {
  3703.     clockTimerXID = 0;
  3704.     DecrementClocks();
  3705. }
  3706.  
  3707. void StartClockTimer(millisec)
  3708.      long millisec;
  3709. {
  3710.     clockTimerXID =
  3711.       XtAppAddTimeOut(appContext, millisec,
  3712.               (XtTimerCallbackProc) ClockTimerCallback,
  3713.               (XtPointer) 0);
  3714. }
  3715.  
  3716. void DisplayTimerLabel(w, color, timer, highlight)
  3717.      Widget w;
  3718.      char *color;
  3719.      long timer;
  3720.      int highlight;
  3721. {
  3722.     char buf[MSG_SIZ];
  3723.     Arg args[16];
  3724.     
  3725.     if (appData.clockMode) {
  3726.     sprintf(buf, "%s: %s", color, TimeString(timer));
  3727.     XtSetArg(args[0], XtNlabel, buf);
  3728.     } else {
  3729.     sprintf(buf, "%s  ", color);
  3730.     XtSetArg(args[0], XtNlabel, buf);
  3731.     }
  3732.     
  3733.     if (highlight) {
  3734.     XtSetArg(args[1], XtNbackground, timerForegroundPixel);
  3735.     XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
  3736.     } else {
  3737.     XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
  3738.     XtSetArg(args[2], XtNforeground, timerForegroundPixel);
  3739.     }
  3740.     
  3741.     XtSetValues(w, args, 3);
  3742. }
  3743.  
  3744. void DisplayWhiteClock(timeRemaining, highlight)
  3745.      long timeRemaining;
  3746.      int highlight;
  3747. {
  3748.     Arg args[16];
  3749.     DisplayTimerLabel(whiteTimerWidget, "White", timeRemaining, highlight);
  3750.     if (highlight && iconPixmap == bIconPixmap) {
  3751.     iconPixmap = wIconPixmap;
  3752.     XtSetArg(args[0], XtNiconPixmap, iconPixmap);
  3753.     XtSetValues(shellWidget, args, 1);
  3754.     }
  3755. }
  3756.  
  3757. void DisplayBlackClock(timeRemaining, highlight)
  3758.      long timeRemaining;
  3759.      int highlight;
  3760. {
  3761.     Arg args[16];
  3762.     DisplayTimerLabel(blackTimerWidget, "Black", timeRemaining, highlight);
  3763.     if (highlight && iconPixmap == wIconPixmap) {
  3764.     iconPixmap = bIconPixmap;
  3765.     XtSetArg(args[0], XtNiconPixmap, iconPixmap);
  3766.     XtSetValues(shellWidget, args, 1);
  3767.     }
  3768. }
  3769.  
  3770. #define CPReal 1
  3771. #define CPComm 2
  3772. #define CPSock 3
  3773. #define CPLoop 4
  3774. typedef int CPKind;
  3775.  
  3776. typedef struct {
  3777.     CPKind kind;
  3778.     int pid;
  3779.     int fdTo, fdFrom;  
  3780. } ChildProc;
  3781.  
  3782.  
  3783. int StartChildProcess(cmdLine, pr)
  3784.      char *cmdLine; 
  3785.      ProcRef *pr;
  3786. {
  3787.     char *argv[64], *p;
  3788.     int i, pid;
  3789.     int to_prog[2], from_prog[2];
  3790.     ChildProc *cp;
  3791.     
  3792.     /* We do NOT feed the cmdLine to the shell; we just
  3793.        parse it into blank-separated arguments in the
  3794.        most simple-minded way possible.
  3795.     */
  3796.     i = 0;
  3797.     p = cmdLine;
  3798.     for (;;) {
  3799.     argv[i++] = p;
  3800.     p = strchr(p, ' ');
  3801.     if (p == NULL) break;
  3802.     *p++ = NULLCHAR;
  3803.     }
  3804.     argv[i] = NULL;
  3805.  
  3806.     SetUpChildIO(to_prog, from_prog);
  3807.  
  3808.     if ((pid = fork()) == 0) {
  3809.     /* Child process */
  3810.     dup2(to_prog[0], 0);
  3811.     dup2(from_prog[1], 1);
  3812.     close(to_prog[0]);
  3813.     close(to_prog[1]);
  3814.     close(from_prog[0]);
  3815.     close(from_prog[1]);
  3816.     dup2(1, fileno(stderr)); /* force stderr to the pipe */
  3817.  
  3818.         execvp(argv[0], argv);
  3819.     
  3820.     perror(argv[0]);
  3821.     exit(1);
  3822.     }
  3823.     
  3824.     /* Parent process */
  3825.     close(to_prog[0]);
  3826.     close(from_prog[1]);
  3827.     
  3828.     cp = (ChildProc *) calloc(1, sizeof(ChildProc));
  3829.     cp->kind = CPReal;
  3830.     cp->pid = pid;
  3831.     cp->fdFrom = from_prog[0];
  3832.     cp->fdTo = to_prog[1];
  3833.     *pr = (ProcRef) cp;
  3834.     return 0;
  3835. }
  3836.  
  3837. void DestroyChildProcess(pr)
  3838.      ProcRef pr;
  3839. {
  3840.     ChildProc *cp = (ChildProc *) pr;
  3841.  
  3842.     if (cp->kind != CPReal) return;
  3843.     if (kill(cp->pid, SIGTERM) == 0)
  3844.       wait((int *) 0);
  3845.     close(cp->fdFrom);
  3846.     close(cp->fdTo);
  3847. }
  3848.  
  3849. void InterruptChildProcess(pr)
  3850.      ProcRef pr;
  3851. {
  3852.     ChildProc *cp = (ChildProc *) pr;
  3853.  
  3854.     if (cp->kind != CPReal) return;
  3855.     (void) kill(cp->pid, SIGINT); /* stop it thinking */
  3856. }
  3857.  
  3858. int OpenTelnet(host, port, pr)
  3859.      char *host;
  3860.      int port;
  3861.      ProcRef *pr;
  3862. {
  3863.     char cmdLine[MSG_SIZ];
  3864.  
  3865.     sprintf(cmdLine, "%s %s %d", appData.telnetProgram, host, port);
  3866.     return StartChildProcess(cmdLine, pr);
  3867. }
  3868.  
  3869. int OpenTCP(host, port, pr)
  3870.      char *host;
  3871.      int port;
  3872.      ProcRef *pr;
  3873. {
  3874. #if OMIT_SOCKETS
  3875.     DisplayFatalError("Socket support is not configured in", 0, 2);
  3876. #else /* !OMIT_SOCKETS */
  3877.     int s;
  3878.     struct sockaddr_in sa;
  3879.     struct hostent     *hp;
  3880.     unsigned short uport;
  3881.     ChildProc *cp;
  3882.  
  3883.     if ((s = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
  3884.     return errno;
  3885.     }
  3886.  
  3887.     memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
  3888.     sa.sin_family = AF_INET;
  3889.     sa.sin_addr.s_addr = INADDR_ANY;
  3890.     uport = (unsigned short) 0;
  3891.     sa.sin_port = htons(uport);
  3892.     if (bind(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) {
  3893.     return errno;
  3894.     }
  3895.  
  3896.     memset((char *) &sa, (int)0, sizeof(struct sockaddr_in));
  3897.     if (!(hp = gethostbyname(host))) {
  3898.     int b0, b1, b2, b3;
  3899.     if (sscanf(host, "%d.%d.%d.%d", &b0, &b1, &b2, &b3) == 4) {
  3900.         hp = (struct hostent *) calloc(1, sizeof(struct hostent));
  3901.         hp->h_addrtype = AF_INET;
  3902.         hp->h_length = 4;
  3903.         hp->h_addr_list = (char **) calloc(2, sizeof(char *));
  3904.         hp->h_addr_list[0] = (char *) malloc(4);
  3905.         hp->h_addr_list[0][0] = b0;
  3906.         hp->h_addr_list[0][1] = b1;
  3907.         hp->h_addr_list[0][2] = b2;
  3908.         hp->h_addr_list[0][3] = b3;
  3909.     } else {
  3910.         return ENOENT;
  3911.     }
  3912.     }
  3913.     sa.sin_family = hp->h_addrtype;
  3914.     uport = (unsigned short) port;
  3915.     sa.sin_port = htons(uport);
  3916.     memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
  3917.  
  3918.     if (connect(s, (struct sockaddr *) &sa, 
  3919.         sizeof(struct sockaddr_in)) < 0) {
  3920.     return errno;
  3921.     }
  3922.  
  3923.     cp = (ChildProc *) calloc(1, sizeof(ChildProc));
  3924.     cp->kind = CPSock;
  3925.     cp->pid = 0;
  3926.     cp->fdFrom = s;
  3927.     cp->fdTo = s;
  3928.     *pr = (ProcRef) cp;
  3929.  
  3930. #endif /* !OMIT_SOCKETS */
  3931.  
  3932.     return 0;
  3933. }
  3934.  
  3935. int OpenCommPort(name, pr)
  3936.      char *name;
  3937.      ProcRef *pr;
  3938. {
  3939.     int fd;
  3940.     ChildProc *cp;
  3941.  
  3942.     fd = open(name, 2, 0);
  3943.     if (fd < 0) return errno;
  3944.  
  3945.     cp = (ChildProc *) calloc(1, sizeof(ChildProc));
  3946.     cp->kind = CPComm;
  3947.     cp->pid = 0;
  3948.     cp->fdFrom = fd;
  3949.     cp->fdTo = fd;
  3950.     *pr = (ProcRef) cp;
  3951.  
  3952.     return 0;
  3953. }
  3954.  
  3955. int OpenLoopback(pr)
  3956.      ProcRef *pr;
  3957. {
  3958.     ChildProc *cp;
  3959.     int to[2], from[2];
  3960.  
  3961.     SetUpChildIO(to, from);
  3962.  
  3963.     cp = (ChildProc *) calloc(1, sizeof(ChildProc));
  3964.     cp->kind = CPLoop;
  3965.     cp->pid = 0;
  3966.     cp->fdFrom = to[0];  /* note not from[0]; we are doing a loopback */
  3967.     cp->fdTo = to[1];
  3968.     *pr = (ProcRef) cp;
  3969.  
  3970.     return 0;
  3971. }
  3972.  
  3973. int OpenRcmd(host, user, cmd, pr)
  3974.      char *host, *user, *cmd;
  3975.      ProcRef *pr;
  3976. {
  3977.     DisplayFatalError("internal rcmd not implemented for Unix", 0, 1);
  3978.     return -1;
  3979. }    
  3980.  
  3981. #define INPUT_SOURCE_BUF_SIZE 4096
  3982.  
  3983. typedef struct {
  3984.     CPKind kind;
  3985.     int fd;
  3986.     FILE *f;
  3987.     int lineByLine;
  3988.     InputCallback func;
  3989.     XtInputId xid;
  3990.     char buf[INPUT_SOURCE_BUF_SIZE];
  3991. } InputSource;
  3992.  
  3993. void DoInputCallback(closure, source, xid) 
  3994.      caddr_t closure;
  3995.      int *source;
  3996.      XtInputId *xid;
  3997. {
  3998.     InputSource *is = (InputSource *) closure;
  3999.     int count;
  4000.     int error;
  4001.  
  4002.     if (is->lineByLine) {
  4003.     if (fgets(is->buf, INPUT_SOURCE_BUF_SIZE, is->f) == NULL) {
  4004.         error = ferror(is->f);
  4005.         if (error == 0)
  4006.           count = 0;
  4007.         else
  4008.           count = -1;
  4009.         (is->func)((InputSourceRef) is, is->buf, count, error);
  4010.     } else {
  4011.         (is->func)((InputSourceRef) is, is->buf, strlen(is->buf), 0);
  4012.     }
  4013.     } else {
  4014.     count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE);
  4015.     if (count == -1)
  4016.       error = errno;
  4017.     else
  4018.       error = 0;
  4019.     (is->func)((InputSourceRef) is, is->buf, count, error);
  4020.     }    
  4021. }
  4022.  
  4023. InputSourceRef AddInputSource(pr, lineByLine, func)
  4024.      ProcRef pr;
  4025.      int lineByLine;
  4026.      InputCallback func;
  4027. {
  4028.     InputSource *is;
  4029.     ChildProc *cp = (ChildProc *) pr;
  4030.  
  4031.     is = (InputSource *) calloc(1, sizeof(InputSource));
  4032.     is->lineByLine = lineByLine;
  4033.     is->func = func;
  4034.     if (pr == NoProc) {
  4035.     is->kind = CPReal;
  4036.     is->fd = fileno(stdin);
  4037.     } else {
  4038.     is->kind = cp->kind;
  4039.     is->fd = cp->fdFrom;
  4040.     }
  4041.     if (lineByLine) {
  4042.     is->f = fdopen(is->fd, "r");
  4043.     setbuf(is->f, NULL);
  4044.     }
  4045.     
  4046.     is->xid = XtAppAddInput(appContext, is->fd,
  4047.                 (XtPointer) (XtInputReadMask),
  4048.                 (XtInputCallbackProc) DoInputCallback,
  4049.                 (XtPointer) is);
  4050.     return (InputSourceRef) is;
  4051. }
  4052.  
  4053. void RemoveInputSource(isr)
  4054.      InputSourceRef isr;
  4055. {
  4056.     InputSource *is = (InputSource *) isr;
  4057.  
  4058.     if (is->xid == 0) return;
  4059.     XtRemoveInput(is->xid);
  4060.     if (is->lineByLine) {
  4061.     fclose(is->f);
  4062.     }
  4063.     is->xid = 0;
  4064. }
  4065.  
  4066. int OutputToProcess(pr, message, count, outError)
  4067.      ProcRef pr;
  4068.      char *message;
  4069.      int count;
  4070.      int *outError;
  4071. {
  4072.     ChildProc *cp = (ChildProc *) pr;
  4073.     int outCount;
  4074.  
  4075.     outCount = write(cp->fdTo, message, count);
  4076.     if (outCount == -1)
  4077.       *outError = errno;
  4078.     else
  4079.       *outError = 0;
  4080.     return outCount;
  4081. }
  4082.  
  4083.  
  4084.