/*
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
*/
/* irix */
#define _BSD_SIGNALS 1
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#ifndef __WIN32
#include <sys/wait.h>
#endif
#include <gtk/gtkgl.h>
#include "gdis.h"
#include "file.h"
#include "parse.h"
#include "task.h"
#include "render.h"
#include "matrix.h"
#include "opengl.h"
#include "numeric.h"
#include "module.h"
#include "library.h"
#include "interface.h"
#include "gui_image.h"
/* main data structures */
struct sysenv_pak sysenv;
struct elem_pak elements[MAX_ELEMENTS];
/********************************/
/* sfc hash table value cleanup */
/********************************/
void free_sfc(gpointer sfc_list)
{
free_slist((GSList *) sfc_list);
}
/******************/
/* system cleanup */
/******************/
/* TODO - other things to free? */
void sys_free(void)
{
g_hash_table_destroy(sysenv.sfc_table);
g_hash_table_destroy(sysenv.library);
g_hash_table_destroy(sysenv.manual);
g_hash_table_destroy(sysenv.image_table);
module_free();
}
/**********************************/
/* read the init file if possible */
/**********************************/
gint read_gdisrc(void)
{
gint i, element_flag, num_tokens;
gchar line[LINELEN], **buff;
gdouble version;
FILE *fp;
/* attempt to open */
fp = fopen(sysenv.init_file, "r");
/* check for an old/bad gdisrc */
if (fp)
{
/* scan the 1st line */
buff = get_tokenized_line(fp, &num_tokens);
if (g_ascii_strncasecmp(*buff,"gdis",4) == 0)
{
/* test for right version */
if (num_tokens < 2)
return(1);
version = str_to_float(*(buff+1));
sscanf(*(buff+1),"%lf",&version);
/* 0.75 was when the new element scheme was implemented */
if (version < 0.75)
return(1);
}
else
return(1);
g_strfreev(buff);
}
else
return(1);
/* read until EOF, or (failsafe) reached elements[] array allocation */
element_flag=0;
i=0;
for (;;)
{
/* NB: we need line[] to get the OpenGL font */
if (fgetline(fp, line))
break;
buff = tokenize(line, &num_tokens);
if (!buff)
break;
/* decide what to read */
if (g_ascii_strncasecmp("size",*buff,4) == 0)
{
if (num_tokens > 2)
{
sysenv.width = str_to_float(*(buff+1));
sysenv.height = str_to_float(*(buff+2));
if (sysenv.width < MIN_WIDTH)
sysenv.width = MIN_WIDTH;
if (sysenv.height < MIN_HEIGHT)
sysenv.height = MIN_HEIGHT;
}
}
/* model pane width */
if (g_ascii_strncasecmp("pane",*buff,4) == 0)
{
if (num_tokens > 2)
{
sysenv.tree_width = str_to_float(*(buff+1));
sysenv.tray_height = str_to_float(*(buff+2));
}
}
/* model tree/property divider */
if (g_ascii_strncasecmp("divide",*buff,6) == 0)
{
if (num_tokens > 1)
sysenv.tree_divider = (gint) str_to_float(*(buff+1));
}
/* povray executable */
if (g_ascii_strncasecmp("povray_p", *buff, 8) == 0)
{
if (num_tokens > 1)
sysenv.povray_path = g_strdup(*(buff+1));
}
if (g_ascii_strncasecmp("povray_e", *buff, 8) == 0)
{
if (num_tokens > 1)
{
g_free(sysenv.povray_exe);
sysenv.povray_exe = g_strdup(*(buff+1));
}
}
/* animation creation tool */
if (g_ascii_strncasecmp("convert_p", *buff, 9) == 0)
{
if (num_tokens > 1)
sysenv.convert_path = g_strdup(*(buff+1));
}
if (g_ascii_strncasecmp("convert_e", *buff, 9) == 0)
{
if (num_tokens > 1)
{
g_free(sysenv.convert_exe);
sysenv.convert_exe = g_strdup(*(buff+1));
}
}
/* image viewing */
if (g_ascii_strncasecmp("viewer_p", *buff, 8) == 0)
{
if (num_tokens > 1)
sysenv.viewer_path = g_strdup(*(buff+1));
}
if (g_ascii_strncasecmp("viewer_e", *buff, 8) == 0)
{
if (num_tokens > 1)
{
g_free(sysenv.viewer_exe);
sysenv.viewer_exe = g_strdup(*(buff+1));
}
}
/* gulp */
if (g_ascii_strncasecmp("gulp_p", *buff, 6) == 0)
{
if (num_tokens > 1)
sysenv.gulp_path = g_strdup(*(buff+1));
}
if (g_ascii_strncasecmp("gulp_e", *buff, 6) == 0)
{
if (num_tokens > 1)
{
g_free(sysenv.gulp_exe);
sysenv.gulp_exe = g_strdup(*(buff+1));
}
}
/* OpenGL drawing font */
if (g_ascii_strncasecmp("gl_font",*buff,7) == 0)
if (num_tokens > 1)
strcpy(sysenv.gl_fontname, g_strstrip(&line[8]));
/* model tree box */
if (g_ascii_strncasecmp("mtb",*buff,3) == 0)
if (num_tokens > 1)
sysenv.mtb_on = (gint) str_to_float(*(buff+1));
/* model properties box */
if (g_ascii_strncasecmp("mpb",*buff,3) == 0)
if (num_tokens > 1)
sysenv.mpb_on = (gint) str_to_float(*(buff+1));
/* model symmetry box */
if (g_ascii_strncasecmp("msb",*buff,3) == 0)
if (num_tokens > 1)
sysenv.msb_on = (gint) str_to_float(*(buff+1));
/* atom properties box */
if (g_ascii_strncasecmp("apb",*buff,3) == 0)
if (num_tokens > 1)
sysenv.apb_on = (gint) str_to_float(*(buff+1));
/* halo type */
if (g_ascii_strncasecmp("halo",*buff,4) == 0)
if (num_tokens > 1)
sysenv.render.halos = (gint) str_to_float(*(buff+1));
/* low quality rotation */
if (g_ascii_strncasecmp("fast",*buff,4) == 0)
if (num_tokens > 1)
sysenv.render.fast_rotation = (gint) str_to_float(*(buff+1));
if (g_ascii_strncasecmp(*buff, "colour_bg", 9) == 0)
{
if (num_tokens > 3)
{
sysenv.render.bg_colour[0] = str_to_float(*(buff+1));
sysenv.render.bg_colour[1] = str_to_float(*(buff+2));
sysenv.render.bg_colour[2] = str_to_float(*(buff+3));
}
}
if (g_ascii_strncasecmp(*buff, "colour_morph", 11) == 0)
{
if (num_tokens > 3)
{
sysenv.render.morph_colour[0] = str_to_float(*(buff+1));
sysenv.render.morph_colour[1] = str_to_float(*(buff+2));
sysenv.render.morph_colour[2] = str_to_float(*(buff+3));
}
}
if (g_ascii_strncasecmp("colour_rsurf", *buff, 12) == 0)
{
if (num_tokens > 3)
{
sysenv.render.rsurf_colour[0] = str_to_float(*(buff+1));
sysenv.render.rsurf_colour[1] = str_to_float(*(buff+2));
sysenv.render.rsurf_colour[2] = str_to_float(*(buff+3));
}
}
/* cleanup */
g_strfreev(buff);
}
/* parse for elements */
rewind(fp);
read_elem_data(fp, MODIFIED);
return(0);
}
/*********************************************/
/* write setup & elements to the gdisrc file */
/*********************************************/
gint write_gdisrc(void)
{
FILE *fp;
fp = fopen(sysenv.init_file,"w");
if (!fp)
{
printf("Error: unable to create %s\n", sysenv.init_file);
return(1);
}
/* save final dimensions */
if (sysenv.mpane)
if (GTK_IS_WIDGET(sysenv.mpane))
sysenv.tree_width = GTK_WIDGET(sysenv.mpane)->allocation.width;
if (sysenv.tpane)
if (GTK_IS_WIDGET(sysenv.tpane))
sysenv.tray_height = GTK_WIDGET(sysenv.tpane)->allocation.height;
fprintf(fp,"gdis %f\n", VERSION);
fprintf(fp,"canvas %d\n", sysenv.canvas);
fprintf(fp,"size %d %d\n", sysenv.width,sysenv.height);
fprintf(fp,"pane %d %d\n", sysenv.tree_width, sysenv.tray_height);
fprintf(fp,"divider %d\n", sysenv.tree_divider);
fprintf(fp,"gl_font %s\n", sysenv.gl_fontname);
fprintf(fp,"mtb %d\n", sysenv.mtb_on);
fprintf(fp,"mpb %d\n", sysenv.mpb_on);
fprintf(fp,"msb %d\n", sysenv.msb_on);
fprintf(fp,"apb %d\n", sysenv.apb_on);
fprintf(fp,"halos %d\n", sysenv.render.halos);
fprintf(fp,"fast %d\n", sysenv.render.fast_rotation);
fprintf(fp,"colour_bg %f %f %f\n", sysenv.render.bg_colour[0],
sysenv.render.bg_colour[1],
sysenv.render.bg_colour[2]);
fprintf(fp,"colour_morph %f %f %f\n", sysenv.render.morph_colour[0],
sysenv.render.morph_colour[1],
sysenv.render.morph_colour[2]);
fprintf(fp,"colour_rsurf %f %f %f\n", sysenv.render.rsurf_colour[0],
sysenv.render.rsurf_colour[1],
sysenv.render.rsurf_colour[2]);
if (sysenv.babel_path)
fprintf(fp,"babel_path %s\n", sysenv.babel_path);
if (sysenv.convert_path)
fprintf(fp,"convert_path %s\n", sysenv.convert_path);
if (sysenv.gulp_path)
fprintf(fp,"gulp_path %s\n", sysenv.gulp_path);
if (sysenv.gamess_path)
fprintf(fp,"gamess_path %s\n", sysenv.gamess_path);
if (sysenv.povray_path)
fprintf(fp,"povray_path %s\n", sysenv.povray_path);
if (sysenv.viewer_path)
fprintf(fp,"viewer_path %s\n", sysenv.viewer_path);
fprintf(fp,"babel_exe %s\n", sysenv.babel_exe);
fprintf(fp,"convert_exe %s\n", sysenv.convert_exe);
fprintf(fp,"gulp_exe %s\n", sysenv.gulp_exe);
fprintf(fp,"gamess_exe %s\n", sysenv.gamess_exe);
fprintf(fp,"povray_exe %s\n", sysenv.povray_exe);
fprintf(fp,"viewer_exe %s\n", sysenv.viewer_exe);
/* write the non-default element data */
write_elem_data(fp);
fclose(fp);
return(0);
}
/**************/
/* main setup */
/**************/
#define DEBUG_SYS_INIT 0
void sys_init(gint argc, gchar *argv[])
{
gchar *temp;
const gchar *envdir, *ctemp;
struct light_pak *light;
FILE *fp;
/* top level structure initialization */
sysenv.max_threads = 1;
sysenv.task_list = NULL;
sysenv.dialog_list = NULL;
sysenv.glconfig = NULL;
sysenv.stereo = FALSE;
sysenv.stereo_windowed = FALSE;
sysenv.stereo_fullscreen = FALSE;
sysenv.canvas_list = NULL;
sysenv.canvas_rows = 1;
sysenv.canvas_cols = 1;
sysenv.width = START_WIDTH;
sysenv.height = START_HEIGHT;
sysenv.snapshot = FALSE;
sysenv.snapshot_filename = NULL;
sysenv.tree_width = START_WIDTH/4;
sysenv.tree_divider = -1;
sysenv.tray_height = 60;
sysenv.mpane = NULL;
sysenv.tpane = NULL;
sysenv.fps = 40;
sysenv.moving = FALSE;
sysenv.roving = FALSE;
sysenv.refresh_canvas = FALSE;
sysenv.refresh_dialog = FALSE;
sysenv.refresh_tree = FALSE;
sysenv.refresh_properties = FALSE;
sysenv.refresh_text = FALSE;
sysenv.mtb_on = TRUE;
sysenv.mpb_on = TRUE;
sysenv.msb_on = TRUE;
sysenv.apb_on = TRUE;
sysenv.lmb_on = FALSE;
sysenv.pib_on = FALSE;
/* default to single model display */
sysenv.mal = NULL;
sysenv.displayed[0] = -1;
sysenv.active_model = NULL;
sysenv.canvas = TRUE;
sysenv.select_mode = CORE;
sysenv.calc_pbonds = TRUE;
/* default masks */
sysenv.file_type = DATA;
sysenv.babel_type = AUTO;
sysenv.num_elements = sizeof(elements) / sizeof(struct elem_pak);
sysenv.elements = NULL;
/* rendering setup */
sysenv.render.width = 600;
sysenv.render.height = 600;
sysenv.render.vp_dist = 5.0;
sysenv.render.zone_size = 10.0;
/* stereo defaults */
sysenv.render.stereo_quadbuffer = FALSE;
sysenv.render.stereo_use_frustum = TRUE;
sysenv.render.stereo_eye_offset = 1.0;
sysenv.render.stereo_parallax = 1.0;
sysenv.render.stereo_left = TRUE;
sysenv.render.stereo_right = TRUE;
/* default light */
light = g_malloc(sizeof(struct light_pak));
light->type = DIRECTIONAL;
VEC3SET(light->x, -1.0, 1.0, -1.0);
VEC3SET(light->colour, 1.0, 1.0, 1.0);
light->ambient = 0.2;
light->diffuse = 0.8;
light->specular = 0.7;
/*** JJM new values for better (IMHO) lighting ***/
light->diffuse = 0.5;
//light->specular = 0.3;
sysenv.render.light_list = g_slist_append(sysenv.render.light_list, light);
sysenv.render.num_lights = 1;
sysenv.render.perspective = FALSE;
sysenv.render.antialias = FALSE;
sysenv.render.wire_show_hidden = FALSE;
sysenv.render.fog = FALSE;
sysenv.render.wire_model = FALSE;
sysenv.render.wire_surface = FALSE;
sysenv.render.shadowless = FALSE;
sysenv.render.animate = FALSE;
sysenv.render.no_povray_exec = FALSE;
sysenv.render.no_keep_tempfiles = TRUE;
sysenv.render.animate_type = ANIM_GIF;
sysenv.render.animate_file = g_strdup("movie");
sysenv.render.atype = FALSE;
sysenv.render.axes = FALSE;
sysenv.render.morph_finish = g_strdup("F_Glass4");
sysenv.render.ref_index = 2.5;
sysenv.render.delay = 20.0;
sysenv.render.mpeg_quality = 95.0;
sysenv.render.sphere_quality = 3.0;
sysenv.render.cylinder_quality = 9.0;
sysenv.render.ribbon_quality = 10.0;
sysenv.render.ms_grid_size = 0.5;
sysenv.render.auto_quality = FALSE;
sysenv.render.fast_rotation = FALSE;
sysenv.render.halos = FALSE;
sysenv.render.ambience = 0.2;
sysenv.render.diffuse = 0.9;
sysenv.render.specular = 0.9;
sysenv.render.transmit = 1.0;
sysenv.render.ghost_opacity = 0.5;
sysenv.render.ball_rad = 0.3;
sysenv.render.stick_rad = 0.1;
sysenv.render.stick_thickness = GTKGL_LINE_WIDTH;
sysenv.render.line_thickness = GTKGL_LINE_WIDTH;
sysenv.render.frame_thickness = GTKGL_LINE_WIDTH;
sysenv.render.geom_line_width = 3.0;
sysenv.render.cpk_scale = 1.0;
sysenv.render.fog_density = 0.35;
sysenv.render.fog_start = 0.5;
sysenv.render.ribbon_curvature = 0.5;
sysenv.render.ribbon_thickness = 1.0;
sysenv.render.phonon_scaling = 4.0;
sysenv.render.ahl_strength = 0.7;
sysenv.render.ahl_size = 20;
sysenv.render.shl_strength = 0.8;
sysenv.render.shl_size = 20;
VEC3SET(sysenv.render.fg_colour, 1.0, 1.0, 1.0);
VEC3SET(sysenv.render.bg_colour, 0.0, 0.0, 0.0);
VEC3SET(sysenv.render.morph_colour, 0.1, 0.1, 0.8);
VEC3SET(sysenv.render.rsurf_colour, 0.0, 0.3, 0.6);
VEC3SET(sysenv.render.label_colour, 1.0, 1.0, 0.0);
VEC3SET(sysenv.render.title_colour, 0.0, 1.0, 1.0);
VEC3SET(sysenv.render.ribbon_colour, 0.0, 0.0, 1.0);
/* setup directory and file pointers */
sysenv.cwd = g_get_current_dir();
envdir = g_getenv("GDIS_START_DIR");
if (envdir)
sysenv.cwd = (gchar *) envdir;
#if DEBUG_SYS_INIT
printf("cwd: [%s]\n", sysenv.cwd);
#endif
/* generate element file full pathname */
/* sometimes this returns the program name, and sometimes it doesn't */
#ifdef INSTALL
temp = g_strdup(INSTALL);
#else
temp = g_find_program_in_path(argv[0]);
#endif
/* remove program name (if attached) */
if (g_file_test(temp, G_FILE_TEST_IS_DIR))
sysenv.gdis_path = temp;
else
{
sysenv.gdis_path = g_path_get_dirname(temp);
g_free(temp);
}
#if DEBUG_SYS_INIT
printf("%s path: [%s]\n", argv[0], sysenv.gdis_path);
#endif
if (sysenv.gdis_path)
sysenv.elem_file = g_build_filename(sysenv.gdis_path, ELEM_FILE, NULL);
else
{
printf("WARNING: gdis directory not found.\n");
sysenv.elem_file = g_build_filename(sysenv.cwd, ELEM_FILE, NULL);
}
/* generate gdisrc full pathname */
ctemp = g_get_home_dir();
if (ctemp)
sysenv.init_file = g_build_filename(ctemp, INIT_FILE, NULL);
else
{
printf("WARNING: home directory not found.\n");
if (sysenv.gdis_path)
sysenv.init_file = g_build_filename(sysenv.gdis_path, INIT_FILE, NULL);
else
{
if (sysenv.cwd)
sysenv.init_file = g_build_filename(sysenv.cwd, INIT_FILE, NULL);
else
{
printf("FATAL: current directory not found.\n");
exit(-1);
}
}
}
/* defaults */
#if _WIN32
sysenv.babel_exe = g_strdup("babel.exe");
sysenv.povray_exe = g_strdup("povray.exe");
sysenv.convert_exe = g_strdup("convert.exe");
sysenv.viewer_exe = g_strdup("display.exe");
sysenv.gulp_exe = g_strdup("gulp.exe");
sysenv.gamess_exe = g_strdup("wingamess");
#else
sysenv.babel_exe = g_strdup("babel");
sysenv.povray_exe = g_strdup("povray");
sysenv.convert_exe = g_strdup("convert");
sysenv.viewer_exe = g_strdup("display");
sysenv.gulp_exe = g_strdup("gulp");
sysenv.gamess_exe = g_strdup("run_gms_for_gdis");
#endif
strcpy(sysenv.gl_fontname, GL_FONT);
/* atomic scattering factor coefficients */
sysenv.sfc_table = g_hash_table_new_full(&g_str_hash,
&hash_strcmp,
&g_free,
&free_sfc);
/* IMPORTANT this must be done before gdisrc is parsed as */
/* setup the element data before any possible modifications */
/* can be read in from the gdisrc file */
printf("scanning: %-50s ", sysenv.elem_file);
fp = fopen(sysenv.elem_file, "rt");
if (fp)
{
read_elem_data(fp, DEFAULT);
fclose(fp);
printf("[ok]\n");
}
else
{
/* missing default element info is fatal */
printf("[not found]\n");
exit(1);
}
/* if failed to read gdisrc - write a new one */
/* TODO - if overwrite old version, save/rename first? */
sysenv.babel_path = NULL;
sysenv.convert_path = NULL;
sysenv.gulp_path = NULL;
sysenv.gamess_path = NULL;
sysenv.povray_path = NULL;
sysenv.viewer_path = NULL;
if (read_gdisrc())
{
printf("creating: %-50s ", sysenv.init_file);
if (write_gdisrc())
printf("[error]\n");
else
printf("[ok]\n");
}
else
printf("scanning: %-50s [ok]\n", sysenv.init_file);
/* get executable paths */
if (!sysenv.babel_path)
sysenv.babel_path = g_find_program_in_path(sysenv.babel_exe);
if (!sysenv.convert_path)
sysenv.convert_path = g_find_program_in_path(sysenv.convert_exe);
if (!sysenv.gulp_path)
sysenv.gulp_path = g_find_program_in_path(sysenv.gulp_exe);
if (!sysenv.povray_path)
sysenv.povray_path = g_find_program_in_path(sysenv.povray_exe);
if (!sysenv.viewer_path)
sysenv.viewer_path = g_find_program_in_path(sysenv.viewer_exe);
/* HACK FIX - GAMESS path contains the path, not the path + file */
temp = g_find_program_in_path(sysenv.gamess_exe);
if (temp)
sysenv.gamess_path = g_path_get_dirname(temp);
else
#if __WIN32
sysenv.gamess_path = g_strdup("c:\\wingamess");
#else
sysenv.gamess_path = NULL;
#endif
g_free(temp);
/* tree init */
sysenv.num_trees = 0;
/* copied selection */
sysenv.select_source = NULL;
sysenv.module_list = NULL;
sysenv.projects = NULL;
sysenv.manual = NULL;
sysenv.image_table = NULL;
sysenv.surfaces = NULL;
/* module */
file_init();
help_init();
init_math();
library_init();
}
/********/
/* MAIN */
/********/
gint main(int argc, char *argv[])
{
gint i;
/* NBL read this 1st as it affects canvas type, but command */
/* line arguments should be able to overide */
sys_init(argc, argv);
module_setup();
sysenv.write_gdisrc = FALSE;
/* command line? */
if (argc > 1)
if (g_ascii_strncasecmp(argv[1],"-c",3) == 0)
sysenv.canvas = FALSE;
/* set up main window and event handlers (or start non-gui mode) */
if (sysenv.canvas)
{
/* initialize threads and set up the queue */
task_queue_init();
gtk_init(&argc, &argv);
gtk_gl_init(&argc, &argv);
/* main interface */
gui_init();
/* task update timer */
/* TODO - put this in gui_widget_handler? */
g_timeout_add(1000, (GSourceFunc) &update_task_info, NULL);
/* screen redraw timer */
g_timeout_add(25, (GSourceFunc) &gui_canvas_handler, NULL);
/* CURRENT - gui updates done through a timer */
/* this was done so that threads can safely schedule a gui update */
g_timeout_add(200, (GSourceFunc) &gui_widget_handler, NULL);
/* process arguments as files to load */
for (i=1 ; i<argc ; i++)
file_load(argv[i], NULL);
/* thread-safe handling */
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
}
return(0);
}
syntax highlighted by Code2HTML, v. 0.9.1