/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                            P R I N T F O R M . C                             *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: printform.c,v 1.6 2003/11/07 11:08:33 jrh Exp $
* $Log: printform.c,v $
* Revision 1.6  2003/11/07 11:08:33  jrh
* Release 2.4
*
* Revision 1.5  2000/12/10 15:13:52  jrh
* Release 2.3
*
* Revision 1.4  1999/05/24 01:26:58  jrh
* Release 2.2.1
*
* Revision 1.3  1999/02/07 21:54:50  jrh
* Release 2.2
*
* Revision 1.2  1998/01/26 00:49:05  jrh
* Release 2.1
*
* Revision 1.1  1996/12/10  18:43:19  jrh
* Initial revision
*
*/
#include<math.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<X11/Intrinsic.h>
#include<Xm/Xm.h>
#include<Xm/Form.h>
#include<Xm/Label.h>
#include<Xm/LabelG.h>
#include<Xm/PanedW.h>
#include<Xm/PushB.h>
#include<Xm/PushBG.h>
#include<Xm/RowColumn.h>
#include<Xm/Scale.h>
#include<Xm/Separator.h>
#include<Xm/Text.h>
#include<Xm/ToggleB.h>
#include<GL/glu.h>
#include "tiffio.h"
#include "viewmol.h"
#include "dialog.h"

void printDialog(Widget, caddr_t, XmAnyCallbackStruct *);
void printDialogExit(Widget, caddr_t, XmPushButtonCallbackStruct *);
char *saveFile(struct MOLECULE *, int, char *, char *);
void GetFormat(Widget, caddr_t, XmToggleButtonCallbackStruct *);
void GetOrientation(Widget, caddr_t, XmToggleButtonCallbackStruct *);
void GetPapersize(Widget, caddr_t, XmToggleButtonCallbackStruct *);
void GetCompression(Widget, caddr_t, XmToggleButtonCallbackStruct *);
void SetPapersize(int);
void Fileselect(Widget, caddr_t, XmAnyCallbackStruct *);
char *saveMultipleFiles(struct MOLECULE *, char *, char *, int, int);

extern void GetDouble(Widget, caddr_t, XmAnyCallbackStruct *);
extern Widget makeMenu(Widget, int, char *, struct MenuItem *);
extern void MapBox(Widget, caddr_t, XmAnyCallbackStruct *);
extern Widget CreateToggleBox(Widget, struct PushButtonRow *, int, int,
                              int, int, int);
extern char *selectFile(char *, char *, int);
extern char *getStringResource(Widget, char *);
extern char *saveVectorFile(int, char *, int);
extern char *saveTiff(int, char *, int);
extern char *savePng(int, char *, int);
extern char *savePostScriptBitmap(int, char *);
extern void GetMessageBoxButton(Widget, XtPointer, caddr_t);
extern void setAnimation(int);
extern Boolean normalMode(XtPointer);
extern Boolean animateHistory(XtPointer);
extern int messgb(Widget, int, char *, struct PushButtonRow *, int);
extern void CreatePushButtonRow(Widget, struct PushButtonRow *, int);
extern void setMenuItem(int, int);
extern Widget initShell(Widget, char *, Widget *, Widget *);
extern void GetTransperancy(Widget, caddr_t, XmToggleButtonCallbackStruct *);

extern struct WINDOW windows[];
extern struct MOLECULE *molecules;
extern Widget topShell, fileBox;
extern double paperWidth, paperHeight;
extern int format, landscape, animate, primitive, iwavef;

static Widget filename, dialog, pWidth, pHeight, comp, transparent, paperformat;
static int window, format_save, landscape_save, compression=COMPRESSION_NONE;
static int transparentBackground=FALSE, paper=A4;
static char name[MAXLENLINE];
static struct PushButtonRow radiobox2_buttons[] = {
  { "landscape", GetOrientation, (XtPointer)TRUE, NULL },
  { "portrait", GetOrientation, (XtPointer)FALSE, NULL }
};

