/* 
 * $Id: x11dialg.c,v 1.5 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: x11dialg.c,v $
 * Revision 1.5  2003/02/16 12:43:37  isizaka
 * for release 6.13.18
 *
 * Revision 1.4  2002/07/06 08:57:25  isizaka
 * change to GPL.
 *
 * Revision 1.3  1999/04/11 06:09:20  isizaka
 * *** empty log message ***
 *
 * Revision 1.2  1999/03/21 12:51:43  isizaka
 * change SectionDialog, CrossDialog
 *
 * Revision 1.1  1999/03/17 13:29:01  isizaka
 * Initial revision
 *
 *
 **/

#include <Xm/XmAll.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <time.h>
#include <limits.h>

#include "motif12.h"

#include "ngraph.h"
#include "object.h"

#include "x11gui.h"
#include "x11dialg.h"

void ResetEvent();

char *fwlinestyle[CLINESTYLE]={"solid","dot","short dash","dash","dot dash",
                               "2-dot dash","dot 2-dash"};
char *fwnumstyle[CNUMSTYLE]={"auto","0","1","2","3","4","5","6","7","8","9"};
int fwlinestylelistn[CLINESTYLE]={0,2,2,2,4,6,6};
char *fwlinestylelist[CLINESTYLE]={"","100 100","150 150","450 150",
                                   "450 150 150 150",
                                   "450 150 150 150 150 150",
                                   "450 150 450 150 150 150"};
char *cblinewidth[CBLINEWIDTH]={"10","20","40","80","120"};
char *cbtextpt[CBTEXTPT]={"1200","1600","1800","2000","2400","3000"};
char *cbdirection[CBDIRECTION]={"0","9000","18000","27000"};
char *cbmarksize[CBMARKSIZE]={"100","200","300","400","500"};
char dashes[2]={2,2};

struct FileDialog DlgFile;
struct FileDialog DlgFileDef;
struct EvalDialog DlgEval;
struct MathDialog DlgMath;
struct MathTextDialog DlgMathText;
struct FitDialog DlgFit;
struct FitLoadDialog DlgFitLoad;
struct FitSaveDialog DlgFitSave;
struct FileMoveDialog DlgFileMove;
struct FileMaskDialog DlgFileMask;
struct FileLoadDialog DlgFileLoad;
struct FileMathDialog DlgFileMath;
struct SectionDialog DlgSection;
struct CrossDialog DlgCross;
struct AxisDialog DlgAxis;
struct GridDialog DlgGrid;
struct ZoomDialog DlgZoom;
struct AxisBaseDialog DlgAxisBase;
struct AxisPosDialog DlgAxisPos;
struct NumDialog DlgNum;
struct AxisFontDialog DlgAxisFont;
struct GaugeDialog DlgGauge;
struct MergeDialog DlgMerge;
struct LegendCurveDialog DlgLegendCurve;
struct LegendPolyDialog DlgLegendPoly;
struct LegendArrowDialog DlgLegendArrow;
struct LegendRectDialog DlgLegendRect;
struct LegendArcDialog DlgLegendArc;
struct LegendMarkDialog DlgLegendMark;
struct LegendTextDialog DlgLegendText;
struct LegendTextDialog DlgLegendTextDef;
struct LegendGaussDialog DlgLegendGauss;
struct PageDialog DlgPage;
struct SwitchDialog DlgSwitch;
struct DirectoryDialog DlgDirectory;
struct LoadDialog DlgLoad;
struct PrmDialog DlgPrm;
struct SaveDialog DlgSave;
struct AboutDialog DlgAbout;
struct DriverDialog DlgDriver;
struct PrintDialog DlgPrinter;
struct OutputDataDialog DlgOutputData;
struct ScriptDialog DlgScript;
struct DefaultDialog DlgDefault;
struct SetScriptDialog DlgSetScript;
struct PrefScriptDialog DlgPrefScript;
struct SetDriverDialog DlgSetDriver;
struct PrefDriverDialog DlgPrefDriver;
struct MiscDialog DlgMisc;
struct ExViewerDialog DlgExViewer;
struct ViewerDialog DlgViewer;
struct SelectDialog DlgSelect;
struct CopyDialog DlgCopy;

