/***********************************************************************
* settings.c : Implementation of the settings of the map.
***********************************************************************/
/***********************************************************************
* This file is part of SpaceChart.
* Copyright (C) 2000 Miguel Coca <e970095@zipi.fi.upm.es>
*
* 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.
***********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <gdk/gdk.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include "../include/starmap.h"
#include "../include/star_selection.h"
#include "../include/link_selection.h"
#include "../include/star_draw_rules.h"
#include "../include/link_draw_rules.h"
#include "../include/settings.h"
#include "../include/rcparser.h"
#define FNAME_LENGTH 256
typedef struct
{
properties_set_t prop_set;
void (*callback)(settings_t* settings, void* data);
void *data;
} callback_t;
struct st_settings
{
int callbacks_disabled;
int cb_list_length;
callback_t *callbacks;
properties_set_t changed_properties;
char *catalog_filename;
star_selection_t *star_filter;
link_selection_t *link_filter;
double view_radius;
int show_links;
int show_link_labels;
int show_star_labels;
double labels_color[3];
char labels_font[FNAME_LENGTH];
distance_unit_t distance_unit;
coords_3d_t center;
coords_3d_t line_of_sight;
coords_3d_t up;
double view_distance;
star_drawing_rules_t* star_draw_rules;
link_drawing_rules_t* link_draw_rules;
key_press_t keys[KEY_END_OF_LIST];
};
/* Definition of private functions. */
static int set_default_settings( settings_t *settings );
static void handle_callbacks( settings_t *settings );
static int read_config_files( rcparser_t *parser );
/* Public Functions. */
settings_t* settings_new( void )
{
settings_t *settings;
int i;
if( (settings = (settings_t*) malloc( sizeof( struct st_settings ))) &&
(settings->callbacks = malloc(sizeof(callback_t))) )
{
settings->star_draw_rules = NULL;
settings->link_draw_rules = NULL;
settings->catalog_filename = NULL;
settings->callbacks_disabled = 0;
settings->callbacks[0].prop_set = 0;
settings->cb_list_length = 0;
settings->catalog_filename = NULL;
settings->changed_properties = 0;
for( i = 0; i < KEY_END_OF_LIST; i++ )
{
settings->keys[i].key = 0;
settings->keys[i].mods = 0;
}
if( !set_default_settings( settings ) )
{
free( settings );
settings = NULL;
}
}
return settings;
}
int settings_load_from_files( settings_t *settings )
{
rcparser_t *parser;
parser = rcparser_new();
if( !read_config_files( parser ) )
{
emit_error_message( _("Could not load configuration files. "
"Aborting") );
exit( EXIT_FAILURE );
}
settings_disable_callbacks( settings );
rcparser_apply_to_settings( parser, settings );
settings_enable_callbacks( settings );
}
int settings_add_callback( settings_t* settings, properties_set_t prop_set,
void (*callback)(settings_t* settings, void* data),
void* data )
{
callback_t *list = settings->callbacks;
if( (settings->callbacks = realloc( settings->callbacks,
(settings->cb_list_length+2) *
(sizeof(callback_t)) )) )
{
settings->callbacks[settings->cb_list_length].prop_set =
prop_set;
settings->callbacks[settings->cb_list_length].callback =
callback;
settings->callbacks[settings->cb_list_length].data = data;
settings->callbacks[settings->cb_list_length+1].prop_set = 0;
settings->cb_list_length++;
return settings->cb_list_length;
}
else
{
settings->callbacks = list;
return 0;
}
}
void settings_disable_callbacks( settings_t* settings )
{
settings->callbacks_disabled++;
}
void settings_enable_callbacks( settings_t* settings )
{
if( settings->callbacks_disabled )
settings->callbacks_disabled--;
handle_callbacks( settings );
}
void settings_set_catalog_filename( settings_t *settings,
const char *filename )
{
if( !filename )
{
if( settings->catalog_filename )
free( settings->catalog_filename );
settings->catalog_filename = NULL;
return;
}
if( !( settings->catalog_filename &&
!strcmp( filename, settings->catalog_filename )) )
{
if( settings->catalog_filename )
free( settings->catalog_filename );
settings->catalog_filename = strdup( filename );
settings->changed_properties = settings->changed_properties |
PROPERTIES_CATALOG_FILENAME;
handle_callbacks( settings );
}
}
char *settings_get_catalog_filename( settings_t *settings )
{
return settings->catalog_filename;
}
void settings_set_star_filter( settings_t* settings,star_selection_t* filter )
{
settings->star_filter = filter;
settings->changed_properties = settings->changed_properties |
PROPERTIES_STAR_FILTER;
handle_callbacks( settings );
}
star_selection_t* settings_get_star_filter( settings_t* settings )
{
return settings->star_filter;
}
void settings_set_link_filter( settings_t* settings,link_selection_t* filter )
{
settings->link_filter = filter;
settings->changed_properties = settings->changed_properties |
PROPERTIES_LINK_FILTER;
handle_callbacks( settings );
}
link_selection_t* settings_get_link_filter( settings_t* settings )
{
return settings->link_filter;
}
void settings_set_view_radius( settings_t* settings, double view_radius )
{
settings->view_radius = view_radius;
settings->changed_properties = settings->changed_properties |
PROPERTIES_VIEW_RADIUS;
handle_callbacks( settings );
}
double settings_get_view_radius( settings_t* settings )
{
return settings->view_radius;
}
void settings_set_show_links( settings_t* settings, int value )
{
settings->show_links = value;
settings->changed_properties = settings->changed_properties |
PROPERTIES_SHOW_LINKS;
handle_callbacks( settings );
}
int settings_get_show_links( settings_t* settings )
{
return settings->show_links;
}
void settings_set_show_link_labels( settings_t* settings, int value )
{
settings->show_link_labels = value;
settings->changed_properties = settings->changed_properties |
PROPERTIES_SHOW_LINK_LABELS;
handle_callbacks( settings );
}
int settings_get_show_link_labels( settings_t* settings )
{
return settings->show_link_labels;
}
void settings_set_show_star_labels( settings_t* settings, int value )
{
settings->show_star_labels = value;
settings->changed_properties = settings->changed_properties |
PROPERTIES_SHOW_STAR_LABELS;
handle_callbacks( settings );
}
int settings_get_show_star_labels( settings_t* settings )
{
return settings->show_star_labels;
}
void settings_set_labels_color( settings_t* settings, double rgb[] )
{
settings->labels_color[0] = rgb[0];
settings->labels_color[1] = rgb[1];
settings->labels_color[2] = rgb[2];
settings->changed_properties = settings->changed_properties |
PROPERTIES_LABELS_COLOR;
handle_callbacks( settings );
}
void settings_get_labels_color( settings_t* settings, double rgb[] )
{
rgb[0] = settings->labels_color[0];
rgb[1] = settings->labels_color[1];
rgb[2] = settings->labels_color[2];
}
void settings_set_labels_font( settings_t* settings, const char *font )
{
strncpy( settings->labels_font, font, FNAME_LENGTH );
settings->changed_properties = settings->changed_properties |
PROPERTIES_LABELS_FONT;
handle_callbacks( settings );
}
char *settings_get_labels_font( settings_t* settings )
{
return settings->labels_font;
}
void settings_set_distance_unit( settings_t* settings, distance_unit_t unit )
{
settings->distance_unit = unit;
settings->changed_properties = settings->changed_properties |
PROPERTIES_DISTANCE_UNIT;
handle_callbacks( settings );
}
distance_unit_t settings_get_distance_unit( settings_t* settings )
{
return settings->distance_unit;
}
void settings_set_center( settings_t* settings, coords_3d_t* center )
{
settings->center = *center;
settings->changed_properties = settings->changed_properties |
PROPERTIES_CENTER;
handle_callbacks( settings );
}
void settings_get_center( settings_t* settings, coords_3d_t* center )
{
*center = settings->center;
}
void settings_set_sight_params( settings_t* settings,
coords_3d_t* line_of_sight,
coords_3d_t* up )
{
settings->line_of_sight = *line_of_sight;
settings->up = *up;
settings->changed_properties = settings->changed_properties |
PROPERTIES_SIGHT_PARAMS;
handle_callbacks( settings );
}
void settings_get_sight_params( settings_t* settings,
coords_3d_t* line_of_sight,
coords_3d_t* up )
{
if( line_of_sight )
*line_of_sight = settings->line_of_sight;
if( up )
*up = settings->up;
}
/* FIXME: The math knowledge should be out of these module. How? */
/* Many Thanks to Santiago Cifuentes, <tagore@apdo.com> for working out the
* math used in this functions. */
void settings_set_sight_params_polar( settings_t* settings,
double longitude, double latitude,
double north )
{
coords_3d_t los, up;
los.x = longitude;
los.y = latitude;
los.z = 1;
polar_to_cartesian(&los);
up.x = -cos(north)*cos(longitude)*sin(latitude)+sin(north)*sin(longitude);
up.y = -cos(north)*sin(longitude)*sin(latitude)-sin(north)*cos(longitude);
up.z = cos(north)*cos(latitude);
settings_set_sight_params(settings, &los, &up);
}
void settings_get_sight_params_polar( settings_t* settings,
double *longitude, double *latitude,
double *north )
{
coords_3d_t los, up, north_pole;
double product;
los = settings->line_of_sight;
up = settings->up;
cartesian_to_polar(&los);
*longitude = los.x;
*latitude = los.y;
north_pole.x = -cos(*longitude)*sin(*latitude);
north_pole.y = -sin(*longitude)*sin(*latitude);
north_pole.z = cos(*latitude);
product = (north_pole.x * up.x) + (north_pole.y * up.y) +
(north_pole.z * up.z);
/* Should never happen... but this is floating point we are
* talking about. */
if( product > 1.0 )
product = 1.0;
else if( product < -1.0 )
product = -1.0;
*north = acos(product);
}
void settings_set_star_draw_rules( settings_t* settings,
star_drawing_rules_t* rules )
{
if( settings->star_draw_rules )
star_drawing_rules_destroy( settings->star_draw_rules );
settings->star_draw_rules = rules;
settings->changed_properties = settings->changed_properties |
PROPERTIES_STAR_DRAW_RULES;
handle_callbacks( settings );
}
star_drawing_rules_t* settings_get_star_draw_rules( settings_t* settings )
{
return settings->star_draw_rules;
}
void settings_find_star_draw( settings_t* settings, star_t* star, int* radius,
double rgb[], int* show_name )
{
star_drawing_rules_find( settings->star_draw_rules, star, radius, rgb,
show_name );
}
void settings_set_link_draw_rules( settings_t* settings,
link_drawing_rules_t* rules )
{
if( settings->link_draw_rules )
link_drawing_rules_destroy( settings->link_draw_rules );
settings->link_draw_rules = rules;
settings->changed_properties = settings->changed_properties |
PROPERTIES_LINK_FILTER;
handle_callbacks( settings );
}
link_drawing_rules_t* settings_get_link_draw_rules( settings_t* settings )
{
return settings->link_draw_rules;
}
void settings_find_link_draw( settings_t* settings, link_t* link, int* width,
GdkLineStyle *style, double rgb[] )
{
link_drawing_rules_find( settings->link_draw_rules, link, width,
style, rgb );
}
void settings_set_keybindings( settings_t* settings, key_press_t *keys )
{
memcpy(settings->keys, keys, sizeof(settings->keys));
settings->changed_properties = settings->changed_properties |
PROPERTIES_KEYBINDINGS;
handle_callbacks( settings );
}
void settings_get_keybindings( settings_t* settings, key_press_t *keys )
{
memcpy(keys, settings->keys, sizeof(settings->keys));
}
void settings_destroy( settings_t* settings )
{
free( settings->callbacks );
star_selection_destroy( settings->star_filter );
link_selection_destroy( settings->link_filter );
star_drawing_rules_destroy( settings->star_draw_rules );
link_drawing_rules_destroy( settings->link_draw_rules );
}
/* Private Functions */
void handle_callbacks( settings_t* settings )
{
int i;
properties_set_t changed;
/* A callback could change the settings, thus launching another
* handle_callbacks(), but if the changed properties are not cleared
* after the end of this function, the cb would be called again, in an
* possibly infinite way. So we save the current changes and clear the
* ones in settings.
*/
if( !settings->callbacks_disabled )
{
changed = settings->changed_properties;
settings->changed_properties = 0;
for( i = 0; settings->callbacks[i].prop_set; i++ )
{
if( (settings->callbacks[i].prop_set & changed) )
{
settings->callbacks[i].
callback(settings,
settings->callbacks[i].data);
}
}
}
}
int read_config_files( rcparser_t *parser )
{
char filename[256];
char buffer[256];
struct stat status;
int success;
/* Read the global configuration file */
snprintf( filename, sizeof(filename), "%s/spacechartrc", SYSCONFDIR );
if( access( filename, R_OK ) != -1 )
success = rcparser_parse_file( parser, filename );
else
{
snprintf( buffer, sizeof(buffer), "%s: %s", filename,
strerror(errno) );
emit_error_message(buffer);
exit( EXIT_FAILURE );
}
if( success == 1 )
return 0;
/* Now the user's config file, if it exists */
snprintf( filename, sizeof(filename), "%s/.spacechartrc",
getenv("HOME") );
if( stat( filename, &status ) == -1 )
{
if( errno != ENOENT )
{
snprintf( buffer, sizeof(buffer), "%s: %s",
filename, strerror(errno) );
emit_error_message(buffer);
}
else
/* The file does not exist. Don't worry. */
return 1;
}
if( (access( filename, R_OK ) != -1) &&
( (status.st_mode & S_IFMT) != S_IFDIR ) )
success = rcparser_parse_file( parser, filename );
if( success == 1 )
return 0;
return 1;
}
int set_default_settings( settings_t *settings )
{
#ifdef undef
coords_3d_t line_of_sight, center, up;
star_drawing_rules_t* star_rules;
link_drawing_rules_t* link_rules;
gdouble color[3] = { 1.0, 0.0, 0.0 };
star_selection_t* s_selection;
link_selection_t* l_selection;
double radius;
/* FIXME: Check for memory errors */
/* Just in case, we disable the callbacks. */
settings_disable_callbacks( settings );
/* First, the default coordinates */
radius = 5.5;
line_of_sight.x = 1;
line_of_sight.y = 0;
line_of_sight.z = 0;
center.x = 0;
center.y = 0;
center.z = 0;
up.x = 0;
up.y = 0;
up.z = 1;
/* Now, the star drawing rules. */
star_rules = star_drawing_rules_new( DEFAULT_SIZE, default_color );
s_selection = star_selection_new();
star_selection_act_min_lum( s_selection, 100.0 );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_LUMINOSITY,
5, NULL, FALSE );
s_selection = star_selection_new();
star_selection_act_min_lum( s_selection, 50.0 );
star_selection_act_max_lum( s_selection, 100.0 );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_LUMINOSITY,
4, NULL, FALSE );
s_selection = star_selection_new();
star_selection_act_min_lum( s_selection, 10.0 );
star_selection_act_max_lum( s_selection, 50.0 );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_LUMINOSITY,
3, NULL, FALSE );
s_selection = star_selection_new();
star_selection_act_min_lum( s_selection, 0.4 );
star_selection_act_max_lum( s_selection, 10.0 );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_LUMINOSITY,
2, NULL, FALSE );
s_selection = star_selection_new();
star_selection_act_max_lum( s_selection, 0.4 );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_LUMINOSITY,
1, NULL, FALSE );
color[0] = 1.0;
color[1] = 1.0;
color[2] = 1.0;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_O );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_O,
0, color, FALSE );
color[0] = 1.0;
color[1] = 1.0;
color[2] = 1.0;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_B );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_B,
0, color, FALSE );
color[0] = 0.90;
color[1] = 1.0;
color[2] = 1.0;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_A );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_A,
0, color, FALSE );
color[0] = 1.0;
color[1] = 1.0;
color[2] = 0.75;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_F );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_F,
0, color, FALSE );
color[0] = 1.0;
color[1] = 1.0;
color[2] = 0.0;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_G );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_G,
0, color, FALSE );
color[0] = 1.0;
color[1] = 0.5;
color[2] = 0.0;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_K );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_K,
0, color, FALSE );
color[0] = 1.0;
color[1] = 0.0;
color[2] = 0.0;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_M );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_M,
0, color, FALSE );
color[0] = 0.75;
color[1] = 0.75;
color[2] = 0.75;
s_selection = star_selection_new();
star_selection_act_spectrum( s_selection, SPECTRUM_WHITE_DWARF );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SPECTRUM_WD,
0, color, FALSE );
s_selection = star_selection_new();
star_selection_act_min_lum( s_selection, 1.00 );
star_drawing_rules_add( star_rules, s_selection, PRIORITY_SHOW_NAME,
0, NULL, TRUE );
/* Initialization of the line drawing rules */
color[0] = 0.0;
color[1] = 0.36;
color[2] = 0.6;
link_rules = link_drawing_rules_new( 0, GDK_LINE_DOUBLE_DASH, color );
color[0] = 0.0;
color[1] = 0.7;
color[2] = 1.0;
l_selection = link_selection_new();
link_selection_act_max_length( l_selection, 1.5 );
link_drawing_rules_add( link_rules, l_selection, 0, GDK_LINE_SOLID,
color );
color[0] = 0.0;
color[1] = 0.48;
color[2] = 0.8;
l_selection = link_selection_new();
link_selection_act_min_length( l_selection, 1.5 );
link_selection_act_max_length( l_selection, 2.0 );
link_drawing_rules_add( link_rules, l_selection, 0, GDK_LINE_SOLID,
color );
/* Now we set the selections */
s_selection = star_selection_new(); /* Empty selection: all matches */
l_selection = link_selection_new();
link_selection_act_max_length( l_selection, 2.5 );
/* Finally, write everything to the settings. */
settings_set_center( settings, ¢er );
settings_set_sight_params( settings, &line_of_sight, &up );
settings_set_view_radius( settings, radius );
settings_set_star_filter( settings, s_selection );
settings_set_link_filter( settings, l_selection );
settings_set_star_draw_rules( settings, star_rules );
settings_set_link_draw_rules( settings, link_rules );
settings_set_show_links( settings, TRUE );
settings_set_show_link_labels( settings, FALSE );
settings_set_show_star_labels( settings, TRUE );
color[0] = 0.0;
color[1] = 1.0;
color[2] = 1.0;
settings_set_labels_color( settings, color );
settings_set_labels_font( settings,
"-misc-fixed-medium-r-semicondensed"
"-*-13-*-*-*-c-*-iso8859-8" );
settings_set_distance_unit( settings, DISTANCE_PARSECS );
/* Enable the callbacks */
settings_enable_callbacks( settings );
#endif
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1