1 /*
2 * Engine output (PV)
3 *
4 * Author: Alessandro Scotti (Dec 2005)
5 *
6 * Copyright 2005 Alessandro Scotti
7 *
8 * Enhancements Copyright 2009, 2010, 2011, 2012, 2013,
9 * 2014, 2015, 2016 Free Software Foundation, Inc.
10 *
11 * ------------------------------------------------------------------------
12 *
13 * GNU XBoard is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or (at
16 * your option) any later version.
17 *
18 * GNU XBoard is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see http://www.gnu.org/licenses/.
25 *
26 * ------------------------------------------------------------------------
27 ** See the file ChangeLog for a revision history. */
28
29 #include "config.h"
30
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <errno.h>
34 #include <sys/types.h>
35
36 #if STDC_HEADERS
37 # include <stdlib.h>
38 # include <string.h>
39 #else /* not STDC_HEADERS */
40 extern char *getenv();
41 # if HAVE_STRING_H
42 # include <string.h>
43 # else /* not HAVE_STRING_H */
44 # include <strings.h>
45 # endif /* not HAVE_STRING_H */
46 #endif /* not STDC_HEADERS */
47
48 #if HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif
51
52 #include <X11/Intrinsic.h>
53 #include <X11/StringDefs.h>
54 #include <X11/Shell.h>
55 #include <X11/Xaw/Dialog.h>
56 #include <X11/Xaw/Form.h>
57 #include <X11/Xaw/List.h>
58 #include <X11/Xaw/Label.h>
59 #include <X11/Xaw/SimpleMenu.h>
60 #include <X11/Xaw/SmeBSB.h>
61 #include <X11/Xaw/SmeLine.h>
62 #include <X11/Xaw/Box.h>
63 #include <X11/Xaw/Paned.h>
64 #include <X11/Xaw/MenuButton.h>
65 #include <X11/cursorfont.h>
66 #include <X11/Xaw/Text.h>
67 #include <X11/Xaw/AsciiText.h>
68 #include <X11/Xaw/Viewport.h>
69 #include <X11/Xatom.h>
70 #include <X11/Xmu/Atoms.h>
71
72 #include "common.h"
73 #include "frontend.h"
74 #include "backend.h"
75 #include "dialogs.h"
76 #include "xboard.h"
77 #include "engineoutput.h"
78 #include "gettext.h"
79
80 #ifdef ENABLE_NLS
81 # define _(s) gettext (s)
82 # define N_(s) gettext_noop (s)
83 #else
84 # define _(s) (s)
85 # define N_(s) s
86 #endif
87
88 // [HGM] bitmaps of some ICONS used in the engine-outut window
89
90 static unsigned char CLEAR_14[28];
91
92 static unsigned char WHITE_14[] = {
93 0xe0, 0x01, 0x18, 0x06, 0x04, 0x08, 0x02, 0x10, 0x02, 0x10, 0x01, 0x20, 0x01, 0x20,
94 0x01, 0x20, 0x01, 0x20, 0x02, 0x10, 0x02, 0x10, 0x04, 0x08, 0x18, 0x06, 0xe0, 0x01
95 };
96
97 static unsigned char BLACK_14[] = {
98 0xe0, 0x01, 0xf8, 0x07, 0xfc, 0x0f, 0xfe, 0x1f, 0xfe, 0x1f, 0xff, 0x3f, 0xff, 0x3f,
99 0xff, 0x3f, 0xff, 0x3f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xe0, 0x01
100 };
101
102 static unsigned char ANALYZE_14[] = {
103 0x80, 0x03, 0x60, 0x0c, 0x10, 0x10, 0x90, 0x10, 0xc8, 0x20, 0x08, 0x20, 0x08, 0x20,
104 0x10, 0x10, 0x10, 0x10, 0x68, 0x0c, 0x94, 0x03, 0x0a, 0x00, 0x07, 0x00, 0x00, 0x00
105 };
106
107 static unsigned char THINK_14[] = {
108 0xe0, 0x00, 0x18, 0x03, 0x44, 0x04, 0x42, 0x08, 0x42, 0x08, 0x41, 0x10, 0xe1, 0x13,
109 0x41, 0x10, 0x02, 0x08, 0x02, 0x08, 0x04, 0x04, 0x18, 0x03, 0xe0, 0x00, 0x00, 0x00
110 };
111
112 static unsigned char PONDER_14[] = {
113 0x30, 0x03, 0x8c, 0x0c, 0x02, 0x10, 0x01, 0x08, 0x01, 0x10, 0x06, 0x20, 0x04, 0x20,
114 0x02, 0x10, 0x04, 0x0c, 0xc8, 0x04, 0x34, 0x03, 0x0e, 0x00, 0x01, 0x00, 0x00, 0x00
115 };
116
117 static unsigned char UNKNOWN_14[] = {
118 0xe0, 0x01, 0x58, 0x07, 0xac, 0x0a, 0x56, 0x15, 0xaa, 0x1a, 0x55, 0x35, 0xab, 0x2a,
119 0x55, 0x35, 0xab, 0x2a, 0x56, 0x15, 0xaa, 0x1a, 0x54, 0x0d, 0xb8, 0x06, 0xe0, 0x01
120 };
121
122
123
124 /* Module variables */
125 static int currentPV;
126 static Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle
127 static Widget memoWidget;
128
129
130 static void
ReadIcon(unsigned char pixData[],int iconNr,Widget w)131 ReadIcon (unsigned char pixData[], int iconNr, Widget w)
132 {
133 icons[iconNr] = XCreateBitmapFromData(xDisplay, XtWindow(w), (char*) pixData, 14, 14);
134 }
135
136 void
InitEngineOutput(Option * opt,Option * memo2)137 InitEngineOutput (Option *opt, Option *memo2)
138 { // front-end, because it must have access to the pixmaps
139 Widget w = opt->handle;
140 memoWidget = memo2->handle;
141
142 ReadIcon(WHITE_14, nColorWhite, w);
143 ReadIcon(BLACK_14, nColorBlack, w);
144 ReadIcon(UNKNOWN_14, nColorUnknown, w);
145
146 ReadIcon(CLEAR_14, nClear, w);
147 ReadIcon(PONDER_14, nPondering, w);
148 ReadIcon(THINK_14, nThinking, w);
149 ReadIcon(ANALYZE_14, nAnalyzing, w);
150 }
151
152 void
DrawWidgetIcon(Option * opt,int nIcon)153 DrawWidgetIcon (Option *opt, int nIcon)
154 { // as we are already in X front-end, so do X-stuff here
155 Arg arg;
156 XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]);
157 XtSetValues(opt->handle, &arg, 1);
158 }
159
160 void
InsertIntoMemo(int which,char * text,int where)161 InsertIntoMemo (int which, char * text, int where)
162 {
163 XawTextBlock t;
164 Widget edit;
165
166 /* the backend adds \r\n, which is needed for winboard,
167 * for xboard we delete them again over here */
168 if(t.ptr = strchr(text, '\r')) *t.ptr = ' ';
169
170 t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit;
171 edit = XtNameToWidget(shells[EngOutDlg], which ? "*paneB.text" : "*paneA.text");
172 XawTextReplace(edit, where, where, &t);
173 if(where < highTextStart[which]) { // [HGM] multiPVdisplay: move highlighting
174 int len = strlen(text);
175 highTextStart[which] += len; highTextEnd[which] += len;
176 XawTextSetSelection( edit, highTextStart[which], highTextEnd[which] );
177 }
178 }
179
180 //--------------------------------- PV walking ---------------------------------------
181
182 char memoTranslations[] =
183 ":Ctrl<Key>c: CopyMemoProc() \n \
184 <Btn3Motion>: HandlePV() \n \
185 Shift<Btn3Down>: select-start() extend-end(PRIMARY) SelectPV(1) \n \
186 Any<Btn3Down>: select-start() extend-end(PRIMARY) SelectPV(0) \n \
187 <Btn3Up>: StopPV() \n";
188
189 void
SelectPV(Widget w,XEvent * event,String * params,Cardinal * nParams)190 SelectPV (Widget w, XEvent * event, String * params, Cardinal * nParams)
191 { // [HGM] pv: translate click to PV line, and load it for display
192 String val;
193 int start, end;
194 XawTextPosition index, dummy;
195 int x, y;
196 Arg arg;
197
198 x = event->xmotion.x; y = event->xmotion.y;
199 currentPV = (w != memoWidget);
200 XawTextGetSelectionPos(w, &index, &dummy);
201 XtSetArg(arg, XtNstring, &val);
202 XtGetValues(w, &arg, 1);
203 shiftKey = strcmp(params[0], "0");
204 if(LoadMultiPV(x, y, val, index, &start, &end, currentPV)) {
205 XawTextSetSelection( w, start, end );
206 highTextStart[currentPV] = start; highTextEnd[currentPV] = end;
207 }
208 }
209
210 void
StopPV(Widget w,XEvent * event,String * params,Cardinal * nParams)211 StopPV (Widget w, XEvent * event, String * params, Cardinal * nParams)
212 { // [HGM] pv: on right-button release, stop displaying PV
213 XawTextUnsetSelection( w );
214 highTextStart[currentPV] = highTextEnd[currentPV] = 0;
215 UnLoadPV();
216 XtCallActionProc(w, "beginning-of-file", event, NULL, 0);
217 }
218
219 //------------------------- Ctrl-C copying of memo texts ---------------------------
220
221 // Awfull code: first read our own primary selection into selected_fen_position,
222 // and then transfer ownership of this to the clipboard, so that the
223 // copy-position callback can fetch it there when somebody pastes it
224 // Worst of all is that I only added it because I did not know how to copy primary:
225 // my laptop has no middle button. Ctrl-C might not be needed at all... [HGM]
226
227 // cloned from CopyPositionProc. Abuse selected_fen_position to hold selection
228
229 Boolean SendPositionSelection(Widget w, Atom *selection, Atom *target,
230 Atom *type_return, XtPointer *value_return,
231 unsigned long *length_return, int *format_return); // from xboard.c
232
233 static void
MemoCB(Widget w,XtPointer client_data,Atom * selection,Atom * type,XtPointer value,unsigned long * len,int * format)234 MemoCB (Widget w, XtPointer client_data, Atom *selection,
235 Atom *type, XtPointer value, unsigned long *len, int *format)
236 {
237 if (value==NULL || *len==0) return; /* nothing had been selected to copy */
238 selected_fen_position = value;
239 selected_fen_position[*len]='\0'; /* normally this string is terminated, but be safe */
240 XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
241 CurrentTime,
242 SendPositionSelection,
243 NULL/* lose_ownership_proc */ ,
244 NULL/* transfer_done_proc */);
245 }
246
247 void
CopyMemoProc(Widget w,XEvent * event,String * prms,Cardinal * nprms)248 CopyMemoProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
249 {
250 if(appData.pasteSelection) return;
251 if (selected_fen_position) free(selected_fen_position);
252 XtGetSelectionValue(menuBarWidget,
253 XA_PRIMARY, XA_STRING,
254 /* (XtSelectionCallbackProc) */ MemoCB,
255 NULL, /* client_data passed to PastePositionCB */
256
257 /* better to use the time field from the event that triggered the
258 * call to this function, but that isn't trivial to get
259 */
260 CurrentTime
261 );
262 }
263
264 //------------------------------- pane switching -----------------------------------
265
266 void
ResizeWindowControls(int mode)267 ResizeWindowControls (int mode)
268 { // another hideous kludge: to have only a single pane, we resize the
269 // second to 5 pixels (which makes it too small to display anything)
270 Widget form1, form2;
271 Arg args[16];
272 int j;
273 Dimension ew_height, tmp;
274 Widget shell = shells[EngOutDlg];
275
276 form1 = XtNameToWidget(shell, "*paneA");
277 form2 = XtNameToWidget(shell, "*paneB");
278
279 j = 0;
280 XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++;
281 XtGetValues(form1, args, j);
282 j = 0;
283 XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++;
284 XtGetValues(form2, args, j);
285 ew_height += tmp; // total height
286
287 if(mode==0) {
288 j = 0;
289 XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++;
290 XtSetValues(form2, args, j);
291 j = 0;
292 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++;
293 XtSetValues(form1, args, j);
294 } else {
295 j = 0;
296 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
297 XtSetValues(form1, args, j);
298 j = 0;
299 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
300 XtSetValues(form2, args, j);
301 }
302 }
303