/* 
 * $Id: x11graph.c,v 1.8 2003/02/16 12:43:37 isizaka Exp isizaka $
 * 
 * This file is part of "Ngraph for X11".
 * 
 * Copyright (C) 2002, Satoshi ISHIZAKA. isizaka@msa.biglobe.ne.jp
 * 
 * "Ngraph for X11" is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * "Ngraph for X11" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 */

/**
 *
 * $Log: x11graph.c,v $
 * Revision 1.8  2003/02/16 12:43:37  isizaka
 * for release 6.13.18
 *
 * Revision 1.7  2002/07/06 08:57:25  isizaka
 * change to GPL.
 *
 * Revision 1.6  2001/07/14 17:44:50  isizaka
 * for 6.03.14
 *
 * Revision 1.5  2001/03/23 12:17:43  isizaka
 * for 6.3.13
 *
 * Revision 1.4  1999/05/08 13:31:30  isizaka
 * for release 6.03.02
 *
 * Revision 1.3  1999/04/15 12:14:26  isizaka
 * for release 6.03.01
 *
 * Revision 1.2  1999/04/11 06:09:20  isizaka
 * *** empty log message ***
 *
 * Revision 1.1  1999/03/17 13:29:01  isizaka
 * Initial revision
 *
 *
 **/

#include <Xm/XmAll.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "motif12.h"

#include "ngraph.h"
#include "object.h"
#include "ioutil.h"
#include "shell.h"
#include "nstring.h"
#include "odraw.h"

#include "x11dialg.h"
#include "ox11menu.h"
#include "x11menu.h"
#include "x11gui.h"
#include "x11graph.h"
#include "x11view.h"
#include "x11axis.h"
#include "x11print.h"
#include "x11commn.h"
#include "x11scrip.h"

#define PAGELISTNUM 12

struct pagelisttype {
  char *paper;
  int width;
  int height;
} pagelist[12]={
  {"A3 P (29700x42000)",29700,42000},
  {"A4 P (21000x29700)",21000,29700},
  {"A4 L (29700x21000)",29700,21000},
  {"A5 P (14800x21000)",14800,21000},
  {"A5 L (21000x14800)",21000,14800},
  {"B4 P (25700x36400)",25700,36400},
  {"B5 P (18200x25700)",18200,25700},
  {"B5 L (25700x18200)",25700,18200},
  {"Letter P (21590x27940)",21590,27940},
  {"Letter L (27940x21590)",27940,21590},
  {"Legal  P (21590x35560)",21590,35560},
  {"Legal  L (35560x35560)",35560,21590},
};

void PageDialogSetupItem(Widget w,struct PageDialog *d)
{
  int j;
  char buf[256];

  sprintf(buf,"%d",menulocal.LeftMargin);
  XtVaSetValues(XtNameToWidget(w,"*leftmargin"),XmNvalue,buf,NULL);
  sprintf(buf,"%d",menulocal.TopMargin);
  XtVaSetValues(XtNameToWidget(w,"*topmargin"),XmNvalue,buf,NULL);
  sprintf(buf,"%d",menulocal.PaperWidth);
  XtVaSetValues(XtNameToWidget(w,"*paperwidth"),XmNvalue,buf,NULL);
  sprintf(buf,"%d",menulocal.PaperHeight);
  XtVaSetValues(XtNameToWidget(w,"*paperheight"),XmNvalue,buf,NULL);
  sprintf(buf,"%d",menulocal.PaperZoom);
  XtVaSetValues(XtNameToWidget(w,"*paperzoom"),XmNvalue,buf,NULL);
  XmListDeselectAllItems(GetComboBoxList(w,"*paper"));
  for (j=0;j<PAGELISTNUM;j++)
    if ((menulocal.PaperWidth==pagelist[j].width)
     && (menulocal.PaperHeight==pagelist[j].height))
      break;
  if (j!=PAGELISTNUM)
    XmListSelectPos(GetComboBoxList(w,"*paper"),j+1,TRUE);
}
 
