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