1 /*
2  * Copyright (C) 1996 by Rob McMullen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  *
19  * Author: Rob McMullen <rwmcm@orion.ae.utexas.edu>
20  *         http://www.ae.utexas.edu/~rwmcm
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <time.h>
29 #include <X11/Intrinsic.h>
30 #include <X11/Shell.h>
31 #include <X11/StringDefs.h>
32 #include <Xm/Xm.h>
33 #include <Xm/Label.h>
34 #include <Xm/TextF.h>
35 #include <Xm/RowColumn.h>
36 #include <Xm/Form.h>
37 #include <Xm/PushB.h>
38 #include <Xm/DialogS.h>
39 #include <Xm/MainW.h>
40 #include <Xm/PanedW.h>
41 
42 #include "SciPlot.h"
43 
44 /* Globals */
45 static int DialogCount=0;		/* Number of dialogs on screen */
46 
47 
48 typedef struct {
49   char *text;
50   int num;
51 } textnumpair;
52 
53 textnumpair colors_list[] =
54 {
55   {"blue", 0},
56   {"red", 0},
57   {"ForestGreen", 0},
58   {"DarkGoldenrod", 0},
59   {"orange", 0},
60   {"magenta", 0},
61   {"grey", 0},
62   {"purple", 0},
63 };
64 
65 #define NUM_COLORS 8
66 
67 textnumpair marker_list[] =
68 {
69   {"XtMARKER_SQUARE", XtMARKER_SQUARE},
70   {"XtMARKER_CIRCLE", XtMARKER_CIRCLE},
71   {"XtMARKER_UTRIANG ", XtMARKER_UTRIANGLE},
72   {"XtMARKER_DTRIANG ", XtMARKER_DTRIANGLE},
73   {"XtMARKER_DIAMOND", XtMARKER_DIAMOND},
74   {"XtMARKER_HOURGLA ", XtMARKER_HOURGLASS},
75   {"XtMARKER_BOWTIE", XtMARKER_BOWTIE},
76   {"XtMARKER_LTRIANG ", XtMARKER_LTRIANGLE},
77   {"XtMARKER_RTRIANG", XtMARKER_RTRIANGLE},
78   {"XtMARKER_FCIRCLE ", XtMARKER_FCIRCLE},
79   {"XtMARKER_FSQUARE", XtMARKER_FSQUARE},
80   {"XtMARKER_FUTRIAN", XtMARKER_FUTRIANGLE},
81   {"XtMARKER_FDTRIAN ", XtMARKER_FDTRIANGLE},
82   {"XtMARKER_FDIAMON ", XtMARKER_FDIAMOND},
83   {"XtMARKER_FHOURGL", XtMARKER_FHOURGLASS},
84   {"XtMARKER_FBOWTIE", XtMARKER_FBOWTIE},
85   {"XtMARKER_FLTRIAN", XtMARKER_FLTRIANGLE},
86   {"XtMARKER_FRTRIAN", XtMARKER_FRTRIANGLE}
87 };
88 
89 #define NUM_MARKERS 18
90 
91 
92 /* String Utilities */
93 
94 #ifndef TRUE
95 #define TRUE    1
96 #endif
97 
98 #ifndef FALSE
99 #define FALSE   0
100 #endif
101 
102 #define MAXFIELD 40
103 #define STRING_MAX 63
104 
105 char	field[MAXFIELD][STRING_MAX+1];
106 float	ffield[MAXFIELD];
107 
108 #define PARSE_SEPARATORS	",= \t\n"
109 
110 static void
upper(char * str)111 upper(char *str)
112 {
113   int i;
114   char *dest;
115 
116   dest = str;
117   for (i = strlen(str); i > 0; i--) {
118     if (*str != ' ')
119       *dest++ = toupper(*str);
120     str++;
121   }
122   *dest = (char) 0;
123 }
124 
125 static char *
strparse(char * str,char * primary)126 strparse(char *str, char *primary)
127 {
128   static int start, len;
129   static char *save;
130   static char quotes[] = "'\"";
131   int skip, i, plen, qlen;
132   char c, *begin;
133 
134   if (primary) {
135     if (str) {
136       save = str;
137       len = strlen(str);
138       start = 0;
139     }
140     if (start >= len)
141       return NULL;
142     plen = strlen(primary);
143     qlen = strlen(quotes);
144 
145 /* find first valid character: */
146     skip = TRUE;
147     while ((start < len) && (skip)) {
148       c = save[start];
149       skip = FALSE;
150       for (i = 0; i < plen; i++) {
151         if (c == primary[i]) {
152           skip = TRUE;
153           break;
154         }
155       }
156       if (skip)
157         start++;
158     }
159     if (start >= len)
160       return NULL;
161 
162     begin = &save[start];
163 
164 /* OK, are pointing to first delimeter */
165 
166     if (*begin == '\"') {
167       begin++;
168       start++;
169       while (start < len) {
170         c = save[start];
171         if (c == '\"') {
172           save[start] = '\0';
173           start++;
174           break;
175         }
176         else if (c == '\0') {
177           break;
178         }
179         start++;
180       }
181     }
182     else {
183       skip = FALSE;
184       while ((start < len) && (!skip)) {
185         c = save[start];
186         skip = FALSE;
187         for (i = 0; i < plen; i++)
188           if (c == primary[i]) {
189             skip = TRUE;
190             break;
191           }
192         if (skip) {
193           save[start] = '\0';
194           start++;
195           break;
196         }
197         else
198           start++;
199       }
200     }
201     return begin;
202   }
203   return NULL;
204 }
205 
206 static int
sepfield(char * str,int count)207 sepfield(char *str, int count)
208 {
209   char *ptr, *end;
210   char tmpval[1024];
211 
212   strcpy(tmpval, str);
213   ptr = strchr(tmpval, '#');
214   end = tmpval + strlen(tmpval);
215   if (ptr)
216     *ptr = (char) 0;
217   ptr = strparse(tmpval, PARSE_SEPARATORS);
218   while (ptr) {
219     strncpy(field[count], ptr, STRING_MAX - 1);
220     field[count][STRING_MAX - 1] = (char) 0;
221     count++;
222     ptr = strparse((char *) NULL, PARSE_SEPARATORS);
223   }
224 #ifdef DEBUG
225   printf("sepfield: %d\t", count);
226   for (j = 0; j < count; j++)
227     printf("->%s<-", field[j]);
228   printf("\n");
229 #endif
230   return count;
231 }
232 
233 static void
tofloat(int count)234 tofloat(int count)
235 {
236   int i;
237   float val;
238 
239   for (i = 0; i < count; i++) {
240     val = (float) atof(field[i]);
241     ffield[i] = val;
242   }
243   for (i = count; i < MAXFIELD; i++)
244     ffield[i] = 0.0;
245 #ifdef DEBUG
246   if (1) {
247     int j;
248 
249     printf("tofloat: (%d)", count);
250     for (j = 0; j < count; j++)
251       printf("->%f<-", ffield[j]);
252     printf("\n");
253   }
254 #endif
255 }
256 
257 #define isfloat(c) (isdigit(c) || c=='.' || c=='-')
258 #define isfloatany(c) (isdigit(c) || c=='.' || c=='e' || c=='E' || c=='-' || c=='+')
259 
260 static int
checkfloat(int loc)261 checkfloat(int loc)
262 {
263   char *c;
264 
265   c = field[loc];
266   if (*c && (isfloat(*c))) {
267     c++;
268     while (*c) {
269       if (!isfloatany(*c))
270 	return 0;
271       c++;
272     }
273   }
274   else {
275     return 0;
276   }
277 #ifdef DEBUG
278   printf("%s is a float\n", field[loc]);
279 #endif
280   return 1;
281 }
282 
283 static int
reads(int fd,char * buf,int num)284 reads(int fd, char *buf, int num)
285 {
286   int count;
287 
288   count = 0;
289   while (count < num) {
290     if (read(fd, buf, 1) == 1) {
291       count++;
292       if (*buf == '\n')
293 	break;
294       buf++;
295     }
296     else if (count > 0)
297       break;
298     else {
299       count = -1;
300       break;
301     }
302   }
303   *buf = '\0';
304   return count;
305 }
306 
307 /*
308  * Read a line (ended by \n) from the specified file and call sepfield() to
309  * break the line up into fields.
310  */
311 int
getfields(FILE * fd)312 getfields(FILE *fd)
313 {
314   int count;
315   static char cmdline[1024];
316 
317   do {
318     count = reads(fileno(fd), cmdline, 1000);
319     if (count<=0)
320       return -1;
321     count = sepfield(cmdline, 0);
322   } while (count==0);
323 
324   return count;
325 }
326 
327 
328 
329 
330 
331 /*
332  *  Utils
333  */
334 
335 /* Internal structure for each plot dialog */
336 
337 typedef struct {
338   Widget label1;
339   Widget label2;
340   Widget label3;
341   Widget title;
342   Widget xlabel;
343   Widget ylabel;
344   Widget shell;
345   Widget plot;
346   Widget text;
347 } PlotDialogData;
348 
349 static void
QuitCallback(Widget btn,XtPointer client,XtPointer call)350 QuitCallback(Widget btn, XtPointer client, XtPointer call)
351 {
352   exit(0);
353 }
354 
355 static void
DismissCallback(Widget btn,XtPointer client,XtPointer call)356 DismissCallback(Widget btn, XtPointer client, XtPointer call)
357 {
358   PlotDialogData *stuff = (PlotDialogData *) client;
359 
360   XtPopdown(stuff->shell);
361   XtDestroyWidget(stuff->shell);
362   free(stuff);
363   DialogCount--;
364   if (DialogCount == 0)
365     exit(0);
366 }
367 
368 static void
LogXCallback(Widget btn,XtPointer client,XtPointer call)369 LogXCallback(Widget btn, XtPointer client, XtPointer call)
370 {
371   PlotDialogData *stuff = (PlotDialogData *) client;
372   Boolean state;
373 
374   XtVaGetValues(stuff->plot,
375     XtNxLog,        &state,
376     NULL);
377   state=!state;
378   XtVaSetValues(stuff->plot,
379     XtNxLog,        state,
380     NULL);
381 }
382 
383 static void
LogYCallback(Widget btn,XtPointer client,XtPointer call)384 LogYCallback(Widget btn, XtPointer client, XtPointer call)
385 {
386   PlotDialogData *stuff = (PlotDialogData *) client;
387   Boolean state;
388 
389   XtVaGetValues(stuff->plot,
390     XtNyLog,        &state,
391     NULL);
392   state=!state;
393   XtVaSetValues(stuff->plot,
394     XtNyLog,        state,
395     NULL);
396 }
397 
398 static void
NumbersXCallback(Widget btn,XtPointer client,XtPointer call)399 NumbersXCallback(Widget btn, XtPointer client, XtPointer call)
400 {
401   PlotDialogData *stuff = (PlotDialogData *) client;
402   Boolean state;
403 
404   XtVaGetValues(stuff->plot,
405     XtNxAxisNumbers,        &state,
406     NULL);
407   state=!state;
408   XtVaSetValues(stuff->plot,
409     XtNxAxisNumbers,        state,
410     NULL);
411 }
412 
413 static void
NumbersYCallback(Widget btn,XtPointer client,XtPointer call)414 NumbersYCallback(Widget btn, XtPointer client, XtPointer call)
415 {
416   PlotDialogData *stuff = (PlotDialogData *) client;
417   Boolean state;
418 
419   XtVaGetValues(stuff->plot,
420     XtNyAxisNumbers,        &state,
421     NULL);
422   state=!state;
423   XtVaSetValues(stuff->plot,
424     XtNyAxisNumbers,        state,
425     NULL);
426 }
427 
428 static void
OriginXCallback(Widget btn,XtPointer client,XtPointer call)429 OriginXCallback(Widget btn, XtPointer client, XtPointer call)
430 {
431   PlotDialogData *stuff = (PlotDialogData *) client;
432   Boolean state;
433 
434   XtVaGetValues(stuff->plot,
435     XtNxOrigin,        &state,
436     NULL);
437   state=!state;
438   XtVaSetValues(stuff->plot,
439     XtNxOrigin,        state,
440     NULL);
441 }
442 
443 static void
OriginYCallback(Widget btn,XtPointer client,XtPointer call)444 OriginYCallback(Widget btn, XtPointer client, XtPointer call)
445 {
446   PlotDialogData *stuff = (PlotDialogData *) client;
447   Boolean state;
448 
449   XtVaGetValues(stuff->plot,
450     XtNyOrigin,        &state,
451     NULL);
452   state=!state;
453   XtVaSetValues(stuff->plot,
454     XtNyOrigin,        state,
455     NULL);
456 }
457 
458 static void
MajorCallback(Widget btn,XtPointer client,XtPointer call)459 MajorCallback(Widget btn, XtPointer client, XtPointer call)
460 {
461   PlotDialogData *stuff = (PlotDialogData *) client;
462   Boolean state;
463 
464   XtVaGetValues(stuff->plot,
465     XtNdrawMajor,        &state,
466     NULL);
467   state=!state;
468   XtVaSetValues(stuff->plot,
469     XtNdrawMajor,        state,
470     NULL);
471 }
472 
473 static void
MinorCallback(Widget btn,XtPointer client,XtPointer call)474 MinorCallback(Widget btn, XtPointer client, XtPointer call)
475 {
476   PlotDialogData *stuff = (PlotDialogData *) client;
477   Boolean state;
478 
479   XtVaGetValues(stuff->plot,
480     XtNdrawMinor,        &state,
481     NULL);
482   state=!state;
483   XtVaSetValues(stuff->plot,
484     XtNdrawMinor,        state,
485     NULL);
486 }
487 
488 static void
LegendCallback(Widget btn,XtPointer client,XtPointer call)489 LegendCallback(Widget btn, XtPointer client, XtPointer call)
490 {
491   PlotDialogData *stuff = (PlotDialogData *) client;
492   Boolean state;
493 
494   XtVaGetValues(stuff->plot,
495     XtNshowLegend,        &state,
496     NULL);
497   state=!state;
498   XtVaSetValues(stuff->plot,
499     XtNshowLegend,        state,
500     NULL);
501 }
502 
503 static void
TitleChangeCallback(Widget btn,XtPointer client,XtPointer call)504 TitleChangeCallback(Widget btn, XtPointer client, XtPointer call)
505 {
506   PlotDialogData *stuff = (PlotDialogData *) client;
507   char *ret;
508 
509   ret=XmTextFieldGetString(btn);
510   XtVaSetValues(stuff->plot,
511     XtNplotTitle, ret,
512     NULL);
513   XtFree(ret);
514 }
515 
516 static void
TitleCallback(Widget btn,XtPointer client,XtPointer call)517 TitleCallback(Widget btn, XtPointer client, XtPointer call)
518 {
519   PlotDialogData *stuff = (PlotDialogData *) client;
520   Boolean state;
521 
522   XtVaGetValues(stuff->plot,
523     XtNshowTitle,        &state,
524     NULL);
525   state=!state;
526   XtVaSetValues(stuff->plot,
527     XtNshowTitle,        state,
528     NULL);
529 #ifdef DEBUG
530   if (1) {
531     char label[256],*txt1,*txt2,*txt3;
532     static int count=0;
533 
534     sprintf(label,"Title #%d",++count);
535     XtVaSetValues(stuff->plot,
536       XtNplotTitle, label,
537       NULL);
538     XtVaGetValues(stuff->plot,
539       XtNplotTitle, &txt1,
540       XtNxLabel, &txt2,
541       XtNyLabel, &txt3,
542       NULL);
543     printf("title=%s\nx label=%s\ny label=%s\n",txt);
544 #endif
545 }
546 
547 static void
548 LabelXChangeCallback(Widget btn, XtPointer client, XtPointer call)
549 {
550   PlotDialogData *stuff = (PlotDialogData *) client;
551   char *ret;
552 
553   ret=XmTextFieldGetString(btn);
554   XtVaSetValues(stuff->plot,
555     XtNxLabel, ret,
556     NULL);
557   XtFree(ret);
558 }
559 
560 static void
561 LabelXCallback(Widget btn, XtPointer client, XtPointer call)
562 {
563   PlotDialogData *stuff = (PlotDialogData *) client;
564   Boolean state;
565 
566   XtVaGetValues(stuff->plot,
567     XtNshowXLabel,        &state,
568     NULL);
569   state=!state;
570   XtVaSetValues(stuff->plot,
571     XtNshowXLabel,        state,
572     NULL);
573 #ifdef DEBUG
574   if (1) {
575     char label[256];
576     static int count=0;
577 
578     sprintf(label,"X Label #%d",++count);
579     XtVaSetValues(stuff->plot,
580       XtNxLabel, label,
581       NULL);
582   }
583 #endif
584 }
585 
586 static void
587 LabelYChangeCallback(Widget btn, XtPointer client, XtPointer call)
588 {
589   PlotDialogData *stuff = (PlotDialogData *) client;
590   char *ret;
591 
592   ret=XmTextFieldGetString(btn);
593   XtVaSetValues(stuff->plot,
594     XtNyLabel, ret,
595     NULL);
596   XtFree(ret);
597 }
598 
599 static void
600 LabelYCallback(Widget btn, XtPointer client, XtPointer call)
601 {
602   PlotDialogData *stuff = (PlotDialogData *) client;
603   Boolean state;
604 
605   XtVaGetValues(stuff->plot,
606     XtNshowYLabel,        &state,
607     NULL);
608   state=!state;
609   XtVaSetValues(stuff->plot,
610     XtNshowYLabel,        state,
611     NULL);
612 #ifdef DEBUG
613   if (1) {
614     char label[256];
615     static int count=0;
616 
617     sprintf(label,"Y Label #%d",++count);
618     XtVaSetValues(stuff->plot,
619       XtNyLabel, label,
620       NULL);
621   }
622 #endif
623 }
624 
625 static void
626 PSCallback(Widget btn, XtPointer client, XtPointer call)
627 {
628   PlotDialogData *stuff = (PlotDialogData *) client;
629   char *filename;
630 
631 #ifdef EXTRA_FANCY
632   char txt[1024],*ptr;
633 
634   ptr=XmTextFieldGetString(stuff->label1);
635   strcpy(txt,ptr);
636   strcat(txt,"\n");
637   XtFree(ptr);
638   ptr=XmTextFieldGetString(stuff->label2);
639   strcat(txt,ptr);
640   strcat(txt,"\n\n");
641   XtFree(ptr);
642   ptr=XmTextFieldGetString(stuff->label3);
643   strcat(txt,ptr);
644   strcat(txt,"\n");
645   XtFree(ptr);
646 
647   filename = XmTextFieldGetString(stuff->text);
648   if (strlen(filename) > 0)
649     SciPlotPSCreateFancy(stuff->plot,filename,
650       TRUE,txt,NULL);
651   XtFree(filename);
652 #else
653   filename = XmTextFieldGetString(stuff->text);
654   if (strlen(filename) > 0)
655     SciPlotPSCreateColor(stuff->plot,filename);
656   XtFree(filename);
657 #endif
658 }
659 
660 
661 /*
662  * Create an plot dialog using Motif widgets
663  */
664 static PlotDialogData *
665 SciPlotDialogInternal(Widget parent, char *title)
666 {
667   Widget paned, box, topbox, botbox, btn, t1;
668   PlotDialogData *info;
669   char *text;
670 #ifdef EXTRA_FANCY
671   char buf[256];
672   time_t  now;
673   struct tm *t;
674 #endif
675 
676   info = (PlotDialogData *) malloc(sizeof(PlotDialogData));
677   DialogCount++;
678 
679   text = malloc(strlen(title) + 256);
680   sprintf(text, "Plot #%d: %s ", DialogCount, title);
681 
682   paned=XmCreateFormDialog(parent,text,NULL,0);
683   info->shell=XtParent(paned);
684   XtVaSetValues(paned,
685     XmNdialogStyle,XmDIALOG_MODELESS,
686     XmNnoResize,False,
687     XmNautoUnmanage,False,
688     NULL);
689 
690   topbox = box = XtVaCreateManagedWidget("box",
691     xmRowColumnWidgetClass,paned,
692     XmNleftAttachment, XmATTACH_FORM,
693     XmNrightAttachment, XmATTACH_FORM,
694     XmNtopAttachment, XmATTACH_FORM,
695     XmNpacking,     XmPACK_COLUMN,
696     XmNnumColumns,  2,
697     XmNorientation, XmVERTICAL,
698     NULL);
699 
700 #ifdef EXTRA_FANCY
701   btn = XtVaCreateManagedWidget("Desc 1:",
702     xmLabelWidgetClass, box,
703     NULL);
704   btn = XtVaCreateManagedWidget("Desc 2:",
705     xmLabelWidgetClass, box,
706     NULL);
707   btn = XtVaCreateManagedWidget("Desc 3:",
708     xmLabelWidgetClass, box,
709     NULL);
710 #endif
711   btn = XtVaCreateManagedWidget("Xlabel:",
712     xmLabelWidgetClass, box,
713     NULL);
714   btn = XtVaCreateManagedWidget("Ylabel:",
715     xmLabelWidgetClass, box,
716     NULL);
717   btn = XtVaCreateManagedWidget("Title:",
718     xmLabelWidgetClass, box,
719     NULL);
720 
721 #ifdef EXTRA_FANCY
722   info->label1 = XtVaCreateManagedWidget("entry",
723     xmTextFieldWidgetClass, box,
724     XmNskipAdjust, True,
725     NULL);
726   info->label2 = XtVaCreateManagedWidget("entry",
727     xmTextFieldWidgetClass, box,
728     XmNskipAdjust, True,
729     NULL);
730   now=time(NULL);
731   t=localtime(&now);
732   strftime(buf,256,"%c",t);
733   info->label3 = XtVaCreateManagedWidget("entry",
734     xmTextFieldWidgetClass, box,
735     XmNvalue, buf,
736     XmNcursorPosition, 100,
737     XmNskipAdjust, True,
738     NULL);
739 #endif
740   info->xlabel = XtVaCreateManagedWidget("entry",
741     xmTextFieldWidgetClass, box,
742     NULL);
743   info->ylabel = XtVaCreateManagedWidget("entry",
744     xmTextFieldWidgetClass, box,
745     NULL);
746   info->title = XtVaCreateManagedWidget("entry",
747     xmTextFieldWidgetClass, box,
748     NULL);
749   XtAddCallback(info->xlabel, XmNactivateCallback, LabelXChangeCallback, (XtPointer) info);
750   XtAddCallback(info->ylabel, XmNactivateCallback, LabelYChangeCallback, (XtPointer) info);
751   XtAddCallback(info->title, XmNactivateCallback, TitleChangeCallback, (XtPointer) info);
752 
753   box = XtVaCreateManagedWidget("box",
754     xmRowColumnWidgetClass,paned,
755     XmNleftAttachment,      XmATTACH_FORM,
756     XmNrightAttachment,     XmATTACH_FORM,
757     XmNbottomAttachment,    XmATTACH_FORM,
758     XmNorientation,         XmHORIZONTAL,
759     XmNpacking,             XmPACK_TIGHT,
760     NULL);
761   btn = XtVaCreateManagedWidget("Quit",
762     xmPushButtonWidgetClass, box,
763     NULL);
764   XtAddCallback(btn, XmNactivateCallback, QuitCallback, (XtPointer) NULL);
765 
766   btn = XtVaCreateManagedWidget("Dismiss",
767     xmPushButtonWidgetClass, box,
768     NULL);
769   XtAddCallback(btn, XmNactivateCallback, DismissCallback, (XtPointer) info);
770 
771   btn = XtVaCreateManagedWidget("Make Postscript",
772     xmPushButtonWidgetClass, box,
773     NULL);
774   sprintf(text, "plot%d.ps", DialogCount);
775   t1 = XtVaCreateManagedWidget("entry",
776     xmTextFieldWidgetClass, box,
777     XmNwidth, 200,
778     XmNvalue, text,
779     XmNcursorPosition, 100,
780     NULL);
781   info->text = t1;
782   XtAddCallback(btn, XmNactivateCallback, PSCallback, (XtPointer) info);
783 
784   botbox = box = XtVaCreateManagedWidget("box",
785     xmRowColumnWidgetClass,paned,
786     XmNleftAttachment,      XmATTACH_FORM,
787     XmNrightAttachment,     XmATTACH_FORM,
788     XmNbottomAttachment,    XmATTACH_WIDGET,
789     XmNbottomWidget, box,
790     XmNorientation,         XmHORIZONTAL,
791     XmNpacking,             XmPACK_TIGHT,
792     NULL);
793   btn = XtVaCreateManagedWidget("Log",
794     xmLabelWidgetClass, box,
795     NULL);
796   btn = XtVaCreateManagedWidget("X",
797     xmPushButtonWidgetClass, box,
798     NULL);
799   XtAddCallback(btn, XmNactivateCallback, LogXCallback, (XtPointer) info);
800   btn = XtVaCreateManagedWidget("Y",
801     xmPushButtonWidgetClass, box,
802     NULL);
803   XtAddCallback(btn, XmNactivateCallback, LogYCallback, (XtPointer) info);
804 
805   btn = XtVaCreateManagedWidget("Origin",
806     xmLabelWidgetClass, box,
807     NULL);
808   btn = XtVaCreateManagedWidget("X",
809     xmPushButtonWidgetClass, box,
810     NULL);
811   XtAddCallback(btn, XmNactivateCallback, OriginXCallback, (XtPointer) info);
812   btn = XtVaCreateManagedWidget("Y",
813     xmPushButtonWidgetClass, box,
814     NULL);
815   XtAddCallback(btn, XmNactivateCallback, OriginYCallback, (XtPointer) info);
816 
817   btn = XtVaCreateManagedWidget("Numbers",
818     xmLabelWidgetClass, box,
819     NULL);
820   btn = XtVaCreateManagedWidget("X",
821     xmPushButtonWidgetClass, box,
822     NULL);
823   XtAddCallback(btn, XmNactivateCallback, NumbersXCallback, (XtPointer) info);
824   btn = XtVaCreateManagedWidget("Y",
825     xmPushButtonWidgetClass, box,
826     NULL);
827   XtAddCallback(btn, XmNactivateCallback, NumbersYCallback, (XtPointer) info);
828 
829   btn = XtVaCreateManagedWidget("Major",
830     xmPushButtonWidgetClass, box,
831     NULL);
832   XtAddCallback(btn, XmNactivateCallback, MajorCallback, (XtPointer) info);
833   btn = XtVaCreateManagedWidget("Minor",
834     xmPushButtonWidgetClass, box,
835     NULL);
836   XtAddCallback(btn, XmNactivateCallback, MinorCallback, (XtPointer) info);
837   btn = XtVaCreateManagedWidget("Title",
838     xmPushButtonWidgetClass, box,
839     NULL);
840   XtAddCallback(btn, XmNactivateCallback, TitleCallback, (XtPointer) info);
841   btn = XtVaCreateManagedWidget("X Label",
842     xmPushButtonWidgetClass, box,
843     NULL);
844   XtAddCallback(btn, XmNactivateCallback, LabelXCallback, (XtPointer) info);
845   btn = XtVaCreateManagedWidget("Y Label",
846     xmPushButtonWidgetClass, box,
847     NULL);
848   XtAddCallback(btn, XmNactivateCallback, LabelYCallback, (XtPointer) info);
849   btn = XtVaCreateManagedWidget("Legend",
850     xmPushButtonWidgetClass, box,
851     NULL);
852   XtAddCallback(btn, XmNactivateCallback, LegendCallback, (XtPointer) info);
853 
854   info->plot = XtVaCreateManagedWidget("plot",
855     sciplotWidgetClass, paned,
856     XmNleftAttachment, XmATTACH_FORM,
857     XmNrightAttachment, XmATTACH_FORM,
858     XmNtopAttachment, XmATTACH_WIDGET,
859     XmNtopWidget, topbox,
860     XmNbottomAttachment, XmATTACH_WIDGET,
861     XmNbottomWidget, botbox,
862     XtNheight, (XtArgVal) 600,
863     XtNwidth, (XtArgVal) 500,
864     XtNplotTitle, title,
865 /*     XtNlabelFont, XtFONT_TIMES|8, */
866 /*     XtNtitleFont, XtFONT_TIMES|8, */
867 /*     XtNtitleMargin, 4, */
868 /*     XtNaxisFont, XtFONT_TIMES|8, */
869     NULL);
870 
871   free(text);
872   XtManageChild(paned);
873   XtManageChild(info->shell);
874   return info;
875 }
876 
877 static void
878 SciPlotDialogInternalPopup(PlotDialogData *info)
879 {
880   char *x,*y,*t;
881 
882   XtVaGetValues(info->plot,
883     XtNplotTitle, &t,
884     XtNxLabel, &x,
885     XtNyLabel, &y,
886     NULL);
887   XmTextFieldSetString(info->title,t);
888   XmTextFieldSetString(info->xlabel,x);
889   XmTextFieldSetString(info->ylabel,y);
890 
891   XtManageChild(info->shell);
892 }
893 
894 Widget
895 SciPlotDialog(Widget parent, char *title)
896 {
897   PlotDialogData *info;
898 
899   info = SciPlotDialogInternal(parent,title);
900   return info->plot;
901 }
902 
903 void
904 SciPlotDialogPopup(Widget w)
905 {
906   XtManageChild(XtParent(XtParent(w)));
907 }
908 
909 /*
910  * Process a text input stream for plot commands
911  */
912 void
913 SciPlotReadDataFile(Widget parent, FILE * fd)
914 {
915   int count;
916   PlotDialogData *working;
917   float xlist[10], ylist[10];
918   int line[256], linecount;
919   Boolean readnext;
920   int num, i;
921 
922   working = NULL;
923   count = getfields(fd);
924   while (count > 0) {
925     if (count > 0) {
926       readnext = True;
927       upper(field[0]);
928       if (strcmp(field[0], "TITLE") == 0 || strcmp(field[0], "NEW") == 0 ) {
929           /* Pop up the last dialog if it exists */
930         if (working) SciPlotDialogInternalPopup(working);
931 
932 	working = SciPlotDialogInternal(parent, field[1]);
933 	for (i = 0; i < NUM_COLORS; i++) {
934 	  colors_list[i].num = SciPlotAllocNamedColor(working->plot, colors_list[i].text);
935 	}
936 	linecount = 0;
937       }
938       else if (strcmp(field[0], "POLAR") == 0) {
939 	Boolean degflag;
940 
941 	degflag = True;
942 	if (count > 1) {
943 	  upper(field[1]);
944 	  if (strncmp(field[1], "RAD", 3) == 0)
945 	    degflag = False;
946 	}
947 	XtVaSetValues(working->plot,
948 	  XtNchartType, XtPOLAR,
949 	  XtNdegrees, degflag,
950 	  NULL);
951       }
952       else if (strcmp(field[0], "XAXIS") == 0) {
953 	if (working) {
954             if (count > 1) XtVaSetValues(working->plot, XtNxLabel, field[1], NULL);
955             if (count>2) {
956                 for (i=2; i<count; i++) {
957                     upper(field[i]);
958                     if (strcmp(field[i], "LOG") == 0)
959                         XtVaSetValues(working->plot, XtNxLog, True, NULL);
960                     else if (strcmp(field[i], "NOZERO") == 0)
961                         XtVaSetValues(working->plot, XtNxOrigin, False, NULL);
962                 }
963             }
964         }
965       }
966       else if (strcmp(field[0], "YAXIS") == 0) {
967 	if (working) {
968             if (count > 1) XtVaSetValues(working->plot, XtNyLabel, field[1], NULL);
969             if (count>2) {
970                 for (i=2; i<count; i++) {
971                     upper(field[i]);
972                     if (strcmp(field[i], "LOG") == 0)
973                         XtVaSetValues(working->plot, XtNyLog, True, NULL);
974                     else if (strcmp(field[i], "NOZERO") == 0)
975                         XtVaSetValues(working->plot, XtNyOrigin, False, NULL);
976                 }
977             }
978         }
979       }
980       else if (strcmp(field[0], "LEGEND") == 0) {
981 	int colorcount, markercount, linestyle;
982 
983 	if (working && count > 1) {
984 	  if (count >= 4) {
985 	    XtVaSetValues(working->plot,
986 	      XtNxLabel, field[2],
987 	      XtNyLabel, field[3],
988 	      NULL);
989 	  }
990 	  line[0] = SciPlotListCreateFromFloat(working->plot, 0, NULL, NULL, field[1]);
991 	  do {
992 	    count = getfields(fd);
993 	    readnext = False;
994 
995 	    num = checkfloat(0);
996 	    if (count > 0 && num) {
997 	      tofloat(count);
998 	      xlist[0] = ffield[0];
999 	      ylist[0] = ffield[1];
1000 	      SciPlotListAddFloat(working->plot, line[0], 1, xlist, ylist);
1001 	    }
1002 
1003 	  } while (count > 0 && num);
1004 	  colorcount = linecount % NUM_COLORS;
1005 	  markercount = linecount % NUM_MARKERS;
1006 	  linestyle = -1;
1007 	  SciPlotListSetStyle(working->plot, line[0],
1008 	    colors_list[colorcount].num, marker_list[markercount].num,
1009 	    colors_list[colorcount].num, linestyle);
1010 	  linecount++;
1011 	}
1012 
1013       }
1014       else if (strcmp(field[0], "LINE") == 0) {
1015 	int colorcount, markercount, linestyle, maxlines;
1016         Boolean skip;
1017 
1018 	if (working && count > 1) {
1019 	  for (i = 1; i < count; i++) {
1020 	    line[i] = SciPlotListCreateFromFloat(working->plot, 0, NULL, NULL, field[i]);
1021 	  }
1022 	  maxlines = count;
1023 
1024 	  do {
1025 	    count = getfields(fd);
1026 	    readnext = False;
1027 
1028 	    num = checkfloat(0);
1029             if (strcmp(field[0],"skip")==0) skip=True;
1030             else skip=False;
1031 
1032 	    if (count > 0 && (num || skip)) {
1033               if (skip) {
1034                 for (i = 1; i < maxlines; i++) {
1035                   xlist[0] = ylist[0] = SCIPLOT_SKIP_VAL;
1036                   SciPlotListAddFloat(working->plot, line[i], 1, xlist, ylist);
1037                 }
1038               }
1039               else {
1040                 tofloat(count);
1041                 xlist[0] = ffield[0];
1042                 for (i = 1; i < maxlines; i++) {
1043                   ylist[0] = ffield[i];
1044                   SciPlotListAddFloat(working->plot, line[i], 1, xlist, ylist);
1045                 }
1046               }
1047 
1048 	    }
1049 	  } while (count > 0 && (num || skip));
1050 	  for (i = 1; i < maxlines; i++) {
1051 	    linecount++;
1052 	    colorcount = linecount % NUM_COLORS;
1053 	    markercount = linecount % NUM_MARKERS;
1054 	    linestyle = -1;
1055 	    SciPlotListSetStyle(working->plot, line[i],
1056 	      colors_list[colorcount].num, marker_list[markercount].num,
1057 	      colors_list[colorcount].num, linestyle);
1058 /*             SciPlotListSetMarkerSize(working->plot, line[i], (float) linecount*4); */
1059 	  }
1060 	}
1061 
1062       }
1063     }
1064     if (readnext)
1065       count = getfields(fd);
1066   }
1067   if (working) SciPlotDialogInternalPopup(working);
1068 }
1069