4 * Author: Alessandro Scotti (Dec 2005)
6 * Copyright 2005 Alessandro Scotti
8 * Enhancements Copyright 2009 Free Software Foundation, Inc.
10 * ------------------------------------------------------------------------
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.
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.
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/.
25 * ------------------------------------------------------------------------
26 ** See the file ChangeLog for a revision history. */
33 #include <sys/types.h>
38 #else /* not STDC_HEADERS */
39 extern char *getenv();
42 # else /* not HAVE_STRING_H */
44 # endif /* not HAVE_STRING_H */
45 #endif /* not STDC_HEADERS */
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>
73 #include "engineoutput.h"
77 # define _(s) gettext (s)
78 # define N_(s) gettext_noop (s)
86 // [HGM] pixmaps of some ICONS used in the engine-outut window
87 #include "pixmaps/WHITE_14.xpm"
88 #include "pixmaps/BLACK_14.xpm"
89 #include "pixmaps/CLEAR_14.xpm"
90 #include "pixmaps/UNKNOWN_14.xpm"
91 #include "pixmaps/THINKING_14.xpm"
92 #include "pixmaps/PONDER_14.xpm"
93 #include "pixmaps/ANALYZING_14.xpm"
101 // imports from xboard.c
102 extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;
103 extern Display *xDisplay;
104 extern Window xBoardWindow;
105 extern int squareSize;
106 extern Pixmap xMarkPixmap, wIconPixmap, bIconPixmap;
107 extern char *layoutName;
109 Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle
110 Widget outputField[2][7]; // [HGM] front-end array to translate output field to window handle
112 void EngineOutputPopDown();
113 void engineOutputPopUp();
114 int EngineOutputIsUp();
115 void SetEngineColorIcon( int which );
117 /* Imports from backend.c */
118 char * SavePart(char *str);
119 extern int opponentKibitzes;
121 /* Imports from xboard.c */
122 extern Arg layoutArgs[2], formArgs[2], messageArgs[4];
124 //extern WindowPlacement wpEngineOutput;
126 Position engineOutputX = -1, engineOutputY = -1;
127 Dimension engineOutputW, engineOutputH;
128 Widget engineOutputShell;
129 static int engineOutputDialogUp;
131 /* Module variables */
147 //static void UpdateControls( EngineOutputData * ed );
149 void ReadIcon(char *pixData[], int iconNr)
153 if ((r=XpmCreatePixmapFromData(xDisplay, XtWindow(outputField[0][nColorIcon]),
156 NULL, NULL /*&attr*/)) != 0) {
157 fprintf(stderr, _("Error %d loading icon image\n"), r);
162 static void InitializeEngineOutput()
165 ReadIcon(WHITE_14, nColorWhite);
166 ReadIcon(BLACK_14, nColorBlack);
167 ReadIcon(UNKNOWN_14, nColorUnknown);
169 ReadIcon(CLEAR_14, nClear);
170 ReadIcon(PONDER_14, nPondering);
171 ReadIcon(THINK_14, nThinking);
172 ReadIcon(ANALYZE_14, nAnalyzing);
175 void DoSetWindowText(int which, int field, char *s_label)
179 XtSetArg(arg, XtNlabel, (XtArgVal) s_label);
180 XtSetValues(outputField[which][field], &arg, 1);
183 void InsertIntoMemo( int which, char * text, int where )
185 Arg arg; XawTextBlock t; Widget edit;
187 t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit;
188 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
189 XawTextReplace(edit, where, where, &t);
190 // XtSetArg(arg, XtNstring, (XtArgVal) text);
191 // XtSetValues(outputField[which][nMemo], &arg, 1);
194 void SetIcon( int which, int field, int nIcon )
199 XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]);
200 XtSetValues(outputField[which][field], &arg, 1);
204 void DoClearMemo(int which)
210 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
211 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
212 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
215 // The following routines are mutated clones of the commentPopUp routines
217 void PositionControlSet(which, form, bw_width)
223 Widget edit, NameWidget, ColorWidget, ModeWidget, MoveWidget, NodesWidget;
226 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
227 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
228 XtSetArg(args[j], XtNtop, XtChainTop); j++;
229 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
230 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
231 XtSetArg(args[j], XtNright, XtChainLeft); j++;
232 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
233 XtSetArg(args[j], XtNwidth, (XtArgVal) 17); j++;
234 outputField[which][nColorIcon] = ColorWidget =
235 XtCreateManagedWidget("Color", labelWidgetClass,
239 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
240 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
241 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ColorWidget); j++;
242 XtSetArg(args[j], XtNtop, XtChainTop); j++;
243 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
244 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
245 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
246 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 57); j++;
247 outputField[which][nLabel] = NameWidget =
248 XtCreateManagedWidget("Engine", labelWidgetClass,
252 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
253 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
254 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) NameWidget); j++;
255 XtSetArg(args[j], XtNtop, XtChainTop); j++;
256 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
257 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
258 XtSetArg(args[j], XtNwidth, (XtArgVal) 20); j++;
259 outputField[which][nStateIcon] = ModeWidget =
260 XtCreateManagedWidget("Mode", labelWidgetClass,
264 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
265 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
266 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
267 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ModeWidget); j++;
268 XtSetArg(args[j], XtNtop, XtChainTop); j++;
269 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
270 XtSetArg(args[j], XtNright, XtChainRight); j++;
271 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
272 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 102); j++;
273 outputField[which][nStateData] = MoveWidget =
274 XtCreateManagedWidget("Move", labelWidgetClass,
278 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
279 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyRight); j++;
280 XtSetArg(args[j], XtNlabel, (XtArgVal) _("NPS")); j++;
281 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) MoveWidget); j++;
282 XtSetArg(args[j], XtNtop, XtChainTop); j++;
283 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
284 XtSetArg(args[j], XtNleft, XtChainRight); j++;
285 XtSetArg(args[j], XtNright, XtChainRight); j++;
286 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
287 XtSetArg(args[j], XtNwidth, (XtArgVal) 100); j++;
288 outputField[which][nLabelNPS] = NodesWidget =
289 XtCreateManagedWidget("Nodes", labelWidgetClass,
292 // create "text" within "form"
295 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
296 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
298 XtSetArg(args[j], XtNstring, ""); j++;
299 XtSetArg(args[j], XtNdisplayCaret, False); j++;
300 XtSetArg(args[j], XtNtop, XtChainTop); j++;
301 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
302 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
303 XtSetArg(args[j], XtNright, XtChainRight); j++;
304 XtSetArg(args[j], XtNresizable, True); j++;
305 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
306 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
307 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
308 XtSetArg(args[j], XtNscrollHorizontal, XawtextScrollWhenNeeded); j++;
309 // XtSetArg(args[j], XtNautoFill, True); j++;
310 // XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
311 outputField[which][nMemo] = edit =
312 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
315 XtSetArg(args[j], XtNfromVert, ColorWidget); j++;
316 // XtSetArg(args[j], XtNresizable, (XtArgVal) True); j++;
317 XtSetValues(edit, args, j);
320 Widget EngineOutputCreate(name, text)
324 Widget shell, layout, form, form2, edit;
325 Dimension bw_width, bw_height;
330 XtSetArg(args[j], XtNwidth, &bw_width); j++;
331 XtSetArg(args[j], XtNheight, &bw_height); j++;
332 XtGetValues(boardWidget, args, j);
334 // define form within layout within shell.
336 XtSetArg(args[j], XtNresizable, True); j++;
339 XtCreatePopupShell(name, topLevelShellWidgetClass,
341 XtCreatePopupShell(name, transientShellWidgetClass,
343 shellWidget, args, j);
345 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
346 layoutArgs, XtNumber(layoutArgs));
347 // divide window vertically into two equal parts, by creating two forms
349 XtCreateManagedWidget("form", formWidgetClass, layout,
350 formArgs, XtNumber(formArgs));
352 XtCreateManagedWidget("form2", formWidgetClass, layout,
353 formArgs, XtNumber(formArgs));
355 XtSetArg(args[j], XtNfromVert, (XtArgVal) form); j++;
356 XtSetValues(form2, args, j);
357 // make sure width is known in advance, for better placement of child widgets
359 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width-16); j++;
360 XtSetArg(args[j], XtNheight, (XtArgVal) bw_height/2); j++;
361 XtSetValues(shell, args, j);
363 // fill up both forms with control elements
364 PositionControlSet(0, form, bw_width);
365 PositionControlSet(1, form2, bw_width);
367 XtRealizeWidget(shell);
369 if(wpEngineOutput.width > 0) {
370 engineOutputW = wpEngineOutput.width;
371 engineOutputH = wpEngineOutput.height;
372 engineOutputX = wpEngineOutput.x;
373 engineOutputY = wpEngineOutput.y;
376 if (engineOutputX == -1) {
381 engineOutputH = bw_height/2;
382 engineOutputW = bw_width-16;
384 XSync(xDisplay, False);
386 /* This code seems to tickle an X bug if it is executed too soon
387 after xboard starts up. The coordinates get transformed as if
388 the main window was positioned at (0, 0).
390 XtTranslateCoords(shellWidget,
391 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
392 &engineOutputX, &engineOutputY);
394 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
395 RootWindowOfScreen(XtScreen(shellWidget)),
396 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
401 if (engineOutputY < 0) engineOutputY = 0; /*avoid positioning top offscreen*/
404 XtSetArg(args[j], XtNheight, engineOutputH); j++;
405 XtSetArg(args[j], XtNwidth, engineOutputW); j++;
406 XtSetArg(args[j], XtNx, engineOutputX); j++;
407 XtSetArg(args[j], XtNy, engineOutputY); j++;
408 XtSetValues(shell, args, j);
409 // XtSetKeyboardFocus(shell, edit);
414 void ResizeWindowControls(mode)
420 Dimension ew_height, tmp;
421 Widget shell = engineOutputShell;
423 form1 = XtNameToWidget(shell, "*form");
424 form2 = XtNameToWidget(shell, "*form2");
427 XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++;
428 XtGetValues(form1, args, j);
430 XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++;
431 XtGetValues(form2, args, j);
432 ew_height += tmp; // total height
436 XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++;
437 XtSetValues(form2, args, j);
439 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++;
440 XtSetValues(form1, args, j);
443 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
444 XtSetValues(form1, args, j);
446 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
447 XtSetValues(form2, args, j);
457 static int needInit = TRUE;
458 static char *title = _("Engine output"), *text = _("This feature is experimental");
460 if (engineOutputShell == NULL) {
462 EngineOutputCreate(title, text);
463 XtRealizeWidget(engineOutputShell);
464 CatchDeleteWindow(engineOutputShell, "EngineOutputPopDown");
466 InitializeEngineOutput();
469 SetEngineColorIcon( 0 );
470 SetEngineColorIcon( 1 );
471 SetEngineState( 0, STATE_IDLE, "" );
472 SetEngineState( 1, STATE_IDLE, "" );
474 edit = XtNameToWidget(engineOutputShell, "*form.text");
476 XtSetArg(args[j], XtNstring, text); j++;
477 XtSetValues(edit, args, j);
479 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
480 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
481 XtSetValues(engineOutputShell, args, j);
484 XtPopup(engineOutputShell, XtGrabNone);
485 XSync(xDisplay, False);
488 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
489 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
492 engineOutputDialogUp = True;
493 ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
496 void EngineOutputPopDown()
501 if (!engineOutputDialogUp) return;
504 XtSetArg(args[j], XtNx, &engineOutputX); j++;
505 XtSetArg(args[j], XtNy, &engineOutputY); j++;
506 XtSetArg(args[j], XtNwidth, &engineOutputW); j++;
507 XtSetArg(args[j], XtNheight, &engineOutputH); j++;
508 XtGetValues(engineOutputShell, args, j);
509 wpEngineOutput.x = engineOutputX - 4;
510 wpEngineOutput.y = engineOutputY - 23;
511 wpEngineOutput.width = engineOutputW;
512 wpEngineOutput.height = engineOutputH;
513 XtPopdown(engineOutputShell);
514 XSync(xDisplay, False);
516 XtSetArg(args[j], XtNleftBitmap, None); j++;
517 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
520 engineOutputDialogUp = False;
521 ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
524 int EngineOutputIsUp()
526 return engineOutputDialogUp;
529 int EngineOutputDialogExists()
531 return engineOutputShell != NULL;
535 EngineOutputProc(w, event, prms, nprms)
541 if (engineOutputDialogUp) {
542 EngineOutputPopDown();