/* * Ump - Unnamed Math Program * Copyright (c) 2003-2006 by Mattias Hultgren * * * 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; version 2 of the License. * * 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 "main.h" #include #include #include #include #include "utf8_string.h" #include "math2.h" #include "vector.h" #include "addon_functions.h" #ifndef NO_GTK #include #endif #include "ump_3d_viewer.h" extern "C" { extern char *translation_svenska; } #define GET_BOOLEAN_KEY( KEY, DEST ) if((str = setup_file.get_key( KEY )) != 0) \ { \ if( *str == "True" ) \ DEST = true; \ else if( *str == "False" ) \ DEST = false; \ else \ { \ char tmp_err[ERROR_OBJ_MSG_LEN]; \ snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Invalid format in file %s"), "" ); \ THROW_ERROR( ErrorType_File_IO, tmp_err ); \ } \ } void (*TEXTVIEW_FUNCTION)(const utf8_string &string) = 0; void (*QUIT_FUNCTION)(void) = 0; void term_quit(void); void term_showtext(const utf8_string &string); Format format; math::CodeBlock calc_function; keyfile setup_file; utf8_string language_filename("English"); #ifndef NO_GTK utf8_string default_start_window(""); #include #include "picture2gtk.h" #include "ump_advancedwin.h" #include "ump_editor.h" #include "ump_simplewin.h" #include "ump_picturewin.h" #include "ump_graphwin.h" #include "ump_prefwin.h" #include "matrix_editor.h" void build_std_names(void); uint32 open_windows = 0; const char *dialog_title_save_as, *dialog_title_open_file; const char *menu_file, *menu_file_new, *menu_file_open, *menu_file_save, *menu_file_save_as, *menu_file_close, *menu_file_quit; const char *menu_tools, *menu_tools_advanced, *menu_tools_editor, *menu_tools_simple, *menu_tools_graphtool, *menu_tools_matrixedit; const char *menu_about, *menu_pref; const char *button_ok, *button_cancel, *button_close; const char *main_file_load, *main_file_clear; const char *main_options, *main_opt_radian, *main_opt_degree; const char *edit_edit, *edit_edit_cut, *edit_edit_copy, *edit_edit_paste, *edit_edit_delete, *edit_edit_select_all; const char *filter_ump_files, *filter_all_files, *filter_picture_files, *filter_pcx_files, *filter_ppm_files; uint32 start_window = ADVANCED_WIN; #endif void save_keyfile(void); void read_keyfile(void); void text_setup_functions( void ); void degfix_needs_updating( math::Variable *var ); void show_versions(void); int main(int argc, char **argv) { math::intern_format = &format; translation.replace_escape_sequences = true; try { math::init(); { Variable tmpvar; tmpvar.set_complex( Complex( 0 ) ); tmpvar.set_name( "ans" ); math::global_varlist.create(tmpvar, false, false, true); } read_keyfile(); if( math::autoload_directories.get_size() == 0 ) { utf8_string dir( DATA_DIR "/ump-files" ); math::autoload_directories.append( dir ); } } catch(error_obj error) { fprintf( stderr, "\n\nFATAL ERROR: %s\n\n", error.msg ); exit(-1); } if(argv[1] != 0) { if(strcmp(argv[1],"--version") == 0) { show_versions(); exit(0); } else if(strcmp(argv[1],"--text") == 0) goto terminal_only; #ifndef NO_GTK else if(strcmp(argv[1],"--simple") == 0) start_window = SIMPLE_WIN; else if(strcmp(argv[1],"--advanced") == 0) start_window = ADVANCED_WIN; else if(strcmp(argv[1],"--editor") == 0) start_window = EDITOR_WIN; else if(strcmp(argv[1],"--graphtool") == 0) start_window = GRAPHTOOL_WIN; else if(strcmp(argv[1],"--matrix-editor") == 0) start_window = MATRIX_EDITOR_WIN; #endif else { // let's check if it's a ump-filename char *name_ext = strstr( argv[1], ".ump" ); if( name_ext != 0 ) { text_setup_functions(); // load add on functions math::CodeBlock code; utf8_string str; Variable res; try { code.set_code_from_file( argv[1] ); } catch(error_obj error) { (*TEXTVIEW_FUNCTION)(error.msg); (*TEXTVIEW_FUNCTION)("\n"); exit( -1 ); } // Let's get the name of the funtion to call { int start, stop; char tmp[2]; tmp[1] = '\0'; stop = strlen(argv[1]) - 4; for( start = stop; start != 0 ; start-- ) { if( argv[1][start] == '/' ) { start++; break; } if( start == 0 ) break; } for( ; start set_change_func( degfix_needs_updating ); } } catch(error_obj error) { fprintf( stderr, "\n\nFATAL ERROR: %s\n\n", error.msg ); exit(-1); } switch(start_window) { case EDITOR_WIN: editor_showwin(); break; case SIMPLE_WIN: simplewin_show(); break; case GRAPHTOOL_WIN: graphwin_show(); break; case MATRIX_EDITOR_WIN: matrix_editor_show(); break; case ADVANCED_WIN: default: advancedwin_show(); } gtk_main(); } else // gtk failed to start { #endif terminal_only: char line[2000]; #ifndef NO_GTK setlocale( LC_NUMERIC, "C" ); // gtk+ changes this...which I don't want #endif _3d_viewer_init(); text_setup_functions(); { math::Variable tmpvar; tmpvar.set_complex( Complex( 1 ) ); tmpvar.set_name( "degfix" ); math::global_varlist.create( tmpvar , false,false,false); // default is radians tmpvar.set_name( "radian" ); math::global_varlist.create( tmpvar , true,false,false); // constant tmpvar.set_complex( Complex( PI/180.0 ) ); tmpvar.set_name( "degree" ); math::global_varlist.create( tmpvar , true,false,false); // constant math::global_varlist.get_pointer_rw( math::global_varlist.get_id( "degfix" ) )-> set_change_func( degfix_needs_updating ); } printf( "\n" PRG_NAME " " PRG_VERSION "\n\n Copyright (c) " PRG_DATE " Mattias Hultgren\n%s", get_start_message() ); { utf8_string output; for(;;) { printf( "\n> " ); fgets( line, 2000, stdin ); for( int i=0; ; i++ ) { if( line[i] == 0 ) { if( i >= 2 ) { if( line[i-2] == '\n' || line[i-2] == '\r' ) line[i-2] = 0; } if( i >= 1 ) { if( line[i-1] == '\n' || line[i-1] == '\r' ) line[i-1] = 0; } break; } } { int i; for( i=0; line[i] != '\0'; i++ ) { if( line[i] != ' ' && line[i] != '\t' ) break; } if( line[i] == '\0' ) continue; } try { Variable *varpointer; varpointer = math::global_varlist.get_pointer_rw( math::global_varlist.get_id("ans") ); calc_function.set_code( line ); calc_function.calc( varpointer ); calc_function.clear(); if( !varpointer->is_void() ) { output = ""; varpointer->append_to_string( output, format ); printf( "%s\n", output.c_str() ); } } catch( error_obj error ) { printf( "\n %s\n\n", error.msg ); } } } #ifndef NO_GTK } #endif { Variable *tmpvar; tmpvar = math::global_varlist.get_pointer_rw( math::global_varlist.get_id( "degfix" ) ); tmpvar->set_change_func( 0 ); } return 0; } void degfix_needs_updating( math::Variable *var ) { math::degfix = *( math::global_varlist.get_pointer_rw( math::global_varlist.get_id( "degfix" ) )->get_complex() ); #ifndef NO_GTK degfix_changed(); #endif } void text_setup_functions( void ) { TEXTVIEW_FUNCTION = term_showtext; QUIT_FUNCTION = term_quit; try { math::add_function( "quit", addon_quit, false, false); math::add_function( "exit", addon_quit, false, false); math::add_function( "view", addon_view, false, true); math::add_function( "viewall", addon_viewall, false, false); math::add_function( "print", addon_print, false, true); math::add_function( "message", addon_text_message, false, true); math::add_function( "menu", addon_text_menu, false, true); math::add_function( "input", addon_text_input, false, true); math::add_function( "load", addon_load, false, true); math::add_function( "load_picture", addon_load_picture, false, true); math::add_function( "save_picture", addon_save_picture, false, true); } catch( error_obj error ) { fprintf( stderr, "\n\nFATAL ERROR: %s\n\n", error.msg ); exit(-1); } } const char * get_start_message(void) { const char *trans; if( (trans = translation.get_key_c_str("START_MESSAGE")) == 0 ) trans = " Ump comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.\n" " This is free software, and you are welcome to redistribute it\n" " under certain conditions; see LICENSE for details.\n\n"; return trans; } void show_versions(void) { printf( "\n\n" PRG_NAME " " PRG_VERSION " " PRG_DATE "\nCompiled " __DATE__ " " __TIME__ "\nwith " FLAGS "\n" ); printf( "\nutf8_string.h %-3s " UTF8_STRING_H_DATE, UTF8_STRING_H_VERSION ); printf( "\ninteger.h %-3s " INTEGER_H_DATE, INTEGER_H_VERSION ); printf( "\nreal.h %-3s " REAL_H_DATE, REAL_H_VERSION ); printf( "\ncomplex.h %-3s " COMPLEX_H_DATE, COMPLEX_H_VERSION ); printf( "\nmatrix.h %-3s " MATRIX_H_DATE, MATRIX_H_VERSION ); printf( "\nmath2.h %-3s " MATH2_H_DATE, MATH2_H_VERSION ); printf( "\nvartypes.h %-3s " VARTYPES_H_DATE, VARTYPES_H_VERSION ); printf( "\npicture.h %-3s " PICTURE_H_DATE, PICTURE_H_VERSION ); printf( "\nvector.h %-3s " VECTOR_H_DATE, VECTOR_H_VERSION ); #ifndef NO_GTK printf( "\npicture2gtk.h %-3s " PICTURE2GTK_H_DATE "\n\n", PICTURE2GTK_H_VERSION ); #else printf( "\n\n" ); #endif } void save_keyfile(void) { try { char str[100]; setup_file.set_key( "PROGRAM", PRG_NAME ); setup_file.set_key( "VERSION", PRG_VERSION ); snprintf( str, 100, "%lu", format.get_max_decimals() ); setup_file.set_key( "FORMAT_MAX_DECIMALS", str ); if(strlen(language_filename.c_str()) > 0) setup_file.set_key( "LANGUAGE", language_filename ); else setup_file.remove_key( "LANGUAGE" ); #ifndef NO_GTK if(strlen(default_start_window.c_str()) > 0) setup_file.set_key( "DEFAULT_START_WINDOW", default_start_window ); else setup_file.remove_key( "DEFAULT_START_WINDOW" ); #endif setup_file.set_key( "FORMAT_SHOW_TRAILING", (format.show_trailingzeros) ? "True" : "False" ); switch( FormatType( format.get_type() ) ) { case FormatType_Normal: setup_file.set_key( "FORMAT_TYPE", "Normal" ); break; case FormatType_Mixed: setup_file.set_key( "FORMAT_TYPE", "Mixed" ); break; case FormatType_Science: setup_file.set_key( "FORMAT_TYPE", "Science" ); break; } switch( FormatFractionType( format.get_fraction_type() ) ) { case FormatFractionType_Fractions: setup_file.set_key( "FORMAT_FRACTION_TYPE", "Fractions" ); break; case FormatFractionType_Integer_plus_fraction: setup_file.set_key( "FORMAT_FRACTION_TYPE", "Integer + fraction" ); break; case FormatFractionType_Decimals: setup_file.set_key( "FORMAT_FRACTION_TYPE", "Decimals" ); break; } { utf8_string base("AUTOLOAD_PATH_"), keyname; const utf8_string *tmp; char number[10]; for( int i=0;; i++ ) // removes all old AUTOLOAD_PATH's { snprintf( number, 10, "%ld", i ); keyname = base; keyname.append( number ); tmp = setup_file.get_key( keyname ); if( tmp == 0 ) break; setup_file.remove_key( keyname ); } for( int i=0; i &colors) throw(error_obj) { int i; picture_h::colorrgb color; colors.clear(); for( i=0;; i += 6 ) { if( i == 0 ) hexstring_to_colorrgb( str, color ); else { if( str[i] == ' ' ) { i++; try{ hexstring_to_colorrgb( &str[i], color ); } catch( ... ) { return; } } else if( str[i] == '\0' ) return; else THROW_ERROR( ErrorType_General, _("Unknown format") ); } colors.append( color ); } } void read_keyfile(void) { try { char filename[100],tmpstr[50]; const char *tmp; const utf8_string *str; bool std_settings = true; setup_file.replace_escape_sequences = true; try{ setup_file.read( "/usr/local/etc/ump.conf" ); } catch(...) { std_settings = false; } snprintf(filename,100,"%s/.ump",getenv("HOME")); try{ setup_file.read( filename ); } catch(...) { if( !std_settings ) return; } { utf8_string base("AUTOLOAD_PATH_"), keyname; const utf8_string *tmp; for( int i=0;; i++ ) // loads all AUTOLOAD_PATH's { snprintf( tmpstr, 50, "%ld", i ); keyname = base; keyname.append( tmpstr ); tmp = setup_file.get_key( keyname ); if( tmp == 0 ) break; math::autoload_directories.append( *tmp ); } } #ifndef NO_GTK { utf8_string base("HISTORY_LIST_"), keyname; const utf8_string *tmp; for( int i=0;; i++ ) // loads whole HISTORY_LIST { snprintf( tmpstr, 50, "%ld", i ); keyname = base; keyname.append( tmpstr ); tmp = setup_file.get_key( keyname ); if( tmp == 0 ) break; advanced_history.append( *tmp ); } } if((str = setup_file.get_key("DEFAULT_START_WINDOW")) != 0) { if( *str == "Advanced" ) { default_start_window = *str; start_window = ADVANCED_WIN; } else if( *str == "Simple" ) { default_start_window = *str; start_window = SIMPLE_WIN; } else if( *str == "Editor" ) { default_start_window = *str; start_window = EDITOR_WIN; } else if( *str == "Graphtool" ) { default_start_window = *str; start_window = GRAPHTOOL_WIN; } else if( *str == "MatrixEditor" ) { default_start_window = *str; start_window = MATRIX_EDITOR_WIN; } else printf("\n\nUnknown DEFAULT_START_WINDOW in '%s'\n\n", filename); } if( (tmp = setup_file.get_key_c_str("SNAP_SIZE")) != 0 ) { uint32 tmp_int; if(sscanf( tmp, "%lu", &tmp_int ) == 0) { char tmp_err[ERROR_OBJ_MSG_LEN]; snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Invalid format in file %s"), filename ); THROW_ERROR( ErrorType_File_IO, tmp_err ); } if(tmp_int > 100) { char tmp_err[ERROR_OBJ_MSG_LEN]; snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Invalid format in file %s"), filename ); THROW_ERROR( ErrorType_File_IO, tmp_err ); } SNAP_SIZE = tmp_int; } #endif if((tmp = setup_file.get_key_c_str("LANGUAGE")) != 0) update_translation( tmp ); if((str = setup_file.get_key("FORMAT_TYPE")) != 0) { if(*str == "Normal") format.set_type( FormatType_Normal ); else if(*str == "Mixed") format.set_type( FormatType_Mixed ); else if(*str == "Science") format.set_type( FormatType_Science ); else { char tmp_err[ERROR_OBJ_MSG_LEN]; snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Invalid format in file %s"), filename ); THROW_ERROR( ErrorType_File_IO, tmp_err ); } } if((str = setup_file.get_key("FORMAT_FRACTION_TYPE")) != 0) { if(*str == "Fractions") format.set_fraction_type( FormatFractionType_Fractions ); else if(*str == "Integer + fraction") format.set_fraction_type( FormatFractionType_Integer_plus_fraction ); else if(*str == "Decimals") format.set_fraction_type( FormatFractionType_Decimals ); else { char tmp_err[ERROR_OBJ_MSG_LEN]; snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Invalid format in file %s"), filename ); THROW_ERROR( ErrorType_File_IO, tmp_err ); } } if((tmp = setup_file.get_key_c_str("FORMAT_MAX_DECIMALS")) != 0) { uint32 tmp_int; if(sscanf(tmp,"%lu",&tmp_int) == 0) { char tmp_err[ERROR_OBJ_MSG_LEN]; snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Invalid format in file %s"), filename ); THROW_ERROR( ErrorType_File_IO, tmp_err ); } if(tmp_int > 50) { char tmp_err[ERROR_OBJ_MSG_LEN]; snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Invalid format in file %s"), filename ); THROW_ERROR( ErrorType_File_IO, tmp_err ); } format.set_max_decimals( tmp_int ); } GET_BOOLEAN_KEY( "FORMAT_SHOW_TRAILING", format.show_trailingzeros ); } catch(error_obj error) { printf("\n\nKey file error: %s\n\n",error.msg); } #ifndef NO_GTK build_std_names(); #endif } void term_quit(void) { save_keyfile(); exit(0); } void term_showtext(const utf8_string &string) { printf( "%s", string.c_str() ); } #ifndef NO_GTK void build_std_names(void) { dialog_title_open_file = _("Open file..."); dialog_title_save_as = _("Save as..."); menu_file = _("_File"); menu_file_new = _("_New"); menu_file_open = _("_Open..."); menu_file_save = _("_Save"); menu_file_save_as = _("Save _as..."); menu_file_close = _("_Close"); menu_file_quit = _("_Quit"); menu_tools = _("_Tools"); menu_tools_simple = _("Simple _calculator"); menu_tools_advanced = _("_Advanced calculator"); menu_tools_editor = _("Ump _editor"); menu_tools_graphtool = _("_Graph tools"); menu_tools_matrixedit = _("_Matrix editor"); menu_about = _("_About"); menu_pref = _("Pr_eferences"); button_ok = _("_OK"); button_cancel = _("_Cancel"); button_close = menu_file_close; edit_edit = _("_Edit"); edit_edit_cut = _("Cu_t"); edit_edit_copy = _("_Copy"); edit_edit_paste = _("_Paste"); edit_edit_delete = _("_Delete"); edit_edit_select_all = _("Select _All"); filter_ump_files = _("UMP files"); filter_all_files = _("All files"); filter_picture_files = _("Picture files"); filter_ppm_files = _("PPM files"); filter_pcx_files = _("PCX files"); } void UMP_gtk_quit(void) { graphwin_close(); save_keyfile(); if((open_windows & EDITOR_WIN) == EDITOR_WIN) editor_close(); // gets the user a chance of saving unsaved work try{ math::global_varlist.get_pointer_rw( math::global_varlist.get_id( "degfix" ) )->set_change_func( 0 ); } catch(...) { } gtk_main_quit(); } #endif void update_translation( utf8_string translation_filename, bool window_updating ) { translation.reset(); if( translation_filename == "English" || translation_filename == "" ) translation_filename = "English"; else if(translation_filename == "Svenska") { try{ translation.read_intern( translation_svenska ); } catch(error_obj error){ printf("\n\nError while loading translation 'Svenska' '%s'\n\n", error.msg); } } else { try{ translation.read( translation_filename.c_str() ); } catch(error_obj error){ printf("\n\nError while loading translation file '%s' '%s'\n\n", translation_filename.c_str(), error.msg); } } #ifndef NO_GTK build_std_names(); if(window_updating) { language_filename = translation_filename; simplewin_translate(); advancedwin_translate(); editorwin_translate(); picturewin_translate(); graphwin_translate(); matrix_editor_translate(); } #endif }