From e6f4f8fdada1a701e4be2e4807920dbcad697fb1 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Wed, 24 Oct 2012 08:55:27 +0200 Subject: [PATCH] Move X11 front-end to directory xaw --- Makefile.am | 16 +- xaw/xboard.c | 2556 +++++++++++++++++++++++++++++++++++++++++++++++++++ xaw/xboard.h | 176 ++++ xaw/xedittags.c | 121 +++ xaw/xedittags.h | 30 + xaw/xengineoutput.c | 286 ++++++ xaw/xevalgraph.c | 339 +++++++ xaw/xevalgraph.h | 31 + xaw/xgamelist.c | 118 +++ xaw/xgamelist.h | 31 + xaw/xhistory.c | 169 ++++ xaw/xhistory.h | 29 + xaw/xoptions.c | 1216 ++++++++++++++++++++++++ xboard.c | 2556 --------------------------------------------------- xboard.h | 176 ---- xedittags.c | 121 --- xedittags.h | 30 - xengineoutput.c | 286 ------ xevalgraph.c | 339 ------- xevalgraph.h | 31 - xgamelist.c | 118 --- xgamelist.h | 31 - xhistory.c | 169 ---- xhistory.h | 29 - xoptions.c | 1216 ------------------------ 25 files changed, 5110 insertions(+), 5110 deletions(-) create mode 100644 xaw/.dirstamp create mode 100644 xaw/xboard.c create mode 100644 xaw/xboard.h create mode 100644 xaw/xedittags.c create mode 100644 xaw/xedittags.h create mode 100644 xaw/xengineoutput.c create mode 100644 xaw/xevalgraph.c create mode 100644 xaw/xevalgraph.h create mode 100644 xaw/xgamelist.c create mode 100644 xaw/xgamelist.h create mode 100644 xaw/xhistory.c create mode 100644 xaw/xhistory.h create mode 100644 xaw/xoptions.c delete mode 100644 xboard.c delete mode 100644 xboard.h delete mode 100644 xedittags.c delete mode 100644 xedittags.h delete mode 100644 xengineoutput.c delete mode 100644 xevalgraph.c delete mode 100644 xevalgraph.h delete mode 100644 xgamelist.c delete mode 100644 xgamelist.h delete mode 100644 xhistory.c delete mode 100644 xhistory.h delete mode 100644 xoptions.c diff --git a/Makefile.am b/Makefile.am index b9308c4..e3af927 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,17 +19,17 @@ xboard_SOURCES = backend.c backend.h backendz.h \ parser.c parser.h \ pgntags.c \ uci.c \ - xboard.c xboard.h args.h menus.c menus.h \ + xaw/xboard.c xaw/xboard.h args.h menus.c menus.h \ draw.c draw.h \ usounds.c usystem.c usystem.h \ board.c board.h \ - xedittags.c xedittags.h \ + xaw/xedittags.c xaw/xedittags.h \ engineoutput.c engineoutput.h \ - nengineoutput.c xengineoutput.c \ - evalgraph.c evalgraph.h xevalgraph.c xevalgraph.h\ - xgamelist.c xgamelist.h\ - history.c xhistory.c xhistory.h \ - xoptions.c dialogs.c dialogs.h \ + nengineoutput.c xaw/xengineoutput.c \ + evalgraph.c evalgraph.h xaw/xevalgraph.c xaw/xevalgraph.h\ + xaw/xgamelist.c xaw/xgamelist.h\ + history.c xaw/xhistory.c xaw/xhistory.h \ + xaw/xoptions.c dialogs.c dialogs.h \ $(ZPY) SUBDIRS = po xboard_LDADD = -lm @XAW_LIBS@ @X_LIBS@ @LIBINTL@ @CAIRO_LIBS@ @@ -42,7 +42,7 @@ EXTRA_DIST = pixmaps shogi sounds winboard bitmaps\ DISTCLEANFILES = stamp-h AM_CPPFLAGS=-DINFODIR='"$(infodir)"' @CAIRO_CFLAGS@ @X_CFLAGS@ -DSYSCONFDIR='"$(sysconfdir)"' \ - -DLOCALEDIR='"$(localedir)"' -DSVGDIR='"$(svgdir)"' + -DLOCALEDIR='"$(localedir)"' -DSVGDIR='"$(svgdir)"' -I xaw ACLOCAL_AMFLAGS = -I m4 diff --git a/xaw/.dirstamp b/xaw/.dirstamp new file mode 100644 index 0000000..e69de29 diff --git a/xaw/xboard.c b/xaw/xboard.c new file mode 100644 index 0000000..69079be --- /dev/null +++ b/xaw/xboard.c @@ -0,0 +1,2556 @@ +/* + * xboard.c -- X front end for XBoard + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, + * Massachusetts. + * + * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, + * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * + * The following terms apply to Digital Equipment Corporation's copyright + * interest in XBoard: + * ------------------------------------------------------------------------ + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * ------------------------------------------------------------------------ + * + * The following terms apply to the enhanced version of XBoard + * distributed by the Free Software Foundation: + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#define HIGHDRAG 1 + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !OMIT_SOCKETS +# if HAVE_SYS_SOCKET_H +# include +# include +# include +# else /* not HAVE_SYS_SOCKET_H */ +# if HAVE_LAN_SOCKET_H +# include +# include +# include +# else /* not HAVE_LAN_SOCKET_H */ +# define OMIT_SOCKETS 1 +# endif /* not HAVE_LAN_SOCKET_H */ +# endif /* not HAVE_SYS_SOCKET_H */ +#endif /* !OMIT_SOCKETS */ + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +extern char *getenv(); +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_SYS_FCNTL_H +# include +#else /* not HAVE_SYS_FCNTL_H */ +# if HAVE_FCNTL_H +# include +# endif /* HAVE_FCNTL_H */ +#endif /* not HAVE_SYS_FCNTL_H */ + +#if HAVE_SYS_SYSTEMINFO_H +# include +#endif /* HAVE_SYS_SYSTEMINFO_H */ + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#if HAVE_SYS_WAIT_H +# include +#endif + +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +# define HAVE_DIR_STRUCT +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# define HAVE_DIR_STRUCT +# endif +# if HAVE_SYS_DIR_H +# include +# define HAVE_DIR_STRUCT +# endif +# if HAVE_NDIR_H +# include +# define HAVE_DIR_STRUCT +# endif +#endif + +#if ENABLE_NLS +#include +#endif + +#include +#include +#include +#include +#include +#include +#if USE_XAW3D +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are. +#include "common.h" + +#if HAVE_LIBXPM +#include +#define IMAGE_EXT "xpm" +#else +#define IMAGE_EXT "xim" +#endif + +#include "bitmaps/icon_white.bm" +#include "bitmaps/icon_black.bm" +#include "bitmaps/checkmark.bm" + +#include "frontend.h" +#include "backend.h" +#include "backendz.h" +#include "moves.h" +#include "xboard.h" +#include "childio.h" +#include "xgamelist.h" +#include "xhistory.h" +#include "xevalgraph.h" +#include "xedittags.h" +#include "menus.h" +#include "board.h" +#include "dialogs.h" +#include "engineoutput.h" +#include "usystem.h" +#include "gettext.h" +#include "draw.h" + + +#ifdef __EMX__ +#ifndef HAVE_USLEEP +#define HAVE_USLEEP +#endif +#define usleep(t) _sleep2(((t)+500)/1000) +#endif + +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif + +int main P((int argc, char **argv)); +RETSIGTYPE CmailSigHandler P((int sig)); +RETSIGTYPE IntSigHandler P((int sig)); +RETSIGTYPE TermSizeSigHandler P((int sig)); +Widget CreateMenuBar P((Menu *mb, int boardWidth)); +#if ENABLE_NLS +char *InsertPxlSize P((char *pattern, int targetPxlSize)); +XFontSet CreateFontSet P((char *base_fnt_lst)); +#else +char *FindFont P((char *pattern, int targetPxlSize)); +#endif +void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[], + u_int wreq, u_int hreq)); +void EventProc P((Widget widget, caddr_t unused, XEvent *event)); +void DelayedDrag P((void)); +static void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event)); +void HandlePV P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); +void DrawPositionProc P((Widget w, XEvent *event, + String *prms, Cardinal *nprms)); +void CommentClick P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); +void ICSInputBoxPopUp P((void)); +void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data)); +void KeyBindingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void QuitWrapper P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +static void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +static void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +static void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +Boolean TempBackwardActive = False; +void ManInner P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void DisplayMove P((int moveNumber)); +void ICSInitScript P((void)); +void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams)); +void update_ics_width P(()); +int CopyMemoProc P(()); + +/* +* XBoard depends on Xt R4 or higher +*/ +int xtVersion = XtSpecificationRelease; + +int xScreen; +Display *xDisplay; +Window xBoardWindow; +Pixel lowTimeWarningColor, dialogColor, buttonColor; // used in widgets +Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap; +Widget shellWidget, formWidget, boardWidget, titleWidget, dropMenu, menuBarWidget; +Option *optList; // contains all widgets of main window +#if ENABLE_NLS +XFontSet fontSet, clockFontSet; +#else +Font clockFontID; +XFontStruct *clockFontStruct; +#endif +Font coordFontID, countFontID; +XFontStruct *coordFontStruct, *countFontStruct; +XtAppContext appContext; +char *layoutName; + +char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion + +Position commentX = -1, commentY = -1; +Dimension commentW, commentH; +typedef unsigned int BoardSize; +BoardSize boardSize; +Boolean chessProgram; + +int minX, minY; // [HGM] placement: volatile limits on upper-left corner +int smallLayout = 0, tinyLayout = 0, + marginW, marginH, // [HGM] for run-time resizing + fromX = -1, fromY = -1, toX, toY, commentUp = False, + errorExitStatus = -1, defaultLineGap; +Dimension textHeight; +Pixel timerForegroundPixel, timerBackgroundPixel; +Pixel buttonForegroundPixel, buttonBackgroundPixel; +char *chessDir, *programName, *programVersion; +Boolean alwaysOnTop = False; +char *icsTextMenuString; +char *icsNames; +char *firstChessProgramNames; +char *secondChessProgramNames; + +WindowPlacement wpMain; +WindowPlacement wpConsole; +WindowPlacement wpComment; +WindowPlacement wpMoveHistory; +WindowPlacement wpEvalGraph; +WindowPlacement wpEngineOutput; +WindowPlacement wpGameList; +WindowPlacement wpTags; + + +/* This magic number is the number of intermediate frames used + in each half of the animation. For short moves it's reduced + by 1. The total number of frames will be factor * 2 + 1. */ +#define kFactor 4 + +SizeDefaults sizeDefaults[] = SIZE_DEFAULTS; + +typedef struct { + char piece; + char* widget; +} DropMenuEnables; + +DropMenuEnables dmEnables[] = { + { 'P', "Pawn" }, + { 'N', "Knight" }, + { 'B', "Bishop" }, + { 'R', "Rook" }, + { 'Q', "Queen" } +}; + +Arg shellArgs[] = { + { XtNwidth, 0 }, + { XtNheight, 0 }, + { XtNminWidth, 0 }, + { XtNminHeight, 0 }, + { XtNmaxWidth, 0 }, + { XtNmaxHeight, 0 } +}; + +XtResource clientResources[] = { + { "flashCount", "flashCount", XtRInt, sizeof(int), + XtOffset(AppDataPtr, flashCount), XtRImmediate, + (XtPointer) FLASH_COUNT }, +}; + +XrmOptionDescRec shellOptions[] = { + { "-flashCount", "flashCount", XrmoptionSepArg, NULL }, + { "-flash", "flashCount", XrmoptionNoArg, "3" }, + { "-xflash", "flashCount", XrmoptionNoArg, "0" }, +}; + +XtActionsRec boardActions[] = { + { "DrawPosition", DrawPositionProc }, + { "HandlePV", HandlePV }, + { "SelectPV", SelectPV }, + { "StopPV", StopPV }, + { "MenuItem", KeyBindingProc }, // [HGM] generic handler for key bindings + { "QuitProc", QuitWrapper }, + { "ManProc", ManInner }, + { "TempBackwardProc", TempBackwardProc }, + { "TempForwardProc", TempForwardProc }, + { "CommentClick", (XtActionProc) CommentClick }, + { "GenericPopDown", (XtActionProc) GenericPopDown }, + { "ErrorPopDown", (XtActionProc) ErrorPopDown }, + { "CopyMemoProc", (XtActionProc) CopyMemoProc }, + { "SelectMove", (XtActionProc) SelectMove }, + { "LoadSelectedProc", LoadSelectedProc }, + { "SetFilterProc", SetFilterProc }, + { "TypeInProc", TypeInProc }, + { "EnterKeyProc", EnterKeyProc }, + { "UpKeyProc", UpKeyProc }, + { "DownKeyProc", DownKeyProc }, + { "WheelProc", WheelProc }, + { "TabProc", TabProc }, +}; + +char globalTranslations[] = + ":F9: MenuItem(Actions.Resign) \n \ + :Ctrln: MenuItem(File.NewGame) \n \ + :MetaV: MenuItem(File.NewVariant) \n \ + :Ctrlo: MenuItem(File.LoadGame) \n \ + :MetaNext: MenuItem(LoadNextGameProc) \n \ + :MetaPrior: MenuItem(LoadPrevGameProc) \n \ + :CtrlDown: LoadSelectedProc(3) \n \ + :CtrlUp: LoadSelectedProc(-3) \n \ + :Ctrls: MenuItem(File.SaveGame) \n \ + :Ctrlc: MenuItem(Edit.CopyGame) \n \ + :Ctrlv: MenuItem(Edit.PasteGame) \n \ + :CtrlO: MenuItem(File.LoadPosition) \n \ + :ShiftNext: MenuItem(LoadNextPositionProc) \n \ + :ShiftPrior: MenuItem(LoadPrevPositionProc) \n \ + :CtrlS: MenuItem(File.SavePosition) \n \ + :CtrlC: MenuItem(Edit.CopyPosition) \n \ + :CtrlV: MenuItem(Edit.PastePosition) \n \ + :Ctrlq: MenuItem(File.Quit) \n \ + :Ctrlw: MenuItem(Mode.MachineWhite) \n \ + :Ctrlb: MenuItem(Mode.MachineBlack) \n \ + :Ctrlt: MenuItem(Mode.TwoMachines) \n \ + :Ctrla: MenuItem(Mode.AnalysisMode) \n \ + :Ctrlg: MenuItem(Mode.AnalyzeFile) \n \ + :Ctrle: MenuItem(Mode.EditGame) \n \ + :CtrlE: MenuItem(Mode.EditPosition) \n \ + :MetaO: MenuItem(View.EngineOutput) \n \ + :MetaE: MenuItem(View.EvaluationGraph) \n \ + :MetaG: MenuItem(View.GameList) \n \ + :MetaH: MenuItem(View.MoveHistory) \n \ + :Pause: MenuItem(Mode.Pause) \n \ + :F3: MenuItem(Action.Accept) \n \ + :F4: MenuItem(Action.Decline) \n \ + :F12: MenuItem(Action.Rematch) \n \ + :F5: MenuItem(Action.CallFlag) \n \ + :F6: MenuItem(Action.Draw) \n \ + :F7: MenuItem(Action.Adjourn) \n \ + :F8: MenuItem(Action.Abort) \n \ + :F10: MenuItem(Action.StopObserving) \n \ + :F11: MenuItem(Action.StopExamining) \n \ + :Ctrld: MenuItem(DebugProc) \n \ + :Meta CtrlF12: MenuItem(DebugProc) \n \ + :MetaEnd: MenuItem(Edit.ForwardtoEnd) \n \ + :MetaRight: MenuItem(Edit.Forward) \n \ + :MetaHome: MenuItem(Edit.BacktoStart) \n \ + :MetaLeft: MenuItem(Edit.Backward) \n \ + :Left: MenuItem(Edit.Backward) \n \ + :Right: MenuItem(Edit.Forward) \n \ + :Home: MenuItem(Edit.Revert) \n \ + :End: MenuItem(Edit.TruncateGame) \n \ + :Ctrlm: MenuItem(Engine.MoveNow) \n \ + :Ctrlx: MenuItem(Engine.RetractMove) \n \ + :MetaJ: MenuItem(Options.Adjudications) \n \ + :MetaU: MenuItem(Options.CommonEngine) \n \ + :MetaT: MenuItem(Options.TimeControl) \n \ + :CtrlP: MenuItem(PonderNextMove) \n " +#ifndef OPTIONSDIALOG + "\ + :CtrlQ: MenuItem(AlwaysQueenProc) \n \ + :CtrlF: MenuItem(AutoflagProc) \n \ + :CtrlA: MenuItem(AnimateMovingProc) \n \ + :CtrlL: MenuItem(TestLegalityProc) \n \ + :CtrlH: MenuItem(HideThinkingProc) \n " +#endif + "\ + :F1: MenuItem(Help.ManXBoard) \n \ + :F2: MenuItem(View.FlipView) \n \ + :Return: TempBackwardProc() \n \ + :Return: TempForwardProc() \n"; + +char ICSInputTranslations[] = + "Up: UpKeyProc() \n " + "Down: DownKeyProc() \n " + "Return: EnterKeyProc() \n"; + +// [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works, +// as the widget is destroyed before the up-click can call extend-end +char commentTranslations[] = ": extend-end() select-start() CommentClick() \n"; + +String xboardResources[] = { + "*Error*translations: #override\\n Return: ErrorPopDown()", + NULL + }; + + +/* Max possible square size */ +#define MAXSQSIZE 256 + +static int xpm_avail[MAXSQSIZE]; + +#ifdef HAVE_DIR_STRUCT + +/* Extract piece size from filename */ +static int +xpm_getsize (char *name, int len, char *ext) +{ + char *p, *d; + char buf[10]; + + if (len < 4) + return 0; + + if ((p=strchr(name, '.')) == NULL || + StrCaseCmp(p+1, ext) != 0) + return 0; + + p = name + 3; + d = buf; + + while (*p && isdigit(*p)) + *(d++) = *(p++); + + *d = 0; + return atoi(buf); +} + +/* Setup xpm_avail */ +static int +xpm_getavail (char *dirname, char *ext) +{ + DIR *dir; + struct dirent *ent; + int i; + + for (i=0; id_name, NAMLEN(ent), ext); + if (i > 0 && i < MAXSQSIZE) + xpm_avail[i] = 1; + } + + closedir(dir); + + return 0; +} + +void +xpm_print_avail (FILE *fp, char *ext) +{ + int i; + + fprintf(fp, _("Available `%s' sizes:\n"), ext); + for (i=1; iWM_PROTOCOLS: %s() \n", procname); + XtAugmentTranslations(w, XtParseTranslationTable(buf)); +} + +void +BoardToTop () +{ + Arg args[16]; + XtSetArg(args[0], XtNiconic, False); + XtSetValues(shellWidget, args, 1); + + XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */ +} + +//--------------------------------------------------------------------------------------------------------- +// some symbol definitions to provide the proper (= XBoard) context for the code in args.h +#define XBOARD True +#define JAWS_ARGS +#define CW_USEDEFAULT (1<<31) +#define ICS_TEXT_MENU_SIZE 90 +#define DEBUG_FILE "xboard.debug" +#define SetCurrentDirectory chdir +#define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE) +#define OPTCHAR "-" +#define SEPCHAR " " + +// The option definition and parsing code common to XBoard and WinBoard is collected in this file +#include "args.h" + +// front-end part of option handling + +// [HGM] This platform-dependent table provides the location for storing the color info +extern char *crWhite, * crBlack; + +void * +colorVariable[] = { + &appData.whitePieceColor, + &appData.blackPieceColor, + &appData.lightSquareColor, + &appData.darkSquareColor, + &appData.highlightSquareColor, + &appData.premoveHighlightColor, + &appData.lowTimeWarningColor, + NULL, + NULL, + NULL, + NULL, + NULL, + &crWhite, + &crBlack, + NULL +}; + +// [HGM] font: keep a font for each square size, even non-stndard ones +#define NUM_SIZES 18 +#define MAX_SIZE 130 +Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE]; +char *fontTable[NUM_FONTS][MAX_SIZE]; + +void +ParseFont (char *name, int number) +{ // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name + int size; + if(sscanf(name, "size%d:", &size)) { + // [HGM] font: font is meant for specific boardSize (likely from settings file); + // defer processing it until we know if it matches our board size + if(size >= 0 && sizeargLoc; + switch(n) { + case 0: // CLOCK_FONT + name = appData.clockFont; + break; + case 1: // MESSAGE_FONT + name = appData.font; + break; + case 2: // COORD_FONT + name = appData.coordFont; + break; + default: + return; + } + for(i=0; iargName, i, fontTable[n][i]); +} + +void +ExportSounds () +{ // nothing to do, as the sounds are at all times represented by their text-string names already +} + +void +SaveAttribsArg (FILE *f, ArgDescriptor *ad) +{ // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though + fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]); +} + +void +SaveColor (FILE *f, ArgDescriptor *ad) +{ // in WinBoard the color is an int and has to be converted to text. In X it would be a string already? + if(colorVariable[(int)(intptr_t)ad->argLoc]) + fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]); +} + +void +SaveBoardSize (FILE *f, char *name, void *addr) +{ // wrapper to shield back-end from BoardSize & sizeInfo + fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize); +} + +void +ParseCommPortSettings (char *s) +{ // no such option in XBoard (yet) +} + +int frameX, frameY; + +void +GetActualPlacement (Widget wg, WindowPlacement *wp) +{ + XWindowAttributes winAt; + Window win, dummy; + int rx, ry; + + if(!wg) return; + + win = XtWindow(wg); + XGetWindowAttributes(xDisplay, win, &winAt); // this works, where XtGetValues on XtNx, XtNy does not! + XTranslateCoordinates (xDisplay, win, winAt.root, -winAt.border_width, -winAt.border_width, &rx, &ry, &dummy); + wp->x = rx - winAt.x; + wp->y = ry - winAt.y; + wp->height = winAt.height; + wp->width = winAt.width; + frameX = winAt.x; frameY = winAt.y; // remember to decide if windows touch +} + +void +GetWindowCoords () +{ // wrapper to shield use of window handles from back-end (make addressible by number?) + // In XBoard this will have to wait until awareness of window parameters is implemented + GetActualPlacement(shellWidget, &wpMain); + if(shellUp[EngOutDlg]) GetActualPlacement(shells[EngOutDlg], &wpEngineOutput); + if(shellUp[HistoryDlg]) GetActualPlacement(shells[HistoryDlg], &wpMoveHistory); + if(shellUp[EvalGraphDlg]) GetActualPlacement(shells[EvalGraphDlg], &wpEvalGraph); + if(shellUp[GameListDlg]) GetActualPlacement(shells[GameListDlg], &wpGameList); + if(shellUp[CommentDlg]) GetActualPlacement(shells[CommentDlg], &wpComment); + if(shellUp[TagsDlg]) GetActualPlacement(shells[TagsDlg], &wpTags); +} + +void +PrintCommPortSettings (FILE *f, char *name) +{ // This option does not exist in XBoard +} + +void +EnsureOnScreen (int *x, int *y, int minX, int minY) +{ + return; +} + +int +MainWindowUp () +{ // [HGM] args: allows testing if main window is realized from back-end + return xBoardWindow != 0; +} + +void +PopUpStartupDialog () +{ // start menu not implemented in XBoard +} + +char * +ConvertToLine (int argc, char **argv) +{ + static char line[128*1024], buf[1024]; + int i; + + line[0] = NULLCHAR; + for(i=1; imax_logical_extent.height + 5; // add borderWidth + } +#else + appData.font = FindFont(appData.font, fontPxlSize); + appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize); + appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize); + clockFontID = XLoadFont(xDisplay, appData.clockFont); + clockFontStruct = XQueryFont(xDisplay, clockFontID); + coordFontID = XLoadFont(xDisplay, appData.coordFont); + coordFontStruct = XQueryFont(xDisplay, coordFontID); + // textHeight in !NLS mode! +#endif + countFontID = coordFontID; // [HGM] holdings + countFontStruct = coordFontStruct; + + xdb = XtDatabase(xDisplay); +#if ENABLE_NLS + XrmPutLineResource(&xdb, "*international: True"); + vTo.size = sizeof(XFontSet); + vTo.addr = (XtPointer) &fontSet; + XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo); +#else + XrmPutStringResource(&xdb, "*font", appData.font); +#endif +} + +char * +PrintArg (ArgType t) +{ + char *p=""; + switch(t) { + case ArgZ: + case ArgInt: p = " N"; break; + case ArgString: p = " STR"; break; + case ArgBoolean: p = " TF"; break; + case ArgSettingsFilename: + case ArgFilename: p = " FILE"; break; + case ArgX: p = " Nx"; break; + case ArgY: p = " Ny"; break; + case ArgAttribs: p = " TEXTCOL"; break; + case ArgColor: p = " COL"; break; + case ArgFont: p = " FONT"; break; + case ArgBoardSize: p = " SIZE"; break; + case ArgFloat: p = " FLOAT"; break; + case ArgTrue: + case ArgFalse: + case ArgTwo: + case ArgNone: + case ArgCommSettings: + break; + } + return p; +} + +void +PrintOptions () +{ + char buf[MSG_SIZ]; + int len=0; + ArgDescriptor *q, *p = argDescriptors+5; + printf("\nXBoard accepts the following options:\n" + "(N = integer, TF = true or false, STR = text string, FILE = filename,\n" + " Nx, Ny = relative coordinates, COL = color, FONT = X-font spec,\n" + " SIZE = board-size spec(s)\n" + " Within parentheses are short forms, or options to set to true or false.\n" + " Persistent options (saved in the settings file) are marked with *)\n\n"); + while(p->argName) { + if(p->argType == ArgCommSettings) { p++; continue; } // XBoard has no comm port + snprintf(buf+len, MSG_SIZ, "-%s%s", p->argName, PrintArg(p->argType)); + if(p->save) strcat(buf+len, "*"); + for(q=p+1; q->argLoc == p->argLoc; q++) { + if(q->argName[0] == '-') continue; + strcat(buf+len, q == p+1 ? " (" : " "); + sprintf(buf+strlen(buf), "-%s%s", q->argName, PrintArg(q->argType)); + } + if(q != p+1) strcat(buf+len, ")"); + len = strlen(buf); + if(len > 39) len = 0, printf("%s\n", buf); else while(len < 39) buf[len++] = ' '; + p = q; + } + if(len) buf[len] = NULLCHAR, printf("%s\n", buf); +} + +int +main (int argc, char **argv) +{ + int i, clockFontPxlSize, coordFontPxlSize, fontPxlSize; + XSetWindowAttributes window_attributes; + Arg args[16]; + Dimension boardWidth, boardHeight, w, h; + char *p; + int forceMono = False; + + srandom(time(0)); // [HGM] book: make random truly random + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + debugFP = stderr; + + if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) { + printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); + exit(0); + } + + if(argc > 1 && !strcmp(argv[1], "--help" )) { + PrintOptions(); + exit(0); + } + + programName = strrchr(argv[0], '/'); + if (programName == NULL) + programName = argv[0]; + else + programName++; + +#ifdef ENABLE_NLS + XtSetLanguageProc(NULL, NULL, NULL); + if (appData.debugMode) { + fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL)); + } + + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); +#endif + + appData.boardSize = ""; + InitAppData(ConvertToLine(argc, argv)); + p = getenv("HOME"); + if (p == NULL) p = "/tmp"; + i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1; + gameCopyFilename = (char*) malloc(i); + gamePasteFilename = (char*) malloc(i); + snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid()); + snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid()); + + { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string. + static char buf[MSG_SIZ]; + EscapeExpand(buf, appData.firstInitString); + appData.firstInitString = strdup(buf); + EscapeExpand(buf, appData.secondInitString); + appData.secondInitString = strdup(buf); + EscapeExpand(buf, appData.firstComputerString); + appData.firstComputerString = strdup(buf); + EscapeExpand(buf, appData.secondComputerString); + appData.secondComputerString = strdup(buf); + } + + if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) { + chessDir = "."; + } else { + if (chdir(chessDir) != 0) { + fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName); + perror(chessDir); + exit(1); + } + } + + if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) { + /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */ + if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) { + printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile); + exit(errno); + } + setbuf(debugFP, NULL); + } + + /* [HGM,HR] make sure board size is acceptable */ + if(appData.NrFiles > BOARD_FILES || + appData.NrRanks > BOARD_RANKS ) + DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2); + +#if !HIGHDRAG + /* This feature does not work; animation needs a rewrite */ + appData.highlightDragging = FALSE; +#endif + InitBackEnd1(); + + gameInfo.variant = StringToVariant(appData.variant); + InitPosition(FALSE); + + shellWidget = + XtAppInitialize(&appContext, "XBoard", shellOptions, + XtNumber(shellOptions), + &argc, argv, xboardResources, NULL, 0); + + XtGetApplicationResources(shellWidget, (XtPointer) &appData, + clientResources, XtNumber(clientResources), + NULL, 0); + + xDisplay = XtDisplay(shellWidget); + xScreen = DefaultScreen(xDisplay); + wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True); + + /* + * determine size, based on supplied or remembered -size, or screen size + */ + if (isdigit(appData.boardSize[0])) { + i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize, + &lineGap, &clockFontPxlSize, &coordFontPxlSize, + &fontPxlSize, &smallLayout, &tinyLayout); + if (i == 0) { + fprintf(stderr, _("%s: bad boardSize syntax %s\n"), + programName, appData.boardSize); + exit(2); + } + if (i < 7) { + /* Find some defaults; use the nearest known size */ + SizeDefaults *szd, *nearest; + int distance = 99999; + nearest = szd = sizeDefaults; + while (szd->name != NULL) { + if (abs(szd->squareSize - squareSize) < distance) { + nearest = szd; + distance = abs(szd->squareSize - squareSize); + if (distance == 0) break; + } + szd++; + } + if (i < 2) lineGap = nearest->lineGap; + if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize; + if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize; + if (i < 5) fontPxlSize = nearest->fontPxlSize; + if (i < 6) smallLayout = nearest->smallLayout; + if (i < 7) tinyLayout = nearest->tinyLayout; + } + } else { + SizeDefaults *szd = sizeDefaults; + if (*appData.boardSize == NULLCHAR) { + while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize || + DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) { + szd++; + } + if (szd->name == NULL) szd--; + appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings + } else { + while (szd->name != NULL && + StrCaseCmp(szd->name, appData.boardSize) != 0) szd++; + if (szd->name == NULL) { + fprintf(stderr, _("%s: unrecognized boardSize name %s\n"), + programName, appData.boardSize); + exit(2); + } + } + squareSize = szd->squareSize; + lineGap = szd->lineGap; + clockFontPxlSize = szd->clockFontPxlSize; + coordFontPxlSize = szd->coordFontPxlSize; + fontPxlSize = szd->fontPxlSize; + smallLayout = szd->smallLayout; + tinyLayout = szd->tinyLayout; + // [HGM] font: use defaults from settings file if available and not overruled + } + + defaultLineGap = lineGap; + if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; + + /* [HR] height treated separately (hacked) */ + boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap); + boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap); + + /* + * Determine what fonts to use. + */ + InitializeFonts(clockFontPxlSize, coordFontPxlSize, fontPxlSize); + + /* + * Detect if there are not enough colors available and adapt. + */ + if (DefaultDepth(xDisplay, xScreen) <= 2) { + appData.monoMode = True; + } + + forceMono = MakeColors(); + + if (forceMono) { + fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"), + programName); + appData.monoMode = True; + } + + if (appData.monoMode && appData.debugMode) { + fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"), + (unsigned long) XWhitePixel(xDisplay, xScreen), + (unsigned long) XBlackPixel(xDisplay, xScreen)); + } + + ParseIcsTextColors(); + + XtAppAddActions(appContext, boardActions, XtNumber(boardActions)); + + /* + * widget hierarchy + */ + if (tinyLayout) { + layoutName = "tinyLayout"; + } else if (smallLayout) { + layoutName = "smallLayout"; + } else { + layoutName = "normalLayout"; + } + + optList = BoardPopUp(squareSize, lineGap, (void*) +#if ENABLE_NLS + &clockFontSet); +#else + clockFontStruct); +#endif + InitDrawingHandle(optList + W_BOARD); + currBoard = &optList[W_BOARD]; + boardWidget = optList[W_BOARD].handle; + menuBarWidget = optList[W_MENU].handle; + dropMenu = optList[W_DROP].handle; + titleWidget = optList[optList[W_TITLE].type != -1 ? W_TITLE : W_SMALL].handle; + formWidget = XtParent(boardWidget); + XtSetArg(args[0], XtNbackground, &timerBackgroundPixel); + XtSetArg(args[1], XtNforeground, &timerForegroundPixel); + XtGetValues(optList[W_WHITE].handle, args, 2); + if (appData.showButtonBar) { // can't we use timer pixels for this? (Or better yet, just black & white?) + XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel); + XtSetArg(args[1], XtNforeground, &buttonForegroundPixel); + XtGetValues(optList[W_PAUSE].handle, args, 2); + } + AppendEnginesToMenu(appData.recentEngineList); + + xBoardWindow = XtWindow(boardWidget); + + // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would + // not need to go into InitDrawingSizes(). + + /* + * Create X checkmark bitmap and initialize option menu checks. + */ + ReadBitmap(&xMarkPixmap, "checkmark.bm", + checkmark_bits, checkmark_width, checkmark_height); + InitMenuMarkers(); + + /* + * Create an icon. + */ + ReadBitmap(&wIconPixmap, "icon_white.bm", + icon_white_bits, icon_white_width, icon_white_height); + ReadBitmap(&bIconPixmap, "icon_black.bm", + icon_black_bits, icon_black_width, icon_black_height); + iconPixmap = wIconPixmap; + i = 0; + XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++; + XtSetValues(shellWidget, args, i); + + /* + * Create a cursor for the board widget. + */ + window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2); + XChangeWindowAttributes(xDisplay, xBoardWindow, + CWCursor, &window_attributes); + + /* + * Inhibit shell resizing. + */ + shellArgs[0].value = (XtArgVal) &w; + shellArgs[1].value = (XtArgVal) &h; + XtGetValues(shellWidget, shellArgs, 2); + shellArgs[4].value = shellArgs[2].value = w; + shellArgs[5].value = shellArgs[3].value = h; +// XtSetValues(shellWidget, &shellArgs[2], 4); + marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board + marginH = h - boardHeight; + + CatchDeleteWindow(shellWidget, "QuitProc"); + + CreateAnyPieces(); + CreateGrid(); + + if(appData.logoSize) + { // locate and read user logo + char buf[MSG_SIZ]; + snprintf(buf, MSG_SIZ, "%s/%s.png", appData.logoDir, UserName()); + ASSIGN(userLogo, buf); + } + + if (appData.animate || appData.animateDragging) + CreateAnimVars(); + + XtAugmentTranslations(formWidget, + XtParseTranslationTable(globalTranslations)); + + XtAddEventHandler(formWidget, KeyPressMask, False, + (XtEventHandler) MoveTypeInProc, NULL); + XtAddEventHandler(shellWidget, StructureNotifyMask, False, + (XtEventHandler) EventProc, NULL); + + /* [AS] Restore layout */ + if( wpMoveHistory.visible ) { + HistoryPopUp(); + } + + if( wpEvalGraph.visible ) + { + EvalGraphPopUp(); + }; + + if( wpEngineOutput.visible ) { + EngineOutputPopUp(); + } + + InitBackEnd2(); + + if (errorExitStatus == -1) { + if (appData.icsActive) { + /* We now wait until we see "login:" from the ICS before + sending the logon script (problems with timestamp otherwise) */ + /*ICSInitScript();*/ + if (appData.icsInputBox) ICSInputBoxPopUp(); + } + + #ifdef SIGWINCH + signal(SIGWINCH, TermSizeSigHandler); + #endif + signal(SIGINT, IntSigHandler); + signal(SIGTERM, IntSigHandler); + if (*appData.cmailGameName != NULLCHAR) { + signal(SIGUSR1, CmailSigHandler); + } + } + + gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes() + InitPosition(TRUE); + UpdateLogos(TRUE); +// XtSetKeyboardFocus(shellWidget, formWidget); + XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime); + + XtAppMainLoop(appContext); + if (appData.debugMode) fclose(debugFP); // [DM] debug + return 0; +} + +RETSIGTYPE +TermSizeSigHandler (int sig) +{ + update_ics_width(); +} + +RETSIGTYPE +IntSigHandler (int sig) +{ + ExitEvent(sig); +} + +RETSIGTYPE +CmailSigHandler (int sig) +{ + int dummy = 0; + int error; + + signal(SIGUSR1, SIG_IGN); /* suspend handler */ + + /* Activate call-back function CmailSigHandlerCallBack() */ + OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error); + + signal(SIGUSR1, CmailSigHandler); /* re-activate handler */ +} + +void +CmailSigHandlerCallBack (InputSourceRef isr, VOIDSTAR closure, char *message, int count, int error) +{ + BoardToTop(); + ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */ +} +/**** end signal code ****/ + + +#define Abs(n) ((n)<0 ? -(n) : (n)) + +#ifdef ENABLE_NLS +char * +InsertPxlSize (char *pattern, int targetPxlSize) +{ + char *base_fnt_lst, strInt[12], *p, *q; + int alternatives, i, len, strIntLen; + + /* + * Replace the "*" (if present) in the pixel-size slot of each + * alternative with the targetPxlSize. + */ + p = pattern; + alternatives = 1; + while ((p = strchr(p, ',')) != NULL) { + alternatives++; + p++; + } + snprintf(strInt, sizeof(strInt), "%d", targetPxlSize); + strIntLen = strlen(strInt); + base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1); + + p = pattern; + q = base_fnt_lst; + while (alternatives--) { + char *comma = strchr(p, ','); + for (i=0; i<14; i++) { + char *hyphen = strchr(p, '-'); + if (!hyphen) break; + if (comma && hyphen > comma) break; + len = hyphen + 1 - p; + if (i == 7 && *p == '*' && len == 2) { + p += len; + memcpy(q, strInt, strIntLen); + q += strIntLen; + *q++ = '-'; + } else { + memcpy(q, p, len); + p += len; + q += len; + } + } + if (!comma) break; + len = comma + 1 - p; + memcpy(q, p, len); + p += len; + q += len; + } + strcpy(q, p); + + return base_fnt_lst; +} + +XFontSet +CreateFontSet (char *base_fnt_lst) +{ + XFontSet fntSet; + char **missing_list; + int missing_count; + char *def_string; + + fntSet = XCreateFontSet(xDisplay, base_fnt_lst, + &missing_list, &missing_count, &def_string); + if (appData.debugMode) { + int i, count; + XFontStruct **font_struct_list; + char **font_name_list; + fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst); + if (fntSet) { + fprintf(debugFP, " got list %s, locale %s\n", + XBaseFontNameListOfFontSet(fntSet), + XLocaleOfFontSet(fntSet)); + count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list); + for (i = 0; i < count; i++) { + fprintf(debugFP, " got charset %s\n", font_name_list[i]); + } + } + for (i = 0; i < missing_count; i++) { + fprintf(debugFP, " missing charset %s\n", missing_list[i]); + } + } + if (fntSet == NULL) { + fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst); + exit(2); + } + return fntSet; +} +#else // not ENABLE_NLS +/* + * Find a font that matches "pattern" that is as close as + * possible to the targetPxlSize. Prefer fonts that are k + * pixels smaller to fonts that are k pixels larger. The + * pattern must be in the X Consortium standard format, + * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*". + * The return value should be freed with XtFree when no + * longer needed. + */ +char * +FindFont (char *pattern, int targetPxlSize) +{ + char **fonts, *p, *best, *scalable, *scalableTail; + int i, j, nfonts, minerr, err, pxlSize; + + fonts = XListFonts(xDisplay, pattern, 999999, &nfonts); + if (nfonts < 1) { + fprintf(stderr, _("%s: no fonts match pattern %s\n"), + programName, pattern); + exit(2); + } + + best = fonts[0]; + scalable = NULL; + minerr = 999999; + for (i=0; i 0 && err < 0 && -err == minerr)) { + best = fonts[i]; + minerr = err; + } + } + } + if (scalable && Abs(minerr) > appData.fontSizeTolerance) { + /* If the error is too big and there is a scalable font, + use the scalable font. */ + int headlen = scalableTail - scalable; + p = (char *) XtMalloc(strlen(scalable) + 10); + while (isdigit(*scalableTail)) scalableTail++; + sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail); + } else { + p = (char *) XtMalloc(strlen(best) + 2); + safeStrCpy(p, best, strlen(best)+1 ); + } + if (appData.debugMode) { + fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"), + pattern, targetPxlSize, p); + } + XFreeFontNames(fonts); + return p; +} +#endif + +void +ReadBitmap (Pixmap *pm, String name, unsigned char bits[], u_int wreq, u_int hreq) +{ + if (bits != NULL) { + *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits, + wreq, hreq); + } +} + +void +MarkMenuItem (char *menuRef, int state) +{ + MenuItem *item = MenuNameToItem(menuRef); + + if(item) { + Arg args[2]; + XtSetArg(args[0], XtNleftBitmap, state ? xMarkPixmap : None); + XtSetValues(item->handle, args, 1); + } +} + +void +EnableNamedMenuItem (char *menuRef, int state) +{ + MenuItem *item = MenuNameToItem(menuRef); + + if(item) XtSetSensitive(item->handle, state); +} + +void +EnableButtonBar (int state) +{ + XtSetSensitive(optList[W_BUTTON].handle, state); +} + + +void +SetMenuEnables (Enables *enab) +{ + while (enab->name != NULL) { + EnableNamedMenuItem(enab->name, enab->value); + enab++; + } +} + +void +KeyBindingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // [HGM] new method of key binding: specify MenuItem(FlipView) in stead of FlipViewProc in translation string + MenuItem *item; + if(*nprms == 0) return; + item = MenuNameToItem(prms[0]); + if(item) ((MenuProc *) item->proc) (); +} + +static void +MenuEngineSelect (Widget w, caddr_t addr, caddr_t index) +{ + RecentEngineEvent((int) (intptr_t) addr); +} + +void +AppendMenuItem (char *msg, int n) +{ + CreateMenuItem((Widget) optList[W_ENGIN].textValue, msg, (XtCallbackProc) MenuEngineSelect, n); +} + +void +SetupDropMenu () +{ + int i, j, count; + char label[32]; + Arg args[16]; + Widget entry; + char* p; + + for (i=0; i 1.) f = 1.; else if(f < 0.) f = 0.; + return f; +} + +static WindowPlacement wpNew; + +void +CoDrag (Widget sh, WindowPlacement *wp) +{ + Arg args[16]; + int j=0, touch=0, fudge = 2; + GetActualPlacement(sh, wp); + if(abs(wpMain.x + wpMain.width + 2*frameX - wp->x) < fudge) touch = 1; else // right touch + if(abs(wp->x + wp->width + 2*frameX - wpMain.x) < fudge) touch = 2; else // left touch + if(abs(wpMain.y + wpMain.height + frameX + frameY - wp->y) < fudge) touch = 3; else // bottom touch + if(abs(wp->y + wp->height + frameX + frameY - wpMain.y) < fudge) touch = 4; // top touch + if(!touch ) return; // only windows that touch co-move + if(touch < 3 && wpNew.height != wpMain.height) { // left or right and height changed + int heightInc = wpNew.height - wpMain.height; + double fracTop = Fraction(wp->y, wpMain.y, wpMain.y + wpMain.height + frameX + frameY); + double fracBot = Fraction(wp->y + wp->height + frameX + frameY + 1, wpMain.y, wpMain.y + wpMain.height + frameX + frameY); + wp->y += fracTop * heightInc; + heightInc = (int) (fracBot * heightInc) - (int) (fracTop * heightInc); + if(heightInc) XtSetArg(args[j], XtNheight, wp->height + heightInc), j++; + } else if(touch > 2 && wpNew.width != wpMain.width) { // top or bottom and width changed + int widthInc = wpNew.width - wpMain.width; + double fracLeft = Fraction(wp->x, wpMain.x, wpMain.x + wpMain.width + 2*frameX); + double fracRght = Fraction(wp->x + wp->width + 2*frameX + 1, wpMain.x, wpMain.x + wpMain.width + 2*frameX); + wp->y += fracLeft * widthInc; + widthInc = (int) (fracRght * widthInc) - (int) (fracLeft * widthInc); + if(widthInc) XtSetArg(args[j], XtNwidth, wp->width + widthInc), j++; + } + wp->x += wpNew.x - wpMain.x; + wp->y += wpNew.y - wpMain.y; + if(touch == 1) wp->x += wpNew.width - wpMain.width; else + if(touch == 3) wp->y += wpNew.height - wpMain.height; + XtSetArg(args[j], XtNx, wp->x); j++; + XtSetArg(args[j], XtNy, wp->y); j++; + XtSetValues(sh, args, j); +} + +void +ReSize (WindowPlacement *wp) +{ + int sqx, sqy, w, h; + if(wp->width == wpMain.width && wp->height == wpMain.height) return; // not sized + sqx = (wp->width - lineGap - marginW) / BOARD_WIDTH - lineGap; + sqy = (wp->height - lineGap - marginH) / BOARD_HEIGHT - lineGap; + if(sqy < sqx) sqx = sqy; + if(sqx != squareSize) { + squareSize = sqx; // adopt new square size + CreatePNGPieces(); // make newly scaled pieces + InitDrawingSizes(0, 0); // creates grid etc. + } else ResizeBoardWindow(BOARD_WIDTH * (squareSize + lineGap) + lineGap, BOARD_HEIGHT * (squareSize + lineGap) + lineGap, 0); + w = BOARD_WIDTH * (squareSize + lineGap) + lineGap; + h = BOARD_HEIGHT * (squareSize + lineGap) + lineGap; + if(optList[W_BOARD].max > w) optList[W_BOARD].max = w; + if(optList[W_BOARD].value > h) optList[W_BOARD].value = h; +} + +static XtIntervalId delayedDragID = 0; + +void +DragProc () +{ + static int busy; + if(busy) return; + + busy = 1; + GetActualPlacement(shellWidget, &wpNew); + if(wpNew.x == wpMain.x && wpNew.y == wpMain.y && // not moved + wpNew.width == wpMain.width && wpNew.height == wpMain.height) { // not sized + busy = 0; return; // false alarm + } + ReSize(&wpNew); + if(shellUp[EngOutDlg]) CoDrag(shells[EngOutDlg], &wpEngineOutput); + if(shellUp[HistoryDlg]) CoDrag(shells[HistoryDlg], &wpMoveHistory); + if(shellUp[EvalGraphDlg]) CoDrag(shells[EvalGraphDlg], &wpEvalGraph); + if(shellUp[GameListDlg]) CoDrag(shells[GameListDlg], &wpGameList); + wpMain = wpNew; + DrawPosition(True, NULL); + delayedDragID = 0; // now drag executed, make sure next DelayedDrag will not cancel timer event (which could now be used by other) + busy = 0; +} + + +void +DelayedDrag () +{ + if(delayedDragID) XtRemoveTimeOut(delayedDragID); // cancel pending + delayedDragID = + XtAppAddTimeOut(appContext, 200, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later +} + +void +EventProc (Widget widget, caddr_t unused, XEvent *event) +{ + if(XtIsRealized(widget) && event->type == ConfigureNotify || appData.useStickyWindows) + DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other +} + +/* + * event handler for redrawing the board + */ +void +DrawPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + DrawPosition(True, NULL); +} + + +void +HandlePV (Widget w, XEvent * event, String * params, Cardinal * nParams) +{ // [HGM] pv: walk PV + MovePV(event->xmotion.x, event->xmotion.y, lineGap + BOARD_HEIGHT * (squareSize + lineGap)); +} + +static int savedIndex; /* gross that this is global */ + +void +CommentClick (Widget w, XEvent * event, String * params, Cardinal * nParams) +{ + String val; + XawTextPosition index, dummy; + Arg arg; + + XawTextGetSelectionPos(w, &index, &dummy); + XtSetArg(arg, XtNstring, &val); + XtGetValues(w, &arg, 1); + ReplaceComment(savedIndex, val); + if(savedIndex != currentMove) ToNrEvent(savedIndex); + LoadVariation( index, val ); // [HGM] also does the actual moving to it, now +} + +void +EditCommentPopUp (int index, char *title, char *text) +{ + savedIndex = index; + if (text == NULL) text = ""; + NewCommentPopup(title, text, index); +} + +void +CommentPopUp (char *title, char *text) +{ + savedIndex = currentMove; // [HGM] vari + NewCommentPopup(title, text, currentMove); +} + +void +CommentPopDown () +{ + PopDown(CommentDlg); +} + + +/* Disable all user input other than deleting the window */ +static int frozen = 0; + +void +FreezeUI () +{ + if (frozen) return; + /* Grab by a widget that doesn't accept input */ + XtAddGrab(optList[W_MESSG].handle, TRUE, FALSE); + frozen = 1; +} + +/* Undo a FreezeUI */ +void +ThawUI () +{ + if (!frozen) return; + XtRemoveGrab(optList[W_MESSG].handle); + frozen = 0; +} + +void +ModeHighlight () +{ + Arg args[16]; + static int oldPausing = FALSE; + static GameMode oldmode = (GameMode) -1; + char *wname; + + if (!boardWidget || !XtIsRealized(boardWidget)) return; + + if (pausing != oldPausing) { + oldPausing = pausing; + MarkMenuItem("Mode.Pause", pausing); + + if (appData.showButtonBar) { + /* Always toggle, don't set. Previous code messes up when + invoked while the button is pressed, as releasing it + toggles the state again. */ + { + Pixel oldbg, oldfg; + XtSetArg(args[0], XtNbackground, &oldbg); + XtSetArg(args[1], XtNforeground, &oldfg); + XtGetValues(optList[W_PAUSE].handle, + args, 2); + XtSetArg(args[0], XtNbackground, oldfg); + XtSetArg(args[1], XtNforeground, oldbg); + } + XtSetValues(optList[W_PAUSE].handle, args, 2); + } + } + + wname = ModeToWidgetName(oldmode); + if (wname != NULL) { + MarkMenuItem(wname, False); + } + wname = ModeToWidgetName(gameMode); + if (wname != NULL) { + MarkMenuItem(wname, True); + } + oldmode = gameMode; + MarkMenuItem("Mode.MachineMatch", matchMode && matchGame < appData.matchGames); + + /* Maybe all the enables should be handled here, not just this one */ + EnableNamedMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile); + + DisplayLogos(&optList[W_WHITE-1], &optList[W_BLACK+1]); +} + + +/* + * Button/menu procedures + */ + +/* this variable is shared between CopyPositionProc and SendPositionSelection */ +char *selected_fen_position=NULL; + +Boolean +SendPositionSelection (Widget w, Atom *selection, Atom *target, + Atom *type_return, XtPointer *value_return, + unsigned long *length_return, int *format_return) +{ + char *selection_tmp; + +// if (!selected_fen_position) return False; /* should never happen */ + if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){ + if (!selected_fen_position) { // since it never happens, we use it for indicating a game is being sent + FILE* f = fopen(gameCopyFilename, "r"); // This code, taken from SendGameSelection, now merges the two + long len; + size_t count; + if (f == NULL) return False; + fseek(f, 0, 2); + len = ftell(f); + rewind(f); + selection_tmp = XtMalloc(len + 1); + count = fread(selection_tmp, 1, len, f); + fclose(f); + if (len != count) { + XtFree(selection_tmp); + return False; + } + selection_tmp[len] = NULLCHAR; + } else { + /* note: since no XtSelectionDoneProc was registered, Xt will + * automatically call XtFree on the value returned. So have to + * make a copy of it allocated with XtMalloc */ + selection_tmp= XtMalloc(strlen(selected_fen_position)+16); + safeStrCpy(selection_tmp, selected_fen_position, strlen(selected_fen_position)+16 ); + } + + *value_return=selection_tmp; + *length_return=strlen(selection_tmp); + *type_return=*target; + *format_return = 8; /* bits per byte */ + return True; + } else if (*target == XA_TARGETS(xDisplay)) { + Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom)); + targets_tmp[0] = XA_UTF8_STRING(xDisplay); + targets_tmp[1] = XA_STRING; + *value_return = targets_tmp; + *type_return = XA_ATOM; + *length_return = 2; +#if 0 + // This code leads to a read of value_return out of bounds on 64-bit systems. + // Other code which I have seen always sets *format_return to 32 independent of + // sizeof(Atom) without adjusting *length_return. For instance see TextConvertSelection() + // at http://cgit.freedesktop.org/xorg/lib/libXaw/tree/src/Text.c -- BJ + *format_return = 8 * sizeof(Atom); + if (*format_return > 32) { + *length_return *= *format_return / 32; + *format_return = 32; + } +#else + *format_return = 32; +#endif + return True; + } else { + return False; + } +} + +/* note: when called from menu all parameters are NULL, so no clue what the + * Widget which was clicked on was, or what the click event was + */ +void +CopySomething (char *src) +{ + selected_fen_position = src; + /* + * Set both PRIMARY (the selection) and CLIPBOARD, since we don't + * have a notion of a position that is selected but not copied. + * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki + */ + XtOwnSelection(menuBarWidget, XA_PRIMARY, + CurrentTime, + SendPositionSelection, + NULL/* lose_ownership_proc */ , + NULL/* transfer_done_proc */); + XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay), + CurrentTime, + SendPositionSelection, + NULL/* lose_ownership_proc */ , + NULL/* transfer_done_proc */); +} + +/* function called when the data to Paste is ready */ +static void +PastePositionCB (Widget w, XtPointer client_data, Atom *selection, + Atom *type, XtPointer value, unsigned long *len, int *format) +{ + char *fenstr=value; + if (value==NULL || *len==0) return; /* nothing had been selected to copy */ + fenstr[*len]='\0'; /* normally this string is terminated, but be safe */ + EditPositionPasteFEN(fenstr); + XtFree(value); +} + +/* called when Paste Position button is pressed, + * all parameters will be NULL */ +void +PastePositionProc () +{ + XtGetSelectionValue(menuBarWidget, + appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING, + /* (XtSelectionCallbackProc) */ PastePositionCB, + NULL, /* client_data passed to PastePositionCB */ + + /* better to use the time field from the event that triggered the + * call to this function, but that isn't trivial to get + */ + CurrentTime + ); + return; +} + +/* note: when called from menu all parameters are NULL, so no clue what the + * Widget which was clicked on was, or what the click event was + */ +/* function called when the data to Paste is ready */ +static void +PasteGameCB (Widget w, XtPointer client_data, Atom *selection, + Atom *type, XtPointer value, unsigned long *len, int *format) +{ + FILE* f; + if (value == NULL || *len == 0) { + return; /* nothing had been selected to copy */ + } + f = fopen(gamePasteFilename, "w"); + if (f == NULL) { + DisplayError(_("Can't open temp file"), errno); + return; + } + fwrite(value, 1, *len, f); + fclose(f); + XtFree(value); + LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE); +} + +/* called when Paste Game button is pressed, + * all parameters will be NULL */ +void +PasteGameProc () +{ + XtGetSelectionValue(menuBarWidget, + appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING, + /* (XtSelectionCallbackProc) */ PasteGameCB, + NULL, /* client_data passed to PasteGameCB */ + + /* better to use the time field from the event that triggered the + * call to this function, but that isn't trivial to get + */ + CurrentTime + ); + return; +} + + +void +QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + QuitProc(); +} + +int +ShiftKeys () +{ // bassic primitive for determining if modifier keys are pressed + long int codes[] = { XK_Meta_L, XK_Meta_R, XK_Control_L, XK_Control_R, XK_Shift_L, XK_Shift_R }; + char keys[32]; + int i,j, k=0; + XQueryKeymap(xDisplay,keys); + for(i=0; i<6; i++) { + k <<= 1; + j = XKeysymToKeycode(xDisplay, codes[i]); + k += ( (keys[j>>3]&1<<(j&7)) != 0 ); + } + return k; +} + +static void +MoveTypeInProc (Widget widget, caddr_t unused, XEvent *event) +{ + char buf[10]; + KeySym sym; + int n = XLookupString(&(event->xkey), buf, 10, &sym, NULL); + if ( n == 1 && *buf >= 32 // printable + && !(ShiftKeys() & 0x3C) // no Alt, Ctrl + ) BoxAutoPopUp (buf); +} + +static void +UpKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // [HGM] input: let up-arrow recall previous line from history + IcsKey(1); +} + +static void +DownKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // [HGM] input: let down-arrow recall next line from history + IcsKey(-1); +} + +static void +EnterKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + IcsKey(0); +} + +void +TempBackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + if (!TempBackwardActive) { + TempBackwardActive = True; + BackwardEvent(); + } +} + +void +TempForwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + /* Check to see if triggered by a key release event for a repeating key. + * If so the next queued event will be a key press of the same key at the same time */ + if (XEventsQueued(xDisplay, QueuedAfterReading)) { + XEvent next; + XPeekEvent(xDisplay, &next); + if (next.type == KeyPress && next.xkey.time == event->xkey.time && + next.xkey.keycode == event->xkey.keycode) + return; + } + ForwardEvent(); + TempBackwardActive = False; +} + +void +ManInner (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // called as key binding + char buf[MSG_SIZ]; + String name; + if (nprms && *nprms > 0) + name = prms[0]; + else + name = "xboard"; + snprintf(buf, sizeof(buf), "xterm -e man %s &", name); + system(buf); +} + +void +ManProc () +{ // called from menu + ManInner(NULL, NULL, NULL, NULL); +} + +void +SetWindowTitle (char *text, char *title, char *icon) +{ + Arg args[16]; + int i; + if (appData.titleInWindow) { + i = 0; + XtSetArg(args[i], XtNlabel, text); i++; + XtSetValues(titleWidget, args, i); + } + i = 0; + XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++; + XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++; + XtSetValues(shellWidget, args, i); + XSync(xDisplay, False); +} + + +static int +NullXErrorCheck (Display *dpy, XErrorEvent *error_event) +{ + return 0; +} + +void +DisplayIcsInteractionTitle (String message) +{ + if (oldICSInteractionTitle == NULL) { + /* Magic to find the old window title, adapted from vim */ + char *wina = getenv("WINDOWID"); + if (wina != NULL) { + Window win = (Window) atoi(wina); + Window root, parent, *children; + unsigned int nchildren; + int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck); + for (;;) { + if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break; + if (!XQueryTree(xDisplay, win, &root, &parent, + &children, &nchildren)) break; + if (children) XFree((void *)children); + if (parent == root || parent == 0) break; + win = parent; + } + XSetErrorHandler(oldHandler); + } + if (oldICSInteractionTitle == NULL) { + oldICSInteractionTitle = "xterm"; + } + } + printf("\033]0;%s\007", message); + fflush(stdout); +} + + +XtIntervalId delayedEventTimerXID = 0; +DelayedEventCallback delayedEventCallback = 0; + +void +FireDelayedEvent () +{ + delayedEventTimerXID = 0; + delayedEventCallback(); +} + +void +ScheduleDelayedEvent (DelayedEventCallback cb, long millisec) +{ + if(delayedEventTimerXID && delayedEventCallback == cb) + // [HGM] alive: replace, rather than add or flush identical event + XtRemoveTimeOut(delayedEventTimerXID); + delayedEventCallback = cb; + delayedEventTimerXID = + XtAppAddTimeOut(appContext, millisec, + (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0); +} + +DelayedEventCallback +GetDelayedEvent () +{ + if (delayedEventTimerXID) { + return delayedEventCallback; + } else { + return NULL; + } +} + +void +CancelDelayedEvent () +{ + if (delayedEventTimerXID) { + XtRemoveTimeOut(delayedEventTimerXID); + delayedEventTimerXID = 0; + } +} + +XtIntervalId loadGameTimerXID = 0; + +int +LoadGameTimerRunning () +{ + return loadGameTimerXID != 0; +} + +int +StopLoadGameTimer () +{ + if (loadGameTimerXID != 0) { + XtRemoveTimeOut(loadGameTimerXID); + loadGameTimerXID = 0; + return TRUE; + } else { + return FALSE; + } +} + +void +LoadGameTimerCallback (XtPointer arg, XtIntervalId *id) +{ + loadGameTimerXID = 0; + AutoPlayGameLoop(); +} + +void +StartLoadGameTimer (long millisec) +{ + loadGameTimerXID = + XtAppAddTimeOut(appContext, millisec, + (XtTimerCallbackProc) LoadGameTimerCallback, + (XtPointer) 0); +} + +XtIntervalId analysisClockXID = 0; + +void +AnalysisClockCallback (XtPointer arg, XtIntervalId *id) +{ + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile + || appData.icsEngineAnalyze) { // [DM] + AnalysisPeriodicEvent(0); + StartAnalysisClock(); + } +} + +void +StartAnalysisClock () +{ + analysisClockXID = + XtAppAddTimeOut(appContext, 2000, + (XtTimerCallbackProc) AnalysisClockCallback, + (XtPointer) 0); +} + +XtIntervalId clockTimerXID = 0; + +int +ClockTimerRunning () +{ + return clockTimerXID != 0; +} + +int +StopClockTimer () +{ + if (clockTimerXID != 0) { + XtRemoveTimeOut(clockTimerXID); + clockTimerXID = 0; + return TRUE; + } else { + return FALSE; + } +} + +void +ClockTimerCallback (XtPointer arg, XtIntervalId *id) +{ + clockTimerXID = 0; + DecrementClocks(); +} + +void +StartClockTimer (long millisec) +{ + clockTimerXID = + XtAppAddTimeOut(appContext, millisec, + (XtTimerCallbackProc) ClockTimerCallback, + (XtPointer) 0); +} + +void +DisplayTimerLabel (Option *opt, char *color, long timer, int highlight) +{ + char buf[MSG_SIZ]; + Arg args[16]; + Widget w = (Widget) opt->handle; + + /* check for low time warning */ + Pixel foregroundOrWarningColor = timerForegroundPixel; + + if (timer > 0 && + appData.lowTimeWarning && + (timer / 1000) < appData.icsAlarmTime) + foregroundOrWarningColor = lowTimeWarningColor; + + if (appData.clockMode) { + snprintf(buf, MSG_SIZ, "%s:%s%s", color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer)); + XtSetArg(args[0], XtNlabel, buf); + } else { + snprintf(buf, MSG_SIZ, "%s ", color); + XtSetArg(args[0], XtNlabel, buf); + } + + if (highlight) { + + XtSetArg(args[1], XtNbackground, foregroundOrWarningColor); + XtSetArg(args[2], XtNforeground, timerBackgroundPixel); + } else { + XtSetArg(args[1], XtNbackground, timerBackgroundPixel); + XtSetArg(args[2], XtNforeground, foregroundOrWarningColor); + } + + XtSetValues(w, args, 3); +} + +static Pixmap *clockIcons[] = { &wIconPixmap, &bIconPixmap }; + +void +SetClockIcon (int color) +{ + Arg args[16]; + Pixmap pm = *clockIcons[color]; + if (iconPixmap != pm) { + iconPixmap = pm; + XtSetArg(args[0], XtNiconPixmap, iconPixmap); + XtSetValues(shellWidget, args, 1); + } +} + +void +DoInputCallback (caddr_t closure, int *source, XtInputId *xid) +{ + InputSource *is = (InputSource *) closure; + int count; + int error; + char *p, *q; + + if (is->lineByLine) { + count = read(is->fd, is->unused, + INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf)); + if (count <= 0) { + (is->func)(is, is->closure, is->buf, count, count ? errno : 0); + return; + } + is->unused += count; + p = is->buf; + while (p < is->unused) { + q = memchr(p, '\n', is->unused - p); + if (q == NULL) break; + q++; + (is->func)(is, is->closure, p, q - p, 0); + p = q; + } + q = is->buf; + while (p < is->unused) { + *q++ = *p++; + } + is->unused = q; + } else { + count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE); + if (count == -1) + error = errno; + else + error = 0; + (is->func)(is, is->closure, is->buf, count, error); + } +} + +InputSourceRef +AddInputSource (ProcRef pr, int lineByLine, InputCallback func, VOIDSTAR closure) +{ + InputSource *is; + ChildProc *cp = (ChildProc *) pr; + + is = (InputSource *) calloc(1, sizeof(InputSource)); + is->lineByLine = lineByLine; + is->func = func; + if (pr == NoProc) { + is->kind = CPReal; + is->fd = fileno(stdin); + } else { + is->kind = cp->kind; + is->fd = cp->fdFrom; + } + if (lineByLine) { + is->unused = is->buf; + } + + is->xid = XtAppAddInput(appContext, is->fd, + (XtPointer) (XtInputReadMask), + (XtInputCallbackProc) DoInputCallback, + (XtPointer) is); + is->closure = closure; + return (InputSourceRef) is; +} + +void +RemoveInputSource (InputSourceRef isr) +{ + InputSource *is = (InputSource *) isr; + + if (is->xid == 0) return; + XtRemoveInput(is->xid); + is->xid = 0; +} + +#ifndef HAVE_USLEEP + +static Boolean frameWaiting; + +static RETSIGTYPE +FrameAlarm (int sig) +{ + frameWaiting = False; + /* In case System-V style signals. Needed?? */ + signal(SIGALRM, FrameAlarm); +} + +void +FrameDelay (int time) +{ + struct itimerval delay; + + XSync(xDisplay, False); + + if (time > 0) { + frameWaiting = True; + signal(SIGALRM, FrameAlarm); + delay.it_interval.tv_sec = + delay.it_value.tv_sec = time / 1000; + delay.it_interval.tv_usec = + delay.it_value.tv_usec = (time % 1000) * 1000; + setitimer(ITIMER_REAL, &delay, NULL); + while (frameWaiting) pause(); + delay.it_interval.tv_sec = delay.it_value.tv_sec = 0; + delay.it_interval.tv_usec = delay.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &delay, NULL); + } +} + +#else + +void +FrameDelay (int time) +{ + XSync(xDisplay, False); + if (time > 0) + usleep(time * 1000); +} + +#endif + +static void +LoadLogo (ChessProgramState *cps, int n, Boolean ics) +{ + char buf[MSG_SIZ], *logoName = buf; + if(appData.logo[n][0]) { + logoName = appData.logo[n]; + } else if(appData.autoLogo) { + if(ics) { // [HGM] logo: in ICS mode second can be used for ICS + sprintf(buf, "%s/%s.png", appData.logoDir, appData.icsHost); + } else if(appData.directory[n] && appData.directory[n][0]) { + sprintf(buf, "%s/%s.png", appData.logoDir, cps->tidy); + } + } + if(logoName[0]) + { ASSIGN(cps->programLogo, logoName); } +} + +void +UpdateLogos (int displ) +{ + if(optList[W_WHITE-1].handle == NULL) return; + LoadLogo(&first, 0, 0); + LoadLogo(&second, 1, appData.icsActive); + if(displ) DisplayLogos(&optList[W_WHITE-1], &optList[W_BLACK+1]); + return; +} + diff --git a/xaw/xboard.h b/xaw/xboard.h new file mode 100644 index 0000000..5a6587e --- /dev/null +++ b/xaw/xboard.h @@ -0,0 +1,176 @@ +/* + * xboard.h -- Parameter definitions for X front end + * + * Copyright 1991 by Digital Equipment Corporation, Maynard, + * Massachusetts. + * + * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, + * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * + * The following terms apply to Digital Equipment Corporation's copyright + * interest in XBoard: + * ------------------------------------------------------------------------ + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * ------------------------------------------------------------------------ + * + * The following terms apply to the enhanced version of XBoard + * distributed by the Free Software Foundation: + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#include + +#define ICS_LOGON ".icsrc" +#define MANPAGE "xboard.6" +#if ENABLE_NLS +#define CLOCK_FONT_NAME \ + "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*," \ + "-misc-fixed-bold-r-normal--*-*-*-*-*-*-*-*," \ + "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" +#define COORD_FONT_NAME \ + "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*," \ + "-misc-fixed-bold-r-normal--*-*-*-*-*-*-*-*," \ + "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" +#define DEFAULT_FONT_NAME \ + "-*-helvetica-medium-r-normal--*-*-*-*-*-*-*-*," \ + "-misc-fixed-medium-r-normal--*-*-*-*-*-*-*-*," \ + "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" +#else +#define CLOCK_FONT_NAME "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*" +#define COORD_FONT_NAME "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*" +#define DEFAULT_FONT_NAME "-*-helvetica-medium-r-normal--*-*-*-*-*-*-*-*" +#endif +#define COLOR_SHOUT "green" +#define COLOR_SSHOUT "green,black,1" +#define COLOR_CHANNEL1 "cyan" +#define COLOR_CHANNEL "cyan,black,1" +#define COLOR_KIBITZ "magenta,black,1" +#define COLOR_TELL "yellow,black,1" +#define COLOR_CHALLENGE "red,black,1" +#define COLOR_REQUEST "red" +#define COLOR_SEEK "blue" +#define COLOR_NORMAL "default" +#define COLOR_LOWTIMEWARNING "red" + +typedef struct { + char *name; + int squareSize; + int lineGap; + int clockFontPxlSize; + int coordFontPxlSize; + int fontPxlSize; + int smallLayout; + int tinyLayout; + int minScreenSize; +} SizeDefaults; + +#define SIZE_DEFAULTS \ +{ { "Titanic", 129, 4, 34, 14, 14, 0, 0, 1200 }, \ + { "Colossal", 116, 4, 34, 14, 14, 0, 0, 1200 }, \ + { "Giant", 108, 3, 34, 14, 14, 0, 0, 1024 }, \ + { "Huge", 95, 3, 34, 14, 14, 0, 0, 1024 }, \ + { "Big", 87, 3, 34, 14, 14, 0, 0, 864 }, \ + { "Large", 80, 3, 34, 14, 14, 0, 0, 864 }, \ + { "Bulky", 72, 3, 34, 12, 14, 0, 0, 864 }, \ + { "Medium", 64, 3, 34, 12, 14, 1, 0, 768 }, \ + { "Moderate", 58, 3, 34, 12, 14, 1, 0, 768 }, \ + { "Average", 54, 2, 30, 11, 12, 1, 0, 600 }, \ + { "Middling", 49, 2, 24, 10, 12, 1, 0, 600 }, \ + { "Mediocre", 45, 2, 20, 10, 12, 1, 0, 600 }, \ + { "Small", 40, 2, 20, 10, 12, 1, 0, 480 }, \ + { "Slim", 37, 2, 20, 10, 12, 1, 0, 480 }, \ + { "Petite", 33, 1, 15, 9, 11, 1, 0, 480 }, \ + { "Dinky", 29, 1, 15, 9, 11, 1, 0, 480 }, \ + { "Teeny", 25, 1, 12, 8, 11, 1, 1, 480 }, \ + { "Tiny", 21, 1, 12, 8, 11, 1, 1, 0 }, \ + { NULL, 0, 0, 0, 0, 0, 0, 0, 0 } } + +#define BORDER_X_OFFSET 3 +#define BORDER_Y_OFFSET 27 +#define FIRST_CHESS_PROGRAM "fairymax" +#define SECOND_CHESS_PROGRAM "fairymax" +#define FIRST_DIRECTORY "." +#define SECOND_DIRECTORY "." +#define SOUND_BELL "" +#define ICS_NAMES "" +#define FCP_NAMES "" +#define SCP_NAMES "" +#define ICS_TEXT_MENU_DEFAULT "" +#define SETTINGS_FILE SYSCONFDIR"/xboard.conf" +#define COLOR_BKGD "white" + +void NewTagsPopup P((char *text, char *msg)); +int AppendText P((Option *opt, char *s)); +void NewCommentPopup P((char *title, char *text, int index)); +void CatchDeleteWindow(Widget w, String procname); +void GenericPopDown P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void InitDrawingSizes P((int i, int j)); +void SendToICS P((char *buf)); +void SendToProgram P((char *message, ChessProgramState *cps)); +void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b); // from xoptions.c +void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +Widget CreateMenuItem P((Widget menu, char *msg, XtCallbackProc CB, int n)); +void WheelProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void TabProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void GenericMenu P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); + +// from xengineoutput.c +void SelectPV P((Widget w, XEvent * event, String * params, Cardinal * nParams)); +void StopPV P((Widget w, XEvent * event, String * params, Cardinal * nParams)); + +extern char memoTranslations[]; + + +extern Widget shells[]; +extern int dialogError; +extern Widget formWidget, shellWidget, boardWidget, menuBarWidget; +extern Display *xDisplay; +extern Window xBoardWindow; +extern int squareSize; +extern Pixmap xMarkPixmap, wIconPixmap, bIconPixmap; +extern char *layoutName; +extern Pixel timerForegroundPixel, timerBackgroundPixel, dialogColor, buttonColor; +extern int searchTime; +extern Atom wm_delete_window; +extern int squareSize, lineGap, defaultLineGap, useImages, useImageSqs; +extern int startedFromPositionFile; +extern char *icsTextMenuString; +extern char ICSInputTranslations[]; +extern char *selected_fen_position; +extern GC coordGC; +extern Dimension textHeight; // of message widget in board window + + +#define TOPLEVEL 1 /* preference item; 1 = make popup windows toplevel */ + diff --git a/xaw/xedittags.c b/xaw/xedittags.c new file mode 100644 index 0000000..d27aca3 --- /dev/null +++ b/xaw/xedittags.c @@ -0,0 +1,121 @@ +/* + * xedittags.c -- Tags edit window, part of X front end for XBoard + * + * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#include "config.h" + +#include +#include +#include +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +extern char *getenv(); +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#if USE_XAW3D +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "common.h" +#include "frontend.h" +#include "backend.h" +#include "xboard.h" +#include "xedittags.h" +#include "dialogs.h" +#include "gettext.h" + +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif + +Position tagsX = -1, tagsY = -1; + +void +TagsPopUp (char *tags, char *msg) +{ + NewTagsPopup(tags, cmailMsgLoaded ? msg : NULL); +} + + +void +EditTagsPopUp (char *tags, char **dest) +{ + NewTagsPopup(tags, NULL); +} + +void +TagsPopDown() +{ + PopDown(TagsDlg); + bookUp = False; +} + +void +EditTagsProc () +{ + if (bookUp || !PopDown(TagsDlg)) EditTagsEvent(); +} diff --git a/xaw/xedittags.h b/xaw/xedittags.h new file mode 100644 index 0000000..6245bfd --- /dev/null +++ b/xaw/xedittags.h @@ -0,0 +1,30 @@ +/* + * xedittags.h + * + * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#ifndef XB_XEDITTAGS +#define XB_XEDITTAGS + +void EditTagsProc P((void)); + +extern Widget editTagsShell, tagsShell; +#endif diff --git a/xaw/xengineoutput.c b/xaw/xengineoutput.c new file mode 100644 index 0000000..78269b8 --- /dev/null +++ b/xaw/xengineoutput.c @@ -0,0 +1,286 @@ +/* + * Engine output (PV) + * + * Author: Alessandro Scotti (Dec 2005) + * + * Copyright 2005 Alessandro Scotti + * + * Enhancements Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + * ------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#include "config.h" + +#include +#include +#include +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +extern char *getenv(); +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "frontend.h" +#include "backend.h" +#include "dialogs.h" +#include "xboard.h" +#include "engineoutput.h" +#include "gettext.h" + +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif + +#include + +// [HGM] pixmaps of some ICONS used in the engine-outut window +#include "pixmaps/WHITE_14.xpm" +#include "pixmaps/BLACK_14.xpm" +#include "pixmaps/CLEAR_14.xpm" +#include "pixmaps/UNKNOWN_14.xpm" +#include "pixmaps/THINKING_14.xpm" +#include "pixmaps/PONDER_14.xpm" +#include "pixmaps/ANALYZING_14.xpm" + + +/* Module variables */ +static int currentPV, highTextStart[2], highTextEnd[2]; +static Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle +static Widget memoWidget; + + +static void +ReadIcon (char *pixData[], int iconNr, Widget w) +{ + int r; + + if ((r=XpmCreatePixmapFromData(xDisplay, XtWindow(w), + pixData, + &(icons[iconNr]), + NULL, NULL /*&attr*/)) != 0) { + fprintf(stderr, _("Error %d loading icon image\n"), r); + exit(1); + } +} + +void +InitEngineOutput (Option *opt, Option *memo2) +{ // front-end, because it must have access to the pixmaps + Widget w = opt->handle; + memoWidget = memo2->handle; + + ReadIcon(WHITE_14, nColorWhite, w); + ReadIcon(BLACK_14, nColorBlack, w); + ReadIcon(UNKNOWN_14, nColorUnknown, w); + + ReadIcon(CLEAR_14, nClear, w); + ReadIcon(PONDER_14, nPondering, w); + ReadIcon(THINK_14, nThinking, w); + ReadIcon(ANALYZE_14, nAnalyzing, w); +} + +void +DrawWidgetIcon (Option *opt, int nIcon) +{ // as we are already in X front-end, so do X-stuff here + Arg arg; + XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]); + XtSetValues(opt->handle, &arg, 1); +} + +void +InsertIntoMemo (int which, char * text, int where) +{ + XawTextBlock t; + Widget edit; + + /* the backend adds \r\n, which is needed for winboard, + * for xboard we delete them again over here */ + if(t.ptr = strchr(text, '\r')) *t.ptr = ' '; + + t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit; + edit = XtNameToWidget(shells[EngOutDlg], which ? "*paneB.text" : "*paneA.text"); + XawTextReplace(edit, where, where, &t); + if(where < highTextStart[which]) { // [HGM] multiPVdisplay: move highlighting + int len = strlen(text); + highTextStart[which] += len; highTextEnd[which] += len; + XawTextSetSelection( edit, highTextStart[which], highTextEnd[which] ); + } +} + +//--------------------------------- PV walking --------------------------------------- + +char memoTranslations[] = +":Ctrlc: CopyMemoProc() \n \ +: HandlePV() \n \ +Shift: select-start() extend-end() SelectPV(1) \n \ +Any: select-start() extend-end() SelectPV(0) \n \ +: StopPV() \n"; + +void +SelectPV (Widget w, XEvent * event, String * params, Cardinal * nParams) +{ // [HGM] pv: translate click to PV line, and load it for display + String val; + int start, end; + XawTextPosition index, dummy; + int x, y; + Arg arg; + + x = event->xmotion.x; y = event->xmotion.y; + currentPV = (w != memoWidget); + XawTextGetSelectionPos(w, &index, &dummy); + XtSetArg(arg, XtNstring, &val); + XtGetValues(w, &arg, 1); + shiftKey = strcmp(params[0], "0"); + if(LoadMultiPV(x, y, val, index, &start, &end, currentPV)) { + XawTextSetSelection( w, start, end ); + highTextStart[currentPV] = start; highTextEnd[currentPV] = end; + } +} + +void +StopPV (Widget w, XEvent * event, String * params, Cardinal * nParams) +{ // [HGM] pv: on right-button release, stop displaying PV + XawTextUnsetSelection( w ); + highTextStart[currentPV] = highTextEnd[currentPV] = 0; + UnLoadPV(); + XtCallActionProc(w, "beginning-of-file", event, NULL, 0); +} + +//------------------------- Ctrl-C copying of memo texts --------------------------- + +// Awfull code: first read our own primary selection into selected_fen_position, +// and then transfer ownership of this to the clipboard, so that the +// copy-position callback can fetch it there when somebody pastes it +// Worst of all is that I only added it because I did not know how to copy primary: +// my laptop has no middle button. Ctrl-C might not be needed at all... [HGM] + +// cloned from CopyPositionProc. Abuse selected_fen_position to hold selection + +Boolean SendPositionSelection(Widget w, Atom *selection, Atom *target, + Atom *type_return, XtPointer *value_return, + unsigned long *length_return, int *format_return); // from xboard.c + +static void +MemoCB (Widget w, XtPointer client_data, Atom *selection, + Atom *type, XtPointer value, unsigned long *len, int *format) +{ + if (value==NULL || *len==0) return; /* nothing had been selected to copy */ + selected_fen_position = value; + selected_fen_position[*len]='\0'; /* normally this string is terminated, but be safe */ + XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay), + CurrentTime, + SendPositionSelection, + NULL/* lose_ownership_proc */ , + NULL/* transfer_done_proc */); +} + +void +CopyMemoProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + if(appData.pasteSelection) return; + if (selected_fen_position) free(selected_fen_position); + XtGetSelectionValue(menuBarWidget, + XA_PRIMARY, XA_STRING, + /* (XtSelectionCallbackProc) */ MemoCB, + NULL, /* client_data passed to PastePositionCB */ + + /* better to use the time field from the event that triggered the + * call to this function, but that isn't trivial to get + */ + CurrentTime + ); +} + +//------------------------------- pane switching ----------------------------------- + +void +ResizeWindowControls (int mode) +{ // another hideous kludge: to have only a single pane, we resize the + // second to 5 pixels (which makes it too small to display anything) + Widget form1, form2; + Arg args[16]; + int j; + Dimension ew_height, tmp; + Widget shell = shells[EngOutDlg]; + + form1 = XtNameToWidget(shell, "*paneA"); + form2 = XtNameToWidget(shell, "*paneB"); + + j = 0; + XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++; + XtGetValues(form1, args, j); + j = 0; + XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++; + XtGetValues(form2, args, j); + ew_height += tmp; // total height + + if(mode==0) { + j = 0; + XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++; + XtSetValues(form2, args, j); + j = 0; + XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++; + XtSetValues(form1, args, j); + } else { + j = 0; + XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++; + XtSetValues(form1, args, j); + j = 0; + XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++; + XtSetValues(form2, args, j); + } +} + diff --git a/xaw/xevalgraph.c b/xaw/xevalgraph.c new file mode 100644 index 0000000..f3cac1f --- /dev/null +++ b/xaw/xevalgraph.c @@ -0,0 +1,339 @@ +/* + * Evaluation graph + * + * Author: Alessandro Scotti (Dec 2005) + * Translated to X by H.G.Muller (Nov 2009) + * + * Copyright 2005 Alessandro Scotti + * + * Enhancements Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + * ------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#include "config.h" + +#include +#include +#include +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +extern char *getenv(); +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common.h" +#include "frontend.h" +#include "backend.h" +#include "dialogs.h" +#include "menus.h" +#include "xboard.h" +#include "evalgraph.h" +#include "xevalgraph.h" +#include "draw.h" +#include "gettext.h" + +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif + +#include + +#ifdef SNAP +#include "wsnap.h" +#endif + +#define _LL_ 100 + +Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle +Widget outputField[2][7]; // [HGM] front-end array to translate output field to window handle +static char *title = N_("Evaluation graph"); + +//extern WindowPlacement wpEvalGraph; + +Position evalGraphX = -1, evalGraphY = -1; +Dimension evalGraphW, evalGraphH; + +/* Module variables */ + +char *crWhite = "#FFFFB0"; +char *crBlack = "#AD5D3D"; +Option *disp; + +static Option *EvalCallback P((int button, int x, int y)); + +static void +ChoosePen(cairo_t *cr, int i) +{ + switch(i) { + case PEN_BLACK: + SetPen(cr, 1.0, "#000000", 0); + break; + case PEN_DOTTED: + SetPen(cr, 1.0, "#A0A0A0", 1); + break; + case PEN_BLUEDOTTED: + SetPen(cr, 1.0, "#0000FF", 1); + break; + case PEN_BOLDWHITE: + SetPen(cr, 3.0, crWhite, 0); + break; + case PEN_BOLDBLACK: + SetPen(cr, 3.0, crBlack, 0); + break; + case PEN_BACKGD: + SetPen(cr, 3.0, "#E0E0F0", 0); + break; + } +} + +// [HGM] front-end, added as wrapper to avoid use of LineTo and MoveToEx in other routines (so they can be back-end) +void +DrawSegment (int x, int y, int *lastX, int *lastY, enum PEN penType) +{ + static int curX, curY; + + if(penType != PEN_NONE) { + cairo_t *cr = cairo_create(DRAWABLE(disp)); + cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); + cairo_move_to (cr, curX, curY); + cairo_line_to (cr, x,y); + ChoosePen(cr, penType); + cairo_stroke (cr); + cairo_destroy (cr); + } + + if(lastX != NULL) { *lastX = curX; *lastY = curY; } + curX = x; curY = y; +} + +// front-end wrapper for drawing functions to do rectangles +void +DrawRectangle (int left, int top, int right, int bottom, int side, int style) +{ + cairo_t *cr; + + cr = cairo_create (DRAWABLE(disp)); + cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); + cairo_rectangle (cr, left, top, right-left, bottom-top); + switch(side) + { + case 0: ChoosePen(cr, PEN_BOLDWHITE); break; + case 1: ChoosePen(cr, PEN_BOLDBLACK); break; + case 2: ChoosePen(cr, PEN_BACKGD); break; + } + cairo_fill (cr); + + if(style != FILLED) + { + cairo_rectangle (cr, left, top, right-left-1, bottom-top-1); + ChoosePen(cr, PEN_BLACK); + cairo_stroke (cr); + } + + cairo_destroy(cr); +} + +// front-end wrapper for putting text in graph +void +DrawEvalText (char *buf, int cbBuf, int y) +{ + // the magic constants 8 and 5 should really be derived from the font size somehow + cairo_text_extents_t extents; + cairo_t *cr = cairo_create(DRAWABLE(disp)); + + /* GTK-TODO this has to go into the font-selection */ + cairo_select_font_face (cr, "Sans", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, 12.0); + + + cairo_text_extents (cr, buf, &extents); + + cairo_move_to (cr, MarginX - 2 - 8*cbBuf, y+5); + cairo_text_path (cr, buf); + cairo_set_source_rgb (cr, 0.0, 0.0, 0); + cairo_fill_preserve (cr); + cairo_set_source_rgb (cr, 0, 1.0, 0); + cairo_set_line_width (cr, 0.1); + cairo_stroke (cr); + + /* free memory */ + cairo_destroy (cr); +} + +static int initDone = FALSE; + +static void +InitializeEvalGraph (Option *opt, int w, int h) +{ + if(w == 0) { + Arg args[10]; + XtSetArg(args[0], XtNwidth, &evalGraphW); + XtSetArg(args[1], XtNheight, &evalGraphH); + XtGetValues(opt->handle, args, 2); + nWidthPB = evalGraphW; nHeightPB = evalGraphH; + } else nWidthPB = w, nHeightPB = h; + + initDone = TRUE; +} + +// The following stuff is really back-end (but too little to bother with a separate file) + +static void +EvalClick (int x, int y) +{ + int index = GetMoveIndexFromPoint( x, y ); + + if( index >= 0 && index < currLast ) ToNrEvent( index + 1 ); +} + +static Option graphOptions[] = { +{ 150, 0x9C, 300, NULL, (void*) &EvalCallback, NULL, NULL, Graph , "" }, +{ 0, 2, 0, NULL, NULL, "", NULL, EndMark , "" } +}; + +static void +DisplayEvalGraph () +{ // back-end painting; calls back front-end primitives for lines, rectangles and text + char *t = MakeEvalTitle(_(title)); + nWidthPB = disp->max; nHeightPB = disp->value; + if(t != title && nWidthPB < 340) t = MakeEvalTitle(nWidthPB < 240 ? "" : _("Eval")); + PaintEvalGraph(); + GraphExpose(graphOptions, 0, 0, nWidthPB, nHeightPB); + SetDialogTitle(EvalGraphDlg, t); +} + +static Option * +EvalCallback (int button, int x, int y) +{ + if(!initDone) return NULL; + + switch(button) { + case 10: // expose event + /* Create or recreate paint box if needed */ + if(x != nWidthPB || y != nHeightPB) { + InitializeEvalGraph(&graphOptions[0], x, y); + } + nWidthPB = x; + nHeightPB = y; + DisplayEvalGraph(); + break; + case 1: EvalClick(x, y); // left button + default: break; // other buttons ignored + } + return NULL; // no context menu! +} + +void +EvalGraphPopUp () +{ + if (GenericPopUp(graphOptions, _(title), EvalGraphDlg, BoardWindow, NONMODAL, 1)) { + InitializeEvalGraph(&graphOptions[0], 0, 0); // first time: add callbacks and initialize pens + disp = graphOptions; + } else { + SetDialogTitle(EvalGraphDlg, _(title)); + SetIconName(EvalGraphDlg, _(title)); + } + + MarkMenu("View.EvaluationGraph", EvalGraphDlg); + +// ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output +} + +void +EvalGraphPopDown () +{ + PopDown(EvalGraphDlg); + +// ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output +} + +Boolean +EvalGraphIsUp () +{ + return shellUp[EvalGraphDlg]; +} + +int +EvalGraphDialogExists () +{ + return DialogExists(EvalGraphDlg); +} + +void +EvalGraphProc () +{ + if (!PopDown(EvalGraphDlg)) EvalGraphPopUp(); +} + +// This function is the interface to the back-end. + +void +EvalGraphSet (int first, int last, int current, ChessProgramStats_Move * pvInfo) +{ + /* [AS] Danger! For now we rely on the pvInfo parameter being a static variable! */ + + currFirst = first; + currLast = last; + currCurrent = current; + currPvInfo = pvInfo; + + if( DialogExists(EvalGraphDlg) ) { + DisplayEvalGraph(); + } +} + diff --git a/xaw/xevalgraph.h b/xaw/xevalgraph.h new file mode 100644 index 0000000..e1227c6 --- /dev/null +++ b/xaw/xevalgraph.h @@ -0,0 +1,31 @@ +/* + * xevalgraph.h + * + * Copyright 2010, 2011, 2012 Free Software Foundation, Inc. + * + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#ifndef XB_XEVALGRAPH +#define XB_XEVALGRAPH + +void EvalGraphSet P(( int first, int last, int current, ChessProgramStats_Move * pvInfo )); +float Color P((char *col, int n)); +void SetPen P((cairo_t *cr, float w, char *col, int dash)); + +#endif diff --git a/xaw/xgamelist.c b/xaw/xgamelist.c new file mode 100644 index 0000000..50367b1 --- /dev/null +++ b/xaw/xgamelist.c @@ -0,0 +1,118 @@ +/* + * xgamelist.c -- Game list window, part of X front end for XBoard + * + * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#include "config.h" + +#include +#include +#include +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +extern char *getenv(); +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#if USE_XAW3D +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "common.h" +#include "backend.h" +#include "xboard.h" +#include "xgamelist.h" +#include "dialogs.h" + + +char gameListTranslations[] = + ": WheelProc(-3) \n \ + : WheelProc(3) \n \ + : LoadSelectedProc(100) Set() \n \ + (2): LoadSelectedProc(0) \n \ + Home: LoadSelectedProc(-2) \n \ + End: LoadSelectedProc(2) \n \ + CtrlUp: LoadSelectedProc(-3) \n \ + CtrlDown: LoadSelectedProc(3) \n \ + Up: LoadSelectedProc(-1) \n \ + Down: LoadSelectedProc(1) \n \ + Left: LoadSelectedProc(-1) \n \ + Right: LoadSelectedProc(1) \n \ + Prior: LoadSelectedProc(-4) \n \ + Next: LoadSelectedProc(4) \n \ + Return: LoadSelectedProc(0) \n"; +char filterTranslations[] = + "Return: SetFilterProc() \n"; + + +void +LoadSelectedProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + if(GameListClicks(atoi(prms[0]))) return; // if no game loaded, no focus transfer + XSync(xDisplay, False); + XSetInputFocus(xDisplay, XtWindow(boardWidget), RevertToPointerRoot, CurrentTime); +} + +void +SetFilterProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + SetFilter(); +} + diff --git a/xaw/xgamelist.h b/xaw/xgamelist.h new file mode 100644 index 0000000..fa7b41a --- /dev/null +++ b/xaw/xgamelist.h @@ -0,0 +1,31 @@ +/* + * xgamelist.h -- Game list window, part of X front end for XBoard + * + * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#ifndef XB_XGAMELIST +#define XB_XGAMELIST + +void LoadSelectedProc P((Widget w, XEvent *event, + String *prms, Cardinal *nprms)); +void SetFilterProc P((Widget w, XEvent *event, + String *prms, Cardinal *nprms)); + +#endif /* XB_XGAMELIST */ diff --git a/xaw/xhistory.c b/xaw/xhistory.c new file mode 100644 index 0000000..4277f82 --- /dev/null +++ b/xaw/xhistory.c @@ -0,0 +1,169 @@ +/* + * New (WinBoard-style) Move history for XBoard + * + * Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + * ------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "frontend.h" +#include "backend.h" +#include "xhistory.h" +#include "xboard.h" +#include "dialogs.h" +#include "gettext.h" + +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif + +// templates for calls into back-end (= history.c; should be moved to history.h header shared with it!) +void RefreshMemoContent P((void)); +void MemoContentUpdated P((void)); +void FindMoveByCharIndex P(( int char_index )); + +// variables in xoptions.c +extern Option historyOptions[]; + +// ------------- low-level front-end actions called by MoveHistory back-end ----------------- + +void +HighlightMove (int from, int to, Boolean highlight) +{ + if(highlight) + XawTextSetSelection( historyOptions[0].handle, from, to ); // for lack of a better method, use selection for highighting +} + +void +ClearHistoryMemo () +{ + SetWidgetText(&historyOptions[0], "", HistoryDlg); +} + +// the bold argument says 0 = normal, 1 = bold typeface +// the colorNr argument says 0 = font-default, 1 = gray +int +AppendToHistoryMemo (char * text, int bold, int colorNr) +{ + return AppendText(&historyOptions[0], text); // for now ignore bold & color stuff, as Xaw cannot handle that +} + +void +ScrollToCurrent (int caretPos) +{ + Arg args[10]; + char *s; + int len; + GetWidgetText(&historyOptions[0], &s); + len = strlen(s); + if(caretPos < 0 || caretPos > len) caretPos = len; + if(caretPos > len-30) { // scroll to end, which causes no flicker + static XEvent event; + XtCallActionProc(historyOptions[0].handle, "end-of-file", &event, NULL, 0); + return; + } + // the following leads to a very annoying flicker, even when no scrolling is done at all. + XtSetArg(args[0], XtNinsertPosition, caretPos); // this triggers scrolling in Xaw + XtSetArg(args[1], XtNdisplayCaret, False); + XtSetValues(historyOptions[0].handle, args, 2); +} + + +// ------------------------------ callbacks -------------------------- + +char *historyText; +char historyTranslations[] = +": select-start() \n \ +: extend-end() SelectMove() \n"; + +void +SelectMove (Widget w, XEvent * event, String * params, Cardinal * nParams) +{ + XawTextPosition index, dummy; + + XawTextGetSelectionPos(w, &index, &dummy); + FindMoveByCharIndex( index ); // [HGM] also does the actual moving to it, now +} + +Option historyOptions[] = { +{ 200, T_VSCRL | T_FILL | T_WRAP | T_TOP, 400, NULL, (void*) &historyText, "", NULL, TextBox, "" }, +{ 0, NO_OK, 0, NULL, (void*) NULL, "", NULL, EndMark , "" } +}; + +// ------------ standard entry points into MoveHistory code ----------- + +Boolean +MoveHistoryIsUp () +{ + return shellUp[HistoryDlg]; +} + +Boolean +MoveHistoryDialogExists () +{ + return DialogExists(HistoryDlg); +} + +void +HistoryPopUp () +{ + if(GenericPopUp(historyOptions, _("Move list"), HistoryDlg, BoardWindow, NONMODAL, 1)) + AddHandler(&historyOptions[0], 0); + MarkMenu("View.MoveHistory", HistoryDlg); +} + +void +HistoryShowProc () +{ + if (!shellUp[HistoryDlg]) { + ASSIGN(historyText, ""); + HistoryPopUp(); + RefreshMemoContent(); + MemoContentUpdated(); + } else PopDown(HistoryDlg); + ToNrEvent(currentMove); +} diff --git a/xaw/xhistory.h b/xaw/xhistory.h new file mode 100644 index 0000000..90f0c9b --- /dev/null +++ b/xaw/xhistory.h @@ -0,0 +1,29 @@ +/* + * xhistory.h -- Eval graph window, part of X front end for XBoard + * + * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +#ifndef XB_XHISTLIST +#define XB_XHISTLIST + +void HistoryShowProc P((void)); +Boolean MoveHistoryIsUp P((void)); + +#endif /* XB_XHISTLIST */ diff --git a/xaw/xoptions.c b/xaw/xoptions.c new file mode 100644 index 0000000..a475c58 --- /dev/null +++ b/xaw/xoptions.c @@ -0,0 +1,1216 @@ +/* + * xoptions.c -- Move list window, part of X front end for XBoard + * + * Copyright 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + * ------------------------------------------------------------------------ + * + * GNU XBoard is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * GNU XBoard is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + +// [HGM] this file is the counterpart of woptions.c, containing xboard popup menus +// similar to those of WinBoard, to set the most common options interactively. + +#include "config.h" + +#include +#include +#include +#include + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +extern char *getenv(); +# if HAVE_STRING_H +# include +# else /* not HAVE_STRING_H */ +# include +# endif /* not HAVE_STRING_H */ +#endif /* not STDC_HEADERS */ + +#if HAVE_UNISTD_H +# include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common.h" +#include "backend.h" +#include "xboard.h" +#include "dialogs.h" +#include "menus.h" +#include "gettext.h" + +#ifdef ENABLE_NLS +# define _(s) gettext (s) +# define N_(s) gettext_noop (s) +#else +# define _(s) (s) +# define N_(s) s +#endif + +// [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines + +static Widget previous = NULL; +static Option *currentOption; + +void +UnCaret () +{ + Arg args[2]; + + if(previous) { + XtSetArg(args[0], XtNdisplayCaret, False); + XtSetValues(previous, args, 1); + } + previous = NULL; +} + +void +SetFocus (Widget w, XtPointer data, XEvent *event, Boolean *b) +{ + Arg args[2]; + char *s; + int j; + + UnCaret(); + XtSetArg(args[0], XtNstring, &s); + XtGetValues(w, args, 1); + j = 1; + XtSetArg(args[0], XtNdisplayCaret, True); + if(!strchr(s, '\n') && strlen(s) < 80) XtSetArg(args[1], XtNinsertPosition, strlen(s)), j++; + XtSetValues(w, args, j); + XtSetKeyboardFocus((Widget) data, w); + previous = w; +} + +void +BoardFocus () +{ + XtSetKeyboardFocus(shellWidget, formWidget); +} + +//--------------------------- Engine-specific options menu ---------------------------------- + +int dialogError; +Option *dialogOptions[NrOfDialogs]; + +static Arg layoutArgs[] = { + { XtNborderWidth, 0 }, + { XtNdefaultDistance, 0 }, +}; + +static Arg formArgs[] = { + { XtNborderWidth, 0 }, + { XtNresizable, (XtArgVal) True }, +}; + +void +GetWidgetText (Option *opt, char **buf) +{ + Arg arg; + XtSetArg(arg, XtNstring, buf); + XtGetValues(opt->handle, &arg, 1); +} + +void +SetWidgetText (Option *opt, char *buf, int n) +{ + Arg arg; + XtSetArg(arg, XtNstring, buf); + XtSetValues(opt->handle, &arg, 1); + if(n >= 0) SetFocus(opt->handle, shells[n], NULL, False); +} + +void +GetWidgetState (Option *opt, int *state) +{ + Arg arg; + XtSetArg(arg, XtNstate, state); + XtGetValues(opt->handle, &arg, 1); +} + +void +SetWidgetState (Option *opt, int state) +{ + Arg arg; + XtSetArg(arg, XtNstate, state); + XtSetValues(opt->handle, &arg, 1); +} + +void +SetWidgetLabel (Option *opt, char *buf) +{ + Arg arg; + XtSetArg(arg, XtNlabel, (XtArgVal) buf); + XtSetValues(opt->handle, &arg, 1); +} + +void +SetDialogTitle (DialogClass dlg, char *title) +{ + Arg args[16]; + XtSetArg(args[0], XtNtitle, title); + XtSetValues(shells[dlg], args, 1); +} + +void +LoadListBox (Option *opt, char *emptyText) +{ + static char *dummyList[2]; + dummyList[0] = emptyText; // empty listboxes tend to crash X, so display user-supplied warning string instead + XawListChange(opt->handle, *(char*)opt->target ? opt->target : dummyList, 0, 0, True); +} + +int +ReadScroll (Option *opt, float *top, float *bottom) +{ // retreives fractions of top and bottom of thumb + Arg args[16]; + Widget w = XtParent(opt->handle); // viewport + Widget v = XtNameToWidget(w, "vertical"); + int j=0; + float h; + if(!v) return FALSE; // no scroll bar + XtSetArg(args[j], XtNshown, &h); j++; + XtSetArg(args[j], XtNtopOfThumb, top); j++; + XtGetValues(v, args, j); + *bottom = *top + h; + return TRUE; +} + +void +SetScroll (Option *opt, float f) +{ // sets top of thumb to given fraction + static char *params[3] = { "", "Continuous", "Proportional" }; + static XEvent event; + Widget w = XtParent(opt->handle); // viewport + Widget v = XtNameToWidget(w, "vertical"); + if(!v) return; // no scroll bar + XtCallActionProc(v, "StartScroll", &event, params+1, 1); + XawScrollbarSetThumb(v, f, -1.0); + XtCallActionProc(v, "NotifyThumb", &event, params, 0); +// XtCallActionProc(v, "NotifyScroll", &event, params+2, 1); + XtCallActionProc(v, "EndScroll", &event, params, 0); +} + +void +HighlightListBoxItem (Option *opt, int nr) +{ + XawListHighlight(opt->handle, nr); +} + +void +HighlightWithScroll (Option *opt, int sel, int max) +{ + float top, bottom, f, g; + HighlightListBoxItem(opt, sel); + if(!ReadScroll(opt, &top, &bottom)) return; // no scroll bar + bottom = bottom*max - 1.f; + f = g = top; + top *= max; + if(sel > (top + 3*bottom)/4) f = (sel - 0.75f*(bottom-top))/max; else + if(sel < (3*top + bottom)/4) f = (sel - 0.25f*(bottom-top))/max; + if(f < 0.f) f = 0.; if(f + 1.f/max > 1.f) f = 1. - 1./max; + if(f != g) SetScroll(opt, f); +} + +int +SelectedListBoxItem (Option *opt) +{ + XawListReturnStruct *rs; + rs = XawListShowCurrent(opt->handle); + return rs->list_index; +} + +void +FocusOnWidget (Option *opt, DialogClass dlg) +{ + UnCaret(); + XtSetKeyboardFocus(shells[dlg], opt->handle); +} + +void +SetIconName (DialogClass dlg, char *name) +{ + Arg args[16]; + int j = 0; + XtSetArg(args[j], XtNiconName, (XtArgVal) name); j++; +// XtSetArg(args[j], XtNtitle, (XtArgVal) name); j++; + XtSetValues(shells[dlg], args, j); +} + +static void +CheckCallback (Widget ww, XtPointer client_data, XEvent *event, Boolean *b) +{ + int s, data = (intptr_t) client_data; + Option *opt = dialogOptions[data >> 8] + (data & 255); + + if(opt->type == Label) { ((ButtonCallback*) opt->target)(data&255); return; } + + GetWidgetState(opt, &s); + SetWidgetState(opt, !s); +} + +static void +SpinCallback (Widget w, XtPointer client_data, XtPointer call_data) +{ + String name, val; + Arg args[16]; + char buf[MSG_SIZ], *p; + int j = 0; // Initialisation is necessary because the text value may be non-numeric causing the scanf conversion to fail + int data = (intptr_t) client_data; + Option *opt = dialogOptions[data >> 8] + (data & 255); + + XtSetArg(args[0], XtNlabel, &name); + XtGetValues(w, args, 1); + + GetWidgetText(opt, &val); + sscanf(val, "%d", &j); + if (strcmp(name, _("browse")) == 0) { + char *q=val, *r; + for(r = ""; *q; q++) if(*q == '.') r = q; else if(*q == '/') r = ""; // last dot after last slash + if(!strcmp(r, "") && !currentCps && opt->type == FileName && opt->textValue) + r = opt->textValue; + Browse(data>>8, opt->name, NULL, r, opt->type == PathName, "", &p, (FILE**) opt); + return; + } else + if (strcmp(name, "+") == 0) { + if(++j > opt->max) return; + } else + if (strcmp(name, "-") == 0) { + if(--j < opt->min) return; + } else return; + snprintf(buf, MSG_SIZ, "%d", j); + SetWidgetText(opt, buf, TransientDlg); +} + +static void +ComboSelect (Widget w, caddr_t addr, caddr_t index) // callback for all combo items +{ + Arg args[16]; + Option *opt = dialogOptions[((intptr_t)addr)>>24]; // applicable option list + int i = ((intptr_t)addr)>>16 & 255; // option number + int j = 0xFFFF & (intptr_t) addr; + + values[i] = j; // store selected value in Option struct, for retrieval at OK + + if(opt[i].type == Graph || opt[i].min & COMBO_CALLBACK && (!currentCps || shellUp[BrowserDlg])) { + ((ButtonCallback*) opt[i].target)(i); + return; + } + + if(opt[i].min & NO_GETTEXT) + XtSetArg(args[0], XtNlabel, ((char**)opt[i].choice)[j]); + else + XtSetArg(args[0], XtNlabel, _(((char**)opt[i].choice)[j])); + + XtSetValues(opt[i].handle, args, 1); +} + +Widget +CreateMenuItem (Widget menu, char *msg, XtCallbackProc CB, int n) +{ + int j=0; + Widget entry; + Arg args[16]; + XtSetArg(args[j], XtNleftMargin, 20); j++; + XtSetArg(args[j], XtNrightMargin, 20); j++; + if(!strcmp(msg, "----")) { XtCreateManagedWidget(msg, smeLineObjectClass, menu, args, j); return NULL; } + XtSetArg(args[j], XtNlabel, msg); + entry = XtCreateManagedWidget("item", smeBSBObjectClass, menu, args, j+1); + XtAddCallback(entry, XtNcallback, CB, (caddr_t)(intptr_t) n); + return entry; +} + +static Widget +CreateComboPopup (Widget parent, Option *opt, int n, int fromList, int def) +{ // fromList determines if the item texts are taken from a list of strings, or from a menu table + int i; + Widget menu, entry; + Arg arg; + MenuItem *mb = (MenuItem *) opt->choice; + char **list = (char **) opt->choice; + + if(list[0] == NULL) return NULL; // avoid empty menus, as they cause crash + menu = XtCreatePopupShell(opt->name, simpleMenuWidgetClass, parent, NULL, 0); + + for (i=0; 1; i++) + { + char *msg = fromList ? list[i] : mb[i].string; + if(!msg) break; + entry = CreateMenuItem(menu, opt->min & NO_GETTEXT ? msg : _(msg), (XtCallbackProc) ComboSelect, (n<<16)+i); + if(!fromList) mb[i].handle = (void*) entry; // save item ID, for enabling / checkmarking + if(i==def) { + XtSetArg(arg, XtNpopupOnEntry, entry); + XtSetValues(menu, &arg, 1); + } + } + return menu; +} + +char moveTypeInTranslations[] = + "Return: TypeInProc(1) \n" + "Escape: TypeInProc(0) \n"; +extern char filterTranslations[]; +extern char gameListTranslations[]; +extern char memoTranslations[]; + + +char *translationTable[] = { // beware: order is essential! + historyTranslations, commentTranslations, moveTypeInTranslations, ICSInputTranslations, + filterTranslations, gameListTranslations, memoTranslations +}; + +void +AddHandler (Option *opt, int nr) +{ + XtOverrideTranslations(opt->handle, XtParseTranslationTable(translationTable[nr])); +} + +//----------------------------Generic dialog -------------------------------------------- + +// cloned from Engine Settings dialog (and later merged with it) + +Widget shells[NrOfDialogs]; +DialogClass parents[NrOfDialogs]; +WindowPlacement *wp[NrOfDialogs] = { // Beware! Order must correspond to DialogClass enum + NULL, &wpComment, &wpTags, NULL, NULL, NULL, NULL, &wpMoveHistory, &wpGameList, &wpEngineOutput, &wpEvalGraph, + NULL, NULL, NULL, NULL, /*&wpMain*/ NULL +}; + +int +DialogExists (DialogClass n) +{ // accessor for use in back-end + return shells[n] != NULL; +} + +void +RaiseWindow (DialogClass dlg) +{ + static XEvent xev; + Window root = RootWindow(xDisplay, DefaultScreen(xDisplay)); + Atom atom = XInternAtom (xDisplay, "_NET_ACTIVE_WINDOW", False); + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = xDisplay; + xev.xclient.window = XtWindow(shells[dlg]); + xev.xclient.message_type = atom; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = CurrentTime; + + XSendEvent (xDisplay, + root, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); + + XFlush(xDisplay); + XSync(xDisplay, False); +} + +int +PopDown (DialogClass n) +{ // pops down any dialog created by GenericPopUp (or returns False if it wasn't up), unmarks any associated marked menu + int j; + Arg args[10]; + Dimension windowH, windowW; Position windowX, windowY; + if (!shellUp[n] || !shells[n]) return 0; + if(n && wp[n]) { // remember position + j = 0; + XtSetArg(args[j], XtNx, &windowX); j++; + XtSetArg(args[j], XtNy, &windowY); j++; + XtSetArg(args[j], XtNheight, &windowH); j++; + XtSetArg(args[j], XtNwidth, &windowW); j++; + XtGetValues(shells[n], args, j); + wp[n]->x = windowX; + wp[n]->x = windowY; + wp[n]->width = windowW; + wp[n]->height = windowH; + } + previous = NULL; + XtPopdown(shells[n]); + shellUp[n]--; // count rather than clear + if(n == 0 || n >= PromoDlg) XtDestroyWidget(shells[n]), shells[n] = NULL; + if(marked[n]) { + MarkMenuItem(marked[n], False); + marked[n] = NULL; + } + if(!n && n != BrowserDlg) currentCps = NULL; // if an Engine Settings dialog was up, we must be popping it down now + currentOption = dialogOptions[TransientDlg]; // just in case a transient dialog was up (to allow its check and combo callbacks to work) + RaiseWindow(parents[n]); + if(parents[n] == BoardWindow) XtSetKeyboardFocus(shellWidget, formWidget); + return 1; +} + +void +GenericPopDown (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // to cause popdown through a translation (Delete Window button!) + int dlg = atoi(prms[0]); + Widget sh = shells[dlg]; + if(shellUp[BrowserDlg] && dlg != BrowserDlg || dialogError) return; // prevent closing dialog when it has an open file-browse daughter + shells[dlg] = w; + PopDown(dlg); + shells[dlg] = sh; // restore +} + +int +AppendText (Option *opt, char *s) +{ + XawTextBlock t; + char *v; + int len; + GetWidgetText(opt, &v); + len = strlen(v); + t.ptr = s; t.firstPos = 0; t.length = strlen(s); t.format = XawFmt8Bit; + XawTextReplace(opt->handle, len, len, &t); + return len; +} + +void +SetColor (char *colorName, Option *box) +{ // sets the color of a widget + Arg args[5]; + Pixel buttonColor; + XrmValue vFrom, vTo; + if (!appData.monoMode) { + vFrom.addr = (caddr_t) colorName; + vFrom.size = strlen(colorName); + XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); + if (vTo.addr == NULL) { + buttonColor = (Pixel) -1; + } else { + buttonColor = *(Pixel *) vTo.addr; + } + } else buttonColor = timerBackgroundPixel; + XtSetArg(args[0], XtNbackground, buttonColor);; + XtSetValues(box->handle, args, 1); +} + +void +ColorChanged (Widget w, XtPointer data, XEvent *event, Boolean *b) +{ // for detecting a typed change in color + char buf[10]; + if ( (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) && *buf == '\r' ) + RefreshColor((int)(intptr_t) data, 0); +} + +static void +GraphEventProc(Widget widget, caddr_t client_data, XEvent *event) +{ // handle expose and mouse events on Graph widget + Dimension w, h; + Arg args[16]; + int j, button=10, f=1, sizing=0; + Option *opt, *graph = (Option *) client_data; + PointerCallback *userHandler = graph->target; + + if (!XtIsRealized(widget)) return; + + switch(event->type) { + case Expose: // make handling of expose events generic, just copying from memory buffer (->choice) to display (->textValue) + /* Get window size */ + j = 0; + XtSetArg(args[j], XtNwidth, &w); j++; + XtSetArg(args[j], XtNheight, &h); j++; + XtGetValues(widget, args, j); + + if(w < graph->max || w > graph->max + 1 || h != graph->value) { // use width fudge of 1 pixel + if(((XExposeEvent*)event)->count >= 0) { // suppress sizing on expose for ordered redraw in response to sizing. + sizing = 1; + graph->max = w; graph->value = h; // note: old values are kept if we we don't exceed width fudge + } + } else w = graph->max; + + if(sizing && ((XExposeEvent*)event)->count > 0) { graph->max = 0; return; } // don't bother if further exposure is pending during resize + if(!graph->textValue || sizing) { // create surfaces of new size for display widget + if(graph->textValue) cairo_surface_destroy((cairo_surface_t *)graph->textValue); + graph->textValue = (char*) cairo_xlib_surface_create(xDisplay, XtWindow(widget), DefaultVisual(xDisplay, 0), w, h); + } + if(sizing) { // the memory buffer was already created in GenericPopup(), + // to give drawing routines opportunity to use it before first expose event + // (which are only processed when main gets to the event loop, so after all init!) + // so only change when size is no longer good + if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice); + graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); + break; + } + w = ((XExposeEvent*)event)->width; + if(((XExposeEvent*)event)->x + w > graph->max) w--; // cut off fudge pixel + if(w) ExposeRedraw(graph, ((XExposeEvent*)event)->x, ((XExposeEvent*)event)->y, w, ((XExposeEvent*)event)->height); + return; + case MotionNotify: + f = 0; + w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y; + break; + case ButtonRelease: + f = -1; // release indicated by negative button numbers + case ButtonPress: + w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y; + switch(((XButtonEvent*)event)->button) { + case Button1: button = 1; break; + case Button2: button = 2; break; + case Button3: button = 3; break; + case Button4: button = 4; break; + case Button5: button = 5; break; + } + } + button *= f; + opt = userHandler(button, w, h); + if(opt) { // user callback specifies a context menu; pop it up + XUngrabPointer(xDisplay, CurrentTime); + XtCallActionProc(widget, "XawPositionSimpleMenu", event, &(opt->name), 1); + XtPopupSpringLoaded(opt->handle); + } + XSync(xDisplay, False); +} + +void +GraphExpose (Option *opt, int x, int y, int w, int h) +{ + XExposeEvent e; + if(!opt->handle) return; + e.x = x; e.y = y; e.width = w; e.height = h; e.count = -1; e.type = Expose; // count = -1: kludge to suppress sizing + GraphEventProc(opt->handle, (caddr_t) opt, (XEvent *) &e); // fake expose event +} + +static void +GenericCallback (Widget w, XtPointer client_data, XtPointer call_data) +{ // all Buttons in a dialog (including OK, cancel) invoke this + String name; + Arg args[16]; + char buf[MSG_SIZ]; + int data = (intptr_t) client_data; + DialogClass dlg; + Widget sh = XtParent(XtParent(XtParent(w))), oldSh; + + currentOption = dialogOptions[dlg=data>>16]; data &= 0xFFFF; + oldSh = shells[dlg]; shells[dlg] = sh; // bow to reality + if (data == 30000) { // cancel + PopDown(dlg); + } else + if (data == 30001) { // save buttons imply OK + if(GenericReadout(currentOption, -1)) PopDown(dlg); // calls OK-proc after full readout, but no popdown if it returns false + } else + + if(currentCps && dlg != BrowserDlg) { + XtSetArg(args[0], XtNlabel, &name); + XtGetValues(w, args, 1); + if(currentOption[data].type == SaveButton) GenericReadout(currentOption, -1); + snprintf(buf, MSG_SIZ, "option %s\n", name); + SendToProgram(buf, currentCps); + } else ((ButtonCallback*) currentOption[data].target)(data); + + shells[dlg] = oldSh; // in case of multiple instances, restore previous (as this one could be popped down now) +} + +void +TabProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // for transfering focus to the next text-edit + Option *opt; + for(opt = currentOption; opt->type != EndMark; opt++) { + if(opt->handle == w) { + while(++opt) { + if(opt->type == EndMark) opt = currentOption; // wrap + if(opt->handle == w) return; // full circle + if(opt->type == TextBox || opt->type == Spin || opt->type == Fractional || opt->type == FileName || opt->type == PathName) { + SetFocus(opt->handle, XtParent(XtParent(XtParent(w))), NULL, 0); + return; + } + } + } + } +} + +void +WheelProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // for scrolling a widget seen through a viewport with the mouse wheel (ListBox!) + int j=0, n = atoi(prms[0]); + static char *params[3] = { "", "Continuous", "Proportional" }; + Arg args[16]; + float h, top; + Widget v; + if(!n) { // transient dialogs also use this for list-selection callback + n = prms[1][0]-'0'; + Option *opt=dialogOptions[prms[2][0]-'A'] + n; + if(opt->textValue) ((ListBoxCallback*) opt->textValue)(n, SelectedListBoxItem(opt)); + return; + } + v = XtNameToWidget(XtParent(w), "vertical"); + if(!v) return; + XtSetArg(args[j], XtNshown, &h); j++; + XtSetArg(args[j], XtNtopOfThumb, &top); j++; + XtGetValues(v, args, j); + top += 0.1f*h*n; if(top < 0.f) top = 0.; + XtCallActionProc(v, "StartScroll", event, params+1, 1); + XawScrollbarSetThumb(v, top, -1.0); + XtCallActionProc(v, "NotifyThumb", event, params, 0); +// XtCallActionProc(w, "NotifyScroll", event, params+2, 1); + XtCallActionProc(v, "EndScroll", event, params, 0); +} + +static char *oneLiner = + "Return: redraw-display() \n \ + Tab: TabProc() \n "; +static char scrollTranslations[] = + "(2): WheelProc(0 0 A) \n \ + : WheelProc(-1) \n \ + : WheelProc(1) \n "; + +static void +SqueezeIntoBox (Option *opt, int nr, int width) +{ // size buttons in bar to fit, clipping button names where necessary + int i, wtot = 0; + Dimension widths[20], oldWidths[20]; + Arg arg; + for(i=1; imin = wtot; + if(width <= 0) return; + while(wtot > width) { + int wmax=0, imax=0; + for(i=1; i wmax) wmax = widths[imax=i]; + widths[imax]--; + wtot--; + } + for(i=1; imin = wtot; +} + +int +SetPositionAndSize (Arg *args, Widget leftNeigbor, Widget topNeigbor, int b, int w, int h, int chaining) +{ // sizing and positioning most widgets have in common + int j = 0; + // first position the widget w.r.t. earlier ones + if(chaining & 1) { // same row: position w.r.t. last (on current row) and lastrow + XtSetArg(args[j], XtNfromVert, topNeigbor); j++; + XtSetArg(args[j], XtNfromHoriz, leftNeigbor); j++; + } else // otherwise it goes at left margin (which is default), below the previous element + XtSetArg(args[j], XtNfromVert, leftNeigbor), j++; + // arrange chaining ('2'-bit indicates top and bottom chain the same) + if((chaining & 14) == 6) XtSetArg(args[j], XtNtop, XtChainBottom), j++; + if((chaining & 14) == 10) XtSetArg(args[j], XtNbottom, XtChainTop ), j++; + if(chaining & 4) XtSetArg(args[j], XtNbottom, XtChainBottom ), j++; + if(chaining & 8) XtSetArg(args[j], XtNtop, XtChainTop), j++; + if(chaining & 0x10) XtSetArg(args[j], XtNright, XtChainRight), j++; + if(chaining & 0x20) XtSetArg(args[j], XtNleft, XtChainRight), j++; + if(chaining & 0x40) XtSetArg(args[j], XtNright, XtChainLeft ), j++; + if(chaining & 0x80) XtSetArg(args[j], XtNleft, XtChainLeft ), j++; + // set size (if given) + if(w) XtSetArg(args[j], XtNwidth, w), j++; + if(h) XtSetArg(args[j], XtNheight, h), j++; + // color + if(!appData.monoMode) { + if(!b && appData.dialogColor[0]) XtSetArg(args[j], XtNbackground, dialogColor), j++; + if(b == 3 && appData.buttonColor[0]) XtSetArg(args[j], XtNbackground, buttonColor), j++; + } + if(b == 3) b = 1; + // border + XtSetArg(args[j], XtNborderWidth, b); j++; + return j; +} + +int +GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent, int modal, int top) +{ + Arg args[24]; + Widget popup, layout, dialog=NULL, edit=NULL, form, last, b_ok, b_cancel, previousPane = NULL, textField = NULL, oldForm, oldLastRow, oldForeLast; + Window root, child; + int x, y, i, j, height=999, width=1, h, c, w, shrink=FALSE, stack = 0, box, chain; + int win_x, win_y, maxWidth, maxTextWidth; + unsigned int mask; + char def[MSG_SIZ], *msg, engineDlg = (currentCps != NULL && dlgNr != BrowserDlg); + static char pane[6] = "paneX"; + Widget texts[100], forelast = NULL, anchor, widest, lastrow = NULL, browse = NULL; + Dimension bWidth = 50; + + if(dlgNr < PromoDlg && shellUp[dlgNr]) return 0; // already up + if(dlgNr && dlgNr < PromoDlg && shells[dlgNr]) { // reusable, and used before (but popped down) + XtPopup(shells[dlgNr], XtGrabNone); + shellUp[dlgNr] = True; + return 0; + } + + dialogOptions[dlgNr] = option; // make available to callback + // post currentOption globally, so Spin and Combo callbacks can already use it + // WARNING: this kludge does not work for persistent dialogs, so that these cannot have spin or combo controls! + currentOption = option; + + if(engineDlg) { // Settings popup for engine: format through heuristic + int n = currentCps->nrOptions; + if(!n) { DisplayNote(_("Engine has no options")); currentCps = NULL; return 0; } + if(n > 50) width = 4; else if(n>24) width = 2; else width = 1; + height = n / width + 1; + if(n && (currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton)) currentOption[n].min = SAME_ROW; // OK on same line + currentOption[n].type = EndMark; currentOption[n].target = NULL; // delimit list by callback-less end mark + } + i = 0; + XtSetArg(args[i], XtNresizable, True); i++; + shells[BoardWindow] = shellWidget; parents[dlgNr] = parent; + + if(dlgNr == BoardWindow) popup = shellWidget; else + popup = shells[dlgNr] = + XtCreatePopupShell(title, !top || !appData.topLevel ? transientShellWidgetClass : topLevelShellWidgetClass, + shells[parent], args, i); + + layout = + XtCreateManagedWidget(layoutName, formWidgetClass, popup, + layoutArgs, XtNumber(layoutArgs)); + if(!appData.monoMode && appData.dialogColor[0]) XtSetArg(args[0], XtNbackground, dialogColor); + XtSetValues(layout, args, 1); + + for(c=0; c and + + if(option[i].type == TextBox || option[i].type == Fractional) break; + + // add increment and decrement controls for spin + if(option[i].type == FileName || option[i].type == PathName) { + msg = _("browse"); w = 0; // automatically scale to width of text + j = textHeight ? textHeight : 0; + } else { + w = 20; msg = "+"; j = textHeight/2; // spin button + } + j = SetPositionAndSize(args, last, edit, 3 /* border */, + w /* w */, j /* h */, 0x31 /* chain to right edge */); + edit = XtCreateManagedWidget(msg, commandWidgetClass, form, args, j); + XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i + 256*dlgNr); + if(w == 0) browse = edit; + + if(option[i].type != Spin) break; + + j = SetPositionAndSize(args, last, edit, 3 /* border */, + 20 /* w */, textHeight/2 /* h */, 0x31 /* chain to right edge */); + XtSetArg(args[j], XtNvertDistance, -1); j++; + last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j); + XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i + 256*dlgNr); + break; + case CheckBox: + if(!engineDlg) option[i].value = *(Boolean*)option[i].target; // where checkbox callback uses it + j = SetPositionAndSize(args, last, lastrow, 1 /* border */, + textHeight/2 /* w */, textHeight/2 /* h */, 0xC0 /* chain both to left edge */); + XtSetArg(args[j], XtNvertDistance, (textHeight+2)/4 + 3); j++; + XtSetArg(args[j], XtNstate, option[i].value); j++; + lastrow = last; + option[i].handle = (void*) + (last = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j)); + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + option[i].max /* w */, textHeight /* h */, 0xC1 /* chain */); + XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; + XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; + last = XtCreateManagedWidget("label", commandWidgetClass, form, args, j); + // make clicking the text toggle checkbox + XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i + 256*dlgNr); + shrink = TRUE; // following buttons must get text height + break; + case Label: + msg = option[i].name; + if(!msg) break; + chain = option[i].min; + if(chain & SAME_ROW) forelast = lastrow; else shrink = FALSE; + j = SetPositionAndSize(args, last, lastrow, (chain & 2) != 0 /* border */, + option[i].max /* w */, shrink ? textHeight : 0 /* h */, chain | 2 /* chain */); +#if ENABLE_NLS + if(option[i].choice) XtSetArg(args[j], XtNfontSet, *(XFontSet*)option[i].choice), j++; +#else + if(option[i].choice) XtSetArg(args[j], XtNfont, (XFontStruct*)option[i].choice), j++; +#endif + XtSetArg(args[j], XtNresizable, False); j++; + XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; + XtSetArg(args[j], XtNlabel, _(msg)); j++; + option[i].handle = (void*) (last = XtCreateManagedWidget("label", labelWidgetClass, form, args, j)); + if(option[i].target) // allow user to specify event handler for button presses + XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i + 256*dlgNr); + break; + case SaveButton: + case Button: + if(option[i].min & SAME_ROW) { + chain = 0x31; // 0011.0001 = both left and right side to right edge + forelast = lastrow; + } else chain = 0, shrink = FALSE; + j = SetPositionAndSize(args, last, lastrow, 3 /* border */, + option[i].max /* w */, shrink ? textHeight : 0 /* h */, option[i].min & 0xE | chain /* chain */); + XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; + if(option[i].textValue) { // special for buttons of New Variant dialog + XtSetArg(args[j], XtNsensitive, appData.noChessProgram || option[i].value < 0 + || strstr(first.variants, VariantName(option[i].value))); j++; + XtSetArg(args[j], XtNborderWidth, (gameInfo.variant == option[i].value)+1); j++; + } + option[i].handle = (void*) + (dialog = last = XtCreateManagedWidget(option[i].name, commandWidgetClass, form, args, j)); + if(option[i].choice && ((char*)option[i].choice)[0] == '#' && !engineDlg) { // for the color picker default-reset + SetColor( *(char**) option[i-1].target, &option[i]); + XtAddEventHandler(option[i-1].handle, KeyReleaseMask, False, ColorChanged, (XtPointer)(intptr_t) i-1); + } + XtAddCallback(last, XtNcallback, GenericCallback, (XtPointer)(intptr_t) i + (dlgNr<<16)); // invokes user callback + if(option[i].textValue) SetColor( option[i].textValue, &option[i]); // for new-variant buttons + break; + case ComboBox: + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + 0 /* w */, textHeight /* h */, 0xC0 /* chain both sides to left edge */); + XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; + XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; + texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j); + + if(option[i].min & COMBO_CALLBACK) msg = _(option[i].name); else { + if(!engineDlg) SetCurrentComboSelection(option+i); + msg=_(((char**)option[i].choice)[option[i].value]); + } + + j = SetPositionAndSize(args, dialog, last, (option[i].min & 2) == 0 /* border */, + option[i].max && !engineDlg ? option[i].max : 100 /* w */, + textHeight /* h */, 0x91 /* chain */); // same row as its label! + XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++; + XtSetArg(args[j], XtNlabel, msg); j++; + shrink = TRUE; + option[i].handle = (void*) + (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j)); + CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, -1); + values[i] = option[i].value; + break; + case ListBox: + // Listbox goes in viewport, as needed for game list + if(option[i].min & SAME_ROW) forelast = lastrow; + j = SetPositionAndSize(args, last, lastrow, 1 /* border */, + option[i].max /* w */, option[i].value /* h */, option[i].min /* chain */); + XtSetArg(args[j], XtNresizable, False); j++; + XtSetArg(args[j], XtNallowVert, True); j++; // scoll direction + last = + XtCreateManagedWidget("viewport", viewportWidgetClass, form, args, j); + j = 0; // now list itself + XtSetArg(args[j], XtNdefaultColumns, 1); j++; + XtSetArg(args[j], XtNforceColumns, True); j++; + XtSetArg(args[j], XtNverticalList, True); j++; + option[i].handle = (void*) + (edit = XtCreateManagedWidget("list", listWidgetClass, last, args, j)); + XawListChange(option[i].handle, option[i].target, 0, 0, True); + XawListHighlight(option[i].handle, 0); + scrollTranslations[25] = '0' + i; + scrollTranslations[27] = 'A' + dlgNr; + XtOverrideTranslations(edit, XtParseTranslationTable(scrollTranslations)); // for mouse-wheel + break; + case Graph: + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + option[i].max /* w */, option[i].value /* h */, option[i].min /* chain */); + option[i].handle = (void*) + (last = XtCreateManagedWidget("graph", widgetClass, form, args, j)); + XtAddEventHandler(last, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask, False, + (XtEventHandler) GraphEventProc, &option[i]); // mandatory user-supplied expose handler + if(option[i].min & SAME_ROW) last = forelast, forelast = lastrow; + option[i].choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, option[i].max, option[i].value); // image buffer + break; + case PopUp: // note: used only after Graph, so 'last' refers to the Graph widget + option[i].handle = (void*) CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, option[i].value); + break; + case BoxBegin: + if(option[i].min & SAME_ROW) forelast = lastrow; + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + 0 /* w */, 0 /* h */, option[i].min /* chain */); + XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++; + XtSetArg(args[j], XtNvSpace, 0); j++; + option[box=i].handle = (void*) + (last = XtCreateWidget("box", boxWidgetClass, form, args, j)); + oldForm = form; form = last; oldLastRow = lastrow; oldForeLast = forelast; + lastrow = NULL; last = NULL; + break; + case DropDown: + j = SetPositionAndSize(args, last, lastrow, 0 /* border */, + 0 /* w */, 0 /* h */, 1 /* chain (always on same row) */); + forelast = lastrow; + msg = _(option[i].name); // write name on the menu button + XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++; + XtSetArg(args[j], XtNlabel, msg); j++; + option[i].handle = (void*) + (last = XtCreateManagedWidget(option[i].name, menuButtonWidgetClass, form, args, j)); + option[i].textValue = (char*) CreateComboPopup(last, option + i, i + 256*dlgNr, FALSE, -1); + break; + case BoxEnd: + XtManageChildren(&form, 1); + SqueezeIntoBox(&option[box], i-box, option[box].max); + if(option[i].target) ((ButtonCallback*)option[i].target)(box); // callback that can make sizing decisions + last = form; lastrow = oldLastRow; form = oldForm; forelast = oldForeLast; + break; + case Break: + width++; + height = i+1; + stack = !(option[i].min & SAME_ROW); + break; + default: + printf("GenericPopUp: unexpected case in switch.\n"); + break; + } + } + + // make an attempt to align all spins and textbox controls + maxWidth = maxTextWidth = 0; + if(browse != NULL) { + j=0; + XtSetArg(args[j], XtNwidth, &bWidth); j++; + XtGetValues(browse, args, j); + } + for(h=0; h maxWidth) maxWidth = w; + widest = texts[h]; + } else { + if(w > maxTextWidth) maxTextWidth = w; + if(!widest) widest = texts[h]; + } + } + } + if(maxTextWidth + 110 < maxWidth) + maxTextWidth = maxWidth - 110; + else maxWidth = maxTextWidth + 110; + for(h=0; hWM_PROTOCOLS: GenericPopDown(\"%d\") \n", dlgNr); + XtAugmentTranslations(popup, XtParseTranslationTable(def)); + XQueryPointer(xDisplay, xBoardWindow, &root, &child, + &x, &y, &win_x, &win_y, &mask); + + XtSetArg(args[0], XtNx, x - 10); + XtSetArg(args[1], XtNy, y - 30); + XtSetValues(popup, args, 2); + } + XtPopup(popup, modal ? XtGrabExclusive : XtGrabNone); + shellUp[dlgNr]++; // count rather than flag + previous = NULL; + if(textField) SetFocus(textField, popup, (XEvent*) NULL, False); + if(dlgNr && wp[dlgNr] && wp[dlgNr]->width > 0) { // if persistent window-info available, reposition + j = 0; + XtSetArg(args[j], XtNheight, (Dimension) (wp[dlgNr]->height)); j++; + XtSetArg(args[j], XtNwidth, (Dimension) (wp[dlgNr]->width)); j++; + XtSetArg(args[j], XtNx, (Position) (wp[dlgNr]->x)); j++; + XtSetArg(args[j], XtNy, (Position) (wp[dlgNr]->y)); j++; + XtSetValues(popup, args, j); + } + RaiseWindow(dlgNr); + return 1; // tells caller he must do initialization (e.g. add specific event handlers) +} + + +/* function called when the data to Paste is ready */ +static void +SendTextCB (Widget w, XtPointer client_data, Atom *selection, + Atom *type, XtPointer value, unsigned long *len, int *format) +{ + char buf[MSG_SIZ], *p = (char*) textOptions[(int)(intptr_t) client_data].choice, *name = (char*) value, *q; + if (value==NULL || *len==0) return; /* nothing selected, abort */ + name[*len]='\0'; + strncpy(buf, p, MSG_SIZ); + q = strstr(p, "$name"); + snprintf(buf + (q-p), MSG_SIZ -(q-p), "%s%s", name, q+5); + SendString(buf); + XtFree(value); +} + +void +SendText (int n) +{ + char *p = (char*) textOptions[n].choice; + if(strstr(p, "$name")) { + XtGetSelectionValue(menuBarWidget, + XA_PRIMARY, XA_STRING, + /* (XtSelectionCallbackProc) */ SendTextCB, + (XtPointer) (intptr_t) n, /* client_data passed to PastePositionCB */ + CurrentTime + ); + } else SendString(p); +} + +void +SetInsertPos (Option *opt, int pos) +{ + Arg args[16]; + XtSetArg(args[0], XtNinsertPosition, pos); + XtSetValues(opt->handle, args, 1); +// SetFocus(opt->handle, shells[InputBoxDlg], NULL, False); // No idea why this does not work, and the following is needed: +// XSetInputFocus(xDisplay, XtWindow(opt->handle), RevertToPointerRoot, CurrentTime); +} + +void +TypeInProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ // can be used as handler for any text edit in any dialog (from GenericPopUp, that is) + int n = prms[0][0] - '0'; + Widget sh = XtParent(XtParent(XtParent(w))); // popup shell + + if(n<2) { // Enter or Esc typed from primed text widget: treat as if dialog OK or cancel button hit. + int dlgNr; // figure out what the dialog number is by comparing shells (because we must pass it :( ) + for(dlgNr=0; dlgNrhandle), RevertToPointerRoot, CurrentTime); +} + + diff --git a/xboard.c b/xboard.c deleted file mode 100644 index 69079be..0000000 --- a/xboard.c +++ /dev/null @@ -1,2556 +0,0 @@ -/* - * xboard.c -- X front end for XBoard - * - * Copyright 1991 by Digital Equipment Corporation, Maynard, - * Massachusetts. - * - * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * - * The following terms apply to Digital Equipment Corporation's copyright - * interest in XBoard: - * ------------------------------------------------------------------------ - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of Digital not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * - * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING - * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL - * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR - * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * ------------------------------------------------------------------------ - * - * The following terms apply to the enhanced version of XBoard - * distributed by the Free Software Foundation: - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#define HIGHDRAG 1 - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !OMIT_SOCKETS -# if HAVE_SYS_SOCKET_H -# include -# include -# include -# else /* not HAVE_SYS_SOCKET_H */ -# if HAVE_LAN_SOCKET_H -# include -# include -# include -# else /* not HAVE_LAN_SOCKET_H */ -# define OMIT_SOCKETS 1 -# endif /* not HAVE_LAN_SOCKET_H */ -# endif /* not HAVE_SYS_SOCKET_H */ -#endif /* !OMIT_SOCKETS */ - -#if STDC_HEADERS -# include -# include -#else /* not STDC_HEADERS */ -extern char *getenv(); -# if HAVE_STRING_H -# include -# else /* not HAVE_STRING_H */ -# include -# endif /* not HAVE_STRING_H */ -#endif /* not STDC_HEADERS */ - -#if HAVE_SYS_FCNTL_H -# include -#else /* not HAVE_SYS_FCNTL_H */ -# if HAVE_FCNTL_H -# include -# endif /* HAVE_FCNTL_H */ -#endif /* not HAVE_SYS_FCNTL_H */ - -#if HAVE_SYS_SYSTEMINFO_H -# include -#endif /* HAVE_SYS_SYSTEMINFO_H */ - -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - -#if HAVE_UNISTD_H -# include -#endif - -#if HAVE_SYS_WAIT_H -# include -#endif - -#if HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -# define HAVE_DIR_STRUCT -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# if HAVE_SYS_NDIR_H -# include -# define HAVE_DIR_STRUCT -# endif -# if HAVE_SYS_DIR_H -# include -# define HAVE_DIR_STRUCT -# endif -# if HAVE_NDIR_H -# include -# define HAVE_DIR_STRUCT -# endif -#endif - -#if ENABLE_NLS -#include -#endif - -#include -#include -#include -#include -#include -#include -#if USE_XAW3D -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are. -#include "common.h" - -#if HAVE_LIBXPM -#include -#define IMAGE_EXT "xpm" -#else -#define IMAGE_EXT "xim" -#endif - -#include "bitmaps/icon_white.bm" -#include "bitmaps/icon_black.bm" -#include "bitmaps/checkmark.bm" - -#include "frontend.h" -#include "backend.h" -#include "backendz.h" -#include "moves.h" -#include "xboard.h" -#include "childio.h" -#include "xgamelist.h" -#include "xhistory.h" -#include "xevalgraph.h" -#include "xedittags.h" -#include "menus.h" -#include "board.h" -#include "dialogs.h" -#include "engineoutput.h" -#include "usystem.h" -#include "gettext.h" -#include "draw.h" - - -#ifdef __EMX__ -#ifndef HAVE_USLEEP -#define HAVE_USLEEP -#endif -#define usleep(t) _sleep2(((t)+500)/1000) -#endif - -#ifdef ENABLE_NLS -# define _(s) gettext (s) -# define N_(s) gettext_noop (s) -#else -# define _(s) (s) -# define N_(s) s -#endif - -int main P((int argc, char **argv)); -RETSIGTYPE CmailSigHandler P((int sig)); -RETSIGTYPE IntSigHandler P((int sig)); -RETSIGTYPE TermSizeSigHandler P((int sig)); -Widget CreateMenuBar P((Menu *mb, int boardWidth)); -#if ENABLE_NLS -char *InsertPxlSize P((char *pattern, int targetPxlSize)); -XFontSet CreateFontSet P((char *base_fnt_lst)); -#else -char *FindFont P((char *pattern, int targetPxlSize)); -#endif -void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[], - u_int wreq, u_int hreq)); -void EventProc P((Widget widget, caddr_t unused, XEvent *event)); -void DelayedDrag P((void)); -static void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event)); -void HandlePV P((Widget w, XEvent * event, - String * params, Cardinal * nParams)); -void DrawPositionProc P((Widget w, XEvent *event, - String *prms, Cardinal *nprms)); -void CommentClick P((Widget w, XEvent * event, - String * params, Cardinal * nParams)); -void ICSInputBoxPopUp P((void)); -void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data)); -void KeyBindingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void QuitWrapper P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -static void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -static void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -static void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -Boolean TempBackwardActive = False; -void ManInner P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void DisplayMove P((int moveNumber)); -void ICSInitScript P((void)); -void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams)); -void update_ics_width P(()); -int CopyMemoProc P(()); - -/* -* XBoard depends on Xt R4 or higher -*/ -int xtVersion = XtSpecificationRelease; - -int xScreen; -Display *xDisplay; -Window xBoardWindow; -Pixel lowTimeWarningColor, dialogColor, buttonColor; // used in widgets -Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap; -Widget shellWidget, formWidget, boardWidget, titleWidget, dropMenu, menuBarWidget; -Option *optList; // contains all widgets of main window -#if ENABLE_NLS -XFontSet fontSet, clockFontSet; -#else -Font clockFontID; -XFontStruct *clockFontStruct; -#endif -Font coordFontID, countFontID; -XFontStruct *coordFontStruct, *countFontStruct; -XtAppContext appContext; -char *layoutName; - -char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion - -Position commentX = -1, commentY = -1; -Dimension commentW, commentH; -typedef unsigned int BoardSize; -BoardSize boardSize; -Boolean chessProgram; - -int minX, minY; // [HGM] placement: volatile limits on upper-left corner -int smallLayout = 0, tinyLayout = 0, - marginW, marginH, // [HGM] for run-time resizing - fromX = -1, fromY = -1, toX, toY, commentUp = False, - errorExitStatus = -1, defaultLineGap; -Dimension textHeight; -Pixel timerForegroundPixel, timerBackgroundPixel; -Pixel buttonForegroundPixel, buttonBackgroundPixel; -char *chessDir, *programName, *programVersion; -Boolean alwaysOnTop = False; -char *icsTextMenuString; -char *icsNames; -char *firstChessProgramNames; -char *secondChessProgramNames; - -WindowPlacement wpMain; -WindowPlacement wpConsole; -WindowPlacement wpComment; -WindowPlacement wpMoveHistory; -WindowPlacement wpEvalGraph; -WindowPlacement wpEngineOutput; -WindowPlacement wpGameList; -WindowPlacement wpTags; - - -/* This magic number is the number of intermediate frames used - in each half of the animation. For short moves it's reduced - by 1. The total number of frames will be factor * 2 + 1. */ -#define kFactor 4 - -SizeDefaults sizeDefaults[] = SIZE_DEFAULTS; - -typedef struct { - char piece; - char* widget; -} DropMenuEnables; - -DropMenuEnables dmEnables[] = { - { 'P', "Pawn" }, - { 'N', "Knight" }, - { 'B', "Bishop" }, - { 'R', "Rook" }, - { 'Q', "Queen" } -}; - -Arg shellArgs[] = { - { XtNwidth, 0 }, - { XtNheight, 0 }, - { XtNminWidth, 0 }, - { XtNminHeight, 0 }, - { XtNmaxWidth, 0 }, - { XtNmaxHeight, 0 } -}; - -XtResource clientResources[] = { - { "flashCount", "flashCount", XtRInt, sizeof(int), - XtOffset(AppDataPtr, flashCount), XtRImmediate, - (XtPointer) FLASH_COUNT }, -}; - -XrmOptionDescRec shellOptions[] = { - { "-flashCount", "flashCount", XrmoptionSepArg, NULL }, - { "-flash", "flashCount", XrmoptionNoArg, "3" }, - { "-xflash", "flashCount", XrmoptionNoArg, "0" }, -}; - -XtActionsRec boardActions[] = { - { "DrawPosition", DrawPositionProc }, - { "HandlePV", HandlePV }, - { "SelectPV", SelectPV }, - { "StopPV", StopPV }, - { "MenuItem", KeyBindingProc }, // [HGM] generic handler for key bindings - { "QuitProc", QuitWrapper }, - { "ManProc", ManInner }, - { "TempBackwardProc", TempBackwardProc }, - { "TempForwardProc", TempForwardProc }, - { "CommentClick", (XtActionProc) CommentClick }, - { "GenericPopDown", (XtActionProc) GenericPopDown }, - { "ErrorPopDown", (XtActionProc) ErrorPopDown }, - { "CopyMemoProc", (XtActionProc) CopyMemoProc }, - { "SelectMove", (XtActionProc) SelectMove }, - { "LoadSelectedProc", LoadSelectedProc }, - { "SetFilterProc", SetFilterProc }, - { "TypeInProc", TypeInProc }, - { "EnterKeyProc", EnterKeyProc }, - { "UpKeyProc", UpKeyProc }, - { "DownKeyProc", DownKeyProc }, - { "WheelProc", WheelProc }, - { "TabProc", TabProc }, -}; - -char globalTranslations[] = - ":F9: MenuItem(Actions.Resign) \n \ - :Ctrln: MenuItem(File.NewGame) \n \ - :MetaV: MenuItem(File.NewVariant) \n \ - :Ctrlo: MenuItem(File.LoadGame) \n \ - :MetaNext: MenuItem(LoadNextGameProc) \n \ - :MetaPrior: MenuItem(LoadPrevGameProc) \n \ - :CtrlDown: LoadSelectedProc(3) \n \ - :CtrlUp: LoadSelectedProc(-3) \n \ - :Ctrls: MenuItem(File.SaveGame) \n \ - :Ctrlc: MenuItem(Edit.CopyGame) \n \ - :Ctrlv: MenuItem(Edit.PasteGame) \n \ - :CtrlO: MenuItem(File.LoadPosition) \n \ - :ShiftNext: MenuItem(LoadNextPositionProc) \n \ - :ShiftPrior: MenuItem(LoadPrevPositionProc) \n \ - :CtrlS: MenuItem(File.SavePosition) \n \ - :CtrlC: MenuItem(Edit.CopyPosition) \n \ - :CtrlV: MenuItem(Edit.PastePosition) \n \ - :Ctrlq: MenuItem(File.Quit) \n \ - :Ctrlw: MenuItem(Mode.MachineWhite) \n \ - :Ctrlb: MenuItem(Mode.MachineBlack) \n \ - :Ctrlt: MenuItem(Mode.TwoMachines) \n \ - :Ctrla: MenuItem(Mode.AnalysisMode) \n \ - :Ctrlg: MenuItem(Mode.AnalyzeFile) \n \ - :Ctrle: MenuItem(Mode.EditGame) \n \ - :CtrlE: MenuItem(Mode.EditPosition) \n \ - :MetaO: MenuItem(View.EngineOutput) \n \ - :MetaE: MenuItem(View.EvaluationGraph) \n \ - :MetaG: MenuItem(View.GameList) \n \ - :MetaH: MenuItem(View.MoveHistory) \n \ - :Pause: MenuItem(Mode.Pause) \n \ - :F3: MenuItem(Action.Accept) \n \ - :F4: MenuItem(Action.Decline) \n \ - :F12: MenuItem(Action.Rematch) \n \ - :F5: MenuItem(Action.CallFlag) \n \ - :F6: MenuItem(Action.Draw) \n \ - :F7: MenuItem(Action.Adjourn) \n \ - :F8: MenuItem(Action.Abort) \n \ - :F10: MenuItem(Action.StopObserving) \n \ - :F11: MenuItem(Action.StopExamining) \n \ - :Ctrld: MenuItem(DebugProc) \n \ - :Meta CtrlF12: MenuItem(DebugProc) \n \ - :MetaEnd: MenuItem(Edit.ForwardtoEnd) \n \ - :MetaRight: MenuItem(Edit.Forward) \n \ - :MetaHome: MenuItem(Edit.BacktoStart) \n \ - :MetaLeft: MenuItem(Edit.Backward) \n \ - :Left: MenuItem(Edit.Backward) \n \ - :Right: MenuItem(Edit.Forward) \n \ - :Home: MenuItem(Edit.Revert) \n \ - :End: MenuItem(Edit.TruncateGame) \n \ - :Ctrlm: MenuItem(Engine.MoveNow) \n \ - :Ctrlx: MenuItem(Engine.RetractMove) \n \ - :MetaJ: MenuItem(Options.Adjudications) \n \ - :MetaU: MenuItem(Options.CommonEngine) \n \ - :MetaT: MenuItem(Options.TimeControl) \n \ - :CtrlP: MenuItem(PonderNextMove) \n " -#ifndef OPTIONSDIALOG - "\ - :CtrlQ: MenuItem(AlwaysQueenProc) \n \ - :CtrlF: MenuItem(AutoflagProc) \n \ - :CtrlA: MenuItem(AnimateMovingProc) \n \ - :CtrlL: MenuItem(TestLegalityProc) \n \ - :CtrlH: MenuItem(HideThinkingProc) \n " -#endif - "\ - :F1: MenuItem(Help.ManXBoard) \n \ - :F2: MenuItem(View.FlipView) \n \ - :Return: TempBackwardProc() \n \ - :Return: TempForwardProc() \n"; - -char ICSInputTranslations[] = - "Up: UpKeyProc() \n " - "Down: DownKeyProc() \n " - "Return: EnterKeyProc() \n"; - -// [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works, -// as the widget is destroyed before the up-click can call extend-end -char commentTranslations[] = ": extend-end() select-start() CommentClick() \n"; - -String xboardResources[] = { - "*Error*translations: #override\\n Return: ErrorPopDown()", - NULL - }; - - -/* Max possible square size */ -#define MAXSQSIZE 256 - -static int xpm_avail[MAXSQSIZE]; - -#ifdef HAVE_DIR_STRUCT - -/* Extract piece size from filename */ -static int -xpm_getsize (char *name, int len, char *ext) -{ - char *p, *d; - char buf[10]; - - if (len < 4) - return 0; - - if ((p=strchr(name, '.')) == NULL || - StrCaseCmp(p+1, ext) != 0) - return 0; - - p = name + 3; - d = buf; - - while (*p && isdigit(*p)) - *(d++) = *(p++); - - *d = 0; - return atoi(buf); -} - -/* Setup xpm_avail */ -static int -xpm_getavail (char *dirname, char *ext) -{ - DIR *dir; - struct dirent *ent; - int i; - - for (i=0; id_name, NAMLEN(ent), ext); - if (i > 0 && i < MAXSQSIZE) - xpm_avail[i] = 1; - } - - closedir(dir); - - return 0; -} - -void -xpm_print_avail (FILE *fp, char *ext) -{ - int i; - - fprintf(fp, _("Available `%s' sizes:\n"), ext); - for (i=1; iWM_PROTOCOLS: %s() \n", procname); - XtAugmentTranslations(w, XtParseTranslationTable(buf)); -} - -void -BoardToTop () -{ - Arg args[16]; - XtSetArg(args[0], XtNiconic, False); - XtSetValues(shellWidget, args, 1); - - XtPopup(shellWidget, XtGrabNone); /* Raise if lowered */ -} - -//--------------------------------------------------------------------------------------------------------- -// some symbol definitions to provide the proper (= XBoard) context for the code in args.h -#define XBOARD True -#define JAWS_ARGS -#define CW_USEDEFAULT (1<<31) -#define ICS_TEXT_MENU_SIZE 90 -#define DEBUG_FILE "xboard.debug" -#define SetCurrentDirectory chdir -#define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE) -#define OPTCHAR "-" -#define SEPCHAR " " - -// The option definition and parsing code common to XBoard and WinBoard is collected in this file -#include "args.h" - -// front-end part of option handling - -// [HGM] This platform-dependent table provides the location for storing the color info -extern char *crWhite, * crBlack; - -void * -colorVariable[] = { - &appData.whitePieceColor, - &appData.blackPieceColor, - &appData.lightSquareColor, - &appData.darkSquareColor, - &appData.highlightSquareColor, - &appData.premoveHighlightColor, - &appData.lowTimeWarningColor, - NULL, - NULL, - NULL, - NULL, - NULL, - &crWhite, - &crBlack, - NULL -}; - -// [HGM] font: keep a font for each square size, even non-stndard ones -#define NUM_SIZES 18 -#define MAX_SIZE 130 -Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE]; -char *fontTable[NUM_FONTS][MAX_SIZE]; - -void -ParseFont (char *name, int number) -{ // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name - int size; - if(sscanf(name, "size%d:", &size)) { - // [HGM] font: font is meant for specific boardSize (likely from settings file); - // defer processing it until we know if it matches our board size - if(size >= 0 && sizeargLoc; - switch(n) { - case 0: // CLOCK_FONT - name = appData.clockFont; - break; - case 1: // MESSAGE_FONT - name = appData.font; - break; - case 2: // COORD_FONT - name = appData.coordFont; - break; - default: - return; - } - for(i=0; iargName, i, fontTable[n][i]); -} - -void -ExportSounds () -{ // nothing to do, as the sounds are at all times represented by their text-string names already -} - -void -SaveAttribsArg (FILE *f, ArgDescriptor *ad) -{ // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though - fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]); -} - -void -SaveColor (FILE *f, ArgDescriptor *ad) -{ // in WinBoard the color is an int and has to be converted to text. In X it would be a string already? - if(colorVariable[(int)(intptr_t)ad->argLoc]) - fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]); -} - -void -SaveBoardSize (FILE *f, char *name, void *addr) -{ // wrapper to shield back-end from BoardSize & sizeInfo - fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize); -} - -void -ParseCommPortSettings (char *s) -{ // no such option in XBoard (yet) -} - -int frameX, frameY; - -void -GetActualPlacement (Widget wg, WindowPlacement *wp) -{ - XWindowAttributes winAt; - Window win, dummy; - int rx, ry; - - if(!wg) return; - - win = XtWindow(wg); - XGetWindowAttributes(xDisplay, win, &winAt); // this works, where XtGetValues on XtNx, XtNy does not! - XTranslateCoordinates (xDisplay, win, winAt.root, -winAt.border_width, -winAt.border_width, &rx, &ry, &dummy); - wp->x = rx - winAt.x; - wp->y = ry - winAt.y; - wp->height = winAt.height; - wp->width = winAt.width; - frameX = winAt.x; frameY = winAt.y; // remember to decide if windows touch -} - -void -GetWindowCoords () -{ // wrapper to shield use of window handles from back-end (make addressible by number?) - // In XBoard this will have to wait until awareness of window parameters is implemented - GetActualPlacement(shellWidget, &wpMain); - if(shellUp[EngOutDlg]) GetActualPlacement(shells[EngOutDlg], &wpEngineOutput); - if(shellUp[HistoryDlg]) GetActualPlacement(shells[HistoryDlg], &wpMoveHistory); - if(shellUp[EvalGraphDlg]) GetActualPlacement(shells[EvalGraphDlg], &wpEvalGraph); - if(shellUp[GameListDlg]) GetActualPlacement(shells[GameListDlg], &wpGameList); - if(shellUp[CommentDlg]) GetActualPlacement(shells[CommentDlg], &wpComment); - if(shellUp[TagsDlg]) GetActualPlacement(shells[TagsDlg], &wpTags); -} - -void -PrintCommPortSettings (FILE *f, char *name) -{ // This option does not exist in XBoard -} - -void -EnsureOnScreen (int *x, int *y, int minX, int minY) -{ - return; -} - -int -MainWindowUp () -{ // [HGM] args: allows testing if main window is realized from back-end - return xBoardWindow != 0; -} - -void -PopUpStartupDialog () -{ // start menu not implemented in XBoard -} - -char * -ConvertToLine (int argc, char **argv) -{ - static char line[128*1024], buf[1024]; - int i; - - line[0] = NULLCHAR; - for(i=1; imax_logical_extent.height + 5; // add borderWidth - } -#else - appData.font = FindFont(appData.font, fontPxlSize); - appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize); - appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize); - clockFontID = XLoadFont(xDisplay, appData.clockFont); - clockFontStruct = XQueryFont(xDisplay, clockFontID); - coordFontID = XLoadFont(xDisplay, appData.coordFont); - coordFontStruct = XQueryFont(xDisplay, coordFontID); - // textHeight in !NLS mode! -#endif - countFontID = coordFontID; // [HGM] holdings - countFontStruct = coordFontStruct; - - xdb = XtDatabase(xDisplay); -#if ENABLE_NLS - XrmPutLineResource(&xdb, "*international: True"); - vTo.size = sizeof(XFontSet); - vTo.addr = (XtPointer) &fontSet; - XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo); -#else - XrmPutStringResource(&xdb, "*font", appData.font); -#endif -} - -char * -PrintArg (ArgType t) -{ - char *p=""; - switch(t) { - case ArgZ: - case ArgInt: p = " N"; break; - case ArgString: p = " STR"; break; - case ArgBoolean: p = " TF"; break; - case ArgSettingsFilename: - case ArgFilename: p = " FILE"; break; - case ArgX: p = " Nx"; break; - case ArgY: p = " Ny"; break; - case ArgAttribs: p = " TEXTCOL"; break; - case ArgColor: p = " COL"; break; - case ArgFont: p = " FONT"; break; - case ArgBoardSize: p = " SIZE"; break; - case ArgFloat: p = " FLOAT"; break; - case ArgTrue: - case ArgFalse: - case ArgTwo: - case ArgNone: - case ArgCommSettings: - break; - } - return p; -} - -void -PrintOptions () -{ - char buf[MSG_SIZ]; - int len=0; - ArgDescriptor *q, *p = argDescriptors+5; - printf("\nXBoard accepts the following options:\n" - "(N = integer, TF = true or false, STR = text string, FILE = filename,\n" - " Nx, Ny = relative coordinates, COL = color, FONT = X-font spec,\n" - " SIZE = board-size spec(s)\n" - " Within parentheses are short forms, or options to set to true or false.\n" - " Persistent options (saved in the settings file) are marked with *)\n\n"); - while(p->argName) { - if(p->argType == ArgCommSettings) { p++; continue; } // XBoard has no comm port - snprintf(buf+len, MSG_SIZ, "-%s%s", p->argName, PrintArg(p->argType)); - if(p->save) strcat(buf+len, "*"); - for(q=p+1; q->argLoc == p->argLoc; q++) { - if(q->argName[0] == '-') continue; - strcat(buf+len, q == p+1 ? " (" : " "); - sprintf(buf+strlen(buf), "-%s%s", q->argName, PrintArg(q->argType)); - } - if(q != p+1) strcat(buf+len, ")"); - len = strlen(buf); - if(len > 39) len = 0, printf("%s\n", buf); else while(len < 39) buf[len++] = ' '; - p = q; - } - if(len) buf[len] = NULLCHAR, printf("%s\n", buf); -} - -int -main (int argc, char **argv) -{ - int i, clockFontPxlSize, coordFontPxlSize, fontPxlSize; - XSetWindowAttributes window_attributes; - Arg args[16]; - Dimension boardWidth, boardHeight, w, h; - char *p; - int forceMono = False; - - srandom(time(0)); // [HGM] book: make random truly random - - setbuf(stdout, NULL); - setbuf(stderr, NULL); - debugFP = stderr; - - if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) { - printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); - exit(0); - } - - if(argc > 1 && !strcmp(argv[1], "--help" )) { - PrintOptions(); - exit(0); - } - - programName = strrchr(argv[0], '/'); - if (programName == NULL) - programName = argv[0]; - else - programName++; - -#ifdef ENABLE_NLS - XtSetLanguageProc(NULL, NULL, NULL); - if (appData.debugMode) { - fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL)); - } - - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); -#endif - - appData.boardSize = ""; - InitAppData(ConvertToLine(argc, argv)); - p = getenv("HOME"); - if (p == NULL) p = "/tmp"; - i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1; - gameCopyFilename = (char*) malloc(i); - gamePasteFilename = (char*) malloc(i); - snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid()); - snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid()); - - { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string. - static char buf[MSG_SIZ]; - EscapeExpand(buf, appData.firstInitString); - appData.firstInitString = strdup(buf); - EscapeExpand(buf, appData.secondInitString); - appData.secondInitString = strdup(buf); - EscapeExpand(buf, appData.firstComputerString); - appData.firstComputerString = strdup(buf); - EscapeExpand(buf, appData.secondComputerString); - appData.secondComputerString = strdup(buf); - } - - if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) { - chessDir = "."; - } else { - if (chdir(chessDir) != 0) { - fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName); - perror(chessDir); - exit(1); - } - } - - if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) { - /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */ - if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) { - printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile); - exit(errno); - } - setbuf(debugFP, NULL); - } - - /* [HGM,HR] make sure board size is acceptable */ - if(appData.NrFiles > BOARD_FILES || - appData.NrRanks > BOARD_RANKS ) - DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2); - -#if !HIGHDRAG - /* This feature does not work; animation needs a rewrite */ - appData.highlightDragging = FALSE; -#endif - InitBackEnd1(); - - gameInfo.variant = StringToVariant(appData.variant); - InitPosition(FALSE); - - shellWidget = - XtAppInitialize(&appContext, "XBoard", shellOptions, - XtNumber(shellOptions), - &argc, argv, xboardResources, NULL, 0); - - XtGetApplicationResources(shellWidget, (XtPointer) &appData, - clientResources, XtNumber(clientResources), - NULL, 0); - - xDisplay = XtDisplay(shellWidget); - xScreen = DefaultScreen(xDisplay); - wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True); - - /* - * determine size, based on supplied or remembered -size, or screen size - */ - if (isdigit(appData.boardSize[0])) { - i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize, - &lineGap, &clockFontPxlSize, &coordFontPxlSize, - &fontPxlSize, &smallLayout, &tinyLayout); - if (i == 0) { - fprintf(stderr, _("%s: bad boardSize syntax %s\n"), - programName, appData.boardSize); - exit(2); - } - if (i < 7) { - /* Find some defaults; use the nearest known size */ - SizeDefaults *szd, *nearest; - int distance = 99999; - nearest = szd = sizeDefaults; - while (szd->name != NULL) { - if (abs(szd->squareSize - squareSize) < distance) { - nearest = szd; - distance = abs(szd->squareSize - squareSize); - if (distance == 0) break; - } - szd++; - } - if (i < 2) lineGap = nearest->lineGap; - if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize; - if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize; - if (i < 5) fontPxlSize = nearest->fontPxlSize; - if (i < 6) smallLayout = nearest->smallLayout; - if (i < 7) tinyLayout = nearest->tinyLayout; - } - } else { - SizeDefaults *szd = sizeDefaults; - if (*appData.boardSize == NULLCHAR) { - while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize || - DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) { - szd++; - } - if (szd->name == NULL) szd--; - appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings - } else { - while (szd->name != NULL && - StrCaseCmp(szd->name, appData.boardSize) != 0) szd++; - if (szd->name == NULL) { - fprintf(stderr, _("%s: unrecognized boardSize name %s\n"), - programName, appData.boardSize); - exit(2); - } - } - squareSize = szd->squareSize; - lineGap = szd->lineGap; - clockFontPxlSize = szd->clockFontPxlSize; - coordFontPxlSize = szd->coordFontPxlSize; - fontPxlSize = szd->fontPxlSize; - smallLayout = szd->smallLayout; - tinyLayout = szd->tinyLayout; - // [HGM] font: use defaults from settings file if available and not overruled - } - - defaultLineGap = lineGap; - if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; - - /* [HR] height treated separately (hacked) */ - boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap); - boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap); - - /* - * Determine what fonts to use. - */ - InitializeFonts(clockFontPxlSize, coordFontPxlSize, fontPxlSize); - - /* - * Detect if there are not enough colors available and adapt. - */ - if (DefaultDepth(xDisplay, xScreen) <= 2) { - appData.monoMode = True; - } - - forceMono = MakeColors(); - - if (forceMono) { - fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"), - programName); - appData.monoMode = True; - } - - if (appData.monoMode && appData.debugMode) { - fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"), - (unsigned long) XWhitePixel(xDisplay, xScreen), - (unsigned long) XBlackPixel(xDisplay, xScreen)); - } - - ParseIcsTextColors(); - - XtAppAddActions(appContext, boardActions, XtNumber(boardActions)); - - /* - * widget hierarchy - */ - if (tinyLayout) { - layoutName = "tinyLayout"; - } else if (smallLayout) { - layoutName = "smallLayout"; - } else { - layoutName = "normalLayout"; - } - - optList = BoardPopUp(squareSize, lineGap, (void*) -#if ENABLE_NLS - &clockFontSet); -#else - clockFontStruct); -#endif - InitDrawingHandle(optList + W_BOARD); - currBoard = &optList[W_BOARD]; - boardWidget = optList[W_BOARD].handle; - menuBarWidget = optList[W_MENU].handle; - dropMenu = optList[W_DROP].handle; - titleWidget = optList[optList[W_TITLE].type != -1 ? W_TITLE : W_SMALL].handle; - formWidget = XtParent(boardWidget); - XtSetArg(args[0], XtNbackground, &timerBackgroundPixel); - XtSetArg(args[1], XtNforeground, &timerForegroundPixel); - XtGetValues(optList[W_WHITE].handle, args, 2); - if (appData.showButtonBar) { // can't we use timer pixels for this? (Or better yet, just black & white?) - XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel); - XtSetArg(args[1], XtNforeground, &buttonForegroundPixel); - XtGetValues(optList[W_PAUSE].handle, args, 2); - } - AppendEnginesToMenu(appData.recentEngineList); - - xBoardWindow = XtWindow(boardWidget); - - // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would - // not need to go into InitDrawingSizes(). - - /* - * Create X checkmark bitmap and initialize option menu checks. - */ - ReadBitmap(&xMarkPixmap, "checkmark.bm", - checkmark_bits, checkmark_width, checkmark_height); - InitMenuMarkers(); - - /* - * Create an icon. - */ - ReadBitmap(&wIconPixmap, "icon_white.bm", - icon_white_bits, icon_white_width, icon_white_height); - ReadBitmap(&bIconPixmap, "icon_black.bm", - icon_black_bits, icon_black_width, icon_black_height); - iconPixmap = wIconPixmap; - i = 0; - XtSetArg(args[i], XtNiconPixmap, iconPixmap); i++; - XtSetValues(shellWidget, args, i); - - /* - * Create a cursor for the board widget. - */ - window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2); - XChangeWindowAttributes(xDisplay, xBoardWindow, - CWCursor, &window_attributes); - - /* - * Inhibit shell resizing. - */ - shellArgs[0].value = (XtArgVal) &w; - shellArgs[1].value = (XtArgVal) &h; - XtGetValues(shellWidget, shellArgs, 2); - shellArgs[4].value = shellArgs[2].value = w; - shellArgs[5].value = shellArgs[3].value = h; -// XtSetValues(shellWidget, &shellArgs[2], 4); - marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board - marginH = h - boardHeight; - - CatchDeleteWindow(shellWidget, "QuitProc"); - - CreateAnyPieces(); - CreateGrid(); - - if(appData.logoSize) - { // locate and read user logo - char buf[MSG_SIZ]; - snprintf(buf, MSG_SIZ, "%s/%s.png", appData.logoDir, UserName()); - ASSIGN(userLogo, buf); - } - - if (appData.animate || appData.animateDragging) - CreateAnimVars(); - - XtAugmentTranslations(formWidget, - XtParseTranslationTable(globalTranslations)); - - XtAddEventHandler(formWidget, KeyPressMask, False, - (XtEventHandler) MoveTypeInProc, NULL); - XtAddEventHandler(shellWidget, StructureNotifyMask, False, - (XtEventHandler) EventProc, NULL); - - /* [AS] Restore layout */ - if( wpMoveHistory.visible ) { - HistoryPopUp(); - } - - if( wpEvalGraph.visible ) - { - EvalGraphPopUp(); - }; - - if( wpEngineOutput.visible ) { - EngineOutputPopUp(); - } - - InitBackEnd2(); - - if (errorExitStatus == -1) { - if (appData.icsActive) { - /* We now wait until we see "login:" from the ICS before - sending the logon script (problems with timestamp otherwise) */ - /*ICSInitScript();*/ - if (appData.icsInputBox) ICSInputBoxPopUp(); - } - - #ifdef SIGWINCH - signal(SIGWINCH, TermSizeSigHandler); - #endif - signal(SIGINT, IntSigHandler); - signal(SIGTERM, IntSigHandler); - if (*appData.cmailGameName != NULLCHAR) { - signal(SIGUSR1, CmailSigHandler); - } - } - - gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes() - InitPosition(TRUE); - UpdateLogos(TRUE); -// XtSetKeyboardFocus(shellWidget, formWidget); - XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime); - - XtAppMainLoop(appContext); - if (appData.debugMode) fclose(debugFP); // [DM] debug - return 0; -} - -RETSIGTYPE -TermSizeSigHandler (int sig) -{ - update_ics_width(); -} - -RETSIGTYPE -IntSigHandler (int sig) -{ - ExitEvent(sig); -} - -RETSIGTYPE -CmailSigHandler (int sig) -{ - int dummy = 0; - int error; - - signal(SIGUSR1, SIG_IGN); /* suspend handler */ - - /* Activate call-back function CmailSigHandlerCallBack() */ - OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error); - - signal(SIGUSR1, CmailSigHandler); /* re-activate handler */ -} - -void -CmailSigHandlerCallBack (InputSourceRef isr, VOIDSTAR closure, char *message, int count, int error) -{ - BoardToTop(); - ReloadCmailMsgEvent(TRUE); /* Reload cmail msg */ -} -/**** end signal code ****/ - - -#define Abs(n) ((n)<0 ? -(n) : (n)) - -#ifdef ENABLE_NLS -char * -InsertPxlSize (char *pattern, int targetPxlSize) -{ - char *base_fnt_lst, strInt[12], *p, *q; - int alternatives, i, len, strIntLen; - - /* - * Replace the "*" (if present) in the pixel-size slot of each - * alternative with the targetPxlSize. - */ - p = pattern; - alternatives = 1; - while ((p = strchr(p, ',')) != NULL) { - alternatives++; - p++; - } - snprintf(strInt, sizeof(strInt), "%d", targetPxlSize); - strIntLen = strlen(strInt); - base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1); - - p = pattern; - q = base_fnt_lst; - while (alternatives--) { - char *comma = strchr(p, ','); - for (i=0; i<14; i++) { - char *hyphen = strchr(p, '-'); - if (!hyphen) break; - if (comma && hyphen > comma) break; - len = hyphen + 1 - p; - if (i == 7 && *p == '*' && len == 2) { - p += len; - memcpy(q, strInt, strIntLen); - q += strIntLen; - *q++ = '-'; - } else { - memcpy(q, p, len); - p += len; - q += len; - } - } - if (!comma) break; - len = comma + 1 - p; - memcpy(q, p, len); - p += len; - q += len; - } - strcpy(q, p); - - return base_fnt_lst; -} - -XFontSet -CreateFontSet (char *base_fnt_lst) -{ - XFontSet fntSet; - char **missing_list; - int missing_count; - char *def_string; - - fntSet = XCreateFontSet(xDisplay, base_fnt_lst, - &missing_list, &missing_count, &def_string); - if (appData.debugMode) { - int i, count; - XFontStruct **font_struct_list; - char **font_name_list; - fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst); - if (fntSet) { - fprintf(debugFP, " got list %s, locale %s\n", - XBaseFontNameListOfFontSet(fntSet), - XLocaleOfFontSet(fntSet)); - count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list); - for (i = 0; i < count; i++) { - fprintf(debugFP, " got charset %s\n", font_name_list[i]); - } - } - for (i = 0; i < missing_count; i++) { - fprintf(debugFP, " missing charset %s\n", missing_list[i]); - } - } - if (fntSet == NULL) { - fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst); - exit(2); - } - return fntSet; -} -#else // not ENABLE_NLS -/* - * Find a font that matches "pattern" that is as close as - * possible to the targetPxlSize. Prefer fonts that are k - * pixels smaller to fonts that are k pixels larger. The - * pattern must be in the X Consortium standard format, - * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*". - * The return value should be freed with XtFree when no - * longer needed. - */ -char * -FindFont (char *pattern, int targetPxlSize) -{ - char **fonts, *p, *best, *scalable, *scalableTail; - int i, j, nfonts, minerr, err, pxlSize; - - fonts = XListFonts(xDisplay, pattern, 999999, &nfonts); - if (nfonts < 1) { - fprintf(stderr, _("%s: no fonts match pattern %s\n"), - programName, pattern); - exit(2); - } - - best = fonts[0]; - scalable = NULL; - minerr = 999999; - for (i=0; i 0 && err < 0 && -err == minerr)) { - best = fonts[i]; - minerr = err; - } - } - } - if (scalable && Abs(minerr) > appData.fontSizeTolerance) { - /* If the error is too big and there is a scalable font, - use the scalable font. */ - int headlen = scalableTail - scalable; - p = (char *) XtMalloc(strlen(scalable) + 10); - while (isdigit(*scalableTail)) scalableTail++; - sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail); - } else { - p = (char *) XtMalloc(strlen(best) + 2); - safeStrCpy(p, best, strlen(best)+1 ); - } - if (appData.debugMode) { - fprintf(debugFP, _("resolved %s at pixel size %d\n to %s\n"), - pattern, targetPxlSize, p); - } - XFreeFontNames(fonts); - return p; -} -#endif - -void -ReadBitmap (Pixmap *pm, String name, unsigned char bits[], u_int wreq, u_int hreq) -{ - if (bits != NULL) { - *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits, - wreq, hreq); - } -} - -void -MarkMenuItem (char *menuRef, int state) -{ - MenuItem *item = MenuNameToItem(menuRef); - - if(item) { - Arg args[2]; - XtSetArg(args[0], XtNleftBitmap, state ? xMarkPixmap : None); - XtSetValues(item->handle, args, 1); - } -} - -void -EnableNamedMenuItem (char *menuRef, int state) -{ - MenuItem *item = MenuNameToItem(menuRef); - - if(item) XtSetSensitive(item->handle, state); -} - -void -EnableButtonBar (int state) -{ - XtSetSensitive(optList[W_BUTTON].handle, state); -} - - -void -SetMenuEnables (Enables *enab) -{ - while (enab->name != NULL) { - EnableNamedMenuItem(enab->name, enab->value); - enab++; - } -} - -void -KeyBindingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // [HGM] new method of key binding: specify MenuItem(FlipView) in stead of FlipViewProc in translation string - MenuItem *item; - if(*nprms == 0) return; - item = MenuNameToItem(prms[0]); - if(item) ((MenuProc *) item->proc) (); -} - -static void -MenuEngineSelect (Widget w, caddr_t addr, caddr_t index) -{ - RecentEngineEvent((int) (intptr_t) addr); -} - -void -AppendMenuItem (char *msg, int n) -{ - CreateMenuItem((Widget) optList[W_ENGIN].textValue, msg, (XtCallbackProc) MenuEngineSelect, n); -} - -void -SetupDropMenu () -{ - int i, j, count; - char label[32]; - Arg args[16]; - Widget entry; - char* p; - - for (i=0; i 1.) f = 1.; else if(f < 0.) f = 0.; - return f; -} - -static WindowPlacement wpNew; - -void -CoDrag (Widget sh, WindowPlacement *wp) -{ - Arg args[16]; - int j=0, touch=0, fudge = 2; - GetActualPlacement(sh, wp); - if(abs(wpMain.x + wpMain.width + 2*frameX - wp->x) < fudge) touch = 1; else // right touch - if(abs(wp->x + wp->width + 2*frameX - wpMain.x) < fudge) touch = 2; else // left touch - if(abs(wpMain.y + wpMain.height + frameX + frameY - wp->y) < fudge) touch = 3; else // bottom touch - if(abs(wp->y + wp->height + frameX + frameY - wpMain.y) < fudge) touch = 4; // top touch - if(!touch ) return; // only windows that touch co-move - if(touch < 3 && wpNew.height != wpMain.height) { // left or right and height changed - int heightInc = wpNew.height - wpMain.height; - double fracTop = Fraction(wp->y, wpMain.y, wpMain.y + wpMain.height + frameX + frameY); - double fracBot = Fraction(wp->y + wp->height + frameX + frameY + 1, wpMain.y, wpMain.y + wpMain.height + frameX + frameY); - wp->y += fracTop * heightInc; - heightInc = (int) (fracBot * heightInc) - (int) (fracTop * heightInc); - if(heightInc) XtSetArg(args[j], XtNheight, wp->height + heightInc), j++; - } else if(touch > 2 && wpNew.width != wpMain.width) { // top or bottom and width changed - int widthInc = wpNew.width - wpMain.width; - double fracLeft = Fraction(wp->x, wpMain.x, wpMain.x + wpMain.width + 2*frameX); - double fracRght = Fraction(wp->x + wp->width + 2*frameX + 1, wpMain.x, wpMain.x + wpMain.width + 2*frameX); - wp->y += fracLeft * widthInc; - widthInc = (int) (fracRght * widthInc) - (int) (fracLeft * widthInc); - if(widthInc) XtSetArg(args[j], XtNwidth, wp->width + widthInc), j++; - } - wp->x += wpNew.x - wpMain.x; - wp->y += wpNew.y - wpMain.y; - if(touch == 1) wp->x += wpNew.width - wpMain.width; else - if(touch == 3) wp->y += wpNew.height - wpMain.height; - XtSetArg(args[j], XtNx, wp->x); j++; - XtSetArg(args[j], XtNy, wp->y); j++; - XtSetValues(sh, args, j); -} - -void -ReSize (WindowPlacement *wp) -{ - int sqx, sqy, w, h; - if(wp->width == wpMain.width && wp->height == wpMain.height) return; // not sized - sqx = (wp->width - lineGap - marginW) / BOARD_WIDTH - lineGap; - sqy = (wp->height - lineGap - marginH) / BOARD_HEIGHT - lineGap; - if(sqy < sqx) sqx = sqy; - if(sqx != squareSize) { - squareSize = sqx; // adopt new square size - CreatePNGPieces(); // make newly scaled pieces - InitDrawingSizes(0, 0); // creates grid etc. - } else ResizeBoardWindow(BOARD_WIDTH * (squareSize + lineGap) + lineGap, BOARD_HEIGHT * (squareSize + lineGap) + lineGap, 0); - w = BOARD_WIDTH * (squareSize + lineGap) + lineGap; - h = BOARD_HEIGHT * (squareSize + lineGap) + lineGap; - if(optList[W_BOARD].max > w) optList[W_BOARD].max = w; - if(optList[W_BOARD].value > h) optList[W_BOARD].value = h; -} - -static XtIntervalId delayedDragID = 0; - -void -DragProc () -{ - static int busy; - if(busy) return; - - busy = 1; - GetActualPlacement(shellWidget, &wpNew); - if(wpNew.x == wpMain.x && wpNew.y == wpMain.y && // not moved - wpNew.width == wpMain.width && wpNew.height == wpMain.height) { // not sized - busy = 0; return; // false alarm - } - ReSize(&wpNew); - if(shellUp[EngOutDlg]) CoDrag(shells[EngOutDlg], &wpEngineOutput); - if(shellUp[HistoryDlg]) CoDrag(shells[HistoryDlg], &wpMoveHistory); - if(shellUp[EvalGraphDlg]) CoDrag(shells[EvalGraphDlg], &wpEvalGraph); - if(shellUp[GameListDlg]) CoDrag(shells[GameListDlg], &wpGameList); - wpMain = wpNew; - DrawPosition(True, NULL); - delayedDragID = 0; // now drag executed, make sure next DelayedDrag will not cancel timer event (which could now be used by other) - busy = 0; -} - - -void -DelayedDrag () -{ - if(delayedDragID) XtRemoveTimeOut(delayedDragID); // cancel pending - delayedDragID = - XtAppAddTimeOut(appContext, 200, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later -} - -void -EventProc (Widget widget, caddr_t unused, XEvent *event) -{ - if(XtIsRealized(widget) && event->type == ConfigureNotify || appData.useStickyWindows) - DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other -} - -/* - * event handler for redrawing the board - */ -void -DrawPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - DrawPosition(True, NULL); -} - - -void -HandlePV (Widget w, XEvent * event, String * params, Cardinal * nParams) -{ // [HGM] pv: walk PV - MovePV(event->xmotion.x, event->xmotion.y, lineGap + BOARD_HEIGHT * (squareSize + lineGap)); -} - -static int savedIndex; /* gross that this is global */ - -void -CommentClick (Widget w, XEvent * event, String * params, Cardinal * nParams) -{ - String val; - XawTextPosition index, dummy; - Arg arg; - - XawTextGetSelectionPos(w, &index, &dummy); - XtSetArg(arg, XtNstring, &val); - XtGetValues(w, &arg, 1); - ReplaceComment(savedIndex, val); - if(savedIndex != currentMove) ToNrEvent(savedIndex); - LoadVariation( index, val ); // [HGM] also does the actual moving to it, now -} - -void -EditCommentPopUp (int index, char *title, char *text) -{ - savedIndex = index; - if (text == NULL) text = ""; - NewCommentPopup(title, text, index); -} - -void -CommentPopUp (char *title, char *text) -{ - savedIndex = currentMove; // [HGM] vari - NewCommentPopup(title, text, currentMove); -} - -void -CommentPopDown () -{ - PopDown(CommentDlg); -} - - -/* Disable all user input other than deleting the window */ -static int frozen = 0; - -void -FreezeUI () -{ - if (frozen) return; - /* Grab by a widget that doesn't accept input */ - XtAddGrab(optList[W_MESSG].handle, TRUE, FALSE); - frozen = 1; -} - -/* Undo a FreezeUI */ -void -ThawUI () -{ - if (!frozen) return; - XtRemoveGrab(optList[W_MESSG].handle); - frozen = 0; -} - -void -ModeHighlight () -{ - Arg args[16]; - static int oldPausing = FALSE; - static GameMode oldmode = (GameMode) -1; - char *wname; - - if (!boardWidget || !XtIsRealized(boardWidget)) return; - - if (pausing != oldPausing) { - oldPausing = pausing; - MarkMenuItem("Mode.Pause", pausing); - - if (appData.showButtonBar) { - /* Always toggle, don't set. Previous code messes up when - invoked while the button is pressed, as releasing it - toggles the state again. */ - { - Pixel oldbg, oldfg; - XtSetArg(args[0], XtNbackground, &oldbg); - XtSetArg(args[1], XtNforeground, &oldfg); - XtGetValues(optList[W_PAUSE].handle, - args, 2); - XtSetArg(args[0], XtNbackground, oldfg); - XtSetArg(args[1], XtNforeground, oldbg); - } - XtSetValues(optList[W_PAUSE].handle, args, 2); - } - } - - wname = ModeToWidgetName(oldmode); - if (wname != NULL) { - MarkMenuItem(wname, False); - } - wname = ModeToWidgetName(gameMode); - if (wname != NULL) { - MarkMenuItem(wname, True); - } - oldmode = gameMode; - MarkMenuItem("Mode.MachineMatch", matchMode && matchGame < appData.matchGames); - - /* Maybe all the enables should be handled here, not just this one */ - EnableNamedMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile); - - DisplayLogos(&optList[W_WHITE-1], &optList[W_BLACK+1]); -} - - -/* - * Button/menu procedures - */ - -/* this variable is shared between CopyPositionProc and SendPositionSelection */ -char *selected_fen_position=NULL; - -Boolean -SendPositionSelection (Widget w, Atom *selection, Atom *target, - Atom *type_return, XtPointer *value_return, - unsigned long *length_return, int *format_return) -{ - char *selection_tmp; - -// if (!selected_fen_position) return False; /* should never happen */ - if (*target == XA_STRING || *target == XA_UTF8_STRING(xDisplay)){ - if (!selected_fen_position) { // since it never happens, we use it for indicating a game is being sent - FILE* f = fopen(gameCopyFilename, "r"); // This code, taken from SendGameSelection, now merges the two - long len; - size_t count; - if (f == NULL) return False; - fseek(f, 0, 2); - len = ftell(f); - rewind(f); - selection_tmp = XtMalloc(len + 1); - count = fread(selection_tmp, 1, len, f); - fclose(f); - if (len != count) { - XtFree(selection_tmp); - return False; - } - selection_tmp[len] = NULLCHAR; - } else { - /* note: since no XtSelectionDoneProc was registered, Xt will - * automatically call XtFree on the value returned. So have to - * make a copy of it allocated with XtMalloc */ - selection_tmp= XtMalloc(strlen(selected_fen_position)+16); - safeStrCpy(selection_tmp, selected_fen_position, strlen(selected_fen_position)+16 ); - } - - *value_return=selection_tmp; - *length_return=strlen(selection_tmp); - *type_return=*target; - *format_return = 8; /* bits per byte */ - return True; - } else if (*target == XA_TARGETS(xDisplay)) { - Atom *targets_tmp = (Atom *) XtMalloc(2 * sizeof(Atom)); - targets_tmp[0] = XA_UTF8_STRING(xDisplay); - targets_tmp[1] = XA_STRING; - *value_return = targets_tmp; - *type_return = XA_ATOM; - *length_return = 2; -#if 0 - // This code leads to a read of value_return out of bounds on 64-bit systems. - // Other code which I have seen always sets *format_return to 32 independent of - // sizeof(Atom) without adjusting *length_return. For instance see TextConvertSelection() - // at http://cgit.freedesktop.org/xorg/lib/libXaw/tree/src/Text.c -- BJ - *format_return = 8 * sizeof(Atom); - if (*format_return > 32) { - *length_return *= *format_return / 32; - *format_return = 32; - } -#else - *format_return = 32; -#endif - return True; - } else { - return False; - } -} - -/* note: when called from menu all parameters are NULL, so no clue what the - * Widget which was clicked on was, or what the click event was - */ -void -CopySomething (char *src) -{ - selected_fen_position = src; - /* - * Set both PRIMARY (the selection) and CLIPBOARD, since we don't - * have a notion of a position that is selected but not copied. - * See http://www.freedesktop.org/wiki/Specifications/ClipboardsWiki - */ - XtOwnSelection(menuBarWidget, XA_PRIMARY, - CurrentTime, - SendPositionSelection, - NULL/* lose_ownership_proc */ , - NULL/* transfer_done_proc */); - XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay), - CurrentTime, - SendPositionSelection, - NULL/* lose_ownership_proc */ , - NULL/* transfer_done_proc */); -} - -/* function called when the data to Paste is ready */ -static void -PastePositionCB (Widget w, XtPointer client_data, Atom *selection, - Atom *type, XtPointer value, unsigned long *len, int *format) -{ - char *fenstr=value; - if (value==NULL || *len==0) return; /* nothing had been selected to copy */ - fenstr[*len]='\0'; /* normally this string is terminated, but be safe */ - EditPositionPasteFEN(fenstr); - XtFree(value); -} - -/* called when Paste Position button is pressed, - * all parameters will be NULL */ -void -PastePositionProc () -{ - XtGetSelectionValue(menuBarWidget, - appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING, - /* (XtSelectionCallbackProc) */ PastePositionCB, - NULL, /* client_data passed to PastePositionCB */ - - /* better to use the time field from the event that triggered the - * call to this function, but that isn't trivial to get - */ - CurrentTime - ); - return; -} - -/* note: when called from menu all parameters are NULL, so no clue what the - * Widget which was clicked on was, or what the click event was - */ -/* function called when the data to Paste is ready */ -static void -PasteGameCB (Widget w, XtPointer client_data, Atom *selection, - Atom *type, XtPointer value, unsigned long *len, int *format) -{ - FILE* f; - if (value == NULL || *len == 0) { - return; /* nothing had been selected to copy */ - } - f = fopen(gamePasteFilename, "w"); - if (f == NULL) { - DisplayError(_("Can't open temp file"), errno); - return; - } - fwrite(value, 1, *len, f); - fclose(f); - XtFree(value); - LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE); -} - -/* called when Paste Game button is pressed, - * all parameters will be NULL */ -void -PasteGameProc () -{ - XtGetSelectionValue(menuBarWidget, - appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING, - /* (XtSelectionCallbackProc) */ PasteGameCB, - NULL, /* client_data passed to PasteGameCB */ - - /* better to use the time field from the event that triggered the - * call to this function, but that isn't trivial to get - */ - CurrentTime - ); - return; -} - - -void -QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - QuitProc(); -} - -int -ShiftKeys () -{ // bassic primitive for determining if modifier keys are pressed - long int codes[] = { XK_Meta_L, XK_Meta_R, XK_Control_L, XK_Control_R, XK_Shift_L, XK_Shift_R }; - char keys[32]; - int i,j, k=0; - XQueryKeymap(xDisplay,keys); - for(i=0; i<6; i++) { - k <<= 1; - j = XKeysymToKeycode(xDisplay, codes[i]); - k += ( (keys[j>>3]&1<<(j&7)) != 0 ); - } - return k; -} - -static void -MoveTypeInProc (Widget widget, caddr_t unused, XEvent *event) -{ - char buf[10]; - KeySym sym; - int n = XLookupString(&(event->xkey), buf, 10, &sym, NULL); - if ( n == 1 && *buf >= 32 // printable - && !(ShiftKeys() & 0x3C) // no Alt, Ctrl - ) BoxAutoPopUp (buf); -} - -static void -UpKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // [HGM] input: let up-arrow recall previous line from history - IcsKey(1); -} - -static void -DownKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // [HGM] input: let down-arrow recall next line from history - IcsKey(-1); -} - -static void -EnterKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - IcsKey(0); -} - -void -TempBackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - if (!TempBackwardActive) { - TempBackwardActive = True; - BackwardEvent(); - } -} - -void -TempForwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - /* Check to see if triggered by a key release event for a repeating key. - * If so the next queued event will be a key press of the same key at the same time */ - if (XEventsQueued(xDisplay, QueuedAfterReading)) { - XEvent next; - XPeekEvent(xDisplay, &next); - if (next.type == KeyPress && next.xkey.time == event->xkey.time && - next.xkey.keycode == event->xkey.keycode) - return; - } - ForwardEvent(); - TempBackwardActive = False; -} - -void -ManInner (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // called as key binding - char buf[MSG_SIZ]; - String name; - if (nprms && *nprms > 0) - name = prms[0]; - else - name = "xboard"; - snprintf(buf, sizeof(buf), "xterm -e man %s &", name); - system(buf); -} - -void -ManProc () -{ // called from menu - ManInner(NULL, NULL, NULL, NULL); -} - -void -SetWindowTitle (char *text, char *title, char *icon) -{ - Arg args[16]; - int i; - if (appData.titleInWindow) { - i = 0; - XtSetArg(args[i], XtNlabel, text); i++; - XtSetValues(titleWidget, args, i); - } - i = 0; - XtSetArg(args[i], XtNiconName, (XtArgVal) icon); i++; - XtSetArg(args[i], XtNtitle, (XtArgVal) title); i++; - XtSetValues(shellWidget, args, i); - XSync(xDisplay, False); -} - - -static int -NullXErrorCheck (Display *dpy, XErrorEvent *error_event) -{ - return 0; -} - -void -DisplayIcsInteractionTitle (String message) -{ - if (oldICSInteractionTitle == NULL) { - /* Magic to find the old window title, adapted from vim */ - char *wina = getenv("WINDOWID"); - if (wina != NULL) { - Window win = (Window) atoi(wina); - Window root, parent, *children; - unsigned int nchildren; - int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck); - for (;;) { - if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break; - if (!XQueryTree(xDisplay, win, &root, &parent, - &children, &nchildren)) break; - if (children) XFree((void *)children); - if (parent == root || parent == 0) break; - win = parent; - } - XSetErrorHandler(oldHandler); - } - if (oldICSInteractionTitle == NULL) { - oldICSInteractionTitle = "xterm"; - } - } - printf("\033]0;%s\007", message); - fflush(stdout); -} - - -XtIntervalId delayedEventTimerXID = 0; -DelayedEventCallback delayedEventCallback = 0; - -void -FireDelayedEvent () -{ - delayedEventTimerXID = 0; - delayedEventCallback(); -} - -void -ScheduleDelayedEvent (DelayedEventCallback cb, long millisec) -{ - if(delayedEventTimerXID && delayedEventCallback == cb) - // [HGM] alive: replace, rather than add or flush identical event - XtRemoveTimeOut(delayedEventTimerXID); - delayedEventCallback = cb; - delayedEventTimerXID = - XtAppAddTimeOut(appContext, millisec, - (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0); -} - -DelayedEventCallback -GetDelayedEvent () -{ - if (delayedEventTimerXID) { - return delayedEventCallback; - } else { - return NULL; - } -} - -void -CancelDelayedEvent () -{ - if (delayedEventTimerXID) { - XtRemoveTimeOut(delayedEventTimerXID); - delayedEventTimerXID = 0; - } -} - -XtIntervalId loadGameTimerXID = 0; - -int -LoadGameTimerRunning () -{ - return loadGameTimerXID != 0; -} - -int -StopLoadGameTimer () -{ - if (loadGameTimerXID != 0) { - XtRemoveTimeOut(loadGameTimerXID); - loadGameTimerXID = 0; - return TRUE; - } else { - return FALSE; - } -} - -void -LoadGameTimerCallback (XtPointer arg, XtIntervalId *id) -{ - loadGameTimerXID = 0; - AutoPlayGameLoop(); -} - -void -StartLoadGameTimer (long millisec) -{ - loadGameTimerXID = - XtAppAddTimeOut(appContext, millisec, - (XtTimerCallbackProc) LoadGameTimerCallback, - (XtPointer) 0); -} - -XtIntervalId analysisClockXID = 0; - -void -AnalysisClockCallback (XtPointer arg, XtIntervalId *id) -{ - if (gameMode == AnalyzeMode || gameMode == AnalyzeFile - || appData.icsEngineAnalyze) { // [DM] - AnalysisPeriodicEvent(0); - StartAnalysisClock(); - } -} - -void -StartAnalysisClock () -{ - analysisClockXID = - XtAppAddTimeOut(appContext, 2000, - (XtTimerCallbackProc) AnalysisClockCallback, - (XtPointer) 0); -} - -XtIntervalId clockTimerXID = 0; - -int -ClockTimerRunning () -{ - return clockTimerXID != 0; -} - -int -StopClockTimer () -{ - if (clockTimerXID != 0) { - XtRemoveTimeOut(clockTimerXID); - clockTimerXID = 0; - return TRUE; - } else { - return FALSE; - } -} - -void -ClockTimerCallback (XtPointer arg, XtIntervalId *id) -{ - clockTimerXID = 0; - DecrementClocks(); -} - -void -StartClockTimer (long millisec) -{ - clockTimerXID = - XtAppAddTimeOut(appContext, millisec, - (XtTimerCallbackProc) ClockTimerCallback, - (XtPointer) 0); -} - -void -DisplayTimerLabel (Option *opt, char *color, long timer, int highlight) -{ - char buf[MSG_SIZ]; - Arg args[16]; - Widget w = (Widget) opt->handle; - - /* check for low time warning */ - Pixel foregroundOrWarningColor = timerForegroundPixel; - - if (timer > 0 && - appData.lowTimeWarning && - (timer / 1000) < appData.icsAlarmTime) - foregroundOrWarningColor = lowTimeWarningColor; - - if (appData.clockMode) { - snprintf(buf, MSG_SIZ, "%s:%s%s", color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer)); - XtSetArg(args[0], XtNlabel, buf); - } else { - snprintf(buf, MSG_SIZ, "%s ", color); - XtSetArg(args[0], XtNlabel, buf); - } - - if (highlight) { - - XtSetArg(args[1], XtNbackground, foregroundOrWarningColor); - XtSetArg(args[2], XtNforeground, timerBackgroundPixel); - } else { - XtSetArg(args[1], XtNbackground, timerBackgroundPixel); - XtSetArg(args[2], XtNforeground, foregroundOrWarningColor); - } - - XtSetValues(w, args, 3); -} - -static Pixmap *clockIcons[] = { &wIconPixmap, &bIconPixmap }; - -void -SetClockIcon (int color) -{ - Arg args[16]; - Pixmap pm = *clockIcons[color]; - if (iconPixmap != pm) { - iconPixmap = pm; - XtSetArg(args[0], XtNiconPixmap, iconPixmap); - XtSetValues(shellWidget, args, 1); - } -} - -void -DoInputCallback (caddr_t closure, int *source, XtInputId *xid) -{ - InputSource *is = (InputSource *) closure; - int count; - int error; - char *p, *q; - - if (is->lineByLine) { - count = read(is->fd, is->unused, - INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf)); - if (count <= 0) { - (is->func)(is, is->closure, is->buf, count, count ? errno : 0); - return; - } - is->unused += count; - p = is->buf; - while (p < is->unused) { - q = memchr(p, '\n', is->unused - p); - if (q == NULL) break; - q++; - (is->func)(is, is->closure, p, q - p, 0); - p = q; - } - q = is->buf; - while (p < is->unused) { - *q++ = *p++; - } - is->unused = q; - } else { - count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE); - if (count == -1) - error = errno; - else - error = 0; - (is->func)(is, is->closure, is->buf, count, error); - } -} - -InputSourceRef -AddInputSource (ProcRef pr, int lineByLine, InputCallback func, VOIDSTAR closure) -{ - InputSource *is; - ChildProc *cp = (ChildProc *) pr; - - is = (InputSource *) calloc(1, sizeof(InputSource)); - is->lineByLine = lineByLine; - is->func = func; - if (pr == NoProc) { - is->kind = CPReal; - is->fd = fileno(stdin); - } else { - is->kind = cp->kind; - is->fd = cp->fdFrom; - } - if (lineByLine) { - is->unused = is->buf; - } - - is->xid = XtAppAddInput(appContext, is->fd, - (XtPointer) (XtInputReadMask), - (XtInputCallbackProc) DoInputCallback, - (XtPointer) is); - is->closure = closure; - return (InputSourceRef) is; -} - -void -RemoveInputSource (InputSourceRef isr) -{ - InputSource *is = (InputSource *) isr; - - if (is->xid == 0) return; - XtRemoveInput(is->xid); - is->xid = 0; -} - -#ifndef HAVE_USLEEP - -static Boolean frameWaiting; - -static RETSIGTYPE -FrameAlarm (int sig) -{ - frameWaiting = False; - /* In case System-V style signals. Needed?? */ - signal(SIGALRM, FrameAlarm); -} - -void -FrameDelay (int time) -{ - struct itimerval delay; - - XSync(xDisplay, False); - - if (time > 0) { - frameWaiting = True; - signal(SIGALRM, FrameAlarm); - delay.it_interval.tv_sec = - delay.it_value.tv_sec = time / 1000; - delay.it_interval.tv_usec = - delay.it_value.tv_usec = (time % 1000) * 1000; - setitimer(ITIMER_REAL, &delay, NULL); - while (frameWaiting) pause(); - delay.it_interval.tv_sec = delay.it_value.tv_sec = 0; - delay.it_interval.tv_usec = delay.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &delay, NULL); - } -} - -#else - -void -FrameDelay (int time) -{ - XSync(xDisplay, False); - if (time > 0) - usleep(time * 1000); -} - -#endif - -static void -LoadLogo (ChessProgramState *cps, int n, Boolean ics) -{ - char buf[MSG_SIZ], *logoName = buf; - if(appData.logo[n][0]) { - logoName = appData.logo[n]; - } else if(appData.autoLogo) { - if(ics) { // [HGM] logo: in ICS mode second can be used for ICS - sprintf(buf, "%s/%s.png", appData.logoDir, appData.icsHost); - } else if(appData.directory[n] && appData.directory[n][0]) { - sprintf(buf, "%s/%s.png", appData.logoDir, cps->tidy); - } - } - if(logoName[0]) - { ASSIGN(cps->programLogo, logoName); } -} - -void -UpdateLogos (int displ) -{ - if(optList[W_WHITE-1].handle == NULL) return; - LoadLogo(&first, 0, 0); - LoadLogo(&second, 1, appData.icsActive); - if(displ) DisplayLogos(&optList[W_WHITE-1], &optList[W_BLACK+1]); - return; -} - diff --git a/xboard.h b/xboard.h deleted file mode 100644 index 5a6587e..0000000 --- a/xboard.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * xboard.h -- Parameter definitions for X front end - * - * Copyright 1991 by Digital Equipment Corporation, Maynard, - * Massachusetts. - * - * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * - * The following terms apply to Digital Equipment Corporation's copyright - * interest in XBoard: - * ------------------------------------------------------------------------ - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of Digital not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * - * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING - * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL - * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR - * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * ------------------------------------------------------------------------ - * - * The following terms apply to the enhanced version of XBoard - * distributed by the Free Software Foundation: - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#include - -#define ICS_LOGON ".icsrc" -#define MANPAGE "xboard.6" -#if ENABLE_NLS -#define CLOCK_FONT_NAME \ - "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*," \ - "-misc-fixed-bold-r-normal--*-*-*-*-*-*-*-*," \ - "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" -#define COORD_FONT_NAME \ - "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*," \ - "-misc-fixed-bold-r-normal--*-*-*-*-*-*-*-*," \ - "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" -#define DEFAULT_FONT_NAME \ - "-*-helvetica-medium-r-normal--*-*-*-*-*-*-*-*," \ - "-misc-fixed-medium-r-normal--*-*-*-*-*-*-*-*," \ - "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" -#else -#define CLOCK_FONT_NAME "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*" -#define COORD_FONT_NAME "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*" -#define DEFAULT_FONT_NAME "-*-helvetica-medium-r-normal--*-*-*-*-*-*-*-*" -#endif -#define COLOR_SHOUT "green" -#define COLOR_SSHOUT "green,black,1" -#define COLOR_CHANNEL1 "cyan" -#define COLOR_CHANNEL "cyan,black,1" -#define COLOR_KIBITZ "magenta,black,1" -#define COLOR_TELL "yellow,black,1" -#define COLOR_CHALLENGE "red,black,1" -#define COLOR_REQUEST "red" -#define COLOR_SEEK "blue" -#define COLOR_NORMAL "default" -#define COLOR_LOWTIMEWARNING "red" - -typedef struct { - char *name; - int squareSize; - int lineGap; - int clockFontPxlSize; - int coordFontPxlSize; - int fontPxlSize; - int smallLayout; - int tinyLayout; - int minScreenSize; -} SizeDefaults; - -#define SIZE_DEFAULTS \ -{ { "Titanic", 129, 4, 34, 14, 14, 0, 0, 1200 }, \ - { "Colossal", 116, 4, 34, 14, 14, 0, 0, 1200 }, \ - { "Giant", 108, 3, 34, 14, 14, 0, 0, 1024 }, \ - { "Huge", 95, 3, 34, 14, 14, 0, 0, 1024 }, \ - { "Big", 87, 3, 34, 14, 14, 0, 0, 864 }, \ - { "Large", 80, 3, 34, 14, 14, 0, 0, 864 }, \ - { "Bulky", 72, 3, 34, 12, 14, 0, 0, 864 }, \ - { "Medium", 64, 3, 34, 12, 14, 1, 0, 768 }, \ - { "Moderate", 58, 3, 34, 12, 14, 1, 0, 768 }, \ - { "Average", 54, 2, 30, 11, 12, 1, 0, 600 }, \ - { "Middling", 49, 2, 24, 10, 12, 1, 0, 600 }, \ - { "Mediocre", 45, 2, 20, 10, 12, 1, 0, 600 }, \ - { "Small", 40, 2, 20, 10, 12, 1, 0, 480 }, \ - { "Slim", 37, 2, 20, 10, 12, 1, 0, 480 }, \ - { "Petite", 33, 1, 15, 9, 11, 1, 0, 480 }, \ - { "Dinky", 29, 1, 15, 9, 11, 1, 0, 480 }, \ - { "Teeny", 25, 1, 12, 8, 11, 1, 1, 480 }, \ - { "Tiny", 21, 1, 12, 8, 11, 1, 1, 0 }, \ - { NULL, 0, 0, 0, 0, 0, 0, 0, 0 } } - -#define BORDER_X_OFFSET 3 -#define BORDER_Y_OFFSET 27 -#define FIRST_CHESS_PROGRAM "fairymax" -#define SECOND_CHESS_PROGRAM "fairymax" -#define FIRST_DIRECTORY "." -#define SECOND_DIRECTORY "." -#define SOUND_BELL "" -#define ICS_NAMES "" -#define FCP_NAMES "" -#define SCP_NAMES "" -#define ICS_TEXT_MENU_DEFAULT "" -#define SETTINGS_FILE SYSCONFDIR"/xboard.conf" -#define COLOR_BKGD "white" - -void NewTagsPopup P((char *text, char *msg)); -int AppendText P((Option *opt, char *s)); -void NewCommentPopup P((char *title, char *text, int index)); -void CatchDeleteWindow(Widget w, String procname); -void GenericPopDown P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void InitDrawingSizes P((int i, int j)); -void SendToICS P((char *buf)); -void SendToProgram P((char *message, ChessProgramState *cps)); -void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b); // from xoptions.c -void TypeInProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -Widget CreateMenuItem P((Widget menu, char *msg, XtCallbackProc CB, int n)); -void WheelProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void TabProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void GenericMenu P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); - -// from xengineoutput.c -void SelectPV P((Widget w, XEvent * event, String * params, Cardinal * nParams)); -void StopPV P((Widget w, XEvent * event, String * params, Cardinal * nParams)); - -extern char memoTranslations[]; - - -extern Widget shells[]; -extern int dialogError; -extern Widget formWidget, shellWidget, boardWidget, menuBarWidget; -extern Display *xDisplay; -extern Window xBoardWindow; -extern int squareSize; -extern Pixmap xMarkPixmap, wIconPixmap, bIconPixmap; -extern char *layoutName; -extern Pixel timerForegroundPixel, timerBackgroundPixel, dialogColor, buttonColor; -extern int searchTime; -extern Atom wm_delete_window; -extern int squareSize, lineGap, defaultLineGap, useImages, useImageSqs; -extern int startedFromPositionFile; -extern char *icsTextMenuString; -extern char ICSInputTranslations[]; -extern char *selected_fen_position; -extern GC coordGC; -extern Dimension textHeight; // of message widget in board window - - -#define TOPLEVEL 1 /* preference item; 1 = make popup windows toplevel */ - diff --git a/xedittags.c b/xedittags.c deleted file mode 100644 index d27aca3..0000000 --- a/xedittags.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * xedittags.c -- Tags edit window, part of X front end for XBoard - * - * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#include "config.h" - -#include -#include -#include -#include - -#if STDC_HEADERS -# include -# include -#else /* not STDC_HEADERS */ -extern char *getenv(); -# if HAVE_STRING_H -# include -# else /* not HAVE_STRING_H */ -# include -# endif /* not HAVE_STRING_H */ -#endif /* not STDC_HEADERS */ - -#if HAVE_UNISTD_H -# include -#endif - -#include -#include -#include -#include -#if USE_XAW3D -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "common.h" -#include "frontend.h" -#include "backend.h" -#include "xboard.h" -#include "xedittags.h" -#include "dialogs.h" -#include "gettext.h" - -#ifdef ENABLE_NLS -# define _(s) gettext (s) -# define N_(s) gettext_noop (s) -#else -# define _(s) (s) -# define N_(s) s -#endif - -Position tagsX = -1, tagsY = -1; - -void -TagsPopUp (char *tags, char *msg) -{ - NewTagsPopup(tags, cmailMsgLoaded ? msg : NULL); -} - - -void -EditTagsPopUp (char *tags, char **dest) -{ - NewTagsPopup(tags, NULL); -} - -void -TagsPopDown() -{ - PopDown(TagsDlg); - bookUp = False; -} - -void -EditTagsProc () -{ - if (bookUp || !PopDown(TagsDlg)) EditTagsEvent(); -} diff --git a/xedittags.h b/xedittags.h deleted file mode 100644 index 6245bfd..0000000 --- a/xedittags.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * xedittags.h - * - * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#ifndef XB_XEDITTAGS -#define XB_XEDITTAGS - -void EditTagsProc P((void)); - -extern Widget editTagsShell, tagsShell; -#endif diff --git a/xengineoutput.c b/xengineoutput.c deleted file mode 100644 index 78269b8..0000000 --- a/xengineoutput.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Engine output (PV) - * - * Author: Alessandro Scotti (Dec 2005) - * - * Copyright 2005 Alessandro Scotti - * - * Enhancements Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - * ------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#include "config.h" - -#include -#include -#include -#include - -#if STDC_HEADERS -# include -# include -#else /* not STDC_HEADERS */ -extern char *getenv(); -# if HAVE_STRING_H -# include -# else /* not HAVE_STRING_H */ -# include -# endif /* not HAVE_STRING_H */ -#endif /* not STDC_HEADERS */ - -#if HAVE_UNISTD_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "frontend.h" -#include "backend.h" -#include "dialogs.h" -#include "xboard.h" -#include "engineoutput.h" -#include "gettext.h" - -#ifdef ENABLE_NLS -# define _(s) gettext (s) -# define N_(s) gettext_noop (s) -#else -# define _(s) (s) -# define N_(s) s -#endif - -#include - -// [HGM] pixmaps of some ICONS used in the engine-outut window -#include "pixmaps/WHITE_14.xpm" -#include "pixmaps/BLACK_14.xpm" -#include "pixmaps/CLEAR_14.xpm" -#include "pixmaps/UNKNOWN_14.xpm" -#include "pixmaps/THINKING_14.xpm" -#include "pixmaps/PONDER_14.xpm" -#include "pixmaps/ANALYZING_14.xpm" - - -/* Module variables */ -static int currentPV, highTextStart[2], highTextEnd[2]; -static Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle -static Widget memoWidget; - - -static void -ReadIcon (char *pixData[], int iconNr, Widget w) -{ - int r; - - if ((r=XpmCreatePixmapFromData(xDisplay, XtWindow(w), - pixData, - &(icons[iconNr]), - NULL, NULL /*&attr*/)) != 0) { - fprintf(stderr, _("Error %d loading icon image\n"), r); - exit(1); - } -} - -void -InitEngineOutput (Option *opt, Option *memo2) -{ // front-end, because it must have access to the pixmaps - Widget w = opt->handle; - memoWidget = memo2->handle; - - ReadIcon(WHITE_14, nColorWhite, w); - ReadIcon(BLACK_14, nColorBlack, w); - ReadIcon(UNKNOWN_14, nColorUnknown, w); - - ReadIcon(CLEAR_14, nClear, w); - ReadIcon(PONDER_14, nPondering, w); - ReadIcon(THINK_14, nThinking, w); - ReadIcon(ANALYZE_14, nAnalyzing, w); -} - -void -DrawWidgetIcon (Option *opt, int nIcon) -{ // as we are already in X front-end, so do X-stuff here - Arg arg; - XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]); - XtSetValues(opt->handle, &arg, 1); -} - -void -InsertIntoMemo (int which, char * text, int where) -{ - XawTextBlock t; - Widget edit; - - /* the backend adds \r\n, which is needed for winboard, - * for xboard we delete them again over here */ - if(t.ptr = strchr(text, '\r')) *t.ptr = ' '; - - t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit; - edit = XtNameToWidget(shells[EngOutDlg], which ? "*paneB.text" : "*paneA.text"); - XawTextReplace(edit, where, where, &t); - if(where < highTextStart[which]) { // [HGM] multiPVdisplay: move highlighting - int len = strlen(text); - highTextStart[which] += len; highTextEnd[which] += len; - XawTextSetSelection( edit, highTextStart[which], highTextEnd[which] ); - } -} - -//--------------------------------- PV walking --------------------------------------- - -char memoTranslations[] = -":Ctrlc: CopyMemoProc() \n \ -: HandlePV() \n \ -Shift: select-start() extend-end() SelectPV(1) \n \ -Any: select-start() extend-end() SelectPV(0) \n \ -: StopPV() \n"; - -void -SelectPV (Widget w, XEvent * event, String * params, Cardinal * nParams) -{ // [HGM] pv: translate click to PV line, and load it for display - String val; - int start, end; - XawTextPosition index, dummy; - int x, y; - Arg arg; - - x = event->xmotion.x; y = event->xmotion.y; - currentPV = (w != memoWidget); - XawTextGetSelectionPos(w, &index, &dummy); - XtSetArg(arg, XtNstring, &val); - XtGetValues(w, &arg, 1); - shiftKey = strcmp(params[0], "0"); - if(LoadMultiPV(x, y, val, index, &start, &end, currentPV)) { - XawTextSetSelection( w, start, end ); - highTextStart[currentPV] = start; highTextEnd[currentPV] = end; - } -} - -void -StopPV (Widget w, XEvent * event, String * params, Cardinal * nParams) -{ // [HGM] pv: on right-button release, stop displaying PV - XawTextUnsetSelection( w ); - highTextStart[currentPV] = highTextEnd[currentPV] = 0; - UnLoadPV(); - XtCallActionProc(w, "beginning-of-file", event, NULL, 0); -} - -//------------------------- Ctrl-C copying of memo texts --------------------------- - -// Awfull code: first read our own primary selection into selected_fen_position, -// and then transfer ownership of this to the clipboard, so that the -// copy-position callback can fetch it there when somebody pastes it -// Worst of all is that I only added it because I did not know how to copy primary: -// my laptop has no middle button. Ctrl-C might not be needed at all... [HGM] - -// cloned from CopyPositionProc. Abuse selected_fen_position to hold selection - -Boolean SendPositionSelection(Widget w, Atom *selection, Atom *target, - Atom *type_return, XtPointer *value_return, - unsigned long *length_return, int *format_return); // from xboard.c - -static void -MemoCB (Widget w, XtPointer client_data, Atom *selection, - Atom *type, XtPointer value, unsigned long *len, int *format) -{ - if (value==NULL || *len==0) return; /* nothing had been selected to copy */ - selected_fen_position = value; - selected_fen_position[*len]='\0'; /* normally this string is terminated, but be safe */ - XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay), - CurrentTime, - SendPositionSelection, - NULL/* lose_ownership_proc */ , - NULL/* transfer_done_proc */); -} - -void -CopyMemoProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - if(appData.pasteSelection) return; - if (selected_fen_position) free(selected_fen_position); - XtGetSelectionValue(menuBarWidget, - XA_PRIMARY, XA_STRING, - /* (XtSelectionCallbackProc) */ MemoCB, - NULL, /* client_data passed to PastePositionCB */ - - /* better to use the time field from the event that triggered the - * call to this function, but that isn't trivial to get - */ - CurrentTime - ); -} - -//------------------------------- pane switching ----------------------------------- - -void -ResizeWindowControls (int mode) -{ // another hideous kludge: to have only a single pane, we resize the - // second to 5 pixels (which makes it too small to display anything) - Widget form1, form2; - Arg args[16]; - int j; - Dimension ew_height, tmp; - Widget shell = shells[EngOutDlg]; - - form1 = XtNameToWidget(shell, "*paneA"); - form2 = XtNameToWidget(shell, "*paneB"); - - j = 0; - XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++; - XtGetValues(form1, args, j); - j = 0; - XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++; - XtGetValues(form2, args, j); - ew_height += tmp; // total height - - if(mode==0) { - j = 0; - XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++; - XtSetValues(form2, args, j); - j = 0; - XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++; - XtSetValues(form1, args, j); - } else { - j = 0; - XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++; - XtSetValues(form1, args, j); - j = 0; - XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++; - XtSetValues(form2, args, j); - } -} - diff --git a/xevalgraph.c b/xevalgraph.c deleted file mode 100644 index f3cac1f..0000000 --- a/xevalgraph.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Evaluation graph - * - * Author: Alessandro Scotti (Dec 2005) - * Translated to X by H.G.Muller (Nov 2009) - * - * Copyright 2005 Alessandro Scotti - * - * Enhancements Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - * ------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#include "config.h" - -#include -#include -#include -#include - -#if STDC_HEADERS -# include -# include -#else /* not STDC_HEADERS */ -extern char *getenv(); -# if HAVE_STRING_H -# include -# else /* not HAVE_STRING_H */ -# include -# endif /* not HAVE_STRING_H */ -#endif /* not STDC_HEADERS */ - -#if HAVE_UNISTD_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "common.h" -#include "frontend.h" -#include "backend.h" -#include "dialogs.h" -#include "menus.h" -#include "xboard.h" -#include "evalgraph.h" -#include "xevalgraph.h" -#include "draw.h" -#include "gettext.h" - -#ifdef ENABLE_NLS -# define _(s) gettext (s) -# define N_(s) gettext_noop (s) -#else -# define _(s) (s) -# define N_(s) s -#endif - -#include - -#ifdef SNAP -#include "wsnap.h" -#endif - -#define _LL_ 100 - -Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle -Widget outputField[2][7]; // [HGM] front-end array to translate output field to window handle -static char *title = N_("Evaluation graph"); - -//extern WindowPlacement wpEvalGraph; - -Position evalGraphX = -1, evalGraphY = -1; -Dimension evalGraphW, evalGraphH; - -/* Module variables */ - -char *crWhite = "#FFFFB0"; -char *crBlack = "#AD5D3D"; -Option *disp; - -static Option *EvalCallback P((int button, int x, int y)); - -static void -ChoosePen(cairo_t *cr, int i) -{ - switch(i) { - case PEN_BLACK: - SetPen(cr, 1.0, "#000000", 0); - break; - case PEN_DOTTED: - SetPen(cr, 1.0, "#A0A0A0", 1); - break; - case PEN_BLUEDOTTED: - SetPen(cr, 1.0, "#0000FF", 1); - break; - case PEN_BOLDWHITE: - SetPen(cr, 3.0, crWhite, 0); - break; - case PEN_BOLDBLACK: - SetPen(cr, 3.0, crBlack, 0); - break; - case PEN_BACKGD: - SetPen(cr, 3.0, "#E0E0F0", 0); - break; - } -} - -// [HGM] front-end, added as wrapper to avoid use of LineTo and MoveToEx in other routines (so they can be back-end) -void -DrawSegment (int x, int y, int *lastX, int *lastY, enum PEN penType) -{ - static int curX, curY; - - if(penType != PEN_NONE) { - cairo_t *cr = cairo_create(DRAWABLE(disp)); - cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); - cairo_move_to (cr, curX, curY); - cairo_line_to (cr, x,y); - ChoosePen(cr, penType); - cairo_stroke (cr); - cairo_destroy (cr); - } - - if(lastX != NULL) { *lastX = curX; *lastY = curY; } - curX = x; curY = y; -} - -// front-end wrapper for drawing functions to do rectangles -void -DrawRectangle (int left, int top, int right, int bottom, int side, int style) -{ - cairo_t *cr; - - cr = cairo_create (DRAWABLE(disp)); - cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); - cairo_rectangle (cr, left, top, right-left, bottom-top); - switch(side) - { - case 0: ChoosePen(cr, PEN_BOLDWHITE); break; - case 1: ChoosePen(cr, PEN_BOLDBLACK); break; - case 2: ChoosePen(cr, PEN_BACKGD); break; - } - cairo_fill (cr); - - if(style != FILLED) - { - cairo_rectangle (cr, left, top, right-left-1, bottom-top-1); - ChoosePen(cr, PEN_BLACK); - cairo_stroke (cr); - } - - cairo_destroy(cr); -} - -// front-end wrapper for putting text in graph -void -DrawEvalText (char *buf, int cbBuf, int y) -{ - // the magic constants 8 and 5 should really be derived from the font size somehow - cairo_text_extents_t extents; - cairo_t *cr = cairo_create(DRAWABLE(disp)); - - /* GTK-TODO this has to go into the font-selection */ - cairo_select_font_face (cr, "Sans", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size (cr, 12.0); - - - cairo_text_extents (cr, buf, &extents); - - cairo_move_to (cr, MarginX - 2 - 8*cbBuf, y+5); - cairo_text_path (cr, buf); - cairo_set_source_rgb (cr, 0.0, 0.0, 0); - cairo_fill_preserve (cr); - cairo_set_source_rgb (cr, 0, 1.0, 0); - cairo_set_line_width (cr, 0.1); - cairo_stroke (cr); - - /* free memory */ - cairo_destroy (cr); -} - -static int initDone = FALSE; - -static void -InitializeEvalGraph (Option *opt, int w, int h) -{ - if(w == 0) { - Arg args[10]; - XtSetArg(args[0], XtNwidth, &evalGraphW); - XtSetArg(args[1], XtNheight, &evalGraphH); - XtGetValues(opt->handle, args, 2); - nWidthPB = evalGraphW; nHeightPB = evalGraphH; - } else nWidthPB = w, nHeightPB = h; - - initDone = TRUE; -} - -// The following stuff is really back-end (but too little to bother with a separate file) - -static void -EvalClick (int x, int y) -{ - int index = GetMoveIndexFromPoint( x, y ); - - if( index >= 0 && index < currLast ) ToNrEvent( index + 1 ); -} - -static Option graphOptions[] = { -{ 150, 0x9C, 300, NULL, (void*) &EvalCallback, NULL, NULL, Graph , "" }, -{ 0, 2, 0, NULL, NULL, "", NULL, EndMark , "" } -}; - -static void -DisplayEvalGraph () -{ // back-end painting; calls back front-end primitives for lines, rectangles and text - char *t = MakeEvalTitle(_(title)); - nWidthPB = disp->max; nHeightPB = disp->value; - if(t != title && nWidthPB < 340) t = MakeEvalTitle(nWidthPB < 240 ? "" : _("Eval")); - PaintEvalGraph(); - GraphExpose(graphOptions, 0, 0, nWidthPB, nHeightPB); - SetDialogTitle(EvalGraphDlg, t); -} - -static Option * -EvalCallback (int button, int x, int y) -{ - if(!initDone) return NULL; - - switch(button) { - case 10: // expose event - /* Create or recreate paint box if needed */ - if(x != nWidthPB || y != nHeightPB) { - InitializeEvalGraph(&graphOptions[0], x, y); - } - nWidthPB = x; - nHeightPB = y; - DisplayEvalGraph(); - break; - case 1: EvalClick(x, y); // left button - default: break; // other buttons ignored - } - return NULL; // no context menu! -} - -void -EvalGraphPopUp () -{ - if (GenericPopUp(graphOptions, _(title), EvalGraphDlg, BoardWindow, NONMODAL, 1)) { - InitializeEvalGraph(&graphOptions[0], 0, 0); // first time: add callbacks and initialize pens - disp = graphOptions; - } else { - SetDialogTitle(EvalGraphDlg, _(title)); - SetIconName(EvalGraphDlg, _(title)); - } - - MarkMenu("View.EvaluationGraph", EvalGraphDlg); - -// ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output -} - -void -EvalGraphPopDown () -{ - PopDown(EvalGraphDlg); - -// ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output -} - -Boolean -EvalGraphIsUp () -{ - return shellUp[EvalGraphDlg]; -} - -int -EvalGraphDialogExists () -{ - return DialogExists(EvalGraphDlg); -} - -void -EvalGraphProc () -{ - if (!PopDown(EvalGraphDlg)) EvalGraphPopUp(); -} - -// This function is the interface to the back-end. - -void -EvalGraphSet (int first, int last, int current, ChessProgramStats_Move * pvInfo) -{ - /* [AS] Danger! For now we rely on the pvInfo parameter being a static variable! */ - - currFirst = first; - currLast = last; - currCurrent = current; - currPvInfo = pvInfo; - - if( DialogExists(EvalGraphDlg) ) { - DisplayEvalGraph(); - } -} - diff --git a/xevalgraph.h b/xevalgraph.h deleted file mode 100644 index e1227c6..0000000 --- a/xevalgraph.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * xevalgraph.h - * - * Copyright 2010, 2011, 2012 Free Software Foundation, Inc. - * - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#ifndef XB_XEVALGRAPH -#define XB_XEVALGRAPH - -void EvalGraphSet P(( int first, int last, int current, ChessProgramStats_Move * pvInfo )); -float Color P((char *col, int n)); -void SetPen P((cairo_t *cr, float w, char *col, int dash)); - -#endif diff --git a/xgamelist.c b/xgamelist.c deleted file mode 100644 index 50367b1..0000000 --- a/xgamelist.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * xgamelist.c -- Game list window, part of X front end for XBoard - * - * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#include "config.h" - -#include -#include -#include -#include - -#if STDC_HEADERS -# include -# include -#else /* not STDC_HEADERS */ -extern char *getenv(); -# if HAVE_STRING_H -# include -# else /* not HAVE_STRING_H */ -# include -# endif /* not HAVE_STRING_H */ -#endif /* not STDC_HEADERS */ - -#if HAVE_UNISTD_H -# include -#endif - -#include -#include -#include -#include -#if USE_XAW3D -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "common.h" -#include "backend.h" -#include "xboard.h" -#include "xgamelist.h" -#include "dialogs.h" - - -char gameListTranslations[] = - ": WheelProc(-3) \n \ - : WheelProc(3) \n \ - : LoadSelectedProc(100) Set() \n \ - (2): LoadSelectedProc(0) \n \ - Home: LoadSelectedProc(-2) \n \ - End: LoadSelectedProc(2) \n \ - CtrlUp: LoadSelectedProc(-3) \n \ - CtrlDown: LoadSelectedProc(3) \n \ - Up: LoadSelectedProc(-1) \n \ - Down: LoadSelectedProc(1) \n \ - Left: LoadSelectedProc(-1) \n \ - Right: LoadSelectedProc(1) \n \ - Prior: LoadSelectedProc(-4) \n \ - Next: LoadSelectedProc(4) \n \ - Return: LoadSelectedProc(0) \n"; -char filterTranslations[] = - "Return: SetFilterProc() \n"; - - -void -LoadSelectedProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - if(GameListClicks(atoi(prms[0]))) return; // if no game loaded, no focus transfer - XSync(xDisplay, False); - XSetInputFocus(xDisplay, XtWindow(boardWidget), RevertToPointerRoot, CurrentTime); -} - -void -SetFilterProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - SetFilter(); -} - diff --git a/xgamelist.h b/xgamelist.h deleted file mode 100644 index fa7b41a..0000000 --- a/xgamelist.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * xgamelist.h -- Game list window, part of X front end for XBoard - * - * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#ifndef XB_XGAMELIST -#define XB_XGAMELIST - -void LoadSelectedProc P((Widget w, XEvent *event, - String *prms, Cardinal *nprms)); -void SetFilterProc P((Widget w, XEvent *event, - String *prms, Cardinal *nprms)); - -#endif /* XB_XGAMELIST */ diff --git a/xhistory.c b/xhistory.c deleted file mode 100644 index 4277f82..0000000 --- a/xhistory.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * New (WinBoard-style) Move history for XBoard - * - * Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - * ------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#include "config.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "frontend.h" -#include "backend.h" -#include "xhistory.h" -#include "xboard.h" -#include "dialogs.h" -#include "gettext.h" - -#ifdef ENABLE_NLS -# define _(s) gettext (s) -# define N_(s) gettext_noop (s) -#else -# define _(s) (s) -# define N_(s) s -#endif - -// templates for calls into back-end (= history.c; should be moved to history.h header shared with it!) -void RefreshMemoContent P((void)); -void MemoContentUpdated P((void)); -void FindMoveByCharIndex P(( int char_index )); - -// variables in xoptions.c -extern Option historyOptions[]; - -// ------------- low-level front-end actions called by MoveHistory back-end ----------------- - -void -HighlightMove (int from, int to, Boolean highlight) -{ - if(highlight) - XawTextSetSelection( historyOptions[0].handle, from, to ); // for lack of a better method, use selection for highighting -} - -void -ClearHistoryMemo () -{ - SetWidgetText(&historyOptions[0], "", HistoryDlg); -} - -// the bold argument says 0 = normal, 1 = bold typeface -// the colorNr argument says 0 = font-default, 1 = gray -int -AppendToHistoryMemo (char * text, int bold, int colorNr) -{ - return AppendText(&historyOptions[0], text); // for now ignore bold & color stuff, as Xaw cannot handle that -} - -void -ScrollToCurrent (int caretPos) -{ - Arg args[10]; - char *s; - int len; - GetWidgetText(&historyOptions[0], &s); - len = strlen(s); - if(caretPos < 0 || caretPos > len) caretPos = len; - if(caretPos > len-30) { // scroll to end, which causes no flicker - static XEvent event; - XtCallActionProc(historyOptions[0].handle, "end-of-file", &event, NULL, 0); - return; - } - // the following leads to a very annoying flicker, even when no scrolling is done at all. - XtSetArg(args[0], XtNinsertPosition, caretPos); // this triggers scrolling in Xaw - XtSetArg(args[1], XtNdisplayCaret, False); - XtSetValues(historyOptions[0].handle, args, 2); -} - - -// ------------------------------ callbacks -------------------------- - -char *historyText; -char historyTranslations[] = -": select-start() \n \ -: extend-end() SelectMove() \n"; - -void -SelectMove (Widget w, XEvent * event, String * params, Cardinal * nParams) -{ - XawTextPosition index, dummy; - - XawTextGetSelectionPos(w, &index, &dummy); - FindMoveByCharIndex( index ); // [HGM] also does the actual moving to it, now -} - -Option historyOptions[] = { -{ 200, T_VSCRL | T_FILL | T_WRAP | T_TOP, 400, NULL, (void*) &historyText, "", NULL, TextBox, "" }, -{ 0, NO_OK, 0, NULL, (void*) NULL, "", NULL, EndMark , "" } -}; - -// ------------ standard entry points into MoveHistory code ----------- - -Boolean -MoveHistoryIsUp () -{ - return shellUp[HistoryDlg]; -} - -Boolean -MoveHistoryDialogExists () -{ - return DialogExists(HistoryDlg); -} - -void -HistoryPopUp () -{ - if(GenericPopUp(historyOptions, _("Move list"), HistoryDlg, BoardWindow, NONMODAL, 1)) - AddHandler(&historyOptions[0], 0); - MarkMenu("View.MoveHistory", HistoryDlg); -} - -void -HistoryShowProc () -{ - if (!shellUp[HistoryDlg]) { - ASSIGN(historyText, ""); - HistoryPopUp(); - RefreshMemoContent(); - MemoContentUpdated(); - } else PopDown(HistoryDlg); - ToNrEvent(currentMove); -} diff --git a/xhistory.h b/xhistory.h deleted file mode 100644 index 90f0c9b..0000000 --- a/xhistory.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * xhistory.h -- Eval graph window, part of X front end for XBoard - * - * Copyright 1995, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -#ifndef XB_XHISTLIST -#define XB_XHISTLIST - -void HistoryShowProc P((void)); -Boolean MoveHistoryIsUp P((void)); - -#endif /* XB_XHISTLIST */ diff --git a/xoptions.c b/xoptions.c deleted file mode 100644 index a475c58..0000000 --- a/xoptions.c +++ /dev/null @@ -1,1216 +0,0 @@ -/* - * xoptions.c -- Move list window, part of X front end for XBoard - * - * Copyright 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. - * ------------------------------------------------------------------------ - * - * GNU XBoard is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * GNU XBoard is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. * - * - *------------------------------------------------------------------------ - ** See the file ChangeLog for a revision history. */ - -// [HGM] this file is the counterpart of woptions.c, containing xboard popup menus -// similar to those of WinBoard, to set the most common options interactively. - -#include "config.h" - -#include -#include -#include -#include - -#if STDC_HEADERS -# include -# include -#else /* not STDC_HEADERS */ -extern char *getenv(); -# if HAVE_STRING_H -# include -# else /* not HAVE_STRING_H */ -# include -# endif /* not HAVE_STRING_H */ -#endif /* not STDC_HEADERS */ - -#if HAVE_UNISTD_H -# include -#endif -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "common.h" -#include "backend.h" -#include "xboard.h" -#include "dialogs.h" -#include "menus.h" -#include "gettext.h" - -#ifdef ENABLE_NLS -# define _(s) gettext (s) -# define N_(s) gettext_noop (s) -#else -# define _(s) (s) -# define N_(s) s -#endif - -// [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines - -static Widget previous = NULL; -static Option *currentOption; - -void -UnCaret () -{ - Arg args[2]; - - if(previous) { - XtSetArg(args[0], XtNdisplayCaret, False); - XtSetValues(previous, args, 1); - } - previous = NULL; -} - -void -SetFocus (Widget w, XtPointer data, XEvent *event, Boolean *b) -{ - Arg args[2]; - char *s; - int j; - - UnCaret(); - XtSetArg(args[0], XtNstring, &s); - XtGetValues(w, args, 1); - j = 1; - XtSetArg(args[0], XtNdisplayCaret, True); - if(!strchr(s, '\n') && strlen(s) < 80) XtSetArg(args[1], XtNinsertPosition, strlen(s)), j++; - XtSetValues(w, args, j); - XtSetKeyboardFocus((Widget) data, w); - previous = w; -} - -void -BoardFocus () -{ - XtSetKeyboardFocus(shellWidget, formWidget); -} - -//--------------------------- Engine-specific options menu ---------------------------------- - -int dialogError; -Option *dialogOptions[NrOfDialogs]; - -static Arg layoutArgs[] = { - { XtNborderWidth, 0 }, - { XtNdefaultDistance, 0 }, -}; - -static Arg formArgs[] = { - { XtNborderWidth, 0 }, - { XtNresizable, (XtArgVal) True }, -}; - -void -GetWidgetText (Option *opt, char **buf) -{ - Arg arg; - XtSetArg(arg, XtNstring, buf); - XtGetValues(opt->handle, &arg, 1); -} - -void -SetWidgetText (Option *opt, char *buf, int n) -{ - Arg arg; - XtSetArg(arg, XtNstring, buf); - XtSetValues(opt->handle, &arg, 1); - if(n >= 0) SetFocus(opt->handle, shells[n], NULL, False); -} - -void -GetWidgetState (Option *opt, int *state) -{ - Arg arg; - XtSetArg(arg, XtNstate, state); - XtGetValues(opt->handle, &arg, 1); -} - -void -SetWidgetState (Option *opt, int state) -{ - Arg arg; - XtSetArg(arg, XtNstate, state); - XtSetValues(opt->handle, &arg, 1); -} - -void -SetWidgetLabel (Option *opt, char *buf) -{ - Arg arg; - XtSetArg(arg, XtNlabel, (XtArgVal) buf); - XtSetValues(opt->handle, &arg, 1); -} - -void -SetDialogTitle (DialogClass dlg, char *title) -{ - Arg args[16]; - XtSetArg(args[0], XtNtitle, title); - XtSetValues(shells[dlg], args, 1); -} - -void -LoadListBox (Option *opt, char *emptyText) -{ - static char *dummyList[2]; - dummyList[0] = emptyText; // empty listboxes tend to crash X, so display user-supplied warning string instead - XawListChange(opt->handle, *(char*)opt->target ? opt->target : dummyList, 0, 0, True); -} - -int -ReadScroll (Option *opt, float *top, float *bottom) -{ // retreives fractions of top and bottom of thumb - Arg args[16]; - Widget w = XtParent(opt->handle); // viewport - Widget v = XtNameToWidget(w, "vertical"); - int j=0; - float h; - if(!v) return FALSE; // no scroll bar - XtSetArg(args[j], XtNshown, &h); j++; - XtSetArg(args[j], XtNtopOfThumb, top); j++; - XtGetValues(v, args, j); - *bottom = *top + h; - return TRUE; -} - -void -SetScroll (Option *opt, float f) -{ // sets top of thumb to given fraction - static char *params[3] = { "", "Continuous", "Proportional" }; - static XEvent event; - Widget w = XtParent(opt->handle); // viewport - Widget v = XtNameToWidget(w, "vertical"); - if(!v) return; // no scroll bar - XtCallActionProc(v, "StartScroll", &event, params+1, 1); - XawScrollbarSetThumb(v, f, -1.0); - XtCallActionProc(v, "NotifyThumb", &event, params, 0); -// XtCallActionProc(v, "NotifyScroll", &event, params+2, 1); - XtCallActionProc(v, "EndScroll", &event, params, 0); -} - -void -HighlightListBoxItem (Option *opt, int nr) -{ - XawListHighlight(opt->handle, nr); -} - -void -HighlightWithScroll (Option *opt, int sel, int max) -{ - float top, bottom, f, g; - HighlightListBoxItem(opt, sel); - if(!ReadScroll(opt, &top, &bottom)) return; // no scroll bar - bottom = bottom*max - 1.f; - f = g = top; - top *= max; - if(sel > (top + 3*bottom)/4) f = (sel - 0.75f*(bottom-top))/max; else - if(sel < (3*top + bottom)/4) f = (sel - 0.25f*(bottom-top))/max; - if(f < 0.f) f = 0.; if(f + 1.f/max > 1.f) f = 1. - 1./max; - if(f != g) SetScroll(opt, f); -} - -int -SelectedListBoxItem (Option *opt) -{ - XawListReturnStruct *rs; - rs = XawListShowCurrent(opt->handle); - return rs->list_index; -} - -void -FocusOnWidget (Option *opt, DialogClass dlg) -{ - UnCaret(); - XtSetKeyboardFocus(shells[dlg], opt->handle); -} - -void -SetIconName (DialogClass dlg, char *name) -{ - Arg args[16]; - int j = 0; - XtSetArg(args[j], XtNiconName, (XtArgVal) name); j++; -// XtSetArg(args[j], XtNtitle, (XtArgVal) name); j++; - XtSetValues(shells[dlg], args, j); -} - -static void -CheckCallback (Widget ww, XtPointer client_data, XEvent *event, Boolean *b) -{ - int s, data = (intptr_t) client_data; - Option *opt = dialogOptions[data >> 8] + (data & 255); - - if(opt->type == Label) { ((ButtonCallback*) opt->target)(data&255); return; } - - GetWidgetState(opt, &s); - SetWidgetState(opt, !s); -} - -static void -SpinCallback (Widget w, XtPointer client_data, XtPointer call_data) -{ - String name, val; - Arg args[16]; - char buf[MSG_SIZ], *p; - int j = 0; // Initialisation is necessary because the text value may be non-numeric causing the scanf conversion to fail - int data = (intptr_t) client_data; - Option *opt = dialogOptions[data >> 8] + (data & 255); - - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - - GetWidgetText(opt, &val); - sscanf(val, "%d", &j); - if (strcmp(name, _("browse")) == 0) { - char *q=val, *r; - for(r = ""; *q; q++) if(*q == '.') r = q; else if(*q == '/') r = ""; // last dot after last slash - if(!strcmp(r, "") && !currentCps && opt->type == FileName && opt->textValue) - r = opt->textValue; - Browse(data>>8, opt->name, NULL, r, opt->type == PathName, "", &p, (FILE**) opt); - return; - } else - if (strcmp(name, "+") == 0) { - if(++j > opt->max) return; - } else - if (strcmp(name, "-") == 0) { - if(--j < opt->min) return; - } else return; - snprintf(buf, MSG_SIZ, "%d", j); - SetWidgetText(opt, buf, TransientDlg); -} - -static void -ComboSelect (Widget w, caddr_t addr, caddr_t index) // callback for all combo items -{ - Arg args[16]; - Option *opt = dialogOptions[((intptr_t)addr)>>24]; // applicable option list - int i = ((intptr_t)addr)>>16 & 255; // option number - int j = 0xFFFF & (intptr_t) addr; - - values[i] = j; // store selected value in Option struct, for retrieval at OK - - if(opt[i].type == Graph || opt[i].min & COMBO_CALLBACK && (!currentCps || shellUp[BrowserDlg])) { - ((ButtonCallback*) opt[i].target)(i); - return; - } - - if(opt[i].min & NO_GETTEXT) - XtSetArg(args[0], XtNlabel, ((char**)opt[i].choice)[j]); - else - XtSetArg(args[0], XtNlabel, _(((char**)opt[i].choice)[j])); - - XtSetValues(opt[i].handle, args, 1); -} - -Widget -CreateMenuItem (Widget menu, char *msg, XtCallbackProc CB, int n) -{ - int j=0; - Widget entry; - Arg args[16]; - XtSetArg(args[j], XtNleftMargin, 20); j++; - XtSetArg(args[j], XtNrightMargin, 20); j++; - if(!strcmp(msg, "----")) { XtCreateManagedWidget(msg, smeLineObjectClass, menu, args, j); return NULL; } - XtSetArg(args[j], XtNlabel, msg); - entry = XtCreateManagedWidget("item", smeBSBObjectClass, menu, args, j+1); - XtAddCallback(entry, XtNcallback, CB, (caddr_t)(intptr_t) n); - return entry; -} - -static Widget -CreateComboPopup (Widget parent, Option *opt, int n, int fromList, int def) -{ // fromList determines if the item texts are taken from a list of strings, or from a menu table - int i; - Widget menu, entry; - Arg arg; - MenuItem *mb = (MenuItem *) opt->choice; - char **list = (char **) opt->choice; - - if(list[0] == NULL) return NULL; // avoid empty menus, as they cause crash - menu = XtCreatePopupShell(opt->name, simpleMenuWidgetClass, parent, NULL, 0); - - for (i=0; 1; i++) - { - char *msg = fromList ? list[i] : mb[i].string; - if(!msg) break; - entry = CreateMenuItem(menu, opt->min & NO_GETTEXT ? msg : _(msg), (XtCallbackProc) ComboSelect, (n<<16)+i); - if(!fromList) mb[i].handle = (void*) entry; // save item ID, for enabling / checkmarking - if(i==def) { - XtSetArg(arg, XtNpopupOnEntry, entry); - XtSetValues(menu, &arg, 1); - } - } - return menu; -} - -char moveTypeInTranslations[] = - "Return: TypeInProc(1) \n" - "Escape: TypeInProc(0) \n"; -extern char filterTranslations[]; -extern char gameListTranslations[]; -extern char memoTranslations[]; - - -char *translationTable[] = { // beware: order is essential! - historyTranslations, commentTranslations, moveTypeInTranslations, ICSInputTranslations, - filterTranslations, gameListTranslations, memoTranslations -}; - -void -AddHandler (Option *opt, int nr) -{ - XtOverrideTranslations(opt->handle, XtParseTranslationTable(translationTable[nr])); -} - -//----------------------------Generic dialog -------------------------------------------- - -// cloned from Engine Settings dialog (and later merged with it) - -Widget shells[NrOfDialogs]; -DialogClass parents[NrOfDialogs]; -WindowPlacement *wp[NrOfDialogs] = { // Beware! Order must correspond to DialogClass enum - NULL, &wpComment, &wpTags, NULL, NULL, NULL, NULL, &wpMoveHistory, &wpGameList, &wpEngineOutput, &wpEvalGraph, - NULL, NULL, NULL, NULL, /*&wpMain*/ NULL -}; - -int -DialogExists (DialogClass n) -{ // accessor for use in back-end - return shells[n] != NULL; -} - -void -RaiseWindow (DialogClass dlg) -{ - static XEvent xev; - Window root = RootWindow(xDisplay, DefaultScreen(xDisplay)); - Atom atom = XInternAtom (xDisplay, "_NET_ACTIVE_WINDOW", False); - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = xDisplay; - xev.xclient.window = XtWindow(shells[dlg]); - xev.xclient.message_type = atom; - xev.xclient.format = 32; - xev.xclient.data.l[0] = 1; - xev.xclient.data.l[1] = CurrentTime; - - XSendEvent (xDisplay, - root, False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); - - XFlush(xDisplay); - XSync(xDisplay, False); -} - -int -PopDown (DialogClass n) -{ // pops down any dialog created by GenericPopUp (or returns False if it wasn't up), unmarks any associated marked menu - int j; - Arg args[10]; - Dimension windowH, windowW; Position windowX, windowY; - if (!shellUp[n] || !shells[n]) return 0; - if(n && wp[n]) { // remember position - j = 0; - XtSetArg(args[j], XtNx, &windowX); j++; - XtSetArg(args[j], XtNy, &windowY); j++; - XtSetArg(args[j], XtNheight, &windowH); j++; - XtSetArg(args[j], XtNwidth, &windowW); j++; - XtGetValues(shells[n], args, j); - wp[n]->x = windowX; - wp[n]->x = windowY; - wp[n]->width = windowW; - wp[n]->height = windowH; - } - previous = NULL; - XtPopdown(shells[n]); - shellUp[n]--; // count rather than clear - if(n == 0 || n >= PromoDlg) XtDestroyWidget(shells[n]), shells[n] = NULL; - if(marked[n]) { - MarkMenuItem(marked[n], False); - marked[n] = NULL; - } - if(!n && n != BrowserDlg) currentCps = NULL; // if an Engine Settings dialog was up, we must be popping it down now - currentOption = dialogOptions[TransientDlg]; // just in case a transient dialog was up (to allow its check and combo callbacks to work) - RaiseWindow(parents[n]); - if(parents[n] == BoardWindow) XtSetKeyboardFocus(shellWidget, formWidget); - return 1; -} - -void -GenericPopDown (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // to cause popdown through a translation (Delete Window button!) - int dlg = atoi(prms[0]); - Widget sh = shells[dlg]; - if(shellUp[BrowserDlg] && dlg != BrowserDlg || dialogError) return; // prevent closing dialog when it has an open file-browse daughter - shells[dlg] = w; - PopDown(dlg); - shells[dlg] = sh; // restore -} - -int -AppendText (Option *opt, char *s) -{ - XawTextBlock t; - char *v; - int len; - GetWidgetText(opt, &v); - len = strlen(v); - t.ptr = s; t.firstPos = 0; t.length = strlen(s); t.format = XawFmt8Bit; - XawTextReplace(opt->handle, len, len, &t); - return len; -} - -void -SetColor (char *colorName, Option *box) -{ // sets the color of a widget - Arg args[5]; - Pixel buttonColor; - XrmValue vFrom, vTo; - if (!appData.monoMode) { - vFrom.addr = (caddr_t) colorName; - vFrom.size = strlen(colorName); - XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); - if (vTo.addr == NULL) { - buttonColor = (Pixel) -1; - } else { - buttonColor = *(Pixel *) vTo.addr; - } - } else buttonColor = timerBackgroundPixel; - XtSetArg(args[0], XtNbackground, buttonColor);; - XtSetValues(box->handle, args, 1); -} - -void -ColorChanged (Widget w, XtPointer data, XEvent *event, Boolean *b) -{ // for detecting a typed change in color - char buf[10]; - if ( (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) && *buf == '\r' ) - RefreshColor((int)(intptr_t) data, 0); -} - -static void -GraphEventProc(Widget widget, caddr_t client_data, XEvent *event) -{ // handle expose and mouse events on Graph widget - Dimension w, h; - Arg args[16]; - int j, button=10, f=1, sizing=0; - Option *opt, *graph = (Option *) client_data; - PointerCallback *userHandler = graph->target; - - if (!XtIsRealized(widget)) return; - - switch(event->type) { - case Expose: // make handling of expose events generic, just copying from memory buffer (->choice) to display (->textValue) - /* Get window size */ - j = 0; - XtSetArg(args[j], XtNwidth, &w); j++; - XtSetArg(args[j], XtNheight, &h); j++; - XtGetValues(widget, args, j); - - if(w < graph->max || w > graph->max + 1 || h != graph->value) { // use width fudge of 1 pixel - if(((XExposeEvent*)event)->count >= 0) { // suppress sizing on expose for ordered redraw in response to sizing. - sizing = 1; - graph->max = w; graph->value = h; // note: old values are kept if we we don't exceed width fudge - } - } else w = graph->max; - - if(sizing && ((XExposeEvent*)event)->count > 0) { graph->max = 0; return; } // don't bother if further exposure is pending during resize - if(!graph->textValue || sizing) { // create surfaces of new size for display widget - if(graph->textValue) cairo_surface_destroy((cairo_surface_t *)graph->textValue); - graph->textValue = (char*) cairo_xlib_surface_create(xDisplay, XtWindow(widget), DefaultVisual(xDisplay, 0), w, h); - } - if(sizing) { // the memory buffer was already created in GenericPopup(), - // to give drawing routines opportunity to use it before first expose event - // (which are only processed when main gets to the event loop, so after all init!) - // so only change when size is no longer good - if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice); - graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); - break; - } - w = ((XExposeEvent*)event)->width; - if(((XExposeEvent*)event)->x + w > graph->max) w--; // cut off fudge pixel - if(w) ExposeRedraw(graph, ((XExposeEvent*)event)->x, ((XExposeEvent*)event)->y, w, ((XExposeEvent*)event)->height); - return; - case MotionNotify: - f = 0; - w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y; - break; - case ButtonRelease: - f = -1; // release indicated by negative button numbers - case ButtonPress: - w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y; - switch(((XButtonEvent*)event)->button) { - case Button1: button = 1; break; - case Button2: button = 2; break; - case Button3: button = 3; break; - case Button4: button = 4; break; - case Button5: button = 5; break; - } - } - button *= f; - opt = userHandler(button, w, h); - if(opt) { // user callback specifies a context menu; pop it up - XUngrabPointer(xDisplay, CurrentTime); - XtCallActionProc(widget, "XawPositionSimpleMenu", event, &(opt->name), 1); - XtPopupSpringLoaded(opt->handle); - } - XSync(xDisplay, False); -} - -void -GraphExpose (Option *opt, int x, int y, int w, int h) -{ - XExposeEvent e; - if(!opt->handle) return; - e.x = x; e.y = y; e.width = w; e.height = h; e.count = -1; e.type = Expose; // count = -1: kludge to suppress sizing - GraphEventProc(opt->handle, (caddr_t) opt, (XEvent *) &e); // fake expose event -} - -static void -GenericCallback (Widget w, XtPointer client_data, XtPointer call_data) -{ // all Buttons in a dialog (including OK, cancel) invoke this - String name; - Arg args[16]; - char buf[MSG_SIZ]; - int data = (intptr_t) client_data; - DialogClass dlg; - Widget sh = XtParent(XtParent(XtParent(w))), oldSh; - - currentOption = dialogOptions[dlg=data>>16]; data &= 0xFFFF; - oldSh = shells[dlg]; shells[dlg] = sh; // bow to reality - if (data == 30000) { // cancel - PopDown(dlg); - } else - if (data == 30001) { // save buttons imply OK - if(GenericReadout(currentOption, -1)) PopDown(dlg); // calls OK-proc after full readout, but no popdown if it returns false - } else - - if(currentCps && dlg != BrowserDlg) { - XtSetArg(args[0], XtNlabel, &name); - XtGetValues(w, args, 1); - if(currentOption[data].type == SaveButton) GenericReadout(currentOption, -1); - snprintf(buf, MSG_SIZ, "option %s\n", name); - SendToProgram(buf, currentCps); - } else ((ButtonCallback*) currentOption[data].target)(data); - - shells[dlg] = oldSh; // in case of multiple instances, restore previous (as this one could be popped down now) -} - -void -TabProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // for transfering focus to the next text-edit - Option *opt; - for(opt = currentOption; opt->type != EndMark; opt++) { - if(opt->handle == w) { - while(++opt) { - if(opt->type == EndMark) opt = currentOption; // wrap - if(opt->handle == w) return; // full circle - if(opt->type == TextBox || opt->type == Spin || opt->type == Fractional || opt->type == FileName || opt->type == PathName) { - SetFocus(opt->handle, XtParent(XtParent(XtParent(w))), NULL, 0); - return; - } - } - } - } -} - -void -WheelProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // for scrolling a widget seen through a viewport with the mouse wheel (ListBox!) - int j=0, n = atoi(prms[0]); - static char *params[3] = { "", "Continuous", "Proportional" }; - Arg args[16]; - float h, top; - Widget v; - if(!n) { // transient dialogs also use this for list-selection callback - n = prms[1][0]-'0'; - Option *opt=dialogOptions[prms[2][0]-'A'] + n; - if(opt->textValue) ((ListBoxCallback*) opt->textValue)(n, SelectedListBoxItem(opt)); - return; - } - v = XtNameToWidget(XtParent(w), "vertical"); - if(!v) return; - XtSetArg(args[j], XtNshown, &h); j++; - XtSetArg(args[j], XtNtopOfThumb, &top); j++; - XtGetValues(v, args, j); - top += 0.1f*h*n; if(top < 0.f) top = 0.; - XtCallActionProc(v, "StartScroll", event, params+1, 1); - XawScrollbarSetThumb(v, top, -1.0); - XtCallActionProc(v, "NotifyThumb", event, params, 0); -// XtCallActionProc(w, "NotifyScroll", event, params+2, 1); - XtCallActionProc(v, "EndScroll", event, params, 0); -} - -static char *oneLiner = - "Return: redraw-display() \n \ - Tab: TabProc() \n "; -static char scrollTranslations[] = - "(2): WheelProc(0 0 A) \n \ - : WheelProc(-1) \n \ - : WheelProc(1) \n "; - -static void -SqueezeIntoBox (Option *opt, int nr, int width) -{ // size buttons in bar to fit, clipping button names where necessary - int i, wtot = 0; - Dimension widths[20], oldWidths[20]; - Arg arg; - for(i=1; imin = wtot; - if(width <= 0) return; - while(wtot > width) { - int wmax=0, imax=0; - for(i=1; i wmax) wmax = widths[imax=i]; - widths[imax]--; - wtot--; - } - for(i=1; imin = wtot; -} - -int -SetPositionAndSize (Arg *args, Widget leftNeigbor, Widget topNeigbor, int b, int w, int h, int chaining) -{ // sizing and positioning most widgets have in common - int j = 0; - // first position the widget w.r.t. earlier ones - if(chaining & 1) { // same row: position w.r.t. last (on current row) and lastrow - XtSetArg(args[j], XtNfromVert, topNeigbor); j++; - XtSetArg(args[j], XtNfromHoriz, leftNeigbor); j++; - } else // otherwise it goes at left margin (which is default), below the previous element - XtSetArg(args[j], XtNfromVert, leftNeigbor), j++; - // arrange chaining ('2'-bit indicates top and bottom chain the same) - if((chaining & 14) == 6) XtSetArg(args[j], XtNtop, XtChainBottom), j++; - if((chaining & 14) == 10) XtSetArg(args[j], XtNbottom, XtChainTop ), j++; - if(chaining & 4) XtSetArg(args[j], XtNbottom, XtChainBottom ), j++; - if(chaining & 8) XtSetArg(args[j], XtNtop, XtChainTop), j++; - if(chaining & 0x10) XtSetArg(args[j], XtNright, XtChainRight), j++; - if(chaining & 0x20) XtSetArg(args[j], XtNleft, XtChainRight), j++; - if(chaining & 0x40) XtSetArg(args[j], XtNright, XtChainLeft ), j++; - if(chaining & 0x80) XtSetArg(args[j], XtNleft, XtChainLeft ), j++; - // set size (if given) - if(w) XtSetArg(args[j], XtNwidth, w), j++; - if(h) XtSetArg(args[j], XtNheight, h), j++; - // color - if(!appData.monoMode) { - if(!b && appData.dialogColor[0]) XtSetArg(args[j], XtNbackground, dialogColor), j++; - if(b == 3 && appData.buttonColor[0]) XtSetArg(args[j], XtNbackground, buttonColor), j++; - } - if(b == 3) b = 1; - // border - XtSetArg(args[j], XtNborderWidth, b); j++; - return j; -} - -int -GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent, int modal, int top) -{ - Arg args[24]; - Widget popup, layout, dialog=NULL, edit=NULL, form, last, b_ok, b_cancel, previousPane = NULL, textField = NULL, oldForm, oldLastRow, oldForeLast; - Window root, child; - int x, y, i, j, height=999, width=1, h, c, w, shrink=FALSE, stack = 0, box, chain; - int win_x, win_y, maxWidth, maxTextWidth; - unsigned int mask; - char def[MSG_SIZ], *msg, engineDlg = (currentCps != NULL && dlgNr != BrowserDlg); - static char pane[6] = "paneX"; - Widget texts[100], forelast = NULL, anchor, widest, lastrow = NULL, browse = NULL; - Dimension bWidth = 50; - - if(dlgNr < PromoDlg && shellUp[dlgNr]) return 0; // already up - if(dlgNr && dlgNr < PromoDlg && shells[dlgNr]) { // reusable, and used before (but popped down) - XtPopup(shells[dlgNr], XtGrabNone); - shellUp[dlgNr] = True; - return 0; - } - - dialogOptions[dlgNr] = option; // make available to callback - // post currentOption globally, so Spin and Combo callbacks can already use it - // WARNING: this kludge does not work for persistent dialogs, so that these cannot have spin or combo controls! - currentOption = option; - - if(engineDlg) { // Settings popup for engine: format through heuristic - int n = currentCps->nrOptions; - if(!n) { DisplayNote(_("Engine has no options")); currentCps = NULL; return 0; } - if(n > 50) width = 4; else if(n>24) width = 2; else width = 1; - height = n / width + 1; - if(n && (currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton)) currentOption[n].min = SAME_ROW; // OK on same line - currentOption[n].type = EndMark; currentOption[n].target = NULL; // delimit list by callback-less end mark - } - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; - shells[BoardWindow] = shellWidget; parents[dlgNr] = parent; - - if(dlgNr == BoardWindow) popup = shellWidget; else - popup = shells[dlgNr] = - XtCreatePopupShell(title, !top || !appData.topLevel ? transientShellWidgetClass : topLevelShellWidgetClass, - shells[parent], args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - if(!appData.monoMode && appData.dialogColor[0]) XtSetArg(args[0], XtNbackground, dialogColor); - XtSetValues(layout, args, 1); - - for(c=0; c and - - if(option[i].type == TextBox || option[i].type == Fractional) break; - - // add increment and decrement controls for spin - if(option[i].type == FileName || option[i].type == PathName) { - msg = _("browse"); w = 0; // automatically scale to width of text - j = textHeight ? textHeight : 0; - } else { - w = 20; msg = "+"; j = textHeight/2; // spin button - } - j = SetPositionAndSize(args, last, edit, 3 /* border */, - w /* w */, j /* h */, 0x31 /* chain to right edge */); - edit = XtCreateManagedWidget(msg, commandWidgetClass, form, args, j); - XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i + 256*dlgNr); - if(w == 0) browse = edit; - - if(option[i].type != Spin) break; - - j = SetPositionAndSize(args, last, edit, 3 /* border */, - 20 /* w */, textHeight/2 /* h */, 0x31 /* chain to right edge */); - XtSetArg(args[j], XtNvertDistance, -1); j++; - last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j); - XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i + 256*dlgNr); - break; - case CheckBox: - if(!engineDlg) option[i].value = *(Boolean*)option[i].target; // where checkbox callback uses it - j = SetPositionAndSize(args, last, lastrow, 1 /* border */, - textHeight/2 /* w */, textHeight/2 /* h */, 0xC0 /* chain both to left edge */); - XtSetArg(args[j], XtNvertDistance, (textHeight+2)/4 + 3); j++; - XtSetArg(args[j], XtNstate, option[i].value); j++; - lastrow = last; - option[i].handle = (void*) - (last = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j)); - j = SetPositionAndSize(args, last, lastrow, 0 /* border */, - option[i].max /* w */, textHeight /* h */, 0xC1 /* chain */); - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; - last = XtCreateManagedWidget("label", commandWidgetClass, form, args, j); - // make clicking the text toggle checkbox - XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i + 256*dlgNr); - shrink = TRUE; // following buttons must get text height - break; - case Label: - msg = option[i].name; - if(!msg) break; - chain = option[i].min; - if(chain & SAME_ROW) forelast = lastrow; else shrink = FALSE; - j = SetPositionAndSize(args, last, lastrow, (chain & 2) != 0 /* border */, - option[i].max /* w */, shrink ? textHeight : 0 /* h */, chain | 2 /* chain */); -#if ENABLE_NLS - if(option[i].choice) XtSetArg(args[j], XtNfontSet, *(XFontSet*)option[i].choice), j++; -#else - if(option[i].choice) XtSetArg(args[j], XtNfont, (XFontStruct*)option[i].choice), j++; -#endif - XtSetArg(args[j], XtNresizable, False); j++; - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNlabel, _(msg)); j++; - option[i].handle = (void*) (last = XtCreateManagedWidget("label", labelWidgetClass, form, args, j)); - if(option[i].target) // allow user to specify event handler for button presses - XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i + 256*dlgNr); - break; - case SaveButton: - case Button: - if(option[i].min & SAME_ROW) { - chain = 0x31; // 0011.0001 = both left and right side to right edge - forelast = lastrow; - } else chain = 0, shrink = FALSE; - j = SetPositionAndSize(args, last, lastrow, 3 /* border */, - option[i].max /* w */, shrink ? textHeight : 0 /* h */, option[i].min & 0xE | chain /* chain */); - XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; - if(option[i].textValue) { // special for buttons of New Variant dialog - XtSetArg(args[j], XtNsensitive, appData.noChessProgram || option[i].value < 0 - || strstr(first.variants, VariantName(option[i].value))); j++; - XtSetArg(args[j], XtNborderWidth, (gameInfo.variant == option[i].value)+1); j++; - } - option[i].handle = (void*) - (dialog = last = XtCreateManagedWidget(option[i].name, commandWidgetClass, form, args, j)); - if(option[i].choice && ((char*)option[i].choice)[0] == '#' && !engineDlg) { // for the color picker default-reset - SetColor( *(char**) option[i-1].target, &option[i]); - XtAddEventHandler(option[i-1].handle, KeyReleaseMask, False, ColorChanged, (XtPointer)(intptr_t) i-1); - } - XtAddCallback(last, XtNcallback, GenericCallback, (XtPointer)(intptr_t) i + (dlgNr<<16)); // invokes user callback - if(option[i].textValue) SetColor( option[i].textValue, &option[i]); // for new-variant buttons - break; - case ComboBox: - j = SetPositionAndSize(args, last, lastrow, 0 /* border */, - 0 /* w */, textHeight /* h */, 0xC0 /* chain both sides to left edge */); - XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++; - XtSetArg(args[j], XtNlabel, _(option[i].name)); j++; - texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j); - - if(option[i].min & COMBO_CALLBACK) msg = _(option[i].name); else { - if(!engineDlg) SetCurrentComboSelection(option+i); - msg=_(((char**)option[i].choice)[option[i].value]); - } - - j = SetPositionAndSize(args, dialog, last, (option[i].min & 2) == 0 /* border */, - option[i].max && !engineDlg ? option[i].max : 100 /* w */, - textHeight /* h */, 0x91 /* chain */); // same row as its label! - XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++; - XtSetArg(args[j], XtNlabel, msg); j++; - shrink = TRUE; - option[i].handle = (void*) - (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j)); - CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, -1); - values[i] = option[i].value; - break; - case ListBox: - // Listbox goes in viewport, as needed for game list - if(option[i].min & SAME_ROW) forelast = lastrow; - j = SetPositionAndSize(args, last, lastrow, 1 /* border */, - option[i].max /* w */, option[i].value /* h */, option[i].min /* chain */); - XtSetArg(args[j], XtNresizable, False); j++; - XtSetArg(args[j], XtNallowVert, True); j++; // scoll direction - last = - XtCreateManagedWidget("viewport", viewportWidgetClass, form, args, j); - j = 0; // now list itself - XtSetArg(args[j], XtNdefaultColumns, 1); j++; - XtSetArg(args[j], XtNforceColumns, True); j++; - XtSetArg(args[j], XtNverticalList, True); j++; - option[i].handle = (void*) - (edit = XtCreateManagedWidget("list", listWidgetClass, last, args, j)); - XawListChange(option[i].handle, option[i].target, 0, 0, True); - XawListHighlight(option[i].handle, 0); - scrollTranslations[25] = '0' + i; - scrollTranslations[27] = 'A' + dlgNr; - XtOverrideTranslations(edit, XtParseTranslationTable(scrollTranslations)); // for mouse-wheel - break; - case Graph: - j = SetPositionAndSize(args, last, lastrow, 0 /* border */, - option[i].max /* w */, option[i].value /* h */, option[i].min /* chain */); - option[i].handle = (void*) - (last = XtCreateManagedWidget("graph", widgetClass, form, args, j)); - XtAddEventHandler(last, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask, False, - (XtEventHandler) GraphEventProc, &option[i]); // mandatory user-supplied expose handler - if(option[i].min & SAME_ROW) last = forelast, forelast = lastrow; - option[i].choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, option[i].max, option[i].value); // image buffer - break; - case PopUp: // note: used only after Graph, so 'last' refers to the Graph widget - option[i].handle = (void*) CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, option[i].value); - break; - case BoxBegin: - if(option[i].min & SAME_ROW) forelast = lastrow; - j = SetPositionAndSize(args, last, lastrow, 0 /* border */, - 0 /* w */, 0 /* h */, option[i].min /* chain */); - XtSetArg(args[j], XtNorientation, XtorientHorizontal); j++; - XtSetArg(args[j], XtNvSpace, 0); j++; - option[box=i].handle = (void*) - (last = XtCreateWidget("box", boxWidgetClass, form, args, j)); - oldForm = form; form = last; oldLastRow = lastrow; oldForeLast = forelast; - lastrow = NULL; last = NULL; - break; - case DropDown: - j = SetPositionAndSize(args, last, lastrow, 0 /* border */, - 0 /* w */, 0 /* h */, 1 /* chain (always on same row) */); - forelast = lastrow; - msg = _(option[i].name); // write name on the menu button - XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++; - XtSetArg(args[j], XtNlabel, msg); j++; - option[i].handle = (void*) - (last = XtCreateManagedWidget(option[i].name, menuButtonWidgetClass, form, args, j)); - option[i].textValue = (char*) CreateComboPopup(last, option + i, i + 256*dlgNr, FALSE, -1); - break; - case BoxEnd: - XtManageChildren(&form, 1); - SqueezeIntoBox(&option[box], i-box, option[box].max); - if(option[i].target) ((ButtonCallback*)option[i].target)(box); // callback that can make sizing decisions - last = form; lastrow = oldLastRow; form = oldForm; forelast = oldForeLast; - break; - case Break: - width++; - height = i+1; - stack = !(option[i].min & SAME_ROW); - break; - default: - printf("GenericPopUp: unexpected case in switch.\n"); - break; - } - } - - // make an attempt to align all spins and textbox controls - maxWidth = maxTextWidth = 0; - if(browse != NULL) { - j=0; - XtSetArg(args[j], XtNwidth, &bWidth); j++; - XtGetValues(browse, args, j); - } - for(h=0; h maxWidth) maxWidth = w; - widest = texts[h]; - } else { - if(w > maxTextWidth) maxTextWidth = w; - if(!widest) widest = texts[h]; - } - } - } - if(maxTextWidth + 110 < maxWidth) - maxTextWidth = maxWidth - 110; - else maxWidth = maxTextWidth + 110; - for(h=0; hWM_PROTOCOLS: GenericPopDown(\"%d\") \n", dlgNr); - XtAugmentTranslations(popup, XtParseTranslationTable(def)); - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - } - XtPopup(popup, modal ? XtGrabExclusive : XtGrabNone); - shellUp[dlgNr]++; // count rather than flag - previous = NULL; - if(textField) SetFocus(textField, popup, (XEvent*) NULL, False); - if(dlgNr && wp[dlgNr] && wp[dlgNr]->width > 0) { // if persistent window-info available, reposition - j = 0; - XtSetArg(args[j], XtNheight, (Dimension) (wp[dlgNr]->height)); j++; - XtSetArg(args[j], XtNwidth, (Dimension) (wp[dlgNr]->width)); j++; - XtSetArg(args[j], XtNx, (Position) (wp[dlgNr]->x)); j++; - XtSetArg(args[j], XtNy, (Position) (wp[dlgNr]->y)); j++; - XtSetValues(popup, args, j); - } - RaiseWindow(dlgNr); - return 1; // tells caller he must do initialization (e.g. add specific event handlers) -} - - -/* function called when the data to Paste is ready */ -static void -SendTextCB (Widget w, XtPointer client_data, Atom *selection, - Atom *type, XtPointer value, unsigned long *len, int *format) -{ - char buf[MSG_SIZ], *p = (char*) textOptions[(int)(intptr_t) client_data].choice, *name = (char*) value, *q; - if (value==NULL || *len==0) return; /* nothing selected, abort */ - name[*len]='\0'; - strncpy(buf, p, MSG_SIZ); - q = strstr(p, "$name"); - snprintf(buf + (q-p), MSG_SIZ -(q-p), "%s%s", name, q+5); - SendString(buf); - XtFree(value); -} - -void -SendText (int n) -{ - char *p = (char*) textOptions[n].choice; - if(strstr(p, "$name")) { - XtGetSelectionValue(menuBarWidget, - XA_PRIMARY, XA_STRING, - /* (XtSelectionCallbackProc) */ SendTextCB, - (XtPointer) (intptr_t) n, /* client_data passed to PastePositionCB */ - CurrentTime - ); - } else SendString(p); -} - -void -SetInsertPos (Option *opt, int pos) -{ - Arg args[16]; - XtSetArg(args[0], XtNinsertPosition, pos); - XtSetValues(opt->handle, args, 1); -// SetFocus(opt->handle, shells[InputBoxDlg], NULL, False); // No idea why this does not work, and the following is needed: -// XSetInputFocus(xDisplay, XtWindow(opt->handle), RevertToPointerRoot, CurrentTime); -} - -void -TypeInProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ // can be used as handler for any text edit in any dialog (from GenericPopUp, that is) - int n = prms[0][0] - '0'; - Widget sh = XtParent(XtParent(XtParent(w))); // popup shell - - if(n<2) { // Enter or Esc typed from primed text widget: treat as if dialog OK or cancel button hit. - int dlgNr; // figure out what the dialog number is by comparing shells (because we must pass it :( ) - for(dlgNr=0; dlgNrhandle), RevertToPointerRoot, CurrentTime); -} - - -- 1.7.0.4