void PageDialogPage(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct PageDialog *d;
  XmComboBoxCallbackStruct *dd;
  int a;
  char buf[256];

  d=(struct PageDialog *)client_data;
  dd=(XmComboBoxCallbackStruct *)call_data;
#ifdef ZEROBASECOMBOBOX
  a=dd->item_position;
#else
  a=dd->item_position-1;
#endif
  if (a<0) return;
  sprintf(buf,"%d",pagelist[a].width);
  XtVaSetValues(XtNameToWidget(d->widget,"*paperwidth"),XmNvalue,buf,NULL);
  sprintf(buf,"%d",pagelist[a].height);
  XtVaSetValues(XtNameToWidget(d->widget,"*paperheight"),XmNvalue,buf,NULL);
}

void PageDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc,rc2,cmb;
  int j;
  struct PageDialog *d;
  XmString xs;

  d=(struct PageDialog *)data;

  if (makewidget) {
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
  XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"widthrc",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"PaperWidth",al,ac));
  ac=0;
  XtManageChild(XmCreateTextField(rc2,"paperwidth",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"PaperHeight",al,ac));
  ac=0;
  XtManageChild(XmCreateTextField(rc2,"paperheight",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"paperrc",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNcomboBoxType,XmDROP_DOWN_LIST); ac++;
  XtManageChild(cmb=XmCreateComboBox(rc2,"paper",al,ac));
  for (j=0;j<PAGELISTNUM;j++) {
    xs=XmStringCreateLocalized(pagelist[j].paper);
    XmListAddItem(GetComboBoxList(w,"*paper"),xs,0);
    XmStringFree(xs);
  } 
  SetComboBoxVisibleItemCount(w,"*paper",j);
  XtAddCallback(cmb,XmNselectionCallback,PageDialogPage,d);
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"marginrc",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"LeftMargin",al,ac));
  ac=0;
  XtManageChild(XmCreateTextField(rc2,"leftmargin",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"TopMargin",al,ac));
  ac=0;
  XtManageChild(XmCreateTextField(rc2,"topmargin",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"zoomrc",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"PaperZoom",al,ac));
  ac=0;
  XtManageChild(XmCreateTextField(rc2,"paperzoom",al,ac));
  }
  PageDialogSetupItem(w,d); 
}

void PageDialogClose(Widget w,void *data)
{
  struct PageDialog *d;
  char *buf;
  char *endptr;
  int a;

  d=(struct PageDialog *)data;
  if (d->ret!=IDOK) return;
  XtVaGetValues(XtNameToWidget(d->widget,"*leftmargin"),XmNvalue,&buf,NULL);
  a=strtol(buf,&endptr,10);
  if (endptr[0]=='\0') menulocal.LeftMargin=a;
  XtFree(buf);
  XtVaGetValues(XtNameToWidget(d->widget,"*topmargin"),XmNvalue,&buf,NULL);
  a=strtol(buf,&endptr,10);
  if (endptr[0]=='\0') menulocal.TopMargin=a;
  XtFree(buf);
  XtVaGetValues(XtNameToWidget(d->widget,"*paperwidth"),XmNvalue,&buf,NULL);
  a=strtol(buf,&endptr,10);
  if (endptr[0]=='\0') menulocal.PaperWidth=a;
  XtFree(buf);
  XtVaGetValues(XtNameToWidget(d->widget,"*paperheight"),XmNvalue,&buf,NULL);
  a=strtol(buf,&endptr,10);
  if (endptr[0]=='\0') menulocal.PaperHeight=a;
  XtFree(buf);
  XtVaGetValues(XtNameToWidget(d->widget,"*paperzoom"),XmNvalue,&buf,NULL);
  a=strtol(buf,&endptr,10);
  if (endptr[0]=='\0') menulocal.PaperZoom=a;
  XtFree(buf);
}

void PageDialog(struct PageDialog *data)
{
  data->SetupWindow=PageDialogSetup;
  data->CloseWindow=PageDialogClose;
}

void SwitchDialogSetupItem(Widget w,struct SwitchDialog *d)
{
  int j,num;
  char **buf;
  XmString xs;

  XmListDeleteAllItems(XtNameToWidget(w,"*drawlist"));
  num=arraynum(&(d->idrawrable));
  for (j=0;j<num;j++) {
    buf=(char **)arraynget(&(d->drawrable),
       *(int *)arraynget(&(d->idrawrable),j));
    xs=XmStringCreateLocalized(*buf);
    XmListAddItem(XtNameToWidget(w,"*drawlist"),xs,0);
    XmStringFree(xs);
  }
}