void printDialog(Widget widget, caddr_t which, XmAnyCallbackStruct *data)
{
  Widget board, form, form1, form2, form3, form4, form5, form6, sep1, sep2;
  Widget sep3, sep4, radiobox1, radiobox2, file, select, papersize;
  Widget clabel, wlabel, hlabel;
  static struct PushButtonRow buttons[] = {
    { "ok", printDialogExit, (XtPointer)TRUE, NULL },
    { "cancel", printDialogExit, (XtPointer)FALSE, NULL }
  };
  static struct PushButtonRow radiobox1_buttons[] = {
    { "tiff", GetFormat, (XtPointer)TIFFFILE, NULL },
    { "png", GetFormat, (XtPointer)PNGFILE, NULL },
    { "hpgl", GetFormat, (XtPointer)HPGL, NULL },
    { "postscript", GetFormat, (XtPointer)POSTSCRIPT, NULL },
    { "raytracer", GetFormat, (XtPointer)RAYTRACER, NULL }
  };
  static struct MenuItem paperMenu[] = {
    { "a5", &xmPushButtonGadgetClass, GetPapersize, (XtPointer)A5, NULL, NULL },
    { "a4", &xmPushButtonGadgetClass, GetPapersize, (XtPointer)A4, NULL, NULL },
    { "a3", &xmPushButtonGadgetClass, GetPapersize, (XtPointer)A3, NULL, NULL },
    { "letter", &xmPushButtonGadgetClass, GetPapersize, (XtPointer)LETTER, NULL, NULL },
    { "legal", &xmPushButtonGadgetClass, GetPapersize, (XtPointer)LEGAL, NULL, NULL },
    { "userdefined", &xmPushButtonGadgetClass, GetPapersize, (XtPointer)USER, NULL, NULL },
    { NULL, NULL, NULL, NULL, NULL, NULL }
  };
  static struct MenuItem compressionMenu[] = {
    { "none", &xmPushButtonGadgetClass, GetCompression, (XtPointer)COMPRESSION_NONE, NULL, NULL },
    { "mac", &xmPushButtonGadgetClass, GetCompression, (XtPointer)COMPRESSION_PACKBITS, NULL, NULL },
    { "lzw", &xmPushButtonGadgetClass, GetCompression, (XtPointer)COMPRESSION_LZW, NULL, NULL },
    { NULL, NULL, NULL, NULL, NULL, NULL }
  };
  char line[MAXLENLINE], *word;
  int imol;
  register int i;

  /* This function creates the dialog for file output */

  format_save=format;
  landscape_save=landscape;
  window=(int)which;
  if (windows[window].set >= 0)
    imol=windows[window].set;
  else
    imol=0;

  setMenuItem(VIEWER_HARDCOPY, False);
  if (windows[SPECTRUM].widget) setMenuItem(SPECTRUM_HARDCOPY, False);
  if (windows[HISTORY].widget) setMenuItem(HISTORY_HARDCOPY, False);
  if (windows[MO].widget) setMenuItem(MO_HARDCOPY, False);

  dialog=initShell(windows[window].widget, "printForm", &board,
			 &form);
  form1=XtVaCreateWidget("controlarea1", xmRowColumnWidgetClass, form,
                         XmNorientation, XmHORIZONTAL,
                         XmNleftAttachment, XmATTACH_FORM,
                         XmNrightAttachment, XmATTACH_FORM,
                         NULL);
  radiobox1=CreateToggleBox(form1, radiobox1_buttons, XtNumber(radiobox1_buttons),
                            XmVERTICAL, 1, True, format-2);
  if (window != VIEWER || (windows[VIEWER].mode == WIREMODEL && iwavef == ALL_OFF))
     XtVaSetValues(radiobox1_buttons[RAYTRACER-2].widget, XmNsensitive, False, NULL);
  if ((((animate == ANIMATE && molecules[imol].mode != (-1)) || animate == TRAJECTORY) && window == VIEWER))
  {
    XtVaSetValues(radiobox1_buttons[HPGL-2].widget, XmNsensitive, False, NULL);
    XtVaSetValues(radiobox1_buttons[POSTSCRIPT-2].widget, XmNsensitive, False, NULL);
  }
  if (window == VIEWER && primitive == GLU_FILL &&
     (iwavef != ALL_OFF || windows[window].mode != WIREMODEL))
  {
    XtVaSetValues(radiobox1_buttons[HPGL-2].widget, XmNsensitive, False, NULL);
/*  XtVaSetValues(radiobox1_buttons[POSTSCRIPT-2].widget, XmNsensitive, False, NULL);*/
  }
  XtVaSetValues(radiobox1, XmNleftAttachment, XmATTACH_FORM,
                           XmNtopAttachment, XmATTACH_FORM,
                           XmNbottomAttachment, XmATTACH_FORM,
                           NULL);
  sep1=XtVaCreateManagedWidget("sep1", xmSeparatorWidgetClass, form1,
                               XmNorientation, XmVERTICAL,
                               XmNtraversalOn, False,
                               XmNtopAttachment, XmATTACH_FORM,
                               XmNbottomAttachment, XmATTACH_FORM,
                               XmNleftAttachment, XmATTACH_WIDGET,
                               XmNleftWidget, radiobox1,
                               NULL);
  form2=XtVaCreateWidget("controlarea2", xmRowColumnWidgetClass, form1,
                         XmNorientation, XmVERTICAL,
                         XmNtopAttachment, XmATTACH_FORM,
                         XmNbottomAttachment, XmATTACH_FORM,
                         XmNrightAttachment, XmATTACH_FORM,
                         NULL);
  radiobox2=CreateToggleBox(form2, radiobox2_buttons, XtNumber(radiobox2_buttons),
                            XmVERTICAL, 1, True, landscape ? 0 : 1);
  XtVaSetValues(radiobox2,XmNrightAttachment, XmATTACH_FORM,
                          XmNtopAttachment, XmATTACH_FORM,
                          NULL);
  if (format == TIFFFILE || format == RAYTRACER)
  {
    XtVaSetValues(radiobox2_buttons[0].widget, XmNsensitive, False, NULL);
    XtVaSetValues(radiobox2_buttons[1].widget, XmNsensitive, False, NULL);
  }
  sep2=XtVaCreateManagedWidget("sep2", xmSeparatorWidgetClass, form2,
                               XmNorientation, XmHORIZONTAL,
                               XmNtraversalOn, False,
                               XmNleftAttachment, XmATTACH_FORM,
                               XmNrightAttachment, XmATTACH_FORM,
                               XmNtopAttachment, XmATTACH_WIDGET,
                               XmNtopWidget, radiobox2,
                               NULL);
  clabel=XtVaCreateManagedWidget("compressionlabel", xmLabelWidgetClass, form2,
                                 XmNleftAttachment, XmATTACH_FORM,
                                 XmNrightAttachment, XmATTACH_FORM,
                                 XmNtopAttachment, XmATTACH_WIDGET,
                                 XmNtopWidget, sep2,
                                 NULL);
  word=getStringResource(topShell, "hasLZW");
  if (word && strcmp(word, "True"))
    compressionMenu[2].label=NULL;
  comp=makeMenu(form2, XmMENU_OPTION, "compression", compressionMenu);
  if (format == TIFFFILE)
  {
    for (i=0; compressionMenu[i].label != NULL; i++)
    {
      if ((int)(compressionMenu[i].callback_data) == compression)
        XtVaSetValues(comp, XmNmenuHistory, compressionMenu[i].widget,
                      XmNleftAttachment, XmATTACH_FORM,
                      XmNrightAttachment, XmATTACH_FORM,
                      XmNtopAttachment, XmATTACH_WIDGET,
                      XmNtopWidget, clabel,
                      NULL);
    }
  }
  else
    XtVaSetValues(comp, XmNsensitive, False, NULL);
  XtManageChild(comp);

  transparent=XtVaCreateManagedWidget("transparent", xmToggleButtonWidgetClass, form2,
                                      XmNleftAttachment, XmATTACH_FORM,
                                      XmNtopAttachment, XmATTACH_WIDGET,
						  XmNtopWidget, comp,
                                      XmNrightAttachment, XmATTACH_FORM,
                                      NULL);
  if (transparentBackground) XtVaSetValues(transparent, XmNset, True, NULL);
  XtAddCallback(transparent, XmNvalueChangedCallback, (XtCallbackProc)GetTransperancy,
                &transparentBackground);
  if (format != PNGFILE) 
    XtVaSetValues(transparent, XmNsensitive, False, NULL);

  sep3=XtVaCreateManagedWidget("sep3", xmSeparatorWidgetClass, form,
                               XmNorientation, XmHORIZONTAL,
                               XmNtraversalOn, False,
                               XmNleftAttachment, XmATTACH_FORM,
                               XmNrightAttachment, XmATTACH_FORM,
                               XmNtopAttachment, XmATTACH_WIDGET,
                               XmNleftWidget, form1,
                               NULL);
  form3=XtVaCreateWidget("controlarea3", xmFormWidgetClass, form,
                         NULL);
  file=XtVaCreateManagedWidget("file", xmLabelWidgetClass, form3,
                               XmNleftAttachment, XmATTACH_FORM,
                               XmNtopAttachment, XmATTACH_FORM,
                               XmNbottomAttachment, XmATTACH_FORM,
                               NULL);
  switch (format)
  {
    case TIFFFILE:   strcpy(name, "vm_image.tiff");
                     break;
    case PNGFILE:    strcpy(name, "vm_image.png");
                     break;
    case HPGL:       strcpy(name, "vm_plot.hpgl");
                     break;
    case POSTSCRIPT: strcpy(name, "vm_plot.eps");
                     break;
    case RAYTRACER:  strcpy(name, "vm_image.ray");
                     break;
  }
  filename=XtVaCreateManagedWidget("filename", xmTextWidgetClass, form3,
                                   XmNvalue, name,
                                   XmNcolumns, 12,
                                   XmNleftAttachment, XmATTACH_WIDGET,
                                   XmNleftWidget, file,
                                   XmNtopAttachment, XmATTACH_FORM,
                                   XmNbottomAttachment, XmATTACH_FORM,
                                   NULL);
  select=XtVaCreateManagedWidget("select", xmPushButtonGadgetClass, form3,
                                 XmNleftAttachment, XmATTACH_WIDGET,
                                 XmNleftWidget, filename,
                                 XmNtopAttachment, XmATTACH_FORM,
                                 XmNbottomAttachment, XmATTACH_FORM,
                                 XmNrightAttachment, XmATTACH_FORM,
                                 XmNdefaultButtonShadowThickness, 1,
                                 NULL);
  XtAddCallback(select, XmNactivateCallback, (XtCallbackProc)Fileselect, NULL);

  form4=XtVaCreateWidget("controlarea4", xmFormWidgetClass, form,
                         NULL);
  papersize=XtVaCreateManagedWidget("papersize", xmLabelWidgetClass, form4,
                                    XmNleftAttachment, XmATTACH_FORM,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNbottomAttachment, XmATTACH_FORM,
                                    NULL);
  paperformat=makeMenu(form4, XmMENU_OPTION, "paperformat", paperMenu);
  for (i=0; paperMenu[i].label != NULL; i++)
  {
    if ((int)paperMenu[i].callback_data == paper)
      XtVaSetValues(paperformat, XmNmenuHistory, paperMenu[i].widget,
                                 XmNrightAttachment, XmATTACH_FORM,
                                 XmNtopAttachment, XmATTACH_FORM,
                                 XmNbottomAttachment, XmATTACH_FORM,
                                 NULL);
  }
  if (format == TIFFFILE || format == PNGFILE || format == RAYTRACER)
    XtVaSetValues(paperformat, XmNsensitive, False, NULL);
  XtManageChild(paperformat);

  form5=XtVaCreateWidget("controlarea5", xmFormWidgetClass, form,
                         NULL);
  form6=XtVaCreateWidget("controlarea5", xmFormWidgetClass, form,
                         NULL);
  wlabel=XtVaCreateManagedWidget("widthlabel", xmLabelWidgetClass, form5,
                                 XmNleftAttachment, XmATTACH_FORM,
                                 XmNtopAttachment, XmATTACH_FORM,
                                 XmNbottomAttachment, XmATTACH_FORM,
                                 NULL);

  hlabel=XtVaCreateManagedWidget("heightlabel", xmLabelWidgetClass, form6,
                                 XmNleftAttachment, XmATTACH_FORM,
                                 XmNtopAttachment, XmATTACH_FORM,
                                 XmNbottomAttachment, XmATTACH_FORM,
                                 NULL);

  sprintf(line, "%7.2f", paperWidth);
  pWidth=XtVaCreateManagedWidget("width", xmTextWidgetClass, form5,
                                 XmNvalue, line,
                                 XmNcolumns, 7,
                                 XmNtopAttachment, XmATTACH_FORM,
                                 XmNrightAttachment, XmATTACH_FORM,
                                 XmNbottomAttachment, XmATTACH_FORM,
                                 NULL);
  XtAddCallback(pWidth, XmNvalueChangedCallback, (XtCallbackProc)GetDouble, &paperWidth);

  sprintf(line, "%7.2f", paperHeight);
  pHeight=XtVaCreateManagedWidget("height", xmTextWidgetClass, form6,
                                  XmNvalue, line,
                                  XmNcolumns, 7,
                                  XmNtopAttachment, XmATTACH_FORM,
                                  XmNrightAttachment, XmATTACH_FORM,
                                  XmNbottomAttachment, XmATTACH_FORM,
                                  NULL);
  XtAddCallback(pHeight, XmNvalueChangedCallback, (XtCallbackProc)GetDouble, &paperHeight);

  if (paper != USER)
  {
    XtVaSetValues(pWidth, XmNsensitive, False, NULL);
    XtVaSetValues(pHeight, XmNsensitive, False, NULL);
  }
  sep4=XtVaCreateManagedWidget("sep4", xmSeparatorWidgetClass, form,
                               XmNorientation, XmHORIZONTAL,
                               XmNtraversalOn, False,
                               XmNleftAttachment, XmATTACH_FORM,
                               XmNrightAttachment, XmATTACH_FORM,
                               XmNtopAttachment, XmATTACH_WIDGET,
                               XmNleftWidget, form5,
                               NULL);

  XtManageChild(form1);
  XtManageChild(form2);
  XtManageChild(form3);
  XtManageChild(form4);
  XtManageChild(form5);
  XtManageChild(form6);

  CreatePushButtonRow(form, buttons, 2);
  XtAddCallback(dialog, XmNpopupCallback, (XtCallbackProc)MapBox, (XmAnyCallbackStruct *)NULL);
  XtManageChild(form);
  XtManageChild(board);
}

