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 /* the backend adds \r\n, which is needed for winboard,
188 * for xboard we delete them again over here */
189 if(t.ptr = strchr(text, '\r')) *t.ptr = ' ';
191 t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit;
192 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
193 XawTextReplace(edit, where, where, &t);
194 // XtSetArg(arg, XtNstring, (XtArgVal) text);
195 // XtSetValues(outputField[which][nMemo], &arg, 1);
198 void SetIcon( int which, int field, int nIcon )
203 XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]);
204 XtSetValues(outputField[which][field], &arg, 1);
208 void DoClearMemo(int which)
214 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
215 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
216 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
219 // The following routines are mutated clones of the commentPopUp routines
221 void PositionControlSet(which, form, bw_width)
227 Widget edit, NameWidget, ColorWidget, ModeWidget, MoveWidget, NodesWidget;
230 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
231 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
232 XtSetArg(args[j], XtNtop, XtChainTop); j++;
233 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
234 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
235 XtSetArg(args[j], XtNright, XtChainLeft); j++;
236 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
237 XtSetArg(args[j], XtNwidth, (XtArgVal) 17); j++;
238 outputField[which][nColorIcon] = ColorWidget =
239 XtCreateManagedWidget("Color", labelWidgetClass,
243 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
244 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
245 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ColorWidget); j++;
246 XtSetArg(args[j], XtNtop, XtChainTop); j++;
247 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
248 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
249 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
250 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 57); j++;
251 outputField[which][nLabel] = NameWidget =
252 XtCreateManagedWidget("Engine", labelWidgetClass,
256 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
257 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
258 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) NameWidget); j++;
259 XtSetArg(args[j], XtNtop, XtChainTop); j++;
260 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
261 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
262 XtSetArg(args[j], XtNwidth, (XtArgVal) 20); j++;
263 outputField[which][nStateIcon] = ModeWidget =
264 XtCreateManagedWidget("Mode", labelWidgetClass,
268 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
269 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
270 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
271 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ModeWidget); j++;
272 XtSetArg(args[j], XtNtop, XtChainTop); j++;
273 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
274 XtSetArg(args[j], XtNright, XtChainRight); j++;
275 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
276 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 102); j++;
277 outputField[which][nStateData] = MoveWidget =
278 XtCreateManagedWidget("Move", labelWidgetClass,
282 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
283 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyRight); j++;
284 XtSetArg(args[j], XtNlabel, (XtArgVal) _("NPS")); j++;
285 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) MoveWidget); j++;
286 XtSetArg(args[j], XtNtop, XtChainTop); j++;
287 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
288 XtSetArg(args[j], XtNleft, XtChainRight); j++;
289 XtSetArg(args[j], XtNright, XtChainRight); j++;
290 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
291 XtSetArg(args[j], XtNwidth, (XtArgVal) 100); j++;
292 outputField[which][nLabelNPS] = NodesWidget =
293 XtCreateManagedWidget("Nodes", labelWidgetClass,
296 // create "text" within "form"
299 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
300 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
302 XtSetArg(args[j], XtNstring, ""); j++;
303 XtSetArg(args[j], XtNdisplayCaret, False); j++;
304 XtSetArg(args[j], XtNtop, XtChainTop); j++;
305 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
306 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
307 XtSetArg(args[j], XtNright, XtChainRight); j++;
308 XtSetArg(args[j], XtNresizable, True); j++;
309 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
310 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
311 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
312 XtSetArg(args[j], XtNscrollHorizontal, XawtextScrollWhenNeeded); j++;
313 // XtSetArg(args[j], XtNautoFill, True); j++;
314 // XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
315 outputField[which][nMemo] = edit =
316 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
319 XtSetArg(args[j], XtNfromVert, ColorWidget); j++;
320 // XtSetArg(args[j], XtNresizable, (XtArgVal) True); j++;
321 XtSetValues(edit, args, j);
324 Widget EngineOutputCreate(name, text)
328 Widget shell, layout, form, form2, edit;
329 Dimension bw_width, bw_height;
334 XtSetArg(args[j], XtNwidth, &bw_width); j++;
335 XtSetArg(args[j], XtNheight, &bw_height); j++;
336 XtGetValues(boardWidget, args, j);
338 // define form within layout within shell.
340 XtSetArg(args[j], XtNresizable, True); j++;
343 XtCreatePopupShell(name, topLevelShellWidgetClass,
345 XtCreatePopupShell(name, transientShellWidgetClass,
347 shellWidget, args, j);
349 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
350 layoutArgs, XtNumber(layoutArgs));
351 // divide window vertically into two equal parts, by creating two forms
353 XtCreateManagedWidget("form", formWidgetClass, layout,
354 formArgs, XtNumber(formArgs));
356 XtCreateManagedWidget("form2", formWidgetClass, layout,
357 formArgs, XtNumber(formArgs));
359 XtSetArg(args[j], XtNfromVert, (XtArgVal) form); j++;
360 XtSetValues(form2, args, j);
361 // make sure width is known in advance, for better placement of child widgets
363 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width-16); j++;
364 XtSetArg(args[j], XtNheight, (XtArgVal) bw_height/2); j++;
365 XtSetValues(shell, args, j);
367 // fill up both forms with control elements
368 PositionControlSet(0, form, bw_width);
369 PositionControlSet(1, form2, bw_width);
371 XtRealizeWidget(shell);
373 if(wpEngineOutput.width > 0) {
374 engineOutputW = wpEngineOutput.width;
375 engineOutputH = wpEngineOutput.height;
376 engineOutputX = wpEngineOutput.x;
377 engineOutputY = wpEngineOutput.y;
380 if (engineOutputX == -1) {
385 engineOutputH = bw_height/2;
386 engineOutputW = bw_width-16;
388 XSync(xDisplay, False);
390 /* This code seems to tickle an X bug if it is executed too soon
391 after xboard starts up. The coordinates get transformed as if
392 the main window was positioned at (0, 0).
394 XtTranslateCoords(shellWidget,
395 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
396 &engineOutputX, &engineOutputY);
398 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
399 RootWindowOfScreen(XtScreen(shellWidget)),
400 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
405 if (engineOutputY < 0) engineOutputY = 0; /*avoid positioning top offscreen*/
408 XtSetArg(args[j], XtNheight, engineOutputH); j++;
409 XtSetArg(args[j], XtNwidth, engineOutputW); j++;
410 XtSetArg(args[j], XtNx, engineOutputX); j++;
411 XtSetArg(args[j], XtNy, engineOutputY); j++;
412 XtSetValues(shell, args, j);
413 // XtSetKeyboardFocus(shell, edit);
418 void ResizeWindowControls(mode)
424 Dimension ew_height, tmp;
425 Widget shell = engineOutputShell;
427 form1 = XtNameToWidget(shell, "*form");
428 form2 = XtNameToWidget(shell, "*form2");
431 XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++;
432 XtGetValues(form1, args, j);
434 XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++;
435 XtGetValues(form2, args, j);
436 ew_height += tmp; // total height
440 XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++;
441 XtSetValues(form2, args, j);
443 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++;
444 XtSetValues(form1, args, j);
447 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
448 XtSetValues(form1, args, j);
450 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
451 XtSetValues(form2, args, j);
461 static int needInit = TRUE;
462 static char *title = _("Engine output"), *text = _("This feature is experimental");
464 if (engineOutputShell == NULL) {
466 EngineOutputCreate(title, text);
467 XtRealizeWidget(engineOutputShell);
468 CatchDeleteWindow(engineOutputShell, "EngineOutputPopDown");
470 InitializeEngineOutput();
473 SetEngineColorIcon( 0 );
474 SetEngineColorIcon( 1 );
475 SetEngineState( 0, STATE_IDLE, "" );
476 SetEngineState( 1, STATE_IDLE, "" );
478 edit = XtNameToWidget(engineOutputShell, "*form.text");
480 XtSetArg(args[j], XtNstring, text); j++;
481 XtSetValues(edit, args, j);
483 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
484 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
485 XtSetValues(engineOutputShell, args, j);
488 XtPopup(engineOutputShell, XtGrabNone);
489 XSync(xDisplay, False);
492 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
493 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
496 engineOutputDialogUp = True;
497 ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
500 void EngineOutputPopDown()
505 if (!engineOutputDialogUp) return;
508 XtSetArg(args[j], XtNx, &engineOutputX); j++;
509 XtSetArg(args[j], XtNy, &engineOutputY); j++;
510 XtSetArg(args[j], XtNwidth, &engineOutputW); j++;
511 XtSetArg(args[j], XtNheight, &engineOutputH); j++;
512 XtGetValues(engineOutputShell, args, j);
513 wpEngineOutput.x = engineOutputX - 4;
514 wpEngineOutput.y = engineOutputY - 23;
515 wpEngineOutput.width = engineOutputW;
516 wpEngineOutput.height = engineOutputH;
517 XtPopdown(engineOutputShell);
518 XSync(xDisplay, False);
520 XtSetArg(args[j], XtNleftBitmap, None); j++;
521 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
524 engineOutputDialogUp = False;
525 ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
528 int EngineOutputIsUp()
530 return engineOutputDialogUp;
533 int EngineOutputDialogExists()
535 return engineOutputShell != NULL;
539 EngineOutputProc(w, event, prms, nprms)
545 if (engineOutputDialogUp) {
546 EngineOutputPopDown();