Index: dataobj/height_map_loader.cc =================================================================== --- dataobj/height_map_loader.cc (revisjon 8169) +++ dataobj/height_map_loader.cc (arbeidskopi) @@ -6,6 +6,7 @@ #include "environment.h" #include "height_map_loader.h" +#include "../simsys.h" #include "../simio.h" @@ -18,7 +19,7 @@ // read height data from bmp or ppm files bool height_map_loader_t::get_height_data_from_file( const char *filename, sint8 groundwater, sint8 *&hfield, sint16 &ww, sint16 &hh, bool update_only_values ) { - if (FILE* const file = fopen(filename, "rb")) { + if (FILE* const file = dr_fopen(filename, "rb")) { char id[3]; // parsing the header of this mixed file format is nottrivial ... id[0] = fgetc(file); Index: dataobj/loadsave.cc =================================================================== --- dataobj/loadsave.cc (revisjon 8169) +++ dataobj/loadsave.cc (arbeidskopi) @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "../simsys.h" #include "../simtypes.h" @@ -16,9 +18,6 @@ #include "../utils/simstring.h" -#include -#include - #define INVALID_RDWR_ID (-1) //#undef MULTI_THREAD @@ -268,10 +267,9 @@ { close(); - const char *filename = dr_utf8_to_system_filename( filename_utf8 ); version = 0; mode = zipped; - fd->fp = fopen( filename, "rb"); + fd->fp = dr_fopen(filename_utf8, "rb"); if( fd->fp==NULL ) { // most likely not existing return false; @@ -311,7 +309,7 @@ if( mode!=bzip2 ) { fclose(fd->fp); // and now with zlib ... - fd->gzfp = gzopen(filename, "rb"); + fd->gzfp = dr_gzopen(filename_utf8, "rb"); if(fd->gzfp==NULL) { return false; } @@ -372,7 +370,7 @@ if(*pak_extension==0) { strcpy( pak_extension, "(unknown)" ); } - this->filename = filename; + this->filename = filename_utf8; return true; } @@ -382,18 +380,17 @@ mode = m; close(); - const char *filename = dr_utf8_to_system_filename( filename_utf8, true ); if( is_zipped() ) { // using zlib - fd->gzfp = gzopen(filename, "wb"); + fd->gzfp = dr_gzopen(filename_utf8, "wb"); } else if( mode==binary ) { // no compression - fd->fp = fopen(filename, "wb"); + fd->fp = dr_fopen(filename_utf8, "wb"); } else if( is_bzip2() ) { // XML or bzip ... - fd->fp = fopen(filename, "wb"); + fd->fp = dr_fopen(filename_utf8, "wb"); // the additional magic for bzip2 fd->bse = BZ_OK+1; fd->bzfp = NULL; @@ -407,7 +404,7 @@ else { // uncompressed xml should be here ... assert( mode==xml ); - fd->fp = fopen(filename, "wb"); + fd->fp = dr_fopen(filename_utf8, "wb"); } // check whether we could open the file @@ -452,7 +449,7 @@ ident = 1; } - this->filename = filename; + this->filename = filename_utf8; return true; } Index: dataobj/scenario.cc =================================================================== --- dataobj/scenario.cc (revisjon 8169) +++ dataobj/scenario.cc (arbeidskopi) @@ -1,5 +1,6 @@ #include "../simconst.h" #include "../simtypes.h" +#include "../simsys.h" #include "../simdebug.h" #include "../player/simplay.h" @@ -706,14 +707,14 @@ return cached; } // not cached: try to read file - FILE* file = fopen(wanted_file.c_str(), "rb"); + FILE* file = dr_fopen(wanted_file.c_str(), "rb"); if (file == NULL) { // try English - file = fopen((path + "en/" + filename).c_str(), "rb"); + file = dr_fopen((path + "en/" + filename).c_str(), "rb"); } if (file == NULL) { // try scenario directory - file = fopen((path + filename).c_str(), "rb"); + file = dr_fopen((path + filename).c_str(), "rb"); } plainstring text = ""; Index: dataobj/tabfile.cc =================================================================== --- dataobj/tabfile.cc (revisjon 8169) +++ dataobj/tabfile.cc (arbeidskopi) @@ -16,6 +16,7 @@ #include "../simsys.h" #include "../simdebug.h" #include "../descriptor/image.h" +#include "../simsys.h" #include "koord.h" #include "tabfile.h" @@ -23,7 +24,7 @@ bool tabfile_t::open(const char *filename) { close(); - file = fopen(filename, "r"); + file = dr_fopen(filename, "r"); return file != NULL; } Index: dataobj/translator.cc =================================================================== --- dataobj/translator.cc (revisjon 8169) +++ dataobj/translator.cc (arbeidskopi) @@ -220,13 +220,13 @@ string local_file_name(env_t::user_dir); local_file_name = local_file_name + "addons/" + pakset_path + "text/" + fileprefix + langs[lang].iso_base + ".txt"; DBG_DEBUG("translator::load_custom_list()", "try to read city name list from '%s'", local_file_name.c_str()); - file = fopen(local_file_name.c_str(), "rb"); + file = dr_fopen(local_file_name.c_str(), "rb"); } // not found => try user location if( file==NULL ) { string local_file_name(env_t::user_dir); local_file_name = local_file_name + fileprefix + langs[lang].iso_base + ".txt"; - file = fopen(local_file_name.c_str(), "rb"); + file = dr_fopen(local_file_name.c_str(), "rb"); DBG_DEBUG("translator::load_custom_list()", "try to read city name list from '%s'", local_file_name.c_str()); } // not found => try pak location @@ -234,7 +234,7 @@ string local_file_name(env_t::program_dir); local_file_name = local_file_name + pakset_path + "text/" + fileprefix + langs[lang].iso_base + ".txt"; DBG_DEBUG("translator::load_custom_list()", "try to read city name list from '%s'", local_file_name.c_str()); - file = fopen(local_file_name.c_str(), "rb"); + file = dr_fopen(local_file_name.c_str(), "rb"); } // not found => try global translations if( file==NULL ) { @@ -241,7 +241,7 @@ string local_file_name(env_t::program_dir); local_file_name = local_file_name + "text/" + fileprefix + langs[lang].iso_base + ".txt"; DBG_DEBUG("translator::load_custom_list()", "try to read city name list from '%s'", local_file_name.c_str()); - file = fopen(local_file_name.c_str(), "rb"); + file = dr_fopen(local_file_name.c_str(), "rb"); } fflush(NULL); @@ -407,7 +407,7 @@ lang_info* lang = get_lang_by_iso(iso.c_str()); if (lang != NULL) { DBG_MESSAGE("translator::load_files_from_folder()", "loading %s translations from %s for language %s", what, fileName.c_str(), lang->iso_base); - if (FILE* const file = fopen(fileName.c_str(), "rb")) { + if (FILE* const file = dr_fopen(fileName.c_str(), "rb")) { bool file_is_utf = is_unicode_file(file); load_language_file_body(file, &lang->texts, true, file_is_utf, lang->is_latin2_based ); fclose(file); @@ -425,7 +425,7 @@ bool translator::load(const string &path_to_pakset) { - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); tstrncpy(pakset_path, path_to_pakset.c_str(), lengthof(pakset_path)); //initialize these values to 0(ie. nothing loaded) @@ -442,7 +442,7 @@ size_t pstart = fileName.rfind('/') + 1; const string iso = fileName.substr(pstart, fileName.size() - pstart - 4); - if (FILE* const file = fopen(fileName.c_str(), "rb")) { + if (FILE* const file = dr_fopen(fileName.c_str(), "rb")) { DBG_MESSAGE("translator::load()", "base file \"%s\" - iso: \"%s\"", fileName.c_str(), iso.c_str()); load_language_iso(iso); load_language_file(file); @@ -467,12 +467,12 @@ load_files_from_folder(folderName.c_str(), "pak"); if( env_t::default_settings.get_with_private_paks() ) { - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); // now read the pakset specific text // there can be more than one file per language, provided it is name like iso_xyz.tab const string folderName("addons/" + path_to_pakset + "text/"); load_files_from_folder(folderName.c_str(), "pak addons"); - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); } //if NO languages were loaded then game cannot continue @@ -481,7 +481,7 @@ } // now we try to read the compatibility stuff - if (FILE* const file = fopen((path_to_pakset + "compat.tab").c_str(), "rb")) { + if (FILE* const file = dr_fopen((path_to_pakset + "compat.tab").c_str(), "rb")) { load_language_file_body(file, &compatibility, false, false, false ); DBG_MESSAGE("translator::load()", "pakset compatibility texts loaded."); fclose(file); @@ -492,13 +492,13 @@ // also addon compatibility ... if( env_t::default_settings.get_with_private_paks() ) { - chdir( env_t::user_dir ); - if (FILE* const file = fopen(string("addons/"+path_to_pakset + "compat.tab").c_str(), "rb")) { + dr_chdir( env_t::user_dir ); + if (FILE* const file = dr_fopen(string("addons/"+path_to_pakset + "compat.tab").c_str(), "rb")) { load_language_file_body(file, &compatibility, false, false, false ); DBG_MESSAGE("translator::load()", "pakset addon compatibility texts loaded."); fclose(file); } - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); } #if DEBUG>=4 Index: descriptor/reader/obj_reader.cc =================================================================== --- descriptor/reader/obj_reader.cc (revisjon 8169) +++ descriptor/reader/obj_reader.cc (arbeidskopi) @@ -74,7 +74,7 @@ if(name.at(name.size() - 1) != '/') { // very old style ... (I think unused by now) - if (FILE* const listfp = fopen(name.c_str(), "r")) { + if (FILE* const listfp = dr_fopen(name.c_str(), "r")) { while(!feof(listfp)) { char buf[256]; @@ -161,7 +161,7 @@ // Hajo: added trace DBG_DEBUG("obj_reader_t::read_file()", "filename='%s'", name); - if (FILE* const fp = fopen(name, "rb")) { + if (FILE* const fp = dr_fopen(name, "rb")) { sint32 n = 0; // This is the normal header reading code Index: display/font.cc =================================================================== --- display/font.cc (revisjon 8169) +++ display/font.cc (arbeidskopi) @@ -2,6 +2,7 @@ #include #include #include "../simtypes.h" +#include "../simsys.h" #include "../simmem.h" #include "../simdebug.h" #include "../macros.h" @@ -361,7 +362,7 @@ bool load_font(font_type* fnt, const char* fname) { - FILE* f = fopen(fname, "rb"); + FILE* f = dr_fopen(fname, "rb"); int c; #ifdef USE_FREETYPE @@ -400,7 +401,7 @@ } fclose(f); #ifdef DUMP_OLD_FONTS - f = fopen("C:\\prop.bdf","w"); + f = dr_fopen("C:\\prop.bdf","w"); #endif // convert to new standard font Index: gui/ai_selector.cc =================================================================== --- gui/ai_selector.cc (revisjon 8169) +++ gui/ai_selector.cc (arbeidskopi) @@ -4,6 +4,7 @@ */ #include "../simdebug.h" +#include "../simsys.h" #include "ai_selector.h" #include "messagebox.h" @@ -72,7 +73,7 @@ { char buf[1024]; sprintf( buf, "%s/ai.nut", filename ); - if (FILE* const f = fopen(buf, "r")) { + if (FILE* const f = dr_fopen(buf, "r")) { fclose(f); return true; } Index: gui/gui_theme.cc =================================================================== --- gui/gui_theme.cc (revisjon 8169) +++ gui/gui_theme.cc (arbeidskopi) @@ -386,7 +386,7 @@ else if( char *s = strrchr( pathname, '\\' ) ) { *s = 0; } - chdir( pathname ); + dr_chdir( pathname ); obj_reader_t::read_file(buttonpak.c_str()); gui_theme_t::init_gui_from_images(); free(pathname); Index: gui/help_frame.cc =================================================================== --- gui/help_frame.cc (revisjon 8169) +++ gui/help_frame.cc (arbeidskopi) @@ -191,19 +191,19 @@ { std::string file_prefix("text/"); std::string fullname = file_prefix + translator::get_lang()->iso + "/" + filename; - chdir(env_t::program_dir); + dr_chdir(env_t::program_dir); - FILE* file = fopen(fullname.c_str(), "rb"); + FILE* file = dr_fopen(fullname.c_str(), "rb"); if (!file) { //Check for the 'base' language(ie en from en_gb) - file = fopen((file_prefix + translator::get_lang()->iso_base + "/" + filename).c_str(), "rb"); + file = dr_fopen((file_prefix + translator::get_lang()->iso_base + "/" + filename).c_str(), "rb"); } if (!file) { // Hajo: check fallback english - file = fopen((file_prefix + "/en/" + filename).c_str(), "rb"); + file = dr_fopen((file_prefix + "/en/" + filename).c_str(), "rb"); } // go back to load/save dir - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); if(file) { fseek(file,0,SEEK_END); @@ -386,20 +386,20 @@ mode = native; std::string file_prefix("text/"); std::string fullname = file_prefix + translator::get_lang()->iso + "/" + filename; - chdir(env_t::program_dir); + dr_chdir(env_t::program_dir); - FILE* file = fopen(fullname.c_str(), "rb"); + FILE* file = dr_fopen(fullname.c_str(), "rb"); if( !file && strcmp(translator::get_lang()->iso,translator::get_lang()->iso_base) ) { //Check for the 'base' language(ie en from en_gb) - file = fopen( (file_prefix + translator::get_lang()->iso_base + "/" + filename).c_str(), "rb" ); + file = dr_fopen( (file_prefix + translator::get_lang()->iso_base + "/" + filename).c_str(), "rb" ); } if( !file ) { // Hajo: check fallback english - file = fopen((file_prefix + "en/" + filename).c_str(), "rb"); + file = dr_fopen((file_prefix + "en/" + filename).c_str(), "rb"); mode = english; } // go back to load/save dir - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); // success? if( !file ) { mode = missing; Index: gui/loadsave_frame.cc =================================================================== --- gui/loadsave_frame.cc (revisjon 8169) +++ gui/loadsave_frame.cc (arbeidskopi) @@ -150,7 +150,7 @@ // get file information struct stat sb; - if(stat( dr_utf8_to_system_filename(fname), &sb)!=0) { + if(dr_stat( fname, &sb)!=0) { // file not found? return date; } Index: gui/pakselector.cc =================================================================== --- gui/pakselector.cc (revisjon 8169) +++ gui/pakselector.cc (arbeidskopi) @@ -94,7 +94,7 @@ buf.printf("%s/ground.Outside.pak", filename); // if we can open the file, it is valid. - if (FILE* const f = fopen(buf, "r")) { + if (FILE* const f = dr_fopen(buf, "r")) { fclose(f); return true; } @@ -130,7 +130,7 @@ // if we can't change directory to /addon // Hide the addon button - if( chdir( path ) != 0 ) { + if( dr_chdir( path ) != 0 ) { i.del->set_visible(false); i.del->disable(); @@ -145,7 +145,7 @@ y += D_BUTTON_HEIGHT+D_FOCUS_OFFSET_V; } action_button_width += (D_H_SPACE<<1); - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); if(entries.get_count() > this->num_sections+1) { // empty path as more than one pakset is present, user has to choose Index: gui/scenario_frame.cc =================================================================== --- gui/scenario_frame.cc (revisjon 8169) +++ gui/scenario_frame.cc (arbeidskopi) @@ -5,6 +5,7 @@ * (see licence.txt) */ +#include "../simsys.h" #include "../simdebug.h" #include "scenario_frame.h" @@ -79,7 +80,7 @@ { char buf[1024]; sprintf( buf, "%s/scenario.nut", filename ); - if (FILE* const f = fopen(buf, "r")) { + if (FILE* const f = dr_fopen(buf, "r")) { fclose(f); return true; } Index: gui/settings_frame.cc =================================================================== --- gui/settings_frame.cc (revisjon 8169) +++ gui/settings_frame.cc (arbeidskopi) @@ -91,7 +91,7 @@ tabfile_t simuconf; env_t::init(); *sets = settings_t(); - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); if(simuconf.open("config/simuconf.tab")) { sint16 dummy16; string dummy_str; @@ -99,8 +99,8 @@ sets->parse_colours( simuconf ); } stadt_t::cityrules_init(env_t::objfilename); - chdir( env_t::program_dir ); - chdir( env_t::objfilename.c_str() ); + dr_chdir( env_t::program_dir ); + dr_chdir( env_t::objfilename.c_str() ); if(simuconf.open("config/simuconf.tab")) { sint16 dummy16; string dummy_str; @@ -107,7 +107,7 @@ sets->parse_simuconf( simuconf, dummy16, dummy16, dummy16, dummy_str ); sets->parse_colours( simuconf ); } - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); if(simuconf.open("simuconf.tab")) { sint16 dummy16; string dummy_str; @@ -127,7 +127,7 @@ else if( komp==&revert_to_last_save ) { // load settings of last generated map loadsave_t file; - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); if( file.rd_open("default.sve") ) { sets->rdwr(&file); file.close(); Index: gui/simwin.cc =================================================================== --- gui/simwin.cc (revisjon 8169) +++ gui/simwin.cc (arbeidskopi) @@ -1465,7 +1465,7 @@ } // save and reload all windows (currently only used when a new theme is applied) if( ev->ev_class==EVENT_SYSTEM && ev->ev_code==SYSTEM_RELOAD_WINDOWS ) { - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); loadsave_t dlg; if( dlg.wr_open( "dlgpos.xml", loadsave_t::xml_zipped, "temp", SERVER_SAVEGAME_VER_NR ) ) { // save all Index: gui/sprachen.cc =================================================================== --- gui/sprachen.cc (revisjon 8169) +++ gui/sprachen.cc (arbeidskopi) @@ -51,8 +51,8 @@ } // load large font - chdir( env_t::program_dir ); - chdir( FONT_PATH ); + dr_chdir( env_t::program_dir ); + dr_chdir( FONT_PATH ); bool ok = false; char prop_font_file_name[1024]; tstrncpy( prop_font_file_name, prop_font_file, lengthof(prop_font_file_name) ); @@ -62,7 +62,7 @@ f = strtok( NULL, ";" ); } while( !ok && f ); - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); const char * p = translator::translate("SEP_THOUSAND"); char c = ','; @@ -117,8 +117,8 @@ cursor.y = max( seperator.get_pos().y + D_DIVIDER_HEIGHT, flags.get_pos().y + flags.get_size().h); const translator::lang_info* lang = translator::get_langs(); - chdir( env_t::program_dir ); - chdir( FONT_PATH ); + dr_chdir( env_t::program_dir ); + dr_chdir( FONT_PATH ); for (int i = 0; i < translator::get_language_count(); ++i, ++lang) { button_t* b = new button_t(); @@ -176,7 +176,7 @@ add_component( buttons[i].button ); } - chdir(env_t::user_dir); + dr_chdir(env_t::user_dir); set_windowsize( scr_size(L_DIALOG_WIDTH, D_TITLEBAR_HEIGHT + cursor.y + ((count+1)>>1)*(max(D_CHECKBOX_HEIGHT, LINESPACE)+D_V_SPACE) + D_MARGIN_BOTTOM ) ); } Index: makeobj/Makefile =================================================================== --- makeobj/Makefile (revisjon 8169) +++ makeobj/Makefile (arbeidskopi) @@ -117,6 +117,7 @@ SHARED_SOURCES += ../dataobj/freelist.cc SHARED_SOURCES += ../simdebug.cc SHARED_SOURCES += ../simmem.cc +SHARED_SOURCES += ../simio.cc SHARED_SOURCES += ../utils/simstring.cc SHARED_SOURCES += ../utils/searchfolder.cc VARIANT_SOURCES += ../dataobj/tabfile.cc Index: network/network_cmd_ingame.cc =================================================================== --- network/network_cmd_ingame.cc (revisjon 8169) +++ network/network_cmd_ingame.cc (arbeidskopi) @@ -87,7 +87,7 @@ gi.rdwr( &fd ); fd.close(); // get gameinfo size - FILE *fh = fopen( "serverinfo.sve", "rb" ); + FILE *fh = dr_fopen( "serverinfo.sve", "rb" ); fseek( fh, 0, SEEK_END ); nwgi.len = ftell( fh ); rewind( fh ); @@ -682,7 +682,7 @@ } // transfer game, all clients need to sync (save, reload, and pause) // now save and send - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); if( !env_t::server ) { char fn[256]; sprintf( fn, "client%i-network.sve", network_get_client_id() ); Index: network/network_file_transfer.cc =================================================================== --- network/network_file_transfer.cc (revisjon 8169) +++ network/network_file_transfer.cc (arbeidskopi) @@ -1,4 +1,5 @@ #include "network_file_transfer.h" +#include "../simsys.h" #include "../simdebug.h" #include "../simloadingscreen.h" @@ -30,7 +31,7 @@ // good place to show a progress bar char rbuf[4096]; sint32 length_read = 0; - if (FILE* const f = fopen(save_as, "wb")) { + if (FILE* const f = dr_fopen(save_as, "wb")) { while(length_read < length) { if( timeout > 0 ) { /** 10s for 4096 bytes: @@ -242,7 +243,7 @@ const char *network_send_file( uint32 client_id, const char *filename ) { - FILE *fp = fopen(filename,"rb"); + FILE *fp = dr_fopen(filename,"rb"); if (fp == NULL) { dbg->warning("network_send_file", "could not open file %s", filename); return "Could not open file"; Index: siminteraction.cc =================================================================== --- siminteraction.cc (revisjon 8169) +++ siminteraction.cc (arbeidskopi) @@ -309,7 +309,7 @@ env_t::server_save_game_on_quit = false; // following code quite similar to nwc_sync_t::do_coomand - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); // first save password hashes char fn[256]; Index: simio.cc =================================================================== --- simio.cc (revisjon 8169) +++ simio.cc (arbeidskopi) @@ -4,7 +4,28 @@ */ #include +#include +#include +#ifdef _WIN32 +# include +# include +# include +# include +# if !defined(__CYGWIN__) +# include +# else +# include +# endif +# undef PATH_MAX +# define PATH_MAX MAX_PATH +#else +# include +# if !defined __AMIGA__ && !defined __BEOS__ +# include +# endif +#endif + char *read_line(char *s, int size, FILE *file) { char *r; @@ -15,3 +36,74 @@ return r; } + +#if defined(_WIN32) && !defined(__CYGWIN__) +const WCHAR *dr_utf8_to_wide_filename(const char *path) { + static WCHAR pathW[MAX_PATH]; + MultiByteToWideChar( CP_UTF8, 0, path, -1, pathW, sizeof(pathW) ); + return pathW; +} +#endif + +char *dr_getcwd(char *buf, int size) { +#ifdef _WIN32 + WCHAR *bufW = new WCHAR[size]; + WCHAR *buf2 = _wgetcwd(bufW, size); + if( !buf2 ) { + delete[] bufW; + return NULL; + } + int ret = WideCharToMultiByte(CP_UTF8, 0, bufW, -1, buf, size, NULL, NULL); + delete[] bufW; + if( ret <= 0 ) { + return NULL; + } + return buf; +#else + return getcwd(buf, size); +#endif +} + + +int dr_stat(const char *filename, struct stat *stat_struct) { +#ifdef _WIN32 + return _wstat(dr_utf8_to_wide_filename(filename), (struct _stat*)stat_struct); +#else + return stat(filename, stat_struct); +#endif +} + + +int dr_chdir(const char *dirname) { +#ifdef _WIN32 + return _wchdir(dr_utf8_to_wide_filename(dirname)); +#else + return chdir(dirname); +#endif +} + + +FILE *dr_fopen(const char *filename, const char *mode) { +#ifdef _WIN32 + static const size_t MODE_SIZE = 128; // This should be enough for any reasonable mode Simutrans uses + WCHAR wmode[MODE_SIZE]; + WCHAR wfilename[FILENAME_MAX]; + + MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, MODE_SIZE); + MultiByteToWideChar(CP_UTF8, 0, filename, -1, wfilename, FILENAME_MAX); + + return _wfopen(wfilename, wmode); +#else + // Assume fopen operates on UTF-8 + return fopen(filename, mode); +#endif +} + +gzFile dr_gzopen(const char *filename, const char *mode) { +#ifdef _WIN32 + return gzopen_w(dr_utf8_to_wide_filename(filename), mode); +#else + // Assume fopen operates on UTF-8 + return gzopen(filename, mode); +#endif +} Index: simmain.cc =================================================================== --- simmain.cc (revisjon 8169) +++ simmain.cc (arbeidskopi) @@ -479,7 +479,7 @@ #endif { // save the current directories - getcwd(env_t::program_dir, lengthof(env_t::program_dir)); + dr_getcwd(env_t::program_dir, lengthof(env_t::program_dir)); strcat( env_t::program_dir, path_sep ); } else { @@ -508,7 +508,7 @@ } #endif - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); } printf("Use work dir %s\n", env_t::program_dir); @@ -544,7 +544,7 @@ // save in program directory env_t::user_dir = env_t::program_dir; } - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); #ifdef REVISION @@ -586,7 +586,7 @@ } } else if (gimme_arg(argc, argv, "-log", 0)) { - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); char temp_log_name[256]; const char *logname = "simu.log"; if( gimme_arg(argc, argv, "-server", 0) ) { @@ -626,7 +626,7 @@ } // continue parsing ... - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); if( found_simuconf ) { if(simuconf.open(path_to_simuconf)) { printf("parse_simuconf() at config/simuconf.tab: "); @@ -808,36 +808,36 @@ // prepare skins first bool themes_ok = false; if( const char *themestr = gimme_arg(argc, argv, "-theme", 1) ) { - chdir( env_t::user_dir ); - chdir( "themes" ); + dr_chdir( env_t::user_dir ); + dr_chdir( "themes" ); themes_ok = gui_theme_t::themes_init(themestr); if( !themes_ok ) { - chdir( env_t::program_dir ); - chdir( "themes" ); + dr_chdir( env_t::program_dir ); + dr_chdir( "themes" ); themes_ok = gui_theme_t::themes_init(themestr); } } // next try the last used theme if( !themes_ok && env_t::default_theme.c_str()!=NULL ) { - chdir( env_t::user_dir ); - chdir( "themes" ); + dr_chdir( env_t::user_dir ); + dr_chdir( "themes" ); themes_ok = gui_theme_t::themes_init( env_t::default_theme ); if( !themes_ok ) { - chdir( env_t::program_dir ); - chdir( "themes" ); + dr_chdir( env_t::program_dir ); + dr_chdir( "themes" ); themes_ok = gui_theme_t::themes_init( env_t::default_theme ); } } // specified themes not found => try default themes if( !themes_ok ) { - chdir( env_t::program_dir ); - chdir( "themes" ); + dr_chdir( env_t::program_dir ); + dr_chdir( "themes" ); themes_ok = gui_theme_t::themes_init("themes.tab"); } if( !themes_ok ) { dbg->fatal( "simmain()", "No GUI themes found! Please re-install!" ); } - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); // The loading screen needs to be initialized show_pointer(1); @@ -875,7 +875,7 @@ buf.append( env_t::objfilename.c_str() ); buf.append("ground.Outside.pak"); - FILE* const f = fopen(buf, "r"); + FILE* const f = dr_fopen(buf, "r"); if( !f ) { dr_fatal_notify("*** No pak set found ***\n\nMost likely, you have no pak set installed.\nPlease download and install a pak set (graphics).\n"); simgraph_exit(); @@ -1005,7 +1005,7 @@ // Hajo: simgraph init loads default fonts, now we need to load // the real fonts for the current language sprachengui_t::init_font_from_lang(); - chdir(env_t::program_dir); + dr_chdir(env_t::program_dir); dbg->important("Reading city configuration ..."); stadt_t::cityrules_init(env_t::objfilename); @@ -1021,12 +1021,12 @@ obj_reader_t::load(env_t::objfilename.c_str(), translator::translate("Loading paks ...") ); if( env_t::default_settings.get_with_private_paks() ) { // try to read addons from private directory - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); if(!obj_reader_t::load(("addons/" + env_t::objfilename).c_str(), translator::translate("Loading addon paks ..."))) { fprintf(stderr, "reading addon object data failed (disabling).\n"); env_t::default_settings.set_with_private_paks( false ); } - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); } obj_reader_t::finish_loading(); pakset_info_t::calculate_checksum(); @@ -1049,7 +1049,7 @@ if( gimme_arg(argc, argv, "-load", 0) != NULL ) { cbuffer_t buf; - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); /** * Added automatic adding of extension */ @@ -1067,7 +1067,7 @@ // recover last server game if( new_world && env_t::server ) { - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); loadsave_t file; static char servername[128]; sprintf( servername, "server%d-network.sve", env_t::server ); @@ -1092,7 +1092,7 @@ pak_name.append( env_t::objfilename ); pak_name.erase( pak_name.length()-1 ); pak_name.append( ".sve" ); - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); unlink( "temp-load.sve" ); if( rename( pak_name.c_str(), "temp-load.sve" )==0 ) { loadgame = "temp-load.sve"; @@ -1103,11 +1103,11 @@ // still nothing to be loaded => search for demo games if( new_world ) { - chdir( env_t::program_dir ); + dr_chdir( env_t::program_dir ); char buffer[256]; sprintf(buffer, "%s%sdemo.sve", (const char*)env_t::program_dir, env_t::objfilename.c_str()); // access did not work! - if (FILE* const f = fopen(buffer, "rb")) { + if (FILE* const f = dr_fopen(buffer, "rb")) { // there is a demo game to load loadgame = buffer; fclose(f); @@ -1130,7 +1130,7 @@ } // now always writing in user dir (which points the the program dir in multiuser mode) - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); // init midi before loading sounds if( dr_init_midi() ) { @@ -1199,7 +1199,7 @@ env_t::server_admin_pw = ref_str; } - chdir(env_t::user_dir); + dr_chdir(env_t::user_dir); // reset random counter to true randomness setsimrand(dr_time(), dr_time()); @@ -1353,7 +1353,7 @@ intr_disable(); // save setting ... - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); if( file.wr_open("settings.xml",loadsave_t::xml,"settings only/",SAVEGAME_VER_NR) ) { env_t::rdwr(&file); env_t::default_settings.rdwr(&file); Index: simsound.cc =================================================================== --- simsound.cc (revisjon 8169) +++ simsound.cc (arbeidskopi) @@ -163,7 +163,7 @@ char full_path[1024]; sprintf( full_path, "%smusic/music.tab", directory ); - if( FILE* const file = fopen(full_path, "rb") ) { + if( FILE* const file = dr_fopen(full_path, "rb") ) { while(!feof(file)) { char buf[256]; char title[256]; Index: simsys.cc =================================================================== --- simsys.cc (revisjon 8169) +++ simsys.cc (arbeidskopi) @@ -26,6 +26,7 @@ # include # if !defined(__CYGWIN__) # include + extern const WCHAR *dr_utf8_to_wide_filename(const char *path); # else # include # endif @@ -66,9 +67,7 @@ void dr_mkdir(char const* const path) { #if defined(_WIN32) && !defined(__CYGWIN__) - WCHAR pathW[MAX_PATH]; - MultiByteToWideChar( CP_UTF8, 0, path, -1, pathW, sizeof(pathW) ); - CreateDirectoryW( pathW, NULL ); + CreateDirectoryW( dr_utf8_to_wide_filename(path), NULL ); #else mkdir(path, 0777); #endif @@ -79,16 +78,16 @@ bool dr_movetotrash(const char *path) { // We just have a Windows implementation so far #ifdef _WIN32 - SHFILEOPSTRUCTA FileOp; + SHFILEOPSTRUCTW FileOp; int len = strlen(path); - char * wfilename = new char [len+2]; + WCHAR * wfilename = new WCHAR [len+2]; - strcpy(wfilename, path); + int wlen = MultiByteToWideChar( CP_UTF8, 0, path, -1, wfilename, len+1 ); // Double \0 terminated string as required by the function. - wfilename[len+1]='\0'; + wfilename[wlen+1]='\0'; ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCTA)); @@ -98,7 +97,7 @@ FileOp.pFrom = wfilename; FileOp.pTo = NULL; - int successful = SHFileOperationA(&FileOp); + int successful = SHFileOperationW(&FileOp); delete wfilename; @@ -109,48 +108,6 @@ #endif -// accecpt whatever encoding your filename has (assuming ANSI for windows) and returns the Unicode name -const char *dr_system_filename_to_uft8( const char *path_in ) -{ -#if defined _WIN32 - WCHAR bufferW[1024], bufferW2[1024]; - static char buffer[1024*3]; - MultiByteToWideChar( CP_UTF8, 0, path_in, -1, bufferW, lengthof(bufferW) ); - GetLongPathNameW( bufferW, bufferW2, lengthof(bufferW2) ); - WideCharToMultiByte( CP_UTF8, 0, bufferW2, -1, buffer, lengthof(buffer), NULL, NULL ); - return buffer; -#endif - return path_in; -} - - - -// accecpt utf8 and returns (on windows) an ANSI filename -const char *dr_utf8_to_system_filename( const char *path_in_utf8, bool create ) -{ -#if defined _WIN32 - WCHAR bufferW[1024], bufferW2[1024]; - static char buffer[1024*3]; - MultiByteToWideChar( CP_UTF8, 0, path_in_utf8, -1, bufferW, lengthof(bufferW) ); - if( GetShortPathNameW( bufferW, bufferW2, lengthof(bufferW2) ) == 0 ) { - if( !create ) { - // file does not exist, return input path - return path_in_utf8; - } - else { - CloseHandle( CreateFileW( bufferW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ) ); - GetShortPathNameW( bufferW, bufferW2, lengthof(bufferW2) ); - } - } - WideCharToMultiByte( CP_UTF8, 0, bufferW2, -1, buffer, lengthof(buffer), NULL, NULL ); - return buffer; -#endif - (void)create; - return path_in_utf8; -} - - - void dr_rename( const char *existing_utf8, const char *new_utf8 ) { #if defined _WIN32 @@ -170,7 +127,7 @@ static char buffer[PATH_MAX+24]; #if defined _WIN32 - WCHAR bufferW[PATH_MAX+24], bufferW2[PATH_MAX+24]; + WCHAR bufferW[PATH_MAX+24]; if( SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, bufferW) ) { DWORD len = PATH_MAX; HKEY hHomeDir; @@ -179,11 +136,9 @@ } RegQueryValueExW(hHomeDir, L"Personal", 0, 0, (LPBYTE)bufferW, &len); } - // this is needed to access multibyte user driectories with ASCII names ... wcscat( bufferW, L"\\Simutrans" ); - CreateDirectoryW( bufferW, NULL ); // must create it, because otherwise the short name does not exist - GetShortPathNameW( bufferW, bufferW2, lengthof(bufferW2) ); - WideCharToMultiByte( CP_UTF8, 0, bufferW2, -1, buffer, MAX_PATH, NULL, NULL ); + CreateDirectoryW( bufferW, NULL ); + WideCharToMultiByte( CP_UTF8, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL ); #elif defined __APPLE__ sprintf(buffer, "%s/Library/Simutrans", getenv("HOME")); #elif defined __HAIKU__ @@ -218,10 +173,12 @@ { #if defined _WIN32 static char buffer[PATH_MAX]; + WCHAR bufferW[PATH_MAX]; - if( SHGetFolderPathA(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, buffer) ) { - strcpy( buffer, "C:\\Windows\\Fonts" ); + if( SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, bufferW) ) { + wcscpy( bufferW, L"C:\\Windows\\Fonts" ); } + WideCharToMultiByte( CP_UTF8, 0, bufferW, -1, buffer, PATH_MAX, NULL, NULL ); strcat( buffer, "\\" ); strcat( buffer, fontname ); return buffer; @@ -756,15 +713,16 @@ bool dr_download_pakset( const char *path_to_program, bool portable ) { #ifdef _WIN32 - char param[2048]; + WCHAR param[2048]; + const WCHAR *wpath_to_program = dr_utf8_to_wide_filename(path_to_program); if( portable ) { - sprintf( param, "/P /D=%s", path_to_program ); + wsprintfW( param, L"/P /D=%s", wpath_to_program ); } else { - sprintf( param, "/D=%s", path_to_program ); + wsprintfW( param, L"/D=%s", wpath_to_program ); } - SHELLEXECUTEINFOA shExInfo; + SHELLEXECUTEINFOW shExInfo; shExInfo.cbSize = sizeof(shExInfo); shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; shExInfo.hwnd = 0; @@ -773,14 +731,14 @@ * Otherwise the waiting for installation will fail! * (no idea how this works on XP though) */ - shExInfo.lpVerb = "runas"; - shExInfo.lpFile = "download-paksets.exe"; + shExInfo.lpVerb = L"runas"; + shExInfo.lpFile = L"download-paksets.exe"; shExInfo.lpParameters = param; - shExInfo.lpDirectory = path_to_program; + shExInfo.lpDirectory = wpath_to_program; shExInfo.nShow = SW_SHOW; shExInfo.hInstApp = 0; - if( ShellExecuteExA(&shExInfo) ) { + if( ShellExecuteExW(&shExInfo) ) { WaitForSingleObject( shExInfo.hProcess, INFINITE ); CloseHandle( shExInfo.hProcess ); } @@ -799,10 +757,9 @@ #ifdef _WIN32 char pathname[1024]; // so simutran can has also a multibyte name ... - WCHAR pathnameW[MAX_PATH], pathnameW2[MAX_PATH]; + WCHAR pathnameW[MAX_PATH]; GetModuleFileNameW(GetModuleHandle(0), pathnameW, sizeof(pathname) ); - GetShortPathNameW( pathnameW, pathnameW2, lengthof(pathnameW2) ); - WideCharToMultiByte( CP_UTF8, 0, pathnameW2, -1, pathname, MAX_PATH, NULL, NULL ); + WideCharToMultiByte( CP_UTF8, 0, pathnameW, -1, pathname, MAX_PATH, NULL, NULL ); argv[0] = pathname; #elif !defined __BEOS__ # if defined __GLIBC__ && !defined __AMIGA__ Index: simsys.h =================================================================== --- simsys.h (revisjon 8169) +++ simsys.h (arbeidskopi) @@ -10,13 +10,6 @@ #include #include "simtypes.h" -// Provide chdir(). -#if defined(_WIN32) && !defined(__CYGWIN__) -# include -#else -# include -#endif - #ifdef _WIN32 #define SIM_SYSTEM_TRASHBINAVAILABLE #endif @@ -73,6 +66,34 @@ // scale according to dpi setting bool dr_auto_scale(bool); +struct stat; +/** + * stat with UTF-8 encoded file name. This is done differently on Windows and POSIX. + */ +int dr_stat(const char *filename, struct stat *_Stat); + +/** + * Get current directory using an UTF-8 encoded path. This is done differently on Windows and POSIX. + */ +char *dr_getcwd(char *buf, int size); + +/** + * Change current directory using an UTF-8 encoded path. This is done differently on Windows and POSIX. + */ +int dr_chdir(const char *dirname); + +/** + * Opens a file using an UTF-8 encoded file name. This is done differently on Windows and POSIX. + */ +FILE *dr_fopen(const char *filename, const char *mode); + +#ifdef ZLIB_H +/** + * Opens a zlib file using an UTF-8 encoded file name. This is done differently on Windows and POSIX. + */ +gzFile dr_gzopen(const char *filename, const char *mode); +#endif + bool dr_os_init(int const* parameter); /* maximum size possible (if there) */ @@ -91,12 +112,6 @@ void dr_mkdir(char const* path); -// accecpt whatever encoding your filename has (assuming ANSI for windows) and returns the Unicode name -const char *dr_system_filename_to_uft8( const char *path_in ); - -// accecpt utf8 and returns (on windows) an ANSI filename -const char *dr_utf8_to_system_filename( const char *path_in_utf8, bool create=false ); - // rename a file and delete eventually existing file new_utf8 void dr_rename( const char *existing_utf8, const char *new_utf8 ); Index: simsys_w.cc =================================================================== --- simsys_w.cc (revisjon 8169) +++ simsys_w.cc (arbeidskopi) @@ -8,6 +8,9 @@ #error "Only Windows has GDI!" #endif +#define UNICODE +#define _UNICODE + #include #include @@ -126,15 +129,10 @@ RECT r = { 0, 0, w, h }; AdjustWindowRectEx(&r, style, false, ex_style); -#if 0 - // Try with a wide character window; need the title with full width - WCHAR *wSIM_TITLE = new wchar_t[lengthof(SIM_TITLE)]; - size_t convertedChars = 0; - mbstowcs( wSIM_TITLE, SIM_TITLE, lengthof(SIM_TITLE) ); + wchar_t *wSIM_TITLE = new wchar_t[lengthof(SIM_TITLE)]; + MultiByteToWideChar(CP_UTF8, 0, SIM_TITLE, -1, wSIM_TITLE, lengthof(SIM_TITLE)); hwnd = CreateWindowExW(ex_style, L"Simu", wSIM_TITLE, style, x, y, r.right - r.left, r.bottom - r.top, 0, 0, hInstance, 0); -#else - hwnd = CreateWindowExA(ex_style, "Simu", SIM_TITLE, style, x, y, r.right - r.left, r.bottom - r.top, 0, 0, hInstance, 0); -#endif + delete[] wSIM_TITLE; ShowWindow(hwnd, SW_SHOW); SetTimer( hwnd, 0, 1111, NULL ); // HACK: so windows thinks we are not dead when processing a timer every 1111 ms ... @@ -413,7 +411,7 @@ #endif if (!dr_screenshot_png(filename, w, h, AllDib->bmiHeader.biWidth, (unsigned short*)AllDibData+x+y*AllDib->bmiHeader.biWidth, bpp)) { // not successful => save full screen as BMP - if (FILE* const fBmp = fopen(filename, "wb")) { + if (FILE* const fBmp = dr_fopen(filename, "wb")) { BITMAPFILEHEADER bf; // since the number of drawn pixel can be smaller than the actual width => only use the drawn pixel for bitmap Index: simworld.cc =================================================================== --- simworld.cc (revisjon 8169) +++ simworld.cc (arbeidskopi) @@ -4775,10 +4775,10 @@ if( file->get_version() >= 112008 ) { xml_tag_t t( file, "motd_t" ); - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); // maybe show message about server DBG_MESSAGE("karte_t::speichern(loadsave_t *file)", "motd filename %s", env_t::server_motd_filename.c_str() ); - if( FILE *fmotd = fopen( env_t::server_motd_filename.c_str(), "r" ) ) { + if( FILE *fmotd = dr_fopen( env_t::server_motd_filename.c_str(), "r" ) ) { struct stat st; stat( env_t::server_motd_filename.c_str(), &st ); sint32 len = min( 32760, st.st_size+1 ); @@ -4844,7 +4844,7 @@ if( env_t::networkmode ) { network_core_shutdown(); } - chdir( env_t::user_dir ); + dr_chdir( env_t::user_dir ); const char *err = network_connect(filename+4, this); if(err) { create_win( new news_img(err), w_info, magic_none ); Index: sound/win32_sound.cc =================================================================== --- sound/win32_sound.cc (revisjon 8169) +++ sound/win32_sound.cc (arbeidskopi) @@ -11,7 +11,9 @@ #include "sound.h" +extern const WCHAR *dr_utf8_to_wide_filename(const char *path); + /* * Hajo: flag if sound module should be used * with Win32 the number+1 of the device used @@ -43,7 +45,7 @@ int dr_load_sample(char const* filename) { if(use_sound && sample_number>=0 && sample_number<64) { - if (FILE* const fIn = fopen(filename, "rb")) { + if (FILE* const fIn = _wfopen(dr_utf8_to_wide_filename(filename), L"rb")) { long len; fseek( fIn, 0, SEEK_END ); len = ftell( fIn ); Index: utils/log.cc =================================================================== --- utils/log.cc (revisjon 8169) +++ utils/log.cc (arbeidskopi) @@ -407,7 +407,7 @@ tee = NULL; #endif } else { - log = fopen(logfilename,"wb"); + log = dr_fopen(logfilename,"wb"); if(log == NULL) { fprintf(stderr,"log_t::log_t: can't open file '%s' for writing\n", logfilename); Index: utils/searchfolder.cc =================================================================== --- utils/searchfolder.cc (revisjon 8169) +++ utils/searchfolder.cc (arbeidskopi) @@ -1,7 +1,7 @@ #include #include -#ifndef _MSC_VER +#ifndef _WIN32 #include #else #define NOMINMAX @@ -95,7 +95,7 @@ path = path.substr(0, slash + 1); } } -#ifdef _MSC_VER +#ifdef _WIN32 lookfor = path + name + ext; struct _wfinddata_t entry; WCHAR path_inW[1024];