diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f007dbcc..552a6997a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,7 +305,7 @@ if(DPKG_PROGRAM) Data files from the original game is required to run it.") SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") - SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher") + SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "nvidia-cg-toolkit (>= 2.1), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") SET(CPACK_DEBIAN_PACKAGE_SECTION "Games") @@ -391,6 +391,11 @@ if (BUILD_LAUNCHER) add_subdirectory( apps/launcher ) endif() +option(BUILD_MWINIIMPORTER "build MWiniImporter inspector" ON) +if (BUILD_MWINIIMPORTER) + add_subdirectory( apps/mwiniimporter ) +endif() + if (WIN32) if (MSVC) if (USE_DEBUG_CONSOLE) diff --git a/apps/mwiniimporter/CMakeLists.txt b/apps/mwiniimporter/CMakeLists.txt new file mode 100644 index 000000000..2a8c0f5fe --- /dev/null +++ b/apps/mwiniimporter/CMakeLists.txt @@ -0,0 +1,20 @@ +set(MWINIIMPORT + main.cpp + importer.cpp +) + +set(MWINIIMPORT_HEADER + importer.hpp +) + +source_group(launcher FILES ${MWINIIMPORT} ${MWINIIMPORT_HEADER}) + +add_executable(mwiniimport + ${MWINIIMPORT} +) + +target_link_libraries(mwiniimport + ${Boost_LIBRARIES} + components +) + diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp new file mode 100644 index 000000000..f662f42d6 --- /dev/null +++ b/apps/mwiniimporter/importer.cpp @@ -0,0 +1,105 @@ +#include "importer.hpp" +#include +#include +#include + +void MwIniImporter::setVerbose(bool verbose) { + mVerbose = verbose; +} + +strmap MwIniImporter::loadIniFile(std::string filename) { + std::cout << "load ini file: " << filename << std::endl; + + std::string section(""); + std::map map; + boost::iostreams::streamfile(filename.c_str()); + + std::string line; + while (std::getline(file, line)) { + + // ignore sections for now + if(line.empty() || line[0] == ';') { + continue; + } + + if(line[0] == '[') { + if(line.length() > 2) { + section = line.substr(1, line.length()-3); + continue; + } + throw IniParseException(); + } + + int pos = line.find("="); + if(pos < 1) { + throw IniParseException(); + } + + map.insert(std::pair( + section + " " + line.substr(0,pos), line.substr(pos+1) + )); + } + + return map; +} + +strmap MwIniImporter::loadCfgFile(std::string filename) { + std::cout << "load cfg file: " << filename << std::endl; + + std::map map; + boost::iostreams::streamfile(filename.c_str()); + + std::string line; + while (std::getline(file, line)) { + + if(line[0] == '[') { // section + continue; // ignore for now + } + + // we cant say comment by only looking at first char anymore + int comment_pos = line.find("#"); + if(comment_pos > 0) { + line = line.substr(0,comment_pos); + } + + if(line.empty()) { + continue; + } + + int pos = line.find("="); + if(pos < 1) { + throw IniParseException(); + } + + map.insert(std::pair( + line.substr(0,pos), line.substr(pos+1) + )); + } + + return map; +} + +void MwIniImporter::merge(strmap &cfg, strmap &ini) { + strmap::iterator ini_it; + for(strmap::iterator it=cfg.begin(); it != cfg.end(); it++) { + ini_it = ini.find(it->first); + + // found a key in both files + if(ini_it != ini.end()) { + cfg.erase(it); + cfg.insert(std::pair( + ini_it->first, ini_it->second + )); + } + } +} + +void MwIniImporter::writeToFile(std::string file, strmap &cfg) { + boost::iostreams::stream out(file); + + for(strmap::iterator it=cfg.begin(); it != cfg.end(); it++) { + out << (it->first) << "=" << (it->second) << std::endl; + } +} + + diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp new file mode 100644 index 000000000..1933830f2 --- /dev/null +++ b/apps/mwiniimporter/importer.hpp @@ -0,0 +1,31 @@ +#ifndef MWINIIMPORTER_IMPORTER +#define MWINIIMPORTER_IMPORTER 1 + +#include +#include +#include + +typedef std::map strmap; + +class IniParseException : public std::exception { + virtual const char* what() const throw() { + return "unexpected end of line"; + } +}; + +class MwIniImporter { + + public: + void setVerbose(bool verbose); + strmap loadIniFile(std::string filename); + strmap loadCfgFile(std::string filename); + void merge(strmap &cfg, strmap &ini); + void writeToFile(std::string file, strmap &cfg); + + private: + bool mVerbose; + +}; + + +#endif diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp new file mode 100644 index 000000000..fa7a5c512 --- /dev/null +++ b/apps/mwiniimporter/main.cpp @@ -0,0 +1,75 @@ +#include "importer.hpp" + +#include +#include +#include +#include + +namespace bpo = boost::program_options; + +int main(int argc, char *argv[]) { + + bpo::options_description desc("Syntax: mwiniimporter \nAllowed options"); + desc.add_options() + ("help,h", "produce help message") + ("verbose,v", "verbose output") + ("ini,i", bpo::value()->required(), "morrowind.ini file") + ("cfg,c", bpo::value()->required(), "openmw.cfg file") + ("output,o", bpo::value()->default_value(""), "openmw.cfg file") + ; + + bpo::variables_map vm; + try { + bpo::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + + // parse help before calling notify because we dont want it to throw an error if help is set + if(vm.count("help")) { + std::cout << desc; + return 0; + } + + bpo::notify(vm); + + } + catch(std::exception& e) { + std::cerr << "Error:" << e.what() << std::endl; + return -1; + } + catch(...) { + std::cerr << "Error" << std::endl; + return -2; + } + + std::string iniFile = vm["ini"].as(); + std::string cfgFile = vm["cfg"].as(); + + // if no output is given, write back to cfg file + std::string outputFile(vm["output"].as()); + if(vm["output"].defaulted()) { + outputFile = vm["cfg"].as(); + } + + if(!boost::filesystem::exists(iniFile)) { + std::cerr << "ini file does not exist" << std::endl; + return -3; + } + if(!boost::filesystem::exists(cfgFile)) { + std::cerr << "cfg file does not exist" << std::endl; + return -4; + } + + MwIniImporter importer; + importer.setVerbose(vm.count("verbose")); + + std::mapini = importer.loadIniFile(iniFile); + std::mapcfg = importer.loadCfgFile(cfgFile); + + importer.merge(cfg, ini); + + std::cout << "write to: " << outputFile << std::endl; + importer.writeToFile(outputFile, cfg); + + return 0; +} + +