void SwitchDialogAdd(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SwitchDialog *d;
  int j,num,a;
  int *selected;

  d=(struct SwitchDialog *)client_data;
  XmListGetSelectedPos(XtNameToWidget(d->widget,"*objlist"),
                       &selected,&num);
  if (num!=0) {
    for (j=0;j<num;j++) {
      a=selected[j]-1;
      arrayadd(&(d->idrawrable),&a);
    }
    XtFree((char *)selected);
  }
  SwitchDialogSetupItem(d->widget,d);
}

void SwitchDialogInsert(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SwitchDialog *d;
  int i,j,a,num,pos,num2;
  int *data;
  int *selected;

  d=(struct SwitchDialog *)client_data;
  XmListGetSelectedPos(XtNameToWidget(d->widget,"*drawlist"),
                       &selected,&num);
  pos=0;
  for (i=0;i<num;i++) if (selected[i]>pos) pos=selected[i];
  if (num!=0) XtFree((char *)selected);
  num2=arraynum(&(d->idrawrable));
  data=(int *)arraydata(&(d->idrawrable));
  XmListGetSelectedPos(XtNameToWidget(d->widget,"*objlist"),
                       &selected,&num);
  for (j=num-1;j>=0;j--) {
    a=selected[j]-1;
    for (i=0;i<num2;i++) if (data[i]==a) break;
    if (i==num2) arrayins(&(d->idrawrable),&a,pos);
  }
  if (num!=0) XtFree((char *)selected);
  SwitchDialogSetupItem(d->widget,d);
}

void SwitchDialogTop(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SwitchDialog *d;
  int i,j,num,k,item;
  int *selected;

  d=(struct SwitchDialog *)client_data;
  XmListGetSelectedPos(XtNameToWidget(d->widget,"*drawlist"),
                       &selected,&num);
  XtVaGetValues(XtNameToWidget(d->widget,"*drawlist"),
                XmNitemCount,&item,NULL);
  for (j=0;j<item;j++) {
    for (i=0;i<num;i++)
      if ((selected[i]-1)==j) {
        k=*(int *)arraynget(&(d->idrawrable),j);
        arrayndel(&(d->idrawrable),j);
        arrayins(&(d->idrawrable),&k,0);
      }
  }
  if (num!=0) XtFree((char *)selected);
  SwitchDialogSetupItem(d->widget,d);
}

void SwitchDialogLast(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SwitchDialog *d;
  int i,j,num,k,item;
  int *selected;

  d=(struct SwitchDialog *)client_data;
  XmListGetSelectedPos(XtNameToWidget(d->widget,"*drawlist"),
                       &selected,&num);
  XtVaGetValues(XtNameToWidget(d->widget,"*drawlist"),
                XmNitemCount,&item,NULL);
  for (j=item-1;j>=0;j--) {
    for (i=0;i<num;i++)
      if ((selected[i]-1)==j) {
        k=*(int *)arraynget(&(d->idrawrable),j);
        arrayndel(&(d->idrawrable),j);
        arrayadd(&(d->idrawrable),&k);
      }
  }
  if (num!=0) XtFree((char *)selected);
  SwitchDialogSetupItem(d->widget,d);
}

void SwitchDialogRemove(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SwitchDialog *d;
  int i,j,num,item;
  int *selected;

  d=(struct SwitchDialog *)client_data;
  XmListGetSelectedPos(XtNameToWidget(d->widget,"*drawlist"),
                       &selected,&num);
  XtVaGetValues(XtNameToWidget(d->widget,"*drawlist"),
                XmNitemCount,&item,NULL);
  for (j=item-1;j>=0;j--) {
    for (i=0;i<num;i++)
      if ((selected[i]-1)==j) {
        arrayndel(&(d->idrawrable),j);
      }
  }
  if (num!=0) XtFree((char *)selected);
  SwitchDialogSetupItem(d->widget,d);
}

void SwitchDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc,rc2,button;
  struct SwitchDialog *d;
  int num2,num1,j,k;
  char **buf;
  XmString xs;

  d=(struct SwitchDialog *)data;

  if (makewidget) {

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"rc1",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"DrawOrder",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNlistSizePolicy,XmCONSTANT); ac++;
  XtSetArg(al[ac],XmNscrollBarDisplayPolicy,XmSTATIC); ac++;
  XtSetArg(al[ac],XmNselectionPolicy,XmEXTENDED_SELECT); ac++;
  XtManageChild(XmCreateScrolledList(rc2,"drawlist",al,ac));

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"rc2",al,ac));

  ac=0;
  XtManageChild(button=XmCreatePushButton(rc2,"Add",al,ac));
  XtAddCallback(button,XmNdisarmCallback,SwitchDialogAdd,d);
  ac=0;
  XtManageChild(button=XmCreatePushButton(rc2,"Insert",al,ac));
  XtAddCallback(button,XmNdisarmCallback,SwitchDialogInsert,d);
  ac=0;
  XtManageChild(button=XmCreatePushButton(rc2,"Top",al,ac));
  XtAddCallback(button,XmNdisarmCallback,SwitchDialogTop,d);
  ac=0;
  XtManageChild(button=XmCreatePushButton(rc2,"Last",al,ac));
  XtAddCallback(button,XmNdisarmCallback,SwitchDialogLast,d);
  ac=0;
  XtManageChild(button=XmCreatePushButton(rc2,"Remove",al,ac));
  XtAddCallback(button,XmNdisarmCallback,SwitchDialogRemove,d);

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"rc3",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"Objects",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNlistSizePolicy,XmCONSTANT); ac++;
  XtSetArg(al[ac],XmNscrollBarDisplayPolicy,XmSTATIC); ac++;
  XtSetArg(al[ac],XmNselectionPolicy,XmEXTENDED_SELECT); ac++;
  XtManageChild(XmCreateScrolledList(rc2,"objlist",al,ac));

  }

  menuadddrawrable(chkobject("draw"),&(d->drawrable));
  XmListDeleteAllItems(XtNameToWidget(w,"*objlist"));
  num2=arraynum(&(d->drawrable));
  for (j=0;j<num2;j++) {
    buf=(char **)arraynget(&(d->drawrable),j);
    xs=XmStringCreateLocalized(*buf);
    XmListAddItem(XtNameToWidget(w,"*objlist"),xs,0);
    XmStringFree(xs);
  }
  num1=arraynum(&(menulocal.drawrable));
  for (j=0;j<num1;j++) {
    buf=(char **)arraynget(&(menulocal.drawrable),j);
    for (k=0;k<num2;k++)
      if (strcmp0(*(char **)arraynget(&(d->drawrable),k),*buf)==0) break;
    if (k!=num2) arrayadd(&(d->idrawrable),&k);
  }
  SwitchDialogSetupItem(w,d);
}

void SwitchDialogClose(Widget w,void *data)
{
  struct SwitchDialog *d;
  int j,num;
  char **buf;

  d=(struct SwitchDialog *)data;
  if (d->ret==IDOK) {
    arraydel2(&(menulocal.drawrable));
    num=arraynum(&(d->idrawrable));
    for (j=0;j<num;j++) {
      buf=(char **)arraynget(&(d->drawrable),
         *(int *)arraynget(&(d->idrawrable),j));
      if ((*buf)!=NULL) arrayadd2(&(menulocal.drawrable),buf);
    }
  }
  arraydel2(&(d->drawrable));
  arraydel(&(d->idrawrable));
}

void SwitchDialog(struct SwitchDialog *data)
{
  data->SetupWindow=SwitchDialogSetup;
  data->CloseWindow=SwitchDialogClose;
  arrayinit(&(data->drawrable),sizeof(char *));
  arrayinit(&(data->idrawrable),sizeof(int));
}

void DirectoryDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc;
  struct DirectoryDialog *d;
  char *cwd;
  
  d=(struct DirectoryDialog *)data;
  if (makewidget) {
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc,"Dir",al,ac));
    ac=0;
    XtManageChild(XmCreateTextField(rc,"dir",al,ac));
  }  
  if ((cwd=ngetcwd())!=NULL)
    XtVaSetValues(XtNameToWidget(w,"*dir"),XmNvalue,cwd,NULL);
  memfree(cwd);
}

