/*
Copyright (C) 2003 by Sean David Fleming
sean@ivec.org
This program 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.
This program 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.
The GNU GPL can also be found at http://www.gnu.org
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "gdis.h"
#include "coords.h"
#include "file.h"
#include "parse.h"
#include "matrix.h"
#include "model.h"
#include "space.h"
#include "zone.h"
#include "render.h"
#include "select.h"
#include "shortcuts.h"
#include "interface.h"
#include "dialog.h"
#include "opengl.h"
#define DEBUG_MORE 0
#define MAX_KEYS 15
/* main structures */
extern struct sysenv_pak sysenv;
extern struct elem_pak elements[];
/***************************************/
/* setup the recognized file type list */
/***************************************/
#define DEBUG_FILE_INIT 0
void file_init(void)
{
GSList *rlist=NULL;
struct file_pak *file_data;
/* NEW - build a recognized image read format list */
/* also used in picture writing as it avoids overlap */
/* problems when getting the file_data structure by extension */
#define PICTURE_SUPPORT 0
#if PICTURE_SUPPORT
for (list=gdk_pixbuf_get_formats() ; list ; list=g_slist_next(list))
{
gint i;
gchar **ext;
ext = gdk_pixbuf_format_get_extensions(list->data);
i = 0;
while (*(ext+i))
{
/*
if (gdk_pixbuf_format_is_writable(list->data))
wlist = g_slist_prepend(wlist, g_strdup(*(ext+i)));
*/
rlist = g_slist_prepend(rlist, g_strdup(*(ext+i)));
i++;
}
}
#endif
#if DEBUG_FILE_INIT
printf("read: ");
for (list=rlist ; list ; list=g_slist_next(list))
{
printf("[%s] ", (gchar *) list->data);
}
printf("\n");
#endif
/* build the recognized file type list */
sysenv.file_list = NULL;
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = DATA; /* unique identifier */
file_data->group = DATA; /* used to group inp/out types */
file_data->menu = TRUE; /* include in menu listing */
file_data->label = g_strdup("All known types"); /* text info for the user */
file_data->ext = NULL; /* extension matching */
file_data->write_file = NULL; /* file creation */
file_data->read_file = NULL; /* file reading */
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = ABINIT_OUT;
file_data->group = ABINIT;
file_data->menu = FALSE;
file_data->label = g_strdup("ABINIT output");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "about");
file_data->ext = g_slist_prepend(file_data->ext, "abot");
file_data->write_file = NULL;
file_data->read_file = read_about;
file_data->read_frame = read_about_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = MD_ANALYSIS;
file_data->group = MD_ANALYSIS;
file_data->menu = FALSE;
file_data->label = g_strdup("Analysis");
file_data->ext = NULL;
file_data->ext = NULL;
/* import/export handled in analysis as a special case */
file_data->write_file = NULL;
file_data->read_file = NULL;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = BIOGRAF;
file_data->group = BIOGRAF;
file_data->menu = TRUE;
file_data->label = g_strdup("bgf");
file_data->label = g_strdup("Biograf");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "bgf");
file_data->write_file = write_bgf;
file_data->read_file = read_bgf;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = BIOSYM;
file_data->group = BIOSYM;
file_data->menu = TRUE;
file_data->label = g_strdup("Biosym");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "car");
file_data->ext = g_slist_prepend(file_data->ext, "cor");
file_data->ext = g_slist_prepend(file_data->ext, "arc");
file_data->write_file = write_arc;
file_data->read_file = read_arc;
file_data->read_frame = read_arc_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = CASTEP;
file_data->group = CASTEP;
file_data->menu = TRUE;
file_data->label = g_strdup("CASTEP");
file_data->ext = NULL;
file_data->write_file = NULL;
file_data->read_file = NULL;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = CASTEP_OUT;
file_data->group = CASTEP;
file_data->menu = FALSE;
file_data->label = g_strdup("CASTEP output");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "castep");
file_data->write_file = NULL;
file_data->read_file = read_castep_out;
file_data->read_frame = read_castep_out_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = CIF;
file_data->group = CIF;
file_data->menu = TRUE;
file_data->label = g_strdup("CIF");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "cif");
file_data->write_file = write_cif;
file_data->read_file = read_cif;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* NEW: monty crystal graph file format */
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = CRYSTAL_GRAPH;
file_data->group = CRYSTAL_GRAPH;
file_data->menu = TRUE;
file_data->label = g_strdup("cgf");
file_data->label = g_strdup("Crystal Graph Files");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "cgf");
file_data->write_file = write_cgf;
file_data->read_file = read_cgf;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = CSSR;
file_data->group = CSSR;
file_data->menu = TRUE;
file_data->label = g_strdup("CSSR");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "cssr");
file_data->write_file = write_cssr;
file_data->read_file = read_cssr;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = DIFFAX_INP;
file_data->group = DIFFAX_INP;
file_data->menu = FALSE;
file_data->label = g_strdup("DIFFaX");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "dfx");
file_data->write_file = write_diffax;
file_data->read_file = read_diffax;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = DLP;
file_data->group = DLP;
file_data->menu = TRUE;
file_data->label = g_strdup("DLP");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "dlp");
file_data->write_file = write_dlp;
file_data->read_file = read_dlp;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = DMOL_INPUT;
file_data->group = DMOL_INPUT;
file_data->menu = TRUE;
file_data->label = g_strdup("DMOL");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "dmol");
file_data->write_file = write_dmol;
file_data->read_file = read_dmol;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = DLPOLY;
file_data->group = DLPOLY;
file_data->menu = TRUE;
file_data->label = g_strdup("DL_POLY");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "");
file_data->ext = g_slist_append(file_data->ext, "dlpoly");
file_data->write_file = write_dlpoly;
file_data->read_file = read_dlpoly;
file_data->read_frame = read_dlpoly_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = GAMESS;
file_data->group = GAMESS;
file_data->menu = TRUE;
file_data->label = g_strdup("GAMESS");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "inp");
file_data->write_file = write_gms;
file_data->read_file = read_gms;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = GAMESS_OUT;
file_data->group = GAMESS;
file_data->menu = FALSE;
file_data->label = g_strdup("GAMESS Output");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "gmout");
file_data->ext = g_slist_prepend(file_data->ext, "gmot");
file_data->write_file = NULL;
file_data->read_file = read_gms_out;
file_data->read_frame = read_gms_out_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = GAUSS;
file_data->group = GAUSS;
file_data->menu = TRUE;
file_data->label = g_strdup("GAUSSIAN");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "com");
file_data->write_file = write_gauss;
file_data->read_file = NULL;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = GAUSS_OUT;
file_data->group = GAUSS;
file_data->menu = FALSE;
file_data->label = g_strdup("GAUSSIAN output");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "log");
file_data->write_file = NULL;
file_data->read_file = read_gauss_out;
file_data->read_frame = read_gauss_out_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = MORPH;
file_data->group = MORPH;
file_data->menu = TRUE;
file_data->label = g_strdup("GDIS Morphology");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "gmf");
file_data->write_file = write_gmf;
file_data->read_file = read_gmf;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = GEOMVIEW_OFF;
file_data->group = GEOMVIEW_OFF;
file_data->menu = TRUE;
file_data->label = g_strdup("Geomview OFF");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "off");
file_data->write_file = NULL;
file_data->read_file = read_off;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = GULP;
file_data->group = GULP;
file_data->menu = TRUE;
file_data->label = g_strdup("GULP");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "gin");
file_data->ext = g_slist_prepend(file_data->ext, "res");
file_data->write_file = write_gulp;
file_data->read_file = read_gulp;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = GULPOUT;
file_data->group = GULP;
file_data->menu = FALSE;
file_data->label = g_strdup("GULP output");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "got");
file_data->ext = g_slist_prepend(file_data->ext, "gout");
file_data->write_file = NULL;
file_data->read_file = read_gulp_output;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = MARVIN;
file_data->group = MARVIN;
file_data->menu = TRUE;
file_data->label = g_strdup("MARVIN");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "mar");
file_data->ext = g_slist_prepend(file_data->ext, "mvn");
file_data->ext = g_slist_prepend(file_data->ext, "mvn-r");
file_data->write_file = write_marvin;
file_data->read_file = read_marvin;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = MVNOUT;
file_data->group = MARVIN;
file_data->menu = FALSE;
file_data->label = g_strdup("MARVIN output");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "mot");
file_data->ext = g_slist_prepend(file_data->ext, "mvout");
file_data->ext = g_slist_prepend(file_data->ext, "mvnout");
file_data->write_file = NULL;
file_data->read_file = read_mvnout;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = NWCHEM;
file_data->group = NWCHEM;
file_data->menu = TRUE;
file_data->label = g_strdup("NWChem");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "nwin");
file_data->write_file = NULL;
file_data->read_file = read_nw;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = NWCHEM_OUT;
file_data->group = NWCHEM;
file_data->menu = FALSE;
file_data->label = g_strdup("NWChem output");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "nwout");
file_data->ext = g_slist_prepend(file_data->ext, "nwot");
file_data->write_file = NULL;
file_data->read_file = read_nwout;
file_data->read_frame = read_nwout_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = PDB;
file_data->group = PDB;
file_data->menu = TRUE;
file_data->label = g_strdup("PDB");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "pdb");
file_data->write_file = write_pdb;
file_data->read_file = read_pdb;
file_data->read_frame = read_pdb_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = PICTURE;
file_data->group = PICTURE;
file_data->menu = FALSE;
/* TODO - check supported image types with glib - add to string */
file_data->label = g_strdup("Picture (jpg)");
file_data->ext = rlist;
file_data->write_file = NULL;
file_data->read_file = NULL;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = POVRAY;
file_data->group = POVRAY;
file_data->menu = FALSE;
file_data->label = g_strdup("POVRay");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "pov");
file_data->write_file = write_povray;
file_data->read_file = NULL;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = PROJECT;
file_data->group = PROJECT;
file_data->menu = FALSE;
file_data->label = g_strdup("Project");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "pcf");
file_data->write_file = NULL;
file_data->read_file = project_read;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = CEL;
file_data->group = CEL;
file_data->menu = TRUE;
file_data->label = g_strdup("PowderCell");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "cel");
file_data->write_file = NULL;
file_data->read_file = read_cel;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = RIETICA;
file_data->group = RIETICA;
file_data->menu = TRUE;
file_data->label = g_strdup("Rietica");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "inp");
file_data->write_file = NULL;
file_data->read_file = read_rietica;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = FDF;
file_data->group = FDF;
file_data->menu = TRUE;
file_data->label = g_strdup("SIESTA");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "fdf");
file_data->write_file = write_fdf;
file_data->read_file = read_fdf;
file_data->read_frame = NULL;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = SIESTA_OUT;
file_data->group = FDF;
file_data->menu = FALSE;
file_data->label = g_strdup("SIESTA output");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "sout");
file_data->ext = g_slist_prepend(file_data->ext, "sot");
file_data->write_file = NULL;
file_data->read_file = read_sout;
file_data->read_frame = read_sout_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = XML;
file_data->group = XML;
file_data->menu = TRUE;
file_data->label = g_strdup("XML");
file_data->ext = NULL;
file_data->ext = g_slist_prepend(file_data->ext, "xml");
file_data->write_file = write_xml;
file_data->read_file = read_xml;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = XTL;
file_data->group = XTL;
file_data->menu = TRUE;
file_data->label = g_strdup("XTL");
file_data->ext = NULL;
file_data->ext = g_slist_append(file_data->ext, "xtl");
file_data->write_file = write_xtl;
file_data->read_file = read_xtl;
file_data->read_frame = NULL; /* frame reading */
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
/* supported file type */
file_data = g_malloc(sizeof(struct file_pak));
file_data->id = XYZ;
file_data->group = XYZ;
file_data->menu = TRUE;
file_data->label = g_strdup("XYZ");
file_data->ext = NULL;
/*
file_data->ext = g_slist_append(file_data->ext, "ani");
file_data->ext = g_slist_append(file_data->ext, "xmol");
*/
file_data->ext = g_slist_append(file_data->ext, "xyz");
file_data->write_file = write_xyz;
file_data->read_file = read_xyz;
file_data->read_frame = read_xyz_frame;
sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data);
sysenv.file_list = g_slist_reverse(sysenv.file_list);
}
/************************/
/* current version info */
/************************/
void gdis_blurb(FILE *fp)
{
fprintf(fp, "Created by GDIS version %4.2f.%d\n", VERSION, PATCH);
}
/*********************************************/
/* alphabetically sort the directory listing */
/*********************************************/
gint alpha_slist_sort(gpointer ptr1, gpointer ptr2)
{
return(g_ascii_strcasecmp((gchar *) ptr1, (gchar *) ptr2));
}
/*********************************************/
/* an all-platform directory listing routine */
/*********************************************/
GSList *get_dir_list(const char *path, gint sort)
{
const gchar *name;
GDir *dir;
GSList *files=NULL;
/* ensure we can go up a directory */
files = g_slist_prepend(files, g_strdup(".."));
/* build the directory list */
dir = g_dir_open(path, 0, NULL);
name = g_dir_read_name(dir);
while (name)
{
if (g_ascii_strncasecmp(".", name, 1) != 0)
files = g_slist_prepend(files, g_strdup(name));
name = g_dir_read_name(dir);
}
g_dir_close(dir);
if (sort)
files = g_slist_sort(files, (gpointer) alpha_slist_sort);
return(files);
}
/*******************************************************/
/* allocate a new string containing the file extension */
/*******************************************************/
gchar *file_extension_get(const gchar *name)
{
gint i,n;
gchar *ext;
if (!name)
return(NULL);
/* search for '.' character in reverse order */
i = n = strlen(name);
/* minimum size, avoids troublesome cases (eg "..") */
if (n > 2)
{
for (i=n-1 ; i-- ; )
{
if (name[i] == '.')
{
ext = g_strndup(name+i+1, n-i-1);
/* ignore any .# extension */
if (!str_is_float(ext))
return(ext);
g_free(ext);
/* mark the .# as the new end */
n = i;
}
}
}
return(NULL);
}
/************************************************/
/* routine to determine if a file is recognized */
/************************************************/
/* returns pointer to file info if found, NULL otherwise */
#define DEBUG_GET_FILE_INFO 0
struct file_pak *get_file_info(gpointer ptr, gint type)
{
gint code=-1;
gchar *text=NULL, *ext;
GSList *file, *ext_list;
struct file_pak *file_data;
/* checks */
g_return_val_if_fail(ptr != NULL, NULL);
/* init for search */
switch(type)
{
case BY_LABEL:
text = g_strdup(ptr);
#if DEBUG_GET_FILE_INFO
printf("Searching for type [%s]\n", text);
#endif
break;
case BY_EXTENSION:
/* fix to get around the quotes needed to properly pass win32 filesnames with spaces */
#if __WIN32
{
gchar *tmp = g_shell_unquote(ptr, NULL);
text = file_extension_get(tmp);
g_free(tmp);
}
#else
text = file_extension_get(ptr);
#endif
if (!text)
return(NULL);
#if DEBUG_GET_FILE_INFO
printf("Searching for extension [%s]\n", text);
#endif
break;
case BY_FILE_ID:
code = GPOINTER_TO_INT(ptr);
#if DEBUG_GET_FILE_INFO
printf("Searching for code [%d]\n", code);
#endif
break;
}
/* search */
for (file=sysenv.file_list ; file ; file=g_slist_next(file))
{
file_data = file->data;
switch (type)
{
/* compare to all extensions in list */
case BY_EXTENSION:
/* go through all extensions listed under this file type */
for (ext_list=file_data->ext ; ext_list ; ext_list=g_slist_next(ext_list))
{
ext = ext_list->data;
if (strlen(text) == strlen(ext))
{
if (g_ascii_strcasecmp(text, ext) == 0)
{
#if DEBUG_GET_FILE_INFO
printf("Matched: %s\n", file_data->label);
#endif
g_free(text);
return(file_data);
}
}
}
break;
/* compare with label */
case BY_LABEL:
if (strlen(text) != strlen(file_data->label))
break;
if (g_ascii_strcasecmp(text, file_data->label) == 0)
{
#if DEBUG_GET_FILE_INFO
printf("Matched: %s\n", file_data->label);
#endif
g_free(text);
return(file_data);
}
break;
case BY_FILE_ID:
if (code == file_data->id)
{
#if DEBUG_GET_FILE_INFO
printf("Matched: %s\n", file_data->label);
#endif
return(file_data);
}
break;
default:
printf("get_file_info() error: bad search type.\n");
}
}
if (text)
g_free(text);
return(NULL);
}
/**************************/
/* detect valid filetypes */
/**************************/
gint file_extension_valid(const gchar *name)
{
gchar *ext;
GSList *item, *list;
struct file_pak *file;
/* locate the extension */
/*FIXME: can find_char be replaced by standard strchr()/strrchr() functions?
- MW */
ext = find_char(name, '.', LAST);
if (ext)
ext++;
if (sysenv.file_type == DATA)
/* compare against all extension types - any match is allowed */
{
if (!ext) /* files without extensions are matched only in strict case */
return(FALSE);
for (list=sysenv.file_list ; list ; list=g_slist_next(list))
{
file = list->data;
for (item=file->ext ; item ; item=g_slist_next(item))
if (g_ascii_strcasecmp(item->data, ext) == 0)
return(TRUE);
}
}
else
/* strict case - file must match the dialog filter */
{
for (list=sysenv.file_list ; list ; list=g_slist_next(list))
{
file = list->data;
if (sysenv.file_type == file->group)
for (item=file->ext ; item ; item=g_slist_next(item))
if ((ext && g_ascii_strcasecmp(item->data, ext) == 0)
|| (!ext && strlen(item->data) == 0))
return(TRUE);
}
}
return(FALSE);
}
/*******************************************************/
/* get an unused BASENAME (of supplied extension type) */
/*******************************************************/
/* TODO - supply a basename+ext & this inserts _? until new? */
#define DEBUG_GUN 0
gchar *gun(const gchar *ext)
{
gint i;
gchar *name;
GString *filename;
FILE *fp;
/* seek a file name that doesn't exist (avoid background overwriting) */
filename = g_string_new(NULL);
i=0;
do
{
g_string_sprintf(filename,"dummy_%d.%s", i, ext);
#if DEBUG_GUN
printf("testing: %s\n",filename->str);
#endif
i++;
}
while (g_file_test(filename->str, G_FILE_TEST_EXISTS));
/* create the file to prevent another process from taking it */
/* b4 the current caller gets around to writing anything to it */
fp = fopen(filename->str, "wt");
if (fp)
{
fprintf(fp, "locked.\n");
fclose(fp);
}
else
{
printf("Fatal error in gun()\n");
return(NULL);
}
name = g_string_free(filename, FALSE);
#if DEBUG_GUN
printf("using base: %s\n", name);
#endif
return(name);
}
/**************************************************************/
/* correct numbers in binary files with reverse byte ordering */
/**************************************************************/
void swap_bytes(void *ptr, const gint size)
{
gint i,j;
gchar tmp;
/*
printf("start: ");
for (i=0 ; i<size ; i++)
printf("%d ", *((char *)(ptr+i)));
printf("\n");
*/
j=size-1;
for (i=0 ; i<size/2 ; i++)
{
tmp = *((gchar *)(ptr+j));
*((gchar *)(ptr+j)) = *((gchar *)(ptr+i));
*((gchar *)(ptr+i)) = tmp;
j--;
}
/*
printf(" stop: ");
for (i=0 ; i<size ; i++)
printf("%d ", *((char *)(ptr+i)));
printf("\n");
*/
}
/**************************************/
/* get a non trivial line from a file */
/**************************************/
gint fgetline(FILE *fp, gchar *line)
{
gint i, linlen;
for(;;)
{
/* get a line */
if (fgets(line, LINELEN/2, fp) == NULL)
return(1);
linlen = strlen(line);
/* only treated as data if not a comment and non empty */
if (line[0] != '#' && linlen)
{
/* ampersand concatenation */
/* TODO - extra var in fgetline() (eg mode) that requests this */
/* TODO - handle multiple line concatenation */
for (i=linlen ; i-- ; )
{
if (line[i] == '&')
{
if (fgets(&line[linlen], LINELEN/2, fp) == NULL)
return(1);
break;
}
}
break;
}
}
/* all clear */
return(0);
}
/*****************************************/
/* read in and return a line of any size */
/*****************************************/
/* TODO - replacement routine for fgetline() */
gchar *file_read_line(FILE *fp)
{
gboolean comment;
gchar c;
GString *buff;
/* checks */
g_assert(fp != NULL);
c = fgetc(fp);
if (c == EOF)
return(NULL);
/* read single chars into an expandable buffer */
buff = g_string_new(NULL);
while (c != EOF)
{
if (c == '#')
comment = TRUE;
else
comment = FALSE;
/* read a complete line */
while (c != EOF)
{
g_string_append_c(buff, c);
if (c == '\n')
break;
if (c == '\r')
{
gchar d;
d = fgetc(fp);
if (d == '\n')
{
/*
printf("skipping MSDOS crap.\n");
*/
}
else
ungetc(d, fp);
break;
}
c = fgetc(fp);
}
/* ignore comments (keep reading) */
if (comment)
{
g_string_assign(buff, "");
c = fgetc(fp);
}
else
break;
}
/* create a properly terminated line of text */
g_string_append_c(buff, '\0');
/* free the GString, but not the text */
return(g_string_free(buff, FALSE));
}
/**********************************************************/
/* format value as a float printed to dp places plus unit */
/**********************************************************/
gchar *format_value_and_units(gchar *string, gint dp)
{
gint num_tokens;
GString *text, *format_string;
gchar *text_str, *units, **buff;
gdouble float_val;
float_val = str_to_float(string);
buff = tokenize(string, &num_tokens);
if (num_tokens < 2)
units = "";
else
units = *(buff+1);
format_string = g_string_new("");
g_string_append_printf(format_string, "%%.%df %%s", dp);
text = g_string_new("");
g_string_append_printf(text, format_string->str, float_val, units);
text_str = text->str;
g_string_free(format_string, TRUE);
g_string_free(text, FALSE);
g_strfreev(buff);
return (text_str);
}
/************************************************/
/* read in a raw frame (animation and analysis) */
/************************************************/
#define DEBUG_READ_RAW 0
gint read_raw_frame(FILE *fp, gint n, struct model_pak *model)
{
gint i, flag=99;
gchar *filename;
fpos_t *offset;
FILE *fp2;
struct file_pak *file;
g_assert(fp != NULL);
g_assert(model != NULL);
file = get_file_info(GINT_TO_POINTER(model->id), BY_FILE_ID);
#if DEBUG_READ_RAW
printf("reading frame: %d\n", n);
#endif
/* position the file pointer */
if (model->id != GULP)
{
offset = g_list_nth_data(model->frame_list, n);
#if DEBUG_READ_RAW
printf("offset = %d\n", offset);
#endif
if (!offset)
return(1);
if (fsetpos(fp, offset))
{
printf("Error positioning file pointer.\n");
return(2);
}
/* use supplied routine (if available) */
if (file->read_frame)
flag = file->read_frame(fp, model);
else
gui_text_show(ERROR, "No animation read routine.\n");
}
else
{
/* GULP exception */
if (!n)
{
/* NEW - 0th frame exception - load original GULP coords */
if (model->cores)
g_assert(model->gulp.orig_cores != NULL);
if (model->shels)
g_assert(model->gulp.orig_shells != NULL);
/* free connectivity lists */
free_slist(model->bonds);
free_slist(model->moles);
model->bonds = NULL;
model->moles = NULL;
/* restore coords */
free_slist(model->cores);
free_slist(model->shels);
model->cores = dup_core_list(model->gulp.orig_cores);
model->shels = dup_shell_list(model->gulp.orig_shells);
/* restore lattice */
/*
model->fractional = model->gulp.orig_fractional;
*/
/* FIXME - I don't know why this works (and the above doesn't)... */
model->fractional = TRUE;
model->construct_pbc = model->gulp.orig_construct_pbc;
memcpy(model->latmat, model->gulp.orig_latmat, 9*sizeof(gdouble));
memcpy(model->pbc, model->gulp.orig_pbc, 6*sizeof(gdouble));
/* turn space group lookup on */
model->sginfo.lookup = TRUE;
flag = 0;
}
else
{
/* turn off space group lookup */
/* trg files contain ALL atoms & symmetry may be broken */
model->sginfo.lookup = FALSE;
/* FIXME - trj files resist every attempt at random access... why??? */
filename = g_strdup_printf("%s/%s", sysenv.cwd, model->gulp.trj_file);
fp2 = fopen(filename, "r");
if (!fp2)
{
printf("Failed to open: %s\n", filename);
g_free(filename);
return(3);
}
/* FIXME - ugly hack to get the nth frame */
read_trj_header(fp2, model);
for (i=0 ; i<n-1 ; i++)
read_trj_frame(fp2, model, FALSE);
read_trj_frame(fp2, model, TRUE);
fclose(fp2);
g_free(filename);
flag = 0;
}
}
return(flag);
}
/***********************************/
/* handler for normal file loading */
/***********************************/
#define DEBUG_FILE_LOAD 0
void file_load(gchar *filename, struct model_pak *mdata)
{
gint j;
gint flag, status=-1;
gchar *fullname;
GSList *list;
struct model_pak *data;
struct file_pak *file_data;
#if DEBUG_FILE_LOAD
printf("loading: [%s] into: %p\n", filename, mdata);
#endif
/* get the file structure required to parse the file */
switch (sysenv.file_type)
{
/* cases for which duplicate extensions occur */
case RIETICA:
case GAMESS:
case DLPOLY:
file_data = get_file_info(GINT_TO_POINTER(sysenv.file_type), BY_FILE_ID);
break;
/* cases for which extensions must be used to determine type (eg .gin/.got) */
default:
file_data = get_file_info((gpointer *) filename, BY_EXTENSION);
}
if (!file_data)
return;
#if DEBUG_FILE_LOAD
printf("Using file load routine for: [%s] files.\n", file_data->label);
#endif
if (mdata)
data = mdata;
else
{
/* get the new model number */
data = model_new();
if (!data)
{
gui_text_show(ERROR, "Model memory allocation failed.\n");
return;
}
}
data->id = file_data->id;
/* read file if exists, else try prepending current working directory */
if (file_data->read_file)
{
if (g_path_is_absolute(filename))
{
status = file_data->read_file(filename, data);
}
else
{
fullname = g_build_filename(sysenv.cwd, filename, NULL);
status = file_data->read_file(fullname, data);
g_free(fullname);
}
}
else
gui_text_show(ERROR, "No read routine for this type. ");
/* NEW - display error (if any) */
if ((data->error_file_read)->len)
{
gui_text_show(ERROR, (data->error_file_read)->str);
}
/* check for successful file load */
if (status)
{
gui_text_show(ERROR, "Load failed.\n");
printf("Load failed, error code: %d\n", status);
model_delete(data);
}
else
{
/* we don't know how many new models were loaded so */
/* scan through them all & check for initialization */
for (list=sysenv.mal ; list ; list=g_slist_next(list))
{
data = list->data;
/* skip if already on the tree */
if (data->grafted)
continue;
/* NEW - big model display mode exceptions */
/* CURRENT - this doesn't work - something not set up? */
/* TODO - automaticaly choose an appropriate zone size */
/*
if (data->num_atoms > 100000)
{
gpointer za;
core_render_mode_set(ZONE, data->cores);
za = zone_make(10.0, data);
zone_display_init(za, data);
zone_free(za);
}
else
*/
{
if (data->num_atoms > 1000)
core_render_mode_set(STICK, data->cores);
}
/* surfaces are always conv by default */
if (data->periodic == 2)
data->gulp.method = CONV;
/* not on tree - must have just been loaded */
tree_model_add(data);
/* create gulp supercells */
flag=0;
for (j=0 ; j<3 ; j++)
{
if (data->gulp.super[j] > 1)
{
data->image_limit[2*j+1] = data->gulp.super[j];
data->expected_cores *= data->gulp.super[j];
data->expected_shells *= data->gulp.super[j];
flag++;
}
}
if (flag)
{
space_make_images(CREATE, data);
space_make_supercell(data);
model_prep(data);
}
/* NEW - store initial frame, as trajectory animation will overwrite */
if (data->gulp.trj_file && !data->gulp.orig_cores)
{
/* FIXME - saving fractional type here instead of at the end of read_gulp() stuffs things up - why? */
/* NB: we need to save the coords here (and not earlier) in case a supercell was created */
memcpy(data->gulp.orig_pbc, data->pbc, 6*sizeof(gdouble));
memcpy(data->gulp.orig_latmat, data->latmat, 9*sizeof(gdouble));
data->gulp.orig_cores = dup_core_list(data->cores);
data->gulp.orig_shells = dup_shell_list(data->shels);
}
sysenv.active_model = data;
}
}
/* finished - only now we destroy the file dialog */
dialog_destroy_type(FILE_SELECT);
tree_select_active();
}
/****************/
/* load dialog */
/***************/
void file_load_dialog(void)
{
/* revert to data filetypes for special cases */
switch (sysenv.file_type)
{
case MD_ANALYSIS:
case PICTURE:
case PROJECT:
case GEOMVIEW_OFF:
sysenv.file_type = DATA;
}
file_dialog("Load file", NULL, FILE_LOAD, (gpointer) file_load, sysenv.file_type);
}
/**********************************/
/* save file with name */
/**********************************/
gint file_save_as(gchar *filename, struct model_pak *model)
{
gint id, ret;
gchar *name;
struct file_pak *file_data;
/* setup & checks */
if (!model)
model = sysenv.active_model;
if (!filename || !model)
return(1);
file_data = get_file_info((gpointer *) filename, BY_EXTENSION);
if (file_data)
{
/* use extension */
id = file_data->id;
strcpy(model->filename, filename);
g_free(model->basename);
model->basename = strdup_basename(filename);
}
else
{
gchar *ext;
/* no extension - attempt to use filter type */
file_data = get_file_info(GINT_TO_POINTER(sysenv.file_type), BY_FILE_ID);
if (!file_data)
return(2);
ext = g_slist_nth_data(file_data->ext, 0);
if (!ext)
return(2);
id = file_data->id;
g_free(model->basename);
model->basename = strdup_basename(filename);
name = g_strdup_printf("%s.%s", model->basename, ext);
strcpy(model->filename, name);
g_free(name);
}
/* file info indicates routine to call */
if (file_data->write_file == NULL)
{
printf("No write routine for this type.\n");
return(3);
}
else
{
/* build the full name */
name = g_build_filename(sysenv.cwd, model->filename, NULL);
ret = file_data->write_file(name, model);
g_free(name);
}
/* update */
if (ret)
gui_text_show(ERROR, "Save failed.\n");
else
{
gui_text_show(STANDARD, "Saved model.\n");
dialog_destroy_type(FILE_SELECT);
tree_model_refresh(model);
redraw_canvas(SINGLE);
}
return(ret);
}
/*************************************/
/* save active model using same name */
/*************************************/
void file_save(void)
{
gchar *name;
struct model_pak *model;
model = sysenv.active_model;
if (!model)
return;
/* strip the path, as file_save_as() prepends the cwd */
name = g_path_get_basename(model->filename);
file_save_as(name, model);
g_free(name);
}
/******************/
/* save as dialog */
/******************/
void file_save_dialog(void)
{
gchar *text=NULL;
struct model_pak *model;
model = sysenv.active_model;
if (model)
text = model->basename;
file_dialog("File save", text, FILE_SAVE, (gpointer) file_save_as,
sysenv.file_type);
}
/*************************************/
/* get the size of a file (in bytes) */
/*************************************/
gint file_byte_size(const gchar *filename)
{
struct stat buff;
stat(filename, &buff);
return(buff.st_size);
}
syntax highlighted by Code2HTML, v. 0.9.1