/*********************************************************************** * settings.c : Implementation of the settings of the map. ***********************************************************************/ /*********************************************************************** * This file is part of SpaceChart. * Copyright (C) 2000 Miguel Coca * * 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 #include #include #include #include #include #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, 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; }