Cleanse back-end code of all references to X11 types
[xboard.git] / xaw / xevalgraph.c
1 /*
2  * Evaluation graph
3  *
4  * Author: Alessandro Scotti (Dec 2005)
5  * Translated to X by H.G.Muller (Nov 2009)
6  *
7  * Copyright 2005 Alessandro Scotti
8  *
9  * Enhancements Copyright 2009, 2010, 2011, 2012 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
70 #include <cairo/cairo.h>
71 #include <cairo/cairo-xlib.h>
72
73 #include "common.h"
74 #include "frontend.h"
75 #include "backend.h"
76 #include "dialogs.h"
77 #include "menus.h"
78 #include "xboard.h"
79 #include "evalgraph.h"
80 #include "xevalgraph.h"
81 #include "draw.h"
82 #include "gettext.h"
83
84 #ifdef ENABLE_NLS
85 # define  _(s) gettext (s)
86 # define N_(s) gettext_noop (s)
87 #else
88 # define  _(s) (s)
89 # define N_(s)  s
90 #endif
91
92 #include <X11/xpm.h>
93
94 #ifdef SNAP
95 #include "wsnap.h"
96 #endif
97
98 #define _LL_ 100
99
100 Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle
101 Widget outputField[2][7]; // [HGM] front-end array to translate output field to window handle
102 static char *title = N_("Evaluation graph");
103
104 //extern WindowPlacement wpEvalGraph;
105
106 Position evalGraphX = -1, evalGraphY = -1;
107 Dimension evalGraphW, evalGraphH;
108
109 /* Module variables */
110
111 char *crWhite = "#FFFFB0";
112 char *crBlack = "#AD5D3D";
113 Option *disp;
114
115 static Option *EvalCallback P((int button, int x, int y));
116
117 static void
118 ChoosePen(cairo_t *cr, int i)
119 {
120   switch(i) {
121     case PEN_BLACK:
122       SetPen(cr, 1.0, "#000000", 0);
123       break;
124     case PEN_DOTTED:
125       SetPen(cr, 1.0, "#A0A0A0", 1);
126       break;
127     case PEN_BLUEDOTTED:
128       SetPen(cr, 1.0, "#0000FF", 1);
129       break;
130     case PEN_BOLDWHITE:
131       SetPen(cr, 3.0, crWhite, 0);
132       break;
133     case PEN_BOLDBLACK:
134       SetPen(cr, 3.0, crBlack, 0);
135       break;
136     case PEN_BACKGD:
137       SetPen(cr, 3.0, "#E0E0F0", 0);
138       break;
139   }
140 }
141
142 // [HGM] front-end, added as wrapper to avoid use of LineTo and MoveToEx in other routines (so they can be back-end)
143 void
144 DrawSegment (int x, int y, int *lastX, int *lastY, enum PEN penType)
145 {
146   static int curX, curY;
147
148   if(penType != PEN_NONE) {
149     cairo_t *cr = cairo_create(DRAWABLE(disp));
150     cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
151     cairo_move_to (cr, curX, curY);
152     cairo_line_to (cr, x,y);
153     ChoosePen(cr, penType);
154     cairo_stroke (cr);
155     cairo_destroy (cr);
156   }
157
158   if(lastX != NULL) { *lastX = curX; *lastY = curY; }
159   curX = x; curY = y;
160 }
161
162 // front-end wrapper for drawing functions to do rectangles
163 void
164 DrawRectangle (int left, int top, int right, int bottom, int side, int style)
165 {
166   cairo_t *cr;
167
168   cr = cairo_create (DRAWABLE(disp));
169   cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
170   cairo_rectangle (cr, left, top, right-left, bottom-top);
171   switch(side)
172     {
173     case 0: ChoosePen(cr, PEN_BOLDWHITE); break;
174     case 1: ChoosePen(cr, PEN_BOLDBLACK); break;
175     case 2: ChoosePen(cr, PEN_BACKGD); break;
176     }
177   cairo_fill (cr);
178
179   if(style != FILLED)
180     {
181       cairo_rectangle (cr, left, top, right-left-1, bottom-top-1);
182       ChoosePen(cr, PEN_BLACK);
183       cairo_stroke (cr);
184     }
185
186   cairo_destroy(cr);
187 }
188
189 // front-end wrapper for putting text in graph
190 void
191 DrawEvalText (char *buf, int cbBuf, int y)
192 {
193     // the magic constants 8 and 5 should really be derived from the font size somehow
194   cairo_text_extents_t extents;
195   cairo_t *cr = cairo_create(DRAWABLE(disp));
196
197   /* GTK-TODO this has to go into the font-selection */
198   cairo_select_font_face (cr, "Sans",
199                           CAIRO_FONT_SLANT_NORMAL,
200                           CAIRO_FONT_WEIGHT_NORMAL);
201   cairo_set_font_size (cr, 12.0);
202
203
204   cairo_text_extents (cr, buf, &extents);
205
206   cairo_move_to (cr, MarginX - 2 - 8*cbBuf, y+5);
207   cairo_text_path (cr, buf);
208   cairo_set_source_rgb (cr, 0.0, 0.0, 0);
209   cairo_fill_preserve (cr);
210   cairo_set_source_rgb (cr, 0, 1.0, 0);
211   cairo_set_line_width (cr, 0.1);
212   cairo_stroke (cr);
213
214   /* free memory */
215   cairo_destroy (cr);
216 }
217
218 static int initDone = FALSE;
219
220 static void
221 InitializeEvalGraph (Option *opt, int w, int h)
222 {
223   if(w == 0) {
224     Arg args[10];
225     XtSetArg(args[0], XtNwidth, &evalGraphW);
226     XtSetArg(args[1], XtNheight, &evalGraphH);
227     XtGetValues(opt->handle, args, 2);
228     nWidthPB = evalGraphW; nHeightPB = evalGraphH;
229   } else nWidthPB = w, nHeightPB = h;
230
231   initDone = TRUE;
232 }
233
234 // The following stuff is really back-end (but too little to bother with a separate file)
235
236 static void
237 EvalClick (int x, int y)
238 {
239     int index = GetMoveIndexFromPoint( x, y );
240
241     if( index >= 0 && index < currLast ) ToNrEvent( index + 1 );
242 }
243
244 static Option graphOptions[] = {
245 { 150, 0x9C, 300, NULL, (void*) &EvalCallback, NULL, NULL, Graph , "" },
246 { 0, 2, 0, NULL, NULL, "", NULL, EndMark , "" }
247 };
248
249 static void
250 DisplayEvalGraph ()
251 {   // back-end painting; calls back front-end primitives for lines, rectangles and text
252     char *t = MakeEvalTitle(_(title));
253     nWidthPB = disp->max; nHeightPB = disp->value;
254     if(t != title && nWidthPB < 340) t = MakeEvalTitle(nWidthPB < 240 ? "" : _("Eval"));
255     PaintEvalGraph();
256     GraphExpose(graphOptions, 0, 0, nWidthPB, nHeightPB);
257     SetDialogTitle(EvalGraphDlg, t);
258 }
259
260 static Option *
261 EvalCallback (int button, int x, int y)
262 {
263     if(!initDone) return NULL;
264
265     switch(button) {
266         case 10: // expose event
267             /* Create or recreate paint box if needed */
268             if(x != nWidthPB || y != nHeightPB) {
269                 InitializeEvalGraph(&graphOptions[0], x, y);
270             }
271             nWidthPB = x;
272             nHeightPB = y;
273             DisplayEvalGraph();
274             break;
275         case 1: EvalClick(x, y); // left button
276         default: break; // other buttons ignored
277     }
278     return NULL; // no context menu!
279 }
280
281 void
282 EvalGraphPopUp ()
283 {
284     if (GenericPopUp(graphOptions, _(title), EvalGraphDlg, BoardWindow, NONMODAL, 1)) {
285         InitializeEvalGraph(&graphOptions[0], 0, 0); // first time: add callbacks and initialize pens
286         disp = graphOptions;
287     } else {
288         SetDialogTitle(EvalGraphDlg, _(title));
289         SetIconName(EvalGraphDlg, _(title));
290     }
291
292     MarkMenu("View.EvaluationGraph", EvalGraphDlg);
293
294 //    ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
295 }
296
297 void
298 EvalGraphPopDown ()
299 {
300     PopDown(EvalGraphDlg);
301
302 //    ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
303 }
304
305 Boolean
306 EvalGraphIsUp ()
307 {
308     return shellUp[EvalGraphDlg];
309 }
310
311 int
312 EvalGraphDialogExists ()
313 {
314     return DialogExists(EvalGraphDlg);
315 }
316
317 void
318 EvalGraphProc ()
319 {
320   if (!PopDown(EvalGraphDlg)) EvalGraphPopUp();
321 }
322
323 // This function is the interface to the back-end.
324
325 void
326 EvalGraphSet (int first, int last, int current, ChessProgramStats_Move * pvInfo)
327 {
328     /* [AS] Danger! For now we rely on the pvInfo parameter being a static variable! */
329
330     currFirst = first;
331     currLast = last;
332     currCurrent = current;
333     currPvInfo = pvInfo;
334
335     if( DialogExists(EvalGraphDlg) ) {
336         DisplayEvalGraph();
337     }
338 }
339