4 * Author: Alessandro Scotti (Dec 2005)
\r
6 * ------------------------------------------------------------------------
\r
7 * This program is free software; you can redistribute it and/or modify
\r
8 * it under the terms of the GNU General Public License as published by
\r
9 * the Free Software Foundation; either version 2 of the License, or
\r
10 * (at your option) any later version.
\r
12 * This program is distributed in the hope that it will be useful,
\r
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 * GNU General Public License for more details.
\r
17 * You should have received a copy of the GNU General Public License
\r
18 * along with this program; if not, write to the Free Software
\r
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
\r
20 * ------------------------------------------------------------------------
\r
27 #include <sys/types.h>
32 #else /* not STDC_HEADERS */
33 extern char *getenv();
36 # else /* not HAVE_STRING_H */
38 # endif /* not HAVE_STRING_H */
39 #endif /* not STDC_HEADERS */
45 #include <X11/Intrinsic.h>
46 #include <X11/StringDefs.h>
47 #include <X11/Shell.h>
48 #include <X11/Xaw/Dialog.h>
49 #include <X11/Xaw/Form.h>
50 #include <X11/Xaw/List.h>
51 #include <X11/Xaw/Label.h>
52 #include <X11/Xaw/SimpleMenu.h>
53 #include <X11/Xaw/SmeBSB.h>
54 #include <X11/Xaw/SmeLine.h>
55 #include <X11/Xaw/Box.h>
56 #include <X11/Xaw/Paned.h>
57 #include <X11/Xaw/MenuButton.h>
58 #include <X11/cursorfont.h>
59 #include <X11/Xaw/Text.h>
60 #include <X11/Xaw/AsciiText.h>
61 #include <X11/Xaw/Viewport.h>
67 // Add xengineo.h later
69 #include <X11/xpm.h>
\r
71 // [HGM] pixmaps of some ICONS used in the engine-outut window
72 #include "pixmaps/WHITE_14.xpm"
73 #include "pixmaps/BLACK_14.xpm"
74 #include "pixmaps/CLEAR_14.xpm"
75 #include "pixmaps/UNKNOWN_14.xpm"
76 #include "pixmaps/THINKING_14.xpm"
77 #include "pixmaps/PONDER_14.xpm"
78 #include "pixmaps/ANALYZING_14.xpm"
86 // imports from xboard.c
87 extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;
88 extern Display *xDisplay;
89 extern Window xBoardWindow;
90 extern int squareSize;
91 extern Pixmap xMarkPixmap, wIconPixmap, bIconPixmap;
92 extern char *layoutName;
94 // temporary kludge to avoid compile errors untill all Windows code has been replaced
98 // [HGM] define numbers to indicate icons, for referring to them in platform-independent way
\r
99 #define nColorBlack 1
\r
100 #define nColorWhite 2
\r
101 #define nColorUnknown 3
\r
103 #define nPondering 5
\r
104 #define nThinking 6
\r
105 #define nAnalyzing 7
\r
107 Pixmap icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle
\r
109 // [HGM] same for output fields (note that there are two of each type, one per color)
\r
110 #define nColorIcon 1
\r
111 #define nStateIcon 2
\r
113 #define nStateData 4
\r
114 #define nLabelNPS 5
\r
117 Widget outputField[2][7]; // [HGM] front-end array to translate output field to window handle
\r
119 void EngineOutputPopDown();
\r
120 void engineOutputPopUp(char *title, char *text);
\r
121 int EngineOutputIsUp();
\r
122 static void SetEngineColorIcon( int which );
\r
124 #define SHOW_PONDERING
\r
126 /* Imports from backend.c */
\r
127 char * SavePart(char *str);
\r
129 /* Imports from winboard.c */
\r
130 //extern HWND engineOutputDialog;
\r
131 extern Arg layoutArgs[2], formArgs[2], messageArgs[4];
\r
133 //extern WindowPlacement wpEngineOutput;
\r
135 Position engineOutputX = -1, engineOutputY = -1;
136 Dimension engineOutputW, engineOutputH;
137 Widget engineOutputShell;
138 int engineOutputDialogUp;
140 /* Module variables */
\r
143 #define LABEL_V_DISTANCE 1 /* Distance between label and memo */
\r
144 #define SPLITTER_SIZE 4 /* Distance between first memo and second label */
\r
146 #define ICON_SIZE 14
\r
148 #define STATE_UNKNOWN -1
\r
149 #define STATE_THINKING 0
\r
150 #define STATE_IDLE 1
\r
151 #define STATE_PONDERING 2
\r
152 #define STATE_ANALYZING 3
\r
154 static int windowMode = 1;
\r
156 static int needInit = TRUE;
\r
158 static int lastDepth[2] = { -1, -1 };
\r
159 static int lastForwardMostMove[2] = { -1, -1 };
\r
160 static int engineState[2] = { -1, -1 };
\r
166 unsigned long nodes;
\r
173 } EngineOutputData;
\r
175 static VerifyDisplayMode();
\r
176 static void UpdateControls( EngineOutputData * ed );
\r
177 static SetEngineState( int which, int state, char * state_data );
\r
179 void ReadIcon(char *pixData[], int iconNr)
183 if ((r=XpmCreatePixmapFromData(xDisplay, XtWindow(outputField[0][nColorIcon]),
\r
186 NULL, NULL /*&attr*/)) != 0) {
\r
187 fprintf(stderr, "Error %d loading icon image\n", r);
\r
192 static void InitializeEngineOutput()
\r
195 ReadIcon(WHITE_14, nColorWhite);
\r
196 ReadIcon(BLACK_14, nColorBlack);
\r
197 ReadIcon(UNKNOWN_14, nColorUnknown);
\r
199 ReadIcon(CLEAR_14, nClear);
\r
200 ReadIcon(PONDER_14, nPondering);
\r
201 ReadIcon(THINK_14, nThinking);
\r
202 ReadIcon(ANALYZE_14, nAnalyzing);
\r
203 // icons[nClear] = wIconPixmap;
\r
204 // icons[nPondering] = bIconPixmap;
\r// icons[nThinking] = wIconPixmap;
\r
205 // icons[nAnalyzing] = bIconPixmap;
\r}
208 // Windows routines commented out
211 static HICON LoadIconEx( int id )
\r
213 return LoadImage( hInst, MAKEINTRESOURCE(id), IMAGE_ICON, ICON_SIZE, ICON_SIZE, 0 );
\r
216 // [HGM] the platform-dependent way of indicating where output should go is now all
\r
217 // concentrated here, where a table of platform-dependent handles are initialized.
\r
218 // This cleanses most other routines of front-end stuff, so they can go into the back end.
\r
219 static void InitializeEngineOutput()
\r
221 // if( needInit ) { // needInit was already tested before call
\r
222 // [HGM] made this into a table, rather than separate global variables
\r
223 icons[nColorBlack] = LoadIconEx( IDI_BLACK_14 );
\r
224 icons[nColorWhite] = LoadIconEx( IDI_WHITE_14 );
\r
225 icons[nColorUnknown] = LoadIconEx( IDI_UNKNOWN_14 );
\r
226 icons[nClear] = LoadIconEx( IDI_TRANS_14 );
\r
227 icons[nPondering] = LoadIconEx( IDI_PONDER_14 );
\r
228 icons[nThinking] = LoadIconEx( IDI_CLOCK_14 );
\r
229 icons[nAnalyzing] = LoadIconEx( IDI_ANALYZE2_14 );
\r
231 // [HGM] also make a table of handles to output controls
\r
232 // Note that engineOutputDialog must be defined first!
\r
233 outputField[0][nColorIcon] = GetDlgItem( engineOutputDialog, IDC_Color1 );
\r
234 outputField[0][nLabel] = GetDlgItem( engineOutputDialog, IDC_EngineLabel1 );
\r
235 outputField[0][nStateIcon] = GetDlgItem( engineOutputDialog, IDC_StateIcon1 );
\r
236 outputField[0][nStateData] = GetDlgItem( engineOutputDialog, IDC_StateData1 );
\r
237 outputField[0][nLabelNPS] = GetDlgItem( engineOutputDialog, IDC_Engine1_NPS );
\r
238 outputField[0][nMemo] = GetDlgItem( engineOutputDialog, IDC_EngineMemo1 );
\r
240 outputField[1][nColorIcon] = GetDlgItem( engineOutputDialog, IDC_Color2 );
\r
241 outputField[1][nLabel] = GetDlgItem( engineOutputDialog, IDC_EngineLabel2 );
\r
242 outputField[1][nStateIcon] = GetDlgItem( engineOutputDialog, IDC_StateIcon2 );
\r
243 outputField[1][nStateData] = GetDlgItem( engineOutputDialog, IDC_StateData2 );
\r
244 outputField[1][nLabelNPS] = GetDlgItem( engineOutputDialog, IDC_Engine2_NPS );
\r
245 outputField[1][nMemo] = GetDlgItem( engineOutputDialog, IDC_EngineMemo2 );
\r
246 // needInit = FALSE;
\r
251 static void SetControlPos( HWND hDlg, int id, int x, int y, int width, int height )
\r
253 HWND hControl = GetDlgItem( hDlg, id );
\r
255 SetWindowPos( hControl, HWND_TOP, x, y, width, height, SWP_NOZORDER );
\r
258 #define HIDDEN_X 20000
\r
259 #define HIDDEN_Y 20000
\r
262 static void HideControl( HWND hDlg, int id )
\r
264 HWND hControl = GetDlgItem( hDlg, id );
\r
267 GetWindowRect( hControl, &rc );
\r
270 Avoid hiding an already hidden control, because that causes many
\r
271 unnecessary WM_ERASEBKGND messages!
\r
273 if( rc.left != HIDDEN_X || rc.top != HIDDEN_Y ) {
\r
274 SetControlPos( hDlg, id, 20000, 20000, 100, 100 );
\r
278 // front end, although we might make GetWindowRect front end instead
\r
279 static int GetControlWidth( HWND hDlg, int id )
\r
283 GetWindowRect( GetDlgItem( hDlg, id ), &rc );
\r
285 return rc.right - rc.left;
\r
289 static int GetControlHeight( HWND hDlg, int id )
\r
293 GetWindowRect( GetDlgItem( hDlg, id ), &rc );
\r
295 return rc.bottom - rc.top;
\r
298 static int GetHeaderHeight()
\r
300 int result = GetControlHeight( engineOutputDialog, IDC_EngineLabel1 );
\r
302 if( result < ICON_SIZE ) result = ICON_SIZE;
\r
307 // The size calculations should be backend? If setControlPos is a platform-dependent way of doing things,
\r
308 // a platform-independent wrapper for it should be supplied.
\r
309 static void PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int memoHeight, int idColor, int idEngineLabel, int idNPS, int idMemo, int idStateIcon, int idStateData )
\r
311 int label_x = x + ICON_SIZE + H_MARGIN;
\r
312 int label_h = GetControlHeight( hDlg, IDC_EngineLabel1 );
\r
313 int label_y = y + ICON_SIZE - label_h;
\r
314 int nps_w = GetControlWidth( hDlg, IDC_Engine1_NPS );
\r
315 int nps_x = clientWidth - H_MARGIN - nps_w;
\r
316 int state_data_w = GetControlWidth( hDlg, IDC_StateData1 );
\r
317 int state_data_x = nps_x - H_MARGIN - state_data_w;
\r
318 int state_icon_x = state_data_x - ICON_SIZE - 2;
\r
319 int max_w = clientWidth - 2*H_MARGIN;
\r
320 int memo_y = y + ICON_SIZE + LABEL_V_DISTANCE;
\r
322 SetControlPos( hDlg, idColor, x, y, ICON_SIZE, ICON_SIZE );
\r
323 SetControlPos( hDlg, idEngineLabel, label_x, label_y, state_icon_x - label_x, label_h );
\r
324 SetControlPos( hDlg, idStateIcon, state_icon_x, y, ICON_SIZE, ICON_SIZE );
\r
325 SetControlPos( hDlg, idStateData, state_data_x, label_y, state_data_w, label_h );
\r
326 SetControlPos( hDlg, idNPS, nps_x, label_y, nps_w, label_h );
\r
327 SetControlPos( hDlg, idMemo, x, memo_y, max_w, memoHeight );
\r
330 // Also here some of the size calculations should go to the back end, and their actual application to a front-end routine
\r
331 static void ResizeWindowControls( HWND hDlg, int mode )
\r
334 int headerHeight = GetHeaderHeight();
\r
335 int labelHeight = GetControlHeight( hDlg, IDC_EngineLabel1 );
\r
336 int labelOffset = H_MARGIN + ICON_SIZE + H_MARGIN;
\r
337 int labelDeltaY = ICON_SIZE - labelHeight;
\r
340 int maxControlWidth;
\r
343 /* Initialize variables */
\r
344 GetClientRect( hDlg, &rc );
\r
346 clientWidth = rc.right - rc.left;
\r
347 clientHeight = rc.bottom - rc.top;
\r
349 maxControlWidth = clientWidth - 2*H_MARGIN;
\r
351 npsWidth = GetControlWidth( hDlg, IDC_Engine1_NPS );
\r
353 /* Resize controls */
\r
356 PositionControlSet( hDlg, H_MARGIN, V_MARGIN,
\r
358 clientHeight - V_MARGIN - LABEL_V_DISTANCE - headerHeight- V_MARGIN,
\r
359 IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );
\r
361 /* Hide controls for the second engine */
\r
362 HideControl( hDlg, IDC_Color2 );
\r
363 HideControl( hDlg, IDC_EngineLabel2 );
\r
364 HideControl( hDlg, IDC_StateIcon2 );
\r
365 HideControl( hDlg, IDC_StateData2 );
\r
366 HideControl( hDlg, IDC_Engine2_NPS );
\r
367 HideControl( hDlg, IDC_EngineMemo2 );
\r
368 SendDlgItemMessage( hDlg, IDC_EngineMemo2, WM_SETTEXT, 0, (LPARAM) "" );
\r
369 /* TODO: we should also hide/disable them!!! what about tab stops?!?! */
\r
373 int memo_h = (clientHeight - headerHeight*2 - V_MARGIN*2 - LABEL_V_DISTANCE*2 - SPLITTER_SIZE) / 2;
\r
374 int header1_y = V_MARGIN;
\r
375 int header2_y = V_MARGIN + headerHeight + LABEL_V_DISTANCE + memo_h + SPLITTER_SIZE;
\r
377 PositionControlSet( hDlg, H_MARGIN, header1_y, clientWidth, memo_h,
\r
378 IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );
\r
380 PositionControlSet( hDlg, H_MARGIN, header2_y, clientWidth, memo_h,
\r
381 IDC_Color2, IDC_EngineLabel2, IDC_Engine2_NPS, IDC_EngineMemo2, IDC_StateIcon2, IDC_StateData2 );
\r
384 InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo1), NULL, FALSE );
\r
385 InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE );
\r
388 // front end. Actual printing of PV lines into the output field
\r
389 static void InsertIntoMemo( int which, char * text )
\r
391 SendMessage( outputField[which][nMemo], EM_SETSEL, 0, 0 );
\r
393 SendMessage( outputField[which][nMemo], EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );
\r
396 // front end. Associates an icon with an output field ("control" in Windows jargon).
\r
397 // [HGM] let it find out the output field from the 'which' number by itself
\r
398 static void SetIcon( int which, int field, int nIcon )
\r
402 SendMessage( outputField[which][field], STM_SETICON, (WPARAM) icons[nIcon], 0 );
\r
406 // front end wrapper for SetWindowText, taking control number in stead of handle
\r
407 void DoSetWindowText(int which, int field, char *s_label)
\r
409 SetWindowText( outputField[which][field], s_label );
\r
413 void DoSetWindowText(int which, int field, char *s_label)
\r
417 XtSetArg(arg, XtNlabel, (XtArgVal) s_label);
\r
418 XtSetValues(outputField[which][field], &arg, 1);
\r
421 static void InsertIntoMemo( int which, char * text )
\r
423 Arg arg; XawTextBlock t; Widget edit;
425 t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit;
\r
426 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
\r
427 XawTextReplace(edit, 0, 0, &t);
428 // XtSetArg(arg, XtNstring, (XtArgVal) text);
\r
429 // XtSetValues(outputField[which][nMemo], &arg, 1);
\r
432 static void SetIcon( int which, int field, int nIcon )
437 XtSetArg(arg, XtNleftBitmap, (XtArgVal) icons[nIcon]);
\r
438 XtSetValues(outputField[which][field], &arg, 1);
\r
442 void DoClearMemo(int which)
\r{
\r Arg args[16];
\r
446 edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
\r
447 XtCallActionProc(edit, "select-all", NULL, NULL, 0);
\r
448 XtCallActionProc(edit, "kill-selection", NULL, NULL, 0);
\r
451 // The following routines are mutated clones of the commentPopUp routines
\r
453 void PositionControlSet(which, form, bw_width)
\r
456 Dimension bw_width;
\r{
\r
458 Widget edit, NameWidget, ColorWidget, ModeWidget, MoveWidget, NodesWidget;
\r
461 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
462 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
\r
463 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
464 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
\r
465 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r XtSetArg(args[j], XtNright, XtChainLeft); j++;
\r XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
\r
466 XtSetArg(args[j], XtNwidth, (XtArgVal) 17); j++;
\r
467 outputField[which][nColorIcon] = ColorWidget =
468 XtCreateManagedWidget("Color", labelWidgetClass,
\r
472 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
473 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
474 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ColorWidget); j++;
\r
475 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
476 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
\r
477 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
\r
478 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 57); j++;
\r
479 outputField[which][nLabel] = NameWidget =
480 XtCreateManagedWidget("Engine", labelWidgetClass,
\r
484 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
485 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
\r
486 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) NameWidget); j++;
\r
487 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
488 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
\r
489 XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
\r
490 XtSetArg(args[j], XtNwidth, (XtArgVal) 20); j++;
\r
491 outputField[which][nStateIcon] = ModeWidget =
492 XtCreateManagedWidget("Mode", labelWidgetClass,
\r
496 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
497 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyLeft); j++;
498 XtSetArg(args[j], XtNlabel, (XtArgVal) ""); j++;
\r
499 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) ModeWidget); j++;
\r
500 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
501 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
\r
502 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
\r
503 XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width/2 - 102); j++;
\r
504 outputField[which][nStateData] = MoveWidget =
505 XtCreateManagedWidget("Move", labelWidgetClass,
\r
509 XtSetArg(args[j], XtNborderWidth, (XtArgVal) 0); j++;
510 XtSetArg(args[j], XtNjustify, (XtArgVal) XtJustifyRight); j++;
\r
511 XtSetArg(args[j], XtNlabel, (XtArgVal) "NPS"); j++;
\r
512 XtSetArg(args[j], XtNfromHoriz, (XtArgVal) MoveWidget); j++;
\r
513 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
514 XtSetArg(args[j], XtNbottom, XtChainTop); j++;
\r
515 XtSetArg(args[j], XtNleft, XtChainRight); j++;
\r XtSetArg(args[j], XtNright, XtChainRight); j++;
\r XtSetArg(args[j], XtNheight, (XtArgVal) 16); j++;
\r
516 XtSetArg(args[j], XtNwidth, (XtArgVal) 100); j++;
\r
517 outputField[which][nLabelNPS] = NodesWidget =
518 XtCreateManagedWidget("Nodes", labelWidgetClass,
\r
521 // create "text" within "form"
524 XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
\r
525 XtSetArg(args[j], XtNuseStringInPlace, False); j++;
\r
527 XtSetArg(args[j], XtNstring, ""); j++;
\r
528 XtSetArg(args[j], XtNdisplayCaret, False); j++;
\r
529 XtSetArg(args[j], XtNtop, XtChainTop); j++;
\r
530 XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
\r
531 XtSetArg(args[j], XtNleft, XtChainLeft); j++;
\r
532 XtSetArg(args[j], XtNright, XtChainRight); j++;
\r
533 XtSetArg(args[j], XtNresizable, True); j++;
\r
534 XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/
\r
536 XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++;
\r
538 /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */
\r
539 XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++;
\r
540 XtSetArg(args[j], XtNscrollHorizontal, XawtextScrollWhenNeeded); j++;
\r#endif
\r
541 // XtSetArg(args[j], XtNautoFill, True); j++;
\r
542 // XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++;
\r
543 outputField[which][nMemo] = edit =
\r
544 XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
\r
547 XtSetArg(args[j], XtNfromVert, ColorWidget); j++;
\r
548 // XtSetArg(args[j], XtNresizable, (XtArgVal) True); j++;
\r
549 XtSetValues(edit, args, j);
\r
552 Widget EngineOutputCreate(name, text)
\r
556 Widget shell, layout, form, form2, edit;
557 Dimension bw_width, bw_height;
\r
562 XtSetArg(args[j], XtNwidth, &bw_width); j++;
\r XtSetArg(args[j], XtNheight, &bw_height); j++;
\r XtGetValues(boardWidget, args, j);
\r
564 // define form within layout within shell.
566 XtSetArg(args[j], XtNresizable, True); j++;
\r
568 XtCreatePopupShell(name, transientShellWidgetClass,
\r
569 shellWidget, args, j);
\r
571 XtCreateManagedWidget(layoutName, formWidgetClass, shell,
\r
572 layoutArgs, XtNumber(layoutArgs));
\r
573 // divide window vertically into two equal parts, by creating two forms
575 XtCreateManagedWidget("form", formWidgetClass, layout,
\r
576 formArgs, XtNumber(formArgs));
\r
578 XtCreateManagedWidget("form2", formWidgetClass, layout,
\r
579 formArgs, XtNumber(formArgs));
\r
580 j = 0;
\r XtSetArg(args[j], XtNfromVert, (XtArgVal) form); j++;
\r XtSetValues(form2, args, j);
\r
581 // make sure width is known in advance, for better placement of child widgets
582 j = 0;
\r XtSetArg(args[j], XtNwidth, (XtArgVal) bw_width-16); j++;
\r XtSetArg(args[j], XtNheight, (XtArgVal) bw_height/2); j++;
\r XtSetValues(shell, args, j);
\r
584 // fill up both forms with control elements
585 PositionControlSet(0, form, bw_width);
586 PositionControlSet(1, form2, bw_width);
588 XtRealizeWidget(shell);
\r
590 if (engineOutputX == -1) {
\r
593 Dimension pw_height;
\r
594 Dimension ew_height;
\r
597 XtSetArg(args[j], XtNheight, &ew_height); j++;
\r
598 XtGetValues(edit, args, j);
\r
601 XtSetArg(args[j], XtNheight, &pw_height); j++;
\r
602 XtGetValues(shell, args, j);
\r
603 engineOutputH = pw_height + (lines - 1) * ew_height;
\r
604 engineOutputW = bw_width - 16;
606 engineOutputH = bw_height/2;
\r engineOutputW = bw_width-16;
\r#endif
608 XSync(xDisplay, False);
\r
610 /* This code seems to tickle an X bug if it is executed too soon
\r
611 after xboard starts up. The coordinates get transformed as if
\r
612 the main window was positioned at (0, 0).
\r
614 XtTranslateCoords(shellWidget,
\r
615 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
\r
616 &engineOutputX, &engineOutputY);
\r
618 XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
\r
619 RootWindowOfScreen(XtScreen(shellWidget)),
\r
620 (bw_width - engineOutputW) / 2, 0 - engineOutputH / 2,
\r
622 engineOutputX = xx;
\r
623 engineOutputY = yy;
\r
625 if (engineOutputY < 0) engineOutputY = 0; /*avoid positioning top offscreen*/
\r
628 XtSetArg(args[j], XtNheight, engineOutputH); j++;
\r XtSetArg(args[j], XtNwidth, engineOutputW); j++;
\r
629 XtSetArg(args[j], XtNx, engineOutputX); j++;
\r
630 XtSetArg(args[j], XtNy, engineOutputY); j++;
\r
631 XtSetValues(shell, args, j);
\r
632 // XtSetKeyboardFocus(shell, edit);
\r
637 void ResizeWindowControls(shell, mode)
644 Dimension ew_height, tmp;
646 form1 = XtNameToWidget(shell, "*form");
\r
647 form2 = XtNameToWidget(shell, "*form2");
650 XtSetArg(args[j], XtNheight, (XtArgVal) &ew_height); j++;
\r XtGetValues(form1, args, j);
652 XtSetArg(args[j], XtNheight, (XtArgVal) &tmp); j++;
\r XtGetValues(form2, args, j);
653 ew_height += tmp; // total height
657 XtSetArg(args[j], XtNheight, (XtArgVal) 5); j++;
\r
658 XtSetValues(form2, args, j);
660 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height-5)); j++;
\r
661 XtSetValues(form1, args, j);
664 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
\r
665 XtSetValues(form1, args, j);
667 XtSetArg(args[j], XtNheight, (XtArgVal) (ew_height/2)); j++;
\r
668 XtSetValues(form2, args, j);
673 void EngineOutputCallback(w, client_data, call_data)
\r
675 XtPointer client_data, call_data;
\r
682 XtSetArg(args[j], XtNlabel, &name); j++;
\r
683 XtGetValues(w, args, j);
\r
685 if (strcmp(name, "close") == 0) {
\r
686 EngineOutputPopDown();
\r
687 } else if (strcmp(name, "edit") == 0) {
\r
688 EngineOutputPopDown();
\r
689 EditCommentEvent();
\r
695 // This seems pure front end
\r
696 LRESULT CALLBACK EngineOutputProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
\r
698 static SnapData sd;
\r
701 case WM_INITDIALOG:
\r
702 if( engineOutputDialog == NULL ) {
\r
703 engineOutputDialog = hDlg;
\r
705 RestoreWindowPlacement( hDlg, &wpEngineOutput ); /* Restore window placement */
\r
707 ResizeWindowControls( hDlg, windowMode );
\r
709 SetEngineState( 0, STATE_IDLE, "" );
\r
710 SetEngineState( 1, STATE_IDLE, "" );
\r
716 switch (LOWORD(wParam)) {
\r
718 EndDialog(hDlg, TRUE);
\r
722 EndDialog(hDlg, FALSE);
\r
731 case WM_GETMINMAXINFO:
\r
733 MINMAXINFO * mmi = (MINMAXINFO *) lParam;
\r
735 mmi->ptMinTrackSize.x = 100;
\r
736 mmi->ptMinTrackSize.y = 160;
\r
741 EngineOutputPopDown();
\r
745 ResizeWindowControls( hDlg, windowMode );
\r
748 case WM_ENTERSIZEMOVE:
\r
749 return OnEnterSizeMove( &sd, hDlg, wParam, lParam );
\r
752 return OnSizing( &sd, hDlg, wParam, lParam );
\r
755 return OnMoving( &sd, hDlg, wParam, lParam );
\r
757 case WM_EXITSIZEMOVE:
\r
758 return OnExitSizeMove( &sd, hDlg, wParam, lParam );
\r
765 void EngineOutputPopUp(title, text)
\r
766 char *title, *text;
\r
772 if (engineOutputShell == NULL) {
\r
773 engineOutputShell =
\r
774 EngineOutputCreate(title, text);
\r
775 XtRealizeWidget(engineOutputShell);
\r
776 CatchDeleteWindow(engineOutputShell, "EngineOutputPopDown");
\r
778 InitializeEngineOutput();
\r
779 needInit = FALSE;
\r }
\r
780 SetEngineColorIcon( 0 );
\r
781 SetEngineColorIcon( 1 );
\r
782 SetEngineState( 0, STATE_IDLE, "" );
\r
783 SetEngineState( 1, STATE_IDLE, "" );
\r
785 edit = XtNameToWidget(engineOutputShell, "*form.text");
\r
787 XtSetArg(args[j], XtNstring, text); j++;
\r
788 XtSetValues(edit, args, j);
\r
790 XtSetArg(args[j], XtNiconName, (XtArgVal) title); j++;
\r
791 XtSetArg(args[j], XtNtitle, (XtArgVal) title); j++;
\r
792 XtSetValues(engineOutputShell, args, j);
\r
795 XtPopup(engineOutputShell, XtGrabNone);
\r
796 XSync(xDisplay, False);
\r
799 XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
800 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
803 engineOutputDialogUp = True;
\r
804 ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
809 void EngineOutputPopUp()
\r
813 CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_CHECKED);
\r
815 if( engineOutputDialog ) {
\r
816 SendMessage( engineOutputDialog, WM_INITDIALOG, 0, 0 );
\r
818 if( ! engineOutputDialogUp ) {
\r
819 ShowWindow(engineOutputDialog, SW_SHOW);
\r
823 lpProc = MakeProcInstance( (FARPROC) EngineOutputProc, hInst );
\r
825 /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */
\r
826 CreateDialog( hInst, MAKEINTRESOURCE(DLG_EngineOutput), hwndMain, (DLGPROC)lpProc );
\r
828 FreeProcInstance(lpProc);
\r
831 // [HGM] displaced to after creation of dialog, to allow initialization of output fields
\r
833 InitializeEngineOutput();
\r
837 engineOutputDialogUp = TRUE;
\r
841 void EngineOutputPopDown()
\r
846 if (!engineOutputDialogUp) return;
\r
848 XtSetArg(args[j], XtNx, &engineOutputX); j++;
\r
849 XtSetArg(args[j], XtNy, &engineOutputY); j++;
\r
850 XtSetArg(args[j], XtNwidth, &engineOutputW); j++;
\r
851 XtSetArg(args[j], XtNheight, &engineOutputH); j++;
\r
852 XtGetValues(engineOutputShell, args, j);
\r
853 XtPopdown(engineOutputShell);
\r
854 XSync(xDisplay, False);
856 XtSetArg(args[j], XtNleftBitmap, None); j++;
857 XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Engine Output"),
860 engineOutputDialogUp = False;
\r
861 ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
866 void EngineOutputPopDown()
\r
868 CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_UNCHECKED);
\r
870 if( engineOutputDialog ) {
\r
871 ShowWindow(engineOutputDialog, SW_HIDE);
\r
874 engineOutputDialogUp = FALSE;
\r
877 // front end. [HGM] Takes handle of output control from table, so only number is passed
\r
878 void DoClearMemo(int which)
\r
880 SendMessage( outputField[which][nMemo], WM_SETTEXT, 0, (LPARAM) "" );
\r
884 //------------------------ pure back-end routines -------------------------------
\r
887 // back end, due to front-end wrapper for SetWindowText, and new SetIcon arguments
\r
888 static SetEngineState( int which, int state, char * state_data )
\r
890 int x_which = 1 - which;
\r
892 if( engineState[ which ] != state ) {
\r
893 engineState[ which ] = state;
\r
896 case STATE_THINKING:
\r
897 SetIcon( which, nStateIcon, nThinking );
\r
898 if( engineState[ x_which ] == STATE_THINKING ) {
\r
899 SetEngineState( x_which, STATE_IDLE, "" );
\r
902 case STATE_PONDERING:
\r
903 SetIcon( which, nStateIcon, nPondering );
\r
905 case STATE_ANALYZING:
\r
906 SetIcon( which, nStateIcon, nAnalyzing );
\r
909 SetIcon( which, nStateIcon, nClear );
\r
914 if( state_data != 0 ) {
\r
915 DoSetWindowText( which, nStateData, state_data );
\r
919 // back end, now the front-end wrapper ClearMemo is used, and ed no longer contains handles.
\r
920 void EngineOutputUpdate( FrontEndProgramStats * stats )
\r
922 EngineOutputData ed;
\r
923 int clearMemo = FALSE;
\r
928 SetEngineState( 0, STATE_IDLE, "" );
\r
929 SetEngineState( 1, STATE_IDLE, "" );
\r
933 which = stats->which;
\r
934 depth = stats->depth;
\r
936 if( which < 0 || which > 1 || depth < 0 || stats->time < 0 || stats->pv == 0 ) {
\r
940 if( engineOutputShell == NULL ) {
\r
944 VerifyDisplayMode();
\r
948 ed.nodes = stats->nodes;
\r
949 ed.score = stats->score;
\r
950 ed.time = stats->time;
\r
952 ed.hint = stats->hint;
\r
953 ed.an_move_index = stats->an_move_index;
\r
954 ed.an_move_count = stats->an_move_count;
\r
956 /* Get target control. [HGM] this is moved to front end, which get them from a table */
\r
958 ed.name = first.tidy;
\r
961 ed.name = second.tidy;
\r
964 /* Clear memo if needed */
\r
965 if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) {
\r
969 if( lastForwardMostMove[which] != forwardMostMove ) {
\r
973 if( clearMemo ) DoClearMemo(which);
\r
976 lastDepth[which] = depth;
\r
977 lastForwardMostMove[which] = forwardMostMove;
\r
979 if( ed.pv != 0 && ed.pv[0] == ' ' ) {
\r
980 if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */
\r
985 UpdateControls( &ed );
\r
988 #define ENGINE_COLOR_WHITE 'w'
\r
989 #define ENGINE_COLOR_BLACK 'b'
\r
990 #define ENGINE_COLOR_UNKNOWN ' '
\r
993 char GetEngineColor( int which )
\r
995 char result = ENGINE_COLOR_UNKNOWN;
\r
997 if( which == 0 || which == 1 ) {
\r
998 ChessProgramState * cps;
\r
1000 switch (gameMode) {
\r
1001 case MachinePlaysBlack:
\r
1002 case IcsPlayingBlack:
\r
1003 result = ENGINE_COLOR_BLACK;
\r
1005 case MachinePlaysWhite:
\r
1006 case IcsPlayingWhite:
\r
1007 result = ENGINE_COLOR_WHITE;
\r
1011 result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
\r
1013 case TwoMachinesPlay:
\r
1014 cps = (which == 0) ? &first : &second;
\r
1015 result = cps->twoMachinesColor[0];
\r
1016 result = result == 'w' ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
\r
1025 char GetActiveEngineColor()
\r
1027 char result = ENGINE_COLOR_UNKNOWN;
\r
1029 if( gameMode == TwoMachinesPlay ) {
\r
1030 result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
\r
1037 static int IsEnginePondering( int which )
\r
1039 int result = FALSE;
\r
1041 switch (gameMode) {
\r
1042 case MachinePlaysBlack:
\r
1043 case IcsPlayingBlack:
\r
1044 if( WhiteOnMove(forwardMostMove) ) result = TRUE;
\r
1046 case MachinePlaysWhite:
\r
1047 case IcsPlayingWhite:
\r
1048 if( ! WhiteOnMove(forwardMostMove) ) result = TRUE;
\r
1050 case TwoMachinesPlay:
\r
1051 if( GetActiveEngineColor() != ENGINE_COLOR_UNKNOWN ) {
\r
1052 if( GetEngineColor( which ) != GetActiveEngineColor() ) result = TRUE;
\r
1061 static void SetDisplayMode( int mode )
\r
1063 if( windowMode != mode ) {
\r
1064 windowMode = mode;
\r
1066 ResizeWindowControls( engineOutputShell, mode );
\r
1071 static VerifyDisplayMode()
\r
1075 /* Get proper mode for current game */
\r
1076 switch( gameMode ) {
\r
1079 case MachinePlaysWhite:
\r
1080 case MachinePlaysBlack:
\r
1081 case IcsPlayingWhite:
\r
1082 case IcsPlayingBlack:
\r
1085 case TwoMachinesPlay:
\r
1089 /* Do not change */
\r
1093 SetDisplayMode( mode );
\r
1096 // back end. Determine what icon to se in the color-icon field, and print it
\r
1097 static void SetEngineColorIcon( int which )
\r
1099 char color = GetEngineColor(which);
\r
1102 if( color == ENGINE_COLOR_BLACK )
\r
1103 nicon = nColorBlack;
\r
1104 else if( color == ENGINE_COLOR_WHITE )
\r
1105 nicon = nColorWhite;
\r
1107 nicon = nColorUnknown;
\r
1109 SetIcon( which, nColorIcon, nicon );
\r
1112 #define MAX_NAME_LENGTH 32
\r
1114 // pure back end, now SetWindowText is called via wrapper DoSetWindowText
\r
1115 static void UpdateControls( EngineOutputData * ed )
\r
1117 int isPondering = FALSE;
\r
1119 char s_label[MAX_NAME_LENGTH + 32];
\r
1121 char * name = ed->name;
\r
1124 if( name == 0 || *name == '\0' ) {
\r
1128 strncpy( s_label, name, MAX_NAME_LENGTH );
\r
1129 s_label[ MAX_NAME_LENGTH-1 ] = '\0';
\r
1131 #ifdef SHOW_PONDERING
\r
1132 if( IsEnginePondering( ed->which ) ) {
\r
1137 if( ed->hint != 0 && *ed->hint != '\0' ) {
\r
1138 strncpy( buf, ed->hint, sizeof(buf) );
\r
1139 buf[sizeof(buf)-1] = '\0';
\r
1141 else if( ed->pv != 0 && *ed->pv != '\0' ) {
\r
1142 char * sep = strchr( ed->pv, ' ' );
\r
1143 int buflen = sizeof(buf);
\r
1145 if( sep != NULL ) {
\r
1146 buflen = sep - ed->pv + 1;
\r
1147 if( buflen > sizeof(buf) ) buflen = sizeof(buf);
\r
1150 strncpy( buf, ed->pv, buflen );
\r
1151 buf[ buflen-1 ] = '\0';
\r
1154 SetEngineState( ed->which, STATE_PONDERING, buf );
\r
1156 else if( gameMode == TwoMachinesPlay ) {
\r
1157 SetEngineState( ed->which, STATE_THINKING, "" );
\r
1159 else if( gameMode == AnalyzeMode || gameMode == AnalyzeFile ) {
\r
1161 int time_secs = ed->time / 100;
\r
1162 int time_mins = time_secs / 60;
\r
1166 if( ed->an_move_index != 0 && ed->an_move_count != 0 && *ed->hint != '\0' ) {
\r
1169 strncpy( mov, ed->hint, sizeof(mov) );
\r
1170 mov[ sizeof(mov)-1 ] = '\0';
\r
1172 sprintf( buf, "%d/%d: %s [%02d:%02d:%02d]", ed->an_move_index, ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );
\r
1175 SetEngineState( ed->which, STATE_ANALYZING, buf );
\r
1178 SetEngineState( ed->which, STATE_IDLE, "" );
\r
1182 DoSetWindowText( ed->which, nLabel, s_label );
\r
1184 s_label[0] = '\0';
\r
1186 if( ed->time > 0 && ed->nodes > 0 ) {
\r
1187 unsigned long nps_100 = ed->nodes / ed->time;
\r
1189 if( nps_100 < 100000 ) {
\r
1190 sprintf( s_label, "NPS: %lu", nps_100 * 100 );
\r
1193 sprintf( s_label, "NPS: %.1fk", nps_100 / 10.0 );
\r
1197 DoSetWindowText( ed->which, nLabelNPS, s_label );
\r
1200 if( ed->pv != 0 && *ed->pv != '\0' ) {
\r
1206 int time_secs = ed->time / 100;
\r
1207 int time_cent = ed->time % 100;
\r
1210 if( ed->nodes < 1000000 ) {
\r
1211 sprintf( s_nodes, "%lu", ed->nodes );
\r
1214 sprintf( s_nodes, "%.1fM", ed->nodes / 1000000.0 );
\r
1218 if( ed->score > 0 ) {
\r
1219 sprintf( s_score, "+%.2f", ed->score / 100.0 );
\r
1221 sprintf( s_score, "%.2f", ed->score / 100.0 );
\r
1224 sprintf( s_time, "%d:%02d.%02d", time_secs / 60, time_secs % 60, time_cent );
\r
1226 /* Put all together... */
\r
1227 sprintf( buf, "%3d %s %s\t%s\t", ed->depth, s_score, s_nodes, s_time );
\r
1230 buflen = strlen(buf);
\r
1232 strncpy( buf + buflen, ed->pv, sizeof(buf) - buflen );
\r
1234 buf[ sizeof(buf) - 3 ] = '\0';
\r
1236 strcat( buf + buflen, "\n" );
\r
1239 InsertIntoMemo( ed->which, buf );
\r
1243 SetEngineColorIcon( ed->which );
\r
1247 int EngineOutputIsUp()
\r
1249 return engineOutputDialogUp;
\r
1253 EngineOutputProc(w, event, prms, nprms)
1259 if (engineOutputDialogUp) {
1260 EngineOutputPopDown();
1262 EngineOutputPopUp("engine output","This feature is experimental");
1264 // ToNrEvent(currentMove);