void initdialog()
{
  DlgFile.widget=NULL;
  DlgFile.resource="data";
  DlgFile.mark.widget=NULL;
  DlgFile.mark.resource="markselection";
  DlgFileDef.widget=NULL;
  DlgFileDef.resource="datadefault";
  DlgFileDef.mark.widget=NULL;
  DlgFileDef.mark.resource="markselection";
  DlgEval.widget=NULL;
  DlgEval.resource="evaluation";
  DlgMath.widget=NULL;
  DlgMath.resource="math";
  DlgMathText.widget=NULL;
  DlgMathText.resource="mathtext";
  DlgFit.widget=NULL;
  DlgFit.resource="fit";
  DlgFitLoad.widget=NULL;
  DlgFitLoad.resource="fitload";
  DlgFitSave.widget=NULL;
  DlgFitSave.resource="fitsave";
  DlgFileMove.widget=NULL;
  DlgFileMove.resource="datamove";
  DlgFileMask.widget=NULL;
  DlgFileMask.resource="datamask";
  DlgFileLoad.widget=NULL;
  DlgFileLoad.resource="dataload";
  DlgFileMath.widget=NULL;
  DlgFileMath.resource="datamath";
  DlgSection.widget=NULL;
  DlgSection.resource="section";
  DlgCross.widget=NULL;
  DlgCross.resource="cross";
  DlgAxis.widget=NULL;
  DlgAxis.resource="axis";
  DlgGrid.widget=NULL;
  DlgGrid.resource="grid";
  DlgZoom.widget=NULL;
  DlgZoom.resource="zoom";
  DlgAxisBase.widget=NULL;
  DlgAxisBase.resource="axisbaseline";
  DlgAxisPos.widget=NULL;
  DlgAxisPos.resource="axisposition";
  DlgNum.widget=NULL;
  DlgNum.resource="numbering";
  DlgAxisFont.widget=NULL;
  DlgAxisFont.resource="axisfont";
  DlgGauge.widget=NULL;
  DlgGauge.resource="gauge";
  DlgMerge.widget=NULL;
  DlgMerge.resource="merge";
  DlgLegendCurve.widget=NULL;
  DlgLegendCurve.resource="curve";
  DlgLegendPoly.widget=NULL;
  DlgLegendPoly.resource="polygon";
  DlgLegendArrow.widget=NULL;
  DlgLegendArrow.resource="line";
  DlgLegendRect.widget=NULL;
  DlgLegendRect.resource="rectangle";
  DlgLegendArc.widget=NULL;
  DlgLegendArc.resource="arc";
  DlgLegendMark.widget=NULL;
  DlgLegendMark.resource="mark";
  DlgLegendMark.mark.widget=NULL;
  DlgLegendMark.mark.resource="markselection";
  DlgLegendText.widget=NULL;
  DlgLegendText.resource="text";
  DlgLegendTextDef.widget=NULL;
  DlgLegendTextDef.resource="textdefault";
  DlgLegendGauss.widget=NULL;
  DlgLegendGauss.resource="gauss";
  DlgPage.widget=NULL;
  DlgPage.resource="page";
  DlgSwitch.widget=NULL;
  DlgSwitch.resource="drawobj";
  DlgDirectory.widget=NULL;
  DlgDirectory.resource="directory";
  DlgLoad.widget=NULL;
  DlgLoad.resource="load";
  DlgPrm.widget=NULL;
  DlgPrm.resource="loadprm";
  DlgSave.widget=NULL;
  DlgSave.resource="save";
  DlgAbout.widget=NULL;
  DlgAbout.resource="about";
  DlgDriver.widget=NULL;
  DlgDriver.resource="driver";
  DlgPrinter.widget=NULL;
  DlgPrinter.resource="print";
  DlgOutputData.widget=NULL;
  DlgOutputData.resource="outputdata";
  DlgScript.widget=NULL;
  DlgScript.resource="addin";
  DlgDefault.widget=NULL;
  DlgDefault.resource="savedefault";
  DlgSetScript.widget=NULL;
  DlgSetScript.resource="setscript";
  DlgPrefScript.widget=NULL;
  DlgPrefScript.resource="prefscript";
  DlgSetDriver.widget=NULL;
  DlgSetDriver.resource="setdriver";
  DlgPrefDriver.widget=NULL;
  DlgPrefDriver.resource="prefdriver";
  DlgMisc.widget=NULL;
  DlgMisc.resource="misc";
  DlgExViewer.widget=NULL;
  DlgExViewer.resource="extviewer";
  DlgViewer.widget=NULL;
  DlgViewer.resource="viewer";
  DlgSelect.widget=NULL;
  DlgSelect.resource="multi_select";
  DlgCopy.widget=NULL;
  DlgCopy.resource="single_select";
}

void SelectDialogAllCB(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SelectDialog *data;

  data=(struct SelectDialog *)client_data;
  data->ret=IDSALL;
  data->CloseWindow(XtParent(w),data);
}

