Make XBoard xpm-free
[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 #include <X11/xpm.h>
88
89 // [HGM] bitmaps of some ICONS used in the engine-outut window
90
91 static unsigned char CLEAR_14[28];
92
93 static unsigned char WHITE_14[] = {
94 0xe0, 0x01, 0x18, 0x06, 0x04, 0x08, 0x02, 0x10, 0x02, 0x10, 0x01, 0x20, 0x01, 0x20,
95 0x01, 0x20, 0x01, 0x20, 0x02, 0x10, 0x02, 0x10, 0x04, 0x08, 0x18, 0x06, 0xe0, 0x01
96 };
97
98 static unsigned char BLACK_14[] = {
99 0xe0, 0x01, 0xf8, 0x07, 0xfc, 0x0f, 0xfe, 0x1f, 0xfe, 0x1f, 0xff, 0x3f, 0xff, 0x3f,
100 0xff, 0x3f, 0xff, 0x3f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xe0, 0x01
101 };
102
103 static unsigned char ANALYZE_14[] = {
104 0x80, 0x03, 0x60, 0x0c, 0x10, 0x10, 0x90, 0x10, 0xc8, 0x20, 0x08, 0x20, 0x08, 0x20,
105 0x10, 0x10, 0x10, 0x10, 0x68, 0x0c, 0x94, 0x03, 0x0a, 0x00, 0x07, 0x00, 0x00, 0x00
106 };
107
108 static unsigned char THINK_14[] = {
109 0xe0, 0x00, 0x18, 0x03, 0x44, 0x04, 0x42, 0x08, 0x42, 0x08, 0x41, 0x10, 0xe1, 0x13,
110 0x41, 0x10, 0x02, 0x08, 0x02, 0x08, 0x04, 0x04, 0x18, 0x03, 0xe0, 0x00, 0x00, 0x00
111 };
112
113 static unsigned char PONDER_14[] = {
114 0x30, 0x03, 0x8c, 0x0c, 0x02, 0x10, 0x01, 0x08, 0x01, 0x10, 0x06, 0x20, 0x04, 0x20,
115 0x02, 0x10, 0x04, 0x0c, 0xc8, 0x04, 0x34, 0x03, 0x0e, 0x00, 0x01, 0x00, 0x00, 0x00
116 };
117
118 static unsigned char UNKNOWN_14[] = {
119 0xe0, 0x01, 0x58, 0x07, 0xac, 0x0a, 0x56, 0x15, 0xaa, 0x1a, 0x55, 0x35, 0xab, 0x2a,
120 0x55, 0x35, 0xab, 0x2a, 0x56, 0x15, 0xaa, 0x1a, 0x54, 0x0d, 0xb8, 0x06, 0xe0, 0x01
121 };
122
123
124
125 /* Module variables */
126 static int currentPV;
127 static Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle
128 static Widget memoWidget;
129
130
131 static void
132 ReadIcon (unsigned char pixData[], int iconNr, Widget w)
133 {
134     icons[iconNr] = XCreateBitmapFromData(xDisplay, XtWindow(w), (char*) pixData, 14, 14);
135 }
136
137 void
138 InitEngineOutput (Option *opt, Option *memo2)
139 {       // front-end, because it must have access to the pixmaps
140         Widget w = opt->handle;
141         memoWidget = memo2->handle;
142
143         ReadIcon(WHITE_14,   nColorWhite, w);
144         ReadIcon(BLACK_14,   nColorBlack, w);
145         ReadIcon(UNKNOWN_14, nColorUnknown, w);
146
147         ReadIcon(CLEAR_14,   nClear, w);
148         ReadIcon(PONDER_14,  nPondering, w);
149         ReadIcon(THINK_14,   nThinking, w);
150         ReadIcon(ANALYZE_14, nAnalyzing, w);
151 }
152
153 void
154 DrawWidgetIcon (Option *opt, int nIcon)
155 {   // as we are already in X front-end, so do X-stuff here
156     Arg arg;
157     XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]);
158     XtSetValues(opt->handle, &arg, 1);
159 }
160
161 void
162 InsertIntoMemo (int which, char * text, int where)
163 {
164         XawTextBlock t;
165         Widget edit;
166
167         /* the backend adds \r\n, which is needed for winboard,
168          * for xboard we delete them again over here */
169         if(t.ptr = strchr(text, '\r')) *t.ptr = ' ';
170
171         t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit;
172         edit = XtNameToWidget(shells[EngOutDlg], which ? "*paneB.text" : "*paneA.text");
173         XawTextReplace(edit, where, where, &t);
174         if(where < highTextStart[which]) { // [HGM] multiPVdisplay: move highlighting
175             int len = strlen(text);
176             highTextStart[which] += len; highTextEnd[which] += len;
177             XawTextSetSelection( edit, highTextStart[which], highTextEnd[which] );
178         }
179 }
180
181 //--------------------------------- PV walking ---------------------------------------
182
183 char memoTranslations[] =
184 ":Ctrl<Key>c: CopyMemoProc() \n \
185 <Btn3Motion>: HandlePV() \n \
186 Shift<Btn3Down>: select-start() extend-end(PRIMARY) SelectPV(1) \n \
187 Any<Btn3Down>: select-start() extend-end(PRIMARY) SelectPV(0) \n \
188 <Btn3Up>: StopPV() \n";
189
190 void
191 SelectPV (Widget w, XEvent * event, String * params, Cardinal * nParams)
192 {       // [HGM] pv: translate click to PV line, and load it for display
193         String val;
194         int start, end;
195         XawTextPosition index, dummy;
196         int x, y;
197         Arg arg;
198
199         x = event->xmotion.x; y = event->xmotion.y;
200         currentPV = (w != memoWidget);
201         XawTextGetSelectionPos(w, &index, &dummy);
202         XtSetArg(arg, XtNstring, &val);
203         XtGetValues(w, &arg, 1);
204         shiftKey = strcmp(params[0], "0");
205         if(LoadMultiPV(x, y, val, index, &start, &end, currentPV)) {
206             XawTextSetSelection( w, start, end );
207             highTextStart[currentPV] = start; highTextEnd[currentPV] = end;
208         }
209 }
210
211 void
212 StopPV (Widget w, XEvent * event, String * params, Cardinal * nParams)
213 {       // [HGM] pv: on right-button release, stop displaying PV
214         XawTextUnsetSelection( w );
215         highTextStart[currentPV] = highTextEnd[currentPV] = 0;
216         UnLoadPV();
217         XtCallActionProc(w, "beginning-of-file", event, NULL, 0);
218 }
219
220 //------------------------- Ctrl-C copying of memo texts ---------------------------
221
222 // Awfull code: first read our own primary selection into selected_fen_position,
223 //              and then transfer ownership of this to the clipboard, so that the
224 //              copy-position callback can fetch it there when somebody pastes it
225 // Worst of all is that I only added it because I did not know how to copy primary:
226 // my laptop has no middle button. Ctrl-C might not be needed at all... [HGM]
227
228 // cloned from CopyPositionProc. Abuse selected_fen_position to hold selection
229
230 Boolean SendPositionSelection(Widget w, Atom *selection, Atom *target,
231                  Atom *type_return, XtPointer *value_return,
232                  unsigned long *length_return, int *format_return); // from xboard.c
233
234 static void
235 MemoCB (Widget w, XtPointer client_data, Atom *selection,
236         Atom *type, XtPointer value, unsigned long *len, int *format)
237 {
238   if (value==NULL || *len==0) return; /* nothing had been selected to copy */
239   selected_fen_position = value;
240   selected_fen_position[*len]='\0'; /* normally this string is terminated, but be safe */
241     XtOwnSelection(menuBarWidget, XA_CLIPBOARD(xDisplay),
242                    CurrentTime,
243                    SendPositionSelection,
244                    NULL/* lose_ownership_proc */ ,
245                    NULL/* transfer_done_proc */);
246 }
247
248 void
249 CopyMemoProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
250 {
251     if(appData.pasteSelection) return;
252     if (selected_fen_position) free(selected_fen_position);
253     XtGetSelectionValue(menuBarWidget,
254       XA_PRIMARY, XA_STRING,
255       /* (XtSelectionCallbackProc) */ MemoCB,
256       NULL, /* client_data passed to PastePositionCB */
257
258       /* better to use the time field from the event that triggered the
259        * call to this function, but that isn't trivial to get
260        */
261       CurrentTime
262     );
263 }
264
265 //------------------------------- pane switching -----------------------------------
266
267 void
268 ResizeWindowControls (int mode)
269 {   // another hideous kludge: to have only a single pane, we resize the
270     // second to 5 pixels (which makes it too small to display anything)
271     Widget form1, form2;
272     Arg args[16];
273     int j;
274     Dimension ew_height, tmp;
275     Widget shell = shells[EngOutDlg];
276
277     form1 = XtNameToWidget(shell, "*paneA");
278     form2 = XtNameToWidget(shell, "*paneB");
279
280     j = 0;
281     XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++;
282     XtGetValues(form1, args, j);
283     j = 0;
284     XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++;
285     XtGetValues(form2, args, j);
286     ew_height += tmp; // total height
287
288     if(mode==0) {
289         j = 0;
290         XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++;
291         XtSetValues(form2, args, j);
292         j = 0;
293         XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++;
294         XtSetValues(form1, args, j);
295     } else {
296         j = 0;
297         XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
298         XtSetValues(form1, args, j);
299         j = 0;
300         XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
301         XtSetValues(form2, args, j);
302     }
303 }