void DirectoryDialogClose(Widget w,void *data)
{
  struct DirectoryDialog *d;
  char *s;
  
  d=(struct DirectoryDialog *)data;
  if (d->ret==IDCANCEL) return;
  XtVaGetValues(XtNameToWidget(w,"*dir"),XmNvalue,&s,NULL);
  if ((s!=NULL) && (strlen(s)!=0)) chdir(s);
  XtFree(s);
}

void DirectoryDialog(struct DirectoryDialog *data)
{
  data->SetupWindow=DirectoryDialogSetup;
  data->CloseWindow=DirectoryDialogClose;
}

void LoadDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc,rc1;
  struct LoadDialog *d;
  
  d=(struct LoadDialog *)data;
  if (makewidget) {
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
    XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));
    ac=0;
    XtManageChild(XmCreateToggleButton(rc,"ExpandIncludedFile",al,ac));
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc1=XmCreateRowColumn(rc,"rc1",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"Dir",al,ac));
    ac=0;
    XtManageChild(XmCreateTextField(rc1,"dir",al,ac));
    ac=0;
    XtManageChild(XmCreateToggleButton(rc,"IgnoreFilePath",al,ac));
  }
  XtVaSetValues(XtNameToWidget(w,"*ExpandIncludedFile"),
                XmNset,d->expand,NULL);
  XtVaSetValues(XtNameToWidget(w,"*dir"),XmNvalue,d->exdir,NULL);
  XtVaSetValues(XtNameToWidget(w,"*IgnoreFilePath"),XmNset,d->ignorepath,NULL);
}

void LoadDialogClose(Widget w,void *data)
{
  struct LoadDialog *d;
  char *s;
  
  d=(struct LoadDialog *)data;
  if (d->ret==IDCANCEL) return;
  d->expand=XmToggleButtonGetState(XtNameToWidget(w,"*ExpandIncludedFile"));
  XtVaGetValues(XtNameToWidget(w,"*dir"),XmNvalue,&s,NULL);
  memfree(d->exdir);
  d->exdir=memalloc(strlen(s)+1);
  strcpy(d->exdir,s);
  d->ignorepath=XmToggleButtonGetState(XtNameToWidget(w,"*IgnoreFilePath"));
}

void LoadDialog(struct LoadDialog *data)
{
  data->SetupWindow=LoadDialogSetup;
  data->CloseWindow=LoadDialogClose;
  data->expand=menulocal.expand;
  data->exdir=memalloc(strlen(menulocal.expanddir)+1);
  strcpy(data->exdir,menulocal.expanddir);
  data->ignorepath=menulocal.ignorepath;
}

void PrmDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc;
  struct PrmDialog *d;
  int a;
  
  d=(struct PrmDialog *)data;
  if (makewidget) {
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
    XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));
    ac=0;
    XtManageChild(XmCreateToggleButton(rc,"IgnoreFilePath",al,ac));
    ac=0;
    XtManageChild(XmCreateToggleButton(rc,"GreekSymbol",al,ac));
  }
  getobj(d->Obj,"ignore_path",d->Id,0,NULL,&a);
  XtVaSetValues(XtNameToWidget(w,"*IgnoreFilePath"),XmNset,a,NULL);
  getobj(d->Obj,"symbol_greek",d->Id,0,NULL,&a);
  XtVaSetValues(XtNameToWidget(w,"*GreekSymbol"),XmNset,a,NULL);
}

void PrmDialogClose(Widget w,void *data)
{
  int a;
  struct PrmDialog *d;
  
  d=(struct PrmDialog *)data;
  if (d->ret==IDCANCEL) return;
  a=XmToggleButtonGetState(XtNameToWidget(w,"*IgnoreFilePath"));
  if (putobj(d->Obj,"ignore_path",d->Id,&a)==-1) {
    d->ret=IDLOOP;
    return;
  }
  a=XmToggleButtonGetState(XtNameToWidget(w,"*GreekSymbol"));
  if (putobj(d->Obj,"symbol_greek",d->Id,&a)==-1) {
    d->ret=IDLOOP;
    return;
  }
}

void PrmDialog(struct PrmDialog *data,struct objlist *obj,int id)
{
  data->SetupWindow=PrmDialogSetup;
  data->CloseWindow=PrmDialogClose;
  data->Obj=obj;
  data->Id=id;
}

void SaveDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc,rc1;
  int j;
  struct SaveDialog *d;
  
  d=(struct SaveDialog *)data;
  if (makewidget) {
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
    XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc1=XmCreateRowColumn(rc,"rc1",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"Path",al,ac));
    ac=0;
    XtSetArg(al[ac],XmNcomboBoxType,XmDROP_DOWN_LIST); ac++;
    XtManageChild(XmCreateComboBox(rc1,"path",al,ac));
    ac=0;
    XtManageChild(XmCreateToggleButton(rc,"IncludeDataFile",al,ac));
    ac=0;
    XtManageChild(XmCreateToggleButton(rc,"IncludeMergeFile",al,ac));

    for (j=0;pathchar[j]!=NULL;j++);
    SetComboList(w,"*path",pathchar,j);

  }
  XmListDeselectAllItems(GetComboBoxList(w,"*path"));
  XmListSelectPos(GetComboBoxList(w,"*path"),menulocal.savepath+1,TRUE);
  XtVaSetValues(XtNameToWidget(w,"*IncludeDataFile"),XmNset,
                menulocal.savewithdata,NULL);
  XtVaSetValues(XtNameToWidget(w,"*IncludeMergeFile"),XmNset,
                menulocal.savewithmerge,NULL);
}

void SaveDialogClose(Widget w,void *data)
{
  int *selected,num;
  struct SaveDialog *d;
  
  d=(struct SaveDialog *)data;
  if (d->ret==IDCANCEL) return;
  XmListGetSelectedPos(GetComboBoxList(w,"*path"),&selected,&num);
  if (num!=0) {
    d->Path=selected[0]-1;
    XtFree((char *)selected);
  }
  *(d->SaveData)=
    XmToggleButtonGetState(XtNameToWidget(w,"*IncludeDataFile"));
  *(d->SaveMerge)=
    XmToggleButtonGetState(XtNameToWidget(w,"*IncludeMergeFile"));
}

void SaveDialog(struct SaveDialog *data,int *sdata,int *smerge)
{
  data->SetupWindow=SaveDialogSetup;
  data->CloseWindow=SaveDialogClose;
  data->SaveData=sdata;
  data->SaveMerge=smerge;
}

void CmGraphNewFrame()
{
  if (menulock || globallock ) return;
  if (!CheckSave()) return;
  DeleteDrawable();
  CmAxisNewFrame();
  UpdateAll();
  CmViewerDraw();
}

void CmGraphNewSection()
{
  if (menulock || globallock ) return;
  if (!CheckSave()) return;
  DeleteDrawable();
  CmAxisNewSection();
  UpdateAll();
  CmViewerDraw();
}

void CmGraphNewCross()
{
  if (menulock || globallock ) return;
  if (!CheckSave()) return;
  DeleteDrawable();
  CmAxisNewCross();
  UpdateAll();
  CmViewerDraw();
}

void CmGraphAllClear()
{
  if (menulock || globallock ) return;
  if (!CheckSave()) return;
  DeleteDrawable();
  UpdateAll();
  CmViewerDraw();
}

void CmGraphNewMenu(Widget w,XtPointer client_data,XtPointer call_data)
{
  int sel;

  sel=(int )client_data;
  switch (sel) {
  case 0:
    CmGraphNewFrame();
    break;
  case 1:
    CmGraphNewSection();
    break;
  case 2:
    CmGraphNewCross();
    break;
  case 3:
    CmGraphAllClear();
    break;
  default:
    break;
  }
}

void CmGraphLoad()
{
  char *ext;
  char *file;

  if (menulock || globallock) return;
  if (!CheckSave()) return;
  if (nGetOpenFileName(TopLevel,"Load NGP file","ngp",
                   &(menulocal.graphloaddir),NULL,
                   &file,"*.ngp",TRUE,menulocal.changedirectory)==IDOK) {
    if (((ext=getextention(file))!=NULL)
    && ((strcmp0(ext,"PRM")==0) || (strcmp0(ext,"prm")==0))) {
      LoadPrmFile(file);
      NgraphApp.Changed=FALSE;
    } else {
      LoadDialog(&DlgLoad);
      if (DialogExecute(TopLevel,&DlgLoad)==IDOK) { 
        LoadNgpFile(file,DlgLoad.ignorepath,DlgLoad.expand,DlgLoad.exdir,
                    menulocal.scriptconsole,"-f");
        NgraphApp.Changed=FALSE;
      }
      memfree(DlgLoad.exdir);
    }
  }
  free(file);
}