void GetFormat(Widget button, caddr_t which, XmToggleButtonCallbackStruct *data)
{
  if (data->set) format=(int)which;
  switch (format)
  {
    case TIFFFILE:   strcpy(name, "vm_image.tiff");
                     XtVaSetValues(radiobox2_buttons[0].widget, XmNsensitive, False, NULL);
                     XtVaSetValues(radiobox2_buttons[1].widget, XmNsensitive, False, NULL);
                     XtVaSetValues(comp, XmNsensitive, True, NULL);
                     XtVaSetValues(paperformat, XmNsensitive, False, NULL);
                     XtVaSetValues(transparent, XmNsensitive, False, NULL);
                     break;
    case PNGFILE:    strcpy(name, "vm_image.png");
                     XtVaSetValues(radiobox2_buttons[0].widget, XmNsensitive, False, NULL);
                     XtVaSetValues(radiobox2_buttons[1].widget, XmNsensitive, False, NULL);
                     XtVaSetValues(comp, XmNsensitive, True, NULL);
                     XtVaSetValues(paperformat, XmNsensitive, False, NULL);
                     XtVaSetValues(transparent, XmNsensitive, True, NULL);
                     break;
    case HPGL:       strcpy(name, "vm_plot.hpgl");
                     XtVaSetValues(radiobox2_buttons[0].widget, XmNsensitive, True, NULL);
                     XtVaSetValues(radiobox2_buttons[1].widget, XmNsensitive, True, NULL);
                     XtVaSetValues(comp, XmNsensitive, False, NULL);
                     XtVaSetValues(paperformat, XmNsensitive, True, NULL);
                     XtVaSetValues(transparent, XmNsensitive, False, NULL);
                     break;
    case POSTSCRIPT: strcpy(name, "vm_plot.eps");
                     XtVaSetValues(radiobox2_buttons[0].widget, XmNsensitive, True, NULL);
                     XtVaSetValues(radiobox2_buttons[1].widget, XmNsensitive, True, NULL);
                     XtVaSetValues(comp, XmNsensitive, False, NULL);
                     XtVaSetValues(paperformat, XmNsensitive, True, NULL);
                     XtVaSetValues(transparent, XmNsensitive, False, NULL);
                     break;
    case RAYTRACER:  strcpy(name, "vm_image.ray");
                     XtVaSetValues(radiobox2_buttons[0].widget, XmNsensitive, False, NULL);
                     XtVaSetValues(radiobox2_buttons[1].widget, XmNsensitive, False, NULL);
                     XtVaSetValues(comp, XmNsensitive, False, NULL);
                     XtVaSetValues(paperformat, XmNsensitive, False, NULL);
                     XtVaSetValues(transparent, XmNsensitive, False, NULL);
                     break;
  }
  XtVaSetValues(filename, XmNvalue, name, NULL);
}