void SelectDialogDblCB(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SelectDialog *data;

  data=(struct SelectDialog *)client_data;
  data->ret=IDOK;
  data->CloseWindow(XtParent(w),data);
}

void SelectDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  XmString xs;
  char *s;
  struct SelectDialog *d;
  int i,*seldata,selnum;
  Widget list,button;

  d=(struct SelectDialog *)data;
  if (makewidget) {
    ac=0;
    XtSetArg(al[ac],XmNlistSizePolicy,XmCONSTANT); ac++;
    XtSetArg(al[ac],XmNscrollBarDisplayPolicy,XmSTATIC); ac++;
    XtSetArg(al[ac],XmNselectionPolicy,XmEXTENDED_SELECT); ac++;
    XtManageChild(list=XmCreateScrolledList(w,"list",al,ac));
    XtAddCallback(list,XmNdefaultActionCallback,SelectDialogDblCB,data);
    ac=0;
    XtManageChild(button=XmCreatePushButton(w,"All",al,ac));
    XtAddCallback(button,XmNdisarmCallback,SelectDialogAllCB,data);
  }
  XmListDeleteAllItems(XtNameToWidget(w,"*list"));
  for (i=0;i<=chkobjlastinst(d->Obj);i++) {
    s=d->cb(d->Obj,i);
    if (s!=NULL) xs=XmStringCreateLocalized(s);
    else xs=XmStringCreateLocalized("");
    XmListAddItem(XtNameToWidget(w,"*list"),xs,0);
    XmStringFree(xs);
    memfree(s);
  }
  if (makewidget) {
    XtManageChild(d->widget);
    d->widget=NULL;
    XtVaSetValues(XtNameToWidget(w,"*list"),XmNwidth,200,NULL);
  }
  if (d->isel!=NULL) {
    seldata=arraydata(d->isel);
    selnum=arraynum(d->isel);
    XtVaSetValues(XtNameToWidget(w,"*list"),
                  XmNselectionPolicy,XmMULTIPLE_SELECT,NULL);
    for (i=0;i<selnum;i++) {
      XmListSelectPos(XtNameToWidget(w,"*list"),seldata[i]+1,FALSE);
    }
    XtVaSetValues(XtNameToWidget(w,"*list"),
                  XmNselectionPolicy,XmEXTENDED_SELECT,NULL);
  }
}

void SelectDialogClose(Widget w,void *data)
{
  int i,a;
  struct SelectDialog *d;
  int num;
  int *selected;

  d=(struct SelectDialog *)data;
  if (d->ret==IDOK) {
    XmListGetSelectedPos(XtNameToWidget(w,"*list"),&selected,&num);
    if (num!=0) {
      for (i=0;i<num;i++) {
        a=selected[i]-1;
        arrayadd(d->sel,&a);
      }
      XtFree((char *)selected);
    }
  } else if (d->ret==IDSALL) {
    for (i=0;i<=chkobjlastinst(d->Obj);i++) arrayadd(d->sel,&i);
    d->ret=IDOK;
  }
}

void SelectDialog(struct SelectDialog *data,
                  struct objlist *obj,
                  char *(*callback)(struct objlist *obj,int id),
                  struct narray *array,struct narray *iarray)
{
  data->SetupWindow=SelectDialogSetup;
  data->CloseWindow=SelectDialogClose;
  data->Obj=obj;
  data->cb=callback;
  arrayinit(array,sizeof(int));
  data->sel=array;
  data->isel=iarray;
}

void CopyDialogDblCB(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct SelectDialog *data;
  XmListCallbackStruct *d;

  data=(struct SelectDialog *)client_data;
  d=(XmListCallbackStruct *)call_data;
  data->ret=IDOK;
  data->CloseWindow(XtParent(w),data);
}

void CopyDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  XmString xs;
  char *s;
  struct CopyDialog *d;
  int i;
  Widget list;

  d=(struct CopyDialog *)data;
  if (makewidget) {
    ac=0;
    XtSetArg(al[ac],XmNlistSizePolicy,XmCONSTANT); ac++;
    XtSetArg(al[ac],XmNscrollBarDisplayPolicy,XmSTATIC); ac++;
    XtSetArg(al[ac],XmNselectionPolicy,XmBROWSE_SELECT); ac++;
    XtManageChild(list=XmCreateScrolledList(w,"list",al,ac));
    XtAddCallback(list,XmNdefaultActionCallback,CopyDialogDblCB,data);
  }
  XmListDeleteAllItems(XtNameToWidget(w,"*list"));
  for (i=0;i<=chkobjlastinst(d->Obj);i++) {
    s=d->cb(d->Obj,i);
    if (s!=NULL) xs=XmStringCreateLocalized(s);
    else xs=XmStringCreateLocalized("");
    XmListAddItem(XtNameToWidget(w,"*list"),xs,0);
    XmStringFree(xs);
    memfree(s);
  }
  if (d->Id>=0)
    XmListSelectPos(XtNameToWidget(w,"*list"),d->Id+1,FALSE);
  if (makewidget) {
    XtManageChild(d->widget);
    d->widget=NULL;
    XtVaSetValues(XtNameToWidget(w,"*list"),XmNwidth,200,NULL);
  }
}

