converted xhistory via dos2unix
[xboard.git] / xhistory.c
1 /*
2  * xhistory.c -- Move list window, part of X front end for XBoard
3  * $Id$
4  *
5  * Copyright 2000,2009 Free Software Foundation, Inc.
6  * ------------------------------------------------------------------------
7  *
8  * GNU XBoard is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or (at
11  * your option) any later version.
12  *
13  * GNU XBoard is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see http://www.gnu.org/licenses/.  *
20  *
21  *------------------------------------------------------------------------
22  ** See the file ChangeLog for a revision history.  */
23
24 #include "config.h"
25
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #include <sys/types.h>
30
31 #if STDC_HEADERS
32 # include <stdlib.h>
33 # include <string.h>
34 #else /* not STDC_HEADERS */
35 extern char *getenv();
36 # if HAVE_STRING_H
37 #  include <string.h>
38 # else /* not HAVE_STRING_H */
39 #  include <strings.h>
40 # endif /* not HAVE_STRING_H */
41 #endif /* not STDC_HEADERS */
42
43 #if HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46
47 #include <X11/Intrinsic.h>
48 #include <X11/StringDefs.h>
49 #include <X11/Shell.h>
50 #include <X11/Xaw/Dialog.h>
51 #include <X11/Xaw/Form.h>
52 #include <X11/Xaw/List.h>
53 #include <X11/Xaw/Label.h>
54 #include <X11/Xaw/SimpleMenu.h>
55 #include <X11/Xaw/SmeBSB.h>
56 #include <X11/Xaw/SmeLine.h>
57 #include <X11/Xaw/Box.h>
58 #include <X11/Xaw/Paned.h>
59 #include <X11/Xaw/MenuButton.h>
60 #include <X11/cursorfont.h>
61 #include <X11/Xaw/Text.h>
62 #include <X11/Xaw/AsciiText.h>
63 #include <X11/Xaw/Viewport.h>
64
65 #include "common.h"
66 #include "frontend.h"
67 #include "backend.h"
68 #include "xboard.h"
69 #include "xhistory.h"
70 #include "gettext.h"
71
72 #ifdef ENABLE_NLS
73 # define  _(s) gettext (s)
74 # define N_(s) gettext_noop (s)
75 #else
76 # define  _(s) (s)
77 # define N_(s)  s
78 #endif
79
80 #define _LL_ 100
81
82 extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;
83 extern Display *xDisplay;
84 extern int squareSize;
85 extern Pixmap xMarkPixmap;
86 extern char *layoutName;
87
88 struct History{
89   String *Nr,*white,*black;
90   int     aNr;  /* space actually alocated */
91   Widget mvn,mvw,mvb,vbox,viewport,sh;
92   char Up;
93 };
94
95 struct History *hist=0;
96 String dots=" ... ";
97 Position gameHistoryX, gameHistoryY;
98
99 void
100 HistoryPopDown(w, client_data, call_data)
101      Widget w;
102      XtPointer client_data, call_data;
103 {
104   Arg args[16];
105   int j;
106   if(hist) {
107     // [HGM] remember old position
108     j = 0;
109     XtSetArg(args[j], XtNx, &gameHistoryX);  j++;
110     XtSetArg(args[j], XtNy, &gameHistoryY);  j++;
111     XtGetValues(hist->sh, args, j);
112
113     XtPopdown(hist->sh);
114     hist->Up=False;
115   }
116   j=0;
117   XtSetArg(args[j], XtNleftBitmap, None); j++;
118   XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Move History"),
119                 args, j);
120 }
121
122 void HistoryMoveProc(Widget w, XtPointer closure, XtPointer call_data)
123 {
124     int to;
125     XawListReturnStruct *R = (XawListReturnStruct *) call_data;
126     if (w == hist->mvn || w == hist->mvw) {
127       to=2*R->list_index-1;
128       ToNrEvent(to);
129     }
130     else if (w == hist->mvb) {
131       to=2*R->list_index;
132       ToNrEvent(to);
133     }
134 }
135
136 void HistoryAlloc(int len){
137   int i;
138   if(hist){
139     free(hist->Nr[0]);free(hist->white[0]);free(hist->black[0]);
140     free(hist->Nr);free(hist->white);free(hist->black);
141   }
142   else{
143     hist=(struct History*)malloc(sizeof(struct History));
144   }
145     hist->aNr=len;
146     hist->Nr=(String*)malloc(hist->aNr*sizeof(String*));
147     hist->white=(String*)malloc(hist->aNr*sizeof(String*));
148     hist->black=(String*)malloc(hist->aNr*sizeof(String*));
149
150     hist->Nr[0]=(String)malloc(hist->aNr*6);
151     hist->white[0]=(String)malloc(hist->aNr*MOVE_LEN);
152     hist->black[0]=(String)malloc(hist->aNr*MOVE_LEN);
153
154       sprintf(hist->Nr[0],"    ");
155       sprintf(hist->white[0],_("White "));
156       sprintf(hist->black[0],_("Black "));
157     for(i=1;i<hist->aNr;i++){
158       hist->Nr[i]= hist->Nr[i-1]+6;
159       hist->white[i]= hist->white[i-1]+MOVE_LEN;
160       hist->black[i]= hist->black[i-1]+MOVE_LEN;
161       sprintf(hist->Nr[i],"%i.",i);
162       sprintf(hist->white[i],"-----");
163       sprintf(hist->black[i],"-----");
164      }
165 }
166
167
168 #if 1
169 /* Find empty space inside vbox form widget and redistribute it amongst
170    the list widgets inside it. */
171 /* This version sort of works */
172 void
173 HistoryFill()
174 {
175   Dimension w, bw;
176   long extra;
177   Position x, x1, x2;
178   int j, dd;
179   Arg args[16];
180
181   j = 0;
182   XtSetArg(args[j], XtNx, &x);  j++;
183   XtSetArg(args[j], XtNwidth, &w);  j++;
184   XtSetArg(args[j], XtNborderWidth, &bw);  j++;
185   XtGetValues(hist->mvb, args, j);
186   x1 = x + w + 2*bw;
187
188   j = 0;
189   XtSetArg(args[j], XtNwidth, &w);  j++;
190   XtSetArg(args[j], XtNdefaultDistance, &dd);  j++;
191   XtGetValues(hist->vbox, args, j);
192   x2 = w - dd;
193
194   extra = x2 - x1;
195   if (extra < 0) {
196     extra = -((-extra)/2);
197   } else {
198     extra = extra/2;
199   }
200
201   j = 0;
202   XtSetArg(args[j], XtNwidth, &w);  j++;
203   XtGetValues(hist->mvw, args, j);
204   w += extra;
205   j = 0;
206   XtSetArg(args[j], XtNwidth, w);  j++;
207   XtSetValues(hist->mvw, args, j);
208
209   j = 0;
210   XtSetArg(args[j], XtNwidth, &w);  j++;
211   XtGetValues(hist->mvb, args, j);
212   w += extra;
213   j = 0;
214   XtSetArg(args[j], XtNwidth, w);  j++;
215   XtSetValues(hist->mvb, args, j);
216 }
217 #else
218 /* Find empty space inside vbox form widget and redistribute it amongst
219    the list widgets inside it. */
220 /* This version doesn't work */
221 void
222 HistoryFill()
223 {
224   Arg args[16];
225   Dimension fw, niw, wiw, biw, nbw, wbw, bbw;
226   int j, nl, wl, bl, fdd;
227   long extra;
228
229   j = 0;
230   XtSetArg(args[j], XtNwidth, &fw);  j++;
231   XtSetArg(args[j], XtNdefaultDistance, &fdd);  j++;
232   XtGetValues(hist->vbox, args, j);
233
234   j = 0;
235   XtSetArg(args[j], XtNlongest, &nl);  j++;
236   XtSetArg(args[j], XtNinternalWidth, &niw);  j++;
237   XtSetArg(args[j], XtNborderWidth, &nbw);  j++;
238   XtGetValues(hist->mvn, args, j);
239
240   j = 0;
241   XtSetArg(args[j], XtNlongest, &wl);  j++;
242   XtSetArg(args[j], XtNinternalWidth, &wiw);  j++;
243   XtSetArg(args[j], XtNborderWidth, &wbw);  j++;
244   XtGetValues(hist->mvw, args, j);
245
246   j = 0;
247   XtSetArg(args[j], XtNlongest, &bl);  j++;
248   XtSetArg(args[j], XtNinternalWidth, &biw);  j++;
249   XtSetArg(args[j], XtNborderWidth, &bbw);  j++;
250   XtGetValues(hist->mvb, args, j);
251
252   extra = fw - 4*fdd -
253     nl - 1 - 2*niw - 2*nbw - wl - 2*wiw - 2*wbw - bl - 2*biw - 2*bbw;
254   if (extra < 0) extra = 0;
255
256   j = 0;
257   XtSetArg(args[j], XtNwidth, nl + 1 + 2*niw);  j++;
258   XtSetValues(hist->mvn, args, j);
259
260   j = 0;
261   XtSetArg(args[j], XtNwidth, wl + 2*wiw + extra/2);  j++;
262   XtSetValues(hist->mvw, args, j);
263
264   j = 0;
265   XtSetArg(args[j], XtNwidth, bl + 2*biw + extra/2);  j++;
266   XtSetValues(hist->mvb, args, j);
267 }
268 #endif
269
270 void HistorySet(char movelist[][2*MOVE_LEN],int first,int last,int current){
271   int i,b,m;
272   if(hist){
273     if(last >= hist->aNr) HistoryAlloc(last+_LL_);
274     for(i=0;i<last;i++) {
275       if((i%2)==0) {
276         if(movelist[i][0]) {
277           char* p = strchr(movelist[i], ' ');
278           if (p) {
279             strncpy(hist->white[i/2+1], movelist[i], p-movelist[i]);
280             hist->white[i/2+1][p-movelist[i]] = NULLCHAR;
281           } else {
282             strcpy(hist->white[i/2+1],movelist[i]);
283           }
284         } else {
285           strcpy(hist->white[i/2+1],dots);
286         }
287       } else {
288         if(movelist[i][0]) {
289           char* p = strchr(movelist[i], ' ');
290           if (p) {
291             strncpy(hist->black[i/2+1], movelist[i], p-movelist[i]);
292             hist->black[i/2+1][p-movelist[i]] = NULLCHAR;
293           } else {
294             strcpy(hist->black[i/2+1],movelist[i]);
295           }
296         } else {
297           strcpy(hist->black[i/2+1],"");
298         }
299       }
300     }
301     strcpy(hist->black[last/2+1],"");
302     b=first/2;
303     m=(last+3)/2-b;
304     XawFormDoLayout(hist->vbox, False);
305     XawListChange(hist->mvn,hist->Nr+b,m,0,True);
306     XawListChange(hist->mvw,hist->white+b,m,0,True);
307     XawListChange(hist->mvb,hist->black+b,m,0,True);
308     HistoryFill();
309     XawFormDoLayout(hist->vbox, True);
310     if(current<0){
311       XawListUnhighlight(hist->mvw);
312       XawListUnhighlight(hist->mvb);
313     }
314     else if((current%2)==0){
315       XawListHighlight(hist->mvw, current/2+1);
316       XawListUnhighlight(hist->mvb);
317     }
318     else{
319       XawListUnhighlight(hist->mvw);
320       if(current) XawListHighlight(hist->mvb, current/2+1);
321       else XawListUnhighlight(hist->mvb);
322     }
323   }
324 }
325
326 Widget HistoryCreate()
327 {
328     Arg args[16];
329     int i,j;
330
331     Widget layout,form,b_close;
332     String trstr=
333              "<Key>Up: BackwardProc() \n \
334              <Key>Left: BackwardProc() \n \
335              <Key>Down: ForwardProc() \n \
336              <Key>Right: ForwardProc() \n";
337     /*--- allocate memory for move-strings ---*/
338     HistoryAlloc(_LL_);
339
340     /*-------- create the widgets ---------------*/
341     j = 0;
342     XtSetArg(args[j], XtNresizable, True);  j++;
343     XtSetArg(args[j], XtNallowShellResize, True);  j++;
344 #if TOPLEVEL
345     hist->sh =
346       XtCreatePopupShell(_("Move list"), topLevelShellWidgetClass,
347                          shellWidget, args, j);
348 #else
349     hist->sh =
350       XtCreatePopupShell(_("Move list"), transientShellWidgetClass,
351                          shellWidget, args, j);
352 #endif
353     j = 0;
354     XtSetArg(args[j], XtNborderWidth, 0); j++;
355     XtSetArg(args[j], XtNdefaultDistance, 0);  j++;
356       layout =
357       XtCreateManagedWidget(layoutName, formWidgetClass, hist->sh,
358                             args, j);
359
360     j = 0;
361     XtSetArg(args[j], XtNborderWidth, 0); j++;
362     XtSetArg(args[j], XtNresizable, True);  j++;
363
364     form =
365       XtCreateManagedWidget("form", formWidgetClass, layout, args, j);
366      j=0;
367
368     j = 0;
369
370     XtSetArg(args[j], XtNtop, XtChainTop);  j++;
371     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
372     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
373     XtSetArg(args[j], XtNright, XtChainRight);  j++;
374
375     XtSetArg(args[j], XtNborderWidth, 1); j++;
376     XtSetArg(args[j], XtNresizable, False);  j++;
377     XtSetArg(args[j], XtNallowVert, True); j++;
378     XtSetArg(args[j], XtNallowHoriz, True);  j++;
379     XtSetArg(args[j], XtNforceBars, False); j++;
380     XtSetArg(args[j], XtNheight, 280); j++;
381     hist->viewport =
382       XtCreateManagedWidget("viewport", viewportWidgetClass,
383                             form, args, j);
384     j=0;
385     XtSetArg(args[j], XtNborderWidth, 0); j++;
386     XtSetArg(args[j], XtNorientation,XtorientHorizontal);j++;
387     hist->vbox =
388       XtCreateManagedWidget("vbox", formWidgetClass, hist->viewport, args, j);
389
390     j=0;
391     XtSetArg(args[j], XtNtop, XtChainTop);  j++;
392     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
393     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
394     XtSetArg(args[j], XtNright, XtChainLeft);  j++;
395
396     XtSetArg(args[j], XtNdefaultColumns, 1);  j++;
397     XtSetArg(args[j], XtNforceColumns, True);  j++;
398     XtSetArg(args[j], XtNverticalList, True);  j++;
399     XtSetArg(args[j], XtNborderWidth, 0); j++;
400     XtSetArg(args[j], XtNresizable,True);j++;
401     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
402     hist->mvn = XtCreateManagedWidget("movesn", listWidgetClass,
403                                       hist->vbox, args, j);
404     XtAddCallback(hist->mvn, XtNcallback, HistoryMoveProc, (XtPointer) hist);
405
406     j=0;
407     XtSetArg(args[j], XtNtop, XtChainTop);  j++;
408     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
409     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
410     XtSetArg(args[j], XtNright, XtRubber);  j++;
411
412     XtSetArg(args[j], XtNdefaultColumns, 1);  j++;
413     XtSetArg(args[j], XtNforceColumns, True);  j++;
414     XtSetArg(args[j], XtNverticalList, True);  j++;
415     XtSetArg(args[j], XtNborderWidth, 0); j++;
416     XtSetArg(args[j], XtNresizable,True);j++;
417     XtSetArg(args[j], XtNfromHoriz, hist->mvn);  j++;
418     hist->mvw = XtCreateManagedWidget("movesw", listWidgetClass,
419                                       hist->vbox, args, j);
420     XtAddCallback(hist->mvw, XtNcallback, HistoryMoveProc, (XtPointer) hist);
421
422     j=0;
423     XtSetArg(args[j], XtNtop, XtChainTop);  j++;
424     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
425     XtSetArg(args[j], XtNleft, XtRubber);  j++;
426     XtSetArg(args[j], XtNright,  XtRubber);  j++;
427
428     XtSetArg(args[j], XtNdefaultColumns, 1);  j++;
429     XtSetArg(args[j], XtNforceColumns, True);  j++;
430     XtSetArg(args[j], XtNverticalList, True);  j++;
431     XtSetArg(args[j], XtNborderWidth, 0); j++;
432     XtSetArg(args[j], XtNresizable,True);j++;
433     XtSetArg(args[j], XtNfromHoriz, hist->mvw);  j++;
434     hist->mvb = XtCreateManagedWidget("movesb", listWidgetClass,
435                                       hist->vbox, args, j);
436     XtAddCallback(hist->mvb, XtNcallback, HistoryMoveProc, (XtPointer) hist);
437
438     j=0;
439     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
440     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
441     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
442     XtSetArg(args[j], XtNright, XtChainLeft);  j++;
443     XtSetArg(args[j], XtNfromVert, hist->viewport);  j++;
444     b_close= XtCreateManagedWidget(_("Close"), commandWidgetClass,
445                                    form, args, j);
446     XtAddCallback(b_close, XtNcallback, HistoryPopDown, (XtPointer) 0);
447
448     XtAugmentTranslations(hist->sh,XtParseTranslationTable (trstr));
449
450     XtRealizeWidget(hist->sh);
451     CatchDeleteWindow(hist->sh, "HistoryPopDown");
452
453     for(i=1;i<hist->aNr;i++){
454       strcpy(hist->white[i],dots);
455       strcpy(hist->black[i],"");
456      }
457
458     return hist->sh;
459 }
460
461 void
462 HistoryPopUp()
463 {
464   Arg args[16];
465   int j;
466
467   if(!hist) HistoryCreate();
468
469   XtPopup(hist->sh, XtGrabNone);
470
471   // [HGM] restore old position
472   j = 0;
473   XtSetArg(args[j], XtNx, gameHistoryX);  j++;
474   XtSetArg(args[j], XtNy, gameHistoryY);  j++;
475   XtSetValues(hist->sh, args, j);
476
477   j=0;
478   XtSetArg(args[j], XtNleftBitmap, xMarkPixmap); j++;
479   XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Show Move History"),
480                 args, j);
481   hist->Up=True;
482 }
483
484
485 void
486 HistoryShowProc(w, event, prms, nprms)
487      Widget w;
488      XEvent *event;
489      String *prms;
490      Cardinal *nprms;
491 {
492   if (!hist) {
493     HistoryCreate();
494     HistoryPopUp();
495   } else if (hist->Up) {
496     HistoryPopDown(0,0,0);
497   } else {
498     HistoryPopUp();
499   }
500   ToNrEvent(currentMove);
501 }
502