void GetOrientation(Widget button, caddr_t which, XmToggleButtonCallbackStruct *data)
{
  if (data->set)
  {
    SetPapersize(TRUE);
    if ((int)which)
      landscape=TRUE;
    else
      landscape=FALSE;
  }
}

void GetTransperancy(Widget button, caddr_t which, XmToggleButtonCallbackStruct *data)
{
  if (data->set)
    *(int *)which=TRUE;
  else
    *(int *)which=FALSE;
}

void GetPapersize(Widget button, caddr_t which, XmToggleButtonCallbackStruct *data)
{
  paper=(int)which;
  switch (paper)
  {
    case A5:     paperWidth=210.2;
                 paperHeight=148.6;
                 break;
    case A4:     paperWidth=297.3;
                 paperHeight=210.2;
                 break;
    case A3:     paperWidth=420.4;
                 paperHeight=297.3;
                 break;
    case LETTER: paperWidth=278.0;
                 paperHeight=216.0;
                 break;
    case LEGAL:  paperWidth=356.0;
                 paperHeight=216.0;
                 break;
  }
  if (button == 0) return;
  SetPapersize(!landscape);
  if (paper == USER)
  {
    XtVaSetValues(pWidth, XmNsensitive, True,
                          NULL);
    XtVaSetValues(pHeight, XmNsensitive, True,
                           NULL);
  }
  else
  {
    XtVaSetValues(pWidth, XmNsensitive, False,
                          NULL);
    XtVaSetValues(pHeight, XmNsensitive, False,
                           NULL);
  }
}