void CopyDialogClose(Widget w,void *data)
{
  struct CopyDialog *d;
  int *selected;
  int num;

  d=(struct CopyDialog *)data;
  if (d->ret==IDCANCEL) return;
  XmListGetSelectedPos(XtNameToWidget(w,"*list"),&selected,&num);
  if (num!=0) {
    d->sel=selected[0]-1;
    XtFree((char *)selected);
  } else d->sel=-1;
}

void CopyDialog(struct CopyDialog *data,
                  struct objlist *obj,int id,
                  char *(*callback)(struct objlist *obj,int id))
{
  data->SetupWindow=CopyDialogSetup;
  data->CloseWindow=CopyDialogClose;
  data->Obj=obj;
  data->Id=id;
  data->cb=callback;
  data->sel=id;
}

int CopyClick(Widget parent,struct objlist *obj,int Id,
              char *(*callback)(struct objlist *obj,int id))
{
  int sel;

  CopyDialog(&DlgCopy,obj,Id,callback);
  if (DialogExecute(parent,&DlgCopy)==IDOK) sel=DlgCopy.sel;
  else sel=-1;
  return sel;
}

int SetObjFieldFromText(Widget w,char *res,struct objlist *Obj,int Id,
                        char *field)
{
  char *buf;

  if (res==NULL) XtVaGetValues(w,XmNvalue,&buf,NULL);
  else XtVaGetValues(XtNameToWidget(w,res),XmNvalue,&buf,NULL);
  if (sputobjfield(Obj,Id,field,buf)!=0) {
    XtFree(buf);
    return -1;
  }
  XtFree(buf);
  return 0;
}

void SetTextFromObjField(Widget w,char *res,struct objlist *Obj,int Id,
                         char *field)
{
  char *buf;

  sgetobjfield(Obj,Id,field,NULL,&buf,FALSE,FALSE,FALSE);
  if (res==NULL) XtVaSetValues(w,XmNvalue,buf,NULL);
  else XtVaSetValues(XtNameToWidget(w,res),XmNvalue,buf,NULL);
  memfree(buf);
}

void SetComboListFromObjField(Widget w,char *res,struct objlist *Obj,int Id,
                              char *field)
{
  char *buf;
  XmString xs;

  sgetobjfield(Obj,Id,field,NULL,&buf,FALSE,FALSE,FALSE);
  if (buf!=NULL) {
    xs=XmStringCreateLocalized(buf);
    XmListSelectItem(w,xs,FALSE);
    XmStringFree(xs);
    memfree(buf);
  }
}

int SetObjFieldFromToggle(Widget w,char *res,struct objlist *Obj,int Id,
                          char *field)
{
  int a;

  a=XmToggleButtonGetState(XtNameToWidget(w,res));
  a=a?TRUE:FALSE;
  if (putobj(Obj,field,Id,&a)==-1) return -1;
  return 0;
}

void SetToggleFromObjField(Widget w,char *res,struct objlist *Obj,int Id,
                           char *field)
{
  int a;

  getobj(Obj,field,Id,0,NULL,&a);
  XmToggleButtonSetState(XtNameToWidget(w,res),a,TRUE);
}

int SetObjFieldFromStyle(Widget w,char *res,struct objlist *Obj,int Id,
                         char *field)
{
  int j;
  char *buf;

  XtVaGetValues(GetComboBoxText(w,res),XmNvalue,&buf,NULL);
  for (j=0;j<CLINESTYLE;j++) {
    if (strcmp(buf,fwlinestyle[j])==0) {
      if (sputobjfield(Obj,Id,field,fwlinestylelist[j])!=0) {
        XtFree(buf);
        return -1;
      }
      break;
    }
  }
  if (j==CLINESTYLE) {
    if (sputobjfield(Obj,Id,field,buf)!=0) {
      XtFree(buf);
      return -1;
    }
  }
  XtFree(buf);
  return 0;
}