void CmGraphSave()
{
  if (menulock || globallock ) return;
  GraphSave(FALSE);
}

void CmGraphOverWrite()
{
  if (menulock || globallock ) return;
  GraphSave(TRUE);
}

void CmGraphSwitch()
{
  if (menulock || globallock) return;
  SwitchDialog(&DlgSwitch);
  if (DialogExecute(TopLevel,&DlgSwitch)==IDOK) {
    NgraphApp.Changed=TRUE;
    ChangePage();
  }
}

void CmGraphPage()
{
  if (menulock || globallock) return;
  PageDialog(&DlgPage);
  if (DialogExecute(TopLevel,&DlgPage)==IDOK) {
    SetPageSettingsToGRA();
    ChangePage();
    GetPageSettingsFromGRA();
    NgraphApp.Changed=TRUE;
  }
}

void CmGraphDirectory()
{
  if (menulock || globallock) return;
  DirectoryDialog(&DlgDirectory);
  DialogExecute(TopLevel,&DlgDirectory);
}

void CmGraphShell()
{
  struct objlist *obj,*robj,*shell;
  char *inst;
  int idn,allocnow;

  if (menulock || globallock) return;
  menulock=TRUE;
  obj=menulocal.obj;
  inst=menulocal.inst;
  idn=getobjtblpos(obj,"_evloop",&robj);
  registerevloop(chkobjectname(obj),"_evloop",robj,idn,inst,NULL);
  if ((shell=chkobject("shell"))!=NULL) {
    allocnow=AllocConsole();
    exeobj(shell,"shell",0,0,NULL);
    FreeConsole(allocnow);
  }
  unregisterevloop(robj,idn,inst);
  menulock=FALSE;
  UpdateAll();
}

void CmGraphQuit()
{
  int quit;
  XClientMessageEvent event;

  if (menulock || globallock) return;
  quit=CheckSave(); 
  if (quit) {
    SaveHistory(); 
    event.type=ClientMessage;
    event.display=Disp;
    event.window=XtWindow(TopLevel);
    event.message_type=NgraphClose;
    event.format=8;
    XSendEvent(Disp,XtWindow(TopLevel),FALSE,NoEventMask,(XEvent *)&event);
  } 
}

void CmGraphHistory(Widget w,XtPointer client_data,XtPointer call_data)
{
  int i,fil,num,num2;
  char **data,**data2;
  struct narray *ngpfilelist,*ngpdirlist;

  if (menulock || globallock) return;
  for (i=0;i<10;i++) if (w==NgraphApp.ghistory[i]) break;
  fil=i;
  ngpfilelist=menulocal.ngpfilelist;
  ngpdirlist=menulocal.ngpdirlist;
  num=arraynum(ngpfilelist);
  data=(char **)arraydata(ngpfilelist);
  num2=arraynum(ngpdirlist);
  data2=(char **)arraydata(ngpdirlist);
  if ((fil<0) || (fil>=num) || (data[fil]==NULL)) return;
  if (!CheckSave()) return;
  if ((fil>=0) && (fil<num2) && (data2[fil]!=NULL) && (data2[0]!='\0'))
    chdir(data2[fil]);
  LoadDialog(&DlgLoad);
  if (DialogExecute(TopLevel,&DlgLoad)==IDOK) {
    LoadNgpFile(data[fil],DlgLoad.ignorepath,DlgLoad.expand,DlgLoad.exdir,
                menulocal.scriptconsole,"-f");
    NgraphApp.Changed=FALSE;
  }
  memfree(DlgLoad.exdir);
}

void CmGraphLoadB(Widget w,XtPointer client_data,XtPointer call_data)
{
  CmGraphLoad();
}

void CmGraphSaveB(Widget w,XtPointer client_data,XtPointer call_data)
{
  CmGraphSave();
}

