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 (engineOutputX == -1) {
374 engineOutputH = bw_height/2;
375 engineOutputW = bw_width-16;
377 XSync(xDisplay, False);
379 /* This code seems to tickle an X bug if it is executed too soon
380 after xboard starts up. The coordinates get transformed as if
381 the main window was positioned at (0, 0).
383 XtTranslateCoords(shellWidget,
384 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
385 &engineOutputX, &engineOutputY);
387 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
388 RootWindowOfScreen(XtScreen(shellWidget)),
389 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
394 if (engineOutputY < 0) engineOutputY = 0; /*avoid positioning top offscreen*/
397 XtSetArg(args[j], XtNheight, engineOutputH); j++;
398 XtSetArg(args[j], XtNwidth, engineOutputW); j++;
399 XtSetArg(args[j], XtNx, engineOutputX); j++;
400 XtSetArg(args[j], XtNy, engineOutputY); j++;
401 XtSetValues(shell, args, j);
402 // XtSetKeyboardFocus(shell, edit);
407 void ResizeWindowControls(mode)
413 Dimension ew_height, tmp;
414 Widget shell = engineOutputShell;
416 form1 = XtNameToWidget(shell, "*form");
417 form2 = XtNameToWidget(shell, "*form2");
420 XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++;
421 XtGetValues(form1, args, j);
423 XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++;
424 XtGetValues(form2, args, j);
425 ew_height += tmp; // total height
429 XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++;
430 XtSetValues(form2, args, j);
432 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++;
433 XtSetValues(form1, args, j);
436 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
437 XtSetValues(form1, args, j);
439 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
440 XtSetValues(form2, args, j);
450 static int needInit = TRUE;
451 static char *title = _("Engine output"), *text = _("This feature is experimental");
453 if (engineOutputShell == NULL) {
455 EngineOutputCreate(title, text);
456 XtRealizeWidget(engineOutputShell);
457 CatchDeleteWindow(engineOutputShell, "EngineOutputPopDown");
459 InitializeEngineOutput();
462 SetEngineColorIcon( 0 );
463 SetEngineColorIcon( 1 );
464 SetEngineState( 0, STATE_IDLE, "" );
465 SetEngineState( 1, STATE_IDLE, "" );
467 edit = XtNameToWidget(engineOutputShell, "*form.text");
469 XtSetArg(args[j], XtNstring, text); j++;
470 XtSetValues(edit, args, j);
472 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
473 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
474 XtSetValues(engineOutputShell, args, j);
477 XtPopup(engineOutputShell, XtGrabNone);
478 XSync(xDisplay, False);
481 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
482 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
485 engineOutputDialogUp = True;
486 ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
489 void EngineOutputPopDown()
494 if (!engineOutputDialogUp) return;
497 XtSetArg(args[j], XtNx, &engineOutputX); j++;
498 XtSetArg(args[j], XtNy, &engineOutputY); j++;
499 XtSetArg(args[j], XtNwidth, &engineOutputW); j++;
500 XtSetArg(args[j], XtNheight, &engineOutputH); j++;
501 XtGetValues(engineOutputShell, args, j);
502 XtPopdown(engineOutputShell);
503 XSync(xDisplay, False);
505 XtSetArg(args[j], XtNleftBitmap, None); j++;
506 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
509 engineOutputDialogUp = False;
510 ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
513 int EngineOutputIsUp()
515 return engineOutputDialogUp;
518 int EngineOutputDialogExists()
520 return engineOutputShell != NULL;
524 EngineOutputProc(w, event, prms, nprms)
530 if (engineOutputDialogUp) {
531 EngineOutputPopDown();