/* 
 * $Id: x11print.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: x11print.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  2001/03/23 12:17:43  isizaka
 * for 6.3.13
 *
 * 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 <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include "motif12.h"

#include "ngraph.h"
#include "object.h"
#include "ioutil.h"
#include "mathcode.h"

#include "x11gui.h"
#include "x11dialg.h"
#include "ox11menu.h"
#include "x11menu.h"
#include "x11print.h"
#include "x11file.h"
#include "x11commn.h"
#include "x11view.h"

void DriverDialogSelectCB(Widget w,XtPointer client_data,XtPointer call_data)
{
  int a,i,j;
  char *s;
  struct extprinter *pcur;
  struct DriverDialog *d;
  XmComboBoxCallbackStruct *dd;
  char buf[1024];
  
  dd=(XmComboBoxCallbackStruct *)call_data;
  d=(struct DriverDialog *)client_data;
#ifdef ZEROBASECOMBOBOX
  a=dd->item_position;
#else
  a=dd->item_position-1;
#endif
  if (a<0) return;
  pcur=menulocal.extprinterroot;
  i=0;
  while (pcur!=NULL) {
    if (i==a) {
      XtVaSetValues(XtNameToWidget(d->widget,"*file"),XmNvalue,"",NULL);
      if ((pcur->ext!=NULL) && (pcur->ext[0]!='\0') 
      && (NgraphApp.FileName!=NULL)) {
        strcpy(buf,NgraphApp.FileName);
        if (strchr(buf,'.')!=NULL) {
          for (j=strlen(buf)-1;buf[j]!='.';j--);
          buf[j]='\0';
        }
        strcat(buf,pcur->ext);
        XtVaSetValues(XtNameToWidget(d->widget,"*file"),XmNvalue,buf,NULL);
      }
      if (pcur->option==NULL) s="";
      else s=pcur->option;
      XtVaSetValues(XtNameToWidget(d->widget,"*option"),XmNvalue,s,NULL);
      break;
    }
    pcur=pcur->next;
    i++;
  }
}

void DriverDialogBrowseCB(Widget w,XtPointer client_data,XtPointer call_data)
{
  char *file;
  struct DriverDialog *d;
  
  d=(struct DriverDialog *)client_data;
  if (nGetSaveFileName(TopLevel,"External Driver Output",NULL,NULL,
      NULL,&file,"*",menulocal.changedirectory)==IDOK) {
    XtVaSetValues(XtNameToWidget(d->widget,"*file"),XmNvalue,file,NULL);
  }
  free(file);
}

void DriverDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc,rc1;
  XmString s;
  struct DriverDialog *d;
  struct extprinter *pcur;
  int j;
 
  d=(struct DriverDialog *)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,"driverrc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"Driver",al,ac));
    ac=0;
    XtSetArg(al[ac],XmNcomboBoxType,XmDROP_DOWN_LIST); ac++;
    XtManageChild(XmCreateComboBox(rc1,"driver",al,ac));
    XtAddCallback(XtNameToWidget(w,"*driver"),XmNselectionCallback,
                  DriverDialogSelectCB,d);
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc1=XmCreateRowColumn(rc,"optionrc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"Option",al,ac));
    ac=0;
    XtManageChild(XmCreateTextField(rc1,"option",al,ac));
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc1=XmCreateRowColumn(rc,"filerc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"File",al,ac));
    ac=0;
    XtManageChild(XmCreateTextField(rc1,"file",al,ac));
    ac=0;
    XtManageChild(XmCreatePushButton(rc1,"Browse",al,ac));
    XtAddCallback(XtNameToWidget(w,"*Browse"),XmNdisarmCallback,
                  DriverDialogBrowseCB,d);
  }
  XmListDeleteAllItems(GetComboBoxList(w,"*driver"));
  pcur=menulocal.extprinterroot;
  j=0;
  while (pcur!=NULL) {
    s=XmStringCreateLocalized(pcur->name);
    XmListAddItem(GetComboBoxList(w,"*driver"),s,0);
    XmStringFree(s);
    pcur=pcur->next;
    j++;
  }
  SetComboBoxVisibleItemCount(w,"*driver",j);
  XmListSelectPos(GetComboBoxList(w,"*driver"),1,TRUE);
}

void DriverDialogClose(Widget w,void *data)
{
  int a,*selected,count,i,j,len1,len2;
  struct extprinter *pcur;
  struct DriverDialog *d;
  char *s,*driver,*option,*file;
  char *buf;

  d=(struct DriverDialog *)data;
  if (d->ret==IDCANCEL) return;
  XmListGetSelectedPos(GetComboBoxList(w,"*driver"),&selected,&count);
  if (count!=0) {
    a=selected[0]-1;
    XtFree((char *)selected);
    pcur=menulocal.extprinterroot;
    i=0;
    while (pcur!=NULL) {
      if (i==a) {
        if (pcur->driver!=NULL) {
          if ((driver=(char *)memalloc(strlen(pcur->driver)+1))!=NULL) {
            strcpy(driver,pcur->driver);
            putobj(d->Obj,"driver",d->Id,driver);
          }
        }
        break;
      }
      pcur=pcur->next;
      i++;
    }
  }
  XtVaGetValues(XtNameToWidget(w,"*option"),XmNvalue,&s,NULL);
  XtVaGetValues(XtNameToWidget(w,"*file"),XmNvalue,&file,NULL);
  if (s==NULL) len1=0;
  else len1=strlen(s);
  if (file==NULL) len2=0;
  else len2=strlen(file);
  if ((option=memalloc(len1+len2+7))!=NULL) {
    j=0;
    option[j]='\0';
    if (len2!=0) {
      if (access(file,04)==0) {
        buf=(char *)memalloc(len2+60);
        if (buf!=NULL) {
          sprintf(buf,"`%s'\n\nOverwrite existing file?",file);
          if (MessageBox(TopLevel,buf,"Driver",MB_YESNO)!=IDYES) {
            memfree(buf);
            memfree(option);
            XtFree(s);
            XtFree(file);
            d->ret=IDCANCEL;
            return;
          }
          memfree(buf);
        } else {
          if (MessageBox(TopLevel,"Overwrite existing file?",
                         "Driver",MB_YESNO)!=IDNO) {
            memfree(option);
            XtFree(s);
            XtFree(file);
            d->ret=IDCANCEL;
            return;
          }
        }
      }
      option[j++]='-';
      option[j++]='o';
      option[j++]=' ';
      option[j++]='\'';
      strcpy(option+j,file);
      j=strlen(option);
      option[j++]='\'';
      option[j++]=' ';
      option[j]='\0';
      changefilename(option);
    }
    if (len1!=0) strcat(option,s);
    putobj(d->Obj,"option",d->Id,option);
  } else {
    XtFree(s);
    XtFree(file);
    d->ret=IDCANCEL;
    return;
  }
  XtFree(s);
  XtFree(file);
}

void DriverDialog(struct DriverDialog *data,
                 struct objlist *obj,int id)
{
  data->SetupWindow=DriverDialogSetup;
  data->CloseWindow=DriverDialogClose;
  data->Obj=obj;
  data->Id=id;
}

void PrintDialogSelectCB(Widget w,XtPointer client_data,XtPointer call_data)
{
  int a,i;
  char *s;
  struct prnprinter *pcur;
  struct PrintDialog *d;
  XmComboBoxCallbackStruct *dd;
  
  dd=(XmComboBoxCallbackStruct *)call_data;
  d=(struct PrintDialog *)client_data;
#ifdef ZEROBASECOMBOBOX
  a=dd->item_position;
#else
  a=dd->item_position-1;
#endif
  if (a<0) return;
  pcur=menulocal.prnprinterroot;
  i=0;
  while (pcur!=NULL) {
    if (i==a) {
      if (pcur->option==NULL) s="";
      else s=pcur->option;
      XtVaSetValues(XtNameToWidget(d->widget,"*option"),XmNvalue,s,NULL);
      if (pcur->prn==NULL) s="";
      else s=pcur->prn;
      XtVaSetValues(XtNameToWidget(d->widget,"*print"),XmNvalue,s,NULL);
      break;
    }
    pcur=pcur->next;
    i++;
  }
}

void PrintDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc,rc1;
  XmString s;
  struct PrintDialog *d;
  struct prnprinter *pcur;
  int j; 

  d=(struct PrintDialog *)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,"driverrc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"Driver",al,ac));
    ac=0;
    XtSetArg(al[ac],XmNcomboBoxType,XmDROP_DOWN_LIST); ac++;
    XtManageChild(XmCreateComboBox(rc1,"driver",al,ac));
    XtAddCallback(XtNameToWidget(w,"*driver"),XmNselectionCallback,
                  PrintDialogSelectCB,d);
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc1=XmCreateRowColumn(rc,"optionrc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"Option",al,ac));
    ac=0;
    XtManageChild(XmCreateTextField(rc1,"option",al,ac));
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc1=XmCreateRowColumn(rc,"printrc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc1,"Print",al,ac));
    ac=0;
    XtManageChild(XmCreateTextField(rc1,"print",al,ac));
  }

  XmListDeleteAllItems(GetComboBoxList(w,"*driver"));
  pcur=menulocal.prnprinterroot;
  j=0;
  while (pcur!=NULL) {
    s=XmStringCreateLocalized(pcur->name);
    XmListAddItem(GetComboBoxList(w,"*driver"),s,0);
    XmStringFree(s);
    pcur=pcur->next;
    j++;
  }
  SetComboBoxVisibleItemCount(w,"*driver",j);
  XmListSelectPos(GetComboBoxList(w,"*driver"),1,TRUE);
}

void PrintDialogClose(Widget w,void *data)
{
  int a,*selected,count,i;
  struct prnprinter *pcur;
  struct PrintDialog *d;
  char *s,*driver,*option,*prn;
  
  d=(struct PrintDialog *)data;
  if (d->ret==IDCANCEL) return;
  XmListGetSelectedPos(GetComboBoxList(w,"*driver"),&selected,&count);
  if (count!=0) {
    a=selected[0]-1;
    XtFree((char *)selected);
    pcur=menulocal.prnprinterroot;
    i=0;
    while (pcur!=NULL) {
      if (i==a) {
        if (pcur->driver!=NULL) {
          if ((driver=(char *)memalloc(strlen(pcur->driver)+1))!=NULL) {
            strcpy(driver,pcur->driver);
            putobj(d->Obj,"driver",d->Id,driver);
          }
        }
        break;
      }
      pcur=pcur->next;
      i++;
    }
  }
  XtVaGetValues(XtNameToWidget(w,"*option"),XmNvalue,&s,NULL);
  if ((s!=NULL) && (strlen(s)!=0)) {
    if ((option=(char *)memalloc(strlen(s)+1))!=NULL) {
      strcpy(option,s);
      putobj(d->Obj,"option",d->Id,option);
    }
  }
  XtFree(s);
  XtVaGetValues(XtNameToWidget(w,"*print"),XmNvalue,&s,NULL);
  if ((s!=NULL) && (strlen(s)!=0)) {
    if ((prn=(char *)memalloc(strlen(s)+1))!=NULL) {
      strcpy(prn,s);
      putobj(d->Obj,"prn",d->Id,prn);
    }
  }
  XtFree(s);
}

void PrintDialog(struct PrintDialog *data,
                 struct objlist *obj,int id)
{
  data->SetupWindow=PrintDialogSetup;
  data->CloseWindow=PrintDialogClose;
  data->Obj=obj;
  data->Id=id;
}

void OutputDataDialogSetupItem(Widget w,struct OutputDataDialog *d)
{
  char buf[256];

  sprintf(buf,"%d",d->div);
  XtVaSetValues(XtNameToWidget(w,"*div"),XmNvalue,buf,NULL);
}

void OutputDataDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc;
  struct OutputDataDialog *d;
  
  d=(struct OutputDataDialog *)data;
  if (makewidget) {
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));
    ac=0;
    XtManageChild(XmCreateLabel(rc,"Div",al,ac));
    ac=0;
    XtManageChild(XmCreateTextField(rc,"div",al,ac));
  }
  OutputDataDialogSetupItem(w,d);
}

void OutputDataDialogClose(Widget w,void *data)
{
  struct OutputDataDialog *d;
  int a;
  char *buf,*endptr;
  
  d=(struct OutputDataDialog *)data;
  if (d->ret!=IDOK) return;
  XtVaGetValues(XtNameToWidget(d->widget,"*div"),XmNvalue,&buf,NULL);
  a=strtol(buf,&endptr,10);
  if (endptr[0]=='\0') d->div=a;
  XtFree(buf);
}

void OutputDataDialog(struct OutputDataDialog *data,int div)
{
  data->SetupWindow=OutputDataDialogSetup;
  data->CloseWindow=OutputDataDialogClose;
  data->div=div;
}

void CmOutputDriver(int print)
{
  struct objlist *graobj,*g2wobj;
  int id,g2wid,g2woid;
  char *device,*g2winst;
  int GC;
  struct narray *drawrable;
  int i,ret;
  struct savedstdio stdio;

  if (menulock || globallock ) return;
  if (SetFileHidden()) {
    FileAutoScale();
    AdjustAxis();
    if ((graobj=chkobject("gra"))==NULL) return;
    if ((g2wobj=chkobject("gra2prn"))==NULL) return;
    g2wid=newobj(g2wobj);
    if (g2wid>=0) {
      if (print) {
        PrintDialog(&DlgPrinter,g2wobj,g2wid);
        ret=DialogExecute(TopLevel,&DlgPrinter);
      } else {
        DriverDialog(&DlgDriver,g2wobj,g2wid);
        ret=DialogExecute(TopLevel,&DlgDriver);
      }
      if (ret==IDOK) {
        SetStatusBar("Spawning external driver.");
        g2winst=chkobjinst(g2wobj,g2wid);
        _getobj(g2wobj,"oid",g2winst,&g2woid);
        id=newobj(graobj);
        putobj(graobj,"paper_width",id,&(menulocal.PaperWidth));
        putobj(graobj,"paper_height",id,&(menulocal.PaperHeight));
        putobj(graobj,"left_margin",id,&(menulocal.LeftMargin));
        putobj(graobj,"top_margin",id,&(menulocal.TopMargin));
        putobj(graobj,"zoom",id,&(menulocal.PaperZoom));
        if (arraynum(&(menulocal.drawrable))>0) {
          drawrable=arraynew(sizeof(char *));
          for (i=0;i<arraynum(&(menulocal.drawrable));i++) {
            arrayadd2(drawrable,(char **)arraynget(&(menulocal.drawrable),i));
          }
        } else drawrable=NULL;
        putobj(graobj,"draw_obj",id,drawrable);
        device=(char *)memalloc(20);
        sprintf(device,"gra2prn:^%d",g2woid);
        putobj(graobj,"device",id,device);
        SetStatusBar("Printing.");
        ignorestdio(&stdio);
        getobj(graobj,"open",id,0,NULL,&GC);
        exeobj(graobj,"draw",id,0,NULL);
        exeobj(graobj,"flush",id,0,NULL);
        exeobj(graobj,"close",id,0,NULL);
        restorestdio(&stdio);
        delobj(graobj,id);
        ResetStatusBar();
      }
      delobj(g2wobj,g2wid);
    }
  }
}

void CmOutputViewer()
{
  struct objlist *graobj,*g2wobj;
  int id,g2wid,g2woid;
  char *device,*g2winst;
  int GC,delgra;
  struct narray *drawrable;
  int i;

  if (menulock || globallock ) return;
  if (SetFileHidden()) {
    FileAutoScale();
    AdjustAxis();
    if ((graobj=chkobject("gra"))==NULL) return;
    if ((g2wobj=chkobject("gra2x11"))==NULL) return;
    SetStatusBar("Spawning external viewer.");
    g2wid=newobj(g2wobj);
    if (g2wid!=-1) {
      g2winst=chkobjinst(g2wobj,g2wid);
      _getobj(g2wobj,"oid",g2winst,&g2woid);
      putobj(g2wobj,"dpi",g2wid,&(menulocal.exwindpi));
      putobj(g2wobj,"store_in_memory",g2wid,&(menulocal.exwinbackingstore));
      id=newobj(graobj);
      putobj(graobj,"paper_width",id,&(menulocal.PaperWidth));
      putobj(graobj,"paper_height",id,&(menulocal.PaperHeight));
      putobj(graobj,"left_margin",id,&(menulocal.LeftMargin));
      putobj(graobj,"top_margin",id,&(menulocal.TopMargin));
      putobj(graobj,"zoom",id,&(menulocal.PaperZoom));
      if (arraynum(&(menulocal.drawrable))>0) {
        drawrable=arraynew(sizeof(char *));
        for (i=0;i<arraynum(&(menulocal.drawrable));i++) {
          arrayadd2(drawrable,(char **)arraynget(&(menulocal.drawrable),i));
        }
      } else drawrable=NULL;
      putobj(graobj,"draw_obj",id,drawrable);
      device=(char *)memalloc(20);
      sprintf(device,"gra2x11:^%d",g2woid);
      putobj(graobj,"device",id,device);
      getobj(graobj,"open",id,0,NULL,&GC);
      exeobj(graobj,"draw",id,0,NULL);
      exeobj(graobj,"flush",id,0,NULL);
      delgra=TRUE;
      _putobj(g2wobj,"delete_gra",g2winst,&delgra);
    }
    ResetStatusBar();
  }
}

void CmPrintGRAFile()
{
  struct objlist *graobj,*g2wobj;
  int id,g2wid,g2woid;
  char *device,*g2winst;
  int GC;
  char *file,*buf;
  struct narray *drawrable;
  int i;
  char *filebuf;

  if (menulock || globallock ) return;
  if (nGetSaveFileName(TopLevel,"GRA file","gra",NULL,NULL,
      &filebuf,"*.gra",menulocal.changedirectory)==IDOK) {
    if (access(filebuf,04)==0) {
      buf=(char *)memalloc(strlen(filebuf)+60);
      if (buf!=NULL) {
        sprintf(buf,"`%s'\n\nOverwrite existing file?",filebuf);
        if (MessageBox(TopLevel,buf,"GRA file",MB_YESNO)!=IDYES) {
          memfree(buf);
          free(filebuf);
          return;
        }
        memfree(buf);
      } else {
        if (MessageBox(TopLevel,"Overwrite existing file?",
                       "GRA file",MB_YESNO)!=IDYES) {
          free(filebuf);
          return;
        }
      }
    }
    if ((file=(char *)memalloc(strlen(filebuf)+1))==NULL) {
      free(filebuf);
      return;
    }
    strcpy(file,filebuf);
    free(filebuf);
    if (SetFileHidden()) {
      FileAutoScale();
      AdjustAxis();
      if ((graobj=chkobject("gra"))==NULL) {
        memfree(file);
        return;
      }
      if ((g2wobj=chkobject("gra2file"))==NULL) {
        memfree(file);
        return;
      }
      g2wid=newobj(g2wobj);
      if (g2wid>=0) {
        SetStatusBar("Making GRA file.");
        g2winst=chkobjinst(g2wobj,g2wid);
        _getobj(g2wobj,"oid",g2winst,&g2woid);
        putobj(g2wobj,"file",g2wid,file);
        id=newobj(graobj);
        putobj(graobj,"paper_width",id,&(menulocal.PaperWidth));
        putobj(graobj,"paper_height",id,&(menulocal.PaperHeight));
        putobj(graobj,"left_margin",id,&(menulocal.LeftMargin));
        putobj(graobj,"top_margin",id,&(menulocal.TopMargin));
        putobj(graobj,"zoom",id,&(menulocal.PaperZoom));
        if (arraynum(&(menulocal.drawrable))>0) {
          drawrable=arraynew(sizeof(char *));
          for (i=0;i<arraynum(&(menulocal.drawrable));i++) {
            arrayadd2(drawrable,(char **)arraynget(&(menulocal.drawrable),i));
          }
        } else drawrable=NULL;
        putobj(graobj,"draw_obj",id,drawrable);
        device=(char *)memalloc(20);
        sprintf(device,"gra2file:^%d",g2woid);
        putobj(graobj,"device",id,device);
        getobj(graobj,"open",id,0,NULL,&GC);
        exeobj(graobj,"draw",id,0,NULL);
        exeobj(graobj,"flush",id,0,NULL);
        exeobj(graobj,"close",id,0,NULL);
        delobj(graobj,id);
        delobj(g2wobj,g2wid);
        ResetStatusBar();
      }
    }
  }
}

void CmPrintDataFile()
{
  struct objlist *obj;
  int id;
  double dx,dy,d2,d3;
  int type,div;
  char *buf,*file;
  char *argv[3];

  if (menulock || globallock ) return;
  if ((obj=chkobject("file"))==NULL) return;
  if (chkobjlastinst(obj)==-1) return;
  CopyDialog(&DlgCopy,obj,-1,FileCB);
  if (DialogExecute(TopLevel,&DlgCopy)==IDOK) {
    id=DlgCopy.sel;
    if ((id>=0) && (id<=chkobjlastinst(obj))) {
      div=10;
      getobj(obj,"type",id,0,NULL,&type);
      if (type==3) {
        OutputDataDialog(&DlgOutputData,div);
        if (DialogExecute(TopLevel,&DlgOutputData)!=IDOK) return;
        div=DlgOutputData.div;
      }
      if (nGetSaveFileName(TopLevel,"Data file",NULL,NULL,NULL,
          &file,"*",menulocal.changedirectory)==IDOK) {
        if (access(file,04)==0) {
          buf=(char *)memalloc(strlen(file)+60);
          if (buf!=NULL) {
            sprintf(buf,"`%s'\n\nOverwrite existing file?",file);
            if (MessageBox(TopLevel,buf,"Data file",MB_YESNO)!=IDYES) {
              free(file);
              memfree(buf);
              return;
            }
            memfree(buf);
          } else {
            if (MessageBox(TopLevel,"Overwrite existing file?",
                           "Data file",MB_YESNO)!=IDYES) {
              free(file);
              return;
            }
          }
        }
        SetStatusBar("Making data file.");
        argv[0]=(char *)file;
        argv[1]=(char *)&div;
        argv[2]=NULL;
        exeobj(obj,"output_file",id,2,argv);
        ResetStatusBar();
      }
      free(file);
    }
  }
}

void CmOutputDriverB(Widget w,XtPointer client_data,XtPointer call_data)
{
  CmOutputDriver(TRUE);
}

void CmOutputViewerB(Widget w,XtPointer client_data,XtPointer call_data)
{
  CmOutputViewer(TRUE);
}

void CmOutputMenu(Widget w,XtPointer client_data,XtPointer call_data)
{
  switch ((int )client_data) {
  case 0:
    CmViewerDraw();
    break;
  case 1:
    CmViewerClear();
    break;
  case 2:
    CmOutputViewer();
    break;
  case 3:
    CmOutputDriver(FALSE);
    break;
  case 4:
    CmPrintGRAFile();
    break;
  case 5:
    CmPrintDataFile();
    break;
  }
}