void CmGraphMenu(Widget w,XtPointer client_data,XtPointer call_data)
{
  int sel;

  sel=(int )client_data;
  switch (sel) {
  case 1:
    CmGraphLoad();
    break;
  case 2:
    CmGraphSave();
    break;
  case 3:
    CmGraphOverWrite();
    break;
  case 4:
    CmGraphPage();
    break;
  case 5:
    CmGraphSwitch();
    break;
  case 6:
    CmOutputDriver(TRUE);
    break;
  case 7:
    CmGraphDirectory();
    break;
  case 8:
    CmScriptExec();
    break;
  case 9:
    CmGraphShell();
    break;
  case 10: 
    CmGraphQuit();
    break;
  default:
    break;
  }
}

void AboutGPL(Widget w,XtPointer client_data,XtPointer call_data)
{
  pid_t pid;

  if (menulocal.gpl==NULL) return;
  if ((pid=fork())<0) return;
  if (pid==0) {
    system(menulocal.gpl);
    exit(0);
  }
}

void AboutDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget button,rc0,rc,label;
  struct objlist *obj;
  char *version,*email,*web,*copyright;
  char buf[512];
  XmString msg;

  if (makewidget) {
    if ((obj=chkobject("system"))==NULL) return;
    getobj(obj,"version",0,0,NULL,&version);
    getobj(obj,"copyright",0,0,NULL,&copyright);
    getobj(obj,"e-mail",0,0,NULL,&email);
    getobj(obj,"web",0,0,NULL,&web);
    ac=0;
    XtManageChild(button=XmCreatePushButton(w,"GPL",al,ac));
    XtAddCallback(button,XmNdisarmCallback,AboutGPL,NULL);
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
    XtManageChild(rc0=XmCreateRowColumn(w,NULL,al,ac));
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc=XmCreateRowColumn(rc0,NULL,al,ac));
    ac=0;
    XtSetArg(al[ac],XmNlabelType,XmPIXMAP); ac++;
    XtSetArg(al[ac],XmNlabelPixmap,NgraphApp.iconpix); ac++;
    XtManageChild(label=XmCreateLabel(rc,NULL,al,ac));
    XtVaSetValues(label,XmNalignment,XmALIGNMENT_CENTER,NULL);

    sprintf(buf,
    "Ngraph "PLATFORM
    "\nversion %s"GUIVERSION
    "\n\n%s\n%s\n%s\n",version,copyright,email,web);
    msg=XmStringCreateLtoR(buf,XmFONTLIST_DEFAULT_TAG);
    ac=0;
    XtSetArg(al[ac],XmNlabelString,msg); ac++;
    XtManageChild(label=XmCreateLabel(rc,NULL,al,ac));
    XtVaSetValues(label,XmNalignment,XmALIGNMENT_CENTER,NULL);
    XmStringFree(msg);

    sprintf(buf,
"Ngraph comes with ABSOLUTELY NO WARRANTY; for details \npush [GPL] below. This is free software, and you are welcome \nto redistribute it under certain conditions; push [GPL] below \nfor details.");
    msg=XmStringCreateLtoR(buf,XmFONTLIST_DEFAULT_TAG);
    ac=0;
    XtSetArg(al[ac],XmNlabelString,msg); ac++;
    XtManageChild(label=XmCreateLabel(rc0,NULL,al,ac));
    XtVaSetValues(label,XmNalignment,XmALIGNMENT_BEGINNING,NULL);
    XmStringFree(msg);

    XtUnmanageChild(XmMessageBoxGetChild(w,XmDIALOG_CANCEL_BUTTON));
  }
}

void AboutDialog(struct AboutDialog *data)
{
  data->SetupWindow=AboutDialogSetup;
  data->CloseWindow=NULL;
}

void CmHelpAbout()
{
  AboutDialog(&DlgAbout);
  DialogExecute(TopLevel,&DlgAbout);
}

void CmHelpHelp()
{
  pid_t pid;

  if (menulocal.browser==NULL) return;
  if ((pid=fork())<0) return;
  if (pid==0) {
    system(menulocal.browser);
    exit(0);
  }
}

void CmHelpMenu(Widget w,XtPointer client_data,XtPointer call_data)
{
  switch ((int )client_data) {
  case 0: 
    CmHelpAbout();
    break;
  case 1: 
    CmHelpHelp();
    break;
  }
}