void GetCompression(Widget button, caddr_t which, XmToggleButtonCallbackStruct *data)
{
  compression=(int)which;
}

void printDialogExit(Widget button, caddr_t which, XmPushButtonCallbackStruct *data)
{
  static struct PushButtonRow buttons1[] = {{"continue", GetMessageBoxButton, (XtPointer)0, NULL},
                                            {"cancel", GetMessageBoxButton, (XtPointer)1, NULL}};
  static struct PushButtonRow buttons2[] = {{"continue", GetMessageBoxButton, (XtPointer)0, NULL}};
  char *file, *dot, *word=NULL;
  char f[MAXLENLINE], str[MAXLENLINE];
  int imol;

  if (!(int)which)
  {
    format=format_save;
    landscape=landscape_save;
  }
  else
  {
    if (windows[window].set >= 0)
      imol=windows[window].set;
    else
      imol=0;
    file=XmTextGetString(filename);
    if (!access(file, F_OK))
    {
      dot=getStringResource(topShell, "FileExists");
      sprintf(str, dot, file);
      if (messgb(topShell, 1, str, buttons1, 2) == 1) return;
    }
    strcpy(f, file);
    word=saveFile(&molecules[imol], format, file, f);
    if (word)
    {
      sprintf(str, word, f);
      messgb(topShell, 0, str, buttons2, 1);
    }
    XtFree(file);
  }
  XtDestroyWidget(dialog);
  XtUnmanageChild(fileBox);
  setMenuItem(VIEWER_HARDCOPY, True);
  if (windows[SPECTRUM].widget) setMenuItem(SPECTRUM_HARDCOPY, True);
  if (windows[HISTORY].widget) setMenuItem(HISTORY_HARDCOPY, True);
  if (windows[MO].widget) setMenuItem(MO_HARDCOPY, True);
}

