From 0d88b7c20af19de163b648898ec8d3ed4c31d796 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Mon, 22 Oct 2012 17:40:08 +0200 Subject: [PATCH] Delete emptied front-end files, and move rest to gtk directory Remove #ifdeffed-out Xt code that has GTK implementation. The xgamelist and xhistory have been completely cleared off content, and were removed. --- Makefile.am | 8 +- dialogs.h | 2 +- frontend.h | 1 + gtk/xboard.c | 2186 ++++++++++++++++++++++++++++++++++++++++++++ gtk/xboard.h | 175 ++++ gtk/xengineoutput.c | 149 +++ gtk/xoptions.c | 1565 ++++++++++++++++++++++++++++++++ gtk/xtimer.c | 239 +++++ menus.c | 1 - menus.h | 1 + nhistory.c | 8 +- xaw/xhistory.c | 8 +- xboard.c | 2501 --------------------------------------------------- xboard.h | 175 ---- xengineoutput.c | 149 --- xgamelist.c | 90 -- xgamelist.h | 33 - xhistory.c | 65 -- xhistory.h | 29 - xoptions.c | 2004 ----------------------------------------- xtimer.c | 239 ----- 21 files changed, 4332 insertions(+), 5296 deletions(-) create mode 100644 gtk/.dirstamp create mode 100644 gtk/xboard.c create mode 100644 gtk/xboard.h create mode 100644 gtk/xengineoutput.c create mode 100644 gtk/xoptions.c create mode 100644 gtk/xtimer.c delete mode 100644 xboard.c delete mode 100644 xboard.h delete mode 100644 xengineoutput.c 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 delete mode 100644 xtimer.c diff --git a/Makefile.am b/Makefile.am index 3cb4956..96aebba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,10 +10,9 @@ endif ### define sources for the front-end and backend -GTKsources = xboard.c xtimer.c xgamelist.c \ - xhistory.c xoptions.c xboard.h \ - xengineoutput.c xgamelist.h \ - xhistory.h +GTKsources = gtk/xboard.c gtk/xboard.h \ + gtk/xoptions.c gtk/xtimer.c \ + gtk/xengineoutput.c Xsources = xaw/xboard.c xaw/xboard.h \ xaw/xengineoutput.c \ @@ -49,6 +48,7 @@ backendsources = backend.c backend.h backendz.h \ if withGTK xboard_SOURCES = $(backendsources) $(GTKsources) + headers = -I gtk endif if withXaw xboard_SOURCES = $(backendsources) $(Xsources) diff --git a/dialogs.h b/dialogs.h index 6c3c201..498feeb 100644 --- a/dialogs.h +++ b/dialogs.h @@ -152,6 +152,7 @@ void SetDialogTitle P((DialogClass dlg, char *title)); void LoadListBox P((Option *opt, char *emptyText, int n1, int n2)); void HighlightListBoxItem P((Option *opt, int nr)); void HighlightWithScroll P((Option *opt, int sel, int max)); +void ScrollToCursor P((Option *opt, int pos)); int SelectedListBoxItem P((Option *opt)); void BoardFocus P((void)); void FocusOnWidget P((Option *opt, DialogClass dlg)); @@ -191,4 +192,3 @@ void SendString P((char *p)); int GameListClicks P((int direction)); void SetFilter P((void)); - diff --git a/frontend.h b/frontend.h index 01d0da0..949bb18 100644 --- a/frontend.h +++ b/frontend.h @@ -237,5 +237,6 @@ void SlavePopUp P((void)); /* these are in xhistory.c */ Boolean MoveHistoryIsUp P((void)); void HistoryPopUp P((void)); +void FindMoveByCharIndex P(( int char_index )); #endif /* XB_FRONTEND */ diff --git a/gtk/.dirstamp b/gtk/.dirstamp new file mode 100644 index 0000000..e69de29 diff --git a/gtk/xboard.c b/gtk/xboard.c new file mode 100644 index 0000000..44c9984 --- /dev/null +++ b/gtk/xboard.c @@ -0,0 +1,2186 @@ +/* + * 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 +#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 + +// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are. +#include "common.h" + +#include "frontend.h" +#include "backend.h" +#include "backendz.h" +#include "moves.h" +#include "xboard.h" +#include "xboard2.h" +#include "childio.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)); +#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 DelayedDrag P((void)); +void ICSInputBoxPopUp P((void)); +gboolean KeyPressProc P((GtkWindow *window, GdkEventKey *eventkey, gpointer data)); +Boolean TempBackwardActive = False; +void DisplayMove P((int moveNumber)); +void ICSInitScript P((void)); +void update_ics_width P(()); +int CopyMemoProc P(()); +static gboolean EventProc P((GtkWidget *widget, GdkEvent *event, gpointer g)); + +#ifdef TODO_GTK +#if ENABLE_NLS +XFontSet fontSet, clockFontSet; +#else +Font clockFontID; +XFontStruct *clockFontStruct; +#endif +Font coordFontID, countFontID; +XFontStruct *coordFontStruct, *countFontStruct; +#else +void *shellWidget, *formWidget, *boardWidget, *titleWidget, *dropMenu, *menuBarWidget; +GtkWidget *mainwindow; +#endif +Option *optList; // contains all widgets of main window +char *layoutName; + +char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion + +/* pixbufs */ +static GdkPixbuf *mainwindowIcon=NULL; +static GdkPixbuf *WhiteIcon=NULL; +static GdkPixbuf *BlackIcon=NULL; + +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; +#ifdef TODO_GTK +Dimension textHeight; +#endif +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" } +}; + +#ifdef TODO_GTK +XtResource clientResources[] = { + { "flashCount", "flashCount", XtRInt, sizeof(int), + XtOffset(AppDataPtr, flashCount), XtRImmediate, + (XtPointer) FLASH_COUNT }, +}; +#endif + +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"; + +#ifdef TODO_GTK +String xboardResources[] = { + "*Error*translations: #override\\n Return: ErrorPopDown()", + NULL + }; +#endif + +/* Max possible square size */ +#define MAXSQSIZE 256 + +static int xpm_avail[MAXSQSIZE]; + + +void +BoardToTop () +{ + gtk_window_present(GTK_WINDOW(mainwindow)); +} + +//--------------------------------------------------------------------------------------------------------- +// 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 (GtkWidget *shell, WindowPlacement *wp) +{ + GtkAllocation a; + if(!shell) return; + gtk_widget_get_allocation(shell, &a); + wp->x = a.x; + wp->y = a.y; + wp->width = a.width; + wp->height = a.height; +printf("placement\n"); + frameX = a.x; frameY = a.y; // remember to decide if windows touch +} +#ifdef TODO_GTK +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 +} +#endif + +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 DialogExists(BoardWindow); +} + +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 +#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; + int boardWidth, boardHeight, w, h; + char *p; + int forceMono = False; + GError *gtkerror=NULL; + + 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); + } + + /* set up GTK */ + gtk_init (&argc, &argv); + + programName = strrchr(argv[0], '/'); + if (programName == NULL) + programName = argv[0]; + else + programName++; + +#ifdef ENABLE_NLS +// 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); + } + +#if ENABLE_NLS + if (appData.debugMode) { + fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL)); + } +#endif + + /* [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); + + /* + * 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) { + GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(mainwindow)); + guint screenwidth = gdk_screen_get_width(screen); + guint screenheight = gdk_screen_get_height(screen); + while (screenwidth < szd->minScreenSize || + screenheight < 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. + */ +#ifdef TODO_GTK + InitializeFonts(clockFontPxlSize, coordFontPxlSize, fontPxlSize); +#endif + + /* + * Detect if there are not enough colors available and adapt. + */ +#ifdef TODO_GTK + if (DefaultDepth(xDisplay, xScreen) <= 2) { + appData.monoMode = True; + } +#endif + + forceMono = MakeColors(); + + if (forceMono) { + fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"), + programName); + appData.monoMode = True; + } + + ParseIcsTextColors(); + + /* + * widget hierarchy + */ + if (tinyLayout) { + layoutName = "tinyLayout"; + } else if (smallLayout) { + layoutName = "smallLayout"; + } else { + layoutName = "normalLayout"; + } + + optList = BoardPopUp(squareSize, lineGap, (void*) +#ifdef TODO_GTK +#if ENABLE_NLS + &clockFontSet); +#else + clockFontStruct); +#endif +#else +0); +#endif + InitDrawingHandle(optList + W_BOARD); + shellWidget = shells[BoardWindow]; + 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; +#ifdef TODO_GTK + 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); + } +#endif + + // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would + // not need to go into InitDrawingSizes(). + + InitMenuMarkers(); + + /* + * Create an icon. (Use two icons, to indicate whther it is white's or black's turn.) + */ + WhiteIcon = gdk_pixbuf_new_from_file(SVGDIR "/icon_white.svg", NULL); + BlackIcon = gdk_pixbuf_new_from_file(SVGDIR "/icon_black.svg", NULL); + mainwindowIcon = WhiteIcon; + gtk_window_set_icon(GTK_WINDOW(shellWidget), mainwindowIcon); + + + /* + * Create a cursor for the board widget. + */ +#ifdef TODO_GTK + window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2); + XChangeWindowAttributes(xDisplay, xBoardWindow, + CWCursor, &window_attributes); +#endif + + /* + * Inhibit shell resizing. + */ +#ifdef TODO_GTK + 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); +#endif + { + GtkAllocation a; + gtk_widget_get_allocation(shells[BoardWindow], &a); + w = a.width; h = a.height; +printf("start size (%d,%d), %dx%d\n", a.x, a.y, w, h); + } + marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board + marginH = h - boardHeight; + + 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(); + + g_signal_connect(shells[BoardWindow], "key-press-event", G_CALLBACK(KeyPressProc), NULL); + g_signal_connect(shells[BoardWindow], "configure-event", G_CALLBACK(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); +#ifdef TODO_GTK + XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime); +#endif + + /* check for GTK events and process them */ +// gtk_main(); +while(1) { +gtk_main_iteration(); +} + + 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; +} + +#ifdef TODO_GTK +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; +} +#endif +#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; + +#ifdef TODO_GTK + 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); +#endif + return p; +} +#endif + +void +EnableNamedMenuItem (char *menuRef, int state) +{ + MenuItem *item = MenuNameToItem(menuRef); + + if(item) gtk_widget_set_sensitive(item->handle, state); +} + +void +EnableButtonBar (int state) +{ +#ifdef TODO_GTK + XtSetSensitive(optList[W_BUTTON].handle, state); +#endif +} + + +void +SetMenuEnables (Enables *enab) +{ + while (enab->name != NULL) { + EnableNamedMenuItem(enab->name, enab->value); + enab++; + } +} + +gboolean KeyPressProc(window, eventkey, data) + GtkWindow *window; + GdkEventKey *eventkey; + gpointer data; +{ + + MoveTypeInProc(eventkey); // pop up for typed in moves + +#ifdef TODO_GTK + /* check for other key values */ + switch(eventkey->keyval) { + case GDK_question: + AboutGameEvent(); + break; + default: + break; + } +#endif + return False; +} +#ifdef TODO_GTK +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) (); +} +#endif + +void +SetupDropMenu () +{ +#ifdef TODO_GTK + 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 (GtkWidget *sh, WindowPlacement *wp) +{ + 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); +#ifdef TODO_GTK + if(heightInc) XtSetArg(args[j], XtNheight, wp->height + heightInc), j++; +#endif + } 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); +#ifdef TODO_GTK + if(widthInc) XtSetArg(args[j], XtNwidth, wp->width + widthInc), j++; +#endif + } + 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; +#ifdef TODO_GTK + XtSetArg(args[j], XtNx, wp->x); j++; + XtSetArg(args[j], XtNy, wp->y); j++; + XtSetValues(sh, args, j); +#endif +} + +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 guint delayedDragTag = 0; + +void +DragProc () +{ + static int busy; + if(busy) return; + + busy = 1; +// GetActualPlacement(shellWidget, &wpNew); +printf("drag proc (%d,%d) %dx%d\n", wpNew.x, wpNew.y, wpNew.width, wpNew.height); + 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); + if(delayedDragTag) g_source_remove(delayedDragTag); + delayedDragTag = 0; // now drag executed, make sure next DelayedDrag will not cancel timer event (which could now be used by other) + busy = 0; +} + +void +DelayedDrag () +{ +printf("old timr = %d\n", delayedDragTag); + if(delayedDragTag) g_source_remove(delayedDragTag); + delayedDragTag = g_timeout_add( 200, (GSourceFunc) DragProc, NULL); +printf("new timr = %d\n", delayedDragTag); +} + +static gboolean +EventProc (GtkWidget *widget, GdkEvent *event, gpointer g) +{ +printf("event proc (%d,%d) %dx%d\n", event->configure.x, event->configure.y, event->configure.width, event->configure.height); + // immediately + wpNew.x = event->configure.x; + wpNew.y = event->configure.y; + wpNew.width = event->configure.width; + wpNew.height = event->configure.height; + if(appData.useStickyWindows) + DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other + return FALSE; +} + + + +/* 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 */ + gtk_grab_add(optList[W_MESSG].handle); + frozen = 1; +} + +/* Undo a FreezeUI */ +void +ThawUI () +{ + if (!frozen) return; + gtk_grab_remove(optList[W_MESSG].handle); + frozen = 0; +} + +void +ModeHighlight () +{ + static int oldPausing = FALSE; + static GameMode oldmode = (GameMode) -1; + char *wname; + if (!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. */ + GdkColor color; + gdk_color_parse( pausing ? "#808080" : "#F0F0F0", &color ); + gtk_widget_modify_bg ( GTK_WIDGET(optList[W_PAUSE].handle), GTK_STATE_NORMAL, &color ); + } + } + + 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 + */ + +void CopyFileToClipboard(gchar *filename) +{ + gchar *selection_tmp; + GtkClipboard *cb; + + // read the file + FILE* f = fopen(filename, "r"); + long len; + size_t count; + if (f == NULL) return; + fseek(f, 0, 2); + len = ftell(f); + rewind(f); + selection_tmp = g_try_malloc(len + 1); + if (selection_tmp == NULL) { + printf("Malloc failed in CopyFileToClipboard\n"); + return; + } + count = fread(selection_tmp, 1, len, f); + fclose(f); + if (len != count) { + g_free(selection_tmp); + return; + } + selection_tmp[len] = NULLCHAR; // file is now in selection_tmp + + // copy selection_tmp to clipboard + GdkDisplay *gdisp = gdk_display_get_default(); + if (!gdisp) { + g_free(selection_tmp); + return; + } + cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text(cb, selection_tmp, -1); + g_free(selection_tmp); +} + +void +CopySomething (char *src) +{ + GdkDisplay *gdisp = gdk_display_get_default(); + GtkClipboard *cb; + if(!src) { CopyFileToClipboard(gameCopyFilename); return; } + if (gdisp == NULL) return; + cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text(cb, src, -1); +} + +void +PastePositionProc () +{ + GdkDisplay *gdisp = gdk_display_get_default(); + GtkClipboard *cb; + gchar *fenstr; + + if (gdisp == NULL) return; + cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); + fenstr = gtk_clipboard_wait_for_text(cb); + if (fenstr==NULL) return; // nothing had been selected to copy + EditPositionPasteFEN(fenstr); + return; +} + +void +PasteGameProc () +{ + gchar *text=NULL; + GtkClipboard *cb; + guint len=0; + FILE* f; + + // get game from clipboard + GdkDisplay *gdisp = gdk_display_get_default(); + if (gdisp == NULL) return; + cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); + text = gtk_clipboard_wait_for_text(cb); + if (text == NULL) return; // nothing to paste + len = strlen(text); + + // write to temp file + if (text == NULL || len == 0) { + return; //nothing to paste + } + f = fopen(gamePasteFilename, "w"); + if (f == NULL) { + DisplayError(_("Can't open temp file"), errno); + return; + } + fwrite(text, 1, len, f); + fclose(f); + + // load from file + LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE); + return; +} + + +#ifdef TODO_GTK +void +QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + QuitProc(); +} +#endif + +void MoveTypeInProc(eventkey) + GdkEventKey *eventkey; +{ + char buf[10]; + + // ingnore if ctrl or alt is pressed + if (eventkey->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) { + return; + } + + buf[0]=eventkey->keyval; + buf[1]='\0'; + if (*buf >= 32) + BoxAutoPopUp (buf); +} + +#ifdef TODO_GTK +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); +} +#endif + +void +ManProc () +{ // called from menu +#ifdef TODO_GTK + ManInner(NULL, NULL, NULL, NULL); +#endif +} + +void +SetWindowTitle (char *text, char *title, char *icon) +{ +#ifdef TODO_GTK + 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); +#endif + if (appData.titleInWindow) { + SetWidgetLabel(titleWidget, text); + } + gtk_window_set_title (GTK_WINDOW(shells[BoardWindow]), title); +} + + +static int +NullXErrorCheck (Display *dpy, XErrorEvent *error_event) +{ + return 0; +} + +void +DisplayIcsInteractionTitle (String message) +{ +#ifdef TODO_GTK + 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); +#endif +} + + +void +DisplayTimerLabel (Option *opt, char *color, long timer, int highlight) +{ + GtkWidget *w = (GtkWidget *) opt->handle; + char *markup; + char bgcolor[10]; + char fgcolor[10]; + + if (highlight) { + strcpy(bgcolor, "black"); + strcpy(fgcolor, "white"); + } else { + strcpy(bgcolor, "white"); + strcpy(fgcolor, "black"); + } + if (timer > 0 && + appData.lowTimeWarning && + (timer / 1000) < appData.icsAlarmTime) { + strcpy(fgcolor, appData.lowTimeWarningColor); + } + + if (appData.clockMode) { + markup = g_markup_printf_escaped("%s:%s%s", + bgcolor, fgcolor, color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer)); + } else { + markup = g_markup_printf_escaped("%s ", + bgcolor, fgcolor, color); + } + gtk_label_set_markup(GTK_LABEL(w), markup); + g_free(markup); +} + +static GdkPixbuf **clockIcons[] = { &WhiteIcon, &BlackIcon }; + +void +SetClockIcon (int color) +{ + GdkPixbuf *pm = *clockIcons[color]; + if (mainwindowIcon != pm) { + mainwindowIcon = pm; + gtk_window_set_icon(GTK_WINDOW(shellWidget), mainwindowIcon); + } +} + +#define INPUT_SOURCE_BUF_SIZE 8192 + +typedef struct { + CPKind kind; + int fd; + int lineByLine; + char *unused; + InputCallback func; + guint sid; + char buf[INPUT_SOURCE_BUF_SIZE]; + VOIDSTAR closure; +} InputSource; + +gboolean +DoInputCallback(io, cond, data) + GIOChannel *io; + GIOCondition cond; + gpointer *data; +{ + /* read input from one of the input source (for example a chess program, ICS, etc). + * and call a function that will handle the input + */ + + int count; + int error; + char *p, *q; + + /* All information (callback function, file descriptor, etc) is + * saved in an InputSource structure + */ + InputSource *is = (InputSource *) data; + + 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 True; + } + is->unused += count; + p = is->buf; + /* break input into lines and call the callback function on each + * line + */ + 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; + } + /* remember not yet used part of the buffer */ + q = is->buf; + while (p < is->unused) { + *q++ = *p++; + } + is->unused = q; + } else { + /* read maximum length of input buffer and send the whole buffer + * to the callback function + */ + 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); + } + return True; // Must return true or the watch will be removed +} + +InputSourceRef AddInputSource(pr, lineByLine, func, closure) + ProcRef pr; + int lineByLine; + InputCallback func; + VOIDSTAR closure; +{ + InputSource *is; + GIOChannel *channel; + 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; + else + is->unused = NULL; + + /* GTK-TODO: will this work on windows?*/ + + channel = g_io_channel_unix_new(is->fd); + g_io_channel_set_close_on_unref (channel, TRUE); + is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is); + + is->closure = closure; + return (InputSourceRef) is; +} + + +void +RemoveInputSource(isr) + InputSourceRef isr; +{ + InputSource *is = (InputSource *) isr; + + if (is->sid == 0) return; + g_source_remove(is->sid); + is->sid = 0; + return; +} + +#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; + + 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) +{ +#ifdef TODO_GTK + XSync(xDisplay, False); +#endif +// gtk_main_iteration_do(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; +} + +void FileNamePopUpGTK(label, def, filter, proc, pathFlag, openMode, name, fp) + char *label; + char *def; + char *filter; + FileProc proc; + char *openMode; + Boolean pathFlag; + char **name; + FILE **fp; +{ + GtkWidget *dialog; + GtkFileFilter *gtkfilter; + GtkFileFilter *gtkfilter_all; + char space[] = " "; + char fileext[10] = ""; + char *result = NULL; + char *cp; + + /* make a copy of the filter string, so that strtok can work with it*/ + cp = strndup(filter,strlen(filter)); + + /* add filters for file extensions */ + gtkfilter = gtk_file_filter_new(); + gtkfilter_all = gtk_file_filter_new(); + + /* one filter to show everything */ + gtk_file_filter_add_pattern(gtkfilter_all, "*.*"); + gtk_file_filter_set_name (gtkfilter_all, "All Files"); + + /* add filter if present */ + result = strtok(cp, space); + while( result != NULL ) { + snprintf(fileext,10,"*%s",result); + result = strtok( NULL, space ); + gtk_file_filter_add_pattern(gtkfilter, fileext); + }; + + /* second filter to only show what's useful */ + gtk_file_filter_set_name (gtkfilter,filter); + + if (openMode[0] == 'r') + { + dialog = gtk_file_chooser_dialog_new (label, + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + } + else + { + dialog = gtk_file_chooser_dialog_new (label, + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + /* add filename suggestions */ + if (strlen(def) > 0 ) + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), def); + + //gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER (dialog),TRUE); + } + + /* add filters */ + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter_all); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); + /* activate filter */ + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + char *filename; + FILE *f; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + //see loadgamepopup + f = fopen(filename, openMode); + if (f == NULL) + { + DisplayError(_("Failed to open file"), errno); + } + else + { + /* TODO add indec */ + *fp = f; + ASSIGN(*name, filename); + ScheduleDelayedEvent(DelayedLoad, 50); + } + g_free (filename); + }; + + gtk_widget_destroy (dialog); + ModeHighlight(); + + free(cp); + return; + +} + diff --git a/gtk/xboard.h b/gtk/xboard.h new file mode 100644 index 0000000..3527343 --- /dev/null +++ b/gtk/xboard.h @@ -0,0 +1,175 @@ +/* + * 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)); +#ifdef TODO_GTK +void CatchDeleteWindow(Widget w, String procname); +void GenericPopDown P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +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)); +#endif + +extern char memoTranslations[]; + +#if TODO_GTK +extern Widget shells[]; +extern Widget formWidget, shellWidget, boardWidget, menuBarWidget; +extern Display *xDisplay; +extern Window xBoardWindow; +extern Pixmap xMarkPixmap, wIconPixmap, bIconPixmap; +extern Pixel timerForegroundPixel, timerBackgroundPixel, dialogColor, buttonColor; +extern Atom wm_delete_window; +extern GC coordGC; +extern Dimension textHeight; // of message widget in board window +#else +extern GtkWidget *shells[]; +#endif +extern int dialogError; +extern int squareSize; +extern char *layoutName; +extern int useImages, useImageSqs; +extern char ICSInputTranslations[]; +extern char *selected_fen_position; + + +#define TOPLEVEL 1 /* preference item; 1 = make popup windows toplevel */ + diff --git a/gtk/xengineoutput.c b/gtk/xengineoutput.c new file mode 100644 index 0000000..576d58b --- /dev/null +++ b/gtk/xengineoutput.c @@ -0,0 +1,149 @@ +/* + * 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 "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 + +extern Option engoutOptions[]; // must go in header, but which? + +/* Module variables */ +static int currentPV, highTextStart[2], highTextEnd[2]; +#ifdef TODO_GTK +static Widget memoWidget; +#endif +static GdkPixbuf *iconsGTK[8]; +static GtkWidget *outputFieldGTK[2][7]; // [HGM] front-end array to translate output field to window handlestatic void *memoWidget; + +static void +ReadIcon (gchar *svgFilename, int iconNr) +{ + char buf[MSG_SIZ]; + + snprintf(buf, MSG_SIZ, "%s/%s", SVGDIR, svgFilename); + iconsGTK[iconNr] = gdk_pixbuf_new_from_file(buf, NULL); +} + +void +InitEngineOutput (Option *opt, Option *memo2) +{ // front-end, because it must have access to the pixmaps +#ifdef TODO_GTK + Widget w = opt->handle; + memoWidget = memo2->handle; +#endif + ReadIcon("eo_White.svg", nColorWhite); + ReadIcon("eo_Black.svg", nColorBlack); + ReadIcon("eo_Unknown.svg", nColorUnknown); + + ReadIcon("eo_Clear.svg", nClear); + ReadIcon("eo_Ponder.svg", nPondering); + ReadIcon("eo_Thinking.svg", nThinking); + ReadIcon("eo_Analyzing.svg", nAnalyzing); +} + +void +DrawWidgetIcon (Option *opt, int nIcon) +{ // as we are already in GTK front-end, so do GTK-stuff here + if( nIcon != 0 ) gtk_image_set_from_pixbuf(GTK_IMAGE(opt->handle), GDK_PIXBUF(iconsGTK[nIcon])); +} + +void +InsertIntoMemo (int which, char * text, int where) +{ + char *p; + GtkTextIter start; + + /* the backend adds \r\n, which is needed for winboard, + * for xboard we delete them again over here */ + if(p = strchr(text, '\r')) *p = ' '; + + GtkTextBuffer *tb = (GtkTextBuffer *) (engoutOptions[which ? 12 : 5].handle); +// gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(tb), &start); + gtk_text_buffer_get_iter_at_offset(tb, &start, where); + gtk_text_buffer_insert(tb, &start, text, -1); + if(where < highTextStart[which]) { // [HGM] multiPVdisplay: move highlighting + int len = strlen(text); + highTextStart[which] += len; highTextEnd[which] += len; + } +} + +//--------------------------------- 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"; + +//------------------------------- 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) + if(mode) gtk_widget_show(engoutOptions[13].handle); + else gtk_widget_hide(engoutOptions[13].handle); +} + diff --git a/gtk/xoptions.c b/gtk/xoptions.c new file mode 100644 index 0000000..f5d223c --- /dev/null +++ b/gtk/xoptions.c @@ -0,0 +1,1565 @@ +/* + * 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 "common.h" +#include "backend.h" +#include "xboard.h" +#include "xboard2.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 + +#ifdef TODO_GTK +static Widget previous = NULL; +#endif +static Option *currentOption; +static Boolean browserUp; + +void +UnCaret () +{ +#ifdef TODO_GTK + Arg args[2]; + + if(previous) { + XtSetArg(args[0], XtNdisplayCaret, False); + XtSetValues(previous, args, 1); + } + previous = NULL; +#endif +} + +#ifdef TODO_GTK +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; +} +#endif + +void +BoardFocus () +{ +#ifdef TODO_GTK + XtSetKeyboardFocus(shellWidget, formWidget); +#endif +} + +//--------------------------- Engine-specific options menu ---------------------------------- + +int dialogError; +Option *dialogOptions[NrOfDialogs]; + +#ifdef TODO_GTK +static Arg layoutArgs[] = { + { XtNborderWidth, 0 }, + { XtNdefaultDistance, 0 }, +}; + +static Arg formArgs[] = { + { XtNborderWidth, 0 }, + { XtNresizable, (XtArgVal) True }, +}; +#endif + +void +MarkMenuItem (char *menuRef, int state) +{ + MenuItem *item = MenuNameToItem(menuRef); + + if(item) { + ((GtkCheckMenuItem *) (item->handle))->active = state; + } +} + +void GetWidgetTextGTK(GtkWidget *w, char **buf) +{ + GtkTextIter start; + GtkTextIter end; + + if (GTK_IS_ENTRY(w)) { + *buf = gtk_entry_get_text(GTK_ENTRY (w)); + } else + if (GTK_IS_TEXT_BUFFER(w)) { + gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(w), &start); + gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(w), &end); + *buf = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(w), &start, &end, FALSE); + } + else { + printf("error in GetWidgetText, invalid widget\n"); + *buf = NULL; + } +} + +void +GetWidgetText (Option *opt, char **buf) +{ + int x; + static char val[12]; + switch(opt->type) { + case Fractional: + case FileName: + case PathName: + case TextBox: GetWidgetTextGTK((GtkWidget *) opt->handle, buf); break; + case Spin: + x = gtk_spin_button_get_value (GTK_SPIN_BUTTON(opt->handle)); + snprintf(val, 12, "%d", x); *buf = val; + break; + default: + printf("unexpected case (%d) in GetWidgetText\n", opt->type); + *buf = NULL; + } +} + +void SetSpinValue(Option *opt, char *val, int n) +{ + if (opt->type == Spin) + { + if (!strcmp(val, _("Unused"))) + gtk_widget_set_sensitive(opt->handle, FALSE); + else + { + gtk_widget_set_sensitive(opt->handle, TRUE); + gtk_spin_button_set_value(opt->handle, atoi(val)); + } + } + else + printf("error in SetSpinValue, unknown type %d\n", opt->type); +} + +void SetWidgetTextGTK(GtkWidget *w, char *text) +{ + if (GTK_IS_ENTRY(w)) { + gtk_entry_set_text (GTK_ENTRY (w), text); + } else + if (GTK_IS_TEXT_BUFFER(w)) { + gtk_text_buffer_set_text(GTK_TEXT_BUFFER(w), text, -1); + } else + printf("error: SetWidgetTextGTK arg is neitherGtkEntry nor GtkTextBuffer\n"); +} + +void +SetWidgetText (Option *opt, char *buf, int n) +{ + switch(opt->type) { + case Fractional: + case FileName: + case PathName: + case TextBox: SetWidgetTextGTK((GtkWidget *) opt->handle, buf); break; + case Spin: SetSpinValue(opt, buf, n); break; + default: + printf("unexpected case (%d) in GetWidgetText\n", opt->type); + } +#ifdef TODO_GTK +// focus is automatic in GTK? + if(n >= 0) SetFocus(opt->handle, shells[n], NULL, False); +#endif +} + +void +GetWidgetState (Option *opt, int *state) +{ + *state = gtk_toggle_button_get_active(opt->handle); +} + +void +SetWidgetState (Option *opt, int state) +{ + gtk_toggle_button_set_active(opt->handle, state); +} + +void +SetWidgetLabel (Option *opt, char *buf) +{ + gtk_label_set_text(opt->handle, buf); +} + +void +SetDialogTitle (DialogClass dlg, char *title) +{ + gtk_window_set_title(GTK_WINDOW(shells[dlg]), title); +} + +void +SetListBoxItem (GtkListStore *store, int n, char *msg) +{ + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_indices(n, -1); + gtk_tree_model_get_iter(GTK_TREE_MODEL (store), &iter, path); + gtk_tree_path_free(path); + gtk_list_store_set(store, &iter, 0, msg, -1); +} + +void +LoadListBox (Option *opt, char *emptyText, int n1, int n2) +{ + char **data = (char **) (opt->target); + GtkWidget *list = (GtkWidget *) (opt->handle); + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); + GtkListStore *store = GTK_LIST_STORE(model); + GtkTreeIter iter; + + if(n1 >= 0 && n2 >= 0) { + SetListBoxItem(store, n1, data[n1]); + SetListBoxItem(store, n2, data[n2]); + return; + } + + if (gtk_tree_model_get_iter_first(model, &iter)) + gtk_list_store_clear(store); + + while(*data) { // add elements to listbox one by one + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, *data++, -1); // 0 = first column + } +} + +void +HighlightItem (Option *opt, int index, int scroll) +{ + char *value, **data = (char **) (opt->target); + GtkWidget *list = (GtkWidget *) (opt->handle); + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); + GtkListStore *store = GTK_LIST_STORE(model); + GtkTreePath *path = gtk_tree_path_new_from_indices(index, -1); + GtkTreeIter iter; + gtk_tree_selection_select_path(selection, path); + if(scroll) gtk_tree_view_scroll_to_cell(list, path, NULL, 0, 0, 0); + gtk_tree_path_free(path); +} + +void +HighlightListBoxItem (Option *opt, int index) +{ + HighlightItem (opt, index, FALSE); +} + +void +HighlightWithScroll (Option *opt, int index, int max) +{ + HighlightItem (opt, index, TRUE); // ignore max +} + +void +ScrollToCursor (Option *opt, int caretPos) +{ + static GtkTextIter iter; + gtk_text_buffer_get_iter_at_offset((GtkTextBuffer *) opt->handle, &iter, caretPos); + gtk_text_view_scroll_to_iter((GtkTextView *) opt->textValue, &iter, 0.0, 0, 0.5, 0.5); +} + +int +SelectedListBoxItem (Option *opt) +{ + int i; + char *value, **data = (char **) (opt->target); + GtkWidget *list = (GtkWidget *) (opt->handle); + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); + + GtkTreeModel *model; + GtkTreeIter iter; + if (!gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter)) return -1; + gtk_tree_model_get(model, &iter, 0, &value, -1); + for(i=0; data[i]; i++) if(!strcmp(data[i], value)) return i; + g_free(value); + return -1; +} + +void +FocusOnWidget (Option *opt, DialogClass dlg) +{ + UnCaret(); +#ifdef TODO_GTK + XtSetKeyboardFocus(shells[dlg], opt->handle); +#endif + gtk_widget_grab_focus(opt->handle); +} + +void +SetIconName (DialogClass dlg, char *name) +{ +#ifdef TODO_GTK + 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); +#endif +} + +void ComboSelect(GtkWidget *widget, gpointer addr) +{ + Option *opt = dialogOptions[((intptr_t)addr)>>8]; // applicable option list + gint i = ((intptr_t)addr) & 255; // option number + gint g; + + g = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + values[i] = g; // store in temporary, for transfer at OK + +#if TODO_GTK +// Note: setting text on button is probably automatic +// Is this still needed? Could be all comboboxes that needed a callbak are now listboxes! +#endif + if(opt[i].type == Graph || opt[i].min & COMBO_CALLBACK && (!currentCps || shellUp[BrowserDlg])) { + ((ButtonCallback*) opt[i].target)(i); + return; + } +} + +#ifdef TODO_GTK +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; +} +#endif + +static void +MenuSelect (gpointer addr) // callback for all combo items +{ + 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 + ((ButtonCallback*) opt[i].target)(i); +} + +static GtkWidget * +CreateMenuPopup (Option *opt, int n, int def) +{ // fromList determines if the item texts are taken from a list of strings, or from a menu table + int i; + GtkWidget *menu, *entry; + MenuItem *mb = (MenuItem *) opt->choice; + + menu = gtk_menu_new(); +// menu = XtCreatePopupShell(opt->name, simpleMenuWidgetClass, parent, NULL, 0); + for (i=0; 1; i++) + { + char *msg = mb[i].string; + if(!msg) break; + if(strcmp(msg, "----")) { // + if(!(opt->min & NO_GETTEXT)) msg = _(msg); + if(mb[i].handle) { + entry = gtk_check_menu_item_new_with_label(msg); // should be used for items that can be checkmarked + if(mb[i].handle == RADIO) gtk_check_menu_item_set_draw_as_radio(entry, True); + } else + entry = gtk_menu_item_new_with_label(msg); + gtk_signal_connect_object (GTK_OBJECT (entry), "activate", GTK_SIGNAL_FUNC(MenuSelect), (gpointer) (n<<16)+i); + gtk_widget_show(entry); + } else entry = gtk_separator_menu_item_new(); + gtk_menu_append(GTK_MENU (menu), entry); +//CreateMenuItem(menu, opt->min & NO_GETTEXT ? msg : _(msg), (XtCallbackProc) ComboSelect, (n<<16)+i); + mb[i].handle = (void*) entry; // save item ID, for enabling / checkmarking +// if(i==def) { +// XtSetArg(arg, XtNpopupOnEntry, entry); +// XtSetValues(menu, &arg, 1); +// } + } + return menu; +} + +Option *typeIn; // kludge to distinguish type-in callback from input-box callback + +void +CursorAtEnd (Option *opt) +{ + gtk_editable_set_position(opt->handle, -1); +} + +static gboolean +ICSKeyEvent(GtkWidget *widget, GdkEventKey *event, gpointer g) +{ + Option *opt = (Option *) g; + if(opt == typeIn) { + if(event->keyval == GDK_Return) { + char *val; + GetWidgetText(opt, &val); + TypeInDoneEvent(val); + PopDown(TransientDlg); + return TRUE; + } + return FALSE; + } + + switch(event->keyval) { + case GDK_Return: IcsKey(0); return TRUE; + case GDK_Up: IcsKey(1); return TRUE; + case GDK_Down: IcsKey(-1); return TRUE; + default: return FALSE; + } +} + +int shiftState, controlState; + +static gboolean +TypeInProc (GtkWidget *widget, GdkEventKey *event, gpointer gdata) +{ // This callback catches key presses on text-entries, and uses and as synonyms for dialog OK or Cancel + // *** kludge alert *** If a dialog does want some other action, like sending the line typed in the text-entry to an ICS, + // it should define an OK handler that does so, and returns FALSE to suppress the popdown. + int n = (intptr_t) gdata; + int dlg = n >> 16; + Option *opt; + n &= 0xFFFF; + opt = &dialogOptions[dlg][n]; + + if(opt == icsBox) return ICSKeyEvent(event->keyval); // Intercept ICS Input Box, which needs special treatment + + shiftState = event->state & GDK_SHIFT_MASK; + controlState = event->state & GDK_CONTROL_MASK; + switch(event->keyval) { + case GDK_Return: + if(GenericReadout(dialogOptions[dlg], -1)) PopDown(dlg); + break; + case GDK_Escape: + PopDown(dlg); + break; + default: + return FALSE; + } + return TRUE; +} + +void +HighlightText (Option *opt, int from, int to, Boolean highlight) +{ +# define INIT 0x8000 + static GtkTextIter start, end; + + if(!(opt->min & INIT)) { + opt->min |= INIT; // each memo its own init flag! + gtk_text_buffer_create_tag(opt->handle, "highlight", "background", "yellow", NULL); + gtk_text_buffer_create_tag(opt->handle, "normal", "background", "white", NULL); + } + gtk_text_buffer_get_iter_at_offset(opt->handle, &start, from); + gtk_text_buffer_get_iter_at_offset(opt->handle, &end, to); + gtk_text_buffer_apply_tag_by_name(opt->handle, highlight ? "highlight" : "normal", &start, &end); +} + +int +ShiftKeys () +{ // bassic primitive for determining if modifier keys are pressed + return 3*(shiftState != 0) + 0xC*(controlState != 0); // rely on what last mouse button press left us +} + +static gboolean +GameListEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata) +{ + int n = (int) gdata; + + if(n == 4) { + if(((GdkEventKey *) event)->keyval != GDK_Return) return FALSE; + SetFilter(); + return TRUE; + } + + if(event->type == GDK_KEY_PRESS) { + int ctrl = (((GdkEventKey *) event)->state & GDK_CONTROL_MASK) != 0; + switch(((GdkEventKey *) event)->keyval) { + case GDK_Up: GameListClicks(-1 - 2*ctrl); return TRUE; + case GDK_Left: GameListClicks(-1); return TRUE; + case GDK_Down: GameListClicks(1 + 2*ctrl); return TRUE; + case GDK_Right: GameListClicks(1); return TRUE; + case GDK_Prior: GameListClicks(-4); return TRUE; + case GDK_Next: GameListClicks(4); return TRUE; + case GDK_Home: GameListClicks(-2); return TRUE; + case GDK_End: GameListClicks(2); return TRUE; + case GDK_Return: GameListClicks(0); return TRUE; + default: return FALSE; + } + } + if(event->type != GDK_2BUTTON_PRESS || ((GdkEventButton *) event)->button != 1) return FALSE; + GameListClicks(0); + return TRUE; +} + +static gboolean +MemoEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata) +{ // handle mouse clicks on text widgets that need it + int w, h; + int button=10, f=1; + Option *opt, *memo = (Option *) gdata; + MemoCallback *userHandler = (MemoCallback *) memo->choice; + GdkEventButton *bevent = (GdkEventButton *) event; + GdkEventMotion *mevent = (GdkEventMotion *) event; + GtkTextIter start, end; + String val = NULL; + gboolean res; + gint index, x, y; + + if(memo->type == Label) { ((ButtonCallback*) memo->target)(memo->value); return TRUE; } // only clock widgets use this + + switch(event->type) { // figure out what's up + case GDK_MOTION_NOTIFY: + f = 0; + w = mevent->x; h = mevent->y; + break; + case GDK_BUTTON_RELEASE: + f = -1; // release indicated by negative button numbers + w = bevent->x; h = bevent->y; + button = bevent->button; + break; + case GDK_BUTTON_PRESS: + w = bevent->x; h = bevent->y; + button = bevent->button; + shiftState = bevent->state & GDK_SHIFT_MASK; + controlState = bevent->state & GDK_CONTROL_MASK; +// GTK_TODO: is this really the most efficient way to get the character at the mouse cursor??? + gtk_text_view_window_to_buffer_coords(widget, GTK_TEXT_WINDOW_WIDGET, w, h, &x, &y); + gtk_text_view_get_iter_at_location(widget, &start, x, y); + gtk_text_buffer_place_cursor(memo->handle, &start); + /* get cursor position into index */ + g_object_get(memo->handle, "cursor-position", &index, NULL); + /* get text from textbuffer */ + gtk_text_buffer_get_start_iter (memo->handle, &start); + gtk_text_buffer_get_end_iter (memo->handle, &end); + val = gtk_text_buffer_get_text (memo->handle, &start, &end, FALSE); + break; + default: + return FALSE; // should not happen + } + button *= f; + // hand click parameters as well as text & location to user + res = (userHandler) (memo, button, w, h, val, index); + if(val) g_free(val); + return res; +} + +void +AddHandler (Option *opt, DialogClass dlg, int nr) +{ + switch(nr) { + case 0: // history (now uses generic textview callback) + case 1: // comment (likewise) + break; + case 2: // move type-in + typeIn = opt; + case 3: // input box + g_signal_connect(opt->handle, "key-press-event", G_CALLBACK (ICSKeyEvent), (gpointer) opt); + break; + case 5: // game list + g_signal_connect(opt->handle, "button-press-event", G_CALLBACK (GameListEvent), (gpointer) 0 ); + case 4: // game-list filter + g_signal_connect(opt->handle, "key-press-event", G_CALLBACK (GameListEvent), (gpointer) nr ); + break; + case 6: // engine output (uses generic textview callback) + break; + } +} + +//----------------------------Generic dialog -------------------------------------------- + +// cloned from Engine Settings dialog (and later merged with it) + +GtkWidget *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) +{ +#ifdef TODO_GTK + 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,static gboolean +MemoEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata) + + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); + + XFlush(xDisplay); + XSync(xDisplay, False); +#endif +} + +int +PopDown (DialogClass n) +{ + //Arg args[10]; + + if (!shellUp[n] || !shells[n]) return 0; +#ifdef TODO_GTK +// Not sure this is still used + 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; + } +#endif + + gtk_widget_hide(shells[n]); + shellUp[n]--; // count rather than clear + + if(n == 0 || n >= PromoDlg) { + gtk_widget_destroy(shells[n]); + shells[n] = NULL; + } + + if(marked[n]) { + MarkMenuItem(marked[n], False); + marked[n] = NULL; + } + + if(!n) 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) +#ifdef TODO_GTK + RaiseWindow(parents[n]); // automatic in GTK? + if(parents[n] == BoardWindow) XtSetKeyboardFocus(shellWidget, formWidget); // also automatic??? +#endif + return 1; +} + +/* GTK callback used when OK/cancel clicked in genericpopup for non-modal dialog */ +gboolean GenericPopDown(w, resptype, gdata) + GtkWidget *w; + GtkResponseType resptype; + gpointer gdata; +{ + DialogClass dlg = (intptr_t) gdata; /* dialog number dlgnr */ + GtkWidget *sh = shells[dlg]; + + currentOption = dialogOptions[dlg]; + +#ifdef TODO_GTK +// I guess BrowserDlg will be abandoned, as GTK has a better browser of its own + if(shellUp[BrowserDlg] && dlg != BrowserDlg || dialogError) return True; // prevent closing dialog when it has an open file-browse daughter +#else + if(browserUp || dialogError && dlg != FatalDlg) return True; // prevent closing dialog when it has an open file-browse or error-popup daughter +#endif + shells[dlg] = w; // make sure we pop down the right one in case of multiple instances + + /* OK pressed */ + if (resptype == GTK_RESPONSE_ACCEPT) { + if (GenericReadout(currentOption, -1)) PopDown(dlg); + return TRUE; + } else + /* cancel pressed */ + { + if(dlg == BoardWindow) ExitEvent(0); + PopDown(dlg); + } + shells[dlg] = sh; // restore + return TRUE; +} + +int AppendText(Option *opt, char *s) +{ + char *v; + int len; + GtkTextIter end; + + GetWidgetTextGTK(opt->handle, &v); + len = strlen(v); + g_free(v); + gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(opt->handle), &end); + gtk_text_buffer_insert(opt->handle, &end, s, -1); + + return len; +} + +void +SetColor (char *colorName, Option *box) +{ // sets the color of a widget + GdkColor color; + + /* set the colour of the colour button to the colour that will be used */ + gdk_color_parse( colorName, &color ); + gtk_widget_modify_bg ( GTK_WIDGET(box->handle), GTK_STATE_NORMAL, &color ); +} + +#ifdef TODO_GTK +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); +} +#endif + +static void +GraphEventProc(GtkWidget *widget, GdkEvent *event, gpointer gdata) +{ // handle expose and mouse events on Graph widget + int w, h; + int j, button=10, f=1, sizing=0; + Option *opt, *graph = (Option *) gdata; + PointerCallback *userHandler = graph->target; + GdkEventExpose *eevent = (GdkEventExpose *) event; + GdkEventButton *bevent = (GdkEventButton *) event; + GdkEventMotion *mevent = (GdkEventMotion *) event; + GtkAllocation a; + cairo_t *cr; + +// if (!XtIsRealized(widget)) return; + + switch(event->type) { + case GDK_EXPOSE: // make handling of expose events generic, just copying from memory buffer (->choice) to display (->textValue) + /* Get window size */ + gtk_widget_get_allocation(widget, &a); + w = a.width; h = a.height; +//printf("expose %dx%d @ (%d,%d)\n", w, h, a.x, a.y); +#ifdef TODO_GTK + j = 0; + XtSetArg(args[j], XtNwidth, &w); j++; + XtSetArg(args[j], XtNheight, &h); j++; + XtGetValues(widget, args, j); +#endif + if(w < graph->max || w > graph->max + 1 || h != graph->value) { // use width fudge of 1 pixel + if(eevent->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 && eevent->count > 0) { graph->max = 0; return; } // don't bother if further exposure is pending during resize +#ifdef TODO_GTK + 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); + } +#endif + 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 +#ifdef TODO_GTK + if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice); + graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); +#endif + break; + } + w = eevent->area.width; + if(eevent->area.x + w > graph->max) w--; // cut off fudge pixel + cr = gdk_cairo_create(((GtkWidget *) (graph->handle))->window); + cairo_set_source_surface(cr, (cairo_surface_t *) graph->choice, 0, 0); + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + cairo_rectangle(cr, eevent->area.x, eevent->area.y, w, eevent->area.height); + cairo_fill(cr); + cairo_destroy(cr); + default: + return; + case GDK_MOTION_NOTIFY: + f = 0; + w = mevent->x; h = mevent->y; + break; + case GDK_BUTTON_RELEASE: + f = -1; // release indicated by negative button numbers + case GDK_BUTTON_PRESS: + w = bevent->x; h = bevent->y; + button = bevent->button; + shiftState = bevent->state & GDK_SHIFT_MASK; + controlState = bevent->state & GDK_CONTROL_MASK; + } + button *= f; + + opt = userHandler(button, w, h); +#ifdef TODO_GTK + 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); +#endif +} + +void +GraphExpose (Option *opt, int x, int y, int w, int h) +{ +#if 0 + GdkRectangle r; + r.x = x; r.y = y; r.width = w; r.height = h; + gdk_window_invalidate_rect(((GtkWidget *)(opt->handle))->window, &r, FALSE); +#endif + GdkEventExpose e; + if(!opt->handle) return; + e.area.x = x; e.area.y = y; e.area.width = w; e.area.height = h; e.count = -1; e.type = GDK_EXPOSE; // count = -1: kludge to suppress sizing + GraphEventProc(opt->handle, (GdkEvent *) &e, (gpointer) opt); // fake expose event +} + +void GenericCallback(GtkWidget *widget, gpointer gdata) +{ + const gchar *name; + char buf[MSG_SIZ]; + int data = (intptr_t) gdata; + DialogClass dlg; +#ifdef TODO_GTK + GtkWidget *sh = XtParent(XtParent(XtParent(w))), *oldSh; +#else + GtkWidget *sh, *oldSh; +#endif + + currentOption = dialogOptions[dlg=data>>16]; data &= 0xFFFF; +#ifndef TODO_GTK + sh = shells[dlg]; // make following line a no-op, as we haven't found out what the real shell is yet (breaks multiple popups of same type!) +#endif + 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) { + name = gtk_button_get_label (GTK_BUTTON(widget)); + 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 BrowseGTK(GtkWidget *widget, gpointer gdata) +{ + GtkWidget *entry; + GtkWidget *dialog; + GtkFileFilter *gtkfilter; + GtkFileFilter *gtkfilter_all; + int opt_i = (intptr_t) gdata; + GtkFileChooserAction fc_action; + + gtkfilter = gtk_file_filter_new(); + gtkfilter_all = gtk_file_filter_new(); + + char fileext[10] = "*"; + + /* select file or folder depending on option_type */ + if (currentOption[opt_i].type == PathName) + fc_action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + else + fc_action = GTK_FILE_CHOOSER_ACTION_OPEN; + + dialog = gtk_file_chooser_dialog_new ("Open File", + NULL, + fc_action, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + /* one filter to show everything */ + gtk_file_filter_add_pattern(gtkfilter_all, "*"); + gtk_file_filter_set_name (gtkfilter_all, "All Files"); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),gtkfilter_all); + + /* filter for specific filetypes e.g. pgn or fen */ + if (currentOption[opt_i].textValue != NULL && (strcmp(currentOption[opt_i].textValue, "") != 0) ) + { + strcat(fileext, currentOption[opt_i].textValue); + gtk_file_filter_add_pattern(gtkfilter, fileext); + gtk_file_filter_set_name (gtkfilter, currentOption[opt_i].textValue); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); + /* activate filter */ + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); + } + else + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter_all); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + char *filename; + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + entry = currentOption[opt_i].handle; + gtk_entry_set_text (GTK_ENTRY (entry), filename); + g_free (filename); + + } + gtk_widget_destroy (dialog); + dialog = NULL; +} + +gboolean +ListCallback (GtkWidget *widget, GdkEventButton *event, gpointer gdata) +{ + int n = (intptr_t) gdata & 0xFFFF; + int dlg = (intptr_t) gdata >> 16; + Option *opt = dialogOptions[dlg] + n; + + if(event->type != GDK_2BUTTON_PRESS || event->button != 1) return FALSE; + ((ListBoxCallback*) opt->textValue)(n, SelectedListBoxItem(opt)); + return TRUE; +} + +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 +#ifdef TODO_GTK + 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; +#endif +} + +#ifdef TODO_GTK +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; +} +#endif + +static int +TableWidth (Option *opt) +{ // Hideous work-around! If the table is 3 columns, but 2 & 3 are always occupied together, the fixing of the width of column 1 does not work + while(opt->type != EndMark && opt->type != Break) + if(opt->type == FileName || opt->type == PathName || opt++->type == BarBegin) return 3; // This table needs browse button + return 2; // no browse button; +} + +static int +SameRow (Option *opt) +{ + return (opt->min & SAME_ROW && (opt->type == Button || opt->type == SaveButton || opt->type == Label + || opt->type == ListBox || opt->type == BoxBegin || opt->type == Icon)); +} + +static void +Pack (GtkWidget *hbox, GtkWidget *table, GtkWidget *entry, int left, int right, int top, GtkAttachOptions vExpand) +{ + if(hbox) gtk_box_pack_start(GTK_BOX (hbox), entry, TRUE, TRUE, 0); + else gtk_table_attach(GTK_TABLE(table), entry, left, right, top, top+1, + GTK_FILL | GTK_EXPAND, GTK_FILL | vExpand, 2, 1); +} + +int +GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent, int modal, int topLevel) +{ + GtkWidget *dialog = NULL; + gint w; + GtkWidget *label; + GtkWidget *box; + GtkWidget *checkbutton; + GtkWidget *entry; + GtkWidget *oldHbox, *hbox = NULL; + GtkWidget *pane = NULL; + GtkWidget *button; + GtkWidget *table; + GtkWidget *spinner; + GtkAdjustment *spinner_adj; + GtkWidget *combobox; + GtkWidget *textview; + GtkTextBuffer *textbuffer; + GdkColor color; + GtkWidget *actionarea; + GtkWidget *sw; + GtkWidget *list; + GtkWidget *graph; + GtkWidget *menuButton; + GtkWidget *menuBar; + GtkWidget *menu; + + int i, j, arraysize, left, top, height=999, width=1, boxStart, breakType = 0, r; + char def[MSG_SIZ], *msg, engineDlg = (currentCps != NULL && dlgNr != BrowserDlg); + + if(dlgNr < PromoDlg && shellUp[dlgNr]) return 0; // already up + + if(dlgNr && dlgNr < PromoDlg && shells[dlgNr]) { // reusable, and used before (but popped down) + gtk_widget_show(shells[dlgNr]); + 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 > 50) width = 4; else if(n>24) width = 2; else width = 1; + width = n / 20 + 1; + height = n / width + 1; +printf("n=%d, h=%d, w=%d\n",n,height,width); +// 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 + } + + parents[dlgNr] = parent; +#ifdef TODO_GTK + shells[BoardWindow] = shellWidget; parents[dlgNr] = parent; + + if(dlgNr == BoardWindow) dialog = shellWidget; else + dialog = + XtCreatePopupShell(title, !top || !appData.topLevel ? transientShellWidgetClass : topLevelShellWidgetClass, + shells[parent], args, i); +#endif + dialog = gtk_dialog_new_with_buttons( title, + GTK_WINDOW(shells[parent]), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR | + (modal ? GTK_DIALOG_MODAL : 0), + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL ); + + shells[dlgNr] = dialog; + box = gtk_dialog_get_content_area( GTK_DIALOG( dialog ) ); +// gtk_box_set_spacing(GTK_BOX(box), 5); + + arraysize = 0; + for (i=0;option[i].type != EndMark;i++) { + arraysize++; + } + + table = gtk_table_new(arraysize, r=TableWidth(option), FALSE); + left = 0; + top = -1; + + for (i=0;option[i].type != EndMark;i++) { + if(option[i].type == -1) continue; + top++; +printf("option =%2d, top =%2d\n", i, top); + if (top >= height) { + gtk_table_resize(GTK_TABLE(table), height, r); + if(!pane) { // multi-column: put tables in intermediate hbox + if(breakType || engineDlg) + pane = gtk_hbox_new (FALSE, 0); + else + pane = gtk_vbox_new (FALSE, 0); + gtk_box_set_spacing(GTK_BOX(pane), 5 + 5*breakType); + gtk_box_pack_start (GTK_BOX (/*GTK_DIALOG (dialog)->vbox*/box), pane, TRUE, TRUE, 0); + } + gtk_box_pack_start (GTK_BOX (pane), table, TRUE, TRUE, 0); + table = gtk_table_new(arraysize - i, r=TableWidth(option + i), FALSE); + top = 0; + } + if(!SameRow(&option[i])) { + if(SameRow(&option[i+1])) { + GtkAttachOptions x = GTK_FILL; + // make sure hbox is always available when we have more options on same row + hbox = gtk_hbox_new (option[i].type == Button && option[i].textValue, 0); + if(!currentCps && option[i].value > 80) x |= GTK_EXPAND; // only vertically extended widgets should size vertically + if (strcmp(option[i].name, "") == 0 || option[i].type == Label || option[i].type == Button) + // for Label and Button name is contained inside option + gtk_table_attach(GTK_TABLE(table), hbox, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, x, 2, 1); + else + gtk_table_attach(GTK_TABLE(table), hbox, left+1, left+r, top, top+1, GTK_FILL | GTK_EXPAND, x, 2, 1); + } else hbox = NULL; //and also make sure no hbox exists if only singl option on row + } else top--; + switch(option[i].type) { + case Fractional: + snprintf(def, MSG_SIZ, "%.2f", *(float*)option[i].target); + option[i].value = *(float*)option[i].target; + goto tBox; + case Spin: + if(!currentCps) option[i].value = *(int*)option[i].target; + snprintf(def, MSG_SIZ, "%d", option[i].value); + case TextBox: + case FileName: + case PathName: + tBox: + label = gtk_label_new(option[i].name); + /* Left Justify */ + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + /* width */ + w = option[i].type == Spin || option[i].type == Fractional ? 70 : option[i].max ? option[i].max : 205; + if(option[i].type == FileName || option[i].type == PathName) w -= 55; + + if (option[i].type==TextBox && option[i].value > 80){ + textview = gtk_text_view_new(); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), option[i].min & T_WRAP ? GTK_WRAP_WORD : GTK_WRAP_NONE); +#ifdef TODO_GTK + if(option[i].min & T_FILL) { XtSetArg(args[j], XtNautoFill, True); j++; } + if(option[i].min & T_TOP) { XtSetArg(args[j], XtNtop, XtChainTop); j++; +#endif + /* add textview to scrolled window so we have vertical scroll bar */ + sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), + option[i].min & T_HSCRL ? GTK_POLICY_ALWAYS : GTK_POLICY_AUTOMATIC, + option[i].min & T_VSCRL ? GTK_POLICY_ALWAYS : GTK_POLICY_NEVER); + gtk_container_add(GTK_CONTAINER(sw), textview); + gtk_widget_set_size_request(GTK_WIDGET(sw), w, -1); + + textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); + /* check if label is empty */ + if (strcmp(option[i].name,"") != 0) { + gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); + Pack(hbox, table, sw, left+1, left+r, top, 0); + } + else { + /* no label so let textview occupy all columns */ + Pack(hbox, table, sw, left, left+r, top, GTK_EXPAND); + } + if ( *(char**)option[i].target != NULL ) + gtk_text_buffer_set_text (textbuffer, *(char**)option[i].target, -1); + else + gtk_text_buffer_set_text (textbuffer, "", -1); + option[i].handle = (void*)textbuffer; + option[i].textValue = (char*)textview; + if(option[i].choice) { // textviews can request a handler for mouse events in the choice field + g_signal_connect(textview, "button-press-event", G_CALLBACK (MemoEvent), (gpointer) &option[i] ); + g_signal_connect(textview, "button-release-event", G_CALLBACK (MemoEvent), (gpointer) &option[i] ); + g_signal_connect(textview, "motion-notify-event", G_CALLBACK (MemoEvent), (gpointer) &option[i] ); + } + break; + } + + entry = gtk_entry_new(); + + if (option[i].type==Spin || option[i].type==Fractional) + gtk_entry_set_text (GTK_ENTRY (entry), def); + else if (currentCps) + gtk_entry_set_text (GTK_ENTRY (entry), option[i].textValue); + else if ( *(char**)option[i].target != NULL ) + gtk_entry_set_text (GTK_ENTRY (entry), *(char**)option[i].target); + + //gtk_entry_set_width_chars (GTK_ENTRY (entry), 18); + gtk_entry_set_max_length (GTK_ENTRY (entry), w); + + // left, right, top, bottom + if (strcmp(option[i].name, "") != 0) + gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); // leading names do not expand + + if (option[i].type == Spin) { + spinner_adj = (GtkAdjustment *) gtk_adjustment_new (option[i].value, option[i].min, option[i].max, 1.0, 0.0, 0.0); + spinner = gtk_spin_button_new (spinner_adj, 1.0, 0); + gtk_table_attach(GTK_TABLE(table), spinner, left+1, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); + option[i].handle = (void*)spinner; + } + else if (option[i].type == FileName || option[i].type == PathName) { + gtk_table_attach(GTK_TABLE(table), entry, left+1, left+2, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); + button = gtk_button_new_with_label ("Browse"); + gtk_table_attach(GTK_TABLE(table), button, left+2, left+r, top, top+1, GTK_FILL, GTK_FILL, 2, 1); // Browse button does not expand + g_signal_connect (button, "clicked", G_CALLBACK (BrowseGTK), (gpointer)(intptr_t) i); + option[i].handle = (void*)entry; + } + else { + Pack(hbox, table, entry, left + (strcmp(option[i].name, "") != 0), left+r, top, 0); + option[i].handle = (void*)entry; + } + break; + case CheckBox: + checkbutton = gtk_check_button_new_with_label(option[i].name); + if(!currentCps) option[i].value = *(Boolean*)option[i].target; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), option[i].value); + gtk_table_attach(GTK_TABLE(table), checkbutton, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 0); + option[i].handle = (void *)checkbutton; + break; + case Icon: + option[i].handle = (void *) (label = gtk_image_new_from_pixbuf(NULL)); + gtk_widget_set_size_request(label, option[i].max ? option[i].max : -1, -1); + Pack(hbox, table, label, left, left+2, top, 0); + break; + case Label: + option[i].handle = (void *) (label = gtk_label_new(option[i].name)); + /* Left Justify */ + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + if(option[i].min & BORDER) { + GtkWidget *frame = gtk_frame_new(NULL); + gtk_container_add(GTK_CONTAINER(frame), label); + label = frame; + } + gtk_widget_set_size_request(label, option[i].max ? option[i].max : -1, -1); + Pack(hbox, table, label, left, left+2, top, 0); + if(option[i].target) { // allow user to specify event handler for button presses + gtk_widget_add_events(GTK_WIDGET(label), GDK_BUTTON_PRESS_MASK); + g_signal_connect(label, "button-press-event", G_CALLBACK(MemoEvent), (gpointer) &option[i]); + } + break; + case SaveButton: + case Button: + button = gtk_button_new_with_label (option[i].name); + + /* set button color on view board dialog */ + if(option[i].choice && ((char*)option[i].choice)[0] == '#' && !currentCps) { + gdk_color_parse( *(char**) option[i-1].target, &color ); + gtk_widget_modify_bg ( GTK_WIDGET(button), GTK_STATE_NORMAL, &color ); + } + + /* set button color on new variant dialog */ + if(option[i].textValue) { + gdk_color_parse( option[i].textValue, &color ); + gtk_widget_modify_bg ( GTK_WIDGET(button), GTK_STATE_NORMAL, &color ); + gtk_widget_set_sensitive(button, appData.noChessProgram || option[i].value < 0 + || strstr(first.variants, VariantName(option[i].value))); + } + + Pack(hbox, table, button, left, left+1, top, 0); + g_signal_connect (button, "clicked", G_CALLBACK (GenericCallback), (gpointer)(intptr_t) i + (dlgNr<<16)); + option[i].handle = (void*)button; + break; + case ComboBox: + label = gtk_label_new(option[i].name); + /* Left Justify */ + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); + + combobox = gtk_combo_box_new_text(); + + for(j=0;;j++) { + if ( ((char **) option[i].textValue)[j] == NULL) break; + gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), ((char **) option[i].choice)[j]); + } + + if(currentCps) + option[i].choice = (char**) option[i].textValue; + else { + for(j=0; option[i].choice[j]; j++) { + if(*(char**)option[i].target && !strcmp(*(char**)option[i].target, ((char**)(option[i].textValue))[j])) break; + } + /* If choice is NULL set to first */ + if (option[i].choice[j] == NULL) + option[i].value = 0; + else + option[i].value = j; + } + + //option[i].value = j + (option[i].choice[j] == NULL); + gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), option[i].value); + + Pack(hbox, table, combobox, left+1, left+r, top, 0); + g_signal_connect(G_OBJECT(combobox), "changed", G_CALLBACK(ComboSelect), (gpointer) (intptr_t) (i + 256*dlgNr)); + + option[i].handle = (void*)combobox; + values[i] = option[i].value; + break; + case ListBox: + { + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkListStore *store; + + option[i].handle = (void *) (list = gtk_tree_view_new()); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE); + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("List Items", renderer, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); + store = gtk_list_store_new(1, G_TYPE_STRING); // 1 column of text + gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store)); + g_object_unref(store); + LoadListBox(&option[i], "?", -1, -1); + HighlightListBoxItem(&option[i], 0); + + /* add listbox to scrolled window so we have vertical scroll bar */ + sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(sw), list); + gtk_widget_set_size_request(GTK_WIDGET(sw), option[i].max ? option[i].max : -1, option[i].value ? option[i].value : -1); + + if(option[i].textValue) // generic callback for double-clicking listbox item + g_signal_connect(list, "button-press-event", G_CALLBACK(ListCallback), (gpointer) (dlgNr<<16 | i) ); + + /* never has label, so let listbox occupy all columns */ + Pack(hbox, table, sw, left, left+r, top, GTK_EXPAND); + } + break; + case Graph: + option[i].handle = (void*) (graph = gtk_drawing_area_new()); + gtk_widget_set_size_request(graph, option[i].max, option[i].value); + Pack(hbox, GTK_TABLE(table), graph, left, left+r, top, GTK_EXPAND); + g_signal_connect (graph, "expose-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); + gtk_widget_add_events(GTK_WIDGET(graph), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); + g_signal_connect (graph, "button-press-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); + g_signal_connect (graph, "button-release-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); + g_signal_connect (graph, "motion-notify-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); + +#ifdef TODO_GTK + if(option[i].min & SAME_ROW) last = forelast, forelast = lastrow; +#endif + option[i].choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, option[i].max, option[i].value); // image buffer + break; +#ifdef TODO_GTK + 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; +#endif + case DropDown: + top--; + 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*) + (menuButton = gtk_menu_item_new_with_label(msg)); + gtk_widget_show(menuButton); + option[i].textValue = (char*) (menu = CreateMenuPopup(option + i, i + 256*dlgNr, -1)); + gtk_menu_item_set_submenu(GTK_MENU_ITEM (menuButton), menu); + gtk_menu_bar_append (GTK_MENU_BAR (menuBar), menuButton); + + break; + case BarBegin: + menuBar = gtk_menu_bar_new (); + gtk_widget_show (menuBar); + boxStart = i; + break; + case BoxBegin: + option[i+1].min |= SAME_ROW; // kludge to suppress allocation of new hbox + oldHbox = hbox; + option[i].handle = (void*) (hbox = gtk_hbox_new(FALSE, 0)); // hbox to collect buttons + gtk_box_pack_start(GTK_BOX (oldHbox), hbox, FALSE, TRUE, 0); // *** Beware! Assumes button bar always on same row with other! *** +// gtk_table_attach(GTK_TABLE(table), hbox, left+2, left+3, top, top+1, GTK_FILL | GTK_SHRINK, GTK_FILL, 2, 1); + boxStart = i; + break; + case BarEnd: + top--; + gtk_table_attach(GTK_TABLE(table), menuBar, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); + + if(option[i].target) ((ButtonCallback*)option[i].target)(boxStart); // callback that can make sizing decisions + break; + case BoxEnd: +// XtManageChildren(&form, 1); +// SqueezeIntoBox(&option[boxStart], i-boxStart, option[boxStart].max); + hbox = oldHbox; top--; + if(option[i].target) ((ButtonCallback*)option[i].target)(boxStart); // callback that can make sizing decisions + break; + case Break: + breakType = option[i].min & SAME_ROW; + top = height; // force next option to start in a new table + break; + + case PopUp: + top--; + break; + default: + printf("GenericPopUp: unexpected case in switch. i=%d type=%d name=%s.\n", i, option[i].type, option[i].name); + break; + } + } + + if(pane) + gtk_box_pack_start (GTK_BOX (pane), table, TRUE, TRUE, 0); + else + gtk_table_resize(GTK_TABLE(table), top+1, r), + gtk_box_pack_start (GTK_BOX (/*GTK_DIALOG (dialog)->vbox*/box), table, TRUE, TRUE, 0); + + option[i].handle = (void *) table; // remember last table in EndMark handle (for hiding Engine-Output pane). + + /* Show dialog */ + gtk_widget_show_all( dialog ); + + /* hide OK/cancel buttons */ + if((option[i].min & 2)) { + actionarea = gtk_dialog_get_action_area(GTK_DIALOG(dialog)); + gtk_widget_hide(actionarea); + } + + g_signal_connect (dialog, "response", + G_CALLBACK (GenericPopDown), + (gpointer)(intptr_t) dlgNr); + g_signal_connect (dialog, "delete-event", + G_CALLBACK (GenericPopDown), + (gpointer)(intptr_t) dlgNr); + shellUp[dlgNr]++; + + return 1; // tells caller he must do initialization (e.g. add specific event handlers) +} + +/* function called when the data to Paste is ready */ +#ifdef TODO_GTK +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); +} +#endif + +void +SendText (int n) +{ +#ifdef TODO_GTK + 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); +#endif +} + +void +SetInsertPos (Option *opt, int pos) +{ +#ifdef TODO_GTK + 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); +#endif +} + +void +HardSetFocus (Option *opt) +{ +#ifdef TODO_GTK + XSetInputFocus(xDisplay, XtWindow(opt->handle), RevertToPointerRoot, CurrentTime); +#endif +} + + diff --git a/gtk/xtimer.c b/gtk/xtimer.c new file mode 100644 index 0000000..96313f9 --- /dev/null +++ b/gtk/xtimer.c @@ -0,0 +1,239 @@ +/* + * xtimer.c -- timing functions for X front end of 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 + +#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_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 + +#include "common.h" +#include "backend.h" +#include "frontend.h" + +#ifdef __EMX__ +#ifndef HAVE_USLEEP +#define HAVE_USLEEP +#endif +#define usleep(t) _sleep2(((t)+500)/1000) +#endif + +guint delayedEventTimerTag = 0; +DelayedEventCallback delayedEventCallback = 0; + +void +FireDelayedEvent(gpointer data) +{ + g_source_remove(delayedEventTimerTag); + delayedEventTimerTag = 0; + delayedEventCallback(); +} + +void +ScheduleDelayedEvent (DelayedEventCallback cb, long millisec) +{ + if(delayedEventTimerTag && delayedEventCallback == cb) + // [HGM] alive: replace, rather than add or flush identical event + g_source_remove(delayedEventTimerTag); + delayedEventCallback = cb; + delayedEventCallback = cb; + delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL); +} + +DelayedEventCallback +GetDelayedEvent () +{ + if (delayedEventTimerTag) { + return delayedEventCallback; + } else { + return NULL; + } +} + +void +CancelDelayedEvent () +{ + if (delayedEventTimerTag) { + g_source_remove(delayedEventTimerTag); + delayedEventTimerTag = 0; + } +} + + +guint loadGameTimerTag = 0; + +int LoadGameTimerRunning() +{ + return loadGameTimerTag != 0; +} + +int +StopLoadGameTimer () +{ + if (loadGameTimerTag != 0) { + g_source_remove(loadGameTimerTag); + loadGameTimerTag = 0; + return TRUE; + } else { + return FALSE; + } +} + +void +LoadGameTimerCallback(gpointer data) +{ + g_source_remove(loadGameTimerTag); + loadGameTimerTag = 0; + AutoPlayGameLoop(); +} + +void +StartLoadGameTimer (long millisec) +{ + loadGameTimerTag = + g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL); +} + +guint analysisClockTag = 0; + +void +AnalysisClockCallback(gpointer data) +{ + if (gameMode == AnalyzeMode || gameMode == AnalyzeFile + || appData.icsEngineAnalyze) { // [DM] + AnalysisPeriodicEvent(0); + } +} + +void +StartAnalysisClock () +{ + analysisClockTag = + g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL); +} + +guint clockTimerTag = 0; + +int +ClockTimerRunning () +{ + return clockTimerTag != 0; +} + +int +StopClockTimer () +{ + if (clockTimerTag != 0) + { + g_source_remove(clockTimerTag); + clockTimerTag = 0; + return TRUE; + } else { + return FALSE; + } +} + +void +ClockTimerCallback(gpointer data) +{ + /* remove timer */ + g_source_remove(clockTimerTag); + clockTimerTag = 0; + + DecrementClocks(); +} + +void +StartClockTimer (long millisec) +{ + clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL); +} + + diff --git a/menus.c b/menus.c index a75bf5f..df0b733 100644 --- a/menus.c +++ b/menus.c @@ -87,7 +87,6 @@ extern char *getenv(); #include "frontend.h" #include "backend.h" -#include "xhistory.h" #include "menus.h" #include "gettext.h" diff --git a/menus.h b/menus.h index 7731256..7cea0b3 100644 --- a/menus.h +++ b/menus.h @@ -163,6 +163,7 @@ void SaveSettings P((char *)); void EditBookProc P((void)); void InitMenuMarkers P((void)); void ShowGameListProc P((void)); // in ngamelist.c +void HistoryShowProc P((void)); // in nhistory.c // must be moved to xengineoutput.h diff --git a/nhistory.c b/nhistory.c index 59b4226..e1d9766 100644 --- a/nhistory.c +++ b/nhistory.c @@ -26,8 +26,8 @@ #include #include "common.h" +#include "frontend.h" #include "backend.h" -#include "xhistory.h" #include "dialogs.h" #include "gettext.h" @@ -83,6 +83,12 @@ Option historyOptions[] = { { 0, NO_OK, 0, NULL, (void*) NULL, "", NULL, EndMark , "" } }; +void +ScrollToCurrent (int caretPos) +{ + ScrollToCursor(&historyOptions[0], caretPos); +} + // ------------ standard entry points into MoveHistory code ----------- Boolean diff --git a/xaw/xhistory.c b/xaw/xhistory.c index d46206d..805c1f3 100644 --- a/xaw/xhistory.c +++ b/xaw/xhistory.c @@ -74,23 +74,23 @@ extern Option historyOptions[]; // the bold argument says 0 = normal, 1 = bold typeface // the colorNr argument says 0 = font-default, 1 = gray void -ScrollToCurrent (int caretPos) +ScrollToCursor (Option *opt, int caretPos) { Arg args[10]; char *s; int len; - GetWidgetText(&historyOptions[0], &s); + GetWidgetText(opt, &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); + XtCallActionProc(opt->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); + XtSetValues(opt->handle, args, 2); } diff --git a/xboard.c b/xboard.c deleted file mode 100644 index baa4c7f..0000000 --- a/xboard.c +++ /dev/null @@ -1,2501 +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 -#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 - -// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are. -#include "common.h" - -#include "frontend.h" -#include "backend.h" -#include "backendz.h" -#include "moves.h" -#include "xboard.h" -#include "xboard2.h" -#include "childio.h" -#include "xgamelist.h" -#include "xhistory.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)); -#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 DelayedDrag P((void)); -void ICSInputBoxPopUp P((void)); -gboolean KeyPressProc P((GtkWindow *window, GdkEventKey *eventkey, gpointer data)); -#ifdef TODO_GTK -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 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)); -void ManInner P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams)); -#endif -Boolean TempBackwardActive = False; -void DisplayMove P((int moveNumber)); -void ICSInitScript P((void)); -void update_ics_width P(()); -int CopyMemoProc P(()); -static gboolean EventProc P((GtkWidget *widget, GdkEvent *event, gpointer g)); - -#ifdef TODO_GTK -/* -* 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; -#if ENABLE_NLS -XFontSet fontSet, clockFontSet; -#else -Font clockFontID; -XFontStruct *clockFontStruct; -#endif -Font coordFontID, countFontID; -XFontStruct *coordFontStruct, *countFontStruct; -XtAppContext appContext; -#else -void *shellWidget, *formWidget, *boardWidget, *titleWidget, *dropMenu, *menuBarWidget; -void *appContext; -GtkWidget *mainwindow; -#endif -Option *optList; // contains all widgets of main window -char *layoutName; - -char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion - -/* pixbufs */ -static GdkPixbuf *mainwindowIcon=NULL; -static GdkPixbuf *WhiteIcon=NULL; -static GdkPixbuf *BlackIcon=NULL; - -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; -#ifdef TODO_GTK -Dimension textHeight; -Pixel timerForegroundPixel, timerBackgroundPixel; -Pixel buttonForegroundPixel, buttonBackgroundPixel; -#endif -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" } -}; - -#ifdef TODO_GTK -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 }, -}; -#endif - -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"; - -#ifdef TODO_GTK -String xboardResources[] = { - "*Error*translations: #override\\n Return: ErrorPopDown()", - NULL - }; -#endif - -/* 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)); -} -#endif - -void -BoardToTop () -{ - gtk_window_present(GTK_WINDOW(mainwindow)); -} - -//--------------------------------------------------------------------------------------------------------- -// 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 (GtkWidget *shell, WindowPlacement *wp) -{ - GtkAllocation a; - if(!shell) return; - gtk_widget_get_allocation(shell, &a); - wp->x = a.x; - wp->y = a.y; - wp->width = a.width; - wp->height = a.height; -printf("placement\n"); - frameX = a.x; frameY = a.y; // remember to decide if windows touch -} -#ifdef TODO_GTK -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 -} -#endif - -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 -#ifdef TODO_GTK - return xBoardWindow != 0; -#else - return DialogExists(BoardWindow); -#endif -} - -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 -#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; -#ifdef TODO_GTK - XSetWindowAttributes window_attributes; - Arg args[16]; - Dimension boardWidth, boardHeight, w, h; -#else -#endif - int boardWidth, boardHeight, w, h; - char *p; - int forceMono = False; - GError *gtkerror=NULL; - - 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); - } - - /* set up GTK */ - gtk_init (&argc, &argv); - - programName = strrchr(argv[0], '/'); - if (programName == NULL) - programName = argv[0]; - else - programName++; - -#ifdef ENABLE_NLS -// 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); - } - -#if ENABLE_NLS - if (appData.debugMode) { - fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL)); - } -#endif - - /* [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); - -#ifdef TODO_GTK - /* GTK */ - builder = gtk_builder_new(); - filename = get_glade_filename ("mainboard.glade"); - if(! gtk_builder_add_from_file (builder, filename, >kerror) ) - { - if(gtkerror) - printf ("Error: %d %s\n",gtkerror->code,gtkerror->message); - } - mainwindow = GTK_WIDGET(gtk_builder_get_object (builder, "mainwindow")); - - 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); -#endif - - /* - * 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) { -#ifdef TODO_GTK - while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize || - DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) { - szd++; - } -#else - GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(mainwindow)); - guint screenwidth = gdk_screen_get_width(screen); - guint screenheight = gdk_screen_get_height(screen); - while (screenwidth < szd->minScreenSize || - screenheight < szd->minScreenSize) { - szd++; - } -#endif - 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. - */ -#ifdef TODO_GTK - InitializeFonts(clockFontPxlSize, coordFontPxlSize, fontPxlSize); -#endif - - /* - * Detect if there are not enough colors available and adapt. - */ -#ifdef TODO_GTK - if (DefaultDepth(xDisplay, xScreen) <= 2) { - appData.monoMode = True; - } -#endif - - forceMono = MakeColors(); - - if (forceMono) { - fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"), - programName); - appData.monoMode = True; - } - - ParseIcsTextColors(); - -#ifdef TODO_GTK - XtAppAddActions(appContext, boardActions, XtNumber(boardActions)); -#endif - - /* - * widget hierarchy - */ - if (tinyLayout) { - layoutName = "tinyLayout"; - } else if (smallLayout) { - layoutName = "smallLayout"; - } else { - layoutName = "normalLayout"; - } - - optList = BoardPopUp(squareSize, lineGap, (void*) -#ifdef TODO_GTK -#if ENABLE_NLS - &clockFontSet); -#else - clockFontStruct); -#endif -#else -0); -#endif - InitDrawingHandle(optList + W_BOARD); - shellWidget = shells[BoardWindow]; - 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; -#ifdef TODO_GTK - 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); - } -#endif - -#ifdef TODO_GTK - xBoardWindow = XtWindow(boardWidget); -#endif - - // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would - // not need to go into InitDrawingSizes(). - - InitMenuMarkers(); - - /* - * Create an icon. (Use two icons, to indicate whther it is white's or black's turn.) - */ - WhiteIcon = gdk_pixbuf_new_from_file(SVGDIR "/icon_white.svg", NULL); - BlackIcon = gdk_pixbuf_new_from_file(SVGDIR "/icon_black.svg", NULL); - mainwindowIcon = WhiteIcon; - gtk_window_set_icon(GTK_WINDOW(shellWidget), mainwindowIcon); - - - /* - * Create a cursor for the board widget. - */ -#ifdef TODO_GTK - window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2); - XChangeWindowAttributes(xDisplay, xBoardWindow, - CWCursor, &window_attributes); -#endif - - /* - * Inhibit shell resizing. - */ -#ifdef TODO_GTK - 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); -#endif - { - GtkAllocation a; - gtk_widget_get_allocation(shells[BoardWindow], &a); - w = a.width; h = a.height; -printf("start size (%d,%d), %dx%d\n", a.x, a.y, w, h); - } - marginW = w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board - marginH = h - boardHeight; - -#ifdef TODO_GTK - CatchDeleteWindow(shellWidget, "QuitProc"); -#endif - - 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(); - -#ifdef TODO_GTK - XtAugmentTranslations(formWidget, - XtParseTranslationTable(globalTranslations)); - - XtAddEventHandler(formWidget, KeyPressMask, False, - (XtEventHandler) MoveTypeInProc, NULL); - XtAddEventHandler(shellWidget, StructureNotifyMask, False, - (XtEventHandler) EventProc, NULL); -#endif - g_signal_connect(shells[BoardWindow], "key-press-event", G_CALLBACK(KeyPressProc), NULL); - g_signal_connect(shells[BoardWindow], "configure-event", G_CALLBACK(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); -#ifdef TODO_GTK - XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime); -#endif - - /* check for GTK events and process them */ -// gtk_main(); -while(1) { -gtk_main_iteration(); -} - - 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; -} - -#ifdef TODO_GTK -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; -} -#endif -#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; - -#ifdef TODO_GTK - 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); -#endif - return p; -} -#endif - -void -EnableNamedMenuItem (char *menuRef, int state) -{ - MenuItem *item = MenuNameToItem(menuRef); - - if(item) gtk_widget_set_sensitive(item->handle, state); -} - -void -EnableButtonBar (int state) -{ -#ifdef TODO_GTK - XtSetSensitive(optList[W_BUTTON].handle, state); -#endif -} - - -void -SetMenuEnables (Enables *enab) -{ - while (enab->name != NULL) { - EnableNamedMenuItem(enab->name, enab->value); - enab++; - } -} - -gboolean KeyPressProc(window, eventkey, data) - GtkWindow *window; - GdkEventKey *eventkey; - gpointer data; -{ - - MoveTypeInProc(eventkey); // pop up for typed in moves - -#ifdef TODO_GTK - /* check for other key values */ - switch(eventkey->keyval) { - case GDK_question: - AboutGameEvent(); - break; - default: - break; - } -#endif - return False; -} -#ifdef TODO_GTK -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) (); -} -#endif - -void -SetupDropMenu () -{ -#ifdef TODO_GTK - 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 (GtkWidget *sh, WindowPlacement *wp) -{ - 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); -#ifdef TODO_GTK - if(heightInc) XtSetArg(args[j], XtNheight, wp->height + heightInc), j++; -#endif - } 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); -#ifdef TODO_GTK - if(widthInc) XtSetArg(args[j], XtNwidth, wp->width + widthInc), j++; -#endif - } - 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; -#ifdef TODO_GTK - XtSetArg(args[j], XtNx, wp->x); j++; - XtSetArg(args[j], XtNy, wp->y); j++; - XtSetValues(sh, args, j); -#endif -} - -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; -} - -#ifdef TODO_GTK -static XtIntervalId delayedDragID = 0; -#else -static guint delayedDragTag = 0; -#endif - -void -DragProc () -{ - static int busy; - if(busy) return; - - busy = 1; -// GetActualPlacement(shellWidget, &wpNew); -printf("drag proc (%d,%d) %dx%d\n", wpNew.x, wpNew.y, wpNew.width, wpNew.height); - 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); - if(delayedDragTag) g_source_remove(delayedDragTag); - delayedDragTag = 0; // now drag executed, make sure next DelayedDrag will not cancel timer event (which could now be used by other) - busy = 0; -} - -void -DelayedDrag () -{ -printf("old timr = %d\n", delayedDragTag); - if(delayedDragTag) g_source_remove(delayedDragTag); - delayedDragTag = g_timeout_add( 200, (GSourceFunc) DragProc, NULL); -printf("new timr = %d\n", delayedDragTag); -} - -static gboolean -EventProc (GtkWidget *widget, GdkEvent *event, gpointer g) -{ -printf("event proc (%d,%d) %dx%d\n", event->configure.x, event->configure.y, event->configure.width, event->configure.height); - // immediately - wpNew.x = event->configure.x; - wpNew.y = event->configure.y; - wpNew.width = event->configure.width; - wpNew.height = event->configure.height; - if(appData.useStickyWindows) - DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other - return FALSE; -} - -/* - * event handler for redrawing the board - */ -#ifdef TODO_GTK -void -DrawPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - DrawPosition(True, NULL); -} -#endif - - - -/* 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 */ - gtk_grab_add(optList[W_MESSG].handle); - frozen = 1; -} - -/* Undo a FreezeUI */ -void -ThawUI () -{ - if (!frozen) return; - gtk_grab_remove(optList[W_MESSG].handle); - frozen = 0; -} - -void -ModeHighlight () -{ - static int oldPausing = FALSE; - static GameMode oldmode = (GameMode) -1; - char *wname; - if (!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. */ - GdkColor color; - gdk_color_parse( pausing ? "#808080" : "#F0F0F0", &color ); - gtk_widget_modify_bg ( GTK_WIDGET(optList[W_PAUSE].handle), GTK_STATE_NORMAL, &color ); - } - } - - 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 - */ - -void CopyFileToClipboard(gchar *filename) -{ - gchar *selection_tmp; - GtkClipboard *cb; - - // read the file - FILE* f = fopen(filename, "r"); - long len; - size_t count; - if (f == NULL) return; - fseek(f, 0, 2); - len = ftell(f); - rewind(f); - selection_tmp = g_try_malloc(len + 1); - if (selection_tmp == NULL) { - printf("Malloc failed in CopyFileToClipboard\n"); - return; - } - count = fread(selection_tmp, 1, len, f); - fclose(f); - if (len != count) { - g_free(selection_tmp); - return; - } - selection_tmp[len] = NULLCHAR; // file is now in selection_tmp - - // copy selection_tmp to clipboard - GdkDisplay *gdisp = gdk_display_get_default(); - if (!gdisp) { - g_free(selection_tmp); - return; - } - cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); - gtk_clipboard_set_text(cb, selection_tmp, -1); - g_free(selection_tmp); -} - -void -CopySomething (char *src) -{ - GdkDisplay *gdisp = gdk_display_get_default(); - GtkClipboard *cb; - if(!src) { CopyFileToClipboard(gameCopyFilename); return; } - if (gdisp == NULL) return; - cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); - gtk_clipboard_set_text(cb, src, -1); -} - -void -PastePositionProc () -{ - GdkDisplay *gdisp = gdk_display_get_default(); - GtkClipboard *cb; - gchar *fenstr; - - if (gdisp == NULL) return; - cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); - fenstr = gtk_clipboard_wait_for_text(cb); - if (fenstr==NULL) return; // nothing had been selected to copy - EditPositionPasteFEN(fenstr); - return; -} - -void -PasteGameProc () -{ - gchar *text=NULL; - GtkClipboard *cb; - guint len=0; - FILE* f; - - // get game from clipboard - GdkDisplay *gdisp = gdk_display_get_default(); - if (gdisp == NULL) return; - cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD); - text = gtk_clipboard_wait_for_text(cb); - if (text == NULL) return; // nothing to paste - len = strlen(text); - - // write to temp file - if (text == NULL || len == 0) { - return; //nothing to paste - } - f = fopen(gamePasteFilename, "w"); - if (f == NULL) { - DisplayError(_("Can't open temp file"), errno); - return; - } - fwrite(text, 1, len, f); - fclose(f); - - // load from file - LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE); - return; -} - - -#ifdef TODO_GTK -void -QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - QuitProc(); -} -#endif - -void MoveTypeInProc(eventkey) - GdkEventKey *eventkey; -{ - char buf[10]; - - // ingnore if ctrl or alt is pressed - if (eventkey->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) { - return; - } - - buf[0]=eventkey->keyval; - buf[1]='\0'; - if (*buf >= 32) - BoxAutoPopUp (buf); -} - -#ifdef TODO_GTK -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); -} -#endif - -void -ManProc () -{ // called from menu -#ifdef TODO_GTK - ManInner(NULL, NULL, NULL, NULL); -#endif -} - -void -SetWindowTitle (char *text, char *title, char *icon) -{ -#ifdef TODO_GTK - 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); -#endif - if (appData.titleInWindow) { - SetWidgetLabel(titleWidget, text); - } - gtk_window_set_title (GTK_WINDOW(shells[BoardWindow]), title); -} - - -static int -NullXErrorCheck (Display *dpy, XErrorEvent *error_event) -{ - return 0; -} - -void -DisplayIcsInteractionTitle (String message) -{ -#ifdef TODO_GTK - 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); -#endif -} - - -void -DisplayTimerLabel (Option *opt, char *color, long timer, int highlight) -{ - GtkWidget *w = (GtkWidget *) opt->handle; - char *markup; - char bgcolor[10]; - char fgcolor[10]; - - if (highlight) { - strcpy(bgcolor, "black"); - strcpy(fgcolor, "white"); - } else { - strcpy(bgcolor, "white"); - strcpy(fgcolor, "black"); - } - if (timer > 0 && - appData.lowTimeWarning && - (timer / 1000) < appData.icsAlarmTime) { - strcpy(fgcolor, appData.lowTimeWarningColor); - } - - if (appData.clockMode) { - markup = g_markup_printf_escaped("%s:%s%s", - bgcolor, fgcolor, color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer)); - } else { - markup = g_markup_printf_escaped("%s ", - bgcolor, fgcolor, color); - } - gtk_label_set_markup(GTK_LABEL(w), markup); - g_free(markup); -} - -static GdkPixbuf **clockIcons[] = { &WhiteIcon, &BlackIcon }; - -void -SetClockIcon (int color) -{ - GdkPixbuf *pm = *clockIcons[color]; - if (mainwindowIcon != pm) { - mainwindowIcon = pm; - gtk_window_set_icon(GTK_WINDOW(shellWidget), mainwindowIcon); - } -} - -#define INPUT_SOURCE_BUF_SIZE 8192 - -typedef struct { - CPKind kind; - int fd; - int lineByLine; - char *unused; - InputCallback func; - guint sid; - char buf[INPUT_SOURCE_BUF_SIZE]; - VOIDSTAR closure; -} InputSource; - -gboolean -DoInputCallback(io, cond, data) - GIOChannel *io; - GIOCondition cond; - gpointer *data; -{ - /* read input from one of the input source (for example a chess program, ICS, etc). - * and call a function that will handle the input - */ - - int count; - int error; - char *p, *q; - - /* All information (callback function, file descriptor, etc) is - * saved in an InputSource structure - */ - InputSource *is = (InputSource *) data; - - 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 True; - } - is->unused += count; - p = is->buf; - /* break input into lines and call the callback function on each - * line - */ - 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; - } - /* remember not yet used part of the buffer */ - q = is->buf; - while (p < is->unused) { - *q++ = *p++; - } - is->unused = q; - } else { - /* read maximum length of input buffer and send the whole buffer - * to the callback function - */ - 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); - } - return True; // Must return true or the watch will be removed -} - -InputSourceRef AddInputSource(pr, lineByLine, func, closure) - ProcRef pr; - int lineByLine; - InputCallback func; - VOIDSTAR closure; -{ - InputSource *is; - GIOChannel *channel; - 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; - else - is->unused = NULL; - - /* GTK-TODO: will this work on windows?*/ - - channel = g_io_channel_unix_new(is->fd); - g_io_channel_set_close_on_unref (channel, TRUE); - is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is); - - is->closure = closure; - return (InputSourceRef) is; -} - - -void -RemoveInputSource(isr) - InputSourceRef isr; -{ - InputSource *is = (InputSource *) isr; - - if (is->sid == 0) return; - g_source_remove(is->sid); - is->sid = 0; - return; -} - -#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; - - 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) -{ -#ifdef TODO_GTK - XSync(xDisplay, False); -#endif -// gtk_main_iteration_do(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; -} - -void FileNamePopUpGTK(label, def, filter, proc, pathFlag, openMode, name, fp) - char *label; - char *def; - char *filter; - FileProc proc; - char *openMode; - Boolean pathFlag; - char **name; - FILE **fp; -{ - GtkWidget *dialog; - GtkFileFilter *gtkfilter; - GtkFileFilter *gtkfilter_all; - char space[] = " "; - char fileext[10] = ""; - char *result = NULL; - char *cp; - - /* make a copy of the filter string, so that strtok can work with it*/ - cp = strndup(filter,strlen(filter)); - - /* add filters for file extensions */ - gtkfilter = gtk_file_filter_new(); - gtkfilter_all = gtk_file_filter_new(); - - /* one filter to show everything */ - gtk_file_filter_add_pattern(gtkfilter_all, "*.*"); - gtk_file_filter_set_name (gtkfilter_all, "All Files"); - - /* add filter if present */ - result = strtok(cp, space); - while( result != NULL ) { - snprintf(fileext,10,"*%s",result); - result = strtok( NULL, space ); - gtk_file_filter_add_pattern(gtkfilter, fileext); - }; - - /* second filter to only show what's useful */ - gtk_file_filter_set_name (gtkfilter,filter); - - if (openMode[0] == 'r') - { - dialog = gtk_file_chooser_dialog_new (label, - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - } - else - { - dialog = gtk_file_chooser_dialog_new (label, - NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - /* add filename suggestions */ - if (strlen(def) > 0 ) - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), def); - - //gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER (dialog),TRUE); - } - - /* add filters */ - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter_all); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); - /* activate filter */ - gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - char *filename; - FILE *f; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - - //see loadgamepopup - f = fopen(filename, openMode); - if (f == NULL) - { - DisplayError(_("Failed to open file"), errno); - } - else - { - /* TODO add indec */ - *fp = f; - ASSIGN(*name, filename); - ScheduleDelayedEvent(DelayedLoad, 50); - } - g_free (filename); - }; - - gtk_widget_destroy (dialog); - ModeHighlight(); - - free(cp); - return; - -} - diff --git a/xboard.h b/xboard.h deleted file mode 100644 index 3527343..0000000 --- a/xboard.h +++ /dev/null @@ -1,175 +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)); -#ifdef TODO_GTK -void CatchDeleteWindow(Widget w, String procname); -void GenericPopDown P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); -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)); -#endif - -extern char memoTranslations[]; - -#if TODO_GTK -extern Widget shells[]; -extern Widget formWidget, shellWidget, boardWidget, menuBarWidget; -extern Display *xDisplay; -extern Window xBoardWindow; -extern Pixmap xMarkPixmap, wIconPixmap, bIconPixmap; -extern Pixel timerForegroundPixel, timerBackgroundPixel, dialogColor, buttonColor; -extern Atom wm_delete_window; -extern GC coordGC; -extern Dimension textHeight; // of message widget in board window -#else -extern GtkWidget *shells[]; -#endif -extern int dialogError; -extern int squareSize; -extern char *layoutName; -extern int useImages, useImageSqs; -extern char ICSInputTranslations[]; -extern char *selected_fen_position; - - -#define TOPLEVEL 1 /* preference item; 1 = make popup windows toplevel */ - diff --git a/xengineoutput.c b/xengineoutput.c deleted file mode 100644 index 576d58b..0000000 --- a/xengineoutput.c +++ /dev/null @@ -1,149 +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 "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 - -extern Option engoutOptions[]; // must go in header, but which? - -/* Module variables */ -static int currentPV, highTextStart[2], highTextEnd[2]; -#ifdef TODO_GTK -static Widget memoWidget; -#endif -static GdkPixbuf *iconsGTK[8]; -static GtkWidget *outputFieldGTK[2][7]; // [HGM] front-end array to translate output field to window handlestatic void *memoWidget; - -static void -ReadIcon (gchar *svgFilename, int iconNr) -{ - char buf[MSG_SIZ]; - - snprintf(buf, MSG_SIZ, "%s/%s", SVGDIR, svgFilename); - iconsGTK[iconNr] = gdk_pixbuf_new_from_file(buf, NULL); -} - -void -InitEngineOutput (Option *opt, Option *memo2) -{ // front-end, because it must have access to the pixmaps -#ifdef TODO_GTK - Widget w = opt->handle; - memoWidget = memo2->handle; -#endif - ReadIcon("eo_White.svg", nColorWhite); - ReadIcon("eo_Black.svg", nColorBlack); - ReadIcon("eo_Unknown.svg", nColorUnknown); - - ReadIcon("eo_Clear.svg", nClear); - ReadIcon("eo_Ponder.svg", nPondering); - ReadIcon("eo_Thinking.svg", nThinking); - ReadIcon("eo_Analyzing.svg", nAnalyzing); -} - -void -DrawWidgetIcon (Option *opt, int nIcon) -{ // as we are already in GTK front-end, so do GTK-stuff here - if( nIcon != 0 ) gtk_image_set_from_pixbuf(GTK_IMAGE(opt->handle), GDK_PIXBUF(iconsGTK[nIcon])); -} - -void -InsertIntoMemo (int which, char * text, int where) -{ - char *p; - GtkTextIter start; - - /* the backend adds \r\n, which is needed for winboard, - * for xboard we delete them again over here */ - if(p = strchr(text, '\r')) *p = ' '; - - GtkTextBuffer *tb = (GtkTextBuffer *) (engoutOptions[which ? 12 : 5].handle); -// gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(tb), &start); - gtk_text_buffer_get_iter_at_offset(tb, &start, where); - gtk_text_buffer_insert(tb, &start, text, -1); - if(where < highTextStart[which]) { // [HGM] multiPVdisplay: move highlighting - int len = strlen(text); - highTextStart[which] += len; highTextEnd[which] += len; - } -} - -//--------------------------------- 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"; - -//------------------------------- 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) - if(mode) gtk_widget_show(engoutOptions[13].handle); - else gtk_widget_hide(engoutOptions[13].handle); -} - diff --git a/xgamelist.c b/xgamelist.c deleted file mode 100644 index b2f5ade..0000000 --- a/xgamelist.c +++ /dev/null @@ -1,90 +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 "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"; - - -#ifdef TODO_GTK -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(); -} -#endif - diff --git a/xgamelist.h b/xgamelist.h deleted file mode 100644 index c78e736..0000000 --- a/xgamelist.h +++ /dev/null @@ -1,33 +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 - -#ifdef TODO_GTK -void LoadSelectedProc P((Widget w, XEvent *event, - String *prms, Cardinal *nprms)); -void SetFilterProc P((Widget w, XEvent *event, - String *prms, Cardinal *nprms)); -#endif - -#endif /* XB_XGAMELIST */ diff --git a/xhistory.c b/xhistory.c deleted file mode 100644 index 0551ce1..0000000 --- a/xhistory.c +++ /dev/null @@ -1,65 +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 "common.h" -#include "backend.h" -#include "xhistory.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 FindMoveByCharIndex P(( int char_index )); - -// variables in nhistory.c -extern Option historyOptions[]; - -// ------------- low-level front-end actions called by MoveHistory back-end ----------------- - -void -ScrollToCurrent (int caretPos) -{ - static GtkTextIter iter; - gtk_text_buffer_get_iter_at_offset((GtkTextBuffer *) historyOptions[0].handle, &iter, caretPos); - gtk_text_view_scroll_to_iter((GtkTextView *) historyOptions[0].textValue, &iter, 0.0, 0, 0.5, 0.5); -} - - -// ------------------------------ callbacks -------------------------- - -char historyTranslations[] = -": select-start() \n \ -: extend-end() SelectMove() \n"; - 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 a2f749f..0000000 --- a/xoptions.c +++ /dev/null @@ -1,2004 +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 "common.h" -#include "backend.h" -#include "xboard.h" -#include "xboard2.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 - -#ifdef TODO_GTK -static Widget previous = NULL; -#endif -static Option *currentOption; -static Boolean browserUp; - -void -UnCaret () -{ -#ifdef TODO_GTK - Arg args[2]; - - if(previous) { - XtSetArg(args[0], XtNdisplayCaret, False); - XtSetValues(previous, args, 1); - } - previous = NULL; -#endif -} - -#ifdef TODO_GTK -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; -} -#endif - -void -BoardFocus () -{ -#ifdef TODO_GTK - XtSetKeyboardFocus(shellWidget, formWidget); -#endif -} - -//--------------------------- Engine-specific options menu ---------------------------------- - -int dialogError; -Option *dialogOptions[NrOfDialogs]; - -#ifdef TODO_GTK -static Arg layoutArgs[] = { - { XtNborderWidth, 0 }, - { XtNdefaultDistance, 0 }, -}; - -static Arg formArgs[] = { - { XtNborderWidth, 0 }, - { XtNresizable, (XtArgVal) True }, -}; -#endif - -void -MarkMenuItem (char *menuRef, int state) -{ - MenuItem *item = MenuNameToItem(menuRef); - - if(item) { - ((GtkCheckMenuItem *) (item->handle))->active = state; - } -} - -void GetWidgetTextGTK(GtkWidget *w, char **buf) -{ - GtkTextIter start; - GtkTextIter end; - - if (GTK_IS_ENTRY(w)) { - *buf = gtk_entry_get_text(GTK_ENTRY (w)); - } else - if (GTK_IS_TEXT_BUFFER(w)) { - gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(w), &start); - gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(w), &end); - *buf = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(w), &start, &end, FALSE); - } - else { - printf("error in GetWidgetText, invalid widget\n"); - *buf = NULL; - } -} - -void -GetWidgetText (Option *opt, char **buf) -{ - int x; - static char val[12]; - switch(opt->type) { - case Fractional: - case FileName: - case PathName: - case TextBox: GetWidgetTextGTK((GtkWidget *) opt->handle, buf); break; - case Spin: - x = gtk_spin_button_get_value (GTK_SPIN_BUTTON(opt->handle)); - snprintf(val, 12, "%d", x); *buf = val; - break; - default: - printf("unexpected case (%d) in GetWidgetText\n", opt->type); - *buf = NULL; - } -} - -void SetSpinValue(Option *opt, char *val, int n) -{ - if (opt->type == Spin) - { - if (!strcmp(val, _("Unused"))) - gtk_widget_set_sensitive(opt->handle, FALSE); - else - { - gtk_widget_set_sensitive(opt->handle, TRUE); - gtk_spin_button_set_value(opt->handle, atoi(val)); - } - } - else - printf("error in SetSpinValue, unknown type %d\n", opt->type); -} - -void SetWidgetTextGTK(GtkWidget *w, char *text) -{ - if (GTK_IS_ENTRY(w)) { - gtk_entry_set_text (GTK_ENTRY (w), text); - } else - if (GTK_IS_TEXT_BUFFER(w)) { - gtk_text_buffer_set_text(GTK_TEXT_BUFFER(w), text, -1); - } else - printf("error: SetWidgetTextGTK arg is neitherGtkEntry nor GtkTextBuffer\n"); -} - -void -SetWidgetText (Option *opt, char *buf, int n) -{ - switch(opt->type) { - case Fractional: - case FileName: - case PathName: - case TextBox: SetWidgetTextGTK((GtkWidget *) opt->handle, buf); break; - case Spin: SetSpinValue(opt, buf, n); break; - default: - printf("unexpected case (%d) in GetWidgetText\n", opt->type); - } -#ifdef TODO_GTK -// focus is automatic in GTK? - if(n >= 0) SetFocus(opt->handle, shells[n], NULL, False); -#endif -} - -void -GetWidgetState (Option *opt, int *state) -{ - *state = gtk_toggle_button_get_active(opt->handle); -} - -void -SetWidgetState (Option *opt, int state) -{ - gtk_toggle_button_set_active(opt->handle, state); -} - -void -SetWidgetLabel (Option *opt, char *buf) -{ - gtk_label_set_text(opt->handle, buf); -} - -void -SetDialogTitle (DialogClass dlg, char *title) -{ - gtk_window_set_title(GTK_WINDOW(shells[dlg]), title); -} - -void -SetListBoxItem (GtkListStore *store, int n, char *msg) -{ - GtkTreeIter iter; - GtkTreePath *path = gtk_tree_path_new_from_indices(n, -1); - gtk_tree_model_get_iter(GTK_TREE_MODEL (store), &iter, path); - gtk_tree_path_free(path); - gtk_list_store_set(store, &iter, 0, msg, -1); -} - -void -LoadListBox (Option *opt, char *emptyText, int n1, int n2) -{ - char **data = (char **) (opt->target); - GtkWidget *list = (GtkWidget *) (opt->handle); - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); - GtkListStore *store = GTK_LIST_STORE(model); - GtkTreeIter iter; - - if(n1 >= 0 && n2 >= 0) { - SetListBoxItem(store, n1, data[n1]); - SetListBoxItem(store, n2, data[n2]); - return; - } - - if (gtk_tree_model_get_iter_first(model, &iter)) - gtk_list_store_clear(store); - - while(*data) { // add elements to listbox one by one - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, *data++, -1); // 0 = first column - } -} - -void -HighlightItem (Option *opt, int index, int scroll) -{ - char *value, **data = (char **) (opt->target); - GtkWidget *list = (GtkWidget *) (opt->handle); - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list)); - GtkListStore *store = GTK_LIST_STORE(model); - GtkTreePath *path = gtk_tree_path_new_from_indices(index, -1); - GtkTreeIter iter; - gtk_tree_selection_select_path(selection, path); - if(scroll) gtk_tree_view_scroll_to_cell(list, path, NULL, 0, 0, 0); - gtk_tree_path_free(path); -} - -void -HighlightListBoxItem (Option *opt, int index) -{ - HighlightItem (opt, index, FALSE); -} - -void -HighlightWithScroll (Option *opt, int index, int max) -{ - HighlightItem (opt, index, TRUE); // ignore max -} - -int -SelectedListBoxItem (Option *opt) -{ - int i; - char *value, **data = (char **) (opt->target); - GtkWidget *list = (GtkWidget *) (opt->handle); - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list)); - - GtkTreeModel *model; - GtkTreeIter iter; - if (!gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter)) return -1; - gtk_tree_model_get(model, &iter, 0, &value, -1); - for(i=0; data[i]; i++) if(!strcmp(data[i], value)) return i; - g_free(value); - return -1; -} - -void -FocusOnWidget (Option *opt, DialogClass dlg) -{ - UnCaret(); -#ifdef TODO_GTK - XtSetKeyboardFocus(shells[dlg], opt->handle); -#endif - gtk_widget_grab_focus(opt->handle); -} - -void -SetIconName (DialogClass dlg, char *name) -{ -#ifdef TODO_GTK - 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); -#endif -} - -void ComboSelect(GtkWidget *widget, gpointer addr) -{ - Option *opt = dialogOptions[((intptr_t)addr)>>8]; // applicable option list - gint i = ((intptr_t)addr) & 255; // option number - gint g; - - g = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); - values[i] = g; // store in temporary, for transfer at OK - -#if TODO_GTK -// Note: setting text on button is probably automatic -// Is this still needed? Could be all comboboxes that needed a callbak are now listboxes! -#endif - if(opt[i].type == Graph || opt[i].min & COMBO_CALLBACK && (!currentCps || shellUp[BrowserDlg])) { - ((ButtonCallback*) opt[i].target)(i); - return; - } -} - -#ifdef TODO_GTK -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; -} -#endif - -static void -MenuSelect (gpointer addr) // callback for all combo items -{ - 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 - ((ButtonCallback*) opt[i].target)(i); -} - -static GtkWidget * -CreateMenuPopup (Option *opt, int n, int def) -{ // fromList determines if the item texts are taken from a list of strings, or from a menu table - int i; - GtkWidget *menu, *entry; - MenuItem *mb = (MenuItem *) opt->choice; - - menu = gtk_menu_new(); -// menu = XtCreatePopupShell(opt->name, simpleMenuWidgetClass, parent, NULL, 0); - for (i=0; 1; i++) - { - char *msg = mb[i].string; - if(!msg) break; - if(strcmp(msg, "----")) { // - if(!(opt->min & NO_GETTEXT)) msg = _(msg); - if(mb[i].handle) { - entry = gtk_check_menu_item_new_with_label(msg); // should be used for items that can be checkmarked - if(mb[i].handle == RADIO) gtk_check_menu_item_set_draw_as_radio(entry, True); - } else - entry = gtk_menu_item_new_with_label(msg); - gtk_signal_connect_object (GTK_OBJECT (entry), "activate", GTK_SIGNAL_FUNC(MenuSelect), (gpointer) (n<<16)+i); - gtk_widget_show(entry); - } else entry = gtk_separator_menu_item_new(); - gtk_menu_append(GTK_MENU (menu), entry); -//CreateMenuItem(menu, opt->min & NO_GETTEXT ? msg : _(msg), (XtCallbackProc) ComboSelect, (n<<16)+i); - 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 -}; - -Option *typeIn; // kludge to distinguish type-in callback from input-box callback - -void -CursorAtEnd (Option *opt) -{ - gtk_editable_set_position(opt->handle, -1); -} - -static gboolean -ICSKeyEvent(GtkWidget *widget, GdkEventKey *event, gpointer g) -{ - Option *opt = (Option *) g; - if(opt == typeIn) { - if(event->keyval == GDK_Return) { - char *val; - GetWidgetText(opt, &val); - TypeInDoneEvent(val); - PopDown(TransientDlg); - return TRUE; - } - return FALSE; - } - - switch(event->keyval) { - case GDK_Return: IcsKey(0); return TRUE; - case GDK_Up: IcsKey(1); return TRUE; - case GDK_Down: IcsKey(-1); return TRUE; - default: return FALSE; - } -} - -int shiftState, controlState; - -static gboolean -TypeInProc (GtkWidget *widget, GdkEventKey *event, gpointer gdata) -{ // This callback catches key presses on text-entries, and uses and as synonyms for dialog OK or Cancel - // *** kludge alert *** If a dialog does want some other action, like sending the line typed in the text-entry to an ICS, - // it should define an OK handler that does so, and returns FALSE to suppress the popdown. - int n = (intptr_t) gdata; - int dlg = n >> 16; - Option *opt; - n &= 0xFFFF; - opt = &dialogOptions[dlg][n]; - - if(opt == icsBox) return ICSKeyEvent(event->keyval); // Intercept ICS Input Box, which needs special treatment - - shiftState = event->state & GDK_SHIFT_MASK; - controlState = event->state & GDK_CONTROL_MASK; - switch(event->keyval) { - case GDK_Return: - if(GenericReadout(dialogOptions[dlg], -1)) PopDown(dlg); - break; - case GDK_Escape: - PopDown(dlg); - break; - default: - return FALSE; - } - return TRUE; -} - -void -HighlightText (Option *opt, int from, int to, Boolean highlight) -{ -# define INIT 0x8000 - static GtkTextIter start, end; - - if(!(opt->min & INIT)) { - opt->min |= INIT; // each memo its own init flag! - gtk_text_buffer_create_tag(opt->handle, "highlight", "background", "yellow", NULL); - gtk_text_buffer_create_tag(opt->handle, "normal", "background", "white", NULL); - } - gtk_text_buffer_get_iter_at_offset(opt->handle, &start, from); - gtk_text_buffer_get_iter_at_offset(opt->handle, &end, to); - gtk_text_buffer_apply_tag_by_name(opt->handle, highlight ? "highlight" : "normal", &start, &end); -} - -int -ShiftKeys () -{ // bassic primitive for determining if modifier keys are pressed - return 3*(shiftState != 0) + 0xC*(controlState != 0); // rely on what last mouse button press left us -} - -static gboolean -GameListEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata) -{ - int n = (int) gdata; - - if(n == 4) { - if(((GdkEventKey *) event)->keyval != GDK_Return) return FALSE; - SetFilter(); - return TRUE; - } - - if(event->type == GDK_KEY_PRESS) { - int ctrl = (((GdkEventKey *) event)->state & GDK_CONTROL_MASK) != 0; - switch(((GdkEventKey *) event)->keyval) { - case GDK_Up: GameListClicks(-1 - 2*ctrl); return TRUE; - case GDK_Left: GameListClicks(-1); return TRUE; - case GDK_Down: GameListClicks(1 + 2*ctrl); return TRUE; - case GDK_Right: GameListClicks(1); return TRUE; - case GDK_Prior: GameListClicks(-4); return TRUE; - case GDK_Next: GameListClicks(4); return TRUE; - case GDK_Home: GameListClicks(-2); return TRUE; - case GDK_End: GameListClicks(2); return TRUE; - case GDK_Return: GameListClicks(0); return TRUE; - default: return FALSE; - } - } - if(event->type != GDK_2BUTTON_PRESS || ((GdkEventButton *) event)->button != 1) return FALSE; - GameListClicks(0); - return TRUE; -} - -static gboolean -MemoEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata) -{ // handle mouse clicks on text widgets that need it - int w, h; - int button=10, f=1; - Option *opt, *memo = (Option *) gdata; - MemoCallback *userHandler = (MemoCallback *) memo->choice; - GdkEventButton *bevent = (GdkEventButton *) event; - GdkEventMotion *mevent = (GdkEventMotion *) event; - GtkTextIter start, end; - String val = NULL; - gboolean res; - gint index, x, y; - - if(memo->type == Label) { ((ButtonCallback*) memo->target)(memo->value); return TRUE; } // only clock widgets use this - - switch(event->type) { // figure out what's up - case GDK_MOTION_NOTIFY: - f = 0; - w = mevent->x; h = mevent->y; - break; - case GDK_BUTTON_RELEASE: - f = -1; // release indicated by negative button numbers - w = bevent->x; h = bevent->y; - button = bevent->button; - break; - case GDK_BUTTON_PRESS: - w = bevent->x; h = bevent->y; - button = bevent->button; - shiftState = bevent->state & GDK_SHIFT_MASK; - controlState = bevent->state & GDK_CONTROL_MASK; -// GTK_TODO: is this really the most efficient way to get the character at the mouse cursor??? - gtk_text_view_window_to_buffer_coords(widget, GTK_TEXT_WINDOW_WIDGET, w, h, &x, &y); - gtk_text_view_get_iter_at_location(widget, &start, x, y); - gtk_text_buffer_place_cursor(memo->handle, &start); - /* get cursor position into index */ - g_object_get(memo->handle, "cursor-position", &index, NULL); - /* get text from textbuffer */ - gtk_text_buffer_get_start_iter (memo->handle, &start); - gtk_text_buffer_get_end_iter (memo->handle, &end); - val = gtk_text_buffer_get_text (memo->handle, &start, &end, FALSE); - break; - default: - return FALSE; // should not happen - } - button *= f; - // hand click parameters as well as text & location to user - res = (userHandler) (memo, button, w, h, val, index); - if(val) g_free(val); - return res; -} - -void -AddHandler (Option *opt, DialogClass dlg, int nr) -{ - switch(nr) { - case 0: // history (now uses generic textview callback) - case 1: // comment (likewise) - break; - case 2: // move type-in - typeIn = opt; - case 3: // input box - g_signal_connect(opt->handle, "key-press-event", G_CALLBACK (ICSKeyEvent), (gpointer) opt); - break; - case 5: // game list - g_signal_connect(opt->handle, "button-press-event", G_CALLBACK (GameListEvent), (gpointer) 0 ); - case 4: // game-list filter - g_signal_connect(opt->handle, "key-press-event", G_CALLBACK (GameListEvent), (gpointer) nr ); - break; - case 6: // engine output (uses generic textview callback) - break; - } -} - -//----------------------------Generic dialog -------------------------------------------- - -// cloned from Engine Settings dialog (and later merged with it) - -GtkWidget *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) -{ -#ifdef TODO_GTK - 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,static gboolean -MemoEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata) - - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); - - XFlush(xDisplay); - XSync(xDisplay, False); -#endif -} - -int -PopDown (DialogClass n) -{ - //Arg args[10]; - - if (!shellUp[n] || !shells[n]) return 0; -#ifdef TODO_GTK -// Not sure this is still used - 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; - } -#endif - - gtk_widget_hide(shells[n]); - shellUp[n]--; // count rather than clear - - if(n == 0 || n >= PromoDlg) { - gtk_widget_destroy(shells[n]); - shells[n] = NULL; - } - - if(marked[n]) { - MarkMenuItem(marked[n], False); - marked[n] = NULL; - } - - if(!n) 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) -#ifdef TODO_GTK - RaiseWindow(parents[n]); // automatic in GTK? - if(parents[n] == BoardWindow) XtSetKeyboardFocus(shellWidget, formWidget); // also automatic??? -#endif - return 1; -} - -/* GTK callback used when OK/cancel clicked in genericpopup for non-modal dialog */ -gboolean GenericPopDown(w, resptype, gdata) - GtkWidget *w; - GtkResponseType resptype; - gpointer gdata; -{ - DialogClass dlg = (intptr_t) gdata; /* dialog number dlgnr */ - GtkWidget *sh = shells[dlg]; - - currentOption = dialogOptions[dlg]; - -#ifdef TODO_GTK -// I guess BrowserDlg will be abandoned, as GTK has a better browser of its own - if(shellUp[BrowserDlg] && dlg != BrowserDlg || dialogError) return True; // prevent closing dialog when it has an open file-browse daughter -#else - if(browserUp || dialogError && dlg != FatalDlg) return True; // prevent closing dialog when it has an open file-browse or error-popup daughter -#endif - shells[dlg] = w; // make sure we pop down the right one in case of multiple instances - - /* OK pressed */ - if (resptype == GTK_RESPONSE_ACCEPT) { - if (GenericReadout(currentOption, -1)) PopDown(dlg); - return TRUE; - } else - /* cancel pressed */ - { - if(dlg == BoardWindow) ExitEvent(0); - PopDown(dlg); - } - shells[dlg] = sh; // restore - return TRUE; -} - -int AppendText(Option *opt, char *s) -{ - char *v; - int len; - GtkTextIter end; - - GetWidgetTextGTK(opt->handle, &v); - len = strlen(v); - g_free(v); - gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(opt->handle), &end); - gtk_text_buffer_insert(opt->handle, &end, s, -1); - - return len; -} - -void -SetColor (char *colorName, Option *box) -{ // sets the color of a widget - GdkColor color; - - /* set the colour of the colour button to the colour that will be used */ - gdk_color_parse( colorName, &color ); - gtk_widget_modify_bg ( GTK_WIDGET(box->handle), GTK_STATE_NORMAL, &color ); -} - -#ifdef TODO_GTK -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); -} -#endif - -static void -GraphEventProc(GtkWidget *widget, GdkEvent *event, gpointer gdata) -{ // handle expose and mouse events on Graph widget - int w, h; - int j, button=10, f=1, sizing=0; - Option *opt, *graph = (Option *) gdata; - PointerCallback *userHandler = graph->target; - GdkEventExpose *eevent = (GdkEventExpose *) event; - GdkEventButton *bevent = (GdkEventButton *) event; - GdkEventMotion *mevent = (GdkEventMotion *) event; - GtkAllocation a; - cairo_t *cr; - -// if (!XtIsRealized(widget)) return; - - switch(event->type) { - case GDK_EXPOSE: // make handling of expose events generic, just copying from memory buffer (->choice) to display (->textValue) - /* Get window size */ - gtk_widget_get_allocation(widget, &a); - w = a.width; h = a.height; -//printf("expose %dx%d @ (%d,%d)\n", w, h, a.x, a.y); -#ifdef TODO_GTK - j = 0; - XtSetArg(args[j], XtNwidth, &w); j++; - XtSetArg(args[j], XtNheight, &h); j++; - XtGetValues(widget, args, j); -#endif - if(w < graph->max || w > graph->max + 1 || h != graph->value) { // use width fudge of 1 pixel - if(eevent->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 && eevent->count > 0) { graph->max = 0; return; } // don't bother if further exposure is pending during resize -#ifdef TODO_GTK - 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); - } -#endif - 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 -#ifdef TODO_GTK - if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice); - graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); -#endif - break; - } - w = eevent->area.width; - if(eevent->area.x + w > graph->max) w--; // cut off fudge pixel - cr = gdk_cairo_create(((GtkWidget *) (graph->handle))->window); - cairo_set_source_surface(cr, (cairo_surface_t *) graph->choice, 0, 0); - cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); - cairo_rectangle(cr, eevent->area.x, eevent->area.y, w, eevent->area.height); - cairo_fill(cr); - cairo_destroy(cr); - default: - return; - case GDK_MOTION_NOTIFY: - f = 0; - w = mevent->x; h = mevent->y; - break; - case GDK_BUTTON_RELEASE: - f = -1; // release indicated by negative button numbers - case GDK_BUTTON_PRESS: - w = bevent->x; h = bevent->y; - button = bevent->button; - shiftState = bevent->state & GDK_SHIFT_MASK; - controlState = bevent->state & GDK_CONTROL_MASK; - } - button *= f; - - opt = userHandler(button, w, h); -#ifdef TODO_GTK - 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); -#endif -} - -void -GraphExpose (Option *opt, int x, int y, int w, int h) -{ -#if 0 - GdkRectangle r; - r.x = x; r.y = y; r.width = w; r.height = h; - gdk_window_invalidate_rect(((GtkWidget *)(opt->handle))->window, &r, FALSE); -#endif - GdkEventExpose e; - if(!opt->handle) return; - e.area.x = x; e.area.y = y; e.area.width = w; e.area.height = h; e.count = -1; e.type = GDK_EXPOSE; // count = -1: kludge to suppress sizing - GraphEventProc(opt->handle, (GdkEvent *) &e, (gpointer) opt); // fake expose event -} - -void GenericCallback(GtkWidget *widget, gpointer gdata) -{ - const gchar *name; - char buf[MSG_SIZ]; - int data = (intptr_t) gdata; - DialogClass dlg; -#ifdef TODO_GTK - GtkWidget *sh = XtParent(XtParent(XtParent(w))), *oldSh; -#else - GtkWidget *sh, *oldSh; -#endif - - currentOption = dialogOptions[dlg=data>>16]; data &= 0xFFFF; -#ifndef TODO_GTK - sh = shells[dlg]; // make following line a no-op, as we haven't found out what the real shell is yet (breaks multiple popups of same type!) -#endif - 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) { - name = gtk_button_get_label (GTK_BUTTON(widget)); - 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 BrowseGTK(GtkWidget *widget, gpointer gdata) -{ - GtkWidget *entry; - GtkWidget *dialog; - GtkFileFilter *gtkfilter; - GtkFileFilter *gtkfilter_all; - int opt_i = (intptr_t) gdata; - GtkFileChooserAction fc_action; - - gtkfilter = gtk_file_filter_new(); - gtkfilter_all = gtk_file_filter_new(); - - char fileext[10] = "*"; - - /* select file or folder depending on option_type */ - if (currentOption[opt_i].type == PathName) - fc_action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - else - fc_action = GTK_FILE_CHOOSER_ACTION_OPEN; - - dialog = gtk_file_chooser_dialog_new ("Open File", - NULL, - fc_action, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - - /* one filter to show everything */ - gtk_file_filter_add_pattern(gtkfilter_all, "*"); - gtk_file_filter_set_name (gtkfilter_all, "All Files"); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),gtkfilter_all); - - /* filter for specific filetypes e.g. pgn or fen */ - if (currentOption[opt_i].textValue != NULL && (strcmp(currentOption[opt_i].textValue, "") != 0) ) - { - strcat(fileext, currentOption[opt_i].textValue); - gtk_file_filter_add_pattern(gtkfilter, fileext); - gtk_file_filter_set_name (gtkfilter, currentOption[opt_i].textValue); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); - /* activate filter */ - gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter); - } - else - gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter_all); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - { - char *filename; - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - entry = currentOption[opt_i].handle; - gtk_entry_set_text (GTK_ENTRY (entry), filename); - g_free (filename); - - } - gtk_widget_destroy (dialog); - dialog = NULL; -} - -gboolean -ListCallback (GtkWidget *widget, GdkEventButton *event, gpointer gdata) -{ - int n = (intptr_t) gdata & 0xFFFF; - int dlg = (intptr_t) gdata >> 16; - Option *opt = dialogOptions[dlg] + n; - - if(event->type != GDK_2BUTTON_PRESS || event->button != 1) return FALSE; - ((ListBoxCallback*) opt->textValue)(n, SelectedListBoxItem(opt)); - return TRUE; -} - -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 -#ifdef TODO_GTK - 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; -#endif -} - -#ifdef TODO_GTK -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; -} -#endif - -static int -TableWidth (Option *opt) -{ // Hideous work-around! If the table is 3 columns, but 2 & 3 are always occupied together, the fixing of the width of column 1 does not work - while(opt->type != EndMark && opt->type != Break) - if(opt->type == FileName || opt->type == PathName || opt++->type == BarBegin) return 3; // This table needs browse button - return 2; // no browse button; -} - -static int -SameRow (Option *opt) -{ - return (opt->min & SAME_ROW && (opt->type == Button || opt->type == SaveButton || opt->type == Label - || opt->type == ListBox || opt->type == BoxBegin || opt->type == Icon)); -} - -static void -Pack (GtkWidget *hbox, GtkWidget *table, GtkWidget *entry, int left, int right, int top, GtkAttachOptions vExpand) -{ - if(hbox) gtk_box_pack_start(GTK_BOX (hbox), entry, TRUE, TRUE, 0); - else gtk_table_attach(GTK_TABLE(table), entry, left, right, top, top+1, - GTK_FILL | GTK_EXPAND, GTK_FILL | vExpand, 2, 1); -} - -int -GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent, int modal, int topLevel) -{ - GtkWidget *dialog = NULL; - gint w; - GtkWidget *label; - GtkWidget *box; - GtkWidget *checkbutton; - GtkWidget *entry; - GtkWidget *oldHbox, *hbox = NULL; - GtkWidget *pane = NULL; - GtkWidget *button; - GtkWidget *table; - GtkWidget *spinner; - GtkAdjustment *spinner_adj; - GtkWidget *combobox; - GtkWidget *textview; - GtkTextBuffer *textbuffer; - GdkColor color; - GtkWidget *actionarea; - GtkWidget *sw; - GtkWidget *list; - GtkWidget *graph; - GtkWidget *menuButton; - GtkWidget *menuBar; - GtkWidget *menu; - - int i, j, arraysize, left, top, height=999, width=1, boxStart, breakType = 0, r; - char def[MSG_SIZ], *msg, engineDlg = (currentCps != NULL && dlgNr != BrowserDlg); - - if(dlgNr < PromoDlg && shellUp[dlgNr]) return 0; // already up - - if(dlgNr && dlgNr < PromoDlg && shells[dlgNr]) { // reusable, and used before (but popped down) - gtk_widget_show(shells[dlgNr]); - 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 > 50) width = 4; else if(n>24) width = 2; else width = 1; - width = n / 20 + 1; - height = n / width + 1; -printf("n=%d, h=%d, w=%d\n",n,height,width); -// 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 - } - - parents[dlgNr] = parent; -#ifdef TODO_GTK - shells[BoardWindow] = shellWidget; parents[dlgNr] = parent; - - if(dlgNr == BoardWindow) dialog = shellWidget; else - dialog = - XtCreatePopupShell(title, !top || !appData.topLevel ? transientShellWidgetClass : topLevelShellWidgetClass, - shells[parent], args, i); -#endif - dialog = gtk_dialog_new_with_buttons( title, - GTK_WINDOW(shells[parent]), - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR | - (modal ? GTK_DIALOG_MODAL : 0), - GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, - GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, - NULL ); - - shells[dlgNr] = dialog; - box = gtk_dialog_get_content_area( GTK_DIALOG( dialog ) ); -// gtk_box_set_spacing(GTK_BOX(box), 5); - - arraysize = 0; - for (i=0;option[i].type != EndMark;i++) { - arraysize++; - } - - table = gtk_table_new(arraysize, r=TableWidth(option), FALSE); - left = 0; - top = -1; - - for (i=0;option[i].type != EndMark;i++) { - if(option[i].type == -1) continue; - top++; -printf("option =%2d, top =%2d\n", i, top); - if (top >= height) { - gtk_table_resize(GTK_TABLE(table), height, r); - if(!pane) { // multi-column: put tables in intermediate hbox - if(breakType || engineDlg) - pane = gtk_hbox_new (FALSE, 0); - else - pane = gtk_vbox_new (FALSE, 0); - gtk_box_set_spacing(GTK_BOX(pane), 5 + 5*breakType); - gtk_box_pack_start (GTK_BOX (/*GTK_DIALOG (dialog)->vbox*/box), pane, TRUE, TRUE, 0); - } - gtk_box_pack_start (GTK_BOX (pane), table, TRUE, TRUE, 0); - table = gtk_table_new(arraysize - i, r=TableWidth(option + i), FALSE); - top = 0; - } - if(!SameRow(&option[i])) { - if(SameRow(&option[i+1])) { - GtkAttachOptions x = GTK_FILL; - // make sure hbox is always available when we have more options on same row - hbox = gtk_hbox_new (option[i].type == Button && option[i].textValue, 0); - if(!currentCps && option[i].value > 80) x |= GTK_EXPAND; // only vertically extended widgets should size vertically - if (strcmp(option[i].name, "") == 0 || option[i].type == Label || option[i].type == Button) - // for Label and Button name is contained inside option - gtk_table_attach(GTK_TABLE(table), hbox, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, x, 2, 1); - else - gtk_table_attach(GTK_TABLE(table), hbox, left+1, left+r, top, top+1, GTK_FILL | GTK_EXPAND, x, 2, 1); - } else hbox = NULL; //and also make sure no hbox exists if only singl option on row - } else top--; - switch(option[i].type) { - case Fractional: - snprintf(def, MSG_SIZ, "%.2f", *(float*)option[i].target); - option[i].value = *(float*)option[i].target; - goto tBox; - case Spin: - if(!currentCps) option[i].value = *(int*)option[i].target; - snprintf(def, MSG_SIZ, "%d", option[i].value); - case TextBox: - case FileName: - case PathName: - tBox: - label = gtk_label_new(option[i].name); - /* Left Justify */ - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - - /* width */ - w = option[i].type == Spin || option[i].type == Fractional ? 70 : option[i].max ? option[i].max : 205; - if(option[i].type == FileName || option[i].type == PathName) w -= 55; - - if (option[i].type==TextBox && option[i].value > 80){ - textview = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), option[i].min & T_WRAP ? GTK_WRAP_WORD : GTK_WRAP_NONE); -#ifdef TODO_GTK - if(option[i].min & T_FILL) { XtSetArg(args[j], XtNautoFill, True); j++; } - if(option[i].min & T_TOP) { XtSetArg(args[j], XtNtop, XtChainTop); j++; -#endif - /* add textview to scrolled window so we have vertical scroll bar */ - sw = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), - option[i].min & T_HSCRL ? GTK_POLICY_ALWAYS : GTK_POLICY_AUTOMATIC, - option[i].min & T_VSCRL ? GTK_POLICY_ALWAYS : GTK_POLICY_NEVER); - gtk_container_add(GTK_CONTAINER(sw), textview); - gtk_widget_set_size_request(GTK_WIDGET(sw), w, -1); - - textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); - /* check if label is empty */ - if (strcmp(option[i].name,"") != 0) { - gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); - Pack(hbox, table, sw, left+1, left+r, top, 0); - } - else { - /* no label so let textview occupy all columns */ - Pack(hbox, table, sw, left, left+r, top, GTK_EXPAND); - } - if ( *(char**)option[i].target != NULL ) - gtk_text_buffer_set_text (textbuffer, *(char**)option[i].target, -1); - else - gtk_text_buffer_set_text (textbuffer, "", -1); - option[i].handle = (void*)textbuffer; - option[i].textValue = (char*)textview; - if(option[i].choice) { // textviews can request a handler for mouse events in the choice field - g_signal_connect(textview, "button-press-event", G_CALLBACK (MemoEvent), (gpointer) &option[i] ); - g_signal_connect(textview, "button-release-event", G_CALLBACK (MemoEvent), (gpointer) &option[i] ); - g_signal_connect(textview, "motion-notify-event", G_CALLBACK (MemoEvent), (gpointer) &option[i] ); - } - break; - } - - entry = gtk_entry_new(); - - if (option[i].type==Spin || option[i].type==Fractional) - gtk_entry_set_text (GTK_ENTRY (entry), def); - else if (currentCps) - gtk_entry_set_text (GTK_ENTRY (entry), option[i].textValue); - else if ( *(char**)option[i].target != NULL ) - gtk_entry_set_text (GTK_ENTRY (entry), *(char**)option[i].target); - - //gtk_entry_set_width_chars (GTK_ENTRY (entry), 18); - gtk_entry_set_max_length (GTK_ENTRY (entry), w); - - // left, right, top, bottom - if (strcmp(option[i].name, "") != 0) - gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); // leading names do not expand - - if (option[i].type == Spin) { - spinner_adj = (GtkAdjustment *) gtk_adjustment_new (option[i].value, option[i].min, option[i].max, 1.0, 0.0, 0.0); - spinner = gtk_spin_button_new (spinner_adj, 1.0, 0); - gtk_table_attach(GTK_TABLE(table), spinner, left+1, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); - option[i].handle = (void*)spinner; - } - else if (option[i].type == FileName || option[i].type == PathName) { - gtk_table_attach(GTK_TABLE(table), entry, left+1, left+2, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); - button = gtk_button_new_with_label ("Browse"); - gtk_table_attach(GTK_TABLE(table), button, left+2, left+r, top, top+1, GTK_FILL, GTK_FILL, 2, 1); // Browse button does not expand - g_signal_connect (button, "clicked", G_CALLBACK (BrowseGTK), (gpointer)(intptr_t) i); - option[i].handle = (void*)entry; - } - else { - Pack(hbox, table, entry, left + (strcmp(option[i].name, "") != 0), left+r, top, 0); - option[i].handle = (void*)entry; - } - break; - case CheckBox: - checkbutton = gtk_check_button_new_with_label(option[i].name); - if(!currentCps) option[i].value = *(Boolean*)option[i].target; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), option[i].value); - gtk_table_attach(GTK_TABLE(table), checkbutton, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 0); - option[i].handle = (void *)checkbutton; - break; - case Icon: - option[i].handle = (void *) (label = gtk_image_new_from_pixbuf(NULL)); - gtk_widget_set_size_request(label, option[i].max ? option[i].max : -1, -1); - Pack(hbox, table, label, left, left+2, top, 0); - break; - case Label: - option[i].handle = (void *) (label = gtk_label_new(option[i].name)); - /* Left Justify */ - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - if(option[i].min & BORDER) { - GtkWidget *frame = gtk_frame_new(NULL); - gtk_container_add(GTK_CONTAINER(frame), label); - label = frame; - } - gtk_widget_set_size_request(label, option[i].max ? option[i].max : -1, -1); - Pack(hbox, table, label, left, left+2, top, 0); - if(option[i].target) { // allow user to specify event handler for button presses - gtk_widget_add_events(GTK_WIDGET(label), GDK_BUTTON_PRESS_MASK); - g_signal_connect(label, "button-press-event", G_CALLBACK(MemoEvent), (gpointer) &option[i]); - } - break; - case SaveButton: - case Button: - button = gtk_button_new_with_label (option[i].name); - - /* set button color on view board dialog */ - if(option[i].choice && ((char*)option[i].choice)[0] == '#' && !currentCps) { - gdk_color_parse( *(char**) option[i-1].target, &color ); - gtk_widget_modify_bg ( GTK_WIDGET(button), GTK_STATE_NORMAL, &color ); - } - - /* set button color on new variant dialog */ - if(option[i].textValue) { - gdk_color_parse( option[i].textValue, &color ); - gtk_widget_modify_bg ( GTK_WIDGET(button), GTK_STATE_NORMAL, &color ); - gtk_widget_set_sensitive(button, appData.noChessProgram || option[i].value < 0 - || strstr(first.variants, VariantName(option[i].value))); - } - - Pack(hbox, table, button, left, left+1, top, 0); - g_signal_connect (button, "clicked", G_CALLBACK (GenericCallback), (gpointer)(intptr_t) i + (dlgNr<<16)); - option[i].handle = (void*)button; - break; - case ComboBox: - label = gtk_label_new(option[i].name); - /* Left Justify */ - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); - - combobox = gtk_combo_box_new_text(); - - for(j=0;;j++) { - if ( ((char **) option[i].textValue)[j] == NULL) break; - gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), ((char **) option[i].choice)[j]); - } - - if(currentCps) - option[i].choice = (char**) option[i].textValue; - else { - for(j=0; option[i].choice[j]; j++) { - if(*(char**)option[i].target && !strcmp(*(char**)option[i].target, ((char**)(option[i].textValue))[j])) break; - } - /* If choice is NULL set to first */ - if (option[i].choice[j] == NULL) - option[i].value = 0; - else - option[i].value = j; - } - - //option[i].value = j + (option[i].choice[j] == NULL); - gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), option[i].value); - - Pack(hbox, table, combobox, left+1, left+r, top, 0); - g_signal_connect(G_OBJECT(combobox), "changed", G_CALLBACK(ComboSelect), (gpointer) (intptr_t) (i + 256*dlgNr)); - - option[i].handle = (void*)combobox; - values[i] = option[i].value; - break; - case ListBox: - { - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkListStore *store; - - option[i].handle = (void *) (list = gtk_tree_view_new()); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE); - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes("List Items", renderer, "text", 0, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); - store = gtk_list_store_new(1, G_TYPE_STRING); // 1 column of text - gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store)); - g_object_unref(store); - LoadListBox(&option[i], "?", -1, -1); - HighlightListBoxItem(&option[i], 0); - - /* add listbox to scrolled window so we have vertical scroll bar */ - sw = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(sw), list); - gtk_widget_set_size_request(GTK_WIDGET(sw), option[i].max ? option[i].max : -1, option[i].value ? option[i].value : -1); - - if(option[i].textValue) // generic callback for double-clicking listbox item - g_signal_connect(list, "button-press-event", G_CALLBACK(ListCallback), (gpointer) (dlgNr<<16 | i) ); - - /* never has label, so let listbox occupy all columns */ - Pack(hbox, table, sw, left, left+r, top, GTK_EXPAND); - } - break; - case Graph: - option[i].handle = (void*) (graph = gtk_drawing_area_new()); - gtk_widget_set_size_request(graph, option[i].max, option[i].value); - Pack(hbox, GTK_TABLE(table), graph, left, left+r, top, GTK_EXPAND); - g_signal_connect (graph, "expose-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); - gtk_widget_add_events(GTK_WIDGET(graph), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); - g_signal_connect (graph, "button-press-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); - g_signal_connect (graph, "button-release-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); - g_signal_connect (graph, "motion-notify-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); - -#ifdef TODO_GTK - 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; -#endif - option[i].choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, option[i].max, option[i].value); // image buffer - break; -#ifdef TODO_GTK - 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; -#endif - case DropDown: - top--; - 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*) - (menuButton = gtk_menu_item_new_with_label(msg)); - gtk_widget_show(menuButton); - option[i].textValue = (char*) (menu = CreateMenuPopup(option + i, i + 256*dlgNr, -1)); - gtk_menu_item_set_submenu(GTK_MENU_ITEM (menuButton), menu); - gtk_menu_bar_append (GTK_MENU_BAR (menuBar), menuButton); - - break; - case BarBegin: - menuBar = gtk_menu_bar_new (); - gtk_widget_show (menuBar); - boxStart = i; - break; - case BoxBegin: - option[i+1].min |= SAME_ROW; // kludge to suppress allocation of new hbox - oldHbox = hbox; - option[i].handle = (void*) (hbox = gtk_hbox_new(FALSE, 0)); // hbox to collect buttons - gtk_box_pack_start(GTK_BOX (oldHbox), hbox, FALSE, TRUE, 0); // *** Beware! Assumes button bar always on same row with other! *** -// gtk_table_attach(GTK_TABLE(table), hbox, left+2, left+3, top, top+1, GTK_FILL | GTK_SHRINK, GTK_FILL, 2, 1); - boxStart = i; - break; - case BarEnd: - top--; - gtk_table_attach(GTK_TABLE(table), menuBar, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); - - if(option[i].target) ((ButtonCallback*)option[i].target)(boxStart); // callback that can make sizing decisions - break; - case BoxEnd: -// XtManageChildren(&form, 1); -// SqueezeIntoBox(&option[boxStart], i-boxStart, option[boxStart].max); - hbox = oldHbox; top--; - if(option[i].target) ((ButtonCallback*)option[i].target)(boxStart); // callback that can make sizing decisions - break; - case Break: - breakType = option[i].min & SAME_ROW; - top = height; // force next option to start in a new table - break; - - case PopUp: - top--; - break; - default: - printf("GenericPopUp: unexpected case in switch. i=%d type=%d name=%s.\n", i, option[i].type, option[i].name); - break; - } - } - - if(pane) - gtk_box_pack_start (GTK_BOX (pane), table, TRUE, TRUE, 0); - else - gtk_table_resize(GTK_TABLE(table), top+1, r), - gtk_box_pack_start (GTK_BOX (/*GTK_DIALOG (dialog)->vbox*/box), table, TRUE, TRUE, 0); - - option[i].handle = (void *) table; // remember last table in EndMark handle (for hiding Engine-Output pane). - - /* Show dialog */ - gtk_widget_show_all( dialog ); - - /* hide OK/cancel buttons */ - if((option[i].min & 2)) { - actionarea = gtk_dialog_get_action_area(GTK_DIALOG(dialog)); - gtk_widget_hide(actionarea); - } - - g_signal_connect (dialog, "response", - G_CALLBACK (GenericPopDown), - (gpointer)(intptr_t) dlgNr); - g_signal_connect (dialog, "delete-event", - G_CALLBACK (GenericPopDown), - (gpointer)(intptr_t) dlgNr); - shellUp[dlgNr]++; - -#ifdef TODO_GTK - 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 > 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); -#endif - return 1; // tells caller he must do initialization (e.g. add specific event handlers) -} - -/* function called when the data to Paste is ready */ -#ifdef TODO_GTK -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); -} -#endif - -void -SendText (int n) -{ -#ifdef TODO_GTK - 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); -#endif -} - -void -SetInsertPos (Option *opt, int pos) -{ -#ifdef TODO_GTK - 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); -#endif -} - -#ifdef TODO_GTK -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); -#endif -} - - diff --git a/xtimer.c b/xtimer.c deleted file mode 100644 index 96313f9..0000000 --- a/xtimer.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * xtimer.c -- timing functions for X front end of 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 - -#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_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 - -#include "common.h" -#include "backend.h" -#include "frontend.h" - -#ifdef __EMX__ -#ifndef HAVE_USLEEP -#define HAVE_USLEEP -#endif -#define usleep(t) _sleep2(((t)+500)/1000) -#endif - -guint delayedEventTimerTag = 0; -DelayedEventCallback delayedEventCallback = 0; - -void -FireDelayedEvent(gpointer data) -{ - g_source_remove(delayedEventTimerTag); - delayedEventTimerTag = 0; - delayedEventCallback(); -} - -void -ScheduleDelayedEvent (DelayedEventCallback cb, long millisec) -{ - if(delayedEventTimerTag && delayedEventCallback == cb) - // [HGM] alive: replace, rather than add or flush identical event - g_source_remove(delayedEventTimerTag); - delayedEventCallback = cb; - delayedEventCallback = cb; - delayedEventTimerTag = g_timeout_add(millisec,(GSourceFunc) FireDelayedEvent, NULL); -} - -DelayedEventCallback -GetDelayedEvent () -{ - if (delayedEventTimerTag) { - return delayedEventCallback; - } else { - return NULL; - } -} - -void -CancelDelayedEvent () -{ - if (delayedEventTimerTag) { - g_source_remove(delayedEventTimerTag); - delayedEventTimerTag = 0; - } -} - - -guint loadGameTimerTag = 0; - -int LoadGameTimerRunning() -{ - return loadGameTimerTag != 0; -} - -int -StopLoadGameTimer () -{ - if (loadGameTimerTag != 0) { - g_source_remove(loadGameTimerTag); - loadGameTimerTag = 0; - return TRUE; - } else { - return FALSE; - } -} - -void -LoadGameTimerCallback(gpointer data) -{ - g_source_remove(loadGameTimerTag); - loadGameTimerTag = 0; - AutoPlayGameLoop(); -} - -void -StartLoadGameTimer (long millisec) -{ - loadGameTimerTag = - g_timeout_add( millisec, (GSourceFunc) LoadGameTimerCallback, NULL); -} - -guint analysisClockTag = 0; - -void -AnalysisClockCallback(gpointer data) -{ - if (gameMode == AnalyzeMode || gameMode == AnalyzeFile - || appData.icsEngineAnalyze) { // [DM] - AnalysisPeriodicEvent(0); - } -} - -void -StartAnalysisClock () -{ - analysisClockTag = - g_timeout_add( 2000,(GSourceFunc) AnalysisClockCallback, NULL); -} - -guint clockTimerTag = 0; - -int -ClockTimerRunning () -{ - return clockTimerTag != 0; -} - -int -StopClockTimer () -{ - if (clockTimerTag != 0) - { - g_source_remove(clockTimerTag); - clockTimerTag = 0; - return TRUE; - } else { - return FALSE; - } -} - -void -ClockTimerCallback(gpointer data) -{ - /* remove timer */ - g_source_remove(clockTimerTag); - clockTimerTag = 0; - - DecrementClocks(); -} - -void -StartClockTimer (long millisec) -{ - clockTimerTag = g_timeout_add(millisec,(GSourceFunc) ClockTimerCallback,NULL); -} - - -- 1.7.0.4