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