void saveDrawing(int which, int format, char *filename)
{
  int i;
  char f[MAXLENLINE];

  window=which;
  if (windows[which].set >= 0)
    i=windows[which].set;
  else
    i=0;
  (void)saveFile(&molecules[i], format, filename, f);
}

char *saveFile(struct MOLECULE *mol, int format, char *file, char *f)
{
  char *word=NULL;

  switch (format)
  {
    case TIFFFILE:   if (((animate == ANIMATE && mol->mode != (-1))
                        || animate == TRAJECTORY) && window == VIEWER)
			     word=saveMultipleFiles(mol, file, f, animate, format);
                     else
                       word=saveTiff(window, file, compression);
                     break;
    case PNGFILE:    if (((animate == ANIMATE && mol->mode != (-1))
                        || animate == TRAJECTORY) && window == VIEWER)
			     word=saveMultipleFiles(mol, file, f, animate, format);
                     else
                       word=savePng(window, file, transparentBackground);
                     break;
    case HPGL:       word=saveVectorFile(window, file, format);
                     break;
    case POSTSCRIPT: if (window == VIEWER && primitive == GLU_FILL && (windows[VIEWER].mode != WIREMODEL || iwavef != ALL_OFF))
                       word=savePostScriptBitmap(window, file);
		     else
                        word=saveVectorFile(window, file, format);
                     break;
    case RAYTRACER:  if (((animate == ANIMATE && mol->mode != (-1))
                        || animate == TRAJECTORY) && window == VIEWER)
                       word=saveMultipleFiles(mol, file, f, animate, format);
                     else
                       word=saveVectorFile(window, file, format);
                     break;
  }
  return(word);
}