void SetStyleFromObjField(Widget w,char *res,struct objlist *Obj,int Id,
                          char *field)
{
  int i,j;
  struct narray *array;
  int stylenum;
  int *style,a;
  XmString xs;
  char *s;
  int count;

  XtVaGetValues(GetComboBoxList(w,res),XmNitemCount,&count,NULL);
  if (count==0) {
    XmListDeleteAllItems(GetComboBoxList(w,res));
    for (j=0;j<CLINESTYLE;j++) {
      xs=XmStringCreateLocalized(fwlinestyle[j]);
      XmListAddItem(GetComboBoxList(w,res),xs,0);
      XmStringFree(xs);
    }
    SetComboBoxVisibleItemCount(w,res,j);
  }
  getobj(Obj,field,Id,0,NULL,&array);
  stylenum=arraynum(array);
  style=(int *)arraydata(array);
  for (j=0;j<CLINESTYLE;j++) {
    if (stylenum==fwlinestylelistn[j]) {
      s=fwlinestylelist[j];
      for (i=0;i<fwlinestylelistn[j];i++) {
        a=strtol(s,&s,10);
        if (style[i]!=a) break;
      }
      if (i==fwlinestylelistn[j]) goto match;
    }
  }
  SetTextFromObjField(GetComboBoxText(w,res),NULL,Obj,Id,field);
  return;
match:
  XmListSelectPos(GetComboBoxList(w,res),j+1,TRUE);
}

int SetObjFieldFromList(Widget w,char *res,struct objlist *Obj,int Id,
                        char *field)
{
  int *selected,pos,count;

  XmListGetSelectedPos(GetComboBoxList(w,res),&selected,&count);
  if (count!=0) {
    pos=selected[0]-1;
    XtFree((char *)selected);
    if (putobj(Obj,field,Id,&pos)==-1) return -1;
  }
  return 0;
}

void SetListFromObjField(Widget w,char *res,struct objlist *Obj,int Id,
                         char *field)
{
  char **enumlist;
  int j,a;
  XmString xs;
  int count;

  XtVaGetValues(GetComboBoxList(w,res),XmNitemCount,&count,NULL);
  if (count==0) {
    XmListDeleteAllItems(GetComboBoxList(w,res));
    enumlist=(char **)chkobjarglist(Obj,field);
    for (j=0;enumlist[j]!=NULL;j++) {
      xs=XmStringCreateLocalized(enumlist[j]);
      XmListAddItem(GetComboBoxList(w,res),xs,0);
      XmStringFree(xs);
    }
    SetComboBoxVisibleItemCount(w,res,j);
  }
  getobj(Obj,field,Id,0,NULL,&a);
  XmListSelectPos(GetComboBoxList(w,res),a+1,TRUE);
}

void SetComboList(Widget w,char *res,char **list,int num)
{
  int j;
  XmString xs;
  int count;

  XtVaGetValues(GetComboBoxList(w,res),XmNitemCount,&count,NULL);
  if (count==0) {
    XmListDeleteAllItems(GetComboBoxList(w,res));
    for (j=0;j<num;j++) {
      xs=XmStringCreateLocalized(list[j]);
      XmListAddItem(GetComboBoxList(w,res),xs,0);
      XmStringFree(xs);
    }
    SetComboBoxVisibleItemCount(w,res,j);
  }
  XmListDeselectAllItems(GetComboBoxList(w,res));
}

void SetComboList2(Widget w,char *res,char **list,int num)
{
  int j;
  XmString xs;

  XmListDeleteAllItems(GetComboBoxList(w,res));
  for (j=0;j<num;j++) {
    xs=XmStringCreateLocalized(list[j]);
    XmListAddItem(GetComboBoxList(w,res),xs,0);
    XmStringFree(xs);
  }
  SetComboBoxVisibleItemCount(w,res,j);
  XmListDeselectAllItems(GetComboBoxList(w,res));
}

Widget GetComboBoxText(Widget w,char *res)
{
  if (res==NULL) return XtNameToWidget(w,COMBOTEXT);
  else return XtNameToWidget(XtNameToWidget(w,res),COMBOTEXT);
}

Widget GetComboBoxList(Widget w,char *res)
{
  if (res==NULL) return XtNameToWidget(w,COMBOLIST);
  else return XtNameToWidget(XtNameToWidget(w,res),COMBOLIST);
}

void SetComboBoxVisibleItemCount(Widget w,char *res,int count)
{
  if ((count<=0) || (count>30)) count=10;
  XtVaSetValues(GetComboBoxList(w,res),XmNvisibleItemCount,count-1,NULL);
}
