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 extern int opponentKibitzes;
120 /* Imports from xboard.c */
121 extern Arg layoutArgs[2], formArgs[2], messageArgs[4];
123 //extern WindowPlacement wpEngineOutput;
125 Position engineOutputX = -1, engineOutputY = -1;
126 Dimension engineOutputW, engineOutputH;
127 Widget engineOutputShell;
128 static int engineOutputDialogUp;
130 /* Module variables */
146 //static void UpdateControls( EngineOutputData * ed );
148 void ReadIcon(char *pixData[], int iconNr)
152 if ((r=XpmCreatePixmapFromData(xDisplay, XtWindow(outputField[0][nColorIcon]),
155 NULL, NULL /*&attr*/)) != 0) {
156 fprintf(stderr, _("Error %d loading icon image\n"), r);
161 static void InitializeEngineOutput()
164 ReadIcon(WHITE_14, nColorWhite);
165 ReadIcon(BLACK_14, nColorBlack);
166 ReadIcon(UNKNOWN_14, nColorUnknown);
168 ReadIcon(CLEAR_14, nClear);
169 ReadIcon(PONDER_14, nPondering);
170 ReadIcon(THINK_14, nThinking);
171 ReadIcon(ANALYZE_14, nAnalyzing);
174 void DoSetWindowText(int which, int field, char *s_label)
178 XtSetArg(arg, XtNlabel, (XtArgVal) s_label);
179 XtSetValues(outputField[which][field], &arg, 1);
182 void InsertIntoMemo( int which, char * text, int where )
184 Arg arg; XawTextBlock t; Widget edit;
186 /* the backend adds \r\n, which is needed for winboard,
187 * for xboard we delete them again over here */
188 if(t.ptr = strchr(text, '\r')) *t.ptr = ' ';
190 t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit;
191 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
192 XawTextReplace(edit, where, where, &t);
193 // XtSetArg(arg, XtNstring, (XtArgVal) text);
194 // XtSetValues(outputField[which][nMemo], &arg, 1);
197 void SetIcon( int which, int field, int nIcon )
202 XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]);
203 XtSetValues(outputField[which][field], &arg, 1);
207 void DoClearMemo(int which)
213 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
214 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
215 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
218 // The following routines are mutated clones of the commentPopUp routines
220 void PositionControlSet(which, form, bw_width)
226 Widget edit, NameWidget, ColorWidget, ModeWidget, MoveWidget, NodesWidget;
229 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
230 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
231 XtSetArg(args[j], XtNtop, XtChainTop); j++;
232 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
233 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
234 XtSetArg(args[j], XtNright, XtChainLeft); j++;
235 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
236 XtSetArg(args[j], XtNwidth, (XtArgVal) 17); j++;
237 outputField[which][nColorIcon] = ColorWidget =
238 XtCreateManagedWidget("Color", labelWidgetClass,
242 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
243 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
244 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ColorWidget); j++;
245 XtSetArg(args[j], XtNtop, XtChainTop); j++;
246 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
247 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
248 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
249 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 57); j++;
250 outputField[which][nLabel] = NameWidget =
251 XtCreateManagedWidget("Engine", labelWidgetClass,
255 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
256 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
257 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) NameWidget); j++;
258 XtSetArg(args[j], XtNtop, XtChainTop); j++;
259 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
260 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
261 XtSetArg(args[j], XtNwidth, (XtArgVal) 20); j++;
262 outputField[which][nStateIcon] = ModeWidget =
263 XtCreateManagedWidget("Mode", labelWidgetClass,
267 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
268 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
269 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
270 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ModeWidget); j++;
271 XtSetArg(args[j], XtNtop, XtChainTop); j++;
272 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
273 XtSetArg(args[j], XtNright, XtChainRight); j++;
274 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
275 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 102); j++;
276 outputField[which][nStateData] = MoveWidget =
277 XtCreateManagedWidget("Move", labelWidgetClass,
281 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
282 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyRight); j++;
283 XtSetArg(args[j], XtNlabel, (XtArgVal) _("NPS")); j++;
284 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) MoveWidget); j++;
285 XtSetArg(args[j], XtNtop, XtChainTop); j++;
286 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
287 XtSetArg(args[j], XtNleft, XtChainRight); j++;
288 XtSetArg(args[j], XtNright, XtChainRight); j++;
289 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
290 XtSetArg(args[j], XtNwidth, (XtArgVal) 100); j++;
291 outputField[which][nLabelNPS] = NodesWidget =
292 XtCreateManagedWidget("Nodes", labelWidgetClass,
295 // create "text" within "form"
298 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
299 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
301 XtSetArg(args[j], XtNstring, ""); j++;
302 XtSetArg(args[j], XtNdisplayCaret, False); j++;
303 XtSetArg(args[j], XtNtop, XtChainTop); j++;
304 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
305 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
306 XtSetArg(args[j], XtNright, XtChainRight); j++;
307 XtSetArg(args[j], XtNresizable, True); j++;
308 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
309 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
310 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
311 XtSetArg(args[j], XtNscrollHorizontal, XawtextScrollWhenNeeded); j++;
312 // XtSetArg(args[j], XtNautoFill, True); j++;
313 // XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
314 outputField[which][nMemo] = edit =
315 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
318 XtSetArg(args[j], XtNfromVert, ColorWidget); j++;
319 // XtSetArg(args[j], XtNresizable, (XtArgVal) True); j++;
320 XtSetValues(edit, args, j);
323 Widget EngineOutputCreate(name, text)
327 Widget shell, layout, form, form2, edit;
328 Dimension bw_width, bw_height;
333 XtSetArg(args[j], XtNwidth, &bw_width); j++;
334 XtSetArg(args[j], XtNheight, &bw_height); j++;
335 XtGetValues(boardWidget, args, j);
337 // define form within layout within shell.
339 XtSetArg(args[j], XtNresizable, True); j++;
342 XtCreatePopupShell(name, topLevelShellWidgetClass,
344 XtCreatePopupShell(name, transientShellWidgetClass,
346 shellWidget, args, j);
348 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
349 layoutArgs, XtNumber(layoutArgs));
350 // divide window vertically into two equal parts, by creating two forms
352 XtCreateManagedWidget("form", formWidgetClass, layout,
353 formArgs, XtNumber(formArgs));
355 XtCreateManagedWidget("form2", formWidgetClass, layout,
356 formArgs, XtNumber(formArgs));
358 XtSetArg(args[j], XtNfromVert, (XtArgVal) form); j++;
359 XtSetValues(form2, args, j);
360 // make sure width is known in advance, for better placement of child widgets
362 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width-16); j++;
363 XtSetArg(args[j], XtNheight, (XtArgVal) bw_height/2); j++;
364 XtSetValues(shell, args, j);
366 // fill up both forms with control elements
367 PositionControlSet(0, form, bw_width);
368 PositionControlSet(1, form2, bw_width);
370 XtRealizeWidget(shell);
372 if(wpEngineOutput.width > 0) {
373 engineOutputW = wpEngineOutput.width;
374 engineOutputH = wpEngineOutput.height;
375 engineOutputX = wpEngineOutput.x;
376 engineOutputY = wpEngineOutput.y;
379 if (engineOutputX == -1) {
384 engineOutputH = bw_height/2;
385 engineOutputW = bw_width-16;
387 XSync(xDisplay, False);
389 /* This code seems to tickle an X bug if it is executed too soon
390 after xboard starts up. The coordinates get transformed as if
391 the main window was positioned at (0, 0).
393 XtTranslateCoords(shellWidget,
394 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
395 &engineOutputX, &engineOutputY);
397 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
398 RootWindowOfScreen(XtScreen(shellWidget)),
399 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
404 if (engineOutputY < 0) engineOutputY = 0; /*avoid positioning top offscreen*/
407 XtSetArg(args[j], XtNheight, engineOutputH); j++;
408 XtSetArg(args[j], XtNwidth, engineOutputW); j++;
409 XtSetArg(args[j], XtNx, engineOutputX); j++;
410 XtSetArg(args[j], XtNy, engineOutputY); j++;
411 XtSetValues(shell, args, j);
412 // XtSetKeyboardFocus(shell, edit);
417 void ResizeWindowControls(mode)
423 Dimension ew_height, tmp;
424 Widget shell = engineOutputShell;
426 form1 = XtNameToWidget(shell, "*form");
427 form2 = XtNameToWidget(shell, "*form2");
430 XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++;
431 XtGetValues(form1, args, j);
433 XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++;
434 XtGetValues(form2, args, j);
435 ew_height += tmp; // total height
439 XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++;
440 XtSetValues(form2, args, j);
442 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++;
443 XtSetValues(form1, args, j);
446 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
447 XtSetValues(form1, args, j);
449 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
450 XtSetValues(form2, args, j);
460 static int needInit = TRUE;
461 static char *title = _("Engine output"), *text = _("This feature is experimental");
463 if (engineOutputShell == NULL) {
465 EngineOutputCreate(title, text);
466 XtRealizeWidget(engineOutputShell);
467 CatchDeleteWindow(engineOutputShell, "EngineOutputPopDown");
469 InitializeEngineOutput();
472 SetEngineColorIcon( 0 );
473 SetEngineColorIcon( 1 );
474 SetEngineState( 0, STATE_IDLE, "" );
475 SetEngineState( 1, STATE_IDLE, "" );
477 edit = XtNameToWidget(engineOutputShell, "*form.text");
479 XtSetArg(args[j], XtNstring, text); j++;
480 XtSetValues(edit, args, j);
482 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
483 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
484 XtSetValues(engineOutputShell, args, j);
487 XtPopup(engineOutputShell, XtGrabNone);
488 XSync(xDisplay, False);
491 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
492 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
495 engineOutputDialogUp = True;
496 ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
499 void EngineOutputPopDown()
504 if (!engineOutputDialogUp) return;
507 XtSetArg(args[j], XtNx, &engineOutputX); j++;
508 XtSetArg(args[j], XtNy, &engineOutputY); j++;
509 XtSetArg(args[j], XtNwidth, &engineOutputW); j++;
510 XtSetArg(args[j], XtNheight, &engineOutputH); j++;
511 XtGetValues(engineOutputShell, args, j);
512 wpEngineOutput.x = engineOutputX - 4;
513 wpEngineOutput.y = engineOutputY - 23;
514 wpEngineOutput.width = engineOutputW;
515 wpEngineOutput.height = engineOutputH;
516 XtPopdown(engineOutputShell);
517 XSync(xDisplay, False);
519 XtSetArg(args[j], XtNleftBitmap, None); j++;
520 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
523 engineOutputDialogUp = False;
524 ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
527 int EngineOutputIsUp()
529 return engineOutputDialogUp;
532 int EngineOutputDialogExists()
534 return engineOutputShell != NULL;
538 EngineOutputProc(w, event, prms, nprms)
544 if (engineOutputDialogUp) {
545 EngineOutputPopDown();