void SetPapersize(int swap)
{
  double help;
  char line[MAXLENLINE];

  if (swap)
  {
    help=paperWidth;
    paperWidth=paperHeight;
    paperHeight=help;
  }

  sprintf(line, "%f", paperWidth);
  XtVaSetValues(pWidth, XmNvalue, line, NULL);
  sprintf(line, "%f", paperHeight);
  XtVaSetValues(pHeight, XmNvalue, line, NULL);
}

void Fileselect(Widget button, caddr_t dummy, XmAnyCallbackStruct *call_data)
{
  char *str, filter[MAXLENLINE];

  XtVaGetValues(filename, XmNvalue, &str, NULL);
  strcpy(filter, "*");
  strcat(filter, strrchr(str, '.'));
  str=selectFile(filter, str, TRUE);
  XtVaSetValues(filename, XmNvalue, str, NULL);
}

char *saveMultipleFiles(struct MOLECULE *mol, char *file, char *f, int animate, int format)
{
  char *dot, *word=NULL, num[10], fmt[6];
  register int i, j, k=20, n;

  dot=strrchr(file, '.');
  n=dot-file;
  switch (animate)
  {
    case ANIMATE:    k=20;
                     strcpy(fmt, "%2.2d");
			   break;
    case TRAJECTORY: k=mol->nhist;
                     sprintf(fmt, "%%%.1d.%.1dd", (int)floor(log10((double)k))+1, (int)floor(log10((double)k))+1);
			   break;
  }
  setAnimation(FALSE);
  j=1;
  for (i=0; i<k; i++)
  {
     strncpy(f, file, n);
     f[n]='\0';
     sprintf(num, fmt, i+1);
     strcat(f, num);
     strcat(f, dot);
     switch (animate)
     {
       case ANIMATE:    normalMode((XtPointer)j);
                        break;
       case TRAJECTORY: animateHistory((XtPointer)(i+1));
                        break;
     }
     switch (format)
     {
       case TIFFFILE:  word=saveTiff(window, f, compression);
                       break;
       case PNGFILE:   word=savePng(window, f, compression);
                       break;
       case RAYTRACER: word=saveVectorFile(window, f, format);
                       break;
     }
     j=0;
  }
  setAnimation(animate);
  strncpy(f, file, n);
  f[n]='\0';
  strcat(f, "X");
  strcat(f, dot);
  strcat(f, " (X=1-");
  strcat(f, num);
  strcat(f, ")");
  file=f;
  